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 <span> elements with an <c>asp-description-for</c> attribute. /// Adds an <c>id</c> attribute and sets the content of the <span> 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!
Filipe Carneiro Sep 22 '16 at 23:23 2016-09-22 23:23
source share