dotnet / dotnet/aspnetcore

Router incorrectly calls SetParametersAsync multiple times

Open
#44,781 26 comments 18 reactions 1 assignee Claimed by @oroztocil View on GitHub
area-blazor feature-routing investigate Pillar: Technical Debt triaged
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 10h
Merged PRs (30d)
281

Description

### Is there an existing issue for this?

- [X] 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"

```text
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.

```razor
@page "/index"
@page "/index/{id:int}"
@inject ILogger _logger

queryparam=def
/999

@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)

```razor
@inject IConfiguration Config







@code {
[Inject] NavigationManager NavigationManager { get; set; } = default!;
[Inject] AuthenticationStateProvider AuthenticationStateProvider { get; set; } = default!;
[Inject] ILogger 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

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.