LabelFor и TextBoxFor не генерируют одинаковые идентификаторы - PullRequest
5 голосов
/ 18 августа 2010

При использовании следующего кода идентификаторы поля и идентификатор в атрибуте for метки не идентичны.

<%: 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-помощник для метки со вторым параметром для текста метки, я изменил его, чтобы использовать тот же код генерации идентификатора, что и для помощников поля формы.

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. Если есть причина для этого.

Между прочим: нет необходимости фактически изменять атрибут id / for в HTML5, так как совершенно естественно иметь идентификатор, похожий на ^~[], если хотите. Все основные браузеры поддерживают это. Это хорошо объясняется Матиасом Биненсом .

ОБНОВЛЕНИЕ 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 полями.

Ответы [ 2 ]

3 голосов
/ 11 ноября 2010

Это ошибка в MVC3, которую мы планируем исправить в следующем выпуске (MVC 3 RTM). LabelFor пройдет через tagbuilder, чтобы сгенерировать атрибут for, используя ту же логику, которая используется для генерации идентификаторов, чтобы они выстраивались в ряды для массивов и вложенных типов.

В настоящее время мы используем спецификацию html 4.01 для генерации идентификаторов, поэтому вы не можете использовать идентификаторы, начинающиеся с букв. Мы подумаем о том, каким должен быть лучший подход сейчас, когда стандарты изменились.

1 голос
/ 18 августа 2010

MVC намеренно создает id s со специальными символами, которые имеют значение в селекторах jQuery / CSS3 .Это связано с тем, что синтаксис селектора усложняется, когда в идентификаторе присутствуют «зарезервированные» (посредством jQuery / CSS3) символы.

Это не делает это с name, потому что там это не нужно и мешает связыванию.

Это, безусловно, ошибка, если LabelForна самом деле не указывает на соответствующий TextBoxFor.Но я бы сказал, что ошибка в LabelFor, а не в TextBoxFor.

...