Ali*_*uri 10 asp.net-mvc model-binding editorfor razor asp.net-mvc-3
我有一个BookCreateModel,它包含书籍的平面信息,例如Title,PublishYear&etc以及书籍作者集合(复杂类型):
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; }
}
Run Code Online (Sandbox Code Playgroud)
在CreateBook视图中我使用了EditorForhelper:
@Html.EditorFor(m => m.Authors, "AuthorSelector")
Run Code Online (Sandbox Code Playgroud)
和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>
Run Code Online (Sandbox Code Playgroud)
该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="" />
Run Code Online (Sandbox Code Playgroud)
正如你所看到的那样,不是生成名称,Authors[0].FirstName而是添加一个额外的点,这使得默认模型绑定器无法解析发布的数据.
任何的想法 ?
谢谢 !
我建议你坚持惯例,即替换:
@Html.EditorFor(m => m.Authors, "AuthorSelector")
Run Code Online (Sandbox Code Playgroud)
有:
@Html.EditorFor(m => m.Authors)
Run Code Online (Sandbox Code Playgroud)
然后重命名你~/Views/Shared/EditorTemplates/AuthorSelector.cshtml的~/Views/Shared/EditorTemplates/AuthorEntryModel.cshtml并将其强类型化为单个AuthorEntryModel模型并摆脱循环:
@model AuthorEntryModel
@Html.TextBoxFor(o => o.FirstName)
@Html.TextBoxFor(o => o.LastName)
Run Code Online (Sandbox Code Playgroud)
ASP.NET MVC将自动为集合的所有元素呈现编辑器模板并生成专有名称.
更新:
在看到您的更新后,我的回复是:
在您的主视图中:
<div class="ptr_authors_wrapper">
@Html.EditorFor(m => m.Authors)
</div>
Run Code Online (Sandbox Code Playgroud)
在您的编辑器模板中:
@model AuthorEntryModel
<div class="ptr_author_line">
@Html.TextBoxFor(o => o.FirstName)
@Html.TextBoxFor(o => o.LastName)
</div>
Run Code Online (Sandbox Code Playgroud)
你会注意到模板中缺少脚本是完全正常的.脚本与标记无关.他们进入单独的JavaScript文件.在这个文件中,您可以使用jQuery来执行标记所需的任何操作.它为您提供了一些方法.index(),允许您在匹配的选择器中获取元素的索引,这样您就不需要编写任何循环并使用data-line-index属性之类的东西污染您的标记.
我参加派对有点晚了,但希望这对某人有所帮助.
向下挖掘System.Web.Mvc.Html.DefaultEditorTemplates.CollectionTemplate(HtmlHelper html, TemplateHelpers.TemplateHelperDelegate templateHelper),框架的默认模板通过临时设置HtmlFieldPrefix为空字符串并显式地将前缀和索引传递给调用来处理此问题EditorFor().
<div class="ptr_authors_wrapper">
@{
var prefix = ViewData.TemplateInfo.HtmlFieldPrefix;
ViewData.TemplateInfo.HtmlFieldPrefix = String.Empty;
for (int i = 0; i < Model.Count; i++)
{
<div class="ptr_author_line" data-line-index="@i">
@* You can also use null instead of "TextBox" to let the framework resolve which editor to use. *@
@Html.EditorFor(o => o[i].FirstName, "TextBox", String.Format("{0}[{1}].FirstName", prefix, i))
@Html.EditorFor(o => o[i].LastName, "TextBox", String.Format("{0}[{1}].LastName", prefix, i))
</div>
}
ViewData.TemplateInfo.HtmlFieldPrefix = prefix;
}
</div>
<script>
...
</script>
Run Code Online (Sandbox Code Playgroud)
我发现当框架[0].Children.[0].ChildProperty因为Children集合的命名模板而编写名称时,这特别有用.就我而言,解决方案是致电:
@Html.EditorFor(m => m[i], null, String.Format("{0}[{1}]", prefix, i))
Run Code Online (Sandbox Code Playgroud)
而不是简单地调用:
@Html.EditorFor(m => m[i])
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11711 次 |
| 最近记录: |