Add objects one by one when click button MVC C# - c#

I have added items to the list.But the problem is in here i have added items one by one to the list after button click items.Every time only 1 object shows in the list.
List<Items> _objList = new List<Items>();
public ActionResult AddNewItems(int ItemId)
{
Items items = itemBusiness.GetItemByItemId(ItemId);
_objList.Add(new Items { ItemId =items.ItemId,ItemName =items.ItemName,
ItemPrice = items.ItemPrice });
Session["ItemSession"] = _objList;
return RedirectToAction("Index","Home");
}
Items DTO
public class Items
{
public int ItemId { get; set; }
public string ItemCode { get; set; }
public string ItemName { get; set; }
public string ImageUrl { get; set; }
public int? ItemBadge { get; set; }
public DateTime? AddedDate { get; set; }
public int? AddedBy { get; set; }
public DateTime? UpdatedDate { get; set; }
public int? UpdatedBy { get; set; }
public bool? IsActive { get; set; }
public decimal ItemPrice { get; set; }
}

You need to store the list, then retrieve it to add a new item to it. That create could be done a couple ways including calling a method that creates if it does not exist and returns that session list as in the
var _objList = (List<Items>)Session["ItemSession"];
Just make sure you DO have one so it does not throw an InvalidCastException
This code assumes you DO have a list stored in some "create" method prior to adding another one.
public ActionResult AddNewItems(int ItemId)
{
var _objList = (List<Items>)Session["ItemSession"];
Items items = itemBusiness.GetItemByItemId(ItemId);
_objList.Add(new Items { ItemId = items.ItemId,
ItemName = items.ItemName,
ItemPrice = items.ItemPrice });
Session["ItemSession"] = _objList;
return RedirectToAction("Index","Home");
}
Example alternate, set a property on your class and use that avoiding the cast exception by checking for null and creating if not there yet (and store at end as you have):
ItemsHolder.Add(new Items { ItemId = items.ItemId,
ItemName = items.ItemName,
ItemPrice = items.ItemPrice });
Add to your class
// the property
public List<Items> ItemsHolder
{
get
{
object ItemsSession = Session["ItemSession"] as List<Items>;
if (ItemsSession == null)
{
ItemsSession = new List<Items>();
Session["ItemSession"] = ItemsSession;
}
return (List<Items>)ItemsSession;
}
}
Side note, just make sure your items are serializable. You might just want to store a list of ItemId and get the name and price as needed to avoid some issues. https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/serialization/index

Related

How to filter out items that are in a list of a list?

I am a little puzzled to how I can add items depending on the value that is in a list of a list.
I have these models
public class ItemsModel
{
public int OrderItemId { get; set; }
public string Sku { get; set; }
public string Name { get; set; }
public int Quantity { get; set; }
}
public class OrdersModel
{
public int OrderId { get; set; }
public string OrderNumber { get; set; }
public List<ItemsModel> Items { get; set; }
}
public class OrderResultModel
{
public List<OrdersModel> Orders { get; set; }
}
Question
I need to add all orders from an api, but add Items that has SKU only ending with "5".
How can I do this?
How I tried it
I have an API call to get all orders.. List<OrdersModel> GetOrders().
Then I add the data like so:
public ObservableCollection<OrdersModel> Orders { get; private set; }
...
Orders = new ObservableCollection<OrdersModel>();
foreach (var item in GetOrders())
{
Orders.Add(item);
}
Here is how I tried to add values with SKU ending with 5:
var list = GetOrders().Where(x => x.Items.Any(i => i.Sku.EndsWith("5")));
foreach (var item in list)
{
Orders.Add(item);
}
Problem
This still shows me all values.. why? And how I can correct it?
foreach(var order in GetOrders())
{
order.Items = order.Items.Where(i => i.Sku.EndsWith("5")).ToList();
Orders.Add(order);
}
It's showing you all the value because Any() will evaluate to true if any of List of ItemsModels ends with 5.
you should filter on the list first something like
var filteredItems = orders.Items.Where(i => i.sku.EndsWith("5"))

How can I add a DisplayMember and ValueMember to a single ComboBox Item that has an assigned DataSource?

