The Anchor tag helper

The anchor tag helper targets the HTML anchor (<a>) tag which is used to generate relative links from the values passed to various custom attributes. It can also used to generate absolute URLs to external resources.

The anchor tag helper's role is to generate an href attribute from the parameter values passed to its custom attributes. Therefore, if you try to add an href attribute to the anchor tag helper as well as values to the custom attributes, an exception will be raised:

InvalidOperationException: Cannot override the 'href' attribute for <a>. An <a> with a specified 'href' must not have attributes starting with 'asp-route-' or an 'asp-action', 'asp-controller', 'asp-area', 'asp-route', 'asp-protocol', 'asp-host', 'asp-fragment', 'asp-page' or 'asp-page-handler' attribute.

If a route cannot be matched from the values passed to the taghelper attributes, the output for the href attribute will silently fall back to an empty string.

Attribute Description
action The name of the action method on an MVC controller
all-route-data1 Multiple route parameter values
area The name of the Area
controller The name of the MVC controller
fragment2 The fragment in the URL
host The domain
page3 The Razor page to link to
page-handler4 The Razor page handler method to invoke
protocol The protocol (http, https, ftp etc)
route5 The name of the route
route-6 A single route parameter value

Notes

  1. If the target URL includes multiple route parameters, their values can be packaged as a Dictionary<string, string> and passed to the all-route-data parameter:

    @{   
        var d = new Dictionary<string, string>
            {
               { "key1", "value1" },
               { "key2", "value2" }
            };
    }
    
    <a asp-all-route-data="d">Click</a>
    

    If the route has parameters defined, the anchor tag helper will output the values as URL segments: <a href="/Page/value1/value2">Click</a>. If it doesn't, the route parameters will be appended to the URL as query string values: <a href="/Page?key1=value1&amp;key2=value2">Click</a>.

  2. The fragment is the value after a hash or pound sign (#) in a URL used to identify a named portion of a document. The "Notes" heading above has an identity value of "notes" and can be referenced in a URL using the anchor tag helper like this:

    <a asp-fragment="notes">Click</a>
    

    producing this HTML: <a href="/Page#notes">Click</a>

  3. The path to the target Razor page must be provided without the file extension. The leading / specifies an absolute path. If you omit it, the framework looks for a page relative to the current one:

    <a asp-page="/page">Click</a>
    

    If no valid page name is specified, the tag helper will render the href attribute with an empty string. If you want to generate a link to the default page in a folder, you must still include the default page's file name:

    <a asp-page="/folder/index">Folder</a>
    

    This renders as <a href="/folder">Folder</a>
    The tag helper will generate an href attribute whose value will be taken from the route template of the specified page.

  4. The page handler method name will appear as a query string value unless it has been included as a route parameter for the target page.

  5. Razor pages doesn't support named routes. This parameter will only be used for MVC routes.

  6. The route- attribute enables you to specify the value for a single route data parameter. The parameter name is added after the hyphen. Here, the route parameter name is "key1":
    <a asp-route-key1="value1">Click</a>
    This renders as
    <a href="/Page/value1">Click</a>
    if the key1 parameter is defined as part of the page's route template, or
    <a href="/Page?key1=value1">Click</a>
    if not.

Route values specified using the singular route- attribute and the multiple all-route-data attribute are additive.

### Ambient Route Values 

Route Data values for the current request are considered _ambient_ values in ASP.NET Core 2.1 and earlier*. This means that they do not necessarily need to be specified when generating links from the current page to another that requires the same Route Data value. For example, you may provide a page that shows the details of an order that has an `id` as a route data parameter: `"{id:int}"`. 

Within the Details age, you want to provide a link to an Edit page, which also accepts a route data parameter named id. There is no need to specify the asp-route-id attribute to the anchor tag helper because the ambient value from the current request context will be used by default. Therefore the following is sufficient to generate a link to /edit/3:

`<a asp-page="edit">Edit</a>`

In this case, you only need to specify a value for `asp-route-*` if you want to override the ambient value. 

If you override an ambient value by explicitly providing a value, all subsequent ambient values will be ignored. The template `"{pageno=1}/{sortby=Id}"` specifies two parameters, each with a default value. If you override the `pageno` value e.g. `<a asp-page="list" asp-route-pageno="2">2</a>`, the `sortby` value is omitted from the generated URL (along with any subsequent parameters) so that the generated URL is `list/2`. However, if you override the `sortby` value, the `pageno` value is retained (along with any other previous parameters).

***Note:** This behaviour changed in ASP.NET Core 2.2. Ambient route values are no longer reused when the destination page is different to the source page.

Routing Options

The anchor tag helper will generate URLs with the page name capitalised when you pass a value to the page attribute e.g.

<a asp-page="page">Click</a>

becomes

<a href="/Page">Click</a>

You can configure RouteOptions if you prefer the generated URL to be all lower case:

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();
    services.Configure<RouteOptions>(options =>
    {
        options.LowercaseUrls = true;
    });
}
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.Configure<RouteOptions>(options =>
    {
        options.LowercaseUrls = true;
    });
}

Another option, AppendTrailingSlash will result in a trailing slash being appended to the page name in every case:

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();
    services.Configure<RouteOptions>(options =>
    {
        options.AppendTrailingSlash = true;
    });
}
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.Configure<RouteOptions>(options =>
    {
        options.AppendTrailingSlash = true;
    });
}

With both options enabled, the resulting HTML looks like this:

<a href="/page/">Click</a>
Last updated: 10/24/2022 4:46:11 PM

© 2018 - 2024 - Mike Brind.
All rights reserved.
Contact me at Mike dot Brind at Outlook.com