ASP.NET Core 2.0 MVC Custom Tag Helpers

Problem

How to create custom Tag Helpers in ASP.NET Core MVC.

Solution

In an empty project, add NuGet packages update Startup class to add services and middleware for MVC:

Add a controller with an action method:

An Employees.cshtml page:

Add a class EmployeeTagHelper.cs:

Discussion

As discussed in the previous post, Tag Helpers help generate HTML by attaching attributes to existing HTML elements or by creating new elements. In this post we’ve created a new tag to display employee information.

Tag Helper Class

To create custom Tag Helpers you create a C# class that inherits from TagHelper abstract base class. There are two attributes that help define behaviour of our class:

[RestrictChildren] – restricts the nesting structure of tag helpers. For instance here the employee tag can only have friend tag nested in them:

Note: this also restricts the use of razor syntax, which I feel is bit too restrictive!

[HtmlTargetElement] – tag helper names by default are kebab casing of C# class name. However, using this attribute you can explicitly define tag helper name, its parent tag name, tag structure (self-closing, without end tag) and allowed attributes. You can apply this attribute more than once if the C# class is targeting more than one tag helper.

Linking HTML Elements to C# Properties

Properties in your custom C# class maps to HTML element attributes. You could override this behaviour (i.e. stop binding properties to HTML attributes) by using [HtmlAttributeNotBound] attribute on the property. You could also explicitly specify the name of HTML attributes by annotating properties with [HtmlAttributeName].

Process and ProcessAsync (Execution)

Overriding one of these methods enable us to output HTML for our Tag Helpers. There are two parameters to these methods:

TagHelperContext – contains a readonly collection of all HTML attributes applied to your tag helper. Also contains Items dictionary that can be used to pass data between nested tag helpers.

TagHelperOutput – used to set HTML elements and their attributes for the tag helper. There are five properties to set content (PreElement, PreContenet, Content, PostContent, PostElement) and Attributes property to add attributes to tag helper’s HTML. There are also properties to set HTML element that tag helper outputs (TagName) and its closing tag behaviour (TagMode).

Model Data

We can populate tag helper properties via model binding by creating properties of type ModelExpression:

Then using @model directive to declare and use model binding:

Value of the property can be retrieved using Model property of ModelExpression:

ViewContext

Within the tag helper class we can use ViewContext type to access view’s contextual information e.g. HttpContext, ModelState etc. This is achieved by declaring a property of type ViewContext and annotating with a [ViewContext] and [HttpAttirubteNotBound] attributes:

Dependency Injection

Tag Helpers can benefit from dependency injection like other parts of ASP.NET Core. Simply add your service in ConfigureServices method of Startup and inject in tag helper using constructor. The sample code with this post demonstrates this.

Tag Builder

Instead of concatenating strings to create HTML output, you could use TagBuilder class. It helps in building HTML element and their attributes. You could create nested tags easily using this mechanism:

Source Code

GitHub: https://github.com/TahirNaushad/Fiver.Mvc.TagHelpers.Custom

Leave a Reply