Skip to content

Commit b7abe1e

Browse files
authored
[Blazor] Fix publish with different combinations of SWA base paths (#28539)
Description #28017 In 5.0.1 we fixed a publish scenario where Blazor webassembly wasn't respecting the StaticWebAssetBasePath defined for the project. Unfortunately the logic for handling the path composition was not robust enough and while it fixed the publish output layout, it introduced an integration issue later on at runtime. The current fix makes the handling of the path more tolerant to initial and final slashes and includes a new end to end test that validates this scenario. Customer Impact Customers can't host blazor applications outside the root path (/) Regression? Yes. Worked in 3.2 Risk Low. We've included additional tests and E2E automation to verify this case. Validation Automated Manual
1 parent a8646e3 commit b7abe1e

File tree

13 files changed

+252
-26
lines changed

13 files changed

+252
-26
lines changed

AspNetCore.sln

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1503,7 +1503,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.App.Un
15031503
EndProject
15041504
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Localization", "Localization", "{3D34C81F-2CB5-459E-87E9-0CC04757A2A0}"
15051505
EndProject
1506-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GlobalizationWasmApp", "src\Components\test\testassets\GlobalizationWasmApp\GlobalizationWasmApp.csproj", "{04CFE286-6D32-41EF-8887-4B5F8086A365}"
1506+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GlobalizationWasmApp", "src\Components\test\testassets\GlobalizationWasmApp\GlobalizationWasmApp.csproj", "{04CFE286-6D32-41EF-8887-4B5F8086A365}"
15071507
EndProject
15081508
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Localization.Abstractions", "src\Localization\Abstractions\src\Microsoft.Extensions.Localization.Abstractions.csproj", "{FEF97646-9BC9-4D1B-A939-784D915C18A4}"
15091509
EndProject
@@ -1539,6 +1539,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sdk", "Sdk", "{E83B0BCC-A8E
15391539
EndProject
15401540
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HostingStartup", "src\SiteExtensions\Sdk\HostingStartup\HostingStartup.csproj", "{5D6F99C5-D292-4459-B8BD-8E4AD42E1B21}"
15411541
EndProject
1542+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CustomBasePathApp", "src\Components\WebAssembly\testassets\CustomBasePathApp\CustomBasePathApp.csproj", "{E2461809-D2EA-436D-B5C3-8A9EE0A283B8}"
1543+
EndProject
15421544
Global
15431545
GlobalSection(SolutionConfigurationPlatforms) = preSolution
15441546
Debug|Any CPU = Debug|Any CPU
@@ -7199,18 +7201,6 @@ Global
71997201
{BAD47859-95DF-4C8F-9AF7-C48B68F478A1}.Release|x64.Build.0 = Release|Any CPU
72007202
{BAD47859-95DF-4C8F-9AF7-C48B68F478A1}.Release|x86.ActiveCfg = Release|Any CPU
72017203
{BAD47859-95DF-4C8F-9AF7-C48B68F478A1}.Release|x86.Build.0 = Release|Any CPU
7202-
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
7203-
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|Any CPU.Build.0 = Debug|Any CPU
7204-
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|x64.ActiveCfg = Debug|Any CPU
7205-
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|x64.Build.0 = Debug|Any CPU
7206-
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|x86.ActiveCfg = Debug|Any CPU
7207-
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|x86.Build.0 = Debug|Any CPU
7208-
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|Any CPU.ActiveCfg = Release|Any CPU
7209-
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|Any CPU.Build.0 = Release|Any CPU
7210-
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|x64.ActiveCfg = Release|Any CPU
7211-
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|x64.Build.0 = Release|Any CPU
7212-
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|x86.ActiveCfg = Release|Any CPU
7213-
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|x86.Build.0 = Release|Any CPU
72147204
{010A9638-F20E-4FE6-A186-85732BFC9CB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
72157205
{010A9638-F20E-4FE6-A186-85732BFC9CB0}.Debug|Any CPU.Build.0 = Debug|Any CPU
72167206
{010A9638-F20E-4FE6-A186-85732BFC9CB0}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -7223,6 +7213,18 @@ Global
72237213
{010A9638-F20E-4FE6-A186-85732BFC9CB0}.Release|x64.Build.0 = Release|Any CPU
72247214
{010A9638-F20E-4FE6-A186-85732BFC9CB0}.Release|x86.ActiveCfg = Release|Any CPU
72257215
{010A9638-F20E-4FE6-A186-85732BFC9CB0}.Release|x86.Build.0 = Release|Any CPU
7216+
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
7217+
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|Any CPU.Build.0 = Debug|Any CPU
7218+
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|x64.ActiveCfg = Debug|Any CPU
7219+
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|x64.Build.0 = Debug|Any CPU
7220+
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|x86.ActiveCfg = Debug|Any CPU
7221+
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|x86.Build.0 = Debug|Any CPU
7222+
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|Any CPU.ActiveCfg = Release|Any CPU
7223+
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|Any CPU.Build.0 = Release|Any CPU
7224+
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|x64.ActiveCfg = Release|Any CPU
7225+
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|x64.Build.0 = Release|Any CPU
7226+
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|x86.ActiveCfg = Release|Any CPU
7227+
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|x86.Build.0 = Release|Any CPU
72267228
{FEF97646-9BC9-4D1B-A939-784D915C18A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
72277229
{FEF97646-9BC9-4D1B-A939-784D915C18A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
72287230
{FEF97646-9BC9-4D1B-A939-784D915C18A4}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -7367,6 +7369,18 @@ Global
73677369
{5D6F99C5-D292-4459-B8BD-8E4AD42E1B21}.Release|x64.Build.0 = Release|Any CPU
73687370
{5D6F99C5-D292-4459-B8BD-8E4AD42E1B21}.Release|x86.ActiveCfg = Release|Any CPU
73697371
{5D6F99C5-D292-4459-B8BD-8E4AD42E1B21}.Release|x86.Build.0 = Release|Any CPU
7372+
{E2461809-D2EA-436D-B5C3-8A9EE0A283B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
7373+
{E2461809-D2EA-436D-B5C3-8A9EE0A283B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
7374+
{E2461809-D2EA-436D-B5C3-8A9EE0A283B8}.Debug|x64.ActiveCfg = Debug|Any CPU
7375+
{E2461809-D2EA-436D-B5C3-8A9EE0A283B8}.Debug|x64.Build.0 = Debug|Any CPU
7376+
{E2461809-D2EA-436D-B5C3-8A9EE0A283B8}.Debug|x86.ActiveCfg = Debug|Any CPU
7377+
{E2461809-D2EA-436D-B5C3-8A9EE0A283B8}.Debug|x86.Build.0 = Debug|Any CPU
7378+
{E2461809-D2EA-436D-B5C3-8A9EE0A283B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
7379+
{E2461809-D2EA-436D-B5C3-8A9EE0A283B8}.Release|Any CPU.Build.0 = Release|Any CPU
7380+
{E2461809-D2EA-436D-B5C3-8A9EE0A283B8}.Release|x64.ActiveCfg = Release|Any CPU
7381+
{E2461809-D2EA-436D-B5C3-8A9EE0A283B8}.Release|x64.Build.0 = Release|Any CPU
7382+
{E2461809-D2EA-436D-B5C3-8A9EE0A283B8}.Release|x86.ActiveCfg = Release|Any CPU
7383+
{E2461809-D2EA-436D-B5C3-8A9EE0A283B8}.Release|x86.Build.0 = Release|Any CPU
73707384
EndGlobalSection
73717385
GlobalSection(SolutionProperties) = preSolution
73727386
HideSolutionNode = FALSE
@@ -8117,10 +8131,10 @@ Global
81178131
{37329855-01B8-4B03-9765-1A941B06E43C} = {8C15FD04-7F90-43FC-B488-023432FE3CE1}
81188132
{D3246226-BC1A-47F1-8E3E-C3380A8F13FB} = {8C15FD04-7F90-43FC-B488-023432FE3CE1}
81198133
{B06ADD57-E855-4D8C-85DC-B323509AE540} = {898F7E0B-1671-42CB-9DFB-689AFF212ED3}
8120-
{04CFE286-6D32-41EF-8887-4B5F8086A365} = {6126DCE4-9692-4EE2-B240-C65743572995}
81218134
{BAD47859-95DF-4C8F-9AF7-C48B68F478A1} = {A4C26078-B6D8-4FD8-87A6-7C15A3482038}
81228135
{010A9638-F20E-4FE6-A186-85732BFC9CB0} = {A4C26078-B6D8-4FD8-87A6-7C15A3482038}
81238136
{3D34C81F-2CB5-459E-87E9-0CC04757A2A0} = {017429CC-C5FB-48B4-9C46-034E29EE2F06}
8137+
{04CFE286-6D32-41EF-8887-4B5F8086A365} = {6126DCE4-9692-4EE2-B240-C65743572995}
81248138
{FEF97646-9BC9-4D1B-A939-784D915C18A4} = {3D34C81F-2CB5-459E-87E9-0CC04757A2A0}
81258139
{839CE175-E0D9-43B9-9FA8-F32C47E7F56B} = {3D34C81F-2CB5-459E-87E9-0CC04757A2A0}
81268140
{50BF2926-7435-4F4B-88A9-3D0EDEB67FC8} = {3D34C81F-2CB5-459E-87E9-0CC04757A2A0}
@@ -8138,6 +8152,7 @@ Global
81388152
{545751D5-71FC-4889-A3A0-BBD731DBA18A} = {56B45580-B089-424E-A847-A6115D591950}
81398153
{E83B0BCC-A8E0-4FBD-BE51-9A533C9CB972} = {DFC4F588-B4B4-484B-AB93-B36721374AD3}
81408154
{5D6F99C5-D292-4459-B8BD-8E4AD42E1B21} = {E83B0BCC-A8E0-4FBD-BE51-9A533C9CB972}
8155+
{E2461809-D2EA-436D-B5C3-8A9EE0A283B8} = {7D2B0799-A634-42AC-AE77-5D167BA51389}
81418156
EndGlobalSection
81428157
GlobalSection(ExtensibilityGlobals) = postSolution
81438158
SolutionGuid = {3E8720B3-DBDD-498C-B383-2CC32A054E8F}

src/Components/ComponentsNoDeps.slnf

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
"src\\Components\\WebAssembly\\WebAssembly.Authentication\\test\\Microsoft.AspNetCore.Components.WebAssembly.Authentication.Tests.csproj",
3030
"src\\Components\\WebAssembly\\WebAssembly\\src\\Microsoft.AspNetCore.Components.WebAssembly.csproj",
3131
"src\\Components\\WebAssembly\\WebAssembly\\test\\Microsoft.AspNetCore.Components.WebAssembly.Tests.csproj",
32+
"src\\Components\\WebAssembly\\testassets\\CustomBasePathApp\\CustomBasePathApp.csproj",
3233
"src\\Components\\WebAssembly\\testassets\\HostedInAspNet.Client\\HostedInAspNet.Client.csproj",
3334
"src\\Components\\WebAssembly\\testassets\\HostedInAspNet.Server\\HostedInAspNet.Server.csproj",
3435
"src\\Components\\WebAssembly\\testassets\\StandaloneApp\\StandaloneApp.csproj",
@@ -48,4 +49,4 @@
4849
"src\\Components\\test\\testassets\\TestServer\\Components.TestServer.csproj"
4950
]
5051
}
51-
}
52+
}

src/Components/WebAssembly/Sdk/integrationtests/WasmPublishIntegrationTest.cs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -252,14 +252,18 @@ public async Task Publish_WithNoBuild_Works()
252252
VerifyCompression(result, blazorPublishDirectory);
253253
}
254254

255-
[Fact]
256-
public async Task Publish_WithStaticWebBasePathWorks()
255+
[Theory]
256+
[InlineData("different-path")]
257+
[InlineData("/different-path")]
258+
[InlineData("different-path/")]
259+
[InlineData("/different-path/")]
260+
public async Task Publish_WithStaticWebBasePathWorks(string basePath)
257261
{
258262
// Arrange
259263
using var project = ProjectDirectory.Create("blazorwasm", "razorclasslibrary");
260264
project.AddProjectFileContent(
261-
@"<PropertyGroup>
262-
<StaticWebAssetBasePath>different-path/</StaticWebAssetBasePath>
265+
$@"<PropertyGroup>
266+
<StaticWebAssetBasePath>{basePath}</StaticWebAssetBasePath>
263267
</PropertyGroup>");
264268
var result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish");
265269

@@ -300,14 +304,18 @@ public async Task Publish_WithStaticWebBasePathWorks()
300304
staticWebAssetsBasePath: "different-path");
301305
}
302306

303-
[Fact]
304-
public async Task Publish_Hosted_WithStaticWebBasePathWorks()
307+
[Theory]
308+
[InlineData("different-path")]
309+
[InlineData("/different-path")]
310+
[InlineData("different-path/")]
311+
[InlineData("/different-path/")]
312+
public async Task Publish_Hosted_WithStaticWebBasePathWorks(string basePath)
305313
{
306314
using var project = ProjectDirectory.Create("blazorhosted", additionalProjects: new[] { "blazorwasm", "razorclasslibrary", });
307315
var wasmProject = project.GetSibling("blazorwasm");
308316
wasmProject.AddProjectFileContent(
309-
@"<PropertyGroup>
310-
<StaticWebAssetBasePath>different-path/</StaticWebAssetBasePath>
317+
$@"<PropertyGroup>
318+
<StaticWebAssetBasePath>{basePath}</StaticWebAssetBasePath>
311319
</PropertyGroup>");
312320
var result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish");
313321

src/Components/WebAssembly/Sdk/src/targets/Microsoft.NET.Sdk.BlazorWebAssembly.Current.targets

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ Copyright (c) .NET Foundation. All rights reserved.
457457
</JoinItems>
458458

459459
<PropertyGroup>
460-
<_BlazorPublishOutputPath Condition="'$(StaticWebAssetBasePath)' != '/'">wwwroot\$(StaticWebAssetBasePath.Replace('/', '\'))</_BlazorPublishOutputPath>
460+
<_BlazorPublishOutputPath Condition="'$(StaticWebAssetBasePath)' != '/'">wwwroot\$(StaticWebAssetBasePath.Replace('/', '\').Trim('\'))\</_BlazorPublishOutputPath>
461461
<_BlazorPublishOutputPath Condition="'$(StaticWebAssetBasePath)' == '/'">wwwroot\</_BlazorPublishOutputPath>
462462
<_BlazorFrameworkPublishPath>$(_BlazorPublishOutputPath)_framework\</_BlazorFrameworkPublishPath>
463463
</PropertyGroup>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Image from custom path: <img src="img/red-square.png" />
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
2+
3+
<PropertyGroup>
4+
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
5+
<StaticWebAssetBasePath>/app</StaticWebAssetBasePath>
6+
</PropertyGroup>
7+
8+
<ItemGroup>
9+
<Reference Include="Microsoft.AspNetCore.Components.WebAssembly" />
10+
<Reference Include="System.Net.Http.Json" />
11+
</ItemGroup>
12+
13+
<!-- A bit of msbuild magic to support reference resolver tests -->
14+
<Target Name="CreateReferenceHintPathsList" AfterTargets="ResolveAssemblyReferences">
15+
<ItemGroup>
16+
<_BclFile Include="$(ComponentsWebAssemblyBaseClassLibraryPath)*" />
17+
<_BclFile Include="$(ComponentsWebAssemblyBaseClassLibraryFacadesPath)*" />
18+
<_BclFile Include="$(ComponentsWebAssemblyFrameworkPath)*" />
19+
</ItemGroup>
20+
21+
<WriteLinesToFile Lines="@(ReferencePath);@(ReferenceDependencyPaths)" File="$(IntermediateOutputPath)referenceHints.txt" WriteOnlyWhenDifferent="true" Overwrite="true" />
22+
<WriteLinesToFile Lines="@(_BclFile)" File="$(IntermediateOutputPath)bclLocations.txt" WriteOnlyWhenDifferent="true" Overwrite="true" />
23+
24+
<ItemGroup>
25+
<EmbeddedResource Include="$(IntermediateOutputPath)bclLocations.txt" Link="bclLocations.txt" Type="Non-Resx" />
26+
<EmbeddedResource Include="$(IntermediateOutputPath)referenceHints.txt" Link="referenceHints.txt" Type="Non-Resx" />
27+
</ItemGroup>
28+
</Target>
29+
30+
</Project>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
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.Http;
6+
using System.Threading.Tasks;
7+
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
8+
using Microsoft.Extensions.DependencyInjection;
9+
10+
namespace CustomBasePathApp
11+
{
12+
public class Program
13+
{
14+
public static async Task Main(string[] args)
15+
{
16+
var builder = WebAssemblyHostBuilder.CreateDefault(args);
17+
builder.RootComponents.Add<App>("app");
18+
19+
await builder.Build().RunAsync();
20+
}
21+
}
22+
}
201 Bytes
Loading
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
<!-- Forcing the device width here so that our automated tests work consistently on mobile browsers. -->
6+
<meta name="viewport" content="width=1024">
7+
<title>App loaded on custom path</title>
8+
<base href="/app/" />
9+
</head>
10+
<body>
11+
<app>Loading...</app>
12+
<script src="_framework/blazor.webassembly.js"></script>
13+
</body>
14+
</html>

src/Components/WebAssembly/testassets/HostedInAspNet.Server/HostedInAspNet.Server.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
</PropertyGroup>
66

77
<ItemGroup>
8+
<ProjectReference Include="..\CustomBasePathApp\CustomBasePathApp.csproj" />
89
<ProjectReference Include="..\HostedInAspNet.Client\HostedInAspNet.Client.csproj" />
910
</ItemGroup>
1011

0 commit comments

Comments
 (0)