Events
Mar 31, 11 PM - Apr 2, 11 PM
The ultimate Power BI, Fabric, SQL, and AI community-led event. March 31 - April 2. Use code MSCUST for a $150 discount. Prices go up Feb 11th.
Register todayThis browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Note
This isn't the latest version of this article. For the current release, see the .NET 9 version of this article.
Warning
This version of ASP.NET Core is no longer supported. For more information, see the .NET and .NET Core Support Policy. For the current release, see the .NET 9 version of this article.
Important
This information relates to a pre-release product that may be substantially modified before it's commercially released. Microsoft makes no warranties, express or implied, with respect to the information provided here.
For the current release, see the .NET 9 version of this article.
This article describes Blazor app configuration for serving static files.
Serving static assets is managed by either routing endpoint conventions or a middleware described in the following table.
Feature | API | .NET Version | Description |
---|---|---|---|
Map Static Assets routing endpoint conventions | MapStaticAssets | .NET 9 or later | Optimizes the delivery of static assets to clients. |
Static Files Middleware | UseStaticFiles | All .NET versions | Serves static assets to clients without the optimizations of Map Static Assets but useful for some tasks that Map Static Assets isn't capable of managing. |
Configure Map Static Assets by calling MapStaticAssets in the app's request processing pipeline, which performs the following:
Map Static Assets operates by combining build and publish processes to collect information about the static assets in the app. This information is utilized by the runtime library to efficiently serve the static assets to browsers.
Map Static Assets can replace UseStaticFiles in most situations. However, Map Static Assets is optimized for serving the assets from known locations in the app at build and publish time. If the app serves assets from other locations, such as disk or embedded resources, UseStaticFiles should be used.
Map Static Assets (MapStaticAssets) replaces calling UseBlazorFrameworkFiles in apps that serve Blazor WebAssembly framework files, and explicitly calling UseBlazorFrameworkFiles in a Blazor Web App isn't necessary because the API is automatically called when invoking AddInteractiveWebAssemblyComponents.
Map Static Assets provides the following benefits that aren't available when calling UseStaticFiles:
Content-Encoding: gz
) compression is used during development. Gzip with Brotli (Content-Encoding: br
) compression is used during publish.immutable
directive, which results in the browser never requesting the asset again until it changes. For browsers that don't support the immutable
directive, a max-age
directive is added.
ETags
are generated for each static asset using the fingerprint hash of the file as the ETag
value. This ensures that the browser only downloads a file if its content changes (or the file is being downloaded for the first time).<head>
content of the page to preload assets.When Interactive WebAssembly or Interactive Auto render modes are enabled:
_framework/resource-collection.js
), so JS has access to the resource collection for enhanced navigation or to implement features of other frameworks and third-party components.Map Static Assets doesn't provide features for minification or other file transformations. Minification is usually handled by custom code or third-party tooling.
Static File Middleware (UseStaticFiles) is useful in the following situations that Map Static Assets (MapStaticAssets) can't handle:
For more information, see Static files in ASP.NET Core.
This section applies to server-side Blazor apps.
Assets are delivered via the ComponentBase.Assets property, which resolves the fingerprinted URL for a given asset. In the following example, Bootstrap, the Blazor project template app stylesheet (app.css
), and the CSS isolation stylesheet (based on an app's namespace of BlazorSample
) are linked in a root component, typically the App
component (Components/App.razor
):
<link rel="stylesheet" href="@Assets["bootstrap/bootstrap.min.css"]" />
<link rel="stylesheet" href="@Assets["app.css"]" />
<link rel="stylesheet" href="@Assets["BlazorSample.styles.css"]" />
This section applies to server-side Blazor apps.
The Import Map component (ImportMap) represents an import map element (<script type="importmap"></script>
) that defines the import map for module scripts. The Import Map component is placed in <head>
content of the root component, typically the App
component (Components/App.razor
).
<ImportMap />
If a custom ImportMapDefinition isn't assigned to an Import Map component, the import map is generated based on the app's assets.
The following examples demonstrate custom import map definitions and the import maps that they create.
Basic import map:
new ImportMapDefinition(
new Dictionary<string, string>
{
{ "jquery", "https://cdn.example.com/jquery.js" },
},
null,
null);
The preceding code results in the following import map:
{
"imports": {
"jquery": "https://cdn.example.com/jquery.js"
}
}
Scoped import map:
new ImportMapDefinition(
null,
new Dictionary<string, IReadOnlyDictionary<string, string>>
{
["/scoped/"] = new Dictionary<string, string>
{
{ "jquery", "https://cdn.example.com/jquery.js" },
}
},
null);
The preceding code results in the following import map:
{
"scopes": {
"/scoped/": {
"jquery": "https://cdn.example.com/jquery.js"
}
}
}
Import map with integrity:
new ImportMapDefinition(
new Dictionary<string, string>
{
{ "jquery", "https://cdn.example.com/jquery.js" },
},
null,
new Dictionary<string, string>
{
{ "https://cdn.example.com/jquery.js", "sha384-abc123" },
});
The preceding code results in the following import map:
{
"imports": {
"jquery": "https://cdn.example.com/jquery.js"
},
"integrity": {
"https://cdn.example.com/jquery.js": "sha384-abc123"
}
}
Combine import map definitions (ImportMapDefinition) with ImportMapDefinition.Combine.
Import map created from a ResourceAssetCollection that maps static assets to their corresponding unique URLs:
ImportMapDefinition.FromResourceCollection(
new ResourceAssetCollection(
[
new ResourceAsset(
"jquery.fingerprint.js",
[
new ResourceAssetProperty("integrity", "sha384-abc123"),
new ResourceAssetProperty("label", "jquery.js"),
])
]));
The preceding code results in the following import map:
{
"imports": {
"./jquery.js": "./jquery.fingerprint.js"
},
"integrity": {
"jquery.fingerprint.js": "sha384-abc123"
}
}
Configure Static File Middleware to serve static assets to clients by calling UseStaticFiles in the app's request processing pipeline. For more information, see Static files in ASP.NET Core.
In releases prior to .NET 8, Blazor framework static files, such as the Blazor script, are served via Static File Middleware. In .NET 8 or later, Blazor framework static files are mapped using endpoint routing, and Static File Middleware is no longer used.
This section applies to all .NET releases and Blazor apps.
The following tables summarize static file <link>
href
formats by .NET release.
For the location of <head>
content where static file links are placed, see ASP.NET Core Blazor project structure. Static asset links can also be supplied using <HeadContent>
components in individual Razor components.
For the location of <head>
content where static file links are placed, see ASP.NET Core Blazor project structure.
App type | href value |
Examples |
---|---|---|
Blazor Web App | @Assets["{PATH}"] |
<link rel="stylesheet" href="@Assets["app.css"]" /> <link href="@Assets["_content/ComponentLib/styles.css"]" rel="stylesheet" /> |
Blazor Server† | @Assets["{PATH}"] |
<link href="@Assets["css/site.css"]" rel="stylesheet" /> <link href="@Assets["_content/ComponentLib/styles.css"]" rel="stylesheet" /> |
Standalone Blazor WebAssembly | {PATH} |
<link rel="stylesheet" href="css/app.css" /> <link href="_content/ComponentLib/styles.css" rel="stylesheet" /> |
App type | href value |
Examples |
---|---|---|
Blazor Web App | {PATH} |
<link rel="stylesheet" href="app.css" /> <link href="_content/ComponentLib/styles.css" rel="stylesheet" /> |
Blazor Server† | {PATH} |
<link href="css/site.css" rel="stylesheet" /> <link href="_content/ComponentLib/styles.css" rel="stylesheet" /> |
Standalone Blazor WebAssembly | {PATH} |
<link rel="stylesheet" href="css/app.css" /> <link href="_content/ComponentLib/styles.css" rel="stylesheet" /> |
App type | href value |
Examples |
---|---|---|
Blazor Server† | {PATH} |
<link href="css/site.css" rel="stylesheet" /> <link href="_content/ComponentLib/styles.css" rel="stylesheet" /> |
Hosted Blazor WebAssembly‡ | {PATH} |
<link href="css/app.css" rel="stylesheet" /> <link href="_content/ComponentLib/styles.css" rel="stylesheet" /> |
Blazor WebAssembly | {PATH} |
<link href="css/app.css" rel="stylesheet" /> <link href="_content/ComponentLib/styles.css" rel="stylesheet" /> |
†Blazor Server is supported in .NET 8 or later but is no longer a project template after .NET 7.
‡We recommend updating Hosted Blazor WebAssembly apps to Blazor Web Apps when adopting .NET 8 or later.
This section applies to the .Client
project of a Blazor Web App.
The required <StaticWebAssetProjectMode>Default</StaticWebAssetProjectMode>
setting in the .Client
project of a Blazor Web App reverts Blazor WebAssembly static asset behaviors back to the defaults, so that the project behaves as part of the hosted project. The Blazor WebAssembly SDK (Microsoft.NET.Sdk.BlazorWebAssembly
) configures static web assets in a specific way to work in "standalone" mode with a server simply consuming the outputs from the library. This isn't appropriate for a Blazor Web App, where the WebAssembly portion of the app is a logical part of the host and must behave more like a library. For example, the project doesn't expose the styles bundle (for example, BlazorSample.Client.styles.css
) and instead only provides the host with the project bundle, so that the host can include it in its own styles bundle.
Changing the value (Default
) of <StaticWebAssetProjectMode>
or removing the property from the .Client
project isn't supported.
This section applies to server-side static files.
When running an app locally, static web assets are only enabled in the Development environment. To enable static files for environments other than Development during local development and testing (for example, Staging), call UseStaticWebAssets on the WebApplicationBuilder in the Program
file.
Warning
Call UseStaticWebAssets for the exact environment to prevent activating the feature in production, as it serves files from separate locations on disk other than from the project if called in a production environment. The example in this section checks for the Staging environment by calling IsStaging.
if (builder.Environment.IsStaging())
{
builder.WebHost.UseStaticWebAssets();
}
This section applies to Blazor Web Apps.
Use the WebAssemblyComponentsEndpointOptions.PathPrefix endpoint option to set the path string that indicates the prefix for Blazor WebAssembly assets. The path must correspond to a referenced Blazor WebAssembly application project.
endpoints.MapRazorComponents<App>()
.AddInteractiveWebAssemblyRenderMode(options =>
options.PathPrefix = "{PATH PREFIX}");
In the preceding example, the {PATH PREFIX}
placeholder is the path prefix and must start with a forward slash (/
).
In the following example, the path prefix is set to /path-prefix
:
endpoints.MapRazorComponents<App>()
.AddInteractiveWebAssemblyRenderMode(options =>
options.PathPrefix = "/path-prefix");
This section applies to standalone Blazor WebAssembly apps.
Publishing the app places the app's static assets, including Blazor framework files (_framework
folder assets), at the root path (/
) in published output. The <StaticWebAssetBasePath>
property specified in the project file (.csproj
) sets the base path to a non-root path:
<PropertyGroup>
<StaticWebAssetBasePath>{PATH}</StaticWebAssetBasePath>
</PropertyGroup>
In the preceding example, the {PATH}
placeholder is the path.
Without setting the <StaticWebAssetBasePath>
property, a standalone app is published at /BlazorStandaloneSample/bin/Release/{TFM}/publish/wwwroot/
.
In the preceding example, the {TFM}
placeholder is the Target Framework Moniker (TFM) (for example, net6.0
).
If the <StaticWebAssetBasePath>
property in a standalone Blazor WebAssembly app sets the published static asset path to app1
, the root path to the app in published output is /app1
.
In the standalone Blazor WebAssembly app's project file (.csproj
):
<PropertyGroup>
<StaticWebAssetBasePath>app1</StaticWebAssetBasePath>
</PropertyGroup>
In published output, the path to the standalone Blazor WebAssembly app is /BlazorStandaloneSample/bin/Release/{TFM}/publish/wwwroot/app1/
.
In the preceding example, the {TFM}
placeholder is the Target Framework Moniker (TFM) (for example, net6.0
).
This section applies to standalone Blazor WebAssembly apps and hosted Blazor WebAssembly solutions.
Publishing the app places the app's static assets, including Blazor framework files (_framework
folder assets), at the root path (/
) in published output. The <StaticWebAssetBasePath>
property specified in the project file (.csproj
) sets the base path to a non-root path:
<PropertyGroup>
<StaticWebAssetBasePath>{PATH}</StaticWebAssetBasePath>
</PropertyGroup>
In the preceding example, the {PATH}
placeholder is the path.
Without setting the <StaticWebAssetBasePath>
property, the client app of a hosted solution or a standalone app is published at the following paths:
/BlazorHostedSample/Server/bin/Release/{TFM}/publish/wwwroot/
/BlazorStandaloneSample/bin/Release/{TFM}/publish/wwwroot/
If the <StaticWebAssetBasePath>
property in the Client project of a hosted Blazor WebAssembly app or in a standalone Blazor WebAssembly app sets the published static asset path to app1
, the root path to the app in published output is /app1
.
In the Client app's project file (.csproj
) or the standalone Blazor WebAssembly app's project file (.csproj
):
<PropertyGroup>
<StaticWebAssetBasePath>app1</StaticWebAssetBasePath>
</PropertyGroup>
In published output:
/BlazorHostedSample/Server/bin/Release/{TFM}/publish/wwwroot/app1/
/BlazorStandaloneSample/bin/Release/{TFM}/publish/wwwroot/app1/
The <StaticWebAssetBasePath>
property is most commonly used to control the paths to published static assets of multiple Blazor WebAssembly apps in a single hosted deployment. For more information, see Multiple hosted ASP.NET Core Blazor WebAssembly apps. The property is also effective in standalone Blazor WebAssembly apps.
In the preceding examples, the {TFM}
placeholder is the Target Framework Moniker (TFM) (for example, net6.0
).
This section applies to server-side static files.
To create additional file mappings with a FileExtensionContentTypeProvider or configure other StaticFileOptions, use one of the following approaches. In the following examples, the {EXTENSION}
placeholder is the file extension, and the {CONTENT TYPE}
placeholder is the content type. The namespace for the following API is Microsoft.AspNetCore.StaticFiles.
Configure options through dependency injection (DI) in the Program
file using StaticFileOptions:
var provider = new FileExtensionContentTypeProvider();
provider.Mappings["{EXTENSION}"] = "{CONTENT TYPE}";
builder.Services.Configure<StaticFileOptions>(options =>
{
options.ContentTypeProvider = provider;
});
app.UseStaticFiles();
Pass the StaticFileOptions directly to UseStaticFiles in the Program
file:
var provider = new FileExtensionContentTypeProvider();
provider.Mappings["{EXTENSION}"] = "{CONTENT TYPE}";
app.UseStaticFiles(new StaticFileOptions { ContentTypeProvider = provider });
To create additional file mappings with a FileExtensionContentTypeProvider or configure other StaticFileOptions, use one of the following approaches. In the following examples, the {EXTENSION}
placeholder is the file extension, and the {CONTENT TYPE}
placeholder is the content type.
Configure options through dependency injection (DI) in the Program
file using StaticFileOptions:
using Microsoft.AspNetCore.StaticFiles;
...
var provider = new FileExtensionContentTypeProvider();
provider.Mappings["{EXTENSION}"] = "{CONTENT TYPE}";
builder.Services.Configure<StaticFileOptions>(options =>
{
options.ContentTypeProvider = provider;
});
This approach configures the same file provider used to serve the Blazor script. Make sure that your custom configuration doesn't interfere with serving the Blazor script. For example, don't remove the mapping for JavaScript files by configuring the provider with provider.Mappings.Remove(".js")
.
Use two calls to UseStaticFiles in the Program
file:
using Microsoft.AspNetCore.StaticFiles;
...
var provider = new FileExtensionContentTypeProvider();
provider.Mappings["{EXTENSION}"] = "{CONTENT TYPE}";
app.UseStaticFiles(new StaticFileOptions { ContentTypeProvider = provider });
app.UseStaticFiles();
You can avoid interfering with serving _framework/blazor.server.js
by using MapWhen to execute a custom Static File Middleware:
app.MapWhen(ctx => !ctx.Request.Path
.StartsWithSegments("/_framework/blazor.server.js"),
subApp => subApp.UseStaticFiles(new StaticFileOptions() { ... }));
The guidance in this section only applies to Blazor Web Apps.
To serve files from multiple locations with a CompositeFileProvider:
Program
file of the server project.Program
file before the call to UseStaticFiles:
Example:
Create a new folder in the server project named AdditionalStaticAssets
. Place an image into the folder.
Add the following using
statement to the top of the server project's Program
file:
using Microsoft.Extensions.FileProviders;
In the server project's Program
file before the call to UseStaticFiles, add the following code:
var secondaryProvider = new PhysicalFileProvider(
Path.Combine(builder.Environment.ContentRootPath, "AdditionalStaticAssets"));
app.Environment.WebRootFileProvider = new CompositeFileProvider(
app.Environment.WebRootFileProvider, secondaryProvider);
In the app's Home
component (Home.razor
) markup, reference the image with an <img>
tag:
<img src="{IMAGE FILE NAME}" alt="{ALT TEXT}" />
In the preceding example:
{IMAGE FILE NAME}
placeholder is the image file name. There's no need to provide a path segment if the image file is at the root of the AdditionalStaticAssets
folder.{ALT TEXT}
placeholder is the image alternate text.Run the app.
ASP.NET Core feedback
ASP.NET Core is an open source project. Select a link to provide feedback:
Events
Mar 31, 11 PM - Apr 2, 11 PM
The ultimate Power BI, Fabric, SQL, and AI community-led event. March 31 - April 2. Use code MSCUST for a $150 discount. Prices go up Feb 11th.
Register todayTraining
Module
Publish a Blazor WebAssembly app and .NET API with Azure Static Web Apps - Training
Publish a Blazor WebAssembly app and .NET API with Azure Static Web Apps