Append QueryString to href in asp.net core Anchor Helper Tag
Asked Answered
A

2

10

I am trying to add anything in the query of the request to anchors in the html result:

Fictitious example:

User makes a request (note that band and song could be anything, I have a route catering this request: template: "{band}/{song}"):

http://mydomain/band/song?Param1=111&Param2=222

Now I want my anchors to append the query string part to the href of my anchors. So I tried something like this (note the 'asp-all-route-data'):

<a asp-controller="topic" asp-action="topic" asp-route-band="iron-maiden" asp-route-song="run-to-the-hills" asp-all-route-data="@Context.Request.Query.ToDictionary(d=>d.Key,d=>d.Value.ToString())">Iron Maiden - Run to the hills</a>

The append of the query string actually works with the above code but then the "iron-maiden" and "run-to-the-hills" are lost in the result. The above tag helper returns the following (note how the helper mirrors the band and song in the request into the href and not the band and song I specified in the asp-route attributes):

<a href="http://mydomain/band/song?Param1=111&Param2=2222">Iron Maiden - Run to the hills</a>

I expect the following result from the helper:

<a href="http://mydomain/iron-maiden/run-to-the-hills?Param1=111&Param2=2222">Iron Maiden - Run to the hills</a>

It seems like when I use the asp-all-route-data I loose the asp-route-band and asp-route-song values in the result.

Has anybody ever stumbled across this?

Thanks

Hooroo

Anticipative answered 5/4, 2017 at 11:20 Comment(1)
There doesn't seem to be any official way, but I may have an idea for a workaround though, but first: Does the @Context.GetRouteData().Values work? GetRouteData gets the routes from the routing middleware as key value pairs and should also contain query parameters. Not sure if it works in your case and if asp-route-band & asp-route-song are hardcoded or take from route in your caseLeuco
L
10

There doesn't seem to be any official way to do this yet.

If the @Context.GetRouteData().Values works you should use it instead. The idea behind it is, that GetRouteData gets the current route information from the routing middleware as key value pairs (Dictionary) which should also contain query parameters.

I am not sure if it works in your case and if asp-route-band & asp-route-song are hard-coded or taken from route in your case.

In case that may not work, you could try the following extension method & class:

public static class QueryParamsExtensions
{
    public static QueryParameters GetQueryParameters(this HttpContext context)
    {
        var dictionary = context.Request.Query.ToDictionary(d => d.Key, d => d.Value.ToString());
        return new QueryParameters(dictionary);
    }
}

public class QueryParameters : Dictionary<string, string>
{
    public QueryParameters() : base() { }
    public QueryParameters(int capacity) : base(capacity) { }
    public QueryParameters(IDictionary<string, string> dictionary) : base(dictionary) { }

    public QueryParameters WithRoute(string routeParam, string routeValue)
    {
        this[routeParam] = routeValue;

        return this;
    }
}

It basically abstracts your code from above behind a extension method and returns a QueryParameters type (which is an extended Dictionary<string,string>) with a single additional method for pure convenience, so you can chain multiple .WithRoute calls, since Add method of dictionary has a void return type.

You'd be calling it from your View like this

<a  asp-controller="topic"
    asp-action="topic" 
    asp-all-route-data="@Context.GetQueryParameters().WithRoute("band", "iron-maiden").WithRoute("song", "run-to-the-hills");"
>
    Iron Maiden - Run to the hills
</a>
Leuco answered 5/4, 2017 at 12:59 Comment(3)
Hey, thanks for that. Very elegant solution. I did make a small change in the WithRoute method:if (this.ContainsKey(routeParam)) this[routeParam] = routeValue; else Add(routeParam, routeValue);Anticipative
Oh btw. @Context.GetRouteData().Values does not contain any query parametersAnticipative
I had to add a check to prevent duplicate keys to WithRoute() method: if(!ContainsKey(routeParam))Zamboanga
C
0

If you have custom route parameters in your route table like these

asp-route-band="iron-maiden" asp-route-song="run-to-the-hills"
asp-all-route-data="@Context.Request.Query.ToDictionary(d=>d.Key,d=>d.Value.ToString())"

And after using "asp-all-route-data" to save query parameters your custom parameters are removed, just move your parameters after "asp-all-route-data" and everything will be as you expect

asp-all-route-data="@Context.Request.Query.ToDictionary(d=>d.Key,d=>d.Value.ToString()) asp-route-band="iron-maiden" asp-route-song="run-to-the-hills"

This will return the link you expect

<a href="http://mydomain/iron-maiden/run-to-the-hills?Param1=111&Param2=2222">Iron Maiden - Run to the hills</a>
Charlettecharley answered 31/7, 2022 at 20:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.