Skip to content

Commit c39bc6a

Browse files
authored
[Blazor] Move to MapBlazorWebAssemblyApplication (#19147)
Move to MapBlazorWebAssemblyApplication as the way to map blazor files into a hosted application.
1 parent 09ee6a7 commit c39bc6a

File tree

14 files changed

+134
-74
lines changed

14 files changed

+134
-74
lines changed

src/Components/Blazor.sln

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

src/Components/WebAssembly/DevServer/src/Server/Startup.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@ public void ConfigureServices(IServiceCollection services)
2828
{
2929
services.AddRouting();
3030

31-
services.AddWebAssemblyStaticFilesConfiguration();
32-
3331
services.AddResponseCompression(options =>
3432
{
3533
options.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(new[]
@@ -54,6 +52,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment environment,
5452

5553
app.UseEndpoints(endpoints =>
5654
{
55+
endpoints.MapBlazorWebAssemblyApplication();
5756
endpoints.MapFallbackToFile("index.html");
5857
});
5958
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Net.Mime;
6+
using Microsoft.AspNetCore.Hosting;
7+
using Microsoft.AspNetCore.Http;
8+
using Microsoft.AspNetCore.Routing;
9+
using Microsoft.AspNetCore.StaticFiles;
10+
using Microsoft.Extensions.DependencyInjection;
11+
using Microsoft.Extensions.FileProviders;
12+
using Microsoft.Net.Http.Headers;
13+
14+
namespace Microsoft.AspNetCore.Builder
15+
{
16+
/// <summary>
17+
/// Extensions for mapping Blazor WebAssembly applications.
18+
/// </summary>
19+
public static class ComponentsWebAssemblyEndpointRouteBuilderExtensions
20+
{
21+
/// <summary>
22+
/// Maps a Blazor webassembly application to the <paramref name="pathPrefix"/>.
23+
/// </summary>
24+
/// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/>.</param>
25+
/// <param name="pathPrefix">The <see cref="PathString"/> that indicates the prefix for the Blazor application.</param>
26+
/// <returns>The <see cref="IEndpointConventionBuilder"/></returns>
27+
public static IEndpointConventionBuilder MapBlazorWebAssemblyApplication(this IEndpointRouteBuilder endpoints, PathString pathPrefix)
28+
{
29+
if (endpoints is null)
30+
{
31+
throw new ArgumentNullException(nameof(endpoints));
32+
}
33+
34+
var webHostEnvironment = endpoints.ServiceProvider.GetRequiredService<IWebHostEnvironment>();
35+
36+
var options = CreateStaticFilesOptions(webHostEnvironment.WebRootFileProvider);
37+
var appBuilder = endpoints.CreateApplicationBuilder();
38+
39+
appBuilder.Use(async (ctx, next) =>
40+
{
41+
var endpoint = ctx.GetEndpoint();
42+
try
43+
{
44+
// Set the endpoint to null so that static files doesn't discard the path.
45+
ctx.SetEndpoint(null);
46+
47+
if (ctx.Request.Path.StartsWithSegments(pathPrefix, out var rest) &&
48+
rest.StartsWithSegments("/_framework"))
49+
{
50+
// At this point we mapped something from the /_framework
51+
ctx.Response.Headers.Append(HeaderNames.CacheControl, "no-cache");
52+
}
53+
54+
// This will invoke the static files middleware plugged-in below.
55+
await next();
56+
57+
}
58+
finally
59+
{
60+
ctx.SetEndpoint(endpoint);
61+
}
62+
});
63+
64+
appBuilder.UseStaticFiles(options);
65+
66+
var conventionBuilder = endpoints.Map(
67+
$"{pathPrefix}/{{*path:file}}",
68+
appBuilder.Build());
69+
70+
conventionBuilder.Add(builder =>
71+
{
72+
// Map this route with low priority so that it doesn't interfere with any other potential request.
73+
((RouteEndpointBuilder)builder).Order = int.MaxValue - 100;
74+
});
75+
76+
return conventionBuilder;
77+
}
78+
79+
/// <summary>
80+
/// Maps a Blazor webassembly application to the root path of the application "/".
81+
/// </summary>
82+
/// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/>.</param>
83+
/// <param name="pathPrefix">The <see cref="PathString"/> that indicates the prefix for the Blazor application.</param>
84+
/// <returns>The <see cref="IEndpointConventionBuilder"/></returns>
85+
public static IEndpointConventionBuilder MapBlazorWebAssemblyApplication(this IEndpointRouteBuilder endpoints) =>
86+
MapBlazorWebAssemblyApplication(endpoints, default);
87+
88+
private static StaticFileOptions CreateStaticFilesOptions(IFileProvider webRootFileProvider)
89+
{
90+
var options = new StaticFileOptions();
91+
options.FileProvider = webRootFileProvider;
92+
var contentTypeProvider = new FileExtensionContentTypeProvider();
93+
AddMapping(contentTypeProvider, ".dll", MediaTypeNames.Application.Octet);
94+
// We unconditionally map pdbs as there will be no pdbs in the output folder for
95+
// release builds unless BlazorEnableDebugging is explicitly set to true.
96+
AddMapping(contentTypeProvider, ".pdb", MediaTypeNames.Application.Octet);
97+
98+
options.ContentTypeProvider = contentTypeProvider;
99+
100+
return options;
101+
}
102+
103+
private static void AddMapping(FileExtensionContentTypeProvider provider, string name, string mimeType)
104+
{
105+
if (!provider.Mappings.ContainsKey(name))
106+
{
107+
provider.Mappings.Add(name, mimeType);
108+
}
109+
}
110+
}
111+
}

src/Components/WebAssembly/Server/src/Services/ComponentsWebAssemblyServiceCollectionExtensions.cs

Lines changed: 0 additions & 51 deletions
This file was deleted.

src/Components/WebAssembly/testassets/HostedInAspNet.Server/Startup.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ public class Startup
1515
public void ConfigureServices(IServiceCollection services)
1616
{
1717
services.AddSingleton<RequestLog>();
18-
services.AddWebAssemblyStaticFilesConfiguration();
1918
}
2019

2120
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
@@ -34,12 +33,11 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, RequestL
3433
app.UseBlazorDebugging();
3534
}
3635

37-
app.UseStaticFiles();
38-
3936
app.UseRouting();
4037

4138
app.UseEndpoints(endpoints =>
4239
{
40+
endpoints.MapBlazorWebAssemblyApplication();
4341
endpoints.MapFallbackToFile("index.html");
4442
});
4543
}

src/Components/WebAssembly/testassets/MonoSanity/Startup.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ public class Startup
1010
{
1111
public void ConfigureServices(IServiceCollection services)
1212
{
13-
services.AddWebAssemblyStaticFilesConfiguration();
1413
}
1514

1615
public void Configure(IApplicationBuilder app)
@@ -21,6 +20,7 @@ public void Configure(IApplicationBuilder app)
2120
app.UseRouting();
2221
app.UseEndpoints(endpoints =>
2322
{
23+
endpoints.MapBlazorWebAssemblyApplication();
2424
endpoints.MapFallbackToFile("index.html");
2525
});
2626
}

src/Components/WebAssembly/testassets/Wasm.Authentication.Server/Startup.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@ public void ConfigureServices(IServiceCollection services)
3737
services.AddAuthentication()
3838
.AddIdentityServerJwt();
3939

40-
services.AddWebAssemblyStaticFilesConfiguration();
41-
4240
services.AddMvc();
4341
services.AddResponseCompression(opts =>
4442
{
@@ -58,8 +56,6 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
5856
app.UseBlazorDebugging();
5957
}
6058

61-
app.UseStaticFiles();
62-
6359
app.UseRouting();
6460

6561
app.UseAuthentication();
@@ -70,6 +66,8 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
7066
{
7167
endpoints.MapControllers();
7268
endpoints.MapRazorPages();
69+
70+
endpoints.MapBlazorWebAssemblyApplication();
7371
endpoints.MapFallbackToFile("index.html");
7472
});
7573
}

src/Components/test/E2ETest/Tests/BootResourceCachingTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public void CachesResourcesAfterFirstLoad()
5757
var subsequentResourcesRequested = GetAndClearRequestedPaths();
5858
Assert.NotEmpty(initialResourcesRequested.Where(path => path.EndsWith("/blazor.boot.json")));
5959
Assert.Empty(subsequentResourcesRequested.Where(path => path.EndsWith("/dotnet.wasm")));
60-
Assert.Empty(subsequentResourcesRequested.Where(path => path.EndsWith(".js")));
60+
Assert.NotEmpty(subsequentResourcesRequested.Where(path => path.EndsWith(".js")));
6161
Assert.Empty(subsequentResourcesRequested.Where(path => path.EndsWith(".dll")));
6262
}
6363

src/Components/test/testassets/TestServer/AuthenticationStartup.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@ public void ConfigureServices(IServiceCollection services)
2828

2929
services.AddServerSideBlazor();
3030

31-
services.AddWebAssemblyStaticFilesConfiguration();
32-
3331
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie();
3432
services.AddAuthorization(options =>
3533
{
@@ -56,6 +54,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
5654
app.UseRouting();
5755
app.UseEndpoints(endpoints =>
5856
{
57+
endpoints.MapBlazorWebAssemblyApplication();
5958
endpoints.MapControllers();
6059
endpoints.MapRazorPages();
6160
endpoints.MapBlazorHub();

src/Components/test/testassets/TestServer/ClientStartup.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ public void ConfigureServices(IServiceCollection services)
2323
{
2424
services.AddMvc();
2525
services.AddServerSideBlazor();
26-
services.AddWebAssemblyStaticFilesConfiguration();
2726
}
2827

2928
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
@@ -43,6 +42,8 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
4342
app.UseRouting();
4443
app.UseEndpoints(endpoints =>
4544
{
45+
endpoints.MapBlazorWebAssemblyApplication();
46+
4647
endpoints.MapRazorPages();
4748
endpoints.MapControllers();
4849
endpoints.MapFallbackToFile("index.html");

src/Components/test/testassets/TestServer/CorsStartup.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ public CorsStartup(IConfiguration configuration)
1919
public void ConfigureServices(IServiceCollection services)
2020
{
2121
services.AddMvc();
22-
services.AddWebAssemblyStaticFilesConfiguration();
2322
services.AddCors(options =>
2423
{
2524
// It's not enough just to return "Access-Control-Allow-Origin: *", because
@@ -54,6 +53,8 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
5453

5554
app.UseEndpoints(endpoints =>
5655
{
56+
endpoints.MapBlazorWebAssemblyApplication();
57+
5758
endpoints.MapControllers();
5859
endpoints.MapFallbackToFile("index.html");
5960
});

src/Components/test/testassets/TestServer/InternationalizationStartup.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ public void ConfigureServices(IServiceCollection services)
2323
{
2424
services.AddMvc();
2525
services.AddServerSideBlazor();
26-
services.AddWebAssemblyStaticFilesConfiguration();
2726
}
2827

2928
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
@@ -55,6 +54,8 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
5554
app.UseRouting();
5655
app.UseEndpoints(endpoints =>
5756
{
57+
endpoints.MapBlazorWebAssemblyApplication();
58+
5859
endpoints.MapControllers();
5960
endpoints.MapBlazorHub();
6061
endpoints.MapFallbackToPage("/_ServerHost");

src/Components/test/testassets/TestServer/StartupWithMapFallbackToClientSideBlazor.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ public StartupWithMapFallbackToClientSideBlazor(IConfiguration configuration)
2121

2222
public void ConfigureServices(IServiceCollection services)
2323
{
24-
services.AddWebAssemblyStaticFilesConfiguration();
2524
}
2625

2726
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
@@ -34,7 +33,12 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
3433
// The client-side files middleware needs to be here because the base href in hardcoded to /subdir/
3534
app.Map("/subdir", app =>
3635
{
37-
app.UseStaticFiles();
36+
app.UseRouting();
37+
38+
app.UseEndpoints(endpoints =>
39+
{
40+
endpoints.MapBlazorWebAssemblyApplication();
41+
});
3842
});
3943

4044
// The calls to `Map` allow us to test each of these overloads, while keeping them isolated.

src/ProjectTemplates/ComponentsWebAssembly.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Server/Startup.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,6 @@ public void ConfigureServices(IServiceCollection services)
7171
services.AddRazorPages();
7272
#endif
7373

74-
services.AddWebAssemblyStaticFilesConfiguration();
75-
7674
services.AddResponseCompression(opts =>
7775
{
7876
opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
@@ -127,6 +125,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
127125
#endif
128126
endpoints.MapControllers();
129127

128+
endpoints.MapBlazorWebAssemblyApplication();
130129
endpoints.MapFallbackToFile("index.html");
131130
});
132131
}

0 commit comments

Comments
 (0)