I'm having difficulty in saving changes
I make to a existing Delivery
on the Edit Delivery
page when I try to deselect
Orders
that have already been linked to that Delivery
.
I want to be able to remove
those Orders
I've already added when I initially Created
the Delivery
and add
more based on the Orders
available today and then save.
Currently, it doesn't save when I deselect
the Orders
that I have previously added through the Create
method, so those Orders
are still linked to the Delivery
. However, it does allow me to add more Orders
so that's alright.
So, essentially, the problem lies in the POST method of Edit.
Can anyone please advise me on a fix or a way forward? Thank you in advance.
View Models:
public class DeliveryVM
{
public int? ID { get; set; }
public DateTime Dispatched_Date { get; set; }
public List<OrderVM> Orders { get; set; }
}
public class OrderVM
{
public int ID { get; set; }
public string Name { get; set; }
public DateTime Date { get; set; }
public int DeliveryID { get; set; }
public bool IsSelected { get; set; }
}
Models:
public class Order
{
public int OrderID { get; set; }
public int? DeliveryID { get; set; }
public DateTime Expected_Date { get; set; }
public virtual Delivery Delivery { get; set; }
public virtual ICollection<OrderItem> OrderItems { get; set; }
}
public class Delivery
{
public int DeliveryID { get; set; }
public DateTime Dispatched_Date { get; set; }
public virtual ICollection<Order> Orders { get; set; }
}
Edit Method in Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(DeliveryVM model)
{
// Get the data model based on the ID of the view model
Delivery delivery = db.Deliverys.Find(model.ID);
// Map the view model properties to the data model
delivery.DriverID = model.DriverID;
...
// Mark as modified and save
IEnumerable<int> selectedOrders = model.Orders.Where(o => o.IsSelected).Select(o => o.ID);
foreach (int ID in selectedOrders)
{
Order order = db.Orders.Where(o => o.OrderID == ID).FirstOrDefault();
order.DeliveryID = delivery.DeliveryID;
db.Entry(order).State = EntityState.Modified;
db.SaveChanges();
}
return RedirectToAction("Details", new { id = delivery.DeliveryID });
}
Your current code is only modifying the orders that have been selected in the Edit
view, and unnecessarily updating orders that were previously selected.
You need to make a comparison with the original orders, and take the appropriate action
// Get the original selected orders
IEnumerable<int> originalOrders = delivery.Orders.Select(o => o.OrderID);
// Get the selected orders from the Edit view
IEnumerable<int> selectedOrders = model.Orders.Where(o => o.IsSelected).Select(o => o.ID);
// Get the orders that have been added
IEnumerable<int> newOrders = selectedOrders.Except(originalOrders);
// Get the orders that have been deleted
IEnumerable<int> deletedOrders = originalOrders.Except(selectedOrders);
foreach (int ID in newOrders)
{
// Get the order, set its DeliveryID property and save (as per your existing code)
}
IEnumerable<Order> toDelete= db.Orders.Where(o => deletedOrders.Contains(o.OrderID));
foreach (Order order in toDelete)
{
order.DeliveryID = null;
db.Entry(order).State = EntityState.Modified;
}
db.SaveChanges();
Side note: There is no need to update items that have not changed, but if you wanted to get them, it would be
IEnumerable<int> unchangedOrders= originalOrders.Intersect(selectedOrders);