显示属性中的ASP .Net Core 3.0简称(DataAnnotations)

时间:2019-11-22 18:59:48

标签: c# asp.net-mvc razor-pages asp.net-core-3.0 .net-core-3.0

这个问题过去曾被问过,这里的答案https://stackoverflow.com/a/45236544/3074765对我来说是个救命稻草。问题是,当我迁移到.Net Core 3.0时,它崩溃了。原因可以在https://github.com/aspnet/AspNetCore/issues/8678中找到。简而言之,Microsoft公开了某些功能,这些功能属于标为internal的类。解决此问题后,将删除对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。

1 个答案:

答案 0 :(得分:1)

在.Net Core 3.0中,Microsoft提供了一种使用Dependecy Injection和称为ModelExpressionProvider的服务来访问同一MetaData的方法。您可以通过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来检索所需内容后,其他两个扩展功能将正常工作。

干杯!