-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Blazor 404 code re-execution is compatible with OnNavigateAsync
#64034
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 11 commits
0317ecf
d662028
c90449b
64df78f
5ed75df
b8856ad
d444c4a
5f632fe
0f0cf6a
f2fb811
496d430
e97518a
dd17b60
43038f3
a8f44f9
9f63c29
15ee674
288a6c3
1293d10
edd8ae6
5116f8b
9bae2fc
6ca29f0
ff67979
a5fed5c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -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] | ||||||||||||||||||||
|
|
@@ -17,8 +21,12 @@ | |||||||||||||||||||
| [SupplyParameterFromQuery(Name = "appSetsEventArgsPath")] | ||||||||||||||||||||
| public bool AppSetsEventArgsPath { get; set; } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| private const string UseOnNavigateAsyncSwitchName = "Components.TestServer.RazorComponents.UseOnNavigateAsync"; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| private Type? NotFoundPageType { get; set; } | ||||||||||||||||||||
| private NavigationManager _navigationManager = default!; | ||||||||||||||||||||
| private bool ShouldDelayOnNavigateAsync => | ||||||||||||||||||||
| AppContext.TryGetSwitch(UseOnNavigateAsyncSwitchName, out var switchEnabled) && switchEnabled; | ||||||||||||||||||||
|
||||||||||||||||||||
|
|
||||||||||||||||||||
| [Inject] | ||||||||||||||||||||
| private NavigationManager NavigationManager | ||||||||||||||||||||
|
|
@@ -70,6 +78,26 @@ | |||||||||||||||||||
| _navigationManager.OnNotFound -= OnNotFoundEvent; | ||||||||||||||||||||
| } | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| private Task HandleOnNavigateAsync(NavigationContext args) | ||||||||||||||||||||
| { | ||||||||||||||||||||
| if (NavigationCompletionTracker.TryGetGuardTask(args.Path, out var guardTask)) | ||||||||||||||||||||
| { | ||||||||||||||||||||
| return guardTask; | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| if (!ShouldDelayOnNavigateAsync) | ||||||||||||||||||||
| { | ||||||||||||||||||||
| return Task.CompletedTask; | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| return PerformOnNavigateAsyncWork(); | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| private async Task PerformOnNavigateAsyncWork() | ||||||||||||||||||||
| { | ||||||||||||||||||||
| await Task.Yield(); | ||||||||||||||||||||
| } | ||||||||||||||||||||
ilonatommy marked this conversation as resolved.
Show resolved
Hide resolved
Comment on lines
+89
to
+95
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why? |
||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| <!DOCTYPE html> | ||||||||||||||||||||
|
|
@@ -93,7 +121,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]" /> | ||||||||||||||||||||
|
|
@@ -102,7 +130,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]" /> | ||||||||||||||||||||
|
|
||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| using System; | ||
| using System.Threading; | ||
| using System.Threading.Tasks; | ||
|
|
||
| namespace Components.TestServer.RazorComponents; | ||
|
|
||
| internal static class NavigationCompletionTracker | ||
| { | ||
| internal const string GuardSwitchName = "Components.TestServer.RazorComponents.UseNavigationCompletionGuard"; | ||
|
|
||
| private const string TrackedPathSuffix = "with-lazy-assembly"; | ||
| private static int _isNavigationTracked; | ||
| private static int _isNavigationCompleted; | ||
|
|
||
| public static bool TryGetGuardTask(string? path, out Task guardTask) | ||
| { | ||
| if (!IsGuardEnabledForPath(path)) | ||
| { | ||
| guardTask = Task.CompletedTask; | ||
| return false; | ||
| } | ||
|
|
||
| guardTask = TrackNavigationAsync(); | ||
| return true; | ||
| } | ||
|
|
||
| public static void AssertNavigationCompleted() | ||
| { | ||
| if (Volatile.Read(ref _isNavigationTracked) == 1 && Volatile.Read(ref _isNavigationCompleted) == 0) | ||
| { | ||
| throw new InvalidOperationException("Navigation finished before OnNavigateAsync work completed."); | ||
| } | ||
|
|
||
| Volatile.Write(ref _isNavigationTracked, 0); | ||
| } | ||
|
|
||
| private static bool IsGuardEnabledForPath(string? path) | ||
| { | ||
| if (!AppContext.TryGetSwitch(GuardSwitchName, out var isEnabled) || !isEnabled) | ||
| { | ||
| return false; | ||
| } | ||
|
|
||
| return path is not null && path.EndsWith(TrackedPathSuffix, StringComparison.OrdinalIgnoreCase); | ||
| } | ||
|
|
||
| private static async Task TrackNavigationAsync() | ||
| { | ||
| Volatile.Write(ref _isNavigationTracked, 1); | ||
| Volatile.Write(ref _isNavigationCompleted, 0); | ||
oroztocil marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| try | ||
| { | ||
| await Task.Yield(); | ||
| await Task.Delay(TimeSpan.FromMilliseconds(50)).ConfigureAwait(false); | ||
| } | ||
| finally | ||
| { | ||
| Volatile.Write(ref _isNavigationCompleted, 1); | ||
| } | ||
| } | ||
| } | ||
ilonatommy marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| @page "/routing/with-lazy-assembly" | ||
| @using Components.TestServer.RazorComponents; | ||
|
|
||
| <h1 id="lazy-route-status">Lazy route rendered</h1> | ||
|
|
||
| @code | ||
| { | ||
| protected override void OnInitialized() | ||
| { | ||
| NavigationCompletionTracker.AssertNavigationCompleted(); | ||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.