Skip to content

Feature request: strongly-typed route values in a tag-helpers #35376

@dharmatech

Description

@dharmatech

The Issue

The example project from the Razor Pages with Entity Framework Core in ASP.NET Core - Tutorial includes the following code:

<a asp-page="./Index"
   asp-route-sortOrder="@Model.CurrentSort"
   asp-route-pageIndex="@(Model.Students.PageIndex + 1)"
   asp-route-currentFilter="@Model.CurrentFilter"
   class="btn btn-primary @nextDisabled">
    Next
</a>

Link to those lines in the project.

The route parameter names:

asp-route-sortOrder="@Model.CurrentSort"
asp-route-pageIndex="@(Model.Students.PageIndex + 1)"
asp-route-currentFilter="@Model.CurrentFilter"

are not strongly-typed. I.e. there could be a typo in any of the names (sortOrder, pageIndex, currentFilter) and the project will compile and run however the program will not function as expected.

Workaround - use LinkGenerator.GetPathByAction

This stackoverflow post discusses one workaround for the issue. The example there has the following a tag-helper:

    <a class="btn btn-block
       @(category == ViewBag.SelectedCategory 
           ? "btn-primary": "btn-outline-secondary")"
       asp-action="Index" asp-controller="Home"
       asp-route-category="@category"
       asp-route-productPage="1">
        @category
    </a>

It is rewritten in a more strongly-typed manner using LinkGenerator.GetPathByAction as follows:

<a class="btn btn-block @(category == ViewBag.SelectedCategory ? "btn-primary" : "btn-outline-secondary")"
   href="@(
    _linkGenerator.GetPathByAction(
        nameof(HomeController.Index), 
        Regex.Replace(nameof(HomeController), "Controller$", String.Empty),
        new IndexParameters() 
        { 
            Category = category, 
            ProductPage = 1 
        }))">
    @category
</a>

This is more of a demonstration of what is theoretically possible in the form of a quick solution; it's not ideal for end users.

Workaround - R4MVC

Another approach is to use R4MVC.

Here's a video demonstrating R4MVC.

Downsides to R4MVC:

  • Still in pre-release
  • Not built-in to ASP.NET Core

Workaround - object for parameters

If we use a class to represent the parameters to OnGetAsync:

public class OnGetAsyncParameters
{
    public SortOrder? SortOrder { get; set; }
    public string CurrentFilter { get; set; }
    public string SearchString { get; set; }
    public int? PageIndex { get; set; }
}

then instead of:

<a asp-page="./Index"
   asp-route-sortOrder="@Model.CurrentSort"
   asp-route-pageIndex="@(Model.Students.PageIndex + 1)"
   asp-route-currentFilter="@Model.CurrentFilter"
   class="btn btn-primary @nextDisabled">
    Next
</a>

we can use asp-all-route-data and generate a dictionary from an instance of OnGetAsyncParameters:

<a asp-page="./Index"
   asp-all-route-data="to_dict(new OnGetAsyncParameters()
    {
        SortOrder = Model.CurrentSort,
        PageIndex = Model.Students.PageIndex + 1,
        CurrentFilter = Model.CurrentFilter
    })"
   class="btn btn-primary @nextDisabled">
    Next
</a>

Link

where to_dict is the following utility function:

Dictionary<string, string> to_dict(object obj)
{
    return obj
        .GetType()
        .GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public)
        .ToDictionary(
            prop => prop.Name,
            prop =>
            {
                var val = prop.GetValue(obj, null);

                return val == null ? "" : val.ToString();
            });
}

In this case, OnGetAsync is updated to accept OnGetAsyncParameters:

public async Task OnGetAsync(OnGetAsyncParameters onGetAsyncParameters)

Link

Request

The request is for ASP.NET Core to have route parameters be more strongly-typed in a tag-helpers.

I understand that the priority may be low. I'd just like to request that it at least be on the roadmap. :-)

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-mvcIncludes: MVC, Actions and Controllers, Localization, CORS, most templatesenhancementThis issue represents an ask for new feature or an enhancement to an existing onefeature-mvc-razor-viewsFeatures related to the Razor view engine for Razor pages and MVC viewsfeature-routing

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions