Search code examples
c#asp.net-coreasp.net-core-tag-helpers

Why is the TagHelper HtmlAttributeName not resolved in ASP.NET Core 2.2


I'm working on a custom TagHelper, for which I have used the example from Microsoft.

public class EmailTagHelper : TagHelper
{
    private const string EmailDomain = "contoso.com";

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

    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        output.TagName = "a";                                 // Replaces <email> with <a> tag
        var content = await output.GetChildContentAsync();
        var target = content.GetContent() + "@" + EmailDomain;
        output.Attributes.SetAttribute("href", "mailto:" + target);

        output.Content.SetContent(target);
    }
}

I have used it with these examples:

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

The first example works as expected and gives the following output:

<a href="mailto:[email protected]">[email protected]</a>

But the second example, where the mail-to HtmlAttributeName is used, it is not resolved, as shown below.

<a href="mailto:@contoso.com">@contoso.com</a>

This took me all afternoon by now, and I'm probably going to bang my head afterwards, but could someone tell me why this is not working?


Solution

  • You've declared MailTo and bound it to the mail-to attribute, but you don't use MailTo in ProcessAsync. Instead, you're always using the GetChildContentAsync() method to get the content.

    You'll need to make a decision about which takes precedence or whether you want to generate some kind of exception if both mail-to and content are provided, etc. Here's a rough example that prefers the attribute, for completeness:

    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        output.TagName = "a";
    
        var mailTo = MailTo;
    
        if (string.IsNullOrWhiteSpace(mailTo))
        {
            var content = await output.GetChildContentAsync();
            mailTo = content.GetContent();
        }
    
        var target = mailTo + "@" + EmailDomain;
        output.Attributes.SetAttribute("href", "mailto:" + target);
    
        output.Content.SetContent(target);
    }