Creating Custom Tag Helper in AS.NET Core MVC

Creating Custom Tag Helper in AS.NET Core MVC

I will discuss Creating a Custom Tag Helper in the AS.NET Core MVC Application with Examples in this article. Please read our previous article discussing Partial Tag Helper in ASP.NET Core MVC Application.

Creating Custom Tag Helper in AS.NET Core MVC

Using Tag Helper in AS.NET Core MVC, we can extend our existing HTML elements or create our own custom HTML elements. The Custom Tag Helper in AS.NET Core MVC is nothing but the class that implements the ITagHelper interface. However, .NET Core MVC allows us to implement this interface with the TagHelper class.

How to Create a Custom Tag Helper Class?

It’s a three-step process as follows:

  • Add a new class to your project
  • Inherit from TagHelper.
  • Override the Process or ProcessAsync method.

So, to create a Custom Tag Helper in ASP.NET Core MVC, the first step is to create a class that inherits from the TagHelper class. This class provides a virtual method to generate HTML tags. It contains synchronous (Process) and asynchronous (ProcessAsync) implementation of the virtual method.

public virtual Task ProcessAsync(TagHelperContext context, TagHelperOutput output);

public virtual void Process(TagHelperContext context, TagHelperOutput output);

We must override either of these or both based on our requirements. The Process (or ProcessAsync) method is responsible for generating the HTML that is going to be rendered by the browser. It receives context object, i.e., tag helper instances and TegHelperOuter instances, which we can use to read and change the content of our tag helper. If this is not clear at this moment, don’t worry; we will try to understand this with examples.

Example to Understand Tag Helper in ASP.NET Core MVC:

First, create a folder named TagHelpers inside the project root directory. This is the place where we will be creating our custom Tag Helpers.

In the next step, create a class file with MyCustomTagHelper inside the TagHelpers folder. It is recommended to follow the proper naming convention. The point you need to remember is that the name of the Tag Helper should end with the suffix TagHelper. Our newly created MyCustomTagHelper class should be derived from the TagHelper class, which contains two virtual methods: Process and ProcessAsync. These methods are responsible for rendering the output of our custom Tag Helper, and we would use them according to our project’s requirements:

So, once you create the MyCustomTagHelper.cs class file, please copy and paste the following code.

using Microsoft.AspNetCore.Razor.TagHelpers;

namespace TagHelpersDemo.TagHelpers
{
    public class MyCustomTagHelper : TagHelper
    {
        public override void Process(TagHelperContext context, TagHelperOutput output)
        {

        }
    }
}

As you can see in the code above, the TagHelperContext object, passed as the first parameter in the Process method, is used to provide information related to the attached element to Tag Helper. The second parameter, the TagHelperOutput object, renders the output of Tag Helper and can change the generated HTML.

Now, let us set some of the properties by using TagHelperOutput. So, modify the MyCustomTagHelper.cs class file as follows. The following code is self-explained, so please go through the comment lines for a better understanding.

using Microsoft.AspNetCore.Razor.TagHelpers;
using System.Text;

namespace TagHelpersDemo.TagHelpers
{
    public class MyCustomTagHelper : TagHelper
    {
        // PascalCase gets translated into Camel-case.
        // Can be passed via <my-custom employee-id="..." />. 
        public int EmployeeId { get; set; }

        // Can be passed via <my-custom employee-name="..." />. 
        public string? EmployeeName { get; set; }

        // Can be passed via <my-custom designation="..." />. 
        public string? Designation { get; set; }

        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            //TagName: The HTML element's tag name.
            //A whitespace or null value results in no start or end tag being rendered.
            output.TagName = "EmployeeSectionTagHelper"; // Set the HTML element name

            //TagMode: Syntax of the element in the generated HTML.
            //StartTagAndEndTag: Include both start and end tags.
            output.TagMode = TagMode.StartTagAndEndTag;

            //Create a String Builder Object to Hold the Employee Informations
            var sb = new StringBuilder();
            sb.AppendFormat($"<span>Employee Id:</span> <strong>{EmployeeId}</strong><br/>");
            sb.AppendFormat($"<span>Employee Name:</span> <strong>{EmployeeName}</strong><br/>");
            sb.AppendFormat($"<span>Employee Designation:</span> <strong>{Designation}</strong><br/>");

            //Convert the StringBuilder Object to String Type and
            //then set that string as the content either using SetContent and SetHtmlContent method
            //Content: Get or set the HTML element's main content.
            //SetHtmlContent: Sets the content.
            //output.Content.SetHtmlContent(sb.ToString());

