如何显示 DisplayAttribute.Description 属性值

本文关键字:DisplayAttribute Description 属性 显示 何显示 | 更新日期: 2023-09-27 18:01:01

我有一个模型类,具有这样的属性:

[Display(Name = "Phone", Description="Hello World!")]
public string Phone1 { get; set; }

在我的视图中显示标签并呈现文本框以供输入非常简单:

@Html.LabelFor(model => model.Organization.Phone1)
@Html.EditorFor(model => model.Organization.Phone1)
@Html.ValidationMessageFor(model => model.Organization.Phone1)

但是如何呈现描述注释属性的值,即"Hello World!"??

如何显示 DisplayAttribute.Description 属性值

我最终得到了一个这样的助手:

using System;
using System.Linq.Expressions;
using System.Web.Mvc;
public static class MvcHtmlHelpers
{
    public static MvcHtmlString DescriptionFor<TModel, TValue>(this HtmlHelper<TModel> self, Expression<Func<TModel, TValue>> expression)
    {
        var metadata = ModelMetadata.FromLambdaExpression(expression, self.ViewData);
        var description = metadata.Description;
        return MvcHtmlString.Create(string.Format(@"<span>{0}</span>", description));
    }
}

感谢那些带领我走向正确方向的人。 :)

使用本文中有关如何显示表单中字段的视觉提示的技术,可以通过以下方法访问该值:

@Html.TextBoxFor( 
        model => model.Email , 
        new { title = ModelMetadata.FromLambdaExpression<RegisterModel , string>( 
            model => model.Email , ViewData ).Description } )  

在 ASP.NET MVC Core中,您可以使用新的标记帮助程序,这使您的HTML看起来像...网页:)

喜欢这个:

<div class="form-group row">
    <label asp-for="Name" class="col-md-2 form-control-label"></label>
    <div class="col-md-10">
        <input asp-for="Name" class="form-control" aria-describedby="Name-description" />
        <span asp-description-for="Name" class="form-text text-muted" />
        <span asp-validation-for="Name" class="text-danger" />
    </div>
</div>

注意 1:您可以在输入元素中使用 aria-describedby 属性,因为该 id 将在具有 asp-description-for 属性的 span 元素中自动创建。

注意 2:在 Bootstrap 4 中,类form-texttext-muted替换块级帮助文本的 v3 help-block 类。

要实现这种魔术,您只需创建一个新的标记帮助程序:

using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
/// <summary>
/// <see cref="ITagHelper"/> implementation targeting &lt;span&gt; elements with an <c>asp-description-for</c> attribute.
/// Adds an <c>id</c> attribute and sets the content of the &lt;span&gt; with the Description property from the model data annotation DisplayAttribute.
/// </summary>
[HtmlTargetElement("span", Attributes = DescriptionForAttributeName)]
public class SpanDescriptionTagHelper : TagHelper
{
    private const string DescriptionForAttributeName = "asp-description-for";
    /// <summary>
    /// Creates a new <see cref="SpanDescriptionTagHelper"/>.
    /// </summary>
    /// <param name="generator">The <see cref="IHtmlGenerator"/>.</param>
    public SpanDescriptionTagHelper(IHtmlGenerator generator)
    {
        Generator = generator;
    }
    /// <inheritdoc />
    public override int Order
    {
        get
        {
            return -1000;
        }
    }
    [HtmlAttributeNotBound]
    [ViewContext]
    public ViewContext ViewContext { get; set; }
    protected IHtmlGenerator Generator { get; }
    /// <summary>
    /// An expression to be evaluated against the current model.
    /// </summary>
    [HtmlAttributeName(DescriptionForAttributeName)]
    public ModelExpression DescriptionFor { get; set; }
    /// <inheritdoc />
    /// <remarks>Does nothing if <see cref="DescriptionFor"/> is <c>null</c>.</remarks>
    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }
        if (output == null)
        {
            throw new ArgumentNullException(nameof(output));
        }
        var metadata = DescriptionFor.Metadata;
        if (metadata == null)
        {
            throw new InvalidOperationException(string.Format("No provided metadata ({0})", DescriptionForAttributeName));
        }
        output.Attributes.SetAttribute("id", metadata.PropertyName + "-description");
        if( !string.IsNullOrWhiteSpace( metadata.Description))
        {
            output.Content.SetContent(metadata.Description);
            output.TagMode = TagMode.StartTagAndEndTag;
        }
    }
}

并使您的标签帮助程序可用于我们所有的 Razor 视图。将 addTagHelper 指令添加到Views/_ViewImports.cshtml文件:

