MapStaticAssets silently fails with 500 for assets when running dotnet run without Development environment
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 281
Description
### Is there an existing issue for this?
- [x] I have searched the existing issues
### Describe the bug
When running a Blazor Server app via dotnet run without ASPNETCORE_ENVIRONMENT=Development (e.g., no launchSettings.json), all static assets from NuGet packages (_content/*) and framework assets (_framework/*) return HTTP 500 with FileNotFoundException. Project-local assets in wwwroot/ work fine.
There is no documentation indicating that dotnet run requires the Development environment for NuGet or framework static assets to be served.
### Expected Behavior
When using dotnet run even if the environment is set to production MapStaticAssets should work. At the very least this should produce a proper warning and be a documented limitation.
### Steps To Reproduce
1. dotnet new blazor -n ReproApp
2. cd ReproApp
3. DOTNET_ENVIRONMENT=Production dotnet run
4. Open localhost:5xxx you should see the exceptions
Alternatively:
3. rm Properties/launchSettings.json
4. dotnet run
5. Open localhost:5000 you should see the exceptions.
### Exceptions (if any)
[11:56:05 ERR] Connection id "0HNJFKLSO1PV3", Request id "0HNJFKLSO1PV3:00000004": An unhandled exception was thrown by the application.
System.IO.FileNotFoundException: Could not find file '/PATH_TO_PROJECT/wwwroot/_content/MudBlazor/MudBlazor.min.js'.
File name: '/home/felix/projects/apps/helios-batch-download-support/tools/Helios.DocumentAnalyzer/wwwroot/_content/MudBlazor/MudBlazor.min.js'
at System.IO.FileInfo.get_Length()
at Microsoft.AspNetCore.Builder.StaticAssetDevelopmentRuntimeHandler.<>c__DisplayClass3_0.<b__0>d.MoveNext()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
### .NET Version
10.0.101
### Anything else?
# Root Cause
WebHost.ConfigureWebDefaults gates StaticWebAssetsLoader.UseStaticWebAssets() behind a hard IsDevelopment() check. This loader reads staticwebassets.runtime.json and configures WebRootFileProvider as a CompositeFileProvider that maps virtual paths (e.g., _content/MudBlazor/...) to their physical locations in the NuGet cache.
Without it, WebRootFileProvider is a plain PhysicalFileProvider pointing at wwwroot/, and MapStaticAssets() endpoints try to resolve _content/MudBlazor/MudBlazor.min.css from wwwroot/_content/MudBlazor/MudBlazor.min.css — which doesn't exist (only dotnet publish copies those files there).
MapStaticAssets() itself works in all environments, but it depends on WebRootFileProvider being correctly configured — which only happens in Development.
Contributor guide
Research direction
Start with WebHost.ConfigureWebDefaults and the StaticWebAssetsLoader.UseStaticWebAssets() environment check, then trace how MapStaticAssets resolves _content and _framework paths. Reproduce with a Blazor app using DOTNET_ENVIRONMENT=Production or without launchSettings.json. Done means production dotnet run serves package and framework assets correctly, or emits a documented warning instead of a 500.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- web-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100