If I do the following:
@page "/mypage"
@inject NavigationManager NavigationManager
<button @onclick="ts">nav to a random fragment</button>
@code{
private void ts()
{
NavigationManager.NavigateTo($"/mypage#{Guid.NewGuid()}");
StateHasChanged();
Console.WriteLine(NavigationManager.Uri);
}
}
I expect to see a different Guid in both the browser URL bar and in the console every time I click the button. I actually see that the browser URL changes properly but the URL written to the console never does.
Why is NavigationManager.Uri seemingly blatantly wrong? What can I do to get the current URL after I've changed its fragment?
I also tried modifying ts() to the following, which didn't help.
private async Task ts()
{
NavigationManager.NavigateTo($"mypage#{Guid.NewGuid()}");
StateHasChanged();
await Task.Delay(1);
Console.WriteLine(NavigationManager.Uri);
}
On .NET 9; RenderMode is InteractiveWebAssembly.
If I do the following:
@page "/mypage"
@inject NavigationManager NavigationManager
<button @onclick="ts">nav to a random fragment</button>
@code{
private void ts()
{
NavigationManager.NavigateTo($"/mypage#{Guid.NewGuid()}");
StateHasChanged();
Console.WriteLine(NavigationManager.Uri);
}
}
I expect to see a different Guid in both the browser URL bar and in the console every time I click the button. I actually see that the browser URL changes properly but the URL written to the console never does.
Why is NavigationManager.Uri seemingly blatantly wrong? What can I do to get the current URL after I've changed its fragment?
I also tried modifying ts() to the following, which didn't help.
private async Task ts()
{
NavigationManager.NavigateTo($"mypage#{Guid.NewGuid()}");
StateHasChanged();
await Task.Delay(1);
Console.WriteLine(NavigationManager.Uri);
}
On .NET 9; RenderMode is InteractiveWebAssembly.
Share Improve this question edited Apr 1 at 13:05 Patrick Szalapski asked Mar 31 at 19:54 Patrick SzalapskiPatrick Szalapski 9,44812 gold badges82 silver badges153 bronze badges 2- I can't repro this exactly. I see the NavigationManager.Uri changing but 1 step behind. As always, specify Version(s) and RenderMode. – Henk Holterman Commented Apr 1 at 10:05
- Thanks, Henk. Did so. On .NET 9; RenderMode is InteractiveWebAssembly. – Patrick Szalapski Commented Apr 1 at 13:06
2 Answers
Reset to default 1Fragment changes (#...) do not trigger a full navigation event in Blazor. Then NavigationManager.Uri does not reflect the new fragment until another navigation event happens. You could use JS interop to get to current URL.
@page "/mypage"
@inject IJSRuntime JSRuntime
@inject NavigationManager NavigationManager
<button @onclick="ts">nav to a random fragment</button>
@code {
private async Task ts()
{
var newUrl = $"/mypage#{Guid.NewGuid()}";
NavigationManager.NavigateTo(newUrl);
var currentUrl = await JSRuntime.InvokeAsync<string>("eval", "window.location.href");
Console.WriteLine(currentUrl);
}
}
Your attempt with Task.Delay(1)
was close. But things have changed, a 1ms delay isn't enough anymore. I think that Delay() got more 'accurate', not rounding up the value. Or something.
This will basically work:
private async Task ts()
{
NavigationManager.NavigateTo($"mypage#{Guid.NewGuid()}");
StateHasChanged();
await Task.Delay(10); // adapt to taste ...
Console.WriteLine(NavigationManager.Uri);
}
It's all because the NavigationManager is updated on (after) a Render.
So the better, more reliable approach is to catch the value in OnAfterRender and build some change detecting logic there to use it.
You would then not need StateHasChanged() or Delay().