From 5fff491735d23faab0f3c14f58f6e10d7119fbcb Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Wed, 21 May 2025 13:25:26 +0200 Subject: [PATCH 01/20] Add re-exec tests for SSR + move NotFound sources into one directory. --- .../NoInteractivityTest.cs | 28 ++++++++++++++++ ...omponentEndpointsNoInteractivityStartup.cs | 33 ++++++++++++------- .../RazorComponentEndpointsStartup.cs | 2 +- .../Pages/{ => NotFound}/NotFoundPage.razor | 0 .../{ => NotFound}/PageThatSetsNotFound.razor | 0 .../Pages/NotFound/RedirectionNotFound.razor | 28 ++++++++++++++++ .../Pages/{ => NotFound}/ReexecutedPage.razor | 0 7 files changed, 79 insertions(+), 12 deletions(-) rename src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/{ => NotFound}/NotFoundPage.razor (100%) rename src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/{ => NotFound}/PageThatSetsNotFound.razor (100%) create mode 100644 src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound.razor rename src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/{ => NotFound}/ReexecutedPage.razor (100%) diff --git a/src/Components/test/E2ETest/ServerRenderingTests/NoInteractivityTest.cs b/src/Components/test/E2ETest/ServerRenderingTests/NoInteractivityTest.cs index 139f3db4726e..e54125e46937 100644 --- a/src/Components/test/E2ETest/ServerRenderingTests/NoInteractivityTest.cs +++ b/src/Components/test/E2ETest/ServerRenderingTests/NoInteractivityTest.cs @@ -87,6 +87,34 @@ public void CanRenderNotFoundPageAfterStreamingStarted() Browser.Equal("Default Not Found Page", () => Browser.Title); } + [Fact] + public void ProgrammaticNavigationToNotExistingPathReExecutesTo404() + { + Navigate($"{ServerPathBase}/reexecution/redirection-not-found?navigate-programmatically=true"); + Assert404ReExecuted(); + } + + [Fact] + public void LinkNavigationToNotExistingPathReExecutesTo404() + { + Navigate($"{ServerPathBase}/reexecution/redirection-not-found"); + Browser.Click(By.Id("link-to-not-existing-page")); + Assert404ReExecuted(); + } + + [Fact] + public void BrowserNavigationToNotExistingPathReExecutesTo404() + { + // non-existing path has to have re-execution middleware set up + // so it has to have "reexecution" prefix. Otherwise middleware mapping + // will not be activated, see configuration in Startup + Navigate($"{ServerPathBase}/reexecution/not-existing-page"); + Assert404ReExecuted(); + } + + private void Assert404ReExecuted() => + Browser.Equal("Welcome On Page Re-executed After Not Found Event", () => Browser.Exists(By.Id("test-info")).Text); + [Theory] [InlineData(true)] [InlineData(false)] diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsNoInteractivityStartup.cs b/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsNoInteractivityStartup.cs index c4af233c40fe..d072d9b444b0 100644 --- a/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsNoInteractivityStartup.cs +++ b/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsNoInteractivityStartup.cs @@ -48,19 +48,30 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.Map("/subdir", app => { - if (!env.IsDevelopment()) + app.Map("/reexecution", reexecutionApp => { - app.UseExceptionHandler("/Error", createScopeForErrors: true); - } - - app.UseStaticFiles(); - app.UseRouting(); - RazorComponentEndpointsStartup.UseFakeAuthState(app); - app.UseAntiforgery(); - app.UseEndpoints(endpoints => - { - endpoints.MapRazorComponents(); + reexecutionApp.UseStatusCodePagesWithReExecute("/not-found-reexecute", createScopeForErrors: true); + ConfigureSubdirPipeline(reexecutionApp, env); }); + + ConfigureSubdirPipeline(app, env); + }); + } + + private void ConfigureSubdirPipeline(IApplicationBuilder app, IWebHostEnvironment env) + { + if (!env.IsDevelopment()) + { + app.UseExceptionHandler("/Error", createScopeForErrors: true); + } + + app.UseStaticFiles(); + app.UseRouting(); + RazorComponentEndpointsStartup.UseFakeAuthState(app); + app.UseAntiforgery(); + app.UseEndpoints(endpoints => + { + endpoints.MapRazorComponents(); }); } } diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsStartup.cs b/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsStartup.cs index f91db9aa4ee3..9aa6f62b2bb1 100644 --- a/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsStartup.cs +++ b/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsStartup.cs @@ -89,7 +89,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) }); } - protected virtual void ConfigureSubdirPipeline(IApplicationBuilder app, IWebHostEnvironment env) + private void ConfigureSubdirPipeline(IApplicationBuilder app, IWebHostEnvironment env) { WebAssemblyTestHelper.ServeCoopHeadersIfWebAssemblyThreadingEnabled(app); diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFoundPage.razor b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/NotFoundPage.razor similarity index 100% rename from src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFoundPage.razor rename to src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/NotFoundPage.razor diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/PageThatSetsNotFound.razor b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/PageThatSetsNotFound.razor similarity index 100% rename from src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/PageThatSetsNotFound.razor rename to src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/PageThatSetsNotFound.razor diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound.razor b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound.razor new file mode 100644 index 000000000000..97a422dc90b2 --- /dev/null +++ b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound.razor @@ -0,0 +1,28 @@ +@page "/redirection-not-found" +@page "/reexecution/redirection-not-found" +@attribute [StreamRendering(false)] +@inject NavigationManager NavigationManager + +Original page + +

Any content

+ + Go to not-existing-page + + +@code{ + [Parameter] + [SupplyParameterFromQuery(Name = "navigate-programmatically")] + public bool? NavigateProgrammatically { get; set; } + + private string? _nonExistingPath; + + protected override void OnInitialized() + { + _nonExistingPath = $"{NavigationManager.BaseUri}not-existing-page"; + if (NavigateProgrammatically == true) + { + NavigationManager.NavigateTo(_nonExistingPath); + } + } +} diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/ReexecutedPage.razor b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/ReexecutedPage.razor similarity index 100% rename from src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/ReexecutedPage.razor rename to src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/ReexecutedPage.razor From 66cc9747693b2e3bc946cc5ab7ed051f6acff204 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Wed, 21 May 2025 13:57:04 +0200 Subject: [PATCH 02/20] Per-component interactivity: test navigation to non-existing page. --- .../ServerRenderingTests/InteractivityTest.cs | 37 +++++++++++++++++++ .../RedirectionNotFound-Interactive.razor | 32 ++++++++++++++++ ...nd.razor => RedirectionNotFound-SSR.razor} | 0 3 files changed, 69 insertions(+) create mode 100644 src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-Interactive.razor rename src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/{RedirectionNotFound.razor => RedirectionNotFound-SSR.razor} (100%) diff --git a/src/Components/test/E2ETest/ServerRenderingTests/InteractivityTest.cs b/src/Components/test/E2ETest/ServerRenderingTests/InteractivityTest.cs index 286a6de9e12d..5dec3281e98a 100644 --- a/src/Components/test/E2ETest/ServerRenderingTests/InteractivityTest.cs +++ b/src/Components/test/E2ETest/ServerRenderingTests/InteractivityTest.cs @@ -1411,4 +1411,41 @@ public void NavigatesWithInteractivityByRequestRedirection(bool controlFlowByExc Browser.Click(By.Id("redirectButton")); Browser.Equal("Routing test cases", () => Browser.Exists(By.Id("test-info")).Text); } + + [Theory] + // prerendering (SSR) is tested in NoInteractivityTest + [InlineData("ServerNonPrerendered")] + [InlineData("WebAssemblyNonPrerendered")] + public void ProgrammaticNavigationToNotExistingPathReExecutesTo404(string renderMode) + { + Navigate($"{ServerPathBase}/reexecution/redirection-not-found?render-mode={renderMode}&navigate-programmatically=true"); + Assert404ReExecuted(); + } + + [Theory] + // prerendering (SSR) is tested in NoInteractivityTest + [InlineData("ServerNonPrerendered")] + [InlineData("WebAssemblyNonPrerendered")] + public void LinkNavigationToNotExistingPathReExecutesTo404(string renderMode) + { + Navigate($"{ServerPathBase}/reexecution/redirection-not-found?render-mode={renderMode}"); + Browser.Click(By.Id("link-to-not-existing-page")); + Assert404ReExecuted(); + } + + [Theory] + // prerendering (SSR) is tested in NoInteractivityTest + [InlineData("ServerNonPrerendered")] + [InlineData("WebAssemblyNonPrerendered")] + public void BrowserNavigationToNotExistingPathReExecutesTo404(string renderMode) + { + // non-existing path has to have re-execution middleware set up + // so it has to have "reexecution" prefix. Otherwise middleware mapping + // will not be activated, see configuration in Startup + Navigate($"{ServerPathBase}/reexecution/not-existing-page?render-mode={renderMode}"); + Assert404ReExecuted(); + } + + private void Assert404ReExecuted() => + Browser.Equal("Welcome On Page Re-executed After Not Found Event", () => Browser.Exists(By.Id("test-info")).Text); } diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-Interactive.razor b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-Interactive.razor new file mode 100644 index 000000000000..01351b40bb8a --- /dev/null +++ b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-Interactive.razor @@ -0,0 +1,32 @@ +@page "/redirection-not-found" +@page "/reexecution/redirection-not-found" +@rendermode @(RenderModeHelper.GetRenderMode(_currentRenderMode)) +@inject NavigationManager NavigationManager + +Original page + +

