liveBook · Manning

HtmlAttributeName

As explained in Pro ASP.NET Core 7, Tenth Edition

The HtmlAttributeName attribute is an ASP.NET Core attribute that assigns an HTML attribute name or prefix to a tag helper property.

HtmlAttributeName connects a tag helper property to an HTML attribute name or prefix. It lets Razor bind view attributes to deliberately named C# properties instead of relying only on automatic naming. section 8.1.2 section 25.2.1

For prefixed binding, decorate a dictionary-valued property with HtmlAttributeName and give it a prefix such as page-url-. Every element attribute beginning with that prefix is collected into the dictionary. section 8.1.2

The bound values can then participate directly in tag-helper behavior:

  • The tag helper passes the collected PageUrlValues dictionary to IUrlHelper.Action when generating href values. section 8.1.2
  • A view can preserve the current category with page-url-category="@Model.CurrentCategory!" without adding a separate property for every route value. section 8.1.2
  • The resulting pagination URLs retain category filters, so selecting another page does not return products from all categories. section 8.1.2

Custom names for tag-helper properties

Automatic conversion maps an HTML-style attribute such as bg-color to the C# property BgColor. HtmlAttributeName provides an escape hatch when that default name is unclear or undesirable; a tag helper can explicitly choose the HTML attribute represented by a property. Attribute prefixes cannot use asp- or data-. section 25.2.1

Listing 8.4 Prefixed values in the PageLinkTagHelper.cs file in the SportsStore/ Infrastructure folder
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using SportsStore.Models.ViewModels;

namespace SportsStore.Infrastructure {

    [HtmlTargetElement("div", Attributes = "page-model")]
    public class PageLinkTagHelper : TagHelper {
        private IUrlHelperFactory urlHelperFactory;
                
        public PageLinkTagHelper(IUrlHelperFactory helperFactory) {
            urlHelperFactory = helperFactory;
        }
                
        [ViewContext]
        [HtmlAttributeNotBound]
        public ViewContext? ViewContext { get; set; }
                
        public PagingInfo? PageModel { get; set; }
                
        public string? PageAction { get; set; }
                
        [HtmlAttributeName(DictionaryAttributePrefix = "page-url-")]
        public Dictionary<string, object> PageUrlValues { get; set; }
            = new Dictionary<string, object>();
                        
        public bool PageClassesEnabled { get; set; } = false;
        public string PageClass { get; set; } = String.Empty;
        public string PageClassNormal { get; set; } = String.Empty;
        public string PageClassSelected { get; set; } = String.Empty;
                
        public override void Process(TagHelperContext context,
                TagHelperOutput output) {
            if (ViewContext != null && PageModel != null) {
                IUrlHelper urlHelper 
                    = urlHelperFactory.GetUrlHelper(ViewContext);
                TagBuilder result = new TagBuilder("div");
                for (int i = 1; i <= PageModel.TotalPages; i++) {
                    TagBuilder tag = new TagBuilder("a");
                    PageUrlValues["productPage"] = i;
                    tag.Attributes["href"] = urlHelper.Action(PageAction, 
                        PageUrlValues);
                    if (PageClassesEnabled) {
                        tag.AddCssClass(PageClass);
                        tag.AddCssClass(i == PageModel.CurrentPage
                            ? PageClassSelected : PageClassNormal);
                    }
                    tag.InnerHtml.Append(i.ToString());
                    result.InnerHtml.AppendHtml(tag);
                }
                output.Content.AppendHtml(result.InnerHtml);
            }
        }
    }
}

Inspect the complete PageLinkTagHelper implementation to see HtmlAttributeName applied alongside route-value binding and URL generation. section 8.1.2

How Pro ASP.NET Core 7, Tenth Edition covers it

How deep it goes
Explains property naming and prefixed dictionary binding with application code, but defers framework internals.
Examples
Demonstrates page-url-category for pagination and bg-color/text-color for configuring generated table-row classes.
What it assumes
Assumes basic C# properties and ASP.NET Core tag helpers while demonstrating the attribute-binding convention through examples.
What you can do after
Build tag helpers that accept grouped route values or explicitly named HTML attributes.
How it connects
Connects tag helpers with Razor attribute binding, URL generation, routing, dictionaries, and tag-helper output.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Pro ASP.NET Core 7, Tenth Edition. The section links point to the parts of the book it draws on.