            //output.Content.SetContent(sb.ToString());
            output.Content.SetHtmlContent(sb.ToString());
        }
    }
}
Adding addTagHelper to Views

In the next step, we need to add the addTagHelper directive to the Views/_ViewImports.cshtml file to make the Tag Helper available to all the Razor views. This can be done as follows:

@addTagHelper *, TagHelpersDemo

Here, TagHelpersDemo is the name of the assembly in which you have created your custom Tag Helper. So, with this Views/_ViewImports.cshtml file, it should look as follows.

@using TagHelpersDemo.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, TagHelpersDemo
@addTagHelper *, TagHelpersDemo.TagHelpers
How to use the Custom Tag Helper in ASP.NET Core MVC?

To use the custom Tag Helper in the Razor view, you need to write the Tag name in the lower case as shown in the below code snippet:

<my-custom employee-id=”1001″ employee-name=”Pranaya Rout” designation=”Manager”></my-custom>

As you can see, here we are using my-custom as an HTML Element and specifying the EmployeeId, EmployeeName, and Designation attributes of this my-custom tag. Next, modify the Home Controller as follows:

using Microsoft.AspNetCore.Mvc;
namespace TagHelpersDemo.Controllers
{
    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }
    }
}

Next, modify the Index.cshtml view method as follows:

@{
    ViewBag.Title = "Index";
    Layout = null;
}

<my-custom employee-id="1001" employee-name="Pranaya Rout" designation="Manager"></my-custom>

With the above changes, run the application, and you will get the following output.

How to Create Custom Tag Helper in AS.NET Core MVC Application with Examples

If you inspect the generated HTML, you will see the following code being generated.

<EmployeeSectionTagHelper>
    <span>Employee Id:</span> <strong>1001</strong><br/>
    <span>Employee Name:</span> <strong>Pranaya Rout</strong><br/>
    <span>Employee Designation:</span> <strong>Manager</strong><br/>
</EmployeeSectionTagHelper>
Passing Model Data to a Custom Tag Helper

We can use model binding techniques to pass the model data to a custom Tag Helper via properties of the type ModelExpression. In the following example, we will create three properties that take the given model expressions: EmployeeId, EmployeeName, and Designation.

Let’s understand this step-by-step: The first step is to create the model class. So, create a class file with the name Employee.cs within the Models folder and copy and paste the following code into it.

namespace TagHelpersDemo.Models
{
    public class Employee
    {
        public int EmployeeId { get; set; }
        public string? EmployeeName { get; set; }
        public string? Designation { get; set; }
    }
}

Next, modify the Index action method of the Home Controller as follows:

using Microsoft.AspNetCore.Mvc;
using TagHelpersDemo.Models;

namespace TagHelpersDemo.Controllers
{
    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            Employee employee = new Employee()
            {
                EmployeeId = 1,
                EmployeeName = "Pranaya",
                Designation= "Manager"
            };
            return View(employee);
        }
    }
}

Next, modify the Index.cshtml view as follows:

@model Employee
@{
    ViewBag.Title = "Index";
    Layout = null;
}

<my-custom employee-id="@Model.EmployeeId" employee-name="@Model.EmployeeName" designation="@Model.Designation"></my-custom>

We don’t need to make any changes in our MyCustomTagHelper class. With these changes in place, run the application, and you will get the output as expected, as shown in the below image.

How to Create Custom Tag Helper in AS.NET Core MVC Application with Examples

Another Way to Pass Model Data to Custom Tag Helper:

First, modify the MyCustomTagHelper class as follows:

using Microsoft.AspNetCore.Razor.TagHelpers;
using System.Text;

namespace TagHelpersDemo.TagHelpers
{
    [HtmlTargetElement("employee-details")]
    public class MyCustomTagHelper : TagHelper
    {
        [HtmlAttributeName("for-id")]
        public int EmployeeId { get; set; }

        [HtmlAttributeName("for-name")]
        public string? EmployeeName { get; set; }

        [HtmlAttributeName("for-designation")]
        public string? Designation { get; set; }

        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            //TagName: The HTML element's tag name.
            //A whitespace or null value results in no start or end tag being rendered.
            output.TagName = "EmployeeSectionTagHelper"; // Set the HTML element name

            //TagMode: Syntax of the element in the generated HTML.
            //StartTagAndEndTag: Include both start and end tags.
            output.TagMode = TagMode.StartTagAndEndTag;

            //Create a String Builder Object to Hold the Employee Informations
            var sb = new StringBuilder();
            sb.AppendFormat($"<span>Employee Id:</span> <strong>{EmployeeId}</strong><br/>");
            sb.AppendFormat($"<span>Employee Name:</span> <strong>{EmployeeName}</strong><br/>");
            sb.AppendFormat($"<span>Employee Designation:</span> <strong>{Designation}</strong><br/>");

