ASP.NET核心:Display属性中的ShortName(DataAnnotations)
ASP.NET Core: ShortName in the Display attribute (DataAnnotations)
在 ASP .NET Core 1.1 项目(VS 2017)中,我尝试使用 Display
[的 ShortName
属性 属性 为了使用 DisplayFor
HTML 助手:
[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;
}
但实际上我不能 运行 因为不在视图中编译,因为是一个 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 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;
});
}
在 ASP .NET Core 1.1 项目(VS 2017)中,我尝试使用 Display
[的 ShortName
属性 属性 为了使用 DisplayFor
HTML 助手:
[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;
}
但实际上我不能 运行 因为不在视图中编译,因为是一个 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 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;
});
}