Asp.net mvc ASP.NET MVC模型在编辑器模板中绑定IList
我正在尝试绑定一个列表,该列表是较大视图模型的一部分,而无需使用自定义模型绑定器。当我使用编辑器模板构建输入列表时,生成的名称的格式不正确,默认绑定器无法正常工作 而不是项[3]。我希望是项[3]。Id。如果我在没有编辑器模板的情况下构建列表,它将按预期工作 我是否做了一些明显错误的事情,或者这只是Html.Hidden和Html.TextBox的一个怪癖Asp.net mvc ASP.NET MVC模型在编辑器模板中绑定IList,asp.net-mvc,modelbinders,Asp.net Mvc,Modelbinders,我正在尝试绑定一个列表,该列表是较大视图模型的一部分,而无需使用自定义模型绑定器。当我使用编辑器模板构建输入列表时,生成的名称的格式不正确,默认绑定器无法正常工作 而不是项[3]。我希望是项[3]。Id。如果我在没有编辑器模板的情况下构建列表,它将按预期工作 我是否做了一些明显错误的事情,或者这只是Html.Hidden和Html.TextBox的一个怪癖 public class ItemWrapper { [UIHint("ItemList")] public IList<It
public class ItemWrapper
{
[UIHint("ItemList")]
public IList<Item> Items { get; set; }
}
public class Item
{
public Guid Id { get; set; }
public string Name { get; set; }
public int Value { get; set; }
}
Index.aspx
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Index</h2>
<% using(Html.BeginForm())
{%>
<%:Html.EditorFor(m => m.Items) %>
<%}%>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h4>Does Not Work</h4>
<% using(Html.BeginForm("Test", "Home"))
{%>
<%:Html.EditorFor(m => m.Items) %>
<input type="submit" value-"Go" />
<%}%>
<h4>Does Work</h4>
<% using(Html.BeginForm("Test", "Home"))
{%>
<table>
<tbody>
<% for(int i = 0; i < Model.Items.Count; i++)
{%>
<tr>
<td><%: Model.Items[i].Name%></td>
<td>
<%: Html.HiddenFor(m => Model.Items[i].Id) %>
<%: Html.TextBoxFor(m => Model.Items[i].Value) %>
</td>
</tr>
<%}%>
</tbody>
</table>
<input type="submit" value-"Go" />
<%}%>
</asp:Content>
不起作用
m、 项目)%>
行得通
Model.Items[i].Id)%>
模型.项目[i].值)%>
我已经理解了你的问题,我很可能也有一个解决方案:)
首先,让我向您解释一下我通过检查所学到的知识(检查开源项目的源代码以更好地理解某些事情是如何工作的总是一个好主意)
1-当使用简单强类型的html帮助程序(即除EditorFor和DisplayFor之外的所有html.xxxFor(…)方法)时,在定义要呈现的模型属性的lambda表达式中,生成的html元素的名称等于后面的任何字符串“模型=>”,减去“=>”之前的值,即:
- 如果模型是集合,则字符串“模型”
- 或者字符串“model.”(请注意末尾的“”),否则
<%: Html.TextBoxFor( m=>m.OneProperty.OneNestedProperty)%>
m.OneProperty.OneNestedProperty)%%>
将生成此html输出:
<input type="text" name="OneProperty.OneNestedProperty" ../>
这是:
<%: Html.TextBoxFor( m=>m[0].OneProperty.OneNestedProperty)%>
m[0].OneProperty.OneNestedProperty)%%>
将生成以下内容:
<input type="text" name="[0].OneProperty.OneNestedProperty" ../>
==>这部分解释了为什么在使用EditorFor时会出现这种“奇怪”的html输出。
2-当使用复杂的强类型帮助程序(EditorFor和DisplayFor)时,在关联的局部视图中应用相同的规则(ItemList.ascx,在您的情况下),并且此外,所有生成的html元素将以“==>“,如1-中所述
这里的前缀是“项。”,因为您在键入的视图(Index.aspx)中有此前缀:
m.Items)%%>
==>这完全解释了输出,以及为什么默认活页夹不再适用于您的项目列表
解决方案是将[HttpPost]方法中的ItemWrapper参数分解为他的属性,然后对每个复杂属性使用带有前缀的绑定属性,如下所示:
[HttpPost]
public string Index(string foo,[Bind(Prefix = "Items.")]IList<Item> items)
{
return "Hello";
}
[HttpPost]
公共字符串索引(字符串foo,[Bind(Prefix=“Items.”]IList Items)
{
回复“你好”;
}
(假设ItemWrapper还有一个名为Foo的字符串类型的简单属性)
为了避免冲突,在post方法中列出属性时,我强烈建议您按照每个属性的名称命名参数(不适用于这种情况),就像我所做的那样
希望这会有帮助 更懒惰的解决方案就是使用jQuery来“修复”此类实例。 加载页面(或部分页面)后,只需运行以下功能:
因此,MVC生成字段名的方式确实很奇怪。在生成字段名时,局部视图没有考虑到模型是一个集合。我想如果这些物品。是在视图级别而不是局部视图级别创建的,那么可能没有好的方法来修复它。谢谢。kondotine:听起来像是一个asp.net mvc错误,有人报告过吗?好的,我自己报告:,请投票支持这个错误修复!我发现不需要分解整个视图模型。只需将这些有问题的集合分割成参数就足够了,因此代码可能看起来像
公共字符串索引(ItemWrapper,[Bind(Prefix=“Items”)]IList Items)
。在MVC4jQuery中测试不应该被用作重做损坏的HTML的拐杖。在服务器端修复它。
<input type="text" name="OneProperty.OneNestedProperty" ../>
<%: Html.TextBoxFor( m=>m[0].OneProperty.OneNestedProperty)%>
<input type="text" name="[0].OneProperty.OneNestedProperty" ../>
<%:Html.EditorFor(m => m.Items) %>
[HttpPost]
public string Index(string foo,[Bind(Prefix = "Items.")]IList<Item> items)
{
return "Hello";
}
function makeHiddenInputBindable() {
$('input[type="hidden"]').each(
function (i) {
$(this).attr('name', function () {
return this.name.replace(/\.\[/g, "[");
})
}
);
}