@addTagHelper "*, YourAssemblyName"

注意 1:将YourAssemblyName替换为项目的程序集名称。

注意2:您只需要为所有标记助手执行此操作一次!

有关标记帮助程序的详细信息,请参阅此处:https://docs.asp.net/en/latest/mvc/views/tag-helpers/intro.html

就是这样!与新的标签助手一起玩得开心!

我正要使用接受的答案,但它不适用于 ASP.NET Core 1/2(又名 MVC 6(,ModelMetadata.FromLambdaExpression因为它不再存在并且已移至ExpressionMetadataProvider(用法也略有改变(。

这是可用于 ASP.NET Core 1.1和2的更新扩展方法:

using System;
using System.Linq.Expressions;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal;
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)}");
        return new HtmlString(modelExplorer.Metadata.Description);
    }
}

ASP.NET 核心 1

对于 ASP.NET Core 1,相同的代码有效,但您需要不同的命名空间usings

using System;
using System.Linq.Expressions;
using Microsoft.AspNet.Html.Abstractions;
using Microsoft.AspNet.Mvc.ViewFeatures;

用法

@Html.DescriptionFor(model => model.Phone1)

如果有人想知道如何使用接受的答案

1-在解决方案资源管理器中,>添加新文件夹>将其命名为"帮助程序",例如
2-添加一个新类,将其命名为"CustomHtmlHelpers",例如
3-粘贴代码:

public static class MvcHtmlHelpers
{
    public static string DescriptionFor<TModel, TValue>(this HtmlHelper<TModel> self, Expression<Func<TModel, TValue>> expression)
    {
        var metadata = ModelMetadata.FromLambdaExpression(expression, self.ViewData);
        var description = metadata.Description;
        return string.IsNullOrWhiteSpace(description) ? "" : description;
    }
}

4-在您的模型或视图中使用它的模型:

[Display(Name = "User Name", Description = "Enter your User Name")]
public string FullName { get; set; }

5-在Razor视图中,在@model之后,键入此行

@using YOUR_PROJECT.Helpers 

6-显示如下描述:

@Html.DescriptionFor(m => m.FullName) 

7-您可能希望使用描述在输入占位符中显示文本:

@Html.DisplayNameFor(m => m.FullName)
@Html.TextBoxFor(m => m.FullName, new { @class = "form-control", placeholder = Html.DescriptionFor(m => m.FullName) })

谢谢

var attrib = (DisplayAttribute)Attribute.GetCustomAttribute(
             member, typeof(DisplayAttribute));
var desc = attrib == null ? "" : attrib.GetDescription()

以下是 ASP.NET Core 3.1和5的更新版本:

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 expressionProvider = html.ViewContext?.HttpContext?.RequestServices?.GetService<ModelExpressionProvider>()
            ?? new ModelExpressionProvider(html.MetadataProvider);
        var modelExpression = expressionProvider.CreateModelExpression(html.ViewData, expression);
        return new HtmlString(modelExpression.Metadata.Description);
    }
}

我们必须通过ModelExpressionProvider,因为ExpressionMetadataProvider被标记为内部。

无论如何,ModelExpressionProvider.CreateModelExpression()内部调用ExpressionMetadataProvider.FromLambdaExpression()

https://github.com/aspnet/Mvc/blob/04ce6cae44fb0cb11470c21769d41e3f8088e8aa/src/Microsoft.AspNetCore.Mvc.ViewFeatures/ModelExpressionProvider.cs#L42

@ViewData.ModelMetadata.Properties
   .Where(m => m.PropertyName == "Phone1").FirstOrDefault().Description

所以,如果你使用的是引导程序,比如

<div class="form-group col-sm-6">
   @Html.LabelFor(m => m.Organization.Phone1)
   @Html.EditorFor(m => m.Organization.Phone1)
   <p class="help-block">
      @ViewData.ModelMetadata.Properties
         .Where(m => m.PropertyName == "DayCount").FirstOrDefault().Description
   </p>
</div>

您必须编写一个自定义帮助程序来反映您的模型,以提供 Description 属性值。

...如果您希望将描述作为表单标签中的工具提示,请添加如下所示的标记帮助程序:

using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
/// <summary>
/// <see cref="ITagHelper"/> implementation targeting &lt;label&gt; elements with an <c>asp-for</c> attribute.
/// Adds a <c>title</c> attribute to the &lt;label&gt; with the Description property from the model data annotation DisplayAttribute.
/// </summary>
[HtmlTargetElement("label", Attributes = ForAttributeName)]
public class LabelTitleTagHelper : TagHelper
{
    private const string ForAttributeName = "asp-for";
    /// <summary>
    /// Creates a new <see cref="LabelTitleTagHelper"/>.
    /// </summary>
    /// <param name="generator">The <see cref="IHtmlGenerator"/>.</param>
    public LabelTitleTagHelper(IHtmlGenerator generator)
    {
        Generator = generator;
    }
    /// <inheritdoc />
    public override int Order
    {
        get
        {
            return -1000;
        }
    }
    [HtmlAttributeNotBound]
    [ViewContext]
    public ViewContext ViewContext { get; set; }
    protected IHtmlGenerator Generator { get; }
    /// <summary>
    /// An expression to be evaluated against the current model.
    /// </summary>
    [HtmlAttributeName(ForAttributeName)]
    public ModelExpression TitleFor { get; set; }
    /// <inheritdoc />
    /// <remarks>Does nothing if <see cref="TitleFor"/> is <c>null</c>.</remarks>
    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }
        if (output == null)
        {
            throw new ArgumentNullException(nameof(output));
        }
        var metadata = TitleFor.Metadata;
        if (metadata == null)
        {
            throw new InvalidOperationException(string.Format("No provided metadata ({0})", ForAttributeName));
        }
        if (!string.IsNullOrWhiteSpace(metadata.Description))
            output.Attributes.SetAttribute("title", metadata.Description);
    }
}

这将创建一个新的title属性,其中包含模型的数据注释DisplayAttribute中的 Description 属性。

美丽的部分是您无需触摸生成的脚手架视图!因为此标记帮助程序的目标是已经存在的label元素的asp-for属性!

除了Jakob Gade'一个很好的答案:

如果您需要 支持DescriptionAttribute而不是DisplayAttribute ,如果我们覆盖元数据提供程序,他的出色解决方案仍然有效:

public class ExtendedModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
    protected override ModelMetadata CreateMetadata(IEnumerable<System.Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
    {
        //Possible Multiple Enumerations on IEnumerable fix
        var attributeList = attributes as IList<System.Attribute> ?? attributes.ToList();
        //Default behavior
        var data = base.CreateMetadata(attributeList, containerType, modelAccessor, modelType, propertyName);
        //Bind DescriptionAttribute
        var description = attributeList.SingleOrDefault(a => typeof(DescriptionAttribute) == a.GetType());
        if (description != null)
        {
            data.Description = ((DescriptionAttribute)description).Description;
        }
        return data;
    }
}

这需要在Global.asax.csApplication_Start方法中寄存器:

ModelMetadataProviders.Current = new ExtendedModelMetadataProvider();

HANDL的答案,针对 ASP.NET 核心2.0进行了更新

using System;
using System.Linq.Expressions;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal;
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)}");
        return new HtmlString(modelExplorer.Metadata.Description);
    }
}

您始终可以像这样创建自己的自定义扩展:

    public static MvcHtmlString ToolTipLabel (string resourceKey, string text, bool isRequired, string labelFor = "", string labelId = "",string className="")
    {
        string tooltip = string.Empty;
        StringBuilder sb = new StringBuilder();
        if (!string.IsNullOrEmpty(resourceKey))
        {
            var resources = GetAllResourceValues();
            if (resources.ContainsKey(resourceKey))
            {
                tooltip = resources[resourceKey].Value;
            }
        }
        sb.Append("<label");
        if (!string.IsNullOrEmpty(labelFor))
        {
            sb.AppendFormat(" for='"{0}'"", labelFor);
        }
        if (!string.IsNullOrEmpty(labelId))
        {
            sb.AppendFormat(" Id='"{0}'"", labelId);
        }
        if (!string.IsNullOrEmpty(className))
        {
            sb.AppendFormat(" class='"{0}'"", className);
        }
        if (!string.IsNullOrEmpty(tooltip))
        {
            sb.AppendFormat(" data-toggle='tooltip' data-placement='auto left' title='"{0}'"",tooltip);
        }
        if (isRequired)
        {
            sb.AppendFormat("><em class='required'>*</em> {0} </label></br>", text);
        }
        else
        {
            sb.AppendFormat(">{0}</label></br>", text);
        }
        return MvcHtmlString.Create(sb.ToString());
    }

并且可以像这样查看它:

@HtmlExtension.ToolTipLabel(" "," ",true," "," "," ")
相关文章:
  • 没有找到相关文章