asp.net mvc modelbinding没有绑定集合

时间:2014-02-21 12:16:08

标签: c# asp.net asp.net-mvc asp.net-mvc-4 razor

我无法理解asp.net mvc模型绑定器是如何工作的。

模型

public class Detail
{
  public Guid Id { get; set; }
  public string Title {get; set; }    
}

public class Master
{
  public Guid Id { get; set;}
  public string Title { get; set; }
  public List<Detail> Details { get; set; }
}

查看

 <!-- part of master view in ~/Views/Master/EditMaster.cshtml -->
 @model Master

 @using (Html.BeginForm())
 {
     @Html.HiddenFor(m => m.Id)
     @Html.TextBoxFor(m => m.Title)

     @Html.EditorFor(m => m.Details)

     <!-- snip -->
 }

 <!-- detail view in ~/Views/Master/EditorTemplates/Detail.cshtml -->
 @model Detail

 @Html.HiddenFor(m => m.Id)
 @Html.EditorFor(m => m.Title)

控制器

// Alternative 1 - the one that does not work
public ActionResult Save(Master master)
{
   // master.Details not populated!
}

// Alternative 2 - one that do work
public ActionResult Save(Master master, [Bind(Prefix="Details")]IEnumerable<Detail> details)
{
   // master.Details still not populated, but details parameter is.
}

呈现HTML

<form action="..." method="post">
  <input type="hidden" name="Id" value="....">
  <input type="text" name="Title" value="master title">
  <input type="hidden" name="Details[0].Id" value="....">
  <input type="text" name="Details[0].Title value="detail title">
  <input type="hidden" name="Details[1].Id" value="....">
  <input type="text" name="Details[1].Title value="detail title">
  <input type="hidden" name="Details[2].Id" value="....">
  <input type="text" name="Details[2].Title value="detail title">
  <input type="submit">
</form>

为什么希望默认模型绑定器填充模型上的Details-property?为什么我必须将其作为单独的参数包含在控制器中?

我已经阅读了多篇关于asp和绑定到列表的帖子,包括在其他问题中多次引用的Haackeds。 SO this thread引导我[Binding(Prefix...)]选项。它说这个模型可能过于复杂了,但究竟是什么“过于复杂”。使用默认模型绑定器?

1 个答案:

答案 0 :(得分:0)

你问题中的模型并不“过于复杂”。 但是,复杂类型的列表(如您的Details对象)将是一个复杂的绑定。

对于复杂绑定,使用EditorTemplates。此editorTemplate指定如何呈现复杂typ的编辑器。 EditorTemplates正在视图所在文件夹中的“EditorTemplates”文件夹中搜索。默认情况下,editortemplate必须具有复杂类型类的名称。所以在你的情况下你应该将它命名为Detail.cshtml

在您的editortemplate中,你可以使用类似的东西:

@model Detail

@Html.HiddenFor(m => m.Id)
@Html.TextBoxFor(m => m.Title)

现在当你在你的regualar模型中调用@Html.EditorFor(m => m.Details)时,对于Details列表中的每个项目,将呈现指定的editortemplated。

在操作指向的控制器中,您可以只询问模型的实例:

public ActionResult Save(Master model)
{ 

}

现在在Save方法中,model.Details将填充您视图中的数据。

请注意,MVC只会将数据返回到您表单中可用的控制器。所有未呈现或未在表单内的数据都不会被返回。