How do I display the DisplayAttribute.Description attribute value?

前端 未结 12 1714
醉梦人生
醉梦人生 2020-11-27 03:26

I have a model class, with a property like this:

[Display(Name = \"Phone\", Description=\"Hello World!\")]
public string Phone1 { get; set; }
相关标签:
12条回答
  • 2020-11-27 03:56

    Using the technique from this article about how to Display visual hints for the fields in your form, you can access the value via the following:

    @Html.TextBoxFor( 
            model => model.Email , 
            new { title = ModelMetadata.FromLambdaExpression<RegisterModel , string>( 
                model => model.Email , ViewData ).Description } )  
    
    0 讨论(0)
  • 2020-11-27 03:56

    You can always create your own custom extension like this:

        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());
        }
    

    and can get it in view like this:

    @HtmlExtension.ToolTipLabel(" "," ",true," "," "," ")
    
    0 讨论(0)
  • 2020-11-27 03:57

    I ended up with a helper like this:

    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));
        }
    }
    

    Thanks to those who led me in the right direction. :)

    0 讨论(0)
  • 2020-11-27 03:58

    In ASP.NET MVC Core you can use the new Tag Helpers, that makes your HTML look like... HTML :)

    Like this:

    <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>
    

    Note 1: You can use the aria-describedby attribute in the input element as that id will be created automatically in the span element with asp-description-for attribute.

    Note 2: In Bootstrap 4, the classes form-text and text-muted replaces the v3 help-block class for block-level help text.

    For this magic to happen, you just need to create a new 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;
            }
        }
    }
    

    And make your Tag Helpers available to all our Razor views. Add the addTagHelper directive to the Views/_ViewImports.cshtml file:

    @addTagHelper "*, YourAssemblyName"
    

    Note 1: Replace YourAssemblyName with the assembly name of your project.

    Note 2: You just need to do this once, for all your Tag Helpers!

    More information on Tag Helpers here: https://docs.asp.net/en/latest/mvc/views/tag-helpers/intro.html

    That’s it! Have fun with the new Tag Helpers!

    0 讨论(0)
  • 2020-11-27 04:02

    ...and if you prefer to have the description as a tooltip in the form label, add a Tag Helper like this:

    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);
        }
    }
    

    That will create a new title attribute with the Description property from the model's data annotation DisplayAttribute.

    The beautiful part is that you don't need to touch your generated scaffolded views! Because this Tag Helper is targeting the asp-for attribute of the label element that is already there!

    0 讨论(0)
  • 2020-11-27 04:02

    HANDL's answer, updated for ASP.NET Core 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);
        }
    }
    
    0 讨论(0)
提交回复
热议问题