ASP .Net Core 3.0 显示属性中的 ShortName (DataAnnotations)
ASP .Net Core 3.0 ShortName in the Display Attribute (DataAnnotations)
这个问题过去曾被问过,答案在这里 has been a life saver for me. The problem is that when I migrated to .Net Core 3.0, it broke. The reason can be found here https://github.com/aspnet/AspNetCore/issues/8678。简而言之,Microsoft 在标记为内部的 class 中创建了一些函数 public。解决此问题会删除对 ExpressionMetadataProvider 的访问权限。考虑以下 HTML Helper
using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal;
public static class MvcHtmlHelpers
{
private static IHtmlContent MetaDataFor<TModel, TValue>(this IHtmlHelper<TModel> html,
Expression<Func<TModel, TValue>> expression,
Func<ModelMetadata, string> property)
{
if (html == null) throw new ArgumentNullException(nameof(html));
if (expression == null) throw new ArgumentNullException(nameof(expression));
var modelExplorer = ExpressionMetadataProvider.FromLambdaExpression(expression, html.ViewData, html.MetadataProvider);
if (modelExplorer == null) throw new InvalidOperationException($"Failed to get model explorer for {ExpressionHelper.GetExpressionText(expression)}");
return new HtmlString(property(modelExplorer.Metadata));
}
public static IHtmlContent DescriptionFor<TModel, TValue>(this IHtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
{
return html.MetaDataFor(expression, m => m.Description ?? m.Name);
}
public static IHtmlContent ShortNameFor<TModel, TValue>(this IHtmlHelper<TModel> html,
Expression<Func<TModel, TValue>> expression)
{
return html.MetaDataFor(expression, m =>
{
var defaultMetadata = m as
Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.DefaultModelMetadata;
if (defaultMetadata != null)
{
var displayAttribute = defaultMetadata.Attributes.Attributes
.OfType<DisplayAttribute>()
.FirstOrDefault();
if (displayAttribute != null)
{
return displayAttribute.ShortName ?? m.DisplayName ?? m.Name;
}
}
//Return a default value if the property doesn't have a DisplayAttribute
return m.DisplayName ?? m.Name;
});
}
}
当您按照步骤迁移到.Net Core 3.0时,无法再解析ExpressionMetadataProvider和ExpressionHelper。
在 .Net Core 3.0 中,Microsoft 提供了一种使用依赖注入和名为 ModelExpressionProvider 的服务获取相同元数据的方法。您可以通过 IHtmlHelper 中的 HttpContext 访问该服务。只需将 using 替换为:
using Microsoft.AspNetCore.Mvc.ViewFeatures;
删除 .Internal,并将 MetaDataFor 函数替换为:
private static IHtmlContent MetaDataFor<TModel, TValue>(this IHtmlHelper<TModel> html,
Expression<Func<TModel, TValue>> expression,
Func<ModelMetadata, string> property)
{
if (html == null) throw new ArgumentNullException(nameof(html));
if (expression == null) throw new ArgumentNullException(nameof(expression));
ModelExpressionProvider modelExpressionProvider = (ModelExpressionProvider)html.ViewContext.HttpContext.RequestServices.GetService(typeof(IModelExpressionProvider));
var modelExplorer = modelExpressionProvider.CreateModelExpression(html.ViewData, expression);
if (modelExplorer == null) throw new InvalidOperationException($"Failed to get model explorer for {modelExpressionProvider.GetExpressionText(expression)}");
return new HtmlString(property(modelExplorer.Metadata));
}
一旦 MetaDataFor 被修复以检索它们需要的内容,其他两个扩展函数将正常工作。
干杯!
这个问题过去曾被问过,答案在这里
using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal;
public static class MvcHtmlHelpers
{
private static IHtmlContent MetaDataFor<TModel, TValue>(this IHtmlHelper<TModel> html,
Expression<Func<TModel, TValue>> expression,
Func<ModelMetadata, string> property)
{
if (html == null) throw new ArgumentNullException(nameof(html));
if (expression == null) throw new ArgumentNullException(nameof(expression));
var modelExplorer = ExpressionMetadataProvider.FromLambdaExpression(expression, html.ViewData, html.MetadataProvider);
if (modelExplorer == null) throw new InvalidOperationException($"Failed to get model explorer for {ExpressionHelper.GetExpressionText(expression)}");
return new HtmlString(property(modelExplorer.Metadata));
}
public static IHtmlContent DescriptionFor<TModel, TValue>(this IHtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
{
return html.MetaDataFor(expression, m => m.Description ?? m.Name);
}
public static IHtmlContent ShortNameFor<TModel, TValue>(this IHtmlHelper<TModel> html,
Expression<Func<TModel, TValue>> expression)
{
return html.MetaDataFor(expression, m =>
{
var defaultMetadata = m as
Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.DefaultModelMetadata;
if (defaultMetadata != null)
{
var displayAttribute = defaultMetadata.Attributes.Attributes
.OfType<DisplayAttribute>()
.FirstOrDefault();
if (displayAttribute != null)
{
return displayAttribute.ShortName ?? m.DisplayName ?? m.Name;
}
}
//Return a default value if the property doesn't have a DisplayAttribute
return m.DisplayName ?? m.Name;
});
}
}
当您按照步骤迁移到.Net Core 3.0时,无法再解析ExpressionMetadataProvider和ExpressionHelper。
在 .Net Core 3.0 中,Microsoft 提供了一种使用依赖注入和名为 ModelExpressionProvider 的服务获取相同元数据的方法。您可以通过 IHtmlHelper 中的 HttpContext 访问该服务。只需将 using 替换为:
using Microsoft.AspNetCore.Mvc.ViewFeatures;
删除 .Internal,并将 MetaDataFor 函数替换为:
private static IHtmlContent MetaDataFor<TModel, TValue>(this IHtmlHelper<TModel> html,
Expression<Func<TModel, TValue>> expression,
Func<ModelMetadata, string> property)
{
if (html == null) throw new ArgumentNullException(nameof(html));
if (expression == null) throw new ArgumentNullException(nameof(expression));
ModelExpressionProvider modelExpressionProvider = (ModelExpressionProvider)html.ViewContext.HttpContext.RequestServices.GetService(typeof(IModelExpressionProvider));
var modelExplorer = modelExpressionProvider.CreateModelExpression(html.ViewData, expression);
if (modelExplorer == null) throw new InvalidOperationException($"Failed to get model explorer for {modelExpressionProvider.GetExpressionText(expression)}");
return new HtmlString(property(modelExplorer.Metadata));
}
一旦 MetaDataFor 被修复以检索它们需要的内容,其他两个扩展函数将正常工作。
干杯!