How to display the value of the DisplayAttribute.Description attribute?

I have a model class with this property:

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

Displaying a label and rendering a text box for input in my view is pretty simple:

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

But how can I visualize the value of the description annotation attribute, that is, "Hello World!" ??

+68
c # asp.net-mvc
Jul 05 2018-11-11T00:
source share
12 answers

As a result, I got an assistant:

 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. :)

+82
Jul 05 '11 at 6:45
source share

Using the technique from this article on How to Display Visual Prompts for Fields in Your Form , you can access the value using the following

 @Html.TextBoxFor( model => model.Email , new { title = ModelMetadata.FromLambdaExpression<RegisterModel , string>( model => model.Email , ViewData ).Description } ) 
+40
Sept. 19 '13 at 5:14
source share

I was going to use the accepted answer , but it did not work for ASP.NET Core 1/2 (aka MVC 6), because ModelMetadata.FromLambdaExpression no longer exists and was ported to ExpressionMetadataProvider (also the usage has changed a bit).

This is an updated extension method that you can use with ASP.NET Core 1.1 and 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 Kernel 1

The same code works for ASP.NET Core 1, but you need a different usings namespace:

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

Using

 @Html.DescriptionFor(model => model.Phone1) 
+21
Feb 09 '16 at 2:03
source share

In ASP.NET MVC Core, you can use the new tag helpers, which 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, since this identifier will be created automatically in the span element with the asp-description-for attribute.

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

For this magic, 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 for all kinds of Razor. Add the addTagHelper directive to the Views/_ViewImports.cshtml :

 @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

Here it is! Have fun with the new tag helpers!

+5
Sep 22 '16 at 23:23
source share

If anyone is interested how to use the accepted answer

1- In your Solution Explorer> Add New Folder> name it "Helpers", for example
2- Add a new class, for example, name it "CustomHtmlHelpers"
3- Paste the code:

 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- In your model or viewModel, this is:

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

5- On your Razor, after @model, print this line

 @using YOUR_PROJECT.Helpers 

6- Show the description as follows:

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

7- You can use the description to display text in the input placeholder:

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

thank

+4
Sep 26 '18 at 15:44
source share

You need to write a special assistant that will reflect your model to give the value of the Description attribute.

+2
Jul 05 2018-11-11T00:
source share
 @ViewData.ModelMetadata.Properties .Where(m => m.PropertyName == "Phone1").FirstOrDefault().Description 

So, if you used bootstrap, something like

 <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> 
+2
Mar 04 '16 at 17:21
source share
 var attrib = (DisplayAttribute)Attribute.GetCustomAttribute( member, typeof(DisplayAttribute)); var desc = attrib == null ? "" : attrib.GetDescription() 
+1
Jul 05 '11 at 6:23
source share

In addition to Jakob Gade, an excellent answer is:

If you need DescriptionAttribute support instead of DisplayAttribute , its great solution still works if we override MetadataProvider:

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

This is required to register in the Application_Start method in Global.asax.cs :

 ModelMetadataProviders.Current = new ExtendedModelMetadataProvider(); 
0
Feb 11 '16 at 15:49
source share

... and if you prefer the description to be a tooltip in the form label, add a tag helper, for example:

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

This will create a new title attribute with the Description property from the data annotation of the DisplayAttribute model.

The great part is that you don’t need to touch your generated views. Since this tag helper targets the asp-for attribute of the label element that already exists!

0
Sep 23 '16 at 0:09
source share

HANDL 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); } } 
-one
Sep 24 '17 at 20:31 on
source share

You can always create your own custom extension:

  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 the form:

 @HtmlExtension.ToolTipLabel(" "," ",true," "," "," ") 
-2
Sep 25 '17 at 9:54 on
source share



All Articles