2014-02-21 27 views
3

我无法理解asp.net mvc模型绑定器如何工作。asp.net mvc modelbinding不绑定集合

模式

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> 

为什么要默认的模型绑定填充模型上的详细属性?为什么我必须将其作为单独的参数包含在控制器中?

我已经阅读了关于asp和绑定到列表的多篇文章,其中包括在其他问题中被多次引用的Haackeds。这是SO上的this thread,导致我选择了[Binding(Prefix...)]选项。它说'模型可能太复杂了',但是对于默认的模型绑定器来说,究竟是“太复杂”了吗?

+0

你看过可能创建自己的模型粘合剂吗?下面是定制模型绑定器的一个很好的参考:[从MSDN杂志](http://msdn.microsoft.com/en-us/magazine/hh781022.aspx) – jacqijvv

+0

不,我已经看到了可能性,但我更多好奇的为什么asp不能通过它自己来解决这个案例... – Vegar

+0

你应该看看这个旧的[post](http://haacked.com/archive/2008/10/23/model-binding-to -a-list.aspx /)Phil Haack,他很清楚地解释了什么使得一个类型复杂的绑定。但总而言之,动态地(MVC的DefaultModelBinder)确定Request对象中的** id **和** title **的“随机”集合几乎不可能实际上是集合的一部分,而不使用索引。 – jacqijvv

回答

0

您的问题中的模型不是'太复杂'。 但是,复杂类型的列表(如您的Details对象)将是一个复杂的绑定。

对于复杂绑定使用EditorTemplates。这个editorTemplate指定了如何渲染复杂类型的编辑器。 EditorTemplates正在视图所在文件夹内的'EditorTemplates'文件夹中进行搜索。 editortemplate必须默认具有复杂类型类的名称。所以,在你情况下,你应该将其命名为Detail.cshtml

您editortemplate里面,你可以使用类似:

@model Detail 

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

现在当你调用@Html.EditorFor(m => m.Details)在regualar模型,在详细信息列表中的每个项目中,指定的editortemplated将被渲染。

在您控制器那里的行动点,你可以问你一个实例模型,如:

public ActionResult Save(Master model) 
{ 

} 

现在保存方法中,model.Details将充满您的视图中的数据。

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

+0

这正是我所做的。我可以看到它并不完全清楚。我将编辑这个问题一点点... – Vegar

+0

这将是奇怪的,因为这应该工作。那么我们一定错过了一些东西。这个EditorFor(m => m.Details)是否在你的表单中呈现? – middelpat

+0

是的,所有东西都呈现出来,并且每件东西都会回传给服务器。不同之处在于,在替代方案1中,细节项不是从表单数据转换为细节对象,而是在替代方案2中。 – Vegar