I am successfully adding Display/Value pairs to a combobox like this:
List<Student> BRStudents =
studentsList.Where(h => h.EnrolledInAYttFM)
.Where(i =>
i.RecommendedNextTalkTypeID.Equals(BIBLE_READING_TALK_TYPE))
.OrderBy(j => j.WeekOfLastAssignment)
.ToList();
comboBoxBR.DataSource = BRStudents;
comboBoxBR.DisplayMember = "FullName";
comboBoxBR.ValueMember = "StudentID";
...but I then (in some instances) want to add another item to comboBoxBR, one which is not present in the BRStudents list. If I try to do this:
AssignmentHistory ah = AYttFMConstsAndUtils.AssignmentHistList
.FirstOrDefault(i => i.WeekOfAssignment == currentWeek && i.TalkType == 1);
string fullName = AYttFMConstsAndUtils.GetStudentFullNameForID(ah.StudentID_FK);
comboBoxBR.Items.Add(fullName);
...I get, "Items collection cannot be modified when the DataSource property is set."
Really, I want to do something like this:
comboBoxBR.Items.Add(fullName, ah.StudentID_FK);
Is there a way to combine the two results (the list of Student and the single AssignmentHistory) into a Dictionary or some such collection, and then assign that as the DataSource for comboBoxBR?
For full disclosure, here are the definitions of Student and AssignmentHistory:
public class Student
{
public int StudentID { get; set; }
public int FamilyID { get; set; }
public bool EnrolledInAYttFM { get; set; }
public DateTime DateEnrolledOrHiatusAYttFM { get; set; }
public bool GivesBibleReading { get; set; }
public bool PresentsICRVBS { get; set; }
public bool IsHouseholder { get; set; }
public bool IsMale { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string EmailAddr { get; set; }
public DateTime WeekOfLastAssignment { get; set; }
public int RecommendedNextTalkTypeID { get; set; }
public int NextCounselPoint { get; set; }
public string FullName => $"{FirstName} {LastName}";
}
public class AssignmentHistory
{
public DateTime WeekOfAssignment { get; set; }
public int TalkType { get; set; }
public int StudentID_FK { get; set; }
public int AssistantID_FK { get; set; }
public int CounselPoint { get; set; }
public bool HasBeenEmailed { get; set; }
public bool SlipHasBeenPrinted { get; set; }
}
Instead of adding elements to the Items collection of the combo (not possible if you have set the DataSource) the first thing that comes to mind is adding elements to the List<Students> itself used as DataSource, but this doesn't reach your objective because there is no mechanism in place to inform the ComboBox that the DataSource has a new element. You can't see the added element unless you rebind the List to the combobox. To do this you first need to unbind the previous DataSource and then rebind the list again.
// Assuming a lot about your student class, hope it's clear the intention
BRStudents.Add(new Student() { newName = "ANewStudent", ID = 1} );
comboBoxBR.DataSource = null;
comboBoxBR.DataSource = BRStudents;
comboBoxBR.DisplayMember = "FullName";
comboBoxBR.ValueMember = "StudentID";
However, there is a better solution and it is the class BindingList(T)
This class is capable to refresh the object at which you bind an instance of it.
So when you bind the combo for the first time you have to write
BindingList<Student> bl = new BindingList<Student>(BRStudents);
comboBoxBR.DataSource = bl;
comboBoxBR.DisplayMember = "FullName";
comboBoxBR.ValueMember = "StudentID";
and when you want to add a new element to the list you write
(move bl at the global scope if needed)
bl.Add(new Student() { newName = "ANewStudent", ID = 1} );
The documentation states that you should call ResetBindings to force a refresh of the control but this doesn't seems always required...

How to access list of a ViewModel

I have the following model;
public class Object
{
public int Id { get; set; }
public string Name { get; set; }
public Nullable<double> Price { get; set; }
public string Description { get; set; }
public string Image { get; set; }
public Nullable<int> Type { get; set; }
}
and i create a view model;
public class PlanBaseTypedObjects
{
public int? Id { get; set; }
public IEnumerable<Object> ObjectDetails { get; set; }
}
in my controller i did grouping as follows;
var model = model1.GroupBy(t => t.Type).Select(g => new PlanBaseTypedObjects
{
Id = g.Key,
ObjectDetails = g
});
How can i get the number of records that belong to a particular "Type"??
for an example for type 1 how many records under ObjectDetails??
and can i access the "objectDetails" directly??
for an example if i want to know the "Name" of Id=3 of Type 2.how can i get it??
You need to iterate on the grouping result to find the count for each one.
foreach(var group in model)
{
int groupCount = group.ObjectDetails.Count();
}
If you want to access the items in ObjectDetails you need another foreach:
foreach(var group in model
{
int groupCount = group.ObjectDetails.Count();
foreach(var item in group.ObjectDetails))
{
//do something with item
}
}

Asp.Net MVC 4 Controller to update database

I have the following code:
Model
public class Orders
{
public int Id { get; set; }
public int UserId { get; set; }
public int ProductId { get; set; }
public int Quantity { get; set; }
public double Price { get; set; }
public bool OrderStatus { get; set; }
public string OrderNumber { get; set; }
public string AdminStatus { get; set; }
public bool PaymentStatus { get; set; }
public DateTime OrderDate { get; set; }
}
Controller
public ActionResult CheckOut()
{
if (Request.IsAjaxRequest())
{
var userid = WebSecurity.CurrentUserId;
var data = _bbdb.Orders.Where(x => x.OrderStatus == false && x.UserId == userid).ToList();
foreach (var item in data)
{
_bbdb.Orders.Add(new Orders
{
Id = item.Id,
UserId = item.UserId,
ProductId = item.ProductId,
Quantity = item.Quantity,
Price = item.Price,
OrderStatus = true,
OrderNumber = item.UserId + DateTime.Now.ToShortTimeString(),
AdminStatus = item.AdminStatus,
PaymentStatus = item.PaymentStatus,
OrderDate = DateTime.Today
});
_bbdb.SaveChanges();
}
}
var cartdata = GetCartItems();
return PartialView("_CartTable", cartdata);
}
How can I change this bit code _bbdb.Orders.Add(new Orders to UPDATE instead ADD.
I thought something like _bbdb.Orders.AddOrUpdate(new Orders would do the trick, but I does not exist.
It is adding the right value, but I want to update the records not add new ones.
Any suggestion on how to improve or change will be appreciated.
Not sure how correct I am here, but try this...
_bbdb tracks the changes, so you simply need to get the item from the db, make the changes you need and then save them.
foreach (var item in data)
{
item.Price = 100; //Set whatever values you need to update
}
_bbdb.SaveChanges();
Also, notice that the SaveChanges() method was moved outside of foreach. The context will track the changes so you don't need to call SaveChanges after each item is added.
Finally, I believe that you don't need ToList() after the Where-clause

Creating an Object List from another List Object LINQ Lambda

I am trying to add certain objects to another object. But I am getting an error in the Options section. I am quite simply trying to add certain stuff out of one object and into another.
Here is what my code looks like..
var responses = new Responses();
form.Questions.ForEach(
q => responses.Questions.Add(new Models.Question()
{
QuestionId = Convert.ToInt32(q.Id),
Value = q.SingleAnswer,
Options = q.Options.ForEach( o => q.Options.Add(
new Option // <----FAILING HERE!!!!!!!!!!!!
{
OptionId = 1,
Value = "test"
}
))
})
);
The error is
Argument type 'Web.Models.Option' is not assignable to parameter type QuestionOptionViewModel
MODELS:
public class Responses
{
public List<Question> Questions { get; set; }
}
public class Question
{
public int QuestionId { get; set; }
public string Value { get; set; }
public List<Option> Options { get; set; }
}
public class Option
{
public int OptionId { get; set; }
public string Value { get; set; }
}
public class QuestionOptionViewModel
{
public int? Id { get; set; }
public string Text { get; set; }
public string QuestionType { get; set; }
[RequiredIf("QuestionType", "text", ErrorMessage = "Required Field")]
public string Value { get; set; }
[RequiredIf("QuestionType", "checkbox", ErrorMessage = "Required Field")]
public bool IsChecked { get; set; }
}
public class QuestionViewModel
{
public int? Id { get; set; }
public string QuestionType { get; set; }
public string SubType { get; set; }
public string Text { get; set; }
public int SortOrder { get; set; }
public bool IsHidden { get; set; }
[RequiredIf("QuestionType", "singleAnswer", ErrorMessage = "Reqired Field")]
public string SingleAnswer { get; set; }
[RequiredIf("QuestionType", "radio", ErrorMessage = "Radio Reqired")]
public int? SelectedRadio { get; set; }
[RequiredIf("QuestionType", "select", ErrorMessage = "Selection Reqired")]
public int? SelectedSelect { get; set; }
public bool CheckboxError { get; set; }
public List<QuestionOptionViewModel> Options { get; set; }
}
Hopefully this isn't too misguided but I think you're going about this all wrong. You want to do a Select and assign the result to the questions property in responses. Here's a basic example;
var responses = new Responses();
responses.Questions = form.Questions.Select(
q => new Models.Question()
{
QuestionId = Convert.ToInt32(q.Id),
Value = q.SingleAnswer,
Options = q.Options.Select(o =>
new Option
{
OptionId = (int) o.Id,
Value = o.Value
}).ToList()
}).ToList();
I edited your code rather quickly so there is some potential that won't work as is (didn't compile or anything). But basically you use Select for projection, return a List<Question> and assign it to the Questions property. Don't try to do the adds in place. Besides that you never initialized the Questions list so even if that code compiled you'd get a NullReferenceException. Again, there are likely other problems with your code but I think you're fundamentally misusing ForEach when Select is actually the correct operation.
There are two issues here. One you are trying to change the collection you are iterating over with your ForEach. And second you are trying to assign the result of that ForEach. Instead you should use a Select and ToList to create a list to assign to Options. If you change
Options = q.Options.ForEach( o => q.Options.Add(
new Option
{
OptionId = 1,
Value = "test"
}
))
to
Options = q.Options.Select(
new Option
{
OptionId = 1,
Value = "test"
}
).ToList()
it should work

Categories

Resources