如何显示DisplayAttribute.Description属性值?

Jak*_*ade 69 c# asp.net asp.net-mvc

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

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

在我的视图中显示标签并渲染文本框以进行输入非常简单:

@Html.LabelFor(model => model.Organization.Phone1)
@Html.EditorFor(model => model.Organization.Phone1)
@Html.ValidationMessageFor(model => model.Organization.Phone1)
Run Code Online (Sandbox Code Playgroud)

但是如何渲染Description annotation属性的值,即"Hello World!"?

Jak*_*ade 82

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

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));
    }
}
Run Code Online (Sandbox Code Playgroud)

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

  • 为了消除额外的跨度,我将返回更改为`return string.IsNullOrWhiteSpace(description)?MvcHtmlString.Empty:MvcHtmlString.Create(string.Format(@"<span> {0} </ span>",description));` (4认同)
  • 从您的示例开始,我将其构建得更多,能够覆盖span标记,并可选择添加cssClass.https://gist.github.com/4469809 (4认同)
  • 我想知道为什么描述,就此而言,如果我们必须编写扩展来吐出它们,那么提示作为该属性的属性存在? (2认同)

Ada*_*SFT 40

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

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

  • 甚至可以更进一步,更新T4模板,以便使用此方法搭建新的CRUD视图 (4认同)

huy*_*itw 22

我正准备使用已接受的答案,但它不适用于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);
    }
}
Run Code Online (Sandbox Code Playgroud)

ASP.NET核心1

对于ASP.NET Core 1,相同的代码可以工作,但是您需要不同的命名空间usings:

using System;
using System.Linq.Expressions;
using Microsoft.AspNet.Html.Abstractions;
using Microsoft.AspNet.Mvc.ViewFeatures;
Run Code Online (Sandbox Code Playgroud)

用法

@Html.DescriptionFor(model => model.Phone1)
Run Code Online (Sandbox Code Playgroud)


Fil*_*iro 10

在ASP.NET MVC Core中,您可以使用新的Tag Helpers,这使您的HTML看起来像... 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>
Run Code Online (Sandbox Code Playgroud)

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

注2:在引导4类form-texttext-muted替换V3 help-block块级帮助文本类。

为了使这种魔术发生,您只需要创建一个新的Tag Helper:

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

@addTagHelper "*, YourAssemblyName"
Run Code Online (Sandbox Code Playgroud)

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

注意2:对于您的所有标记助手,您只需执行一次即可!

有关标签帮助程序的更多信息,请参见:https : //docs.asp.net/zh/latest/mvc/views/tag-helpers/intro.html

而已!享受新的Tag Helpers的乐趣!

  • 嗨,斯蒂芬!这就是为什么我从“ In ASP.NET MVC Core ...”开始。这个问题对于两个世界都是完全相同的,尽管这是一个古老的问题,但我相信像我一样,人们今天也在为这个问题而绊脚石!我今天早些时候一直在这里寻找答案,经过几个小时的研究,我决定分享我对梨的结论。希望有人觉得有用! (5认同)
  • 对我来说最好的解决方案。由于 HtmlHelpers 可能被认为是一种太旧的方式,因此过时的 TagHelpers 是处理此问题的首选方法。这个答案值得更多的赞! (2认同)

Ade*_*rad 5

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

1-在解决方案资源管理器中>添加新文件夹>将其命名为“ Helpers”,例如
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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

5-在Razor视图中的@model之后,键入以下行

@using YOUR_PROJECT.Helpers 
Run Code Online (Sandbox Code Playgroud)

6-显示如下描述:

@Html.DescriptionFor(m => m.FullName) 
Run Code Online (Sandbox Code Playgroud)

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

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

谢谢


Rya*_*yan 5

以下是 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

ModelExpressionProvider我们现在必须通过ExpressionMetadataProvider标记为内部的通道。

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

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