[Blazor] Move to MapBlazorWebAssemblyApplication (#19147)

Move to MapBlazorWebAssemblyApplication as the way to map blazor files into a hosted application.
This commit is contained in:
Javier Calvarro Nelson 2020-02-19 23:56:43 -08:00 committed by GitHub
parent 09ee6a79b4
commit c39bc6a6bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 134 additions and 74 deletions

View File

@ -552,9 +552,9 @@ Global
{C4D74173-702B-428A-B689-1A9AF51CE356} = {B29FB58D-FAE5-405E-9695-BCF93582BE9A}
{B3EF0C88-3466-40AE-9080-F694370F4192} = {C4D74173-702B-428A-B689-1A9AF51CE356}
{2916EC17-1D1F-4949-9EC7-50725157F1A6} = {C4D74173-702B-428A-B689-1A9AF51CE356}
{7EFB9CAF-6716-43BF-A6EF-C2878E95F8A6} = {B4ACD900-27B6-482B-B434-2C1E86E9D8BC}
{194EBC45-F98E-4919-B714-C1624EF17B31} = {B4ACD900-27B6-482B-B434-2C1E86E9D8BC}
{EAF50654-98ED-44BB-A120-0436EC0CD3E0} = {B4ACD900-27B6-482B-B434-2C1E86E9D8BC}
{7EFB9CAF-6716-43BF-A6EF-C2878E95F8A6} = {CBD2BB24-3EC3-4950-ABE4-8C521D258DCD}
{194EBC45-F98E-4919-B714-C1624EF17B31} = {CBD2BB24-3EC3-4950-ABE4-8C521D258DCD}
{EAF50654-98ED-44BB-A120-0436EC0CD3E0} = {CBD2BB24-3EC3-4950-ABE4-8C521D258DCD}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {27A36094-AA50-4FFD-ADE6-C055E391F741}

View File

@ -28,8 +28,6 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.DevServer.Server
{
services.AddRouting();
services.AddWebAssemblyStaticFilesConfiguration();
services.AddResponseCompression(options =>
{
options.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(new[]
@ -54,6 +52,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.DevServer.Server
app.UseEndpoints(endpoints =>
{
endpoints.MapBlazorWebAssemblyApplication();
endpoints.MapFallbackToFile("index.html");
});
}

View File

@ -0,0 +1,111 @@
// 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
{
/// <summary>
/// Extensions for mapping Blazor WebAssembly applications.
/// </summary>
public static class ComponentsWebAssemblyEndpointRouteBuilderExtensions
{
/// <summary>
/// Maps a Blazor webassembly application to the <paramref name="pathPrefix"/>.
/// </summary>
/// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/>.</param>
/// <param name="pathPrefix">The <see cref="PathString"/> that indicates the prefix for the Blazor application.</param>
/// <returns>The <see cref="IEndpointConventionBuilder"/></returns>
public static IEndpointConventionBuilder MapBlazorWebAssemblyApplication(this IEndpointRouteBuilder endpoints, PathString pathPrefix)
{
if (endpoints is null)
{
throw new ArgumentNullException(nameof(endpoints));
}
var webHostEnvironment = endpoints.ServiceProvider.GetRequiredService<IWebHostEnvironment>();
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;
}
/// <summary>
/// Maps a Blazor webassembly application to the root path of the application "/".
/// </summary>
/// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/>.</param>
/// <param name="pathPrefix">The <see cref="PathString"/> that indicates the prefix for the Blazor application.</param>
/// <returns>The <see cref="IEndpointConventionBuilder"/></returns>
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);
}
}
}
}

View File

@ -1,51 +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.Net.Mime;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
namespace Microsoft.Extensions.DependencyInjection
{
public static class ComponentsWebAssemblyServiceCollectionExtensions
{
public static IServiceCollection AddWebAssemblyStaticFilesConfiguration(this IServiceCollection services)
{
services.TryAddEnumerable(ServiceDescriptor.Singleton<IConfigureOptions<StaticFileOptions>, ClientSideBlazorStaticFilesConfiguration>());
return services;
}
private class ClientSideBlazorStaticFilesConfiguration : IConfigureOptions<StaticFileOptions>
{
private readonly IWebHostEnvironment _webHostEnvironment;
public ClientSideBlazorStaticFilesConfiguration(IWebHostEnvironment webHostEnvironment)
{
_webHostEnvironment = webHostEnvironment;
}
public void Configure(StaticFileOptions options)
{
options.FileProvider = _webHostEnvironment.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;
}
private static void AddMapping(FileExtensionContentTypeProvider provider, string name, string mimeType)
{
if (!provider.Mappings.ContainsKey(name))
{
provider.Mappings.Add(name, mimeType);
}
}
}
}
}

View File

@ -15,7 +15,6 @@ namespace HostedInAspNet.Server
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<RequestLog>();
services.AddWebAssemblyStaticFilesConfiguration();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
@ -34,12 +33,11 @@ namespace HostedInAspNet.Server
app.UseBlazorDebugging();
}
app.UseStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapBlazorWebAssemblyApplication();
endpoints.MapFallbackToFile("index.html");
});
}

