简体   繁体   中英

ASP.NET MVC Complex Model Updating

I have a PersonViewModel that consists of several List<SubViewModel> (Name, Address, etc.)

I have an Html Form with tables for each SubViewModel, where the user can update,add,delete and set items to the primary entry for the person.

a simplified table for names:

@foreach (PersonNameViewModel name in Model.Names)
{
  <tr>
     <td>
         @Html.DisplayFor(modelItem => name.FullName)
     </td>
     <td>
         @Html.DisplayFor(modelItem => name.FirstName)
     </td>
     <td>
         @Html.DisplayFor(modelItem => name.MiddleName)
     </td>
     <td>
         @Html.DisplayFor(modelItem => name.LastName)
     </td>
     <td class="center">
         @Html.RadioButtonFor(modelItem => name.IsPrimary, "")
     </td>
     <td class="center">
         @Html.CheckBoxFor(modelItem => name.ToDelete)
     </td>
  </tr>
}

From here, I don't know how to get all the data back into the PersonViewModel when the user submits the form, to update the person record. If I simply accept a PersonViewModel in my POST controller, it's completely empty. I looked at FormCollection, but I'm not sure if that's right for this. Can someone with experience point me in the right direction for building my model back up for updating? Thankyou very much.

Everyone's answer is correct, But if you want to update people's information, you need to use Html Helper Editor NOT Display . Also, you still can use foreach in your view, just change it like below:

@foreach (var name in Model.Names.Select((value, i) => new { i, value }))
{
    <tr>
        <td>
            @Html.EditorFor(m => m.Names[@name.i].FullName)
        </td>
        <td>
            @Html.EditorFor(m => m.Names[@name.i].FirstName)
        </td>
        <td>
            @Html.EditorFor(m => m.Names[@name.i].MiddleName)
        </td>
        <td>
           @Html.EditorFor(m => m.Names[@name.i].LastName)
        </td>
        <td class="center">
            @Html.RadioButtonFor(m => m.Names[@name.i].IsPrimary,"")
        </td>
        <td class="center">
            @Html.CheckBoxFor(m => m.Names[@name.i].ToDelete)
        </td>
    </tr>
}

You should use sth like this (good article about model binding of collections and complex data here ):

@for(var i = 0;i < Model.Names.Count;i++)
{
  <tr>
     <td>
         @Html.DisplayFor(m => Model.Names[i].FullName)
     </td>
     <td>
         @Html.DisplayFor(m => Model.Names[i].FirstName)
     </td>
     <td>
         @Html.DisplayFor(m => Model.Names[i].MiddleName)
     </td>
     <td>
         @Html.DisplayFor(m => Model.Names[i].LastName)
     </td>
     <td class="center">
         @Html.RadioButtonFor(m => Model.Names[i].IsPrimary, "")
     </td>
     <td class="center">
         @Html.CheckBoxFor(m => Model.Names[i].ToDelete)
     </td>
  </tr>
}

Try replacing the foreach with a for loop:

@for (int i = 0; i < Model.Names.Count; i++)
{
    <tr>
         <td>
                 @Html.DisplayFor(m => m.Names[i].FullName)
         </td>
         <td>
                 @Html.DisplayFor(m => m.Names[i].FirstName)
         </td>
         <td>
                 @Html.DisplayFor(m => m.Names[i].MiddleName)
         </td>
         <td>
                 @Html.DisplayFor(m => m.Names[i].LastName)
         </td>
         <td class="center">
                 @Html.RadioButtonFor(m => m.Names[i].IsPrimary, "")
         </td>
         <td class="center">
                 @Html.CheckBoxFor(m => m.Names[i].ToDelete)
         </td>
    </tr>
}

The expression parsing/model binding does a better job with indexes than with foreach temp variables.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM