ASP.NET MVC 6 Hosting – Easy Way To Use Tag Helpers in ASP.NET MVC 6

Easy Way To Use Tag Helpers in ASP.NET MVC 6

ASP.NET MVC gives you a powerful, patterns-based way to build dynamic websites that enables a clean separation of concerns and that gives you full control over markup for enjoyable, agile development. ASP.NET MVC includes many features that enable fast, TDD-friendly development for creating sophisticated applications that use the latest web standards.

ASP.NET MVC 6 Hosting - Easy Way To Use Tag Helpers in ASP.NET MVC 6

Tag Helpers enable server-side code to participate in creating and rendering HTML elements in Razor files. For example, the built-in ImageTagHelper can append a version number to the image name. Whenever the image changes, the server generates a new unique version for the image, so clients are guaranteed to get the current image (instead of a stale cached image). There are many built-in Tag Helpers for common tasks – such as creating forms, links, loading assets and more – and even more available in public GitHub repositories and as NuGet packages. Tag Helpers are authored in C#, and they target HTML elements based on element name, attribute name, or parent tag. For example, the built-in LabelTagHelper can target the HTML <label> element when the LabelTagHelper attributes are applied. If you’re familiar with HTML Helpers, Tag Helpers reduce the explicit transitions between HTML and C# in Razor views. Tag Helpers compared to HTML Helpers explains the differences in more detail.

Writing a Custom Tag Helper in ASP.NET MVC 6

Let’s say we want to write a custom tag helper for rendering a <time> tag based on aDateTime. Those <time> tags can be used to represent dates and times in a machine-readable format. However, they require a very specific date format that we shouldn’t have to repeat over and over again. Here’s how we would use our tag helper:

@{
    var exampleDate = new DateTime(2016, 12, 02, 14, 50, 31, DateTimeKind.Utc);
}

<time asp-date-time="@exampleDate" />

The output should be something along the lines of the following:

<time datetime="2016-12-02T14:50:31Z" title="Wednesday, December 2, 2016 02:50 PM UTC">December 2, 2016 2:50 PM</time>

We’ll start by creating a custom class that derives from the TagHelper class found in theMicrosoft.AspNet.Razor.TagHelpers namespace. We’ll also create a property to hold the datetime that’s passed in through the asp-date-time attribute:

public class TimeTagHelper : TagHelper
{
    [HtmlAttributeName("asp-date-time")]
    public DateTime DateTime { get; set; }
}

However, we only want to apply our tag helper to <time> tags that specify the asp-date-time attribute, so we’ll explicitly restrict it to those using the HtmlTargetElement attribute on the tag helper class:

[HtmlTargetElement("time", Attributes = DateTimeAttributeName)]
public class TimeTagHelper : TagHelper
{
    private const string DateTimeAttributeName = "asp-date-time";

    [HtmlAttributeName(DateTimeAttributeName)]
    public DateTime DateTime { get; set; }
}

To specify our tag helper’s behavior, we’ll override the Process method and add our datetime manipulation logic inside of it. We’re setting both a machine-readable datetimeattribute and a human-readable title attribute:

[HtmlTargetElement("time", Attributes = DateTimeAttributeName)]
public class TimeTagHelper : TagHelper
{
    private const string DateTimeAttributeName = "asp-date-time";

    [HtmlAttributeName(DateTimeAttributeName)]
    public DateTime DateTime { get; set; }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        output.Attributes["datetime"] = DateTime.ToString("yyyy-MM-dd'T'HH:mm:ss") + "Z";
        output.Attributes["title"] = DateTime.ToString("dddd, MMMM d, yyyy 'at' h:mm tt");
    }
}

Note that we’ll also have to add a line to _ViewImports.cshtml for our tag helper to be recognized within Razor views:

@addTagHelper "*, YourTagHelperAssemblyName"

If we now render a <time> tag using this simple version of the tag helper, we get both attributes, but no inner HMTL (no content). Let’s extend our tag helper such that it adds a default piece of inner HTML if the <time> tag doesn’t define any child content. To do this, we’ll await and inspect the GetChildContentAsync method, which means that we’ll have to override ProcessAsync instead of Process:

[HtmlTargetElement("time", Attributes = DateTimeAttributeName)]
public class TimeTagHelper : TagHelper
{
    private const string DateTimeAttributeName = "asp-date-time";

    [HtmlAttributeName(DateTimeAttributeName)]
    public DateTime DateTime { get; set; }

    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        output.Attributes["datetime"] = DateTime.ToString("yyyy-MM-dd'T'HH:mm:ss") + "Z";
        output.Attributes["title"] = DateTime.ToString("dddd, MMMM d, yyyy 'at' h:mm tt");

        var childContent = await output.GetChildContentAsync();
        if (childContent.IsEmpty)
        {
            output.TagMode = TagMode.StartTagAndEndTag;
            output.Content.SetContent(DateTime.ToString("MMMM d, yyyy h:mm tt"));
        }
    }
}

Now we should get the output we want:

<time datetime="2016-12-02T14:50:31Z" title="Wednesday, December 2, 2016 02:50 PM UTC">December 2, 2016 2:50 PM</time>

Anjali Punjab

Anjali Punjab is a freelance writer, blogger, and ghostwriter who develops high-quality content for businesses. She is also a HubSpot Inbound Marketing Certified and Google Analytics Qualified Professional.