使用以下代码时,字段的id和标签的for属性中的id不相同。
<%: Html.LabelFor(x => x.Localizations["en"]) %> => Localizations[en]
<%: Html.TextBoxFor(x=> x.Localizations["en"]) %> => Localizations_en_
<%: Html.LabelFor(x => x.Localizations["en"].Property) %>
=> Localizations[en]_Property
<%: Html.TextBoxFor(x=> x.Localizations["en"].Property) %>
=> Localizations_en__Property
我在反射器中跟踪代码,发现生成值的方式不同。不使用相同的辅助方法。
LabelFor使用HtmlHelper.GenerateIdFromName
,TextBoxFor使用TagBuilder#GenerateId
。
有没有人知道这个的原因,或者解决方法(除了编写你自己的整套输入/ textarea / select助手)?或者这是一个错误?
更新
因为我总是使用标签文本的第二个参数为标签使用html帮助器,所以我修改它以使用与表单字段助手相同的id生成代码。
public static MvcHtmlString LabelFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression, string labelText)
{
// The main part of this code is taken from the internal code for Html.LabelFor<TModel, TValue>(...).
var metaData = ModelMetadata.FromLambdaExpression(expression, helper.ViewData);
var fieldName = ExpressionHelper.GetExpressionText(expression);
TagBuilder builder = new TagBuilder("label");
// Generate the id as for the form fields (adds it to self).
builder.GenerateId(fieldName);
// Use the generated id for the 'for' attribute.
builder.Attributes.Add("for", builder.Attributes["id"]);
// Remove the id again.
builder.Attributes.Remove("id");
builder.SetInnerText(labelText);
return MvcHtmlString.Create(builder.ToString());
}
这解决了我的直接问题,但它没有回答为什么实现看起来像在MVC2中那样的问题。如果有理由的话。
顺便说一句:没有必要在HTML5中实际修改id / for属性,因为如果你愿意,让id看起来像^~[]
是完全合法的。所有主流浏览器都支持它。 Mathias Bynens很好地解释了这一点。
更新2:
这实际上并没有解决问题,因为DefaultModelBinder无论如何都无法绑定它。 MVC 2中的字段名称生成器似乎不支持在字典中使用嵌套对象,因为它生成:
<input type="text" name="Dict[en]" value="(VALUE)">
而不是模型装订器想要的东西:
<input type="hidden" name="Dict[0].Key" value="en">
<input type="text" name="Dict[0].Value" value="(VALUE)">
奇怪的是它以这种方式开箱即用。
我已经尝试为它创建一个自定义模型绑定器,但无论我尝试使用它,我都无法使用它:
ModelBinders.Binders.Add(typeof(IDictionary<string,object>), new DictionaryModelBinder());
ModelBinders.Binders.Add(typeof(IDictionary<string,string>), new DictionaryModelBinder());
ModelBinders.Binders.Add(typeof(IDictionary), new DictionaryModelBinder());
ModelBinders.Binders.Add(typeof(Dictionary), new DictionaryModelBinder());
现在看起来它似乎又回到了手动创建隐藏.Key
字段的名称属性值。
答案 0 :(得分:3)
这是我们计划修复下一版本(MVC 3 RTM)的MVC3中的错误。 LabelFor将通过tagbuilder使用与生成id相同的逻辑生成'for'属性,以便它们排列为数组和嵌套类型。
我们目前正在使用html 4.01规范生成ID,因此您无法使用以非字母开头的ID。我们将考虑标准发生变化时应采取的最佳方法。
答案 1 :(得分:1)
MVC intentionally mungs id
s with special characters which are significant in jQuery/CSS3 selectors。这是因为当ID中存在“保留”(通过jQuery / CSS3)字符时,选择器语法变得复杂。
它不使用name
执行此操作,因为在那里没有必要并妨碍绑定。
如果LabelFor
实际上没有指向相应的TextBoxFor
,那肯定是个错误。但我认为这个错误发生在LabelFor
,而不是TextBoxFor
。