Skip to content

Router incorrectly calls SetParametersAsync multiple times #44781

@Liero

Description

@Liero

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

WHEN I'm on /index?queryparam=abc and I click a link to /index/999 which is handled by the same component,

THEN SetParametersAsync is called twice:

  1. With QueryParam=null
  2. With Id=999, QueryParam="abc"
      OnNavigateAsync to 'index?queryparam=abc'
      SetParametersAsync Id:0, QueryParam:abc

      OnNavigateAsync to 'index/999'
      SetParametersAsync Id:0, QueryParam:
      SetParametersAsync Id:999, QueryParam:

This is causing a lot of issue when trying to load data based on parameters.

@page "/index"
@page "/index/{id:int}"
@inject ILogger<Index> _logger

<a href="/index?queryparam=abc">queryparam=def</a>
<a href="/index/999">/999</a>

@code {
    [Parameter] public int Id { get; set; }
    [Parameter, SupplyParameterFromQuery(Name = "queryparam")] public string? QueryParamProperty { get; set; }

    public override async Task SetParametersAsync(ParameterView parameters)
    {
        await base.SetParametersAsync(parameters);
        _logger.LogInformation($"SetParametersAsync Id:{Id}, QueryParam:{QueryParamProperty}");
    }
}

This only happens under specific circumstances:

  1. App must have authorization enabled
  2. there is OnNavigateAsync handler on the Router
  3. there is CascadingAuthenticationState on top of the Router (default in blazor template)
@inject IConfiguration Config
<CascadingAuthenticationState>
<Router AppAssembly="@typeof(Program).Assembly" OnNavigateAsync="OnNavigateAsyncHandler">
    <Found Context="routeData">
        <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
        </AuthorizeRouteView>
        <FocusOnNavigate RouteData="@routeData" Selector="[data-action=search]" />
    </Found>
    <NotFound>
    </NotFound>

</Router>
</CascadingAuthenticationState>
@code {
    [Inject] NavigationManager NavigationManager { get; set; } = default!;
    [Inject] AuthenticationStateProvider AuthenticationStateProvider { get; set; } = default!;
    [Inject] ILogger<App> Logger { get; set; } = default!;

    
    protected override async Task OnInitializedAsync()
    {
        ClaimsPrincipal user = (await AuthenticationStateProvider.GetAuthenticationStateAsync()).User;
        await Task.Delay(100);

        await base.OnInitializedAsync();
    }

    void OnNavigateAsyncHandler(NavigationContext context)
    {
        Logger.LogInformation("OnNavigateAsync to '{Path}'", context.Path);
    }
}

Expected Behavior

SetParametersAsync should be called only once per single navigation event

Steps To Reproduce

  1. Download reproducible demo: https://1drv.ms/u/s!An7wnk66a6RRlrI7ETRR9LsXHi2cmg?e=FsLOC2
  2. Start using Visual Studio
  3. Register new user (it uses lndividualAccounts authorization)
  4. Login
  5. Navigate to /index?queryparam=abc
  6. Click the /999 link
  7. Check the console/debug logs

Exceptions (if any)

No response

.NET Version

6.0.400

Anything else?

.NET SDK (reflecting any global.json):
Version: 6.0.400
Commit: 7771abd614

Runtime Environment:
OS Name: Windows
OS Version: 10.0.22000
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\6.0.400\

global.json file:
Not found

Host:
Version: 6.0.8
Architecture: x64
Commit: 55fb7ef977

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions