aspnetcore: Multiple hosted Blazor apps get 404 error on blazor.webassembly.js
Describe the bug
I’m trying to create a Razor pages app with multiple Blazor “sub apps” at urls like /app1 and /app2. Everything works fine locally when debugging in Visual Studio but when I publish and try to run locally using the dotnet command (or when I try to host behind an Nginx reverse proxy) I get a 404 error for _framework/blazor.webassembly.js.
Thanks for any help you can offer.
To Reproduce
Below are my steps and the simplest possible repro is at the following public repo:
https://github.com/fuzl-llc/MultipleHostedBlazorApps
In Visual Studio 2019, created project MultipleHostedBlazorApps with default .NET 5.0 “Blazor WebAssembly App” template. Deselected “Configure for HTTPS” and checked “ASP.NET Core hosted.” Checked in.
Added second client project called “Client2” with HTTPS and ASP.NET Core Hosted unchecked. The project, MultipleHostedBlazorApps.Client2, was put in a “Client2” folder next to the existing “Client” folder. Checked in.
Deleted all IIS references from all three project’s launchSettings.json. Left server app to run on port 5000, updated client and client 2 to run on ports 5001 and 5002, respectively. In retrospect I don’t think this matters as all projects load under the host app’s port 5000…
Updated Blazor apps index.html files to have <base href=“/app1/” /> and <base href=“/app2/” /> for client and client2 (and matching page titles).
Started getting: Conflicting assets with the same path ‘/wwwroot/css/app.css’ for content root paths error (but below actions fix it).
Changed each Blazor app’s project file to include: <StaticWebAssetBasePath>app1</StaticWebAssetBasePath> (and <StaticWebAssetBasePath>app2</StaticWebAssetBasePath>) in the top property group under <TargetFramework>net5.0</TargetFramework>
In main host app’s startup file, mapped both Blazor apps using a new extension method called “MapBlazorApp” which uses “MapWhen” to set up each Blazor app to be loaded at “sub app urls” of the main host app, at /app1 and /app2 of the main host app. This does things like UseBlazorFrameworkFiles passing in the new paths - see code for details.
Added an “index” Razor page to the host app with links to the two sub apps. Added links in both Blazor “sub apps” to each other and the host app main page, updated both app’s index page title to show which app they are.
We can now run the app, see both apps working, and click between them.
Checked in.
This seems to be “success” as everything works beautifully when running locally in Visual Studio. The problems come now when I try to deploy… So, we right click and publish the host app. As part of this we change the default folder profile path from bin\Release\net5.0\publish\ to “C:\Temp\Multi.” In that path we then see, under C:\Temp\Multi\wwwroot, folders like app1, app1_framework, app1app1, app1css which at first seems to make sense e.g. the prefix to distinguish framework files but the app1app1 folder seems a bit strange.
I can run the following successfully:
C:\Temp\Multi>dotnet MultipleHostedBlazorApps.Server.dll --urls http://localhost:5000
Everything appears great at first - I see the host app homepage with links to the two sub apps and when I click them I see the standard Blazor “Loading…” message but when I look in Chrome dev tools > Network, I see that http://localhost:5000/app1/_framework/blazor.webassembly.js gets a 404 “Not Found” error and the app never loads. The same thing happens for http://localhost:5000/app2/_framework/blazor.webassembly.js. All other static files seem fine, such as http://localhost:5000/app1/css/bootstrap/bootstrap.min.css and other .css files. If I search for blazor.webassembly.js I find it exists under app1_framework and app2_framework (as well as other versions with .br and .gz extensions appended).
Ultimately I’m trying to host this on Ubuntu via Nginx reverse proxy where I’d set up a config something like this:
server { listen 443 ssl; server_name test.com; ssl_certificate /etc/letsencrypt/live/test.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/test.com/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location /
{
proxy_pass http://localhost:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# works except _framework/blazor.webassembly.js gets returned as the HTML of the root of the site:
location /app1 {
root /var/www/test.com/wwwroot;
try_files $uri $uri/ /app1/index.html;
}
location /app2 {
root /var/www/test.com/wwwroot;
try_files $uri $uri/ /app2/index.html;
}
} server { listen 80; server_name test.com; return 301 https://$host$request_uri; }
It seemed to work similarly where all static (html, css) files work but the blazor.webassembly.js file gives a 404.
How get I get this blazor.webassembly.js file to load properly using (1) the dotnet command locally and (2) hosting behind an Nginx reverse proxy?
Exceptions (if any)
Just a 404 error that blazor.webassembly.js cannot be found.
Further technical details
- ASP.NET Core version:
5.0.101
- Include the output of
dotnet --info
.NET SDK (reflecting any global.json): Version: 5.0.101 Commit: d05174dc5a
Runtime Environment: OS Name: Windows OS Version: 10.0.18363 OS Platform: Windows RID: win10-x64 Base Path: C:\Program Files\dotnet\sdk\5.0.101\
Host (useful for support): Version: 5.0.1 Commit: b02e13abab
.NET SDKs installed: 3.1.301 [C:\Program Files\dotnet\sdk] 3.1.400 [C:\Program Files\dotnet\sdk] 5.0.101 [C:\Program Files\dotnet\sdk]
.NET runtimes installed: Microsoft.AspNetCore.All 2.1.23 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All] Microsoft.AspNetCore.App 2.1.23 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 3.1.10 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 5.0.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.NETCore.App 2.1.23 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 3.1.10 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 5.0.0-rc.1.20451.14 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 5.0.1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.WindowsDesktop.App 3.1.10 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 5.0.1 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
- The IDE (VS / VS Code/ VS4Mac) you’re running on, and its version Visual Studio 2019 v16.8.3
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 70 (9 by maintainers)
When evaluating priority for this, I hope you’ll consider the history - based on issue #27776 filed on Nov 12, 2020, right after .NET 5.0 was released, it seems like the underlying issue for this has had two incomplete/failed fix attempts in 5.0.1 and 5.0.2, each requiring a month wait. So, while this issue only came up for me a few days ago, it appears some people will have been unable to create Blazor apps as subpaths like /app1 for up to 3 months. I’m not sure of your processes but it would be great, if possible, if you could have a “super senior” person like @SteveSandersonMS review and sign off on this one…, hopefully resulting in a 5.0.3 “final” fix. If there was a supported workaround, that would be great too.
@fuzl-llc you have the right SDK (5.0.102), Are you able to either share your app or patch the SDK with our planned changes (https://github.com/dotnet/aspnetcore/pull/29293) to see if it helps? If you were going down the latter route, here’s what you would do:
C:\Program Files\dotnet\sdk
and needs sufficient access to be able to edit this file)C:\Program Files\dotnet\sdk\5.0.102\Sdks\Microsoft.NET.Sdk.BlazorWebAssembly\targets\Microsoft.NET.Sdk.BlazorWebAssembly.Current.targets
.If you continue seeing the issue, I’d be happy to help diagnose it further.
As an aside, I also don’t like monoliths. I actually had these as a main app i.e. app.com and then separate Blazor subdomain apps app1.app.com and app2.app.com. Then I had id.app.com with OIDC auth used by all the apps. I though it was very nice but started running into all kinds of cross domain issues and then read this:
https://leastprivilege.com/2020/03/31/spas-are-dead/
Very interesting read. I was running into some of the very issues mentioned due to cross domain request issues. Yes, I did a bunch of CORS stuff and could make stuff work for now but not sure about the future… I also wanted to experiment with the BFF (backend for frontend) architecture he mentions. It is interesting because having app.com/app1 and app.com/app2 seems like a monolith but if app.com is really a light razor pages app and has a YARP reverse proxy to a separate API project behind it, it starts to feel pretty well separated. And while app1 and app2 appear to be part of the monolithic parent app, actually they are separate VS projects and don’t have any dependencies on the main app. I’m not even sure I’ve convinced myself yet but that’s why I’m experimenting with it. It seems decoupled in some good ways in spite of sharing the same domain and appearing to be one big app. That appearance might actually be good - I kind of like that people know it is all “under” app.com so they know it is all from me and there are no redirects to subdomains. Anyway, I’d like to figure out how to get it working and then continue to evaluate how much I like the architecture.
The code in the repo right now is the one that I think best demonstrates the issue. If you grab that and run it locally (in Visual Studio if you have a copy) it should work perfectly. If you then right click the “Server” project and publish it (or publish it using any of the methods we’ve discussed) and then try to run that locally with Kestrel using the dotnet command you should get the 404 error.