Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions src/Components/Components/src/Routing/Router.cs
Original file line number Diff line number Diff line change
Expand Up @@ -220,17 +220,20 @@ private void ClearRouteCaches()

internal virtual void Refresh(bool isNavigationIntercepted)
{
// endpointRouterData is populated only in navigations that passed through SSR, including re-executions
var endpointRouteData = RoutingStateProvider?.RouteData;

// If an `OnNavigateAsync` task is currently in progress, then wait
// for it to complete before rendering. Note: because _previousOnNavigateTask
// is initialized to a CompletedTask on initialization, this will still
// allow first-render to complete successfully.
if (_previousOnNavigateTask.Status != TaskStatus.RanToCompletion)
if (_previousOnNavigateTask.Status != TaskStatus.RanToCompletion && endpointRouteData is null)
{
if (Navigating != null)
{
_renderHandle.Render(Navigating);
return;
}
return;
}

var relativePath = NavigationManager.ToBaseRelativePath(_locationAbsolute.AsSpan());
Expand All @@ -239,7 +242,7 @@ internal virtual void Refresh(bool isNavigationIntercepted)
ComponentsActivityHandle activityHandle;

// In order to avoid routing twice we check for RouteData
if (RoutingStateProvider?.RouteData is { } endpointRouteData)
if (endpointRouteData is not null)
{
activityHandle = RecordDiagnostics(endpointRouteData.PageType.FullName, endpointRouteData.Template);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Net.Http;
using System;
using Components.TestServer.RazorComponents;
using Microsoft.AspNetCore.Components.E2ETest;
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure;
Expand Down Expand Up @@ -125,6 +126,25 @@ public void BrowserNavigationToNotExistingPath_ReExecutesTo404(bool streaming)
AssertReExecutionPageRendered();
}

[Fact]
public void BrowserNavigationToNotExistingPath_WithOnNavigateAsync_ReExecutesTo404()
{
AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.DisableThrowNavigationException", isEnabled: true);

// using query for controlling router parameters does not work in re-execution scenario, we have to rely on other communication channel
const string useOnNavigateAsyncSwitch = "Components.TestServer.RazorComponents.UseOnNavigateAsync";
AppContext.SetSwitch(useOnNavigateAsyncSwitch, true);
try
{
Navigate($"{ServerPathBase}/reexecution/not-existing-page");
AssertReExecutionPageRendered();
}
finally
{
AppContext.SetSwitch(useOnNavigateAsyncSwitch, false);
}
}

private void AssertReExecutionPageRendered() =>
Browser.Equal("Welcome On Page Re-executed After Not Found Event", () => Browser.Exists(By.Id("test-info")).Text);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
@using Components.WasmMinimal.Pages.NotFound
@using TestContentPackage.NotFound
@using Components.TestServer.RazorComponents
@using Microsoft.AspNetCore.Components
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using System.Threading.Tasks

@code {
[Parameter]
Expand All @@ -17,8 +21,14 @@
[SupplyParameterFromQuery(Name = "appSetsEventArgsPath")]
public bool AppSetsEventArgsPath { get; set; }

[Parameter]
[SupplyParameterFromQuery(Name = "useOnNavigateAsync")]
public string? UseOnNavigateAsync { get; set; }

private Type? NotFoundPageType { get; set; }
private NavigationManager _navigationManager = default!;
private bool ShouldDelayOnNavigateAsync
=> bool.TryParse(UseOnNavigateAsync, out var result) && result;

[Inject]
private NavigationManager NavigationManager
Expand Down Expand Up @@ -70,6 +80,21 @@
_navigationManager.OnNotFound -= OnNotFoundEvent;
}
}

private Task HandleOnNavigateAsync(NavigationContext args)
{
if (!ShouldDelayOnNavigateAsync)
{
return Task.CompletedTask;
}

return PerformOnNavigateAsyncWork();
}

private async Task PerformOnNavigateAsyncWork()
{
await Task.Yield();
}
}

<!DOCTYPE html>
Expand All @@ -93,7 +118,7 @@
{
@if (NotFoundPageType is not null)
{
<Router AppAssembly="@typeof(App).Assembly" AdditionalAssemblies="new[] { typeof(TestContentPackage.NotFound.NotFoundPage).Assembly }" NotFoundPage="NotFoundPageType">
<Router AppAssembly="@typeof(App).Assembly" AdditionalAssemblies="new[] { typeof(TestContentPackage.NotFound.NotFoundPage).Assembly }" NotFoundPage="NotFoundPageType" OnNavigateAsync="HandleOnNavigateAsync">
<Found Context="routeData">
<RouteView RouteData="@routeData" />
<FocusOnNavigate RouteData="@routeData" Selector="[data-focus-on-navigate]" />
Expand All @@ -102,7 +127,7 @@
}
else
{
<Router AppAssembly="@typeof(App).Assembly" AdditionalAssemblies="new[] { typeof(TestContentPackage.NotFound.NotFoundPage).Assembly }">
<Router AppAssembly="@typeof(App).Assembly" AdditionalAssemblies="new[] { typeof(TestContentPackage.NotFound.NotFoundPage).Assembly }" OnNavigateAsync="HandleOnNavigateAsync">
<Found Context="routeData">
<RouteView RouteData="@routeData" />
<FocusOnNavigate RouteData="@routeData" Selector="[data-focus-on-navigate]" />
Expand Down
Loading