c# - ASP.NET 核心 : ShortName in the Display attribute (DataAnnotations)

标签 c# asp.net-core data-annotations html-helper asp.net-core-1.1

在 ASP .NET Core 1.1 项目(VS 2017)中,我尝试使用 Display 属性的 ShortName 属性,以便使用 DisplayFor HTML Helper:

[Display(Name="Project Name", ShortName="Name", Description="The name of the project")]
public string Name { get; set; }

我读了the following answer这对 Description 起到了作用。不幸的是,由于我不明白的原因,这对 ShortName 不起作用。

有我试过的代码,第一种方法似乎可以,但第二种方法编译不通过,所以我想修复它:

using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal;
using System;
using System.Linq;
using System.ComponentModel.DataAnnotations;
using System.Linq.Expressions;
using System.Reflection;

namespace MyProject.Helpers
{
    public static class HtmlExtensions
    {
        public static IHtmlContent DescriptionFor<TModel, TValue>(this IHtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
        {
            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)}");
            //////// Description is OK 
            return new HtmlString(modelExplorer.Metadata.Description);
        }

        public static IHtmlContent ShortNameFor<TModel, TValue>(this IHtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
        {
            if (html == null) throw new ArgumentNullException(nameof(html));
            if (expression == null) throw new ArgumentNullException(nameof(expression));

            var modelExplorer = ExpressionMetadataProvider.FromLambdaExpression(expression, html., html.MetadataProvider);
            if (modelExplorer == null) throw new InvalidOperationException($"Failed to get model explorer for {ExpressionHelper.GetExpressionText(expression)}");
            //////// ShortName DOES NOT EXIST !!!!!!!!!!!!!!!!
            return new HtmlString(modelExplorer.Metadata.ShortName);
        }
    }
}

不仅如此,回顾 MS code of the DisplayNameFor

方法的签名应该像这样改变:

public static string DisplayShortNameFor<TModelItem, TResult>(
    this IHtmlHelper<IEnumerable<TModelItem>> htmlHelper,
    Expression<Func<TModelItem, TResult>> expression)    

不是

public static IHtmlContent ShortNameFor<TModel, TValue>(
    this IHtmlHelper<TModel> html, 
    Expression<Func<TModel, TValue>> expression)

更新

对于我试过的旧签名

public static string DisplayShortNameFor<TModel, TValue>(this IHtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
{
    string shortNameValue = string.Empty;
    var prop = expression.Body as MemberExpression;
    if (prop != null)
    {
        var DisplayAttrib = prop.Member.GetCustomAttributes<DisplayAttribute>(false).FirstOrDefault();
        if (DisplayAttrib != null)
            shortNameValue = DisplayAttrib.ShortName;
    }
    return shortNameValue;
}

但实际上我无法运行它,因为它没有在 View 中编译,因为它是一个 IEnumerable

@using MyProject.Helpers
@model IEnumerable<MyProject.Models.Record> <!--<<< IEnumerable to display a collection -->

@Html.DisplayShortNameFor(model => model.Name)

所以我需要做

// for my method shortname I need to use FirstOfDefault...
@Html.DisplayShortNameFor(model => model.FirstOrDefault().Name)

// but for ASP.NET DisplayName works
@Html.DisplayNameFor(model => model.Date)

最佳答案

要使用此方法获取 ShortName 属性,您需要手动提取 Display 属性,因为它不是默认元数据的一部分。例如,像这样的东西会起作用:

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;
    }
}
return m.DisplayName;

为了将其插入到您的助手中,我会稍微抽象出该方法,因为其中有一些重复的代码,因此您最终会得到这样的私有(private)方法:

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)方法是这样的:

public static IHtmlContent DescriptionFor<TModel, TValue>(this IHtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
{
    return html.MetaDataFor(expression, m => m.Description);
}

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;
            }
        }
        //Return a default value if the property doesn't have a DisplayAttribute
        return m.DisplayName;
    });
}

关于c# - ASP.NET 核心 : ShortName in the Display attribute (DataAnnotations),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45234670/

相关文章:

c# - 确定 Object 的实例是否在 WCF 中是 DataContract 可序列化的

c# - 如果形状的高度大于表单的高度,则显示滚动条

c# - 当数据过大时,发布请求不起作用 .net 核心 web api

asp.net-mvc-4 - 无法让 MVC 4 FileExtensions 属性处理 ViewModel 属性

c# - EPPlus - 保存在内存中创建的 excel 并在 excel 上打开它会出错

C# 从数组集合中删除 "partial"重复项

git - 在 Bitbucket 管道中增加一个数字

asp.net-core - JWT token 未在远程服务器上验证,无法匹配 'kid' 错误

asp.net-mvc - ASP.NET MVC 4 导航虚拟属性未在后操作中填充

c# - Entity Framework - [无键] 数据注释丢失