我有包括该书的平面信息,如标题,PublishYear和等加书作者的集合(复杂类型)的BookCreateModel:
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鉴于我已经使用EditorFor
帮手:
@Html.EditorFor(m => m.Authors, "AuthorSelector")
EDIT1:
和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
它增加了一个额外的点,这使得默认的模型绑定无法解析发布的数据。
任何的想法 ?
谢谢 !
Answer 1:
我建议你坚持公约,如更换:
@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
的属性。
Answer 2:
我有点迟到了,但希望这可以帮助别人。
挖下来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>
我发现这个特别有用的框架正在写名称为[0].Children.[0].ChildProperty
由于对儿童收集命名模板。 在我的情况下,解决办法是拨打:
@Html.EditorFor(m => m[i], null, String.Format("{0}[{1}]", prefix, i))
而不是简单地调用:
@Html.EditorFor(m => m[i])
Answer 3:
不知道它是否仍然是相关的,但这个博客涵盖了解决问题的方法: http://btburnett.com/2011/03/correcting-mvc-3-editorfor-template-field-names-when-using-collections html的
- >积分去itsmatt寻找它:)雅各布
Answer 4:
这里是你可以用这会使局部视图,并使用正确的HTML字段前缀的扩展方法:
扩展方法
/// <summary>
/// Helper method that renders the specified partial view as a HTML-encoded string using the specified
/// collection as the model, with the intention that the partial view will use an editor template on the items
/// in the collection.
/// </summary>
/// <typeparam name="TModel">the model type</typeparam>
/// <typeparam name="TProperty">the property type</typeparam>
/// <param name="htmlHelper">the <see cref="HtmlHelper"/> instance</param>
/// <param name="partialViewName">the name of the partial view to render</param>
/// <param name="collectionExpression">the model collection property expression</param>
/// <returns>the HTML-encoded string</returns>
public static MvcHtmlString PartialContainingEditorForCollection<TModel, TProperty>
(this HtmlHelper<TModel> htmlHelper, string partialViewName,
Expression<Func<TModel, TProperty>> collectionExpression)
where TProperty : IEnumerable
{
var viewData = htmlHelper.ViewContext.ViewData;
var model = (TModel) viewData.Model;
var collection = collectionExpression.Compile().Invoke(model);
var htmlFieldPrefix = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(
ExpressionHelper.GetExpressionText(collectionExpression));
return htmlHelper.Partial(partialViewName, collection,
new ViewDataDictionary
{
TemplateInfo = new TemplateInfo {HtmlFieldPrefix = htmlFieldPrefix}
});
}
用法示例
@Html.PartialContainingEditorForCollection("_TableWithSummary", m => Model.FormModel.ItemsToOrder)
Answer 5:
我没有找到任何解决这个错误还,但作为一种解决方法我改变了我UpdateModel
通过使用自定义包装类,而不是直接使用集合:
public class BookCreateModel
{
public string Title { get; set; }
public int Year { get; set; }
public BookAuthorsList Authors { get; set; }
}
public class BookAuthorsList
{
public IList<AuthorEntryModel> AuthorsList { get; set; }
}
public class AuthorEntryModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
而由此产生的投入不会做出了命名问题:)
<input id="Authors_AuthorsList_0__FirstName" name="Authors.AuthorsList[0].FirstName" type="text"/>
<input id="Authors_AuthorsList_0__LastName" name="Authors.AuthorsList[0].LastName" type="text"/>
Answer 6:
我偶然发现了这个,当我试图找到几乎相同的问题的解决方案。 我的解决方法是踢罐头的道路,即。 使包装模型的收集和使用,在编辑模板。 在提供的情况下,这将是:
public class BookCreateModel
{
public string Title { get; set; }
public int Year { get; set; }
public BookAuthorsModel Authors { get; set; }
}
public class BookAuthorsModel
{
IList<AuthorEntryModel> Items { get; set; }
}
然后你的编辑模板,重新命名为“BookAuthorsModel.cshtml”,使之像这样:
@model BookAuthorsModel
<div class="ptr_authors_wrapper">
@for (int i = 0; i < Model.Items.Count; i++)
{
<div class="ptr_author_line" data-line-index="@i">
@Html.TextBoxFor(o => Items.o[i].FirstName)
@Html.TextBoxFor(o => Items.o[i].LastName)
</div>
}
</div>
<script>
...
</script>
而当你要使用它,只需拨打:
@Html.EditorFor(m => m.Authors)
然后,它应该产生像这样输入字段:
<input id="Authors_Items_0__FirstName" name="Authors.Items[0].FirstName" type="text" value="" />
<input id="Authors_Items_0__LastName" name="Authors.Items[0].LastName" type="text" value="" />
在我来说,我也适当改变Automapper映射设置控制器代码。 这不是然而,一些更复杂的场景可用,因此可能只是一种变通方法。
文章来源: when passing a collection to EditorFor(), it generates invalid names for input elements