2010-08-18 59 views
5

使用以下代码时,字段的id和标签的for属性中的id不相同。LabelFor和TextBoxFor不生成相同的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助手)?或者它是一个错误?

UPDATE:

因为我无论如何使用标签中的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)"> 

奇怪的是,它这种方式从盒子里出来。

我试着为它创建一个自定义的模型绑定,但我不能让MVC2使用它无论我尝试使用它:

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

我注意到了。尽管我从不在重复结构中使用标签。我用一张桌子。 你试过在foreach循环中吗?这看起来如何? – Stefanvds 2010-08-18 08:53:00

+0

我实际上在foreach循环中使用它,这是一个简单的例子,带有明确的可读性键。 – 2010-08-18 08:56:36

回答

3

这是我们计划修复下一版本(MVC 3 RTM)的MVC3中的一个错误。 LabelFor将通过tagbuilder来使用用于生成ID的相同逻辑生成'for'属性,以便它们排列数组和嵌套类型。

我们目前使用html 4.01规范来生成id,因此您不能使用以非字母开头的id。我们会考虑现在标准已经改变的最好方法。

+0

很高兴发现这是在要解决的事情清单上。我花了半个小时在Google上搜索,没有取得很多成功。非常令人沮丧。 – 2010-11-23 17:00:49