2014-02-21 54 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