Skip to content

Add NotFound method in NavigationManager for interactive and static rendering #60752

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

Merged
merged 23 commits into from
Mar 18, 2025

Conversation

ilonatommy
Copy link
Member

@ilonatommy ilonatommy commented Mar 5, 2025

NavigationManager implements NotFound method

In SSR, calling NavigationManager.NotFound() sets the HttpContext.Response.StatusCode to Status404NotFound.
In interactive, both WebAssembly and Server - it triggers the NotifyNotFound that rises NotFoundEvent. Router, that is subscribed to that event, triggers the render of NotFound page if defined, or DefaultNotFoundContent.

Details

  • If SSR started the response before calling NotFound, we cannot interrupt and we throw InvalidOperationException.
  • After setting 404 code, we stop further rendering - batches that were queued will get rendered but nothing more will get queued.
  • Passing renderer to SSR nav manager required changing InitializeStandardComponentServicesAsync from static to instance method.
  • Added 3 test cases: both interactive checks for the text from defined in router: <NotFound>There's nothing here</NotFound> and the SSR asserts the status code.
  • MVC test was failing with System.InvalidOperationException : 'NavigationManagerProxy' has not been initialized. because we trigger event subscription in http nav manager init method that expects the instance to be initialized.

Fixes #45654

@ilonatommy ilonatommy added area-blazor Includes: Blazor, Razor Components feature-blazor-routing Features related to routing in Blazor applications labels Mar 5, 2025
@ilonatommy ilonatommy added this to the .NET 10 Planning milestone Mar 5, 2025
@ilonatommy ilonatommy requested a review from javiercn March 5, 2025 11:26
@ilonatommy ilonatommy self-assigned this Mar 5, 2025
@ilonatommy ilonatommy changed the title Add NotFound method in NavigationManager for interactive and static navigation managers Add NotFound method in NavigationManager for interactive and static rendering Mar 5, 2025
@ilonatommy ilonatommy marked this pull request as ready for review March 5, 2025 13:31
@Copilot Copilot AI review requested due to automatic review settings March 5, 2025 13:31
@ilonatommy ilonatommy requested a review from a team as a code owner March 5, 2025 13:31
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Overview

This PR adds a NotFound mechanism to NavigationManager to support both interactive and static rendering scenarios. Key changes include:

  • Introducing new NotFound APIs in NavigationManager (including NotFound, NotFoundCore, NotFoundEvent, and their asynchronous variants) to trigger not found behavior.
  • Updating platform-specific implementations (WebAssembly, Server, Http) to override NotFoundCore and properly handle not found responses.
  • Adding new tests to verify that both SSR and interactive render modes render the NotFound page or return a 404 status code as expected.

Reviewed Changes

File Description
src/Components/Components/src/NotFoundRenderingException.cs Introduces a new exception for handling errors during NotFound rendering.
src/Components/Components/src/IEndpointHtmlRenderer.cs Adds the SetNotFoundResponse() API for SSR scenarios.
src/Components/Components/src/Routing/NotFoundContext.cs Provides a context for NotFound handling.
src/Components/Components/src/NavigationManager.cs Adds new NotFound APIs (event, core methods, async handlers, etc.) for navigation failure scenarios.
src/Components/WebAssembly/WebAssembly/src/Services/WebAssemblyNavigationManager.cs Implements NotFoundCore for interactive WebAssembly rendering.
src/Components/Server/src/Circuits/RemoteNavigationManager.cs Updates NotFound handling logic for interactive Server rendering.
src/Components/test/E2ETest/ServerRenderingTests/RenderingTest.cs Adds tests for verifying NotFound behavior in interactive render modes.
src/Components/test/E2ETest/ServerRenderingTests/NoInteractivityTest.cs Adds SSR tests to confirm a 404 status is returned for not found pages.
src/Components/Components/src/Routing/Router.cs Adds subscription and unsubscription for the new NotFoundEvent.
src/Components/Endpoints/src/DependencyInjection/HttpNavigationManager.cs Updates NotFoundCore to set the 404 response via the endpoint HTML renderer.
src/Components/Components/src/Routing/IHostEnvironmentNavigationManager.cs Adds a new overload of Initialize() to support passing a renderer.
src/Components/Endpoints/src/Rendering/EndpointHtmlRenderer.cs Updates service initialization to pass the renderer instance.
src/Components/Endpoints/src/RazorComponentEndpointInvoker.cs Makes use of the new instance-based InitializeStandardComponentServicesAsync().
Test assets (.razor pages) New pages added for testing NotFound behavior across different render modes.

