asp.net-mvc - 将集合传递给 EditorFor() 时,它会为输入元素生成无效名称

标签 asp.net-mvc asp.net-mvc-3 razor model-binding editorfor

我有一个 BookCreateModel,其中包含书籍的平面信息,例如 Title、PublishYear 等以及书籍作者的集合(复杂类型):

public class BookCreateModel
{
    public string Title { get; set; }
    public int Year { get; set; }
    public IList<AuthorEntryModel> Authors { get; set; }
}

public class AuthorEntryModel
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

在 CreateBook View 中我使用了 EditorFor helper :
@Html.EditorFor(m => m.Authors, "AuthorSelector")

编辑1:

AuthorSelector 模板如下:
<div class="ptr_authors_wrapper">
    @for (int i = 0; i < Model.Count; i++)
    {
       <div class="ptr_author_line" data-line-index="@i">
        @Html.TextBoxFor(o => o[i].FirstName)
        @Html.TextBoxFor(o => o[i].LastName)
       </div>
    }
</div>
<script>
     ...
</script>
AuthorSelector模板包含一些包装标记,这些标记需要了解每个渲染项的索引,以及一些处理子输入交互并且需要渲染一次的 javascript(在 AuthorSelector 模板内),从而摆脱了 for 循环/或 AuthorSelector模板是不可能的。

现在的问题是 EditorFor 的行为有点奇怪,并生成这样的输入名称:
<input id="Authors__0__FirstName" name="Authors.[0].FirstName" type="text" value="" />
<input id="Authors__0__LastName" name="Authors.[0].LastName" type="text" value="" />

如您所见,而不是生成像 Authors[0].FirstName 这样的名称它添加了一个额外的点,使默认模型绑定(bind)器无法解析发布的数据。

任何的想法 ?

谢谢 !

最佳答案

我建议您遵守约定,即替换:

@Html.EditorFor(m => m.Authors, "AuthorSelector")

和:
@Html.EditorFor(m => m.Authors)

然后重命名你的~/Views/Shared/EditorTemplates/AuthorSelector.cshtml~/Views/Shared/EditorTemplates/AuthorEntryModel.cshtml并将其强类型化为单个 AuthorEntryModel模型并摆脱循环:
@model AuthorEntryModel
@Html.TextBoxFor(o => o.FirstName)
@Html.TextBoxFor(o => o.LastName)

ASP.NET MVC 将自动为集合的所有元素呈现编辑器模板并生成正确的名称。

更新:

看到您的更新后,这是我的回复:

在您的主视图中:
<div class="ptr_authors_wrapper">
    @Html.EditorFor(m => m.Authors)
</div>

在您的编辑器模板中:
@model AuthorEntryModel
<div class="ptr_author_line">
    @Html.TextBoxFor(o => o.FirstName)
    @Html.TextBoxFor(o => o.LastName)
</div>

您会注意到模板中没有脚本,这是完全正常的。脚本与标记无关。它们进入单独的 javascript 文件。在这个文件中,您可以使用 jQuery 对您的标记做任何您需要做的事情。它为您提供诸如 .index() 之类的方法这允许您在匹配的选择器中获取元素的索引,这样您就不需要编写任何循环并用 data-line-index 之类的东西污染您的标记属性。

关于asp.net-mvc - 将集合传递给 EditorFor() 时,它会为输入元素生成无效名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11403442/

相关文章:

c# - 避免在 Action 中渲染 View 的正确方法

asp.net-mvc - MVC导航到其他 Controller View

c# - 与实例化 Web 引用代理类相关的开销是多少?

c# - 多次抛出 "Missing compiler required member"错误,几乎没有更改代码

asp.net-mvc - 通过Ext.Net.ComponentLoader调用PartialView

Razor HTML条件输出

c# - MVC 5、EF 6 Barebones 无效的列名称 'Model'

asp.net-mvc-3 - 无效的对象名称 dbo.TableName

c# - ASP.NET MVC - 路由问题

c# - 不使用 Javascript(C# MVC3) 将搜索过滤器添加到 URL