Static Files and Asset Delivery
|
This section documents ASP.NET Core on .NET 10 (LTS), the current release — the minimal hosting model, the middleware pipeline, dependency injection, Minimal APIs, MVC & Razor Pages, Blazor with the current render modes, SignalR and gRPC, EF Core, ASP.NET Core Identity and policy-based authorization, output caching, rate limiting, and Native-AOT-aware building — as described by the official documentation at Microsoft Learn, which is the reference these pages are written and verified against. This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. .NET ships a major release every November and its APIs continue to evolve: the examples here target .NET 10 / C# 14. This section’s bibliography lists the reference material consulted while preparing these pages. |
ASP.NET Core serves files from wwwroot through middleware, and, for build-time-known assets, through a
dedicated static web assets pipeline that adds fingerprinting and compression the classic middleware alone does
not.
UseStaticFiles vs. MapStaticAssets
app.UseStaticFiles(); // serves wwwroot as-is; no fingerprinting, no build-time manifest
app.MapStaticAssets(); // .NET 10+: serves the build's static web assets with fingerprinting + compression
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode()
.MapStaticAssets(); // components also resolve <link>/<script> URLs through the fingerprinted map
UseStaticFiles is plain middleware: whatever is under wwwroot at runtime is served, unmodified, with a
default Cache-Control the app must configure itself. MapStaticAssets is endpoint-routed and backed by a
build-time manifest of every static web asset (including ones contributed by referenced projects and RCLs),
so it can rewrite each asset’s referenced URL to a fingerprinted one and serve precompressed variants. Prefer
MapStaticAssets for anything produced at build time; fall back to UseStaticFiles (optionally pointed at a
different physical/IFileProvider location) for files that only exist at runtime — user uploads, generated
reports. See Static files in ASP.NET
Core.
Static web assets
Any project (including a referenced Razor class library or NuGet package) can contribute static web assets — files under its own wwwroot are automatically merged into the consuming app’s static asset set at build time,
namespaced under _content/{LibraryName}/… unless the asset pipeline rewrites the reference for you via
MapStaticAssets. This is what makes a UI component library (see
UI Component Libraries) able to ship its own CSS/JS without
the consuming app copying files manually.
Fingerprinting and compression
MapStaticAssets renames each asset’s served URL to embed a content hash (e.g.
app.a1b2c3d4.css), so a browser can cache it indefinitely — a new deployment produces a new hash, and
old cached copies simply stop being referenced instead of needing cache invalidation. It also serves
precompressed .br/.gz variants generated at publish time when the client’s Accept-Encoding allows it,
rather than compressing on every request.
<link rel="stylesheet" href="~/css/app.css" /> @* rendered as .../app.{hash}.css by MapStaticAssets *@
ImportMap
Blazor and other ES-module-based apps use an import map so JS module specifiers (import "./chart.js")
resolve to the actual fingerprinted URLs without every source file needing to know the hash:
<ImportMap /> @* emits a <script type="importmap"> built from the static asset manifest *@
This is generated automatically alongside MapStaticAssets and is what lets
collocated component JS modules keep plain, hash-free
import paths in source while still benefiting from fingerprinted URLs at runtime.
wwwroot conventions
wwwroot/
css/site.css
js/site.js
lib/ # third-party libraries (LibMan or npm-built output)
favicon.ico
wwwroot is the default web root; anything outside it is not served by either UseStaticFiles or
MapStaticAssets unless explicitly configured with an additional IFileProvider. Bundler-built output
(Webpack/Vite/esbuild) is typically configured to emit straight into wwwroot so the .NET build treats it like
any other static asset.
Razor class library static assets
An RCL’s own wwwroot participates the same way an app’s does — see
Razor class libraries for packaging
components together with their CSS/JS/images for reuse across projects.
CDN and cache-control strategy
| Strategy | Notes |
|---|---|
Fingerprinted assets, |
The default with |
Non-fingerprinted assets (runtime-generated, user uploads) |
Set an explicit, shorter |
CDN in front of the app |
Point the CDN at fingerprinted asset URLs specifically — they can be cached at the edge indefinitely without any purge/invalidation step on deploy. |
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = ctx =>
ctx.Context.Response.Headers.CacheControl = "public,max-age=600"
});
See Static files in ASP.NET Core
for MapStaticAssets, fingerprinting, and compression details, and
Performance and Caching for response/output caching of
dynamic content.