I have the following action method, when I press the update button on my cart and post to this method I need it bind all productId and partquantity values into the respective parameters/arrays (int[] ProductId, int[] partquantity) and it does this. I am presuming when form data, that is keys and values are posted they arrive in some sort of order, likely as elements are laid out on the HTML page (top to bottom)? So I wish for the operation on each cart item to be performed using the correct partquantity entered, that is for the correct productId. I am guessing if they post and bind in strict order then partquantity[2] should be the correct quantity for ProductId[2] etc. ?
The below logic in trying to increment f by 1 for each operation on each productId in the ProductId[] array does not work. I need to get this to work because say I have 5 items added to the cart and change the quantity for 4 of them I wish to just press the one update button and it will update for all these items\lines in the cart. So method needs to catch all the posted productId and quantities and use in the correct order, so the right quantity is assigned to the right cart item which is looked up by ProductId.
public RedirectToRouteResult UpdateCart(Cart cart, int[] ProductId, int[] partquantity, string returnUrl)
{
int f = 0;
int x = partquantity.Length;
while (f <= x)
{
foreach (var pid in ProductId)
{
f++;
var cartItem = cart.Lines.FirstOrDefault(c => c.Product.ProductID == pid);
cartItem.Quantity = partquantity[f];
}
}
return RedirectToAction("Index", new { returnUrl });
}
This is the View:
<% foreach (var line in Model.Cart.Lines)
{ %>
<tr>
<td align="center"><%: Html.TextBox("partquantity", line.Quantity)%></td>
<td align="left"><%: line.Product.Name%></td>
<td align="right"><%: line.Product.ListPrice.ToString("c")%></td>
<td align="right">
<%: (line.Quantity * line.Product.ListPrice).ToString("c")%>
</td>
</tr>
<%: Html.Hidden("ProductId", line.Product.ProductID)%>
<% } %>
Custom Binder
public class CartModelBinder : IModelBinder
{
private const string cartSessionKey = "_cart";
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (bindingContext.Model != null)
throw new InvalidOperationException("Cannot update instances");
Cart cart = (Cart)controllerContext.HttpContext.Session[cartSessionKey];
if (cart == null)
{
cart = new Cart();
controllerContext.HttpContext.Session[cartSessionKey] = cart;
}
return cart;
}
}
}
Your Cart object should be enough as parameter for this scenario, you can have something like this.
The general idea would be to use an index so you get your Cart object with your Lines as you passed them to the view originally but with updated Quantity values.
Your model as I understand it:
In your view:
Your controller: