【问题标题】:ASP .Net Core 3.0 ShortName in the Display Attribute (DataAnnotations)显示属性中的 ASP .Net Core 3.0 ShortName (DataAnnotations)
【发布时间】:2020-03-18 21:05:04
【问题描述】:

这个问题在过去被问过,这里的答案https://stackoverflow.com/a/45236544/3074765 对我来说是一个救命稻草。问题是当我迁移到 .Net Core 3.0 时,它坏了。原因可以在这里找到https://github.com/aspnet/AspNetCore/issues/8678。简而言之,微软公开了一些被标记为内部类的函数。修复此删除对 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。

【问题讨论】:

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


    【解决方案1】:

    在 .Net Core 3.0 中,Microsoft 提供了一种使用 Dependecy Injection 和名为 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 以检索他们需要的内容,其他两个扩展函数将正常工作。

    干杯!

    【讨论】:

    • 如何从 Razor ASP.NET Core 3 中的 Edit.cshtml 文件中调用 MetaDataFor 函数来获取“ShortName”的属性值?
    • 我通常在 Index.cshtml 中使用它,但我很确定它应该在 Edit.cshtml 中工作。我使用的语法是 @Html.ShortNameFor(model => model.MyDataModel[0].MyField) 。请记住,这是一个列标题。您应该可以在任何使用 DisplayNameFor 的地方使用它。
    • 这给了我错误 IHtmlHelper does not contain a definition for ShortNameFor .....
    • @AshMachine 我在命名空间中使用了一个名为 Extensions 的类来创建我的扩展方法。在我的 .cshtml 顶部,我需要有“@using Extensions”。你需要为你的扩展方法添加一个 using。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-21
    相关资源
    最近更新 更多