Skip to content
Elisenda Gascon By Elisenda Gascon Apprentice Engineer II
Tag Helpers in ASP.NET Core

TLDR; In this post, we explore tag helpers, used in web applications using ASP.NET Core. They enable server-side C# code to create and render HTML elements in razor files. We look at some examples of tag helpers and their uses, and learn how to create custom tag helpers.

What are Tag Helpers and why are they used?

In ASP.NET Core web applications, whether using Razor Pages or MVC, the view pages, responsible for creating and rendering the HTML that will be used by the browser to display the requested page, are razor files. These are the files with the .cshtml extension and contain client and server side code. When this code is executed, it will result in HTML being sent to the browser.

The code inside of razor files has two particularities. One is that it uses razor syntax, which allows us to insert C# code inside of HTML. Usually, these bits of C# code will introduce bits of logic or data that we get from the controller or the model (in an MVC web application). The second particularity, and the subject of this blog post, is the use of tag helpers. These enable server-side C# code to create and render HTML elements in razor files. Tag helpers make razor files much more readable and easier to code.

In order to use tag helpers in an application, we must make them available in our application by adding them with the @addTagHelper directive to our _ViewImports.cshtml file in the Views folder:

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

A concrete example: creating forms in ASP.NET Core MVC

One very common place to use tag helpers is in forms. ASP.NET Core has a number of built-in tag helpers that allow us to work with forms. To illustrate how tag helpers are used and why they are useful and simplify our HTML code significantly, we will create a basic form in a web application using ASP.NET Core MVC. The form asks the user to input a username, email address, and password in order to subscribe to the site. In our Models folder, we have a Subscriber class, used as the model in our Subscribe view page here.

Let's see what the Subscribe.cshtml view page looks like:

@model Subscriber

<form asp-action="Subscribe" method="post" class="form-horizontal" role="form">
    <h4>Enter your details in order to subscribe.</h4>

    <div class="form-group">
        <label asp-for="Username" class="col-md-2 control-label"></label>
        <div class="col-md-5">
            <input asp-for="Username" class="form-control" />
            <span asp-validation-for="Username" class="text-danger"></span>
        </div>
    </div>
    <div class="form-group">
        <label asp-for="Email" class="col-md-2 control-label"></label>
        <div class="col-md-5">
            <input asp-for="Email" class="form-control" />
            <span asp-validation-for="Email" class="text-danger"></span>
        </div>
    </div>
    <div class="form-group">
        <label asp-for="Password" class="col-md-2 control-label"></label>
        <div class="col-md-5">
            <input asp-for="Password" class="form-control" />
            <span asp-validation-for="Password" class="text-danger"></span>
        </div>
    </div>

    <div class="form-group">
        <div class="col-md-offset-2 col-md-5">
            <input type="submit" class="btn btn-primary" value="Subscribe" />
        </div>
    </div>

</form>
The Introduction to Rx.NET 2nd Edition (2024) Book, by Ian Griffiths & Lee Campbell, is now available to download for FREE.

This renders the following view:

Showing the Subscribe page of our web application.

Let's look at some tag helpers used in this Subscribe view.

Form tag helper

The form tag helper will allow us to create forms. It will create the <form action="" /> attribute in the HTML code rendered in the browser, which, in an MVC web application, specifies the controller action used. To specify the controller action we want to target using tag helpers, we use the asp-action attribute. Here, we are targeting the Subscribe action in our SubscriberController.

In our code above, the following line

<form asp-action="Subscribe" method="post" class="form-horizontal" role="form">

will generate the following HTML:

<form method="post" class="form-horizontal" role="form" action="/Subscriber/Subscribe">

Other attributes that can be used on the form tag are:

  • The asp-controller tag helper can be used to indicate which controller should be targeted by the post action of a form.
  • The asp-route-* tag helper (where * can be replaced with the name of the parameter we want to specify the value for) allows us to create a route.
  • The asp-route tag helper allows us to indicate which main route we want to use.
  • The asp-forgery tag helper allows us to prevent cross-site request forgery attacks on the site when used with the [ValidateAntiForgeryToken] attribute in the HTTP Post action method.

Label tag helper

Probably the most basic tag helper, the label tag helper is used to create a label for a property on our model object. It has only one attribute, asp-for, used to indicate which property the label tag helper should be working with. This will display the name of the property we want to display.

In our code above, the following line

<label asp-for="Username" class="col-md-2 control-label"></label>

will generate the following HTML:

<label class="col-md-2 control-label" for="Username">Username</label>

We can see that the name of the generated for attribute matches the name of the property we passed into the asp-for tag helper. This is because the content of the label displays the name of the property. If we wanted to override this behaviour, we can add a different name in our razor code:

<label asp-for="Username" class="col-md-2 control-label">Different name</label>

And the following HTML is generated, overriding the label caption:

<label class="col-md-2 control-label" for="Username">Different name</label>

Input tag helper

The input tag helper is used to generate the corresponding HTML type, name, and id attributes based on the model property to which it is bound, determined by the asp-for attribute.

In our code above, the following line

<input asp-for="Username" class="form-control" />

will generate the following HTML:

<input class="form-control" type="text" data-val="true" data-val-length="Must be between 5 and 80 characters" data-val-length-max="80" data-val-length-min="5" data-val-required="Username is required" id="Username" maxlength="80" name="Username" value="" />

The attribute type will change according to the .NET data type or Data Annotation attribute applied to the model, such as [DataType(DataType.EmailAddress)] or [DataType(DataType.Password)].

Notice also the validation attributes generated. They are the data-val-* attributes and contain validation information based on the .NET data type and the data annotations in our model property.

Validation tag helper

When performing validation checks on the user input, the ModelState object will contain the error messages generated after the validation has been carried out. Validation tag helpers allow us to display these error messages in the view. In our razor code, above, we are using the asp-validation-for tag helper, known as the “validation message” tag helper. This will display the validation message for the property specified.

In our code above, the following line

<span asp-validation-for="Username" class="text-danger"></span>

will generate the following HTML:

<span class="text-danger field-validation-valid" data-valmsg-for="Username" data-valmsg-replace="true"></span>

How to create a custom Tag Helper

As we have seen, tag helpers contain pieces of functionality that we can reuse very easily. One useful thing to do, if there is a bit of functionality in our application that we might be reusing more than once (and if a built-in tag helper doesn't exist for it) is to create our own custom tag helper. Let's look at a an example of how to do this.

We will build a tag helper that will render HTML that generates a link that allows the user to send an email to the owner of the web application we have created.

First, we need to make any custom tag helpers we create accessible to the rest of the application. Just like before, we use the @addTagHelper directive in our _ViewImports.cshtml file in the Views folder. If our project is called MVCWebAppExample and we create a folder called TagHelpers in our project, where we will store all our custom tag helpers, we would add the following line of code:

@addTagHelper MVCWebAppExample.TagHelpers.*, MVCWebAppExample

We now create a new class called EmailTagHelper that inherits from the TagHelper base class. Naming conventions are important when creating applications using ASP.NET Core MVC, and this is no exception. By default, custom tag helpers will be usable by the name given before the “TagHelper” suffix, in this case, “email”.

Programming C# 10 Book, by Ian Griffiths, published by O'Reilly Media, is now available to buy.

Our TagHelper is going to accept an Address property - the email address that we are going to send the email to. By overriding the Process() method, we will build the output - the HTML that we want to generate when our tag helper is used. The output is going to be an anchor tag, and the attribute href is set to mailto: with the specified email address as the value. href is the attribute in HTML that specifies the URL of the page the link goes to.

public class EmailTagHelper : TagHelper
{
    public string Address { get; set; }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        output.TagName = "a";
        output.Attributes.SetAttribute("href", "mailto:" + Address);
    }
}

Let's now try to use it in our view page. If we create a Contact view page (and its corresponding controller), we can use our email tag helper, passing in the email address we want the email to be sent to.

Our Contact view page looks like this:

<h3>
    Please use the button below to contact us.
</h3>

<email address="info@@taghelperexample.com">Contact us</email>

The HTML generated is the following:

<h3>Please use the button below to contact us.</h3> 
	
<a href="mailto:info@taghelperexample.com">Contact us</a>

And the link to send the email shows in our Contact page

Showing the Contact page of our web application, where a link is displayed.

Conclusion

In this post, we have defined tag helpers, seen some examples, and learned how to build a very simple custom tag helper. We have seen the HTML code generated by tag helpers, which helps understand that using them makes our code more easily readable. This is especially visible with examples such as the validation tag helpers. It is worth paying a visit to the documentation for tag helpers to see further examples.

Elisenda Gascon

Apprentice Engineer II

Elisenda Gascon

Elisenda was an Apprentice Engineer from 2021 to 2023 at endjin after graduating with a mathematics degree from UCL. Her passion for problem solving drove her to pursue a career in software engineering.

During her time at endjin, she helped clients by delivering data analytics solutions, using tools such as Azure Synapse, Databricks notebooks, and Power BI. Through this, she also gained experience as a consultant by delivering presentations, running customer workshops, and managing stakeholders.

Through her contributions to internal projects, she gaines experience in web development in ASP.NET, contributed to the documentation of the Z3.Linq library, and formed part of a team to develop a report to explore global trends in wealth & health.

During her training as a software engineer, Elisenda wrote a number of blog posts on a wide range of topics, such as DAX, debugging NuGet packages, and dependency injection. She has also become a Microsoft certified Power BI analyst and obtained the Green Software for Practitioners certification from the Linux Foundation.