The Error
Browser console shows 404 for all files in wwwroot:
GET https://site.com/css/site.css 404 (Not Found)
Quick Fix - 30 Seconds
You're missing app.UseStaticFiles(); or it's in the wrong order.
var app = builder.Build();
// This must come BEFORE UseRouting
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllers();
app.Run();
Why This Happens
ASP.NET Core middleware runs in order. If UseRouting runs first, it tries to route /css/site.css to a controller. No controller exists = 404. UseStaticFiles must intercept the request first.
Step-by-Step Debug
- Check Program.cs: Is
UseStaticFiles()present? Is it beforeUseRouting()? - Check folder name: Must be exactly
wwwroot. Notwwworstatic - Check publish: Are files in
wwwrootset to "Copy to Output Directory"?
Real-World Scenario: Static Files Work Locally, 404 on Azure
#1 deployment issue. Files exist in wwwroot locally, 404 in Azure App Service:
// Dev Fix: .NET 8 + Minimal API still needs explicit UseStaticFiles
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
// CRITICAL: Must be before UseRouting and before MapControllers
app.UseStaticFiles(); // Dev Fix: Serves wwwroot
// For SPA: Serve default files + static files
app.UseDefaultFiles(); // Looks for index.html, default.htm
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllers();
// For Blazor WASM hosted: Map fallback to index.html
app.MapFallbackToFile("index.html");
app.Run();
3 Azure/deployment fixes:
- Copy to Output: Right-click css/js in wwwroot → Properties → "Copy to Output Directory" = Copy if newer. MSBuild sometimes skips wwwroot.
- Wrong base path: Azure runs under
/home/site/wwwroot. If you hardcode paths, usePath.Combine(builder.Environment.WebRootPath, "css"). - SPA 404 on refresh: User hits
/users/5directly = 404. Addapp.MapFallbackToFile("index.html")so SPA router handles it.
Related Fixes You Should Know
Static file 404s usually mean middleware order bugs:
- HTTPS Redirect Loop - You added
UseHttpsRedirection()beforeUseStaticFiles(). Static files get 307 redirected, then 404. Order: StaticFiles → HttpsRedirection → Routing. - CORS Error Fix - Static files load but API calls 404.
UseRouting()beforeUseStaticFiles()causes API routes to be treated as files. - SignalR 404 Negotiation -
/hub/negotiatereturns 404 becauseUseStaticFiles()ran first and thought it was a file. MoveMapHub()before static files if using custom paths. - Blazor WASM Loading Failed -
blazor.webassembly.js404. MissingUseBlazorFrameworkFiles()beforeUseStaticFiles()in hosted apps.
FAQ
Q: Why do I need UseDefaultFiles() and UseStaticFiles()?
UseDefaultFiles() rewrites / to /index.html. UseStaticFiles() serves the actual file. You need both. Order matters: DefaultFiles first, then StaticFiles.
Q: Can I serve files from outside wwwroot?
Yes. app.UseStaticFiles(new StaticFileOptions { FileProvider = new PhysicalFileProvider("/var/data"), RequestPath = "/files" });. Now /files/image.jpg maps to /var/data/image.jpg.
Common Scenarios
- Blazor Server: Missing
app.MapBlazorHub()breaks static files too - Minimal APIs: Easy to forget
UseStaticFilesentirely - Wrong path:
<link href="~/css/site.css">needsapp.UseStaticFiles()to work
No comments yet. Be the first to share your thoughts!