ASP.NET MVC HtmlFieldPrefix缺少索引器的属性

时间:2019-06-13 21:21:52

标签: asp.net-mvc asp.net-mvc-5 html-helper unobtrusive-validation .net-4.6.2

借助其他一些StackOverflow问题,我编写了HTML Helper来获取属性的不干扰验证属性:

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属性段或索引器。

I.E。 html.ViewData.TemplateInfo.HtmlFieldPrefix + "." + metaData.PropertyName!= propertyName

为什么HtmlFieldPrefix不包含完整前缀,什么是解决此问题的好方法?


编辑

我查看了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"吗?

0 个答案:

没有答案