ASP .Net Core 3.0 ShortName in the Display Attribute (DataAnnotations)

霸气de小男生 提交于 2020-05-15 11:50:07

问题


This question was asked in the past and the answer here https://stackoverflow.com/a/45236544/3074765 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 . In a nutshell, Microsoft had made some functions public that were in a class that was labeled internal. Fixing this removed access to ExpressionMetadataProvider. Consider the following 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;
        });
    }
}

When you follow the steps to migrate to .Net Core 3.0, ExpressionMetadataProvider and ExpressionHelper can no longer be resolved.


回答1:


In .Net Core 3.0, Microsoft provided a way to get to the same MetaData using Dependecy Injection and a service called ModelExpressionProvider. You can get access to the service via the HttpContext found in the IHtmlHelper. Just replace the using to be:

using Microsoft.AspNetCore.Mvc.ViewFeatures;

Which removes the .Internal, and replace the MetaDataFor function with:

    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));
    }

The other two extension functions will work fine once MetaDataFor is fixed to retrieve what they need.

Cheers!



来源:https://stackoverflow.com/questions/59000215/asp-net-core-3-0-shortname-in-the-display-attribute-dataannotations

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!