Copilot reviewed 20 out of 20 changed files in this pull request and generated no comments.

Comments suppressed due to low confidence (2)

src/Components/test/E2ETest/ServerRenderingTests/NoInteractivityTest.cs:40

  • Ensure that concatenating _serverFixture.RootUri and relativeUrl does not inadvertently produce a double slash if the RootUri already ends with a '/'.
string absoluteUrl = "${_serverFixture.RootUri}/{relativeUrl}";

src/Components/Components/src/NavigationManager.cs:516

  • [nitpick] The logic to handle single versus multiple not found handlers repeats similar patterns; consider refactoring this section into a shared helper method to improve maintainability.
if (handlerCount == 1) { ... }

@ilonatommy ilonatommy requested a review from Copilot March 5, 2025 14:06
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Overview

This PR introduces a NotFound method on NavigationManager to support both SSR and interactive rendering, ensuring proper 404 handling and event notification. Key changes include:

  • Implementation of NotFound behavior for both SSR (by setting the response status code to 404) and interactive rendering (by triggering the NotFoundEvent).
  • Adjustments to public APIs and initialization methods to support optional renderer parameters.
  • Addition of new tests to verify NotFound rendering in various scenarios.

Reviewed Changes

File Description
src/Components/Components/src/NotFoundRenderingException.cs Introduces a new exception for handling NotFound render failures.
src/Components/Components/src/IEndpointHtmlRenderer.cs Adds an interface method to set the 404 response.
src/Components/test/E2ETest/ServerRenderingTests/RenderingTest.cs Adds tests to verify interactive not found rendering.
src/Components/Components/src/Routing/Router.cs Subscribes to NotFoundEvent and implements a new event handler and logger method.
src/Components/test/E2ETest/ServerRenderingTests/NoInteractivityTest.cs Adds a test to verify SSR 404 behavior.
src/Components/WebAssembly/WebAssembly/src/Services/WebAssemblyNavigationManager.cs Implements NotFoundCore to trigger interactive not found notifications.
src/Components/Endpoints/src/DependencyInjection/HttpNavigationManager.cs Implements NotFoundCore by using the endpoint renderer to set a 404 response.
src/Components/Server/src/Circuits/RemoteNavigationManager.cs Provides a new Initialize overload and implements NotFoundCore with logging.
src/Components/Components/src/Routing/IHostEnvironmentNavigationManager.cs Extends the interface with an Initialize overload accepting a renderer.
src/Components/Endpoints/test/RazorComponentResultTest.cs Updates FakeNavigationManager to support the new overload.
src/Components/Endpoints/src/Rendering/EndpointHtmlRenderer.EventDispatch.cs Exposes a new method to set the 404 status code on the HTTP response.
src/Components/Endpoints/src/Rendering/EndpointHtmlRenderer.cs Updates initialization to pass the renderer instance.
src/Components/Endpoints/src/RazorComponentEndpointInvoker.cs Adjusts calls to use the instance method for component service initialization.
src/Components/Components/src/NavigationManager.cs Adds a new NotFound method, event, and related logging functionality.
Razor components in test assets Implements usage of NotFound in various rendering modes and updates routing test cases accordingly.

