我花了大约3个小时来确定为什么发生以下(解释的)错误;最后,我确定这是MVC错误。我想问一下您的意见。
我创建了一个编辑器模板,并将其放在〜/ Shared / EditorTemplates文件夹下。而且我谨慎地使用了文件名,使其与类型名相同(因为我不想将第二个参数与“ @ Html.EditorFor”帮助器方法一起使用)。结果,编辑器模板运行良好:除了回发;我肯定无法从模型中获取值,因为模型始终为空。我试图更改输入的ID和名称,并仔细选择,然后回发帖子:它工作正常。
所以;问题是:当我使用editorTemplate时,它以“ Question。[0] .QuestionContext”作为名称,并以“ Question__0_QuestionContext”作为输入和选择的ID;但是我希望以“ Question [0] .QuestionContext”作为名称,并以“ Question_0__QuestionContext”作为id。
然后我意识到我在EditorTemplate中使用@foreach。然后我切换回@for,但没有任何改变。您可以在下面找到模板:
@using DenemeMvc3Application3.Helpers;
@model DenemeMvc3Application3.Controllers.LocalizedNameViewModels
<table>
<thead>
<tr>
<td>@Html.LabelFor(modelItem => modelItem.ElementAtOrDefault(0).LanguageDropDownList)</td>
<td>@Html.LabelFor(modelItem => modelItem.ElementAtOrDefault(0).Value)</td>
</tr>
</thead>
<tbody>
@for (int index = 0; index < Model.Count; index++)
{
@Html.EditorFor(modelItem => modelItem[index])
}
</tbody>
</table>
因此,通过在editortemplate的外部和视图的内部声明foreach循环,并仅将编辑器模板用于单个项目,将模板更改为更简单的模板。而且有效。因此,我对使用反射器在mvc3上的模板工作原理进行了小小的研究。我发现了我认为的错误:
该问题是由System.Web.Mvc.TemplateInfo类的公共字符串GetFullHtmlFieldName(string partialFieldName)方法引起的,该方法由System.Web.Mvc.Html.SelectExtensions类的私有静态MvcHtmlString SelectInternal(此HtmlHelper htmlHelper,字符串optionLabel,字符串名称, IEnumerable selectList,bool allowMultiple,IDictionary htmlAttributes)方法。
因此,每当我们在EditorTemplate的foreach或for循环内使用@ Html.DropDownListFor(/ blah blah /)时,都会收到错误。
我还想向您展示下面的错误代码以进行说明:
// TemplateInfo method
public string GetFullHtmlFieldName(string partialFieldName)
{
/*Here's the extra dot: causing the error.*/
return (this.HtmlFieldPrefix + "." + (partialFieldName ?? string.Empty)).Trim(new char[] { '.' });
}
// SelectExtensions method
private static MvcHtmlString SelectInternal(this HtmlHelper htmlHelper, string optionLabel, string name, IEnumerable<SelectListItem> selectList, bool allowMultiple, IDictionary<string, object> htmlAttributes)
{
/* blah blah */
string fullHtmlFieldName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
/* blah blah */
}
// SelectExtensions method -> @Html.DropDownListFor
private static MvcHtmlString DropDownListHelper(HtmlHelper htmlHelper, string expression, IEnumerable<SelectListItem> selectList, string optionLabel, IDictionary<string, object> htmlAttributes)
{
return htmlHelper.SelectInternal(optionLabel, expression, selectList, false, htmlAttributes);
所以你的想法是什么?
最佳答案
然后我意识到我在EditorTemplate中使用@foreach。
然后我切换回@for,但没有任何改变。
如何摆脱所有循环并简单地:
@model IEnumerable<FooViewModel>
<table>
<thead>
<tr>
<td>@Html.LabelFor(modelItem => modelItem.ElementAtOrDefault(0).LanguageDropDownList)</td>
<td>@Html.LabelFor(modelItem => modelItem.ElementAtOrDefault(0).Value)</td>
</tr>
</thead>
<tbody>
@Html.EditorForModel()
</tbody>
</table>
好多了?没有循环,正确的名称和ID。这是ASP.NET MVC,它将为模型集合的每个元素自动呈现编辑器模板。
以及相应的编辑器模板(
~/Views/Shared/EditorTemplates/FooViewModel.cshtml
):@model FooViewModel
<tr>
<td>@Html.EditorFor(x => x.SomeProperty)</td>
<td>@Html.EditorFor(x => x.SomeOtherProperty)</td>
</tr>