Submit a form with a collection of a Model
.net, asp.net-mvc, asp.net-mvc-3, c#, razor
Solution
You can't use a `foreach` in this instance, it needs to be a `for` loop so that the `name` attributes of the fields contain the correct index so that default model binding knows it's binding to a list.
Firstly, I'm going to move your dropdown values out of the `ViewBag` (they should really be in there). That'll also take out some of that nasty logic in your view :)
So your model is now:
public class OrderConfirm
{
public List<QuoteLine> SalesLines { get; set; }
public string Currency { get; set; }
public int EnquiryID { get; set; }
public SelectList LostReasons { get; set; }
}
Try this instead of your `foreach`:
@for (var i = 0; i < Model.SalesLines.Count; i++)
{
<tr>
<td>
@Model.SalesLines[i].ItemName
@Html.HiddenFor(m => m.SalesLines[i].QuoteLineId)
@Html.HiddenFor(m => m.SalesLines[i].ItemName) //assuming you want this
</td>
<td>
@Html.DropDownListFor(m => m.SalesLines[i].LostReasonId, Model.LostReasons)
</td>
</tr>
}
Then change your post method to take your `OrderConfirm` model type:
[HttpPost]
public ActionResult ConfirmLostOrder(OrderConfirm model)
Problem
I have a ViewModel which contains a collection of type of my Model, like so: ``` public class OrderConfirm { public ICollection<QuoteLine> SalesLines { get; set; } public string Currency { get; set; } public int EnquiryID { get; set; } } ``` My QuoteLine Model looks like so: ``` public class QuoteLine { public int QuoteLineId { get; set; } public int LostReasonId { get; set; } public virtual LostReason LostReason { get; set; } public string ItemName { get; set; } } ``` In my View, I then Iterate through each of these QuoteLines, within a form, like so: ``` @using (Ajax.BeginForm("ConfirmLostOrder", new AjaxOptions() { InsertionMode = InsertionMode.Replace, UpdateTargetId = "LostOrders", OnBegin = "LostOrderConfirm" })) { <table class="completed-enq-table"> <tr> <th> Item Number </th> <th> Reason </th> </tr> @foreach (var sales in Model.SalesLines) { <tr> <td>@sales.ItemName @Html.HiddenFor(model => sales.QuoteLineID) </td> <td>@Html.DropDownListFor(model => sales.LostReasonId, ((IEnumerable<myApp.Models.LostReason>)ViewBag.LostReasons).Select(option => new SelectListItem { Text = (option == null ? "None" : option.LostReason), Value = option.LostReasonId.ToString(), Selected = (Model != null) && (option.LostReasonId == sales.LostStatusId) })) </td> </tr> } </table> <input type="submit" style="float: right;" value="Submit Lost Order" /> } ``` Then my `HttpPost` action looks like so: ``` [HttpPost] public ActionResult ConfirmLostOrder(List<QuoteLine> models) { // process order return PartialView("Sales/_ConfirmLostOrder"); } ``` The problem is, `models` is null. If I use a `FormCollection` I can see each of the values submitted but I'd like to use my model and not a FormCollection as I'd like to process and edit each of the line submitted individually as they may have different reason's