【问题标题】:LabelFor and TextBoxFor don't generate the same id'sLabelFor 和 TextBoxFor 不会生成相同的 id
【发布时间】:2011-03-31 09:54:40
【问题描述】:

使用以下代码时,字段的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

有谁知道造成这种情况的原因或解决方法(除了编写自己的整套输入/文本区域/选择帮助程序)?还是bug?

更新:

因为无论如何我都为标签使用了一个 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 字段的名称属性值。

【问题讨论】:

  • 我也注意到了。虽然我从不在重复结构中使用标签。我用一张桌子。您是否在 foreach 循环中尝试过?看起来怎么样?
  • 我实际上确实在 foreach 循环中使用了它,这是一个简化的示例,带有显式键以提高可读性。

标签: asp.net-mvc asp.net-mvc-2 html-helper


【解决方案1】:

这是 MVC3 中的一个错误,我们计划在下一个版本 (MVC 3 RTM) 中修复它。 LabelFor 将通过 tagbuilder 使用与生成 id 相同的逻辑生成“for”属性,因此它们将为数组和嵌套类型排列。

我们目前正在使用 html 4.01 规范来生成 id,因此您不能使用以非字母开头的 id。既然标准已经改变,我们将考虑最好的方法应该是什么。

【讨论】:

  • 很高兴发现这是要修复的问题列表。我只是花了半个小时在谷歌上搜索,但没有取得很大的成功。非常令人沮丧。
【解决方案2】:

MVC intentionally mungs ids with special characters which are significant in jQuery/CSS3 selectors。这是因为当 ID 中有“保留”(通过 jQuery/CSS3)字符时,选择器语法变得复杂。

它确实name 执行此操作,因为它在那里没有必要并且会妨碍绑定。

如果LabelFor 实际上没有指向对应的TextBoxFor,那肯定是一个错误。但我认为这个错误存在于LabelFor,而不是TextBoxFor

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-03
    • 2019-04-24
    • 1970-01-01
    • 1970-01-01
    • 2012-05-01
    • 1970-01-01
    • 2013-01-09
    • 1970-01-01
    相关资源
    最近更新 更多