diff --git a/src/Components/Components/src/Routing/Router.cs b/src/Components/Components/src/Routing/Router.cs index 2d2afadc3d39..51fb3fc823d2 100644 --- a/src/Components/Components/src/Routing/Router.cs +++ b/src/Components/Components/src/Routing/Router.cs @@ -223,7 +223,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 +286,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,25 +382,32 @@ private void OnNotFound(object sender, EventArgs args) if (_renderHandle.IsInitialized) { Log.DisplayingNotFound(_logger); - _renderHandle.Render(builder => - { - if (NotFoundPage != null) - { - builder.OpenComponent(0, NotFoundPage); - builder.CloseComponent(); - } - else if (NotFound != null) - { - NotFound(builder); - } - else - { - DefaultNotFoundContent(builder); - } - }); + RenderNotFound(); } } + private void RenderNotFound() + { + _renderHandle.Render(builder => + { + if (NotFoundPage != null) + { + builder.OpenComponent(0); + builder.AddAttribute(1, nameof(RouteView.RouteData), + new RouteData(NotFoundPage, _emptyParametersDictionary)); + builder.CloseComponent(); + } + else if (NotFound != null) + { + NotFound(builder); + } + else + { + DefaultNotFoundContent(builder); + } + }); + } + async Task IHandleAfterRender.OnAfterRenderAsync() { if (!_navigationInterceptionEnabled) diff --git a/src/Components/test/E2ETest/ServerRenderingTests/InteractivityTest.cs b/src/Components/test/E2ETest/ServerRenderingTests/InteractivityTest.cs index 286a6de9e12d..dd9f2a3a47e8 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?renderMode={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?renderMode={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?renderMode={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/E2ETest/ServerRenderingTests/NoInteractivityTest.cs b/src/Components/test/E2ETest/ServerRenderingTests/NoInteractivityTest.cs index 139f3db4726e..35f7140f9170 100644 --- a/src/Components/test/E2ETest/ServerRenderingTests/NoInteractivityTest.cs +++ b/src/Components/test/E2ETest/ServerRenderingTests/NoInteractivityTest.cs @@ -87,6 +87,43 @@ public void CanRenderNotFoundPageAfterStreamingStarted() Browser.Equal("Default Not Found Page", () => Browser.Title); } + [Theory] + [InlineData(true)] + [InlineData(false)] + public void ProgrammaticNavigationToNotExistingPathReExecutesTo404(bool streaming) + { + string streamingPath = streaming ? "-streaming" : ""; + Navigate($"{ServerPathBase}/reexecution/redirection-not-found-ssr{streamingPath}?navigate-programmatically=true"); + Assert404ReExecuted(); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void LinkNavigationToNotExistingPathReExecutesTo404(bool streaming) + { + string streamingPath = streaming ? "-streaming" : ""; + Navigate($"{ServerPathBase}/reexecution/redirection-not-found-ssr{streamingPath}"); + Browser.Click(By.Id("link-to-not-existing-page")); + Assert404ReExecuted(); + } + + [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 + string streamingPath = streaming ? "-streaming" : ""; + Navigate($"{ServerPathBase}/reexecution/not-existing-page-ssr{streamingPath}"); + 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)] @@ -99,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.TestServer/RazorComponentEndpointsNoInteractivityStartup.cs b/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsNoInteractivityStartup.cs index c4af233c40fe..7257fafa898d 100644 --- a/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsNoInteractivityStartup.cs +++ b/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsNoInteractivityStartup.cs @@ -48,19 +48,37 @@ 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.UseStaticFiles(); + reexecutionApp.UseStatusCodePagesWithReExecute("/not-found-reexecute", createScopeForErrors: true); + reexecutionApp.UseRouting(); + RazorComponentEndpointsStartup.UseFakeAuthState(reexecutionApp); + reexecutionApp.UseAntiforgery(); + reexecutionApp.UseEndpoints(endpoints => + { + endpoints.MapRazorComponents(); + }); }); + + 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..ea4f7f7ad220 100644 --- a/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsStartup.cs +++ b/src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsStartup.cs @@ -76,20 +76,17 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.Map("/reexecution", reexecutionApp => { reexecutionApp.UseStatusCodePagesWithReExecute("/not-found-reexecute", createScopeForErrors: true); - reexecutionApp.UseRouting(); + reexecutionApp.UseAntiforgery(); - reexecutionApp.UseEndpoints(endpoints => - { - endpoints.MapRazorComponents(); - }); + ConfigureEndpoints(reexecutionApp, env); }); ConfigureSubdirPipeline(app, env); }); } - protected virtual void ConfigureSubdirPipeline(IApplicationBuilder app, IWebHostEnvironment env) + private void ConfigureSubdirPipeline(IApplicationBuilder app, IWebHostEnvironment env) { WebAssemblyTestHelper.ServeCoopHeadersIfWebAssemblyThreadingEnabled(app); @@ -106,11 +103,15 @@ protected virtual void ConfigureSubdirPipeline(IApplicationBuilder app, IWebHost { 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/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.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-SSR-streaming.razor b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR-streaming.razor new file mode 100644 index 000000000000..74374799ce04 --- /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 new file mode 100644 index 000000000000..80a579a2e456 --- /dev/null +++ b/src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/NotFound/RedirectionNotFound-SSR.razor @@ -0,0 +1,5 @@ +@page "/redirection-not-found-ssr" +@page "/reexecution/redirection-not-found-ssr" +@attribute [StreamRendering(false)] + + \ No newline at end of file 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 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/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/NotFoundLayout.razor b/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/NotFoundLayout.razor new file mode 100644 index 000000000000..14f82987bc24 --- /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/Components/test/testassets/Components.WasmMinimal/Pages/NotFoundSSR.razor b/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/NotFoundSSR.razor similarity index 100% rename from src/Components/test/testassets/Components.WasmMinimal/Pages/NotFoundSSR.razor rename to src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/NotFoundSSR.razor 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..269277bb3be6 --- /dev/null +++ b/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFound-Interactive.razor @@ -0,0 +1,23 @@ +@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); + } + else + { + throw new ArgumentException("RenderModeStr cannot be null or empty. Did you mean to redirect to /redirection-not-found-ssr?", nameof(RenderModeStr)); + } + } +} diff --git a/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFoundComponent.razor b/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFoundComponent.razor new file mode 100644 index 000000000000..68df9c6e0c8c --- /dev/null +++ b/src/Components/test/testassets/Components.WasmMinimal/Pages/NotFound/RedirectionNotFoundComponent.razor @@ -0,0 +1,38 @@ +@inject NavigationManager NavigationManager + +@if (!WaitForInteractivity || RendererInfo.IsInteractive) +{ +

Original page

+ +

Any content

+ + Go to not-existing-page + +} + +@code{ + [Parameter] + [SupplyParameterFromQuery(Name = "navigate-programmatically")] + public bool? NavigateProgrammatically { get; set; } + + [Parameter] + public bool StartStreaming { get; set; } = false; + + [Parameter] + public bool WaitForInteractivity { get; set; } = false; + + private string _nonExistingPath = string.Empty; + + protected override async Task OnInitializedAsync() + { + if (StartStreaming) + { + await Task.Yield(); + } + _nonExistingPath = $"{NavigationManager.BaseUri}reexecution/not-existing-page"; + if (NavigateProgrammatically == true) + { + NavigationManager.NavigateTo(_nonExistingPath); + } + } +} 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) 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 { 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/**", 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..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,3 +10,6 @@ @using Microsoft.AspNetCore.Components.Web.Virtualization @using Microsoft.JSInterop @using BlazorWeb_CSharp.Client +@*#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/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..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 && (!UseWebAssembly || !InteractiveAtRoot)) --> +@*#if ((UseServer && !UseWebAssembly) || !InteractiveAtRoot) --> @using BlazorWeb_CSharp.Components.Layout ##endif*@ 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(); diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/App.razor b/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/App.razor index 15669dfec87b..1962afdd3be6 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",