-
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?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR fixes an issue where Blazor 404 re-execution was not working properly when the Router component had an OnNavigateAsync handler. The fix allows rendering to proceed during 404 re-execution scenarios while still preventing it during client-side navigation when lazy loading is in progress.
Key changes:
- Modified the Router component to differentiate between server-side rendering (SSR) scenarios and client-side navigation
- Updated the navigation blocking logic to check if route data is available from SSR before blocking rendering
- Added comprehensive test coverage for the 404 re-execution scenario with
OnNavigateAsync
Reviewed Changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/Components/Components/src/Routing/Router.cs | Updated navigation logic to allow rendering during SSR/re-execution while maintaining blocking for client navigation |
| src/Components/test/testassets/Components.TestServer/RazorComponents/App.razor | Added test infrastructure with configurable OnNavigateAsync handler and query parameter support |
| src/Components/test/E2ETest/ServerRenderingTests/NoInteractivityTest.cs | Added end-to-end test to verify 404 re-execution works with OnNavigateAsync |
src/Components/test/testassets/Components.TestServer/RazorComponents/App.razor
Outdated
Show resolved
Hide resolved
src/Components/test/E2ETest/ServerRenderingTests/NoInteractivityTest.cs
Outdated
Show resolved
Hide resolved
…onents/App.razor Co-authored-by: Copilot <[email protected]>
…tyTest.cs Co-authored-by: Copilot <[email protected]>
|
Failures of |
…NavigateAsync_ReExecutesTo404 test.
src/Components/test/E2ETest/ServerRenderingTests/NoInteractivityTest.cs
Outdated
Show resolved
Hide resolved
...ponents/test/testassets/Components.TestServer/RazorComponents/NavigationCompletionTracker.cs
Show resolved
Hide resolved
oroztocil
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good 👍
|
@javiercn's review: use the information if we are interactive or not instead of putting a flag into route data. |
… when on navigate task has not finished.
Do not prevent rendering for router that has
OnNavigateAsyncwhen navigation already started during 404 re-execution.In #24225 we blocked rendering for router that has
OnNavigateAsyncthat is typically used for lazy loading actions. The reason was that rendering was throwing when triggered before with lazy loading finished: #24211.With rendering blocked, 404 re-execution mechanism is not able to render the contents of 404 page. We need to implement logic to detect when re-execution has occurred and allow rendering in that specific case.
Description
OnNavigateAsyncin progress ifRefreshis triggered by re-execution to a different component type.OnNavigateAsyncwith the current route's component type. If they differ (indicating 404 re-execution to an error page), rendering is allowed. If they match (same-page lazy loading), rendering remains blocked.BrowserNavigationToNotExistingPath_ReExecutesTo404.OnNavigateAsynccompletion during lazy loading:BrowserNavigationToLazyLoadedRoute_WaitsForOnNavigateAsyncGuard.Fixes #63933
Possible Edge Cases Discussion
Multiple OnNavigateAsync handlers on same component (lazy-loading):
E.g. when navigating from
/products/1to/products/2(both renderProductsPage). Typically the assembly required for rendering is already loaded, so no risk of Lazy loading might encounter issues if host page rerenders during loading #24211 (exceptions during rendering because lazy loaded assembly is missing).Re-execution to same component type:
Real-world re-execution always targets dedicated error/404 components (e.g.,
/invalid-routere-executes to/not-foundwithNotFoundPagecomponent). Same-component re-execution would require anti-pattern design (same component having@page "/users/{id}"and@page "/error"at the same time). In case of using this anti-pattern, the rendering would still be blocked.Null RouteData during re-execution:
IRoutingStateProvideronly providesRouteDataduring endpoint/SSR rendering. After a page becomes interactive (Server Interactive via SignalR or WebAssembly), subsequent navigations are handled client-side by the Router component without going through the endpoint middleware. In these client-side navigation scenarios,RoutingStateProvideris null, which correctly falls back to the original blocking behavior.Query/hash parameter changes (same route): Navigating from
/products?page=1to/products?page=2renders the same component (ProductsPage). I was always blocked during pendingOnNavigateAsync. SinceproviderRouteData.PageType == _previousOnNavigateTaskPageType,allowRenderDuringPendingNavigationisfalse, maintaining the original blocking behavior.