diff --git a/aspnetcore/release-notes/aspnetcore-10/includes/blazor.md b/aspnetcore/release-notes/aspnetcore-10/includes/blazor.md index 2778bf16d292..c4e0d51aa207 100644 --- a/aspnetcore/release-notes/aspnetcore-10/includes/blazor.md +++ b/aspnetcore/release-notes/aspnetcore-10/includes/blazor.md @@ -437,49 +437,56 @@ For more information and examples, see : +The recommended approach that works regardless of the response state is to call . When `NavigationManager.NotFound` is called, the middleware renders the path passed to the method: - ```csharp - app.UseStatusCodePagesWithReExecute( - "/not-found", createScopeForStatusCodePages: true); - ``` +```csharp +app.UseStatusCodePagesWithReExecute( + "/not-found", createScopeForStatusCodePages: true); +``` -* When the response has started, the can be used by subscribing to the `OnNotFoundEvent` in the router: - - ```razor - @code { - [CascadingParameter] - public HttpContext? HttpContext { get; set; } - - private void OnNotFoundEvent(object sender, NotFoundEventArgs e) - { - // Only execute the logic if HTTP response has started, - // because setting NotFoundEventArgs.Path blocks re-execution - if (HttpContext?.Response.HasStarted == false) - { - return; - } - - var type = typeof(CustomNotFoundPage); - var routeAttributes = type.GetCustomAttributes(inherit: true); - - if (routeAttributes.Length == 0) - { - throw new InvalidOperationException($"The type {type.FullName} " + - $"doesn't have a {typeof(RouteAttribute).FullName} applied."); - } - - var routeAttribute = (RouteAttribute)routeAttributes[0]; - - if (routeAttribute.Template != null) - { - e.Path = routeAttribute.Template; - } - } - } - ``` +If you don't want to use , the app can still support `NavigationManager.NotFound` for responses that have already started. Subscribe to `OnNotFoundEvent` in the router and assign the Not Found page path to `NotFoundEventArgs.Path` to inform the renderer what content to render when `NavigationManager.NotFound` is called. + +`CustomRouter.razor`: + +```razor +@using Microsoft.AspNetCore.Components +@using Microsoft.AspNetCore.Components.Routing +@using Microsoft.AspNetCore.Http +@implements IDisposable +@inject NavigationManager NavigationManager + +@code { + protected override void OnInitialized() => + NavigationManager.OnNotFound += OnNotFoundEvent; + + [CascadingParameter] + public HttpContext? HttpContext { get; set; } + + private void OnNotFoundEvent(object sender, NotFoundEventArgs e) + { + // Only execute the logic if HTTP response has started + // because setting NotFoundEventArgs.Path blocks re-execution + if (HttpContext?.Response.HasStarted == false) + { + return; + } + + e.Path = GetNotFoundRoutePath(); + } + + // Return the path of the Not Found page that you want to display + private string GetNotFoundRoutePath() + { + ... + } + + public void Dispose() => NavigationManager.OnNotFound -= OnNotFoundEvent; +} +``` + +If you use both approaches in your app, the Not Found path specified in the `OnNotFoundEvent` handler takes precedence over the path configured in the re-execution middleware. ### Metrics and tracing