[ASP.NET Core 2.0] Custom Tag Helper
ASP.NET Core introduces an extremely natural way to build input, label and a few other tags with the asp-for keyword; they are called tag helpers
You can also create your own tag helpers to render whatever tags you want
- 1. A few tag helpers
- 2. The problem with the label tag helper
- 3. Customize Label tag helper
- 4. Usage
1. A few tag helpers
ASP.NET MVC5
ASP.NET Core
| ASP.NET MVC5 | ASP.NET Core |
|---|---|
@Html.TextBoxFor() |
<input asp-for=""/> |
@Html.DropDownListFor() |
<select asp-for="" asp-items=""/> |
@Html.LabelFor() |
<label asp-for=""></label> |
@Html.ValidationMessageFor() |
<anytag asp-validation-for=""></anytag> |
2. The problem with the label tag helper
label is the tag you’ll customize quite a lot in your asp.net core app. The reason is that you want a red * on required inputs, and you also want (500 characters) when the input only allows 500 characters.
Of course, all of that can easily be added by … adding it by hand
ASP.NET MVC, and later ASP.NET CORE, lets you build a model with DataAnnotations to tell the database the limits or the definition of a column, while also validating its input field in client-side code
[]
[]
[]
public string Username { get; set; }
However, when creating the input field for this username property, you still have to add the * and the max 15 characters text by hand
<label asp-for="Username"></label>
<input asp-for="Username"/>
<span asp-validation-for="Username"></span>
the code above generates the following html
<label for="Username">User name</label>
....other lines...
3. Customize Label tag helper
We’ll create a custom tag helper named requiredlabel
3.1. Code
namespace YourNamespace.Extensions.TagHelpers
{
using System;
using System.IO;
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.TagHelpers;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
// Source code for label tag helper: Mvc/src/Microsoft.AspNetCore.Mvc.TagHelpers/LabelTagHelper.cs
// https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc.TagHelpers/LabelTagHelper.cs
[]
public class RequiredLabelTagHelper : TagHelper
{
private const string ForAttributeName = "asp-for";
// Will be used as highlight-class in html
public string HighlightClass { get; set; }
/// <summary>
/// Creates a new <see cref="LabelTagHelper"/>.
/// </summary>
/// <param name="generator">The <see cref="IHtmlGenerator"/>.</param>
public RequiredLabelTagHelper(IHtmlGenerator generator)
{
Generator = generator;
}
/// <inheritdoc />
public override int Order => -1000;
[]
[]
public ViewContext ViewContext { get; set; }
protected IHtmlGenerator Generator { get; }
/// <summary>
/// An expression to be evaluated against the current model.
/// </summary>
[]
public ModelExpression For { get; set; }
/// <inheritdoc />
/// <remarks>Does nothing if <see cref="For"/> is <c>null</c>.</remarks>
public override void Process(TagHelperContext context, TagHelperOutput output)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (output == null)
{
throw new ArgumentNullException(nameof(output));
}
var requiredMarkTagBuilder = new TagBuilder("span");
requiredMarkTagBuilder.AddCssClass(HighlightClass);
requiredMarkTagBuilder.InnerHtml.Append(" *");
var tagBuilder = Generator.GenerateLabel(
ViewContext,
For.ModelExplorer,
For.Name,
labelText: null,
htmlAttributes: null);
if (For.ModelExplorer.Metadata.IsRequired)
{
using (var writer = new StringWriter())
{
requiredMarkTagBuilder.WriteTo(writer, HtmlEncoder.Default);
tagBuilder.InnerHtml.AppendHtml(writer.ToString());
}
}
output.TagName = tagBuilder.TagName;
output.MergeAttributes(tagBuilder);
output.Content.SetHtmlContent(tagBuilder.InnerHtml);
}
}
}
3.2. Registering it
Open View/_ViewImports.cshtml
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@* Add the following line *@
@addTagHelper *, YourNamespace.Extensions
This code lets your tag helper work inside razor views. With a different namespace name you have to change that code accordingly
Read more at: https://docs.microsoft.com/en-us/aspnet/core/mvc/views/tag-helpers/intro, section Managing Tag Helper scope
4. Usage
Extremely simple
<requiredlabel asp-for="Username" highlight-class="red bold"></requiredlabel>
renders the following html
<label for="Username">User name<span class="red bold"> *</span></label>