如何在MVC3中将嵌套的ViewModel从View绑定到Controller?

Cic*_*ami 25 c# binding viewmodel asp.net-mvc-3

我正在用C#开发一个ASP.NET MVC 3应用程序,我使用Razor.我现在正处理一个问题,涉及通过Controller向View传递/接收的ViewModel绑定对象.让我们说清楚.我有以下ViewModels:

public class ContainerViewModel
{
   public int ContainerId {get; set;}
   public string ContainerName {get; set;}
   public List<ItemPostModel> ItemData {get; set;}
}

public class ItemPostModel
{ 
   public int ItemId {get; set;}
   public string ItemName {get; set;}
   public int ItemValue {get; set;}
}
Run Code Online (Sandbox Code Playgroud)

ContainerViewModel用于将数据传递给视图.其属性ContainerIdContainerName仅用于显示目的.该List<ItemPostModel>酒店于使用填充表单.View看起来像这样(它是简化版):

<strong>@Model.ContainerName</strong>


@using (Html.BeginForm()) 
{
    <fieldset>
    @foreach(var item in Model.ItemData)
    {
       @Html.TextBox(item.ItemId);
       @Html.TextBox(item.ItemName);
       @Html.TextBox(item.ItemValue);

       <p>
           <input type="submit" value="Save" />
       </p>
    }
    </fieldset>
}
Run Code Online (Sandbox Code Playgroud)

控制器相应的操作方法如下:

public ActionResult UpdateItems()
{
   //fill in the ContainerViewModel lcontainer

   return View("UpdateItems", lcontainer);
}

[HttpPost]
public ActionResult UpdateItems(int containerId, ItemPostModel itemData)
{
   //store itemData into repository
}
Run Code Online (Sandbox Code Playgroud)

问题是,这种代码ItemPostModel的ItemData传递给邮政ActionMethod UpdateItems总是空的.该数据筒被正确地传递.如果我在Controller中使用以下代码(显然不是DRY),结果相同;

[HttpPost]
public ActionResult UpdateItems(ContainerViewModel container)
{
   //extract itemData from ContainerViewModel container
   //store itemData into repository
}
Run Code Online (Sandbox Code Playgroud)

如何"教"我希望表单元素存储在应用程序中List<ItemPostModel>?我应该修改ModelBinder还是有一种更简单的方法来执行这个任务?谢谢大家的回答.

Dar*_*rov 26

不要在视图中写循环.使用编辑器模板:

<strong>@Model.ContainerName</strong>
@using (Html.BeginForm()) 
{
    <fieldset>
        @Html.EditorFor(x => x.ItemData)
        <input type="submit" value="Save" />
    </fieldset>
}
Run Code Online (Sandbox Code Playgroud)

并在相应的编辑器模板(~/Views/Shared/EditorTemplates/ItemPostModel.cshtml)内:

@model ItemPostModel
@Html.TextBox(x => x.ItemId)
@Html.TextBox(x => x.ItemName)
@Html.TextBox(x => x.ItemValue)
Run Code Online (Sandbox Code Playgroud)

在控制器操作中,您可能需要指定前缀:

[HttpPost]
public ActionResult UpdateItems(
    int containerId, 
    [Bind(Prefix = "ItemData")]ItemPostModel itemData
)
{
   //store itemData into repository
}
Run Code Online (Sandbox Code Playgroud)

这应该是全部.编辑器模板将负责为绑定生成正确的输入字段名称.