Come posso visualizzare il valore dell’attributo DisplayAttribute.Description?

Ho una class modello, con una proprietà come questa:

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

La visualizzazione di un’etichetta e il rendering di una casella di testo per l’input nella mia vista è piuttosto semplice:

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

Ma come faccio a rendere il valore dell’attributo annotazione Descrizione, ad esempio “Hello World!” ??

Ho finito con un aiutante come questo:

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

Grazie a coloro che mi hanno guidato nella giusta direzione. 🙂

Utilizzando la tecnica di questo articolo su come visualizzare suggerimenti visivi per i campi nel modulo , è ansible accedere al valore tramite il seguente:

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

Stavo per utilizzare la risposta accettata , ma non funzionava con ASP.NET Core 1/2 (ovvero MVC 6) perché ModelMetadata.FromLambdaExpression non esiste più ed è stato spostato su ExpressionMetadataProvider (anche l’utilizzo è stato leggermente modificato).

Questo è un metodo di estensione aggiornato che puoi utilizzare con ASP.NET Core 1.1 e 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(this IHtmlHelper html, Expression> 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 Core 1

Per ASP.NET Core 1, funziona lo stesso codice, ma avrai bisogno di diversi usings spazio usings nomi:

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

uso

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

Dovresti scrivere un helper personalizzato che rifletta sul tuo modello per fornire il valore dell’attributo Description.

Solo per ispezione (cioè non ho provato questo), ma:

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

In ASP.NET MVC Core puoi utilizzare i nuovi Tag Helpers, che rendono il tuo HTML simile a … HTML 🙂

Come questo:

 

Nota 1: è ansible utilizzare l’attributo aria-describedby nell’elemento input poiché tale ID verrà creato automaticamente nell’elemento span con l’attributo asp-description-for .

Nota 2: In Bootstrap 4, le classi form-text e text-muted sostituiscono la class help-block v3 per il testo della guida a livello di blocco.

Perché questa magia avvenga, devi solo creare un nuovo Tag Helper:

 using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Razor.TagHelpers; ///  ///  implementation targeting <span> elements with an asp-description-for attribute. /// Adds an id attribute and sets the content of the <span> with the Description property from the model data annotation DisplayAttribute. ///  [HtmlTargetElement("span", Attributes = DescriptionForAttributeName)] public class SpanDescriptionTagHelper : TagHelper { private const string DescriptionForAttributeName = "asp-description-for"; ///  /// Creates a new . ///  /// The . public SpanDescriptionTagHelper(IHtmlGenerator generator) { Generator = generator; } ///  public override int Order { get { return -1000; } } [HtmlAttributeNotBound] [ViewContext] public ViewContext ViewContext { get; set; } protected IHtmlGenerator Generator { get; } ///  /// An expression to be evaluated against the current model. ///  [HtmlAttributeName(DescriptionForAttributeName)] public ModelExpression DescriptionFor { get; set; } ///  /// Does nothing if  is null. 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; } } } 

E rendi disponibili i tuoi Tag Helpers per tutte le nostre visualizzazioni Razor. Aggiungi la direttiva addTagHelper al file Views/_ViewImports.cshtml :

 @addTagHelper "*, YourAssemblyName" 

Nota 1: sostituire YourAssemblyName con il nome assembly del progetto.

Nota 2: devi solo farlo una volta, per tutti i tuoi Tag Helpers!

Maggiori informazioni su Tag Helpers qui: https://docs.asp.net/en/latest/mvc/views/tag-helpers/intro.html

Questo è tutto! Divertiti con i nuovi Tag Helpers!

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

Quindi, se stavi usando il bootstrap, qualcosa del genere

 
@Html.LabelFor(m => m.Organization.Phone1) @Html.EditorFor(m => m.Organization.Phone1)

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

Oltre a Jakob Gade’a ottima risposta:

Se è necessario supportare un DescriptionAttribute anziché un DisplayAttribute , la sua ottima soluzione funziona ancora se si esegue l’override di MetadataProvider:

 public class ExtendedModelMetadataProvider : DataAnnotationsModelMetadataProvider { protected override ModelMetadata CreateMetadata(IEnumerable attributes, Type containerType, Func modelAccessor, Type modelType, string propertyName) { //Possible Multiple Enumerations on IEnumerable fix var attributeList = attributes as IList ?? 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; } } 

Questo deve essere registrato nel metodo Application_Start in Global.asax.cs :

 ModelMetadataProviders.Current = new ExtendedModelMetadataProvider(); 

… e se preferisci avere la descrizione come suggerimento nell’etichetta del modulo, aggiungi un Tag Helper in questo modo:

 using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Razor.TagHelpers; ///  ///  implementation targeting <label> elements with an asp-for attribute. /// Adds a title attribute to the <label> with the Description property from the model data annotation DisplayAttribute. ///  [HtmlTargetElement("label", Attributes = ForAttributeName)] public class LabelTitleTagHelper : TagHelper { private const string ForAttributeName = "asp-for"; ///  /// Creates a new . ///  /// The . public LabelTitleTagHelper(IHtmlGenerator generator) { Generator = generator; } ///  public override int Order { get { return -1000; } } [HtmlAttributeNotBound] [ViewContext] public ViewContext ViewContext { get; set; } protected IHtmlGenerator Generator { get; } ///  /// An expression to be evaluated against the current model. ///  [HtmlAttributeName(ForAttributeName)] public ModelExpression TitleFor { get; set; } ///  /// Does nothing if  is null. 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); } } 

Ciò creerà un nuovo attributo title con la proprietà Description dall’annotazione dati del modello DisplayAttribute .

La parte bella è che non hai bisogno di toccare le tue viste ponteggi generate! Perché questo Tag Helper ha come target l’attributo asp-for dell’elemento label che è già lì!

La risposta di HANDL, aggiornata per 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(this IHtmlHelper html, Expression> 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); } } 

Puoi sempre creare la tua estensione personalizzata in questo modo:

  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("* {0} ", text); } else { sb.AppendFormat(">{0}", text); } return MvcHtmlString.Create(sb.ToString()); } 

e puoi vederlo in questo modo:

 @HtmlExtension.ToolTipLabel(" "," ",true," "," "," ")