Copilot reviewed 19 out of 19 changed files in this pull request and generated no comments.

Comments suppressed due to low confidence (1)

src/Components/Components/src/Routing/Router.cs:354

  • Duplicate LoggerMessage id '1' is used in multiple logging methods. Consider assigning a unique id to each LoggerMessage to avoid potential conflicts.
[LoggerMessage(1, LogLevel.Debug, "Displaying {nameof(NotFound)} on request", EventName = "DisplayingNotFoundOnRequest")]

@ilonatommy ilonatommy requested a review from javiercn March 10, 2025 15:43
@ilonatommy
Copy link
Member Author

ilonatommy commented Mar 17, 2025

I re run but the failures look connected:

log

2025-03-17T17:44:07.4701814Z [xUnit.net 00:00:02.20]     Microsoft.AspNetCore.Mvc.TagHelpers.ComponentTagHelperTest.ProcessAsync_RendersComponent [FAIL]
2025-03-17T17:44:07.4722055Z [xUnit.net 00:00:02.20]       System.InvalidOperationException : 'NavigationManagerProxy' has not been initialized.
2025-03-17T17:44:07.4755033Z [xUnit.net 00:00:02.21]       Stack Trace:
2025-03-17T17:44:07.4784507Z [xUnit.net 00:00:02.21]         /_/src/Components/Components/src/NavigationManager.cs(544,0): at Microsoft.AspNetCore.Components.NavigationManager.AssertInitialized()
2025-03-17T17:44:07.4810909Z [xUnit.net 00:00:02.21]         /_/src/Components/Components/src/NavigationManager.cs(45,0): at Microsoft.AspNetCore.Components.NavigationManager.add_NotFoundEvent(EventHandler`1 value)
2025-03-17T17:44:07.4838889Z [xUnit.net 00:00:02.21]         /_/src/Components/Endpoints/src/Rendering/EndpointHtmlRenderer.cs(86,0): at Microsoft.AspNetCore.Components.Endpoints.EndpointHtmlRenderer.InitializeStandardComponentServicesAsync(HttpContext httpContext, Type componentType, String handler, IFormCollection form)
2025-03-17T17:44:07.4863970Z [xUnit.net 00:00:02.22]         /_/src/Components/Endpoints/src/Rendering/EndpointHtmlRenderer.Prerendering.cs(113,0): at Microsoft.AspNetCore.Components.Endpoints.EndpointHtmlRenderer.PrerenderComponentAsync(HttpContext httpContext, Type componentType, IComponentRenderMode prerenderMode, ParameterView parameters, Boolean waitForQuiescence)
2025-03-17T17:44:07.4885458Z [xUnit.net 00:00:02.22]         /_/src/Mvc/Mvc.TagHelpers/src/ComponentTagHelper.cs(100,0): at Microsoft.AspNetCore.Mvc.TagHelpers.ComponentTagHelper.ProcessAsync(TagHelperContext context, TagHelperOutput output)
2025-03-17T17:44:07.4906731Z [xUnit.net 00:00:02.22]         /_/src/Mvc/Mvc.TagHelpers/test/ComponentTagHelperTest.cs(36,0): at Microsoft.AspNetCore.Mvc.TagHelpers.ComponentTagHelperTest.ProcessAsync_RendersComponent()
2025-03-17T17:44:07.4940697Z [xUnit.net 00:00:02.22]         --- End of stack trace from previous location ---

edit:
for sure connected, this is the line where we register NotFoundEvent. It cannot get merged without a fix.

@lewing lewing disabled auto-merge March 17, 2025 20:43
@ilonatommy ilonatommy requested a review from javiercn March 18, 2025 11:24
@ilonatommy ilonatommy requested a review from a team as a code owner March 18, 2025 12:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-blazor Includes: Blazor, Razor Components feature-blazor-routing Features related to routing in Blazor applications
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Create simpler way to show Not Found 404 UI with Blazor
2 participants