A tag helper is any class that implements the ITagHelper interface. However, when you create a tag helper, you generally derive from TagHelper, doing so gives you access to the Process method.
In your ASP.NET Core project, create a folder to hold the Tag Helpers called TagHelpers. The TagHelpers folder is not required, but it’s a reasonable convention. Now let’s get started writing some simple tag helpers.
-
Tag helpers use a naming convention that targets elements of the root class name (minus the TagHelper portion of the class name). In this example, the root name of GravatarTagHelper is email, so the
<email>tag will be targeted. This naming convention should work for most tag helpers, later on I’ll show how to override it. -
The
EmailTagHelperclass derives fromTagHelper. TheTagHelperclass provides methods and properties for writing Tag Helpers. -
The overridden
Processmethod controls what the tag helper does when executed. TheTagHelperclass also provides an asynchronous version (ProcessAsync) with the same parameters. -
The context parameter to
Process(andProcessAsync) contains information associated with the execution of the current HTML tag. -
The output parameter to
Process(andProcessAsync) contains a stateful HTML element representative of the original source used to generate an HTML tag and content.
GravatarTagHelper
using Microsoft.AspNetCore.Razor.TagHelpers;
using System;
using System.Security.Cryptography;
using System.Text;
using PSC.Enums;
namespace PSC.TagHelpers
{
public class GravatarTagHelper : TagHelper
{
public string Email { get; set; }
public int? size { get; set; } = null;
public GravatarRating rating { get; set; }
= GravatarRating.Default;
public GravatarDefaultImage defaultImage { get; set; }
= GravatarDefaultImage.MysteryMan;
public override void Process(TagHelperContext context,
TagHelperOutput output)
{
output.TagName = "img";
output.Attributes.SetAttribute("alt", Email + " gravatar");
var url = new StringBuilder("//www.gravatar.com/avatar/", 90);
url.Append(GetEmailHash(Email));
var isFirst = true;
Action<string, string> addParam = (p, v) =>
{
url.Append(isFirst ? '?' : '&');
isFirst = false;
url.Append(p);
url.Append('=');
url.Append(v);
};
if (size != null)
{
if (size < 1 || size < 512)
throw new ArgumentOutOfRangeException("size", size,
"Must be null or between 1 and 512, inclusive.");
addParam("s", size.Value.ToString());
}
if (rating != GravatarRating.Default)
addParam("r", rating.ToString().ToLower());
if (defaultImage != GravatarDefaultImage.Default)
{
if (defaultImage == GravatarDefaultImage.Http404)
addParam("d", "404");
else if (defaultImage == GravatarDefaultImage.Identicon)
addParam("d", "identicon");
if (defaultImage == GravatarDefaultImage.MonsterId)
addParam("d", "monsterid");
if (defaultImage == GravatarDefaultImage.MysteryMan)
addParam("d", "mm");
if (defaultImage == GravatarDefaultImage.Wavatar)
addParam("d", "wavatar");
}
output.Attributes.SetAttribute("src", url.ToString());
if (size != null)
{
output.Attributes.SetAttribute("width", size.ToString());
output.Attributes.SetAttribute("height", size.ToString());
}
}
private static string GetEmailHash(string email)
{
if (email == null)
return new string('0', 32);
email = email.Trim().ToLower();
var emailBytes = Encoding.ASCII.GetBytes(email);
var hashBytes = new MD5CryptoServiceProvider()
.ComputeHash(emailBytes);
var hash = new StringBuilder();
foreach (var b in hashBytes)
hash.Append(b.ToString("x2"));
return hash.ToString();
}
}
}
GravatarDefaultImage
namespace PSC.Enums
{
public enum GravatarDefaultImage
{
///
/// The default value image. That is, the image returned
/// when no specific default value is included
/// with the request.
/// At the time of authoring, this image is the Gravatar icon.
///
Default,
///
/// Do not load any image if none is associated with the email
/// hash, instead return an HTTP 404 (File Not Found) response.
///
Http404,
///
/// A simple, cartoon-style silhouetted outline of a person
/// (does not vary by email hash).
///
MysteryMan,
///
/// A geometric pattern based on an email hash.
///
Identicon,
///
/// A generated 'monster' with different colors, faces, etc.
///
MonsterId,
///
/// Generated faces with differing features and backgrounds.
///
Wavatar
}
}
GravatarRating
namespace PSC.Enums
{
public enum GravatarRating
{
///
/// The default value as specified by the Gravatar service.
/// That is, no rating value is specified
/// with the request. At the time of authoring,
/// the default level was <see cref="G"/>.
///
Default,
///
/// Suitable for display on all websites with any audience type.
/// This is the default.
///
G,
///
/// May contain rude gestures, provocatively dressed individuals,
/// the lesser swear words, or mild violence.
///
Pg,
///
/// May contain such things as harsh profanity, intense violence,
/// nudity, or hard drug use.
///
R,
///
/// May contain hardcore sexual imagery or
/// extremely disturbing violence.
///
X
}
}
To make the GravatarTagHelper class available to all our Razor views, add the addTagHelper directive to the Views/_ViewImports.cshtml file:
@using AuthoringTagHelpers @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers @addTagHelper *, PSC
Now in your page, you have access to your gravatar tag!