GregH
GregH

Reputation: 5459

Multiple query string parameters in Blazor routing

I have multiple working examples in my current project of retrieving 1 query parameter from the url however when trying to follow the same convention for multiple url params, I'm receiving the following error in the chrome debugger console:

Error: System.InvalidOperationException: 'Router' cannot find any component with a route for '/confirmemail'.

my page route is defined as:

@page "/confirmemail/{Token}/{UserId}"

and the @functions{...} section contains the following properties:

[Parameter]
string Token { get; set; }
[Parameter]
string UserId { get; set; }

I am trying to retrieve the query string parameters for a url that looks like this:

http://localhost:50466/confirmemail?Token=SomeReallyLargeToken&UserId=SomeGuidUserId

How can I achieve this?

Upvotes: 13

Views: 19384

Answers (5)

Eugene Shmakov
Eugene Shmakov

Reputation: 1012

Could you try?

http://localhost:50466/confirmemail/SomeReallyLargeToken/SomeGuidUserId

I think it should work.

Upvotes: 5

Dirk Brockhaus
Dirk Brockhaus

Reputation: 5062

A new answer to an old question: At the time of January 2022, query string parameters can be processed with the complementary attribute SupplyParameterFromQuery.

[Parameter] [SupplyParameterFromQuery]
public string Token { get; set; }
[Parameter] [SupplyParameterFromQuery]
public string UserId { get; set; }

Upvotes: 18

Francesco
Francesco

Reputation: 2042

I suggest to use the extension method presented here:

https://chrissainty.com/working-with-query-strings-in-blazor/

I just put more types:

public static class NavigationManagerExtensions
{
    public static bool TryGetQueryString<T>(this NavigationManager navManager, string key, out T value)
    {
        var uri = navManager.ToAbsoluteUri(navManager.Uri);

        if (QueryHelpers.ParseQuery(uri.Query).TryGetValue(key, out var valueFromQueryString))
        {
            if (typeof(T) == typeof(int) && int.TryParse(valueFromQueryString, out var valueAsInt))
            {
                value = (T)(object)valueAsInt;
                return true;
            }

            if (typeof(T) == typeof(int?) && int.TryParse(valueFromQueryString, out var valueAsNullableInt))
            {
                value = (T)(object)valueAsNullableInt;
                return true;
            }

            if (typeof(T) == typeof(bool) && bool.TryParse(valueFromQueryString, out var valueAsBool))
            {
                value = (T)(object)valueAsBool;
                return true;
            }

            if (typeof(T) == typeof(bool?) && bool.TryParse(valueFromQueryString, out var valueAsNullableBool))
            {
                value = (T)(object)valueAsNullableBool;
                return true;
            }

            if (typeof(T) == typeof(string))
            {
                value = (T)(object)valueFromQueryString.ToString();
                return true;
            }

            if (typeof(T) == typeof(decimal) && decimal.TryParse(valueFromQueryString, out var valueAsDecimal))
            {
                value = (T)(object)valueAsDecimal;
                return true;
            }

            if (typeof(T) == typeof(decimal?) && decimal.TryParse(valueFromQueryString, out var valueAsNullableDecimal))
            {
                value = (T)(object)valueAsNullableDecimal;
                return true;
            }

        }

        value = default;
        return false;
    }
}

regarding the: "Dealing with updates to query string values" part... I did like so:

<a class="dropdown-item" @onclick='() => GotoLink("thepage?intValue=0&boolValue=true&stringValue=blahBlah")'>goGoGo</a>

and the GotoLink method is this:

private void GotoLink(string url)
{
    NavManager.NavigateTo(url, forceLoad: true);
}

by the way the route of the component is cleaner:

@page "/ThePage"

Upvotes: 0

Antonio Correia
Antonio Correia

Reputation: 1091

For anyone interested in how to pass and get the parameters in the query string style

http://localhost:50466/confirmemail?Token=SomeReallyLargeToken&UserId=SomeGuidUserId

the page route doesn't change

@page "/confirmemail/"

and you should get the parameters like

protected override void OnInitialized()
{
     var uri = navigationManager.ToAbsoluteUri(navigationManager.Uri); //you can use IURIHelper for older versions

     if(QueryHelpers.ParseQuery(uri.Query).TryGetValue("Token", out var token))
     {
         var token_par = token.First();
     }

     if(QueryHelpers.ParseQuery(uri.Query).TryGetValue("UserId", out var userid))
     {
         var userid_par = userid.First();
     }
}

Remember to add the following

@inject NavigationManager navigationManager
@using Microsoft.AspNetCore.WebUtilities @*for QueryHelpers*@

I'm using preview-9

Upvotes: 29

enet
enet

Reputation: 45704

This ( /{Token}/{UserId} ) is not a pattern of query string. It is a part of the route template url(route parameters). This is a query string: ?Token=SomeReallyLargeToken&UserId=SomeGuidUserId.

I'm not sure about it, right now, but this may work: http://localhost:50466/confirmemail/SomeReallyLargeToken/SomeGuidUserId

If you wish to access query parameters (not route parameters), you want to use the IUriHelper like this:

var uri = new Uri(UriHelper.GetAbsoluteUri());

Note that you should parse the returned value... I once saw a utility created by the Blazor community that does it.

Hope this helps...

Upvotes: 2

Related Questions