Razor:如果model是List 那么@ Html.LabelFor会创建空的“for”字段

如果模型是对象列表,则@Html.LabelFor model => model[i].member) for属性创建一个空。 DisplayName工作正常,模型绑定也可以正常工作。 唯一不起作用的是for属性。

下面有两个版本的MVC代码。 前3个代码片段用于不起作用的模型,控制器和视图组合(模型是列表)。 第二组3个代码片段起作用。 这次列表包含在一个对象中。

我错过了什么?

模型:

 public class ViewModel { public bool ClickMe { get; set; } } 

控制器:

 public ActionResult LabelForViewModel() { List model = new List() { new ViewModel() { ClickMe = true} }; return View(model); } 

视图:

 @model List // form code removed for brevity @for (var i = 0; i < Model.Count; i++) { 
@Html.LabelFor(model => model[i].ClickMe)
@Html.EditorFor(model => model[i].ClickMe, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model[i].ClickMe, "", new { @class = "text-danger" })
}

标记:

 

请注意,for字段为空,输入没有id字段(在“for”字段中使用该字段)。

我创建了一个包装器模型,其中包含一个对象列表,修改了控制器和视图,然后它工作得很好。 在这种情况下,“for”字段被正确填写,一切都按预期工作。

 public class ListWrapper { public List ViewModels { get; set; } } 

视图:

 @for (var i = 0; i < Model.ViewModels.Count; i++) { 
@Html.LabelFor(model => model.ViewModels[i].ClickMe)
@Html.EditorFor(model => model.ViewModels[i].ClickMe, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.ViewModels[i].ClickMe, "", new { @class = "text-danger" })
}

标记:

 

因此,只有当模型是对象列表时,似乎for属性才为空。

这是一个已知的问题? 或者也许我错过了什么?

此行为是框架符合HTML-4规范的结果。 在HTML-4中

ID和NAME令牌必须以字母([A-Za-z])开头,后面可以跟任意数量的字母,数字([0-9]),连字符(“ – ”),下划线(“_”) ,冒号(“:”)和句号(“。”)。

当您的模型是一个集合并使用@Html.EditorFor(m => m[i].SomeProperty)生成表单控件时,该方法会根据属性的名称生成nameid属性。 在这种情况下,集合中第一个项的name属性将是

 name="[0].SomeProperty" 

但为了避免与jQuery选择器的冲突,该方法取代了.[]带有下划线的字符_在生成将导致的id属性时

 id="_0__SomeProperty" 

但是因为根据HTML-4规范这是无效的,助手不会在html中输出它。

使用@Html.LabelFor()时同样适用(因为关联的表单控件不具有id属性,所以html中不输出for属性的值。

请注意,在HTML-5中, id属性是有效的,因此希望将来可以删除此行为。

您的第二个示例有效,因为id="ViewModels_0__ClickMe ”以字母开头,因此有效。

附注:例如,您可以通过生成自己的id属性来解决第一个问题

 @Html.LabelFor(model => model[i].ClickMe, new { for = string.Format("item{0}", i) }) @Html.EditorFor(model => model.ViewModels[i].ClickMe, new { htmlAttributes = new { @class = "form-control", id = string.Format("item{0}", i) } }) 

@model声明将模型对象分配给Model变量(注意captial’M’)。 但是你正在阅读尚未分配的model

试试这个:

  @model List // form code removed for brevity @for (var i = 0; i < Model.Count; i++) { 
@Html.LabelFor(model => Model[i].ClickMe)
@Html.EditorFor(model => Model[i].ClickMe, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => Model[i].ClickMe, "", new { @class = "text-danger" })
}

这并不能解释为什么你的第二个例子可以工作,但是,嘿,试一试。