Creating Custom Tag Helpers in ASP.NET Core
Tags: aspnetcore, custom, tag, helpers
Published: 2021-08-21 13:32:21

In my previous post, I explained the fundamentals of ASP.NET Core Tag Helpers and I gave you the introduction of some of the built-in Tag Helpers available in ASP.NET Core. Web applications are evolving with the speed of light and developers have to implement new features and requirements almost every day. It would be good if we can take advantage of ASP.NET Core Tag Helpers infrastructure and create custom Tag Helpers of our own and become more productive by reusing our custom Tag Helpers across multiple applications. In this guide, I will explain everything you need to know to implement custom ASP.NET Tag Helpers. I will create a custom Tag Helpers that will render [Open Graph Meta Tags](https://ahrefs.com/blog/open-graph-meta-tags/).

## Custom Tag Helpers Basics

Every Tag Helper in ASP.NET Core must implement the [ITagHelper](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.razor.taghelpers.itaghelper?view=aspnetcore-3.1) interface available in [Microsoft.AspNetCore.Razor.TagHelpers](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.razor.taghelpers?view=aspnetcore-3.1) namespace. The default implementation of this interface is available in [TagHelper](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.razor.taghelpers.taghelper?view=aspnetcore-3.1) class and all built-in ASP.NET Core Tag Helpers derived from the TagHelper class. We can follow a similar approach and can inherit our custom Tag Helper classes from TagHelper class and override either Process or ProcessAsync methods as per our requirements.

Tag Helpers are normally used to generate a customized HTML output on the page and when we implement the Tag Helpers we need to have access to some dynamic data or parameters so that we can tweak our Tag Helper logic accordingly to these parameters. A custom Tag Helper can receive these dynamic parameters from many different sources.

- A custom Tag Helper can receive data from the attributes we define in our Tag Helper. For example, if you have a custom tag like the one shown below, you can access the enable property value true/false within your custom Tag Helper and implement your Tag Helper logic accordingly.
```
<seo-helper enable="true"></seo-helper> 
```
- A custom Tag Helper can also access the information from its executing context such as Request object, View Bag, View Context, etc.
- A custom Tag can also access the elements that our tag helper is attached to using the two objects **TagHelperContext** and **TagHelperOutput** passed into the Process method.
```
public override void Process(TagHelperContext context, TagHelperOutput output)
{}
```
- A custom Tag Helper can also access the contents available inside the opening and closing tags.
```
<format>Sample Contents</format>
```
## Implementing Custom Tag Helpers

Create an ASP.NET Core MVC Web Application in Visual Studio 2019 and make sure the project is building fine. Create a folder called “TagHelpers” in your project root directory in which we will create our custom Tag Helpers. This folder is not required and you can give it any name you want but it is better to follow this name as a convention just as we use the “Controllers” folder to put all our controllers and Views folder to store all our Views.

For the purpose of this tutorial, I have decided to create an Open Graph Tag Helper that can help you to generate [Open Graph Meta Tags](https://ahrefs.com/blog/open-graph-meta-tags/) for sharing your posts on different social media platforms. Here are the examples of three of the most common Open Graph meta tags.
```
<meta property="og:title" content="Creating ASP.NET Core Custom Tag Helpers" />
<meta property="og:description" content="Learn how to create custom Tag Helpers in ASP.NET Core" />
<meta property="og:image" content="https://www.ezzylearning.net/images/featured.jpg" />
```
Create a class called "**OpenGraphTagHelper**" inside the newly created **TagHelpers** folder. It is recommended that you follow the Tag Helpers naming conventions and end your Tag Helpers name with the suffix "**TagHelper**". We also need to derive OpenGraphTagHelper class from the TagHelper class that will provide us **Process** or **ProcessAsync** methods which we need to override. When Razor Engine executes our Custom Tag Helpers, the Process or ProcessAsync methods are called to render the output of our custom Tag Helper.
```
using Microsoft.AspNetCore.Razor.TagHelpers;

public class OpenGraphTagHelper : TagHelper
{
	public override void Process(TagHelperContext context, TagHelperOutput output)
	{

	}
}
```
If Tag Helper needs some information about the attached/associated element then it can use the **TagHelperContext** object passed as the first parameter in the above Process method. This class has the following important properties:

<table><tbody><tr><td>AllAttributes</td><td>Every attribute associated with the current HTML element</td></tr><tr><td>Items</td><td>Gets the collection of items used to communicate with other ITagHelpers</td></tr><tr><td>TagName</td><td>The parsed HTML tag name of the element</td></tr><tr><td>UniqueId</td><td>An identifier unique to the HTML element this context is for</td></tr></tbody></table>

The second parameter **TagHelperOutput** represents the output of the tag helper and we can modify the final generated HTML using this object. It has the following important properties.

<table><tbody><tr><td>Attributes</td><td>The HTML element's attributes.</td></tr><tr><td>Content</td><td>Get or set the HTML element's main content.</td></tr><tr><td>IsContentModified</td><td>true if Content has been set, false otherwise.</td></tr><tr><td>PostContent</td><td>The HTML element's post content.</td></tr><tr><td>PostElement</td><td>Content that follows the HTML element.</td></tr><tr><td>PreContent</td><td>The HTML element's pre content.</td></tr><tr><td>PreElement</td><td>Content that precedes the HTML element.</td></tr><tr><td>TagMode</td><td>Syntax of the element in the generated HTML.</td></tr><tr><td>TagName</td><td>The HTML element's tag name.</td></tr></tbody></table>

Let us say you want your custom Tag Helper to generate a simple HTML meta element so you can use the TagHelperOutput object and set the **TagName** property to meta as follows:
```
public override void Process(TagHelperContext context, TagHelperOutput output)
{
	output.TagName = "meta";
}
```
To make the **OpenGraphTagHelper** Tag Helper available to all my Razor views, I have to add the **addTagHelper** directive to the **Views/\_ViewImports.cshtml** file as follows. Here **CustomTagHelpersDemo** is the name of the Assembly in which you are creating your custom Tag Helpers.
```
@addTagHelper \*, CustomTagHelpersDemo
```
To use your custom Tag Helper in Razor View, you need to ignore the TagHelper suffix from the class name **OpenGraphTagHelper** and need to write the Tag Helper name in lower kabab case as shown below:
```
<form>
    <open-graph></open-graph>
</form>
```
If you will run the project, you will see the **meta** element rendered in the HTML with both opening and closing tags.
```
<form>
    <meta> </meta>
</form>
```
Let’s say you want to add some contents inside your generated meta tag, you can do this using the **SetContent** method
```
output.TagName = "meta";
output.Content.SetContent("I am meta tag");
```
The above two statements will generate the following output in the browser
```
<meta>I am meta tag</meta>
```
Let’s say you want to add custom attributes **property** and **content** to your Tag helper. You need to introduce a **Title** property in your custom Tag Helper and then you need to use SetAttribute method as follows:
```
public string Title { get; set; } 

public override void Process(TagHelperContext context, TagHelperOutput output)
{
      output.TagName = "meta";               
            
      output.Attributes.SetAttribute("property", "og:title");
      output.Attributes.SetAttribute("content", Title); 
}
```
Visual Studio will provide us full IntelliSense support when we will use our custom Tag Helper in Razor Views. For example, when you will add a space after your custom Tag helper in Razor View, you will see that a newly added **title** property is now showing in the list of available attributes for our custom Tag Helper.

![Custom Tag Helper Intellisense in Visual Studio](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v4qdyg02trkhjklqp6qq.jpg)

You can specify any string as the title to your custom Tag Helper as follows
```
<open-graph title="Creating ASP.NET Core Custom Tag Helpers"></open-graph>
```
Following HTML will render in the browser once you will run above Tag Helper.
```
<meta property="og:title" content="Creating ASP.NET Core Custom Tag Helpers">
```
Our custom Tag Helper is only generating one meta tag which is not very useful for us. We want our custom Tag Helper to generate multiple Open Graph meta tags so that it can make us more productive as we don’t have to write all those tags ourselves. We can use a built-in **TagBuilder** class to build multiple meta tags. TagBuilder class has **MergeAttribute** method which can be used to attach attributes with the meta tag we are building and finally we can use **AppendHtml** method to append all these meta tags to generate the final output.
```
public override void Process(TagHelperContext context, TagHelperOutput output)
{
	TagBuilder meta1 = new TagBuilder("meta");
	meta1.MergeAttribute("property", "og:title");
	meta1.MergeAttribute("content", Title);            
	output.Content.AppendHtml(meta1);

	TagBuilder meta2 = new TagBuilder("meta");
	meta2.MergeAttribute("property", "og:description");
	meta2.MergeAttribute("content", Description);
	output.Content.AppendHtml(meta2);

	TagBuilder meta3 = new TagBuilder("meta");
	meta3.MergeAttribute("property", "og:image");
	meta3.MergeAttribute("content", Image);
	output.Content.AppendHtml(meta3); 
}
```
We can now use our custom Tag Helper in Razor Views and provide all three properties as follows:
```
<open-graph 
    title="Creating ASP.NET Core Custom Tag Helpers"
    description="Learn how to create custom Tag Helpers in ASP.NET Core"
    image="https://www.ezzylearning.net/images/featured.jpg"></open-graph>
```
If you will run the project now, you will see the following HTML generated in the browser.
```
<open-graph>
   <meta content="Creating ASP.NET Core Custom Tag Helpers" property="og:title"></meta>
   <meta content="Learn how to create custom Tag Helpers in ASP.NET Core" property="og:description"></meta>
   <meta content="https://www.ezzylearning.net/images/featured.jpg" property="og:image"></meta>
</open-graph>
```
Something is not right in the above HTML. We want to generate plain HTML meta tags and we don’t want to generate our custom tag helper name in the final output. To fix this issue, you need to set the TagName property to null and we can add the following line as the first line in the Process method.
```
output.TagName = null; 
```
Run the project again and this time you will see all three Open Graph meta tags.
```
<meta content="Creating ASP.NET Core Custom Tag Helpers" property="og:title"></meta>
<meta content="Learn how to create custom Tag Helpers in ASP.NET Core" property="og:description"></meta>
<meta content="https://www.ezzylearning.net/images/featured.jpg" property="og:image"></meta>
```
## Summary

In this tutorial, I have explained the basics of creating custom Tag Helpers in ASP.NET Core and implemented a simple Open Graph Tag Helper to generate SEO friendly meta tags. Off course, you can develop more powerful and complex custom Tag Helpers as per your requirement. I hope this tutorial will give you a jump start in your ASP.NET Core developer journey.