How do I make my list based editor template bind properly for a POST action?

asp.net-mvc, asp.net-mvc-3, asp.net-mvc-4

Solution

The problem is that ASP.NET can't figure out how to bind to `Model.Items` property.

To to fix it replace:

public IEnumerable<ApplicantBranchItem> Items { get; set; }

with this:

public List<ApplicantBranchItem> Items { get; set; }

and instead of:

@foreach (var item in Model.Items)
{
   @Html.EditorFor(m => item)
}

use this one:

@for (var i = 0; i < Model.Items.Count; i++)
{
   @Html.EditorFor(model => model.Items[i]) // binding works only with items which are accessed by indexer
}

Problem

I have a model, `ApplicantBranchList`, that is used as a property in a larger model as follows: ``` [Display(Name = "Where would you want to work?")] public ApplicantBranchList PreferedBranches { get; set; } ``` `ApplicantBranchList`: ``` public class ApplicantBranchList : ViewModel { public ApplicantBranchItem HeaderItem { get; set; } public ApplicantBranchList() { HeaderItem = new ApplicantBranchItem(); } public void MapFromEntityList(IEnumerable<ApplicantBranch> applicantBranches) { var service = new BranchService(DbContext); var selectedIds = applicantBranches.Select(b => b.BranchId); Items = service.ReadBranches() .Where(i => !i.IsDeleted) .Select(p => new ApplicantBranchItem { BranchName = p.Name, WillWorkAt = selectedIds.Contains(p.Id) }); } public IEnumerable<ApplicantBranchItem> Items { get; set; } } ``` `ApplicantBranchList` has its own editor template, and an inner editor template for each item in `ApplicantBranchList`: Views/Shared/EditorTemplates/ApplicantBranchList.cshtml: ``` @model Comair.RI.UI.Models.ApplicantBranchList <table> <tr> <th style="display: none;"></th> <th> @Html.DisplayNameFor(model => model.HeaderItem.BranchName) </th> <th> @Html.DisplayNameFor(model => model.HeaderItem.WillWorkAt) </th> </tr> @foreach (var item in Model.Items) { @Html.EditorFor(m => item) } </table> ``` Views/Shared/EditorTemplates/ApplicantBranchItem.cshtml: ``` @model Comair.RI.UI.Models.ApplicantBranchItem <tr> <td style="display: none;"> @Html.HiddenFor(m => m.BranchId) </td> <td> @Html.DisplayFor(m => m.BranchName) </td> <td> @Html.EditorFor(m => m.WillWorkAt) </td> </tr> ``` This editor renders properly in the view, but in the post action: ``` public ActionResult Create(ApplicantProfileModel model) { if (ModelState.IsValid) { var branches = model.PreferedBranches; ``` `PreferedBranches.Items` is `null`. What am I doing wrong?

Original source