Every stylesheet and script your Blazor app serves comes back 200 OK with
Content-Length: 0, and the page renders like 1996 — unstyled text, no icon. The app
is running as Production, and MapStaticAssets is looking for published
assets that a development checkout doesn't have.
dotnet run --no-launch-profile skips launchSettings.json, which is where
ASPNETCORE_ENVIRONMENT=Development normally comes from. With no environment set,
ASP.NET Core defaults to Production, and in Production MapStaticAssets serves from
the optimized asset manifest that dotnet publish produces. Nothing published, nothing
to serve — so each request matches an endpoint and returns an empty body. Set the environment
explicitly, or run with the launch profile.
The error
What the screenshot harness saw, abridged — the web host's real asset paths, every one empty:
GET /_content/ClinicLive.Pocket.Shared/pocket.css 200 OK Content-Length: 0 (no Content-Type)
GET /ClinicLive.Pocket.Web.styles.css 200 OK Content-Length: 0
GET /_content/ClinicLive.Pocket.Shared/pocket.js 200 OK Content-Length: 0
Why it happens
MapStaticAssets (the .NET 9 replacement for UseStaticFiles in the
templates) doesn't walk wwwroot at request time. It reads a manifest the build
generates, listing every static web asset with its fingerprint and precompressed variants, and
maps each to an endpoint. In Development the manifest points at the files in your source tree,
including the _content/ assets that Razor class libraries contribute.
Outside Development the manifest expects the processed copies a publish lays down. In a checkout
that has never been published, the endpoints exist but the files behind them don't, and the
response is a successful request with no body and no content type. Kestrel isn't wrong; it served
exactly what the manifest described. The environment is the only variable — the same command,
with Development set, serves every file.
The fix
Say which environment you mean. The profile the app ships with already does, in Properties/launchSettings.json:
"http": {
"commandName": "Project",
"applicationUrl": "http://localhost:5057",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
So the simplest fix is to stop passing --no-launch-profile. If you need it — a
harness that wants its own port and no browser popping open — set the variable yourself before
the run: $env:ASPNETCORE_ENVIRONMENT = "Development" in PowerShell,
export ASPNETCORE_ENVIRONMENT=Development in a shell. And watch the second bite: on
the server side of this app, Production also meant no demo data, because the demo seed only
runs in Development.
What the AI got wrong: it added --no-launch-profile to keep the
harness quiet, and didn't know the flag silently changes which environment the app thinks it
is in. A flag that removes configuration removes all of it.
Where it bit us
Season three, Part 2: one UI, three
hosts, when the season-two screenshot harness first photographed the new web host — tag
pocket-02 in the repo. It
bit again in Part 3, on the clinic
server, as an API with no demo visits in it. The lesson: --no-launch-profile means
Production, and Production means whatever your app does differently there.
Frequently asked
- Why does my Blazor app serve empty CSS and JavaScript files with a 200 status?
- Because the app is running in the Production environment and MapStaticAssets is serving from the manifest of published, optimized assets, which do not exist in a development checkout. Each request matches an endpoint but there is no file behind it, so the response is 200 with a zero Content-Length. Running in Development fixes it.
- Does dotnet run --no-launch-profile change ASPNETCORE_ENVIRONMENT?
- Yes, indirectly. The flag skips launchSettings.json, which is where the Development environment variable is normally set, so the app starts with no environment and ASP.NET Core defaults to Production. Set ASPNETCORE_ENVIRONMENT=Development yourself or run with the launch profile.
- How do I set ASPNETCORE_ENVIRONMENT for dotnet run?
- Either let the launch profile set it, or set the variable in the shell before running: $env:ASPNETCORE_ENVIRONMENT = "Development" in PowerShell or export ASPNETCORE_ENVIRONMENT=Development in bash, then dotnet run.
More decoded errors in the Fixes category; the season starts at Part 1.