Binding collections in MVC

2019-02-14 12:45发布

I have a View Model that consists of an Applicant object and a TeamMember collection. When I post the model back the Team collection is always null. I've tried changing the collection from my original IEnumarable to a List but that didn't make a difference. So I changed the Controllers Edit Action to accept the FormCollection, and verified there was data in viewModel["member.FirstName"]. I'm lost as to why the binding isn't working. I tried to clean out my code samples as much as possible but I'm confused at what I'm missing. Any help is greatly appreciated!

View Model Properties

public class MyViewModel
{
    public Applicant ApplicantInfo { get; set; }
    public List<TeamMember> TeamMembers { get; set; }
}

Controller

[HttpPost]
public ActionResult Edit(MyViewModel viewModel)
{
         //  viewModel.ApplicantInfo has the form data
         //  viewModel.TeamMembers = null              
}

View

<% using (Html.BeginForm())
       {%>
    <h3>
    <a href="#">Applicant Information</a>
    </h3>
    <label>
        City
        <%: Html.TextBoxFor(m => Model.ApplicantInfo.City)%>
    </label>
    <label>
        State
        <%: Html.TextBoxFor(m => Model.ApplicantInfo.State)%>
    </label>

    <h3>
    <a href="#">Team</a>
    </h3>
    <div>
    <% foreach (var member in Model.TeamMembers)
    { %>           
    <div class="editor-field">
        <%: Html.DropDownList("member.Type", Model.GetMemberTypes(member.MemberType.TypeId))%>
    </div>
    <div class="editor-field">
        <%: Html.EditorFor(m => member.FirstName)%>
    </div>
    <div class="editor-field">
        <%: Html.EditorFor(m => member.LastName)%>
    </div>
    <div class="editor-field">
        <%: Html.EditorFor(m => member.Title)%>
    </div>            
    <%} %>
    </div>
    <p>
        <input type="submit" value="Save" />
    </p>
    <% } %>

2条回答
啃猪蹄的小仙女
2楼-- · 2019-02-14 13:36

I believe that input tags associated with items in a collection (when the model itself is not a collection) need to have an index in the name attribute before you can bind posted data to a view model. Here is the way I usually accomplish this...

<% for (int i=0; i<Model.TeamMembers.Count; i++) { %>
<div class="editor-field">
  <%: Html.EditorFor(m => m.TeamMembers[i].FirstName)%>
</div>
<div class="editor-field">
  <%: Html.EditorFor(m => m.TeamMembers[i].LastName)%>
</div>
<% } %>

I've also used the template as suggested by Shea, but I have a tad more code trying to force it to render brackets/indexes.

<% foreach (var member in Model.TeamMembers) { %>
  <%: Html.EditorFor(x => 
    member, 
    "TeamMember", 
    "TeamMembers["+(member.Number-1)+"]", 
    new { MemberTypes = Model.GetMemberTypes(member.MemberType.TypeId) })%>
<% } %>

Here is an old but still relevant article from Phil Haack on the topic.

查看更多
爱情/是我丢掉的垃圾
3楼-- · 2019-02-14 13:37

Try using this:

<%: Html.EditorFor(m => m.TeamMembers) %>

Then, make a shared editor template with a model type of TeamMember. MVC should handle binding everything back to your viewmodel on post for you.

查看更多
登录 后发表回答