View File

@ -10,7 +10,6 @@ namespace MonoSanity
{
public void ConfigureServices(IServiceCollection services)
{
services.AddWebAssemblyStaticFilesConfiguration();
}
public void Configure(IApplicationBuilder app)
@ -21,6 +20,7 @@ namespace MonoSanity
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapBlazorWebAssemblyApplication();
endpoints.MapFallbackToFile("index.html");
});
}

View File

@ -37,8 +37,6 @@ namespace Wasm.Authentication.Server
services.AddAuthentication()
.AddIdentityServerJwt();
services.AddWebAssemblyStaticFilesConfiguration();
services.AddMvc();
services.AddResponseCompression(opts =>
{
@ -58,8 +56,6 @@ namespace Wasm.Authentication.Server
app.UseBlazorDebugging();
}
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
@ -70,6 +66,8 @@ namespace Wasm.Authentication.Server
{
endpoints.MapControllers();
endpoints.MapRazorPages();
endpoints.MapBlazorWebAssemblyApplication();
endpoints.MapFallbackToFile("index.html");
});
}

View File

@ -57,7 +57,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
var subsequentResourcesRequested = GetAndClearRequestedPaths();
Assert.NotEmpty(initialResourcesRequested.Where(path => path.EndsWith("/blazor.boot.json")));
Assert.Empty(subsequentResourcesRequested.Where(path => path.EndsWith("/dotnet.wasm")));
Assert.Empty(subsequentResourcesRequested.Where(path => path.EndsWith(".js")));
Assert.NotEmpty(subsequentResourcesRequested.Where(path => path.EndsWith(".js")));
Assert.Empty(subsequentResourcesRequested.Where(path => path.EndsWith(".dll")));
}

View File

@ -28,8 +28,6 @@ namespace TestServer
services.AddServerSideBlazor();
services.AddWebAssemblyStaticFilesConfiguration();
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie();
services.AddAuthorization(options =>
{
@ -56,6 +54,7 @@ namespace TestServer
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapBlazorWebAssemblyApplication();
endpoints.MapControllers();
endpoints.MapRazorPages();
endpoints.MapBlazorHub();

View File

@ -23,7 +23,6 @@ namespace TestServer
{
services.AddMvc();
services.AddServerSideBlazor();
services.AddWebAssemblyStaticFilesConfiguration();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
@ -43,6 +42,8 @@ namespace TestServer
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapBlazorWebAssemblyApplication();
endpoints.MapRazorPages();
endpoints.MapControllers();
endpoints.MapFallbackToFile("index.html");

View File

@ -19,7 +19,6 @@ namespace TestServer
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddWebAssemblyStaticFilesConfiguration();
services.AddCors(options =>
{
// It's not enough just to return "Access-Control-Allow-Origin: *", because
@ -54,6 +53,8 @@ namespace TestServer
app.UseEndpoints(endpoints =>
{
endpoints.MapBlazorWebAssemblyApplication();
endpoints.MapControllers();
endpoints.MapFallbackToFile("index.html");
});

View File

@ -23,7 +23,6 @@ namespace TestServer
{
services.AddMvc();
services.AddServerSideBlazor();
services.AddWebAssemblyStaticFilesConfiguration();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
@ -55,6 +54,8 @@ namespace TestServer
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapBlazorWebAssemblyApplication();
endpoints.MapControllers();
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_ServerHost");

View File

@ -21,7 +21,6 @@ namespace TestServer
public void ConfigureServices(IServiceCollection services)
{
services.AddWebAssemblyStaticFilesConfiguration();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
@ -34,7 +33,12 @@ namespace TestServer
// The client-side files middleware needs to be here because the base href in hardcoded to /subdir/
app.Map("/subdir", app =>
{
app.UseStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapBlazorWebAssemblyApplication();
});
});
// The calls to `Map` allow us to test each of these overloads, while keeping them isolated.

View File

@ -71,8 +71,6 @@ namespace ComponentsWebAssembly_CSharp.Server
services.AddRazorPages();
#endif
services.AddWebAssemblyStaticFilesConfiguration();
services.AddResponseCompression(opts =>
{
opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
@ -127,6 +125,7 @@ namespace ComponentsWebAssembly_CSharp.Server
#endif
endpoints.MapControllers();
endpoints.MapBlazorWebAssemblyApplication();
endpoints.MapFallbackToFile("index.html");
});
}