Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Blazor optional route parameters

Tags:

blazor

Create new blazor project with dotnet new blazor. Modify Index.cshtml:

@page "/"
@page "/{Id}"

<h1>Id = @Id</h1>

<p><a href="/">Without Id</a></p>
<p><a href="/15">With Id = 15</a></p>

@functions {
    [Parameter]
    public string Id { get; set; }
}

Run application.

When I click With Id = 15 link, everything works as expected - url has changed, parameter {Id} is assigned to value Id, all good.

But when I click Without Id link after that, url has changed, but my Id stays the same - equal 15.

Why my value didn't change? What am I missing here? How can I fix this?

like image 478
Peska Avatar asked Apr 17 '19 17:04

Peska


People also ask

How do you pass parameters in Blazor?

By using Blazor route parameters, you can pass values from one page to another page. Use NavigationManager to pass a value and route the parameter to another page. Follow this example to achieve passing values from one page to another. Get the passed Page1 parameter value in Page2.

How do you pass multiple parameters in Blazor?

The easiest way is to use Route parameters instead of QueryString: @page "/navigatetopage/{id:int}/{key}" @code { [Parameter] public int Id{get;set;} [Parameter] public string Key{get;set;} ... }

What is NavigationManager in Blazor?

Access to browser navigation from Blazor is provided via the NavigationManager service. This can be injected into a Blazor component using @inject in a razor file, or the [Inject] attribute in a CS file. The NavigationManager service has two members that are of particular interest; NavigateTo and LocationChanged .

How do I navigate to another page in Blazor?

You can redirect to a page in Blazor using the Navigation Manager's NavigateTo method. In the following code snippet, it will redirect to the home page when this page gets loaded. Similarly, you can call NavigateTo() method from NavigationManager class anywhere to redirect to another page.


3 Answers

Optional route parameters are supported as of ASP.NET Core 5.0.

For example:

@page "/RouteParameter/{text?}"

<h1>Blazor is @Text!</h1>

@code {
    [Parameter]
    public string Text { get; set; }

    protected override void OnInitialized()
    {
        Text = Text ?? "fantastic";
    }
}
like image 147
DharmaTurtle Avatar answered Nov 25 '22 16:11

DharmaTurtle


This behavior is by design. Note that a changed url does not imply that the current page has changed. The following JavaScript function performs the internal navigation which changes the url:

function performInternalNavigation(absoluteInternalHref: string) {
  history.pushState(null, /* ignored title */ '', absoluteInternalHref);
  handleInternalNavigation();
} 

Source: https://github.com/aspnet/AspNetCore/blob/93127b39e824181d4f9b1a62b6fc8d10c481e2c8/src/Components/src/Microsoft.AspNetCore.Components.Browser.JS/src/Services/UriHelper.ts

Calling history.pushState causes the URL bar to display ".../15", but won't cause the browser to load the new url, or rather cause Blazor to recreate the Index component. Blazor does not recreate a component if only the URL parameters change. Since you are already on the Index page, clicking on the link "Without Id", does not cause the Index Component to re-render. The current Component instance is reused instead, but alas this instance component has its parameter property set to the value of 15, and it is not overwritten by the AssignToProperties method which "Iterates through the ParameterCollection, assigning each parameter to a property of the same name on target." But the ParameterCollection does not contain an Id parameter; recall that this occurs after you hit the "Without Id". The end result, again, is having the parameter property Id containing the value 15. Source: https://github.com/aspnet/Blazor/blob/29f925852b0a5e81e82780e0c1c32b486f7c3be6/src/Microsoft.AspNetCore.Blazor/Components/ParameterCollectionExtensions.cs

Workarounds to solve this issue:

  1. Override the SetParameters method like this:
public override void SetParameters(ParameterCollection parameters)
{
   if (string.IsNullOrEmpty(parameters.GetValueOrDefault<string>("Id")))
   {
      Id = null;
   }
   base.SetParameters(parameters);
}
  1. Implement custom routing logic by subclassing Router

Hope this helps...

like image 26
enet Avatar answered Nov 25 '22 16:11

enet


Try this

@page "/"
@page "/{Id:string}"

<h1>Id = @Id</h1>

<p><NavLink href="/">Without Id</NavLink></p>
<p><NavLink href="/15">With Id = 15</NavLink></p>

@code{
  [Parameter]
  public string Id {get;set;}
}

I hope your problem is solved

like image 28
hosein azimi Avatar answered Nov 25 '22 15:11

hosein azimi