From 9ded8e17d44ef22d71ca3062246faafa208b2298 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Fri, 21 Feb 2020 04:20:41 -0800 Subject: [PATCH] Change MapBlazorWebAssemblyApplication to UseBlazorFrameworkFiles (#19198) --- .../DevServer/src/Server/Startup.cs | 2 +- ...WebAssemblyApplicationBuilderExtensions.cs | 86 ++++++++++++++ ...bAssemblyEndpointRouteBuilderExtensions.cs | 111 ------------------ .../HostedInAspNet.Server/Startup.cs | 4 +- .../testassets/MonoSanity/Startup.cs | 2 +- .../Wasm.Authentication.Server/Startup.cs | 4 +- .../TestServer/AuthenticationStartup.cs | 2 +- .../testassets/TestServer/ClientStartup.cs | 3 +- .../test/testassets/TestServer/CorsStartup.cs | 3 +- .../TestServer/InternationalizationStartup.cs | 3 +- ...tartupWithMapFallbackToClientSideBlazor.cs | 8 +- .../Server/Startup.cs | 3 +- 12 files changed, 101 insertions(+), 130 deletions(-) create mode 100644 src/Components/WebAssembly/Server/src/ComponentsWebAssemblyApplicationBuilderExtensions.cs delete mode 100644 src/Components/WebAssembly/Server/src/ComponentsWebAssemblyEndpointRouteBuilderExtensions.cs diff --git a/src/Components/WebAssembly/DevServer/src/Server/Startup.cs b/src/Components/WebAssembly/DevServer/src/Server/Startup.cs index 84bf7ac852..6b6c2a91f0 100644 --- a/src/Components/WebAssembly/DevServer/src/Server/Startup.cs +++ b/src/Components/WebAssembly/DevServer/src/Server/Startup.cs @@ -46,13 +46,13 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.DevServer.Server app.UseBlazorDebugging(); + app.UseBlazorFrameworkFiles(); app.UseStaticFiles(); app.UseRouting(); app.UseEndpoints(endpoints => { - endpoints.MapBlazorWebAssemblyApplication(); endpoints.MapFallbackToFile("index.html"); }); } diff --git a/src/Components/WebAssembly/Server/src/ComponentsWebAssemblyApplicationBuilderExtensions.cs b/src/Components/WebAssembly/Server/src/ComponentsWebAssemblyApplicationBuilderExtensions.cs new file mode 100644 index 0000000000..eaf19da09e --- /dev/null +++ b/src/Components/WebAssembly/Server/src/ComponentsWebAssemblyApplicationBuilderExtensions.cs @@ -0,0 +1,86 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Net.Mime; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.StaticFiles; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.FileProviders; +using Microsoft.Net.Http.Headers; + +namespace Microsoft.AspNetCore.Builder +{ + /// + /// Extensions for mapping Blazor WebAssembly applications. + /// + public static class ComponentsWebAssemblyApplicationBuilderExtensions + { + /// + /// Configures the application to serve Blazor WebAssembly framework files from the path . This path must correspond to a referenced Blazor WebAssembly application project. + /// + /// The . + /// The that indicates the prefix for the Blazor WebAssembly application. + /// The + public static IApplicationBuilder MapBlazorFrameworkFiles(this IApplicationBuilder builder, PathString pathPrefix) + { + if (builder is null) + { + throw new ArgumentNullException(nameof(builder)); + } + + var webHostEnvironment = builder.ApplicationServices.GetRequiredService(); + + var options = CreateStaticFilesOptions(webHostEnvironment.WebRootFileProvider); + + builder.MapWhen(ctx => ctx.Request.Path.StartsWithSegments(pathPrefix, out var rest) && rest.StartsWithSegments("/_framework") && !rest.StartsWithSegments("/_framework/blazor.server.js"), + subBuilder => + { + subBuilder.Use(async (ctx, next) => + { + // At this point we mapped something from the /_framework + ctx.Response.Headers.Append(HeaderNames.CacheControl, "no-cache"); + // This will invoke the static files middleware plugged-in below. + await next(); + }); + + subBuilder.UseStaticFiles(options); + }); + + return builder; + } + + /// + /// Configures the application to serve Blazor WebAssembly framework files from the root path "/". + /// + /// The . + /// The that indicates the prefix for the Blazor WebAssembly application. + /// The + public static IApplicationBuilder UseBlazorFrameworkFiles(this IApplicationBuilder applicationBuilder) => + MapBlazorFrameworkFiles(applicationBuilder, default); + + private static StaticFileOptions CreateStaticFilesOptions(IFileProvider webRootFileProvider) + { + var options = new StaticFileOptions(); + options.FileProvider = webRootFileProvider; + var contentTypeProvider = new FileExtensionContentTypeProvider(); + AddMapping(contentTypeProvider, ".dll", MediaTypeNames.Application.Octet); + // We unconditionally map pdbs as there will be no pdbs in the output folder for + // release builds unless BlazorEnableDebugging is explicitly set to true. + AddMapping(contentTypeProvider, ".pdb", MediaTypeNames.Application.Octet); + + options.ContentTypeProvider = contentTypeProvider; + + return options; + } + + private static void AddMapping(FileExtensionContentTypeProvider provider, string name, string mimeType) + { + if (!provider.Mappings.ContainsKey(name)) + { + provider.Mappings.Add(name, mimeType); + } + } + } +} diff --git a/src/Components/WebAssembly/Server/src/ComponentsWebAssemblyEndpointRouteBuilderExtensions.cs b/src/Components/WebAssembly/Server/src/ComponentsWebAssemblyEndpointRouteBuilderExtensions.cs deleted file mode 100644 index d29212ff75..0000000000 --- a/src/Components/WebAssembly/Server/src/ComponentsWebAssemblyEndpointRouteBuilderExtensions.cs +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Net.Mime; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Routing; -using Microsoft.AspNetCore.StaticFiles; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.FileProviders; -using Microsoft.Net.Http.Headers; - -namespace Microsoft.AspNetCore.Builder -{ - /// - /// Extensions for mapping Blazor WebAssembly applications. - /// - public static class ComponentsWebAssemblyEndpointRouteBuilderExtensions - { - /// - /// Maps a Blazor webassembly application to the . - /// - /// The . - /// The that indicates the prefix for the Blazor application. - /// The - public static IEndpointConventionBuilder MapBlazorWebAssemblyApplication(this IEndpointRouteBuilder endpoints, PathString pathPrefix) - { - if (endpoints is null) - { - throw new ArgumentNullException(nameof(endpoints)); - } - - var webHostEnvironment = endpoints.ServiceProvider.GetRequiredService(); - - var options = CreateStaticFilesOptions(webHostEnvironment.WebRootFileProvider); - var appBuilder = endpoints.CreateApplicationBuilder(); - - appBuilder.Use(async (ctx, next) => - { - var endpoint = ctx.GetEndpoint(); - try - { - // Set the endpoint to null so that static files doesn't discard the path. - ctx.SetEndpoint(null); - - if (ctx.Request.Path.StartsWithSegments(pathPrefix, out var rest) && - rest.StartsWithSegments("/_framework")) - { - // At this point we mapped something from the /_framework - ctx.Response.Headers.Append(HeaderNames.CacheControl, "no-cache"); - } - - // This will invoke the static files middleware plugged-in below. - await next(); - - } - finally - { - ctx.SetEndpoint(endpoint); - } - }); - - appBuilder.UseStaticFiles(options); - - var conventionBuilder = endpoints.Map( - $"{pathPrefix}/{{*path:file}}", - appBuilder.Build()); - - conventionBuilder.Add(builder => - { - // Map this route with low priority so that it doesn't interfere with any other potential request. - ((RouteEndpointBuilder)builder).Order = int.MaxValue - 100; - }); - - return conventionBuilder; - } - - /// - /// Maps a Blazor webassembly application to the root path of the application "/". - /// - /// The . - /// The that indicates the prefix for the Blazor application. - /// The - public static IEndpointConventionBuilder MapBlazorWebAssemblyApplication(this IEndpointRouteBuilder endpoints) => - MapBlazorWebAssemblyApplication(endpoints, default); - - private static StaticFileOptions CreateStaticFilesOptions(IFileProvider webRootFileProvider) - { - var options = new StaticFileOptions(); - options.FileProvider = webRootFileProvider; - var contentTypeProvider = new FileExtensionContentTypeProvider(); - AddMapping(contentTypeProvider, ".dll", MediaTypeNames.Application.Octet); - // We unconditionally map pdbs as there will be no pdbs in the output folder for - // release builds unless BlazorEnableDebugging is explicitly set to true. - AddMapping(contentTypeProvider, ".pdb", MediaTypeNames.Application.Octet); - - options.ContentTypeProvider = contentTypeProvider; - - return options; - } - - private static void AddMapping(FileExtensionContentTypeProvider provider, string name, string mimeType) - { - if (!provider.Mappings.ContainsKey(name)) - { - provider.Mappings.Add(name, mimeType); - } - } - } -} diff --git a/src/Components/WebAssembly/testassets/HostedInAspNet.Server/Startup.cs b/src/Components/WebAssembly/testassets/HostedInAspNet.Server/Startup.cs index a605d10ded..32dcb9d80f 100644 --- a/src/Components/WebAssembly/testassets/HostedInAspNet.Server/Startup.cs +++ b/src/Components/WebAssembly/testassets/HostedInAspNet.Server/Startup.cs @@ -33,11 +33,13 @@ namespace HostedInAspNet.Server app.UseBlazorDebugging(); } + app.UseBlazorFrameworkFiles(); + app.UseStaticFiles(); + app.UseRouting(); app.UseEndpoints(endpoints => { - endpoints.MapBlazorWebAssemblyApplication(); endpoints.MapFallbackToFile("index.html"); }); } diff --git a/src/Components/WebAssembly/testassets/MonoSanity/Startup.cs b/src/Components/WebAssembly/testassets/MonoSanity/Startup.cs index f777cbc4b3..3cf349e787 100644 --- a/src/Components/WebAssembly/testassets/MonoSanity/Startup.cs +++ b/src/Components/WebAssembly/testassets/MonoSanity/Startup.cs @@ -16,11 +16,11 @@ namespace MonoSanity { app.UseDeveloperExceptionPage(); app.UseFileServer(new FileServerOptions() { EnableDefaultFiles = true, }); + app.UseBlazorFrameworkFiles(); app.UseStaticFiles(); app.UseRouting(); app.UseEndpoints(endpoints => { - endpoints.MapBlazorWebAssemblyApplication(); endpoints.MapFallbackToFile("index.html"); }); } diff --git a/src/Components/WebAssembly/testassets/Wasm.Authentication.Server/Startup.cs b/src/Components/WebAssembly/testassets/Wasm.Authentication.Server/Startup.cs index 58c8fdb2c1..f7fdfab434 100644 --- a/src/Components/WebAssembly/testassets/Wasm.Authentication.Server/Startup.cs +++ b/src/Components/WebAssembly/testassets/Wasm.Authentication.Server/Startup.cs @@ -56,6 +56,9 @@ namespace Wasm.Authentication.Server app.UseBlazorDebugging(); } + app.UseBlazorFrameworkFiles(); + app.UseStaticFiles(); + app.UseRouting(); app.UseAuthentication(); @@ -67,7 +70,6 @@ namespace Wasm.Authentication.Server endpoints.MapControllers(); endpoints.MapRazorPages(); - endpoints.MapBlazorWebAssemblyApplication(); endpoints.MapFallbackToFile("index.html"); }); } diff --git a/src/Components/test/testassets/TestServer/AuthenticationStartup.cs b/src/Components/test/testassets/TestServer/AuthenticationStartup.cs index 261587c9ee..ca6648d133 100644 --- a/src/Components/test/testassets/TestServer/AuthenticationStartup.cs +++ b/src/Components/test/testassets/TestServer/AuthenticationStartup.cs @@ -49,12 +49,12 @@ namespace TestServer // Mount the server-side Blazor app on /subdir app.Map("/subdir", app => { + app.UseBlazorFrameworkFiles(); app.UseStaticFiles(); app.UseRouting(); app.UseEndpoints(endpoints => { - endpoints.MapBlazorWebAssemblyApplication(); endpoints.MapControllers(); endpoints.MapRazorPages(); endpoints.MapBlazorHub(); diff --git a/src/Components/test/testassets/TestServer/ClientStartup.cs b/src/Components/test/testassets/TestServer/ClientStartup.cs index 4d4161b13d..b3a1633422 100644 --- a/src/Components/test/testassets/TestServer/ClientStartup.cs +++ b/src/Components/test/testassets/TestServer/ClientStartup.cs @@ -37,13 +37,12 @@ namespace TestServer app.Map("/subdir", app => { // Add it before to ensure it takes priority over files in wwwroot + app.UseBlazorFrameworkFiles(); app.UseStaticFiles(); app.UseRouting(); app.UseEndpoints(endpoints => { - endpoints.MapBlazorWebAssemblyApplication(); - endpoints.MapRazorPages(); endpoints.MapControllers(); endpoints.MapFallbackToFile("index.html"); diff --git a/src/Components/test/testassets/TestServer/CorsStartup.cs b/src/Components/test/testassets/TestServer/CorsStartup.cs index c6ed533955..8674037117 100644 --- a/src/Components/test/testassets/TestServer/CorsStartup.cs +++ b/src/Components/test/testassets/TestServer/CorsStartup.cs @@ -45,6 +45,7 @@ namespace TestServer // Mount the server-side Blazor app on /subdir app.Map("/subdir", app => { + app.UseBlazorFrameworkFiles(); app.UseStaticFiles(); app.UseRouting(); @@ -53,8 +54,6 @@ namespace TestServer app.UseEndpoints(endpoints => { - endpoints.MapBlazorWebAssemblyApplication(); - endpoints.MapControllers(); endpoints.MapFallbackToFile("index.html"); }); diff --git a/src/Components/test/testassets/TestServer/InternationalizationStartup.cs b/src/Components/test/testassets/TestServer/InternationalizationStartup.cs index 5f19ea80f5..ac2fa85eff 100644 --- a/src/Components/test/testassets/TestServer/InternationalizationStartup.cs +++ b/src/Components/test/testassets/TestServer/InternationalizationStartup.cs @@ -36,6 +36,7 @@ namespace TestServer // Mount the server-side Blazor app on /subdir app.Map("/subdir", app => { + app.UseBlazorFrameworkFiles(); app.UseStaticFiles(); app.UseRequestLocalization(options => @@ -54,8 +55,6 @@ namespace TestServer app.UseRouting(); app.UseEndpoints(endpoints => { - endpoints.MapBlazorWebAssemblyApplication(); - endpoints.MapControllers(); endpoints.MapBlazorHub(); endpoints.MapFallbackToPage("/_ServerHost"); diff --git a/src/Components/test/testassets/TestServer/StartupWithMapFallbackToClientSideBlazor.cs b/src/Components/test/testassets/TestServer/StartupWithMapFallbackToClientSideBlazor.cs index 9097914793..382ee8bf10 100644 --- a/src/Components/test/testassets/TestServer/StartupWithMapFallbackToClientSideBlazor.cs +++ b/src/Components/test/testassets/TestServer/StartupWithMapFallbackToClientSideBlazor.cs @@ -33,12 +33,8 @@ namespace TestServer // The client-side files middleware needs to be here because the base href in hardcoded to /subdir/ app.Map("/subdir", app => { - app.UseRouting(); - - app.UseEndpoints(endpoints => - { - endpoints.MapBlazorWebAssemblyApplication(); - }); + app.UseBlazorFrameworkFiles(); + app.UseStaticFiles(); }); // The calls to `Map` allow us to test each of these overloads, while keeping them isolated. diff --git a/src/ProjectTemplates/ComponentsWebAssembly.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Server/Startup.cs b/src/ProjectTemplates/ComponentsWebAssembly.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Server/Startup.cs index 85573e7daf..e37ab2c340 100644 --- a/src/ProjectTemplates/ComponentsWebAssembly.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Server/Startup.cs +++ b/src/ProjectTemplates/ComponentsWebAssembly.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Server/Startup.cs @@ -104,6 +104,7 @@ namespace ComponentsWebAssembly_CSharp.Server } #endif + app.UseBlazorFrameworkFiles(); app.UseStaticFiles(); app.UseRouting(); @@ -124,8 +125,6 @@ namespace ComponentsWebAssembly_CSharp.Server endpoints.MapRazorPages(); #endif endpoints.MapControllers(); - - endpoints.MapBlazorWebAssemblyApplication(); endpoints.MapFallbackToFile("index.html"); }); }