            //Convert the StringBuilder Object to String Type and
            //then set that string as the content either using SetContent and SetHtmlContent method
            //Content: Get or set the HTML element's main content.
            //SetHtmlContent: Sets the content.
            //output.Content.SetHtmlContent(sb.ToString());

            //output.Content.SetContent(sb.ToString());
            output.Content.SetHtmlContent(sb.ToString());
        }
    }
}

Next, modify the Index.cshtml view as follows:

@model Employee
@{
    ViewBag.Title = "Index";
    Layout = null;
}


<employee-details for-id="@Model.EmployeeId" for-name="EmployeeName" for-designation="Designation"></employee-details>

<br/><br/>

<employee-details for-id="@Model.EmployeeId" for-name="@Model.EmployeeName" for-designation="@Model.Designation"></employee-details>

Now, run the application, and you should get the output as expected.

Custom Tag Helpers Real-Time Examples in ASP.NET Core MVC

As we already discussed, Custom Tag Helpers in ASP.NET Core MVC is a powerful way to enhance the HTML rendering process by adding custom behavior or transformations to specific tags or attributes. They enable server-side code to generate or manipulate HTML elements in Razor views. Let’s look at a couple of real-time examples of Custom Tag Helpers in ASP.NET Core MVC Applications:

Email Obfuscate Tag Helper

Imagine you want to protect email addresses on your site from being used by spambots. Obfuscate meaning is to make something less clear and harder to understand, especially intentionally. One approach is to obfuscate the email address in the HTML. We can create a Custom Tag Helper and Obfuscate the email address for this. So, create a class file named EmailTagHelper.cs and copy and paste the following code into it.

using Microsoft.AspNetCore.Razor.TagHelpers;
using System.Net;

namespace TagHelpersDemo.Models
{
    //We need to access this Custom tag using using the tag called email
    [HtmlTargetElement("email")]
    public class EmailTagHelper : TagHelper
    {
        private const string EmailDomain = "dotnettutorials.net";

        // Can be passed via <email mail-to="..." />. 
        // PascalCase gets translated into kebab-case.
        public string MailTo { get; set; }

        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            // Change the tag name to <a>
            // Replaces <email> with <a> tag
            output.TagName = "a";    

            var address = MailTo + "@" + EmailDomain;

            //Set the href attribute of the anchot tag as the email address
            output.Attributes.SetAttribute("href", "mailto:" + address);
            var obfuscatedEmail = "Email Us";
           
            output.Content.SetContent(obfuscatedEmail);
        }
    }
}

Next, modify the Index.cshtml view as follows:

@{
    ViewBag.Title = "Index";
    Layout = null;
}

<email mail-to="info"></email>

Now, run the application and see the following in the browser.

Custom Tag Helpers Real-Time Examples in ASP.NET Core MVC

If you inspect the generated HTML, you will see that the following HTML code is generated behind the scenes.

<a href="mailto:info@dotnettutorials.net">Email Us</a>
External Link Tag Helper

If you want to ensure that external links open in a new tab and are marked with a specific CSS class, you can use Custom Tag Helper. So, create a class file with the name ExternalLinkTagHelper.cs and then copy and paste the following code into it.

using Microsoft.AspNetCore.Razor.TagHelpers;

namespace TagHelpersDemo.Models
{
    [HtmlTargetElement("a", Attributes = "external-link")]
    public class ExternalLinkTagHelper : TagHelper
    {
        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            output.Attributes.SetAttribute("target", "_blank");
            //output.Attributes.SetAttribute("rel", "noopener noreferrer");
            output.Attributes.Add("class", "external-link");
        }
    }
}

Next, modify the Index.cshtml file as follows.

@{
    ViewBag.Title = "Index";
    Layout = null;
}

<a href="https://dotnettutorials.net" external-link> Visit Dot Net Tutorials</a>

You need to remember that custom tag helpers can be as simple or as complex as needed. They offer a powerful way to create reusable components and encapsulate behavior directly in your views. This is just a simple example. Tag Helpers can encapsulate much more complex logic and are particularly helpful for building reusable components or behaviors across views.

In the next article, I will discuss View Component Tag Helper in ASP.NET Core MVC Applications. In this article, I explain Creating a Custom Tag Helper in ASP.NET Core MVC Application with Examples. I hope you enjoy this Creating Custom Tag Helper in AS.NET Core MVC article.

Leave a Reply

Your email address will not be published. Required fields are marked *