С помощью некоторых других вопросов StackOverflow я написал помощник HTML, чтобы получить ненавязчивые атрибуты проверки для свойства:
public static IHtmlString GetUnobtrusiveValidationAttributesFor<TModel, TProperty>(this HtmlHelper<TModel> html, Expression<Func<TModel, TProperty>> propertySelector)
{
string propertyName = html.NameFor(propertySelector).ToString();
ModelMetadata metaData = ModelMetadata.FromLambdaExpression(propertySelector, html.ViewData);
//If the attributes were already generated, remove this flag so they can be generated again. Otherwise GetUnobtrusiveValidationAttributes returns empty
html.ViewContext.FormContext.RenderedField(propertyName, false);
var attributeCollection = html.GetUnobtrusiveValidationAttributes(metaData.PropertyName, metaData);
return html.Raw(String.Join(" ", attributeCollection.Select(kvp => kvp.Key + "=\"" + kvp.Value.ToString() + "\"")));
}
Казалось, работает правильно. Обратите внимание, что закомментированная строка, по-видимому, была необходима при создании атрибутов для одного и того же поля более одного раза. Это связано с тем, что после однократного вызова GetUnobtrusiveValidationAttributes
полное имя свойства добавляется в личный словарь HtmlHelper ViewContext.FormContext._renderedFields
со значением true
. Таким образом, моя закомментированная строка сначала устанавливает значение false
, а затем снова возвращает атрибуты.
Проблема в том, что это не работает для моего текущего использования, на мой взгляд, который находится в цикле. Я думаю, что это будет легче всего объяснить, указав имена свойств. Первый раз это называется propertyName
= "vm.CampPassPricePlans.CampPassPacks[0].SelectedCampPassExpirationRuleID"
. Итак, как вы можете видеть, свойство находится на первом элементе в свойстве CampPassPacks
, которое является List<t>
. В следующий раз, propertyName
= "vm.CampPassPricePlans.CampPassPacks[1].SelectedCampPassExpirationRuleID"
, но GetUnobtrusiveValidationAttributes
возвращает пустой результат, несмотря на то, что для этого свойства для RenderedFields
установлено значение false
.
Полагаю, проблема в том, что после того, как я в первый раз вызываю GetUnobtrusiveValidationAttributes
, он добавляет неправильное имя свойства во внутренний словарь _renderedFields
. Вместо добавления "vm.CampPassPricePlans.CampPassPacks[0].SelectedCampPassExpirationRuleID"
он имеет только "vm.CampPassPricePlans.SelectedCampPassExpirationRuleID"
. Таким образом, он конвертирует их всех в одно и то же имя. Я подозреваю, что это потому, что html.ViewData.TemplateInfo.HtmlFieldPrefix
равен только "vm.CampPassPricePlans"
- он не включает сегмент или индексатор свойства CampPassPacks
.
т.е. html.ViewData.TemplateInfo.HtmlFieldPrefix + "." + metaData.PropertyName
! = propertyName
.
Почему HtmlFieldPrefix
не включает полный префикс и как это можно решить?
EDIT
Я посмотрел на GetUnobtrusiveValidationAttributes
исходный код, и вот что он использует:
string fullName = html.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
где name
- имя свойства, которое я передал.
TL; DR
Почему:
html.NameFor(propertySelector).ToString();
возврат "vm.CampPassPricePlans.CampPassPacks[0].SelectedCampPassExpirationRuleID"
но
html.ViewData.TemplateInfo.GetFullHtmlFieldName("SelectedCampPassExpirationRuleID")
возврат "vm.CampPassPricePlans.SelectedCampPassExpirationRuleID"
?