我花了大约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>

10-02 04:23