模型的ASP.NET MVC结合嵌套集合 [英] Model binding nested collections in ASP.NET MVC
问题描述
我使用的是史蒂夫·桑德森的<一个href=\"http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/\">BeginCollectionItem在ASP.NET MVC 2帮手模型绑定,如果项目的集合。
这工作得很好,只要藏品的模型不包含另一个集合。
我有这样一个模型:
- 产品搜索
--Variants结果
--- IncludedAttributes
每当我渲染和模型结合的变体集合,它的工作原理jusst罚款。但随着IncludedAttributes收藏,我无法使用BeginCollectionItem帮手,因为ID和名称值不会兑现的ID和名称值是因为它产生的是父变:
&LT; DIV CLASS =变种&GT;
&LT;输入类型=隐藏值=bbd4fdd4-fa22-49f9-8a5e-3ff7e2942126自动完成=关闭NAME =Variants.index&GT;
&LT;输入类型=隐藏值=0NAME =变体bbd4fdd4-fa22-49f9-8a5e-3ff7e2942126] .SlotAmountID =Variants_bbd4fdd4-fa22-49f9-8a5e-3ff7e2942126__SlotAmount&GT;
&LT;表类=包含的属性&GT;
&LT;输入类型=隐藏值=0NAME =Variants.IncludedAttributes [c5989db5-b1e1-485b-b09d-a9e50dd1d2cb] .IDID =Variants_IncludedAttributes_c5989db5-b1e1-485b-b09d-a9e50dd1d2cb__Id级=属性-id&GT;
&所述; TR&GT;
&所述; TD&GT;
&LT;输入类型=隐藏值=0NAME =Variants.IncludedAttributes [c5989db5-b1e1-485b-b09d-a9e50dd1d2cb] .IDID =Variants_IncludedAttributes_c5989db5-b1e1-485b-b09d-a9e50dd1d2cb__Id级=属性-id&GT;
&LT; / TD&GT;
&LT; / TR&GT;
&LT; /表&gt;
&LT; / DIV&GT;
如果你看一下表中的第一个隐藏字段的名称,它是Variants.IncludedAttributes - 它应该是变体bbd4fdd4-fa22-49f9-8a5e-3ff7e2942126] .IncludedAttributes [...] ...
这是因为当我打电话BeginCollectionItem第二次(在IncludedAttributes集合)也给了没有关于它的项目指标值信息的父变体。
我的code呈现一个Variant看起来是这样的:
&LT; DIV CLASS =产品变圆的内容盒grid_6数据-ID =&LT;%:Model.AttributeType.Id%&GT;&GT;
&LT; H2&GT;&LT;%:Model.AttributeType.AttributeTypeName%GT;&LT; / H&GT;
&LT; DIV CLASS =框内容&GT;
&LT;使用(Html.BeginCollectionItem(变)){%GT%; &LT; DIV CLASS =插槽金额&GT;
&LT;标签类=内联为=slotAmountSelectList&GT;&LT;%:Text.amountOfThisVariant%&GT;:&LT; /标签&gt;
&LT;选择一个id =slotAmountSelectList&GT;&LT;期权价值=1&GT; 1&LT; /选项&GT;&LT;期权价值=2&GT; 2&LT; /选项&GT;&LT; /选择&GT;
&LT; / DIV&GT; &LT; DIV CLASS =增加值&GT;
&LT;标签类=内联为=txtProductAttributeSearch&GT;&LT;%:Text.addVariantItems%&GT;:&LT; /标签&gt;
&LT;输入类型=文本ID =txtProductAttributeSearch级=产品属性搜索/&GT;&LT;跨度&GT;&LT;%:Text.or%GT; &LT;一类=选择 - 从列表链接的href =#选择 - 从列表数据-ID =&LT;%:Model.AttributeType.Id%&GT;&GT;&LT;%:文本。 selectFromList.ToLowerInvariant()%GT;&下; / A&GT;&下; /跨度&GT;
&LT; DIV CLASS =清除&GT;&LT; / DIV&GT;
&LT; / DIV&GT;
&所述;%:Html.HiddenFor(M =&GT; m.SlotAmount)%GT; &LT; DIV CLASS =包含的属性&GT;
&LT;表&gt;
&LT;&THEAD GT;
&所述; TR&GT;
百分位&GT;&LT;%:Text.name%GT;&LT; /第i
百分位风格=宽度:80px;&GT;&LT;%:Text.price%GT;&LT; /第i
百分位&GT;&LT;%:Text.shipping%GT;&LT; /第i
百分位风格=宽度:90像素;&GT;&LT;%:Text.image%GT;&LT; /第i
&LT; / TR&GT;
&LT; / THEAD&GT;
&LT;&TBODY GT;
&LT;%的for(int i = 0; I&LT; Model.IncludedAttributes.Count;我++){%GT;
&LT; TR&GT;&LT;%:Html.EditorFor(M = GT; m.IncludedAttributes [I])%GT;&LT; / TR&GT;
&LT;%}%GT;
&LT; / TBODY&GT;
&LT; /表&gt;
&LT; / DIV&GT; &LT;%}%GT;
&LT; / DIV&GT;
&LT; / DIV&GT;
而code为渲染IncludedAttribute:
&LT;%使用(Html.BeginCollectionItem(Variants.IncludedAttributes)){%GT;
&所述; TD&GT;
&LT;%:Model.AttributeName%GT;
&LT;%:Html.HiddenFor(M = GT; m.Id,新{@class =属性ID})%GT;
&所述;%:Html.HiddenFor(M =&GT; m.ProductAttributeTypeId)%GT;
&LT; / TD&GT;
&LT; TD&GT;&LT;%:Model.Price.ToCurrencyString()%GT;&LT; / TD&GT;
&所述; TD&GT;&下;%:Html.DropDownListFor(M =&GT; m.RequiredShippingTypeId,AppData.GetShippingTypesSelectListItems(Model.RequiredShippingTypeId))%&GT;&下; / TD&GT;
&所述; TD&GT;&下;%:Model.ImageId%GT;&下; / TD&GT;
&LT;%}%GT;
当你正在使用MVC 2和EditorFor,你不应该需要用史蒂夫的解决方案,我相信这是只是一个变通的MVC 1.你应该只是能够做这样的事情:
&LT;%的for(int i = 0; I&LT; Model.Variants.Count;我++){%GT;
&LT;%= Html.DisplayFor(M = GT; m.Variants [I] .AttributeType.AttributeTypeName)%GT;
&LT;%为(INT J = 0; J&LT; Model.Variants [I] .IncludedAttributes.Count; J ++){%GT;
&LT;%= Html.EditorFor(M = GT; m.Variants [I] .IncludedAttributes [J])%GT;
&LT;%}%GT;
&LT;%}%GT;
请注意,使用索引的... [I] ... [J] ...是重要的,是MVC怎么会知道如何渲染ID和姓名正确。
I'm using Steve Sanderson's BeginCollectionItem helper with ASP.NET MVC 2 to model bind a collection if items.
That works fine, as long as the Model of the collection items does not contain another collection.
I have a model like this:
-Product
--Variants
---IncludedAttributes
Whenever I render and model bind the Variants collection, it works jusst fine. But with the IncludedAttributes collection, I cannot use the BeginCollectionItem helper because the id and names value won't honor the id and names value that was produced for it's parent Variant:
<div class="variant">
<input type="hidden" value="bbd4fdd4-fa22-49f9-8a5e-3ff7e2942126" autocomplete="off" name="Variants.index">
<input type="hidden" value="0" name="Variants[bbd4fdd4-fa22-49f9-8a5e-3ff7e2942126].SlotAmount" id="Variants_bbd4fdd4-fa22-49f9-8a5e-3ff7e2942126__SlotAmount">
<table class="included-attributes">
<input type="hidden" value="0" name="Variants.IncludedAttributes[c5989db5-b1e1-485b-b09d-a9e50dd1d2cb].Id" id="Variants_IncludedAttributes_c5989db5-b1e1-485b-b09d-a9e50dd1d2cb__Id" class="attribute-id">
<tr>
<td>
<input type="hidden" value="0" name="Variants.IncludedAttributes[c5989db5-b1e1-485b-b09d-a9e50dd1d2cb].Id" id="Variants_IncludedAttributes_c5989db5-b1e1-485b-b09d-a9e50dd1d2cb__Id" class="attribute-id">
</td>
</tr>
</table>
</div>
If you look at the name of the first hidden field inside the table, it is Variants.IncludedAttributes - where it should have been Variants[bbd4fdd4-fa22-49f9-8a5e-3ff7e2942126].IncludedAttributes[...]...
That is because when I call BeginCollectionItem the second time (On the IncludedAttributes collection) there's given no information about the item index value of it's parent Variant.
My code for rendering a Variant looks like this:
<div class="product-variant round-content-box grid_6" data-id="<%: Model.AttributeType.Id %>">
<h2><%: Model.AttributeType.AttributeTypeName %></h2>
<div class="box-content">
<% using (Html.BeginCollectionItem("Variants")) { %>
<div class="slot-amount">
<label class="inline" for="slotAmountSelectList"><%: Text.amountOfThisVariant %>:</label>
<select id="slotAmountSelectList"><option value="1">1</option><option value="2">2</option></select>
</div>
<div class="add-values">
<label class="inline" for="txtProductAttributeSearch"><%: Text.addVariantItems %>:</label>
<input type="text" id="txtProductAttributeSearch" class="product-attribute-search" /><span><%: Text.or %> <a class="select-from-list-link" href="#select-from-list" data-id="<%: Model.AttributeType.Id %>"><%: Text.selectFromList.ToLowerInvariant() %></a></span>
<div class="clear"></div>
</div>
<%: Html.HiddenFor(m=>m.SlotAmount) %>
<div class="included-attributes">
<table>
<thead>
<tr>
<th><%: Text.name %></th>
<th style="width: 80px;"><%: Text.price %></th>
<th><%: Text.shipping %></th>
<th style="width: 90px;"><%: Text.image %></th>
</tr>
</thead>
<tbody>
<% for (int i = 0; i < Model.IncludedAttributes.Count; i++) { %>
<tr><%: Html.EditorFor(m => m.IncludedAttributes[i]) %></tr>
<% } %>
</tbody>
</table>
</div>
<% } %>
</div>
</div>
And the code for rendering an IncludedAttribute:
<% using (Html.BeginCollectionItem("Variants.IncludedAttributes")) { %>
<td>
<%: Model.AttributeName %>
<%: Html.HiddenFor(m => m.Id, new { @class = "attribute-id" })%>
<%: Html.HiddenFor(m => m.ProductAttributeTypeId) %>
</td>
<td><%: Model.Price.ToCurrencyString() %></td>
<td><%: Html.DropDownListFor(m => m.RequiredShippingTypeId, AppData.GetShippingTypesSelectListItems(Model.RequiredShippingTypeId)) %></td>
<td><%: Model.ImageId %></td>
<% } %>
As you are using MVC 2 and EditorFor, you shouldn't need to use Steve's solution, which I believe is just a work around for MVC 1. You should just be able to do something like:
<% for (int i = 0; i < Model.Variants.Count; i++) { %>
<%= Html.DisplayFor(m => m.Variants[i].AttributeType.AttributeTypeName) %>
<% for (int j = 0; j < Model.Variants[i].IncludedAttributes.Count; j++) { %>
<%= Html.EditorFor(m => m.Variants[i].IncludedAttributes[j]) %>
<% } %>
<% } %>
Please note that the use of the indexes ...[i]...[j]... is important and is how MVC will know how to render the Id's and names correctly.
这篇关于模型的ASP.NET MVC结合嵌套集合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!