Search code examples
razorasp.net-core-mvc.net-coreasp.net-core-mvc-2.0

asp-route-{value} tag helper not respecting route template


I'm working on a breadcrumb implementation in .net core 2.0,

The requirement is to be able to create a hierarchical menu, where the previous bread crumb item will take to the parent and so on...

the implementation is based on a bread crumb ViewComponent model, which reads the current route data and embeds the params as part of the breadcrumb links as tag helpers (asp-route-{value})

Problems:

I have 2 problems:

  1. The ViewContext.RouteData.Values in the Razor View for the breadcrumb Component does not contain the key "id" thats supposed to get passed as query string parameter
  2. Even if I hard code the above for testing purpose, injecting it back into the anchor tab in Razor view using asp-route-id - doesn't inject it as query string parameter at the end of the action but inserts it as "{controller}/{action}/{id}" after the action

Here's the URL from the browser:

http://127.0.0.1:5100/XXX/Service/{item_id}/Hardware/UpdateOrder?orderId={order_id}

for the previous breadcrumb, it should generate

 http://127.0.0.1:5100/XXX/Service/{item_id}/Hardware/Detail?orderId={order_id}

the Id's are GUID

The Route template in Startup.asp

routes.MapRoute(
                    name: "areaRouteWithWholesaleCustomerCodeAndTargetId",
                    template: "{wholesaleCustomerCode}/{area:exists}/{baseItemId:guid}/{controller=Home}/{action=Index}/{id:guid?}"
                );

The Breadcrumb ViewComponent Razor View:

@model BreadcrumbModel
<ul class="list-unstyled breadcrumbs" id="breadcrumbs">
    @{
        var baseItemId = ViewContext.RouteData.Values["baseItemId"] ?? "";
        var id = ViewContext.HttpContext.Request.QueryString.Value ?? "";
        id = "orderid=testid-123";
    }
    @foreach(var li in Model.Breadcrumb)
    {
        <li>
            <a asp-area="@li.AreaName" asp-controller="@li.ControllerName" asp-action="@li.ActionName" class="@li.Class" asp-route-baseItemId="@baseItemId" asp-route-id="@id">
            @li.DisplayName
            </a>
        </li>
    }
</ul>

Data Available in ViewContext.RouteData - note that there's no id being passed as part of the route data -

enter image description here

ViewContext.HttpContext.Request.QueryString value:

enter image description here

Using the asp-route-{value} tag helper I'm injecting 2 id's into the anchor tag, baseItemId which is part of the route mapping and id - which is also part of the route mapping but as query string

when the menu is rendered this is what I get at the breadcrumb :

<a class="" href="/XXX/Service/Hardware/Detail/orderid%3DtestId-123?baseItemId=09185d87-5e3f">
            Hardware
            </a>

somehow, it isn't respecting the route template at all

I expected it to render it as follows:

Hardware

Expected Behavior:

I would have expected it to work as follows:

  1. I should be able to get the value "id" from route values, rather than relying on query string parameters
  2. on injecting the 2 id's based on the documentation, they should appear at their respective positions as defined in the routing template, baseItemId first as part of the route - then id as a query string part of the last action

Any Suggestions or insights into this ?


Solution

  • It's doing exactly what you're telling it to do. You're setting the id to the query string or simply orderId=test123. As a result, it's cramming that string into the id part of the route (while escaping the = sign, since it's invalid in that portion of the URI). What you should be doing instead, if you want the orderId as part of the query string, is to pass that as a route param: asp-route-orderId="@orderId".

    As far as your baseItemId not going into the route goes, there's most likely another route that's being matched, which doesn't include this param. Routing short-circuits, so it will always choose the least specific route it can match, and then just dump anything else it doesn't need as the query string. You should either change the order of your routes or use a custom named route instead, to remove ambiguity.

    If that's not the issue, the only other possibility is that the guid constraint on baseItemId is somehow not being satisfied by what you're passing for that param.