Any content

+ + Go to not-existing-page + + +@code{ + [Parameter, SupplyParameterFromQuery(Name = "renderMode")] + public string? RenderModeStr { get; set; } + + [Parameter] + [SupplyParameterFromQuery(Name = "navigate-programmatically")] + public bool? NavigateProgrammatically { get; set; } + + private string? _nonExistingPath; + private RenderModeId _currentRenderMode => RenderModeHelper.ParseRenderMode(RenderModeStr); + + protected override void OnInitialized() + { + _nonExistingPath = $"{NavigationManager.BaseUri}not-existing-page"; + if (NavigateProgrammatically == true) + { + NavigationManager.NavigateTo(_nonExistingPath); + } + } +} diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound.razor b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR.razor similarity index 100% rename from src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound.razor rename to src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR.razor From 89075246f9fbdf16eb5e90c63b748d03f21a5c07 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Wed, 21 May 2025 15:07:50 +0200 Subject: [PATCH 03/20] Add streaming SSR tests. --- .../NoInteractivityTest.cs | 27 +++++++++++------ .../RedirectionNotFound-SSR-streaming.razor | 5 ++++ .../NotFound/RedirectionNotFound-SSR.razor | 29 ++----------------- .../RedirectionNotFoundComponent.razor | 26 +++++++++++++++++ .../Pages/NotFoundSSR.razor | 11 ------- 5 files changed, 52 insertions(+), 46 deletions(-) create mode 100644 src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR-streaming.razor create mode 100644 src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFoundComponent.razor delete mode 100644 src/Components/test/testassets/Components.WasmMinimal/Pages/NotFoundSSR.razor diff --git a/src/Components/test/E2ETest/ServerRenderingTests/NoInteractivityTest.cs b/src/Components/test/E2ETest/ServerRenderingTests/NoInteractivityTest.cs index e54125e46937..c7af49fc7b3f 100644 --- a/src/Components/test/E2ETest/ServerRenderingTests/NoInteractivityTest.cs +++ b/src/Components/test/E2ETest/ServerRenderingTests/NoInteractivityTest.cs @@ -87,28 +87,37 @@ public void CanRenderNotFoundPageAfterStreamingStarted() Browser.Equal("Default Not Found Page", () => Browser.Title); } - [Fact] - public void ProgrammaticNavigationToNotExistingPathReExecutesTo404() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void ProgrammaticNavigationToNotExistingPathReExecutesTo404(bool streaming) { - Navigate($"{ServerPathBase}/reexecution/redirection-not-found?navigate-programmatically=true"); + string streamingPath = streaming ? "-streaming" : ""; + Navigate($"{ServerPathBase}/reexecution/redirection-not-found-ssr{streamingPath}?navigate-programmatically=true"); Assert404ReExecuted(); } - [Fact] - public void LinkNavigationToNotExistingPathReExecutesTo404() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void LinkNavigationToNotExistingPathReExecutesTo404(bool streaming) { - Navigate($"{ServerPathBase}/reexecution/redirection-not-found"); + string streamingPath = streaming ? "-streaming" : ""; + Navigate($"{ServerPathBase}/reexecution/redirection-not-found-ssr{streamingPath}"); Browser.Click(By.Id("link-to-not-existing-page")); Assert404ReExecuted(); } - [Fact] - public void BrowserNavigationToNotExistingPathReExecutesTo404() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void BrowserNavigationToNotExistingPathReExecutesTo404(bool streaming) { // non-existing path has to have re-execution middleware set up // so it has to have "reexecution" prefix. Otherwise middleware mapping // will not be activated, see configuration in Startup - Navigate($"{ServerPathBase}/reexecution/not-existing-page"); + string streamingPath = streaming ? "-streaming" : ""; + Navigate($"{ServerPathBase}/reexecution/not-existing-page-ssr{streamingPath}"); Assert404ReExecuted(); } diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR-streaming.razor b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR-streaming.razor new file mode 100644 index 000000000000..07781aa37637 --- /dev/null +++ b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR-streaming.razor @@ -0,0 +1,5 @@ +@page "/redirection-not-found-ssr-streaming" +@page "/reexecution/redirection-not-found-ssr-streaming" +@attribute [StreamRendering(true)] + + diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR.razor b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR.razor index 97a422dc90b2..d69ef0f4acbf 100644 --- a/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR.razor +++ b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR.razor @@ -1,28 +1,5 @@ -@page "/redirection-not-found" -@page "/reexecution/redirection-not-found" +@page "/redirection-not-found-ssr" +@page "/reexecution/redirection-not-found-ssr" @attribute [StreamRendering(false)] -@inject NavigationManager NavigationManager -Original page - -

Any content

- - Go to not-existing-page - - -@code{ - [Parameter] - [SupplyParameterFromQuery(Name = "navigate-programmatically")] - public bool? NavigateProgrammatically { get; set; } - - private string? _nonExistingPath; - - protected override void OnInitialized() - { - _nonExistingPath = $"{NavigationManager.BaseUri}not-existing-page"; - if (NavigateProgrammatically == true) - { - NavigationManager.NavigateTo(_nonExistingPath); - } - } -} + diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFoundComponent.razor b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFoundComponent.razor new file mode 100644 index 000000000000..4196c38b3655 --- /dev/null +++ b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFoundComponent.razor @@ -0,0 +1,26 @@ + +@inject NavigationManager NavigationManager + +

Original page

+ +

Any content

+ + Go to not-existing-page + + +@code{ + [Parameter] + [SupplyParameterFromQuery(Name = "navigate-programmatically")] + public bool? NavigateProgrammatically { get; set; } + + private string? _nonExistingPath; + + protected override void OnInitialized() + { + _nonExistingPath = $"{NavigationManager.BaseUri}not-existing-page"; + if (NavigateProgrammatically == true) + { + NavigationManager.NavigateTo(_nonExistingPath); + } + } +} diff --git a/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFoundSSR.razor b/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFoundSSR.razor deleted file mode 100644 index a4d3fbe8f7aa..000000000000 --- a/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFoundSSR.razor +++ /dev/null @@ -1,11 +0,0 @@ -@page "/render-not-found-ssr" -@inject NavigationManager NavigationManager - -

Any content

- -@code{ - protected override void OnInitialized() - { - NavigationManager.NotFound(); - } -} \ No newline at end of file From 3b89c4b4d984ae113a263afff4c5dabb821f52c4 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Wed, 21 May 2025 17:21:33 +0200 Subject: [PATCH 04/20] Clean up tests and make them work. --- .../ServerRenderingTests/InteractivityTest.cs | 6 ++-- ...omponentEndpointsNoInteractivityStartup.cs | 9 +++++- .../RazorComponentEndpointsStartup.cs | 14 ++++---- .../RedirectionNotFound-Interactive.razor | 32 ------------------- .../RedirectionNotFound-SSR-streaming.razor | 2 +- .../NotFound/RedirectionNotFound-SSR.razor | 2 +- .../NotFoundInteractiveServer.razor | 0 .../NotFoundInteractiveWebassembly.razor | 0 .../Pages/NotFound/NotFoundSSR.razor | 11 +++++++ .../RedirectionNotFound-Interactive.razor | 19 +++++++++++ .../RedirectionNotFoundComponent.razor | 0 .../RenderModeHelper.cs | 2 -- 12 files changed, 51 insertions(+), 46 deletions(-) delete mode 100644 src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-Interactive.razor rename src/Components/test/testassets/Components.WasmMinimal/Pages/{ => NotFound}/NotFoundInteractiveServer.razor (100%) rename src/Components/test/testassets/Components.WasmMinimal/Pages/{ => NotFound}/NotFoundInteractiveWebassembly.razor (100%) create mode 100644 src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/NotFoundSSR.razor create mode 100644 src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFound-Interactive.razor rename src/Components/test/testassets/{Components.TestServer/RazorComponents => Components.WasmMinimal}/Pages/NotFound/RedirectionNotFoundComponent.razor (100%) rename src/Components/test/testassets/{Components.TestServer => Components.WasmMinimal}/RenderModeHelper.cs (98%) diff --git a/src/Components/test/E2ETest/ServerRenderingTests/InteractivityTest.cs b/src/Components/test/E2ETest/ServerRenderingTests/InteractivityTest.cs index 5dec3281e98a..dd9f2a3a47e8 100644 --- a/src/Components/test/E2ETest/ServerRenderingTests/InteractivityTest.cs +++ b/src/Components/test/E2ETest/ServerRenderingTests/InteractivityTest.cs @@ -1418,7 +1418,7 @@ public void NavigatesWithInteractivityByRequestRedirection(bool controlFlowByExc [InlineData("WebAssemblyNonPrerendered")] public void ProgrammaticNavigationToNotExistingPathReExecutesTo404(string renderMode) { - Navigate($"{ServerPathBase}/reexecution/redirection-not-found?render-mode={renderMode}&navigate-programmatically=true"); + Navigate($"{ServerPathBase}/reexecution/redirection-not-found?renderMode={renderMode}&navigate-programmatically=true"); Assert404ReExecuted(); } @@ -1428,7 +1428,7 @@ public void ProgrammaticNavigationToNotExistingPathReExecutesTo404(string render [InlineData("WebAssemblyNonPrerendered")] public void LinkNavigationToNotExistingPathReExecutesTo404(string renderMode) { - Navigate($"{ServerPathBase}/reexecution/redirection-not-found?render-mode={renderMode}"); + Navigate($"{ServerPathBase}/reexecution/redirection-not-found?renderMode={renderMode}"); Browser.Click(By.Id("link-to-not-existing-page")); Assert404ReExecuted(); } @@ -1442,7 +1442,7 @@ public void BrowserNavigationToNotExistingPathReExecutesTo404(string renderMode) // non-existing path has to have re-execution middleware set up // so it has to have "reexecution" prefix. Otherwise middleware mapping // will not be activated, see configuration in Startup - Navigate($"{ServerPathBase}/reexecution/not-existing-page?render-mode={renderMode}"); + Navigate($"{ServerPathBase}/reexecution/not-existing-page?renderMode={renderMode}"); Assert404ReExecuted(); } diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsNoInteractivityStartup.cs b/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsNoInteractivityStartup.cs index d072d9b444b0..b7d06fcf124d 100644 --- a/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsNoInteractivityStartup.cs +++ b/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsNoInteractivityStartup.cs @@ -50,8 +50,15 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.Map("/reexecution", reexecutionApp => { + reexecutionApp.UseStaticFiles(); + reexecutionApp.UseRouting(); reexecutionApp.UseStatusCodePagesWithReExecute("/not-found-reexecute", createScopeForErrors: true); - ConfigureSubdirPipeline(reexecutionApp, env); + reexecutionApp.UseRouting(); + reexecutionApp.UseAntiforgery(); + reexecutionApp.UseEndpoints(endpoints => + { + endpoints.MapRazorComponents(); + }); }); ConfigureSubdirPipeline(app, env); diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsStartup.cs b/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsStartup.cs index 9aa6f62b2bb1..0664081e7d15 100644 --- a/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsStartup.cs +++ b/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsStartup.cs @@ -75,14 +75,12 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.Map("/reexecution", reexecutionApp => { + reexecutionApp.UseRouting(); reexecutionApp.UseStatusCodePagesWithReExecute("/not-found-reexecute", createScopeForErrors: true); - reexecutionApp.UseRouting(); + reexecutionApp.UseAntiforgery(); - reexecutionApp.UseEndpoints(endpoints => - { - endpoints.MapRazorComponents(); - }); + ConfigureEndpoints(reexecutionApp, env); }); ConfigureSubdirPipeline(app, env); @@ -106,11 +104,15 @@ private void ConfigureSubdirPipeline(IApplicationBuilder app, IWebHostEnvironmen { if (ctx.Request.Query.ContainsKey("add-csp")) { - ctx.Response.Headers.Add("Content-Security-Policy", "script-src 'self' 'unsafe-inline'"); + ctx.Response.Headers.Add("Content-Security-Policy", "script-src 'self' 'unsafe-inline'"); } return nxt(); }); + ConfigureEndpoints(app, env); + } + private void ConfigureEndpoints(IApplicationBuilder app, IWebHostEnvironment env) + { _ = app.UseEndpoints(endpoints => { var contentRootStaticAssetsPath = Path.Combine(env.ContentRootPath, "Components.TestServer.staticwebassets.endpoints.json"); diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-Interactive.razor b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-Interactive.razor deleted file mode 100644 index 01351b40bb8a..000000000000 --- a/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-Interactive.razor +++ /dev/null @@ -1,32 +0,0 @@ -@page "/redirection-not-found" -@page "/reexecution/redirection-not-found" -@rendermode @(RenderModeHelper.GetRenderMode(_currentRenderMode)) -@inject NavigationManager NavigationManager - -Original page - -

Any content

- - Go to not-existing-page - - -@code{ - [Parameter, SupplyParameterFromQuery(Name = "renderMode")] - public string? RenderModeStr { get; set; } - - [Parameter] - [SupplyParameterFromQuery(Name = "navigate-programmatically")] - public bool? NavigateProgrammatically { get; set; } - - private string? _nonExistingPath; - private RenderModeId _currentRenderMode => RenderModeHelper.ParseRenderMode(RenderModeStr); - - protected override void OnInitialized() - { - _nonExistingPath = $"{NavigationManager.BaseUri}not-existing-page"; - if (NavigateProgrammatically == true) - { - NavigationManager.NavigateTo(_nonExistingPath); - } - } -} diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR-streaming.razor b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR-streaming.razor index 07781aa37637..2f85f7f972a2 100644 --- a/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR-streaming.razor +++ b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR-streaming.razor @@ -2,4 +2,4 @@ @page "/reexecution/redirection-not-found-ssr-streaming" @attribute [StreamRendering(true)] - + diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR.razor b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR.razor index d69ef0f4acbf..80a579a2e456 100644 --- a/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR.razor +++ b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR.razor @@ -2,4 +2,4 @@ @page "/reexecution/redirection-not-found-ssr" @attribute [StreamRendering(false)] - + \ No newline at end of file diff --git a/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFoundInteractiveServer.razor b/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/NotFoundInteractiveServer.razor similarity index 100% rename from src/Components/test/testassets/Components.WasmMinimal/Pages/NotFoundInteractiveServer.razor rename to src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/NotFoundInteractiveServer.razor diff --git a/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFoundInteractiveWebassembly.razor b/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/NotFoundInteractiveWebassembly.razor similarity index 100% rename from src/Components/test/testassets/Components.WasmMinimal/Pages/NotFoundInteractiveWebassembly.razor rename to src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/NotFoundInteractiveWebassembly.razor diff --git a/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/NotFoundSSR.razor b/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/NotFoundSSR.razor new file mode 100644 index 000000000000..a4d3fbe8f7aa --- /dev/null +++ b/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/NotFoundSSR.razor @@ -0,0 +1,11 @@ +@page "/render-not-found-ssr" +@inject NavigationManager NavigationManager + +

Any content

+ +@code{ + protected override void OnInitialized() + { + NavigationManager.NotFound(); + } +} \ No newline at end of file diff --git a/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFound-Interactive.razor b/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFound-Interactive.razor new file mode 100644 index 000000000000..461d8b6f5263 --- /dev/null +++ b/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFound-Interactive.razor @@ -0,0 +1,19 @@ +@page "/redirection-not-found" +@page "/reexecution/redirection-not-found" + + + +@code{ + [Parameter, SupplyParameterFromQuery(Name = "renderMode")] + public string? RenderModeStr { get; set; } + + private RenderModeId _renderMode; + + protected override void OnInitialized() + { + if (!string.IsNullOrEmpty(RenderModeStr)) + { + _renderMode = RenderModeHelper.ParseRenderMode(RenderModeStr); + } + } +} \ No newline at end of file diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFoundComponent.razor b/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFoundComponent.razor similarity index 100% rename from src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFoundComponent.razor rename to src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFoundComponent.razor diff --git a/src/Components/test/testassets/Components.TestServer/RenderModeHelper.cs b/src/Components/test/testassets/Components.WasmMinimal/RenderModeHelper.cs similarity index 98% rename from src/Components/test/testassets/Components.TestServer/RenderModeHelper.cs rename to src/Components/test/testassets/Components.WasmMinimal/RenderModeHelper.cs index ab1285699691..1845bddfbe22 100644 --- a/src/Components/test/testassets/Components.TestServer/RenderModeHelper.cs +++ b/src/Components/test/testassets/Components.WasmMinimal/RenderModeHelper.cs @@ -5,8 +5,6 @@ using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Web; -namespace TestServer; - public static class RenderModeHelper { public static IComponentRenderMode GetRenderMode(RenderModeId renderMode) From 217e8dd6e8e43a33a91997b48cfed0fc05843189 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Wed, 21 May 2025 18:37:17 +0200 Subject: [PATCH 05/20] Fix interactivity tests. --- .../Pages/NotFound/RedirectionNotFoundComponent.razor | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFoundComponent.razor b/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFoundComponent.razor index 4196c38b3655..f441cc2768f5 100644 --- a/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFoundComponent.razor +++ b/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFoundComponent.razor @@ -4,7 +4,7 @@

Original page

Any content

- + Go to not-existing-page @@ -13,11 +13,11 @@ [SupplyParameterFromQuery(Name = "navigate-programmatically")] public bool? NavigateProgrammatically { get; set; } - private string? _nonExistingPath; + private string _nonExistingPath = string.Empty; protected override void OnInitialized() { - _nonExistingPath = $"{NavigationManager.BaseUri}not-existing-page"; + _nonExistingPath = $"{NavigationManager.BaseUri}reexecution/not-existing-page"; if (NavigateProgrammatically == true) { NavigationManager.NavigateTo(_nonExistingPath); From 6e3eb988a4f43f1dee072ef895311f430e3abcfa Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Thu, 22 May 2025 11:15:31 +0200 Subject: [PATCH 06/20] Remove routing sandwitch. --- .../RazorComponentEndpointsNoInteractivityStartup.cs | 2 +- .../Components.TestServer/RazorComponentEndpointsStartup.cs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsNoInteractivityStartup.cs b/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsNoInteractivityStartup.cs index b7d06fcf124d..7257fafa898d 100644 --- a/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsNoInteractivityStartup.cs +++ b/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsNoInteractivityStartup.cs @@ -51,9 +51,9 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.Map("/reexecution", reexecutionApp => { reexecutionApp.UseStaticFiles(); - reexecutionApp.UseRouting(); reexecutionApp.UseStatusCodePagesWithReExecute("/not-found-reexecute", createScopeForErrors: true); reexecutionApp.UseRouting(); + RazorComponentEndpointsStartup.UseFakeAuthState(reexecutionApp); reexecutionApp.UseAntiforgery(); reexecutionApp.UseEndpoints(endpoints => { diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsStartup.cs b/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsStartup.cs index 0664081e7d15..ea4f7f7ad220 100644 --- a/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsStartup.cs +++ b/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsStartup.cs @@ -75,7 +75,6 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.Map("/reexecution", reexecutionApp => { - reexecutionApp.UseRouting(); reexecutionApp.UseStatusCodePagesWithReExecute("/not-found-reexecute", createScopeForErrors: true); reexecutionApp.UseRouting(); From e89fe2d369958d5c53ccb3f3a5aa19263e228952 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Thu, 22 May 2025 11:52:04 +0200 Subject: [PATCH 07/20] Trigger streaming. --- .../NotFound/RedirectionNotFound-SSR-streaming.razor | 2 +- .../Pages/NotFound/RedirectionNotFoundComponent.razor | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR-streaming.razor b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR-streaming.razor index 2f85f7f972a2..74374799ce04 100644 --- a/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR-streaming.razor +++ b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR-streaming.razor @@ -2,4 +2,4 @@ @page "/reexecution/redirection-not-found-ssr-streaming" @attribute [StreamRendering(true)] - + diff --git a/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFoundComponent.razor b/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFoundComponent.razor index f441cc2768f5..241052e41ed3 100644 --- a/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFoundComponent.razor +++ b/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFoundComponent.razor @@ -13,10 +13,17 @@ [SupplyParameterFromQuery(Name = "navigate-programmatically")] public bool? NavigateProgrammatically { get; set; } + [Parameter] + public bool StartStreaming { get; set; } = false; + private string _nonExistingPath = string.Empty; - protected override void OnInitialized() + protected override async Task OnInitializedAsync() { + if (StartStreaming) + { + await Task.Yield(); + } _nonExistingPath = $"{NavigationManager.BaseUri}reexecution/not-existing-page"; if (NavigateProgrammatically == true) { From e4b89c17e3c11f29fa7d2c7fee1b4f6223fc0a44 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Thu, 22 May 2025 12:16:43 +0200 Subject: [PATCH 08/20] Templates use reexecution. --- .../content/BlazorWeb-CSharp/BlazorWeb-CSharp/Program.Main.cs | 4 +++- .../content/BlazorWeb-CSharp/BlazorWeb-CSharp/Program.cs | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWeb-CSharp/Program.Main.cs b/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWeb-CSharp/Program.Main.cs index d37d24553867..b0b8d955cc6d 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWeb-CSharp/Program.Main.cs +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWeb-CSharp/Program.Main.cs @@ -103,10 +103,12 @@ public static void Main(string[] args) #endif } + app.UseStatusCodePagesWithReExecute("/not-found", createScopeForErrors: true); + #if (HasHttpsProfile) app.UseHttpsRedirection(); - #endif +#endif app.UseAntiforgery(); app.MapStaticAssets(); diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWeb-CSharp/Program.cs b/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWeb-CSharp/Program.cs index 7ea8e5a50033..8eb1deacb1fa 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWeb-CSharp/Program.cs +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWeb-CSharp/Program.cs @@ -96,6 +96,7 @@ app.UseHsts(); #endif } +app.UseStatusCodePagesWithReExecute("/not-found", createScopeForErrors: true); #if (HasHttpsProfile) app.UseHttpsRedirection(); From fe7074f2e2ff7136c1bb0bdc0c0e50cbe961a508 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Wed, 28 May 2025 14:06:07 +0200 Subject: [PATCH 09/20] Fix templates and layout. --- .../Components/src/LayoutAttribute.cs | 1 + .../Components/src/Routing/Router.cs | 50 ++++++++++++++----- .../NoInteractivityTest.cs | 3 ++ .../E2ETest/Tests/GlobalInteractivityTest.cs | 3 ++ .../Pages/CustomNotFoundPage.razor | 4 -- .../Pages/NotFound/CustomNotFoundPage.razor | 5 ++ .../Pages/NotFound/NotFoundLayout.razor | 23 +++++++++ .../BlazorWeb-CSharp.Client/_Imports.razor | 3 ++ .../Components/Pages/NotFound.razor | 1 + .../Components/_Imports.razor | 2 +- .../ComponentsWebAssembly-CSharp/App.razor | 4 +- .../Pages/NotFound.razor | 5 ++ .../Templates.Tests/template-baselines.json | 6 +++ 13 files changed, 91 insertions(+), 19 deletions(-) delete mode 100644 src/Components/test/testassets/Components.WasmMinimal/Pages/CustomNotFoundPage.razor create mode 100644 src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/CustomNotFoundPage.razor create mode 100644 src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/NotFoundLayout.razor create mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Pages/NotFound.razor diff --git a/src/Components/Components/src/LayoutAttribute.cs b/src/Components/Components/src/LayoutAttribute.cs index b7249f82c60c..30de25ca6568 100644 --- a/src/Components/Components/src/LayoutAttribute.cs +++ b/src/Components/Components/src/LayoutAttribute.cs @@ -36,5 +36,6 @@ public LayoutAttribute([DynamicallyAccessedMembers(Component)] Type layoutType) /// The type of the layout. The type must implement /// and must accept a parameter with the name 'Body'. /// + [DynamicallyAccessedMembers(Component)] public Type LayoutType { get; private set; } } diff --git a/src/Components/Components/src/Routing/Router.cs b/src/Components/Components/src/Routing/Router.cs index 2d2afadc3d39..ec3b2538317b 100644 --- a/src/Components/Components/src/Routing/Router.cs +++ b/src/Components/Components/src/Routing/Router.cs @@ -42,6 +42,9 @@ static readonly IReadOnlyDictionary _emptyParametersDictionary private bool _onNavigateCalled; + [DynamicallyAccessedMembers(LinkerFlags.Component)] + private Type? _notFoundLayoutType; + [Inject] private NavigationManager NavigationManager { get; set; } [Inject] private INavigationInterception NavigationInterception { get; set; } @@ -156,6 +159,9 @@ public async Task SetParametersAsync(ParameterView parameters) throw new InvalidOperationException($"The type {NotFoundPage.FullName} " + $"does not have a {typeof(RouteAttribute).FullName} applied to it."); } + + var layoutAttr = NotFoundPage.GetTypeInfo().GetCustomAttribute(); + _notFoundLayoutType = layoutAttr?.LayoutType; } if (!_onNavigateCalled) @@ -223,7 +229,7 @@ internal virtual void Refresh(bool isNavigationIntercepted) var relativePath = NavigationManager.ToBaseRelativePath(_locationAbsolute.AsSpan()); var locationPathSpan = TrimQueryOrHash(relativePath); var locationPath = $"/{locationPathSpan}"; - Activity? activity = null; + Activity? activity; // In order to avoid routing twice we check for RouteData if (RoutingStateProvider?.RouteData is { } endpointRouteData) @@ -286,7 +292,7 @@ internal virtual void Refresh(bool isNavigationIntercepted) // We did not find a Component that matches the route. // Only show the NotFound content if the application developer programatically got us here i.e we did not // intercept the navigation. In all other cases, force a browser navigation since this could be non-Blazor content. - _renderHandle.Render(NotFound ?? DefaultNotFoundContent); + RenderNotFound(); } else { @@ -382,23 +388,43 @@ private void OnNotFound(object sender, EventArgs args) if (_renderHandle.IsInitialized) { Log.DisplayingNotFound(_logger); - _renderHandle.Render(builder => + RenderNotFound(); + } + } + + private void RenderNotFound() + { + _renderHandle.Render(builder => + { + if (NotFoundPage != null) { - if (NotFoundPage != null) + if (_notFoundLayoutType is Type layoutType) { - builder.OpenComponent(0, NotFoundPage); + // Directly instantiate the layout type, supplying the NotFoundPage as the Body + builder.OpenComponent(0, layoutType); + builder.AddAttribute(1, LayoutComponentBase.BodyPropertyName, + (RenderFragment)(childBuilder => + { + childBuilder.OpenComponent(2, NotFoundPage); + childBuilder.CloseComponent(); + })); builder.CloseComponent(); } - else if (NotFound != null) - { - NotFound(builder); - } else { - DefaultNotFoundContent(builder); + builder.OpenComponent(0, NotFoundPage); + builder.CloseComponent(); } - }); - } + } + else if (NotFound != null) + { + NotFound(builder); + } + else + { + DefaultNotFoundContent(builder); + } + }); } async Task IHandleAfterRender.OnAfterRenderAsync() diff --git a/src/Components/test/E2ETest/ServerRenderingTests/NoInteractivityTest.cs b/src/Components/test/E2ETest/ServerRenderingTests/NoInteractivityTest.cs index c7af49fc7b3f..35f7140f9170 100644 --- a/src/Components/test/E2ETest/ServerRenderingTests/NoInteractivityTest.cs +++ b/src/Components/test/E2ETest/ServerRenderingTests/NoInteractivityTest.cs @@ -136,6 +136,9 @@ public void CanRenderNotFoundPageNoStreaming(bool useCustomNotFoundPage) { var infoText = Browser.FindElement(By.Id("test-info")).Text; Assert.Contains("Welcome On Custom Not Found Page", infoText); + // custom page should have a custom layout + var aboutLink = Browser.FindElement(By.Id("about-link")).Text; + Assert.Contains("About", aboutLink); } else { diff --git a/src/Components/test/E2ETest/Tests/GlobalInteractivityTest.cs b/src/Components/test/E2ETest/Tests/GlobalInteractivityTest.cs index 5f91c4b684f7..0595baa95bc0 100644 --- a/src/Components/test/E2ETest/Tests/GlobalInteractivityTest.cs +++ b/src/Components/test/E2ETest/Tests/GlobalInteractivityTest.cs @@ -39,6 +39,9 @@ public void CanRenderNotFoundInteractive(string renderingMode, bool useCustomNot { var infoText = Browser.FindElement(By.Id("test-info")).Text; Assert.Contains("Welcome On Custom Not Found Page", infoText); + // custom page should have a custom layout + var aboutLink = Browser.FindElement(By.Id("about-link")).Text; + Assert.Contains("About", aboutLink); } else { diff --git a/src/Components/test/testassets/Components.WasmMinimal/Pages/CustomNotFoundPage.razor b/src/Components/test/testassets/Components.WasmMinimal/Pages/CustomNotFoundPage.razor deleted file mode 100644 index fc48947d6ec2..000000000000 --- a/src/Components/test/testassets/Components.WasmMinimal/Pages/CustomNotFoundPage.razor +++ /dev/null @@ -1,4 +0,0 @@ -@page "/render-custom-not-found-page" - -

Welcome On Custom Not Found Page

-

Sorry, the page you are looking for does not exist.

\ No newline at end of file diff --git a/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/CustomNotFoundPage.razor b/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/CustomNotFoundPage.razor new file mode 100644 index 000000000000..ed03f17c7ccb --- /dev/null +++ b/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/CustomNotFoundPage.razor @@ -0,0 +1,5 @@ +@page "/render-custom-not-found-page" +@layout NotFoundLayout + +

Welcome On Custom Not Found Page

+

Sorry, the page you are looking for does not exist.

diff --git a/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/NotFoundLayout.razor b/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/NotFoundLayout.razor new file mode 100644 index 000000000000..a84f973cc8ea --- /dev/null +++ b/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/NotFoundLayout.razor @@ -0,0 +1,23 @@ +@inherits LayoutComponentBase + +
+
+ About +
+
+
+ @Body +
+
+
+ + diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWeb-CSharp.Client/_Imports.razor b/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWeb-CSharp.Client/_Imports.razor index c311ee7d72d8..6bf14edd8d56 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWeb-CSharp.Client/_Imports.razor +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWeb-CSharp.Client/_Imports.razor @@ -10,3 +10,6 @@ @using Microsoft.AspNetCore.Components.Web.Virtualization @using Microsoft.JSInterop @using BlazorWeb_CSharp.Client +@*#if (!UseServer && UseWebAssembly && InteractiveAtRoot) --> +@using BlazorWeb_CSharp.Client.Layout +##endif*@ \ No newline at end of file diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWeb-CSharp/Components/Pages/NotFound.razor b/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWeb-CSharp/Components/Pages/NotFound.razor index 52784945efc4..917ada1d2328 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWeb-CSharp/Components/Pages/NotFound.razor +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWeb-CSharp/Components/Pages/NotFound.razor @@ -1,4 +1,5 @@ @page "/not-found" +@layout MainLayout

Not Found

Sorry, the content you are looking for does not exist.

\ No newline at end of file diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWeb-CSharp/Components/_Imports.razor b/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWeb-CSharp/Components/_Imports.razor index d73d6a9c9820..a7dddbc39f32 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWeb-CSharp/Components/_Imports.razor +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWeb-CSharp/Components/_Imports.razor @@ -17,6 +17,6 @@ @using BlazorWeb_CSharp.Client.Layout ##endif*@ @using BlazorWeb_CSharp.Components -@*#if (UseServer && (!UseWebAssembly || !InteractiveAtRoot)) --> +@*#if (UseServer || !InteractiveAtRoot) --> @using BlazorWeb_CSharp.Components.Layout ##endif*@ diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/App.razor b/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/App.razor index 15669dfec87b..faa98a6b8b42 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/App.razor +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/App.razor @@ -1,7 +1,7 @@ @*#if (NoAuth) - + @@ -13,7 +13,7 @@ #else - + diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Pages/NotFound.razor b/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Pages/NotFound.razor new file mode 100644 index 000000000000..917ada1d2328 --- /dev/null +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Pages/NotFound.razor @@ -0,0 +1,5 @@ +@page "/not-found" +@layout MainLayout + +

Not Found

+

Sorry, the content you are looking for does not exist.

\ No newline at end of file diff --git a/src/ProjectTemplates/test/Templates.Tests/template-baselines.json b/src/ProjectTemplates/test/Templates.Tests/template-baselines.json index d8d269531f22..2d2e391f0412 100644 --- a/src/ProjectTemplates/test/Templates.Tests/template-baselines.json +++ b/src/ProjectTemplates/test/Templates.Tests/template-baselines.json @@ -3145,6 +3145,7 @@ "_Imports.razor", "Pages/Counter.razor", "Pages/Home.razor", + "Pages/NotFound.razor", "Pages/Weather.razor", "Layout/MainLayout.razor", "Layout/MainLayout.razor.css", @@ -3227,6 +3228,7 @@ "Pages/Authentication.razor", "Pages/Counter.razor", "Pages/Home.razor", + "Pages/NotFound.razor", "Pages/Weather.razor", "Layout/MainLayout.razor", "Layout/MainLayout.razor.css", @@ -3318,6 +3320,7 @@ "Pages/Authentication.razor", "Pages/Counter.razor", "Pages/Home.razor", + "Pages/NotFound.razor", "Pages/Weather.razor", "Layout/MainLayout.razor", "Layout/MainLayout.razor.css", @@ -3407,6 +3410,7 @@ "Pages/Authentication.razor", "Pages/Counter.razor", "Pages/Home.razor", + "Pages/NotFound.razor", "Pages/Weather.razor", "Layout/MainLayout.razor", "Layout/MainLayout.razor.css", @@ -3495,6 +3499,7 @@ "_Imports.razor", "Pages/Counter.razor", "Pages/Home.razor", + "Pages/NotFound.razor", "Pages/Weather.razor", "Layout/MainLayout.razor", "Layout/MainLayout.razor.css", @@ -3584,6 +3589,7 @@ "_Imports.razor", "Pages/Counter.razor", "Pages/Home.razor", + "Pages/NotFound.razor", "Pages/Weather.razor", "Layout/MainLayout.razor", "Layout/MainLayout.razor.css", From 1c2dcae4c7941dcc529f71741435e8fdb77caa9e Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Wed, 28 May 2025 14:38:15 +0200 Subject: [PATCH 10/20] Fix namespace. --- .../testassets/Components.TestServer/RazorComponents/App.razor | 2 +- .../test/testassets/Components.WasmMinimal/Routes.razor | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponents/App.razor b/src/Components/test/testassets/Components.TestServer/RazorComponents/App.razor index 4418fd392d9b..ace8d627d941 100644 --- a/src/Components/test/testassets/Components.TestServer/RazorComponents/App.razor +++ b/src/Components/test/testassets/Components.TestServer/RazorComponents/App.razor @@ -1,5 +1,5 @@ @using Components.TestServer.RazorComponents.Pages.Forms -@using Components.WasmMinimal.Pages +@using Components.WasmMinimal.Pages.NotFound @code { [Parameter] diff --git a/src/Components/test/testassets/Components.WasmMinimal/Routes.razor b/src/Components/test/testassets/Components.WasmMinimal/Routes.razor index a0807b09bf14..92f41cc8b4f1 100644 --- a/src/Components/test/testassets/Components.WasmMinimal/Routes.razor +++ b/src/Components/test/testassets/Components.WasmMinimal/Routes.razor @@ -1,5 +1,5 @@ @using Microsoft.AspNetCore.Components.Routing -@using Components.WasmMinimal.Pages +@using Components.WasmMinimal.Pages.NotFound @inject NavigationManager NavigationManager @code { From 9f6df0186411a5fff24aa51fffb03944fca4c795 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Wed, 28 May 2025 15:44:18 +0200 Subject: [PATCH 11/20] Make sure that interactive tests work only when interactivity is on. --- .../RedirectionNotFound-Interactive.razor | 8 ++++++-- .../RedirectionNotFoundComponent.razor | 19 ++++++++++++------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFound-Interactive.razor b/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFound-Interactive.razor index 461d8b6f5263..269277bb3be6 100644 --- a/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFound-Interactive.razor +++ b/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFound-Interactive.razor @@ -1,7 +1,7 @@ @page "/redirection-not-found" @page "/reexecution/redirection-not-found" - + @code{ [Parameter, SupplyParameterFromQuery(Name = "renderMode")] @@ -15,5 +15,9 @@ { _renderMode = RenderModeHelper.ParseRenderMode(RenderModeStr); } + else + { + throw new ArgumentException("RenderModeStr cannot be null or empty. Did you mean to redirect to /redirection-not-found-ssr?", nameof(RenderModeStr)); + } } -} \ No newline at end of file +} diff --git a/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFoundComponent.razor b/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFoundComponent.razor index 241052e41ed3..68df9c6e0c8c 100644 --- a/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFoundComponent.razor +++ b/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFoundComponent.razor @@ -1,12 +1,14 @@ - -@inject NavigationManager NavigationManager +@inject NavigationManager NavigationManager -

Original page

+@if (!WaitForInteractivity || RendererInfo.IsInteractive) +{ +

Original page

-

Any content

- - Go to not-existing-page - +

Any content

+ + Go to not-existing-page + +} @code{ [Parameter] @@ -16,6 +18,9 @@ [Parameter] public bool StartStreaming { get; set; } = false; + [Parameter] + public bool WaitForInteractivity { get; set; } = false; + private string _nonExistingPath = string.Empty; protected override async Task OnInitializedAsync() From b69773a8c4e99e7a44af6aba8a2112911249e55d Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Wed, 28 May 2025 16:11:59 +0200 Subject: [PATCH 12/20] Fix: link has to have ID to check if layout is rendered. --- .../Components.WasmMinimal/Pages/NotFound/NotFoundLayout.razor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/NotFoundLayout.razor b/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/NotFoundLayout.razor index a84f973cc8ea..14f82987bc24 100644 --- a/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/NotFoundLayout.razor +++ b/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/NotFoundLayout.razor @@ -2,7 +2,7 @@
- About + About
From f1bbf65cb69f4ffca584c0bdd3885aaadb4e15de Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Wed, 28 May 2025 17:52:38 +0200 Subject: [PATCH 13/20] Fix: Wrong placing of NotFoundPage parameter. --- .../content/ComponentsWebAssembly-CSharp/App.razor | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/App.razor b/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/App.razor index faa98a6b8b42..1bc4054ba5f8 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/App.razor +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/App.razor @@ -1,7 +1,7 @@ @*#if (NoAuth) - + - + From a10a0fb8b85c6f45de4939bf4c778b2829265515 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Wed, 28 May 2025 17:55:57 +0200 Subject: [PATCH 14/20] Whitespace --- .../content/ComponentsWebAssembly-CSharp/App.razor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/App.razor b/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/App.razor index 1bc4054ba5f8..1962afdd3be6 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/App.razor +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/App.razor @@ -13,7 +13,7 @@ #else - + From 561c04c977026791836d65eecedb46302dd17a4d Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Thu, 29 May 2025 09:20:41 +0200 Subject: [PATCH 15/20] Empty templates should not contain `NotFound.razor`. --- .../content/BlazorWeb-CSharp/.template.config/template.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/.template.config/template.json b/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/.template.config/template.json index 09f28a39ffee..33be40a65c2f 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/.template.config/template.json +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/.template.config/template.json @@ -116,6 +116,7 @@ "exclude": [ "BlazorWeb-CSharp/Components/Pages/Auth.*", "BlazorWeb-CSharp/Components/Pages/Counter.*", + "BlazorWeb-CSharp/Components/Pages/NotFound.*", "BlazorWeb-CSharp/Components/Pages/Weather.*", "BlazorWeb-CSharp/Components/Layout/NavMenu.*", "BlazorWeb-CSharp/wwwroot/lib/**", From 8d96617a862b275ff5be2f974cc236eb9ad6347d Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Thu, 29 May 2025 09:51:47 +0200 Subject: [PATCH 16/20] Move layout import for -ai Auto from server to client project. --- .../BlazorWeb-CSharp/BlazorWeb-CSharp.Client/_Imports.razor | 2 +- .../BlazorWeb-CSharp/BlazorWeb-CSharp/Components/_Imports.razor | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWeb-CSharp.Client/_Imports.razor b/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWeb-CSharp.Client/_Imports.razor index 6bf14edd8d56..79c334fb2ef0 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWeb-CSharp.Client/_Imports.razor +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWeb-CSharp.Client/_Imports.razor @@ -10,6 +10,6 @@ @using Microsoft.AspNetCore.Components.Web.Virtualization @using Microsoft.JSInterop @using BlazorWeb_CSharp.Client -@*#if (!UseServer && UseWebAssembly && InteractiveAtRoot) --> +@*#if (UseWebAssembly && InteractiveAtRoot) --> @using BlazorWeb_CSharp.Client.Layout ##endif*@ \ No newline at end of file diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWeb-CSharp/Components/_Imports.razor b/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWeb-CSharp/Components/_Imports.razor index a7dddbc39f32..a2d4bcbc031e 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWeb-CSharp/Components/_Imports.razor +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWeb-CSharp/Components/_Imports.razor @@ -17,6 +17,6 @@ @using BlazorWeb_CSharp.Client.Layout ##endif*@ @using BlazorWeb_CSharp.Components -@*#if (UseServer || !InteractiveAtRoot) --> +@*#if ((UseServer && !UseWebAssembly) || !InteractiveAtRoot) --> @using BlazorWeb_CSharp.Components.Layout ##endif*@ From 90f6f0fd876bec8884e32808a40e79f0e51c24e4 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Thu, 29 May 2025 12:04:47 +0200 Subject: [PATCH 17/20] Feedback: use `RouteView`. --- .../Components/src/Routing/Router.cs | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/Components/Components/src/Routing/Router.cs b/src/Components/Components/src/Routing/Router.cs index ec3b2538317b..9e89c937b56b 100644 --- a/src/Components/Components/src/Routing/Router.cs +++ b/src/Components/Components/src/Routing/Router.cs @@ -398,23 +398,14 @@ private void RenderNotFound() { if (NotFoundPage != null) { + builder.OpenComponent(0); + builder.AddAttribute(1, nameof(RouteView.RouteData), + new RouteData(NotFoundPage, _emptyParametersDictionary)); if (_notFoundLayoutType is Type layoutType) { - // Directly instantiate the layout type, supplying the NotFoundPage as the Body - builder.OpenComponent(0, layoutType); - builder.AddAttribute(1, LayoutComponentBase.BodyPropertyName, - (RenderFragment)(childBuilder => - { - childBuilder.OpenComponent(2, NotFoundPage); - childBuilder.CloseComponent(); - })); - builder.CloseComponent(); - } - else - { - builder.OpenComponent(0, NotFoundPage); - builder.CloseComponent(); + builder.AddAttribute(2, nameof(RouteView.DefaultLayout), layoutType); } + builder.CloseComponent(); } else if (NotFound != null) { From bdc5050e10ccff6217d167f02ad9f7bed8b594a4 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Thu, 29 May 2025 12:41:44 +0200 Subject: [PATCH 18/20] Feedback: explicit layout passing is not necessary when rendering with `RouteView`. --- src/Components/Components/src/LayoutAttribute.cs | 1 - src/Components/Components/src/Routing/Router.cs | 13 +------------ 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/src/Components/Components/src/LayoutAttribute.cs b/src/Components/Components/src/LayoutAttribute.cs index 30de25ca6568..b7249f82c60c 100644 --- a/src/Components/Components/src/LayoutAttribute.cs +++ b/src/Components/Components/src/LayoutAttribute.cs @@ -36,6 +36,5 @@ public LayoutAttribute([DynamicallyAccessedMembers(Component)] Type layoutType) /// The type of the layout. The type must implement /// and must accept a parameter with the name 'Body'. /// - [DynamicallyAccessedMembers(Component)] public Type LayoutType { get; private set; } } diff --git a/src/Components/Components/src/Routing/Router.cs b/src/Components/Components/src/Routing/Router.cs index 9e89c937b56b..6edf8750cb36 100644 --- a/src/Components/Components/src/Routing/Router.cs +++ b/src/Components/Components/src/Routing/Router.cs @@ -42,9 +42,6 @@ static readonly IReadOnlyDictionary _emptyParametersDictionary private bool _onNavigateCalled; - [DynamicallyAccessedMembers(LinkerFlags.Component)] - private Type? _notFoundLayoutType; - [Inject] private NavigationManager NavigationManager { get; set; } [Inject] private INavigationInterception NavigationInterception { get; set; } @@ -157,11 +154,7 @@ public async Task SetParametersAsync(ParameterView parameters) if (routeAttributes.Length == 0) { throw new InvalidOperationException($"The type {NotFoundPage.FullName} " + - $"does not have a {typeof(RouteAttribute).FullName} applied to it."); - } - - var layoutAttr = NotFoundPage.GetTypeInfo().GetCustomAttribute(); - _notFoundLayoutType = layoutAttr?.LayoutType; + $"does not have a {typeof(RouteAttribu } if (!_onNavigateCalled) @@ -401,10 +394,6 @@ private void RenderNotFound() builder.OpenComponent(0); builder.AddAttribute(1, nameof(RouteView.RouteData), new RouteData(NotFoundPage, _emptyParametersDictionary)); - if (_notFoundLayoutType is Type layoutType) - { - builder.AddAttribute(2, nameof(RouteView.DefaultLayout), layoutType); - } builder.CloseComponent(); } else if (NotFound != null) From 05169c907d752b9337898cac70f338a20813dd1c Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Thu, 29 May 2025 13:20:59 +0200 Subject: [PATCH 19/20] Fix misscommit. --- src/Components/Components/src/Routing/Router.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Components/Components/src/Routing/Router.cs b/src/Components/Components/src/Routing/Router.cs index 6edf8750cb36..51fb3fc823d2 100644 --- a/src/Components/Components/src/Routing/Router.cs +++ b/src/Components/Components/src/Routing/Router.cs @@ -154,7 +154,8 @@ public async Task SetParametersAsync(ParameterView parameters) if (routeAttributes.Length == 0) { throw new InvalidOperationException($"The type {NotFoundPage.FullName} " + - $"does not have a {typeof(RouteAttribu + $"does not have a {typeof(RouteAttribute).FullName} applied to it."); + } } if (!_onNavigateCalled) From 1e207c2f0a3934827b7f59606856a1878f66f667 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Fri, 30 May 2025 12:37:53 +0200 Subject: [PATCH 20/20] Add error pages middlewarefor reexecution + use status code pages on static files as well. --- .../RazorComponentEndpointsNoInteractivityStartup.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsNoInteractivityStartup.cs b/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsNoInteractivityStartup.cs index 7257fafa898d..4520d9202397 100644 --- a/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsNoInteractivityStartup.cs +++ b/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsNoInteractivityStartup.cs @@ -50,8 +50,13 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.Map("/reexecution", reexecutionApp => { - reexecutionApp.UseStaticFiles(); + if (!env.IsDevelopment()) + { + app.UseExceptionHandler("/Error", createScopeForErrors: true); + } + reexecutionApp.UseStatusCodePagesWithReExecute("/not-found-reexecute", createScopeForErrors: true); + reexecutionApp.UseStaticFiles(); reexecutionApp.UseRouting(); RazorComponentEndpointsStartup.UseFakeAuthState(reexecutionApp); reexecutionApp.UseAntiforgery();