Comment afficher la valeur de l’atsortingbut DisplayAtsortingbute.Description?

J’ai une classe de modèle, avec une propriété comme celle-ci:

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

L’affichage d’une étiquette et le rendu d’une zone de texte pour la saisie à mon avis est assez simple:

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

Mais comment puis-je rendre la valeur de l’atsortingbut d’annotation Description, par exemple “Hello World!”?

J’ai fini avec un assistant comme ça:

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

Merci à ceux qui m’ont conduit dans la bonne direction. 🙂

En utilisant la technique de cet article sur la façon d’ afficher des indications visuelles pour les champs de votre formulaire , vous pouvez accéder à la valeur via les éléments suivants:

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

J’étais sur le point d’utiliser la réponse acceptée , mais cela ne fonctionnait pas pour ASP.NET Core 1/2 (MVC 6) car ModelMetadata.FromLambdaExpression n’existe plus et a été déplacé vers ExpressionMetadataProvider (l’utilisation a également été légèrement modifiée).

Ceci est une méthode d’extension mise à jour que vous pouvez utiliser avec 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(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 HtmlSsortingng(modelExplorer.Metadata.Description); } } 

ASP.NET Core 1

Pour ASP.NET Core 1, le même code fonctionne, mais vous aurez besoin d’utilisations d’espaces de noms différents:

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

Usage

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

Vous devez écrire une aide personnalisée qui refléterait votre modèle pour donner la valeur de l’atsortingbut Description.

Par inspection seulement (c’est-à-dire que je n’ai pas testé cela), mais:

 var atsortingb = (DisplayAtsortingbute)Atsortingbute.GetCustomAtsortingbute( member, typeof(DisplayAtsortingbute)); var desc = atsortingb == null ? "" : atsortingb.GetDescription() 

Dans ASP.NET MVC Core, vous pouvez utiliser les nouveaux Tag Helpers, qui font ressembler votre HTML … HTML 🙂

Comme ça:

 

Remarque 1: Vous pouvez utiliser l’atsortingbut aria-describedby dans l’élément input car cet identifiant sera créé automatiquement dans l’élément span avec l’atsortingbut asp-description-for .

Remarque 2: dans Bootstrap 4, les classes form-text et text-muted remplacent la classe de bloc d’ help-block v3 pour le texte d’aide au niveau du bloc.

Pour que cette magie se produise, il vous suffit de créer un nouveau 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 atsortingbute. /// Adds an id atsortingbute and sets the content of the <span> with the Description property from the model data annotation DisplayAtsortingbute. ///  [HtmlTargetElement("span", Atsortingbutes = DescriptionForAtsortingbuteName)] public class SpanDescriptionTagHelper : TagHelper { private const ssortingng DescriptionForAtsortingbuteName = "asp-description-for"; ///  /// Creates a new . ///  /// The . public SpanDescriptionTagHelper(IHtmlGenerator generator) { Generator = generator; } ///  public override int Order { get { return -1000; } } [HtmlAtsortingbuteNotBound] [ViewContext] public ViewContext ViewContext { get; set; } protected IHtmlGenerator Generator { get; } ///  /// An expression to be evaluated against the current model. ///  [HtmlAtsortingbuteName(DescriptionForAtsortingbuteName)] 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(ssortingng.Format("No provided metadata ({0})", DescriptionForAtsortingbuteName)); } output.Atsortingbutes.SetAtsortingbute("id", metadata.PropertyName + "-description"); if( !ssortingng.IsNullOrWhiteSpace( metadata.Description)) { output.Content.SetContent(metadata.Description); output.TagMode = TagMode.StartTagAndEndTag; } } } 

Et faites en sorte que vos Tag Helpers soient disponibles pour toutes nos vues Razor. Ajoutez la directive Views/_ViewImports.cshtml fichier Views/_ViewImports.cshtml :

 @addTagHelper "*, YourAssemblyName" 

Remarque 1: remplacez YourAssemblyName par le nom de l’assembly de votre projet.

Note 2: Il vous suffit de le faire une fois pour tous vos Tag Helpers!

Plus d’informations sur Tag Helpers ici: https://docs.asp.net/en/latest/mvc/views/tag-helpers/intro.html

C’est tout! Amusez-vous avec les nouveaux Tag Helpers!

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

Donc, si vous utilisiez le bootstrap, quelque chose comme

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

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

En plus de Jakob Gade’a, une excellente réponse:

Si vous avez besoin de prendre en charge un DescriptionAtsortingbute au lieu d’un DisplayAtsortingbute , sa solution idéale fonctionne toujours si nous remplaçons le MetadataProvider:

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

Cela doit être enregistré dans la méthode Application_Start dans Global.asax.cs :

 ModelMetadataProviders.Current = new ExtendedModelMetadataProvider(); 

… et si vous préférez que la description soit une infobulle dans l’étiquette du formulaire, ajoutez un tag helper comme ceci:

 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 atsortingbute. /// Adds a title atsortingbute to the <label> with the Description property from the model data annotation DisplayAtsortingbute. ///  [HtmlTargetElement("label", Atsortingbutes = ForAtsortingbuteName)] public class LabelTitleTagHelper : TagHelper { private const ssortingng ForAtsortingbuteName = "asp-for"; ///  /// Creates a new . ///  /// The . public LabelTitleTagHelper(IHtmlGenerator generator) { Generator = generator; } ///  public override int Order { get { return -1000; } } [HtmlAtsortingbuteNotBound] [ViewContext] public ViewContext ViewContext { get; set; } protected IHtmlGenerator Generator { get; } ///  /// An expression to be evaluated against the current model. ///  [HtmlAtsortingbuteName(ForAtsortingbuteName)] 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(ssortingng.Format("No provided metadata ({0})", ForAtsortingbuteName)); } if (!ssortingng.IsNullOrWhiteSpace(metadata.Description)) output.Atsortingbutes.SetAtsortingbute("title", metadata.Description); } } 

Cela créera un nouvel atsortingbut title avec la propriété Description de l’annotation de données DisplayAtsortingbute du modèle.

La belle partie est que vous n’avez pas besoin de toucher vos vues générées échafaudées! Parce que cette aide par ciblage cible l’atsortingbut asp-for de l’élément label déjà présent!

La réponse de HANDL, mise à jour pour 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 HtmlSsortingng(modelExplorer.Metadata.Description); } } 

Vous pouvez toujours créer votre propre extension personnalisée comme ceci:

  public static MvcHtmlSsortingng ToolTipLabel (ssortingng resourceKey, ssortingng text, bool isRequired, ssortingng labelFor = "", ssortingng labelId = "",ssortingng className="") { ssortingng tooltip = ssortingng.Empty; SsortingngBuilder sb = new SsortingngBuilder(); if (!ssortingng.IsNullOrEmpty(resourceKey)) { var resources = GetAllResourceValues(); if (resources.ContainsKey(resourceKey)) { tooltip = resources[resourceKey].Value; } } sb.Append("", text); } else { sb.AppendFormat(">{0}", text); } return MvcHtmlSsortingng.Create(sb.ToSsortingng()); } 

et peut le voir comme ceci:

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