При использовании следующего кода идентификаторы поля и идентификатор в атрибуте 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 / выберите помощников)? Или это ошибка?
ОБНОВЛЕНИЕ:
Так как я в любом случае использую помощник html для метки со вторым параметром для текста метки, я изменил его, чтобы использовать тот же код генерации идентификатора, что и для помощников поля формы.
public static MvcHtmlString LabelFor(this HtmlHelper helper, Expression> expression, string labelText)
{
// The main part of this code is taken from the internal code for Html.LabelFor(...).
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());
}
Это решает мою непосредственную проблему, но не t ответить на вопрос, почему реализация выглядит так, как в MVC2. Если есть причина для этого.
Между прочим: нет необходимости фактически изменять атрибут id / for в HTML5, поскольку совершенно законно иметь идентификатор, похожий на ^ ~ []
, если вы хотел бы. Все основные браузеры поддерживают это. Это хорошо объясняется Матиасом Биненсом .
ОБНОВЛЕНИЕ 2:
На самом деле это вообще не решает проблему, поскольку DefaultModelBinder никак не может с ней связаться. Использование вложенных объектов в словарях, по-видимому, не поддерживается генератором имен полей в MVC 2, поскольку он генерирует:
Вместо того, что хочет связыватель модели:
Странно, что он выходит из коробки таким образом.
Я пытался создать для нее специальное связующее, но я могу MVC2 не может использовать его там, где я пытаюсь его использовать:
ModelBinders.Binders.Add(typeof(IDictionary), new DictionaryModelBinder());
ModelBinders.Binders.Add(typeof(IDictionary), new DictionaryModelBinder());
ModelBinders.Binders.Add(typeof(IDictionary), new DictionaryModelBinder());
ModelBinders.Binders.Add(typeof(Dictionary), new DictionaryModelBinder());
Итак, сейчас похоже, что он вернулся к ручному созданию значений атрибута name со скрытыми полями .Key
.