Skip to content

Commit ac43c89

Browse files
authored
Merge pull request #35166 from dotnet/main
2 parents 1e8ad70 + 313991d commit ac43c89

24 files changed

+264
-86
lines changed

Diff for: aspnetcore/blazor/components/built-in-components.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ The following built-in Razor components are provided by the Blazor framework. Fo
2727
* [`FocusOnNavigate`](xref:blazor/fundamentals/routing#focus-an-element-on-navigation)
2828
* [`HeadContent`](xref:blazor/components/control-head-content)
2929
* [`HeadOutlet`](xref:blazor/components/control-head-content)
30-
* [`ImportMap`](xref:blazor/fundamentals/static-files#import-maps)
30+
* [`ImportMap`](xref:blazor/fundamentals/static-files#importmap-component)
3131
* [`InputCheckbox`](xref:blazor/forms/input-components)
3232
* [`InputDate`](xref:blazor/forms/input-components)
3333
* [`InputFile`](xref:blazor/file-uploads)

Diff for: aspnetcore/blazor/forms/input-components.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ In the following example:
327327

328328
## Multiple option selection with the `InputSelect` component
329329

330-
Binding supports [`multiple`](https://developer.mozilla.org/docs/Web/HTML/Attributes/multiple) option selection with the <xref:Microsoft.AspNetCore.Components.Forms.InputSelect%601> component. The [`@onchange`](xref:mvc/views/razor#onevent) event provides an array of the selected options via [event arguments (`ChangeEventArgs`)](xref:blazor/components/event-handling#event-arguments). The value must be bound to an array type, and binding to an array type makes the [`multiple`](https://developer.mozilla.org/docs/Web/HTML/Attributes/multiple) attribute optional on the <xref:Microsoft.AspNetCore.Components.Forms.InputSelect%601> tag.
330+
Binding supports [`multiple`](https://developer.mozilla.org/docs/Web/HTML/Attributes/multiple) option selection with the <xref:Microsoft.AspNetCore.Components.Forms.InputSelect%601> component. The [`@onchange`](xref:mvc/views/razor#onevent) event provides an array of the selected options via [event arguments (`ChangeEventArgs`)](xref:blazor/components/event-handling#event-arguments). The value must be bound to an array type, which results in the <xref:Microsoft.AspNetCore.Components.Forms.InputSelect%601> component automatically adding the [`multiple` attribute](https://developer.mozilla.org/docs/Web/HTML/Attributes/multiple) to the `<select>` element when the component is rendered.
331331

332332
In the following example, the user must select at least two starship classifications but no more than three classifications.
333333

Diff for: aspnetcore/blazor/fundamentals/environments.md

+46-14
Original file line numberDiff line numberDiff line change
@@ -28,34 +28,58 @@ We recommend the following conventions:
2828

2929
## Set the environment
3030

31-
:::moniker range=">= aspnetcore-8.0"
32-
3331
The environment is set using any of the following approaches:
3432

35-
* Blazor Web App: Use any of the approaches described in <xref:fundamentals/environments> for general ASP.NET Core apps.
36-
* Blazor Web App or standalone Blazor WebAssembly: [Blazor start configuration](#set-the-client-side-environment-via-blazor-startup-configuration)
37-
* Standalone Blazor WebAssembly: [`Blazor-Environment` header](#set-the-client-side-environment-via-header)
38-
* Blazor Web App or standalone Blazor WebAssembly: [Azure App Service](#set-the-environment-for-azure-app-service)
33+
:::moniker range=">= aspnetcore-10.0"
34+
35+
* Blazor Web App or Blazor Server: Use any of the approaches described in <xref:fundamentals/environments> for general ASP.NET Core apps.
36+
* Any Blazor app: [Blazor start configuration](#set-the-client-side-environment-via-blazor-startup-configuration)
37+
* Standalone Blazor WebAssembly: `<WasmApplicationEnvironmentName>` property
38+
39+
On the client for a Blazor Web App, the environment is determined from the server via an HTML comment that developers don't interact with:
40+
41+
```html
42+
<!--Blazor-WebAssembly:{"environmentName":"Development", ...}-->
43+
```
44+
45+
For a standalone Blazor WebAssembly app, set the environment with the `<WasmApplicationEnvironmentName>` property in the app's project file (`.csproj`). The following example sets the `Staging` environment:
46+
47+
```xml
48+
<WasmApplicationEnvironmentName>Staging</WasmApplicationEnvironmentName>
49+
```
50+
51+
The default environments are `Development` for build and `Production` for publish.
52+
53+
:::moniker-end
54+
55+
:::moniker range=">= aspnetcore-8.0 < aspnetcore-10.0"
56+
57+
* Blazor Web App or Blazor Server: Use any of the approaches described in <xref:fundamentals/environments> for general ASP.NET Core apps.
58+
* Any Blazor app:
59+
* [Blazor start configuration](#set-the-client-side-environment-via-blazor-startup-configuration)
60+
* [Azure App Service](#set-the-environment-for-azure-app-service)
61+
* Blazor WebAssembly: [`Blazor-Environment` header](#set-the-client-side-environment-via-header)
3962

4063
On the client for a Blazor Web App, the environment is determined from the server via a middleware that communicates the environment to the browser via a header named `Blazor-Environment`. The header sets the environment when the <xref:Microsoft.AspNetCore.Components.WebAssembly.Hosting.WebAssemblyHost> is created in the client-side `Program` file (<xref:Microsoft.AspNetCore.Components.WebAssembly.Hosting.WebAssemblyHostBuilder.CreateDefault%2A?displayProperty=nameWithType>).
4164

65+
For a standalone Blazor WebAssembly app running locally, the development server adds the `Blazor-Environment` header with the environment name obtained from the hosting environment. The hosting environment sets the environment from the `ASPNETCORE_ENVIRONMENT` environment variable established by the project's `Properties/launchSettings.json` file. The default value of the environment variable in a project created from the Blazor WebAssembly project template is `Development`. For more information, see the [Set the client-side environment via header](#set-the-client-side-environment-via-header) section.
66+
4267
:::moniker-end
4368

4469
:::moniker range="< aspnetcore-8.0"
4570

46-
The environment is set using any of the following approaches:
47-
4871
* Blazor Server: Use any of the approaches described in <xref:fundamentals/environments> for general ASP.NET Core apps.
49-
* Blazor Server or Blazor WebAssembly: [Blazor start configuration](#set-the-client-side-environment-via-blazor-startup-configuration)
72+
* Blazor Server or Blazor WebAssembly:
73+
* [Blazor start configuration](#set-the-client-side-environment-via-blazor-startup-configuration)
74+
* [Azure App Service](#set-the-environment-for-azure-app-service)
5075
* Blazor WebAssembly: [`Blazor-Environment` header](#set-the-client-side-environment-via-header)
51-
* Blazor Server or Blazor WebAssembly: [Azure App Service](#set-the-environment-for-azure-app-service)
52-
53-
On the client for a Blazor Web App or the client of a hosted Blazor WebAssembly app, the environment is determined from the server via a middleware that communicates the environment to the browser via a header named `Blazor-Environment`. The header sets the environment when the <xref:Microsoft.AspNetCore.Components.WebAssembly.Hosting.WebAssemblyHost> is created in the client-side `Program` file (<xref:Microsoft.AspNetCore.Components.WebAssembly.Hosting.WebAssemblyHostBuilder.CreateDefault%2A?displayProperty=nameWithType>).
5476

55-
:::moniker-end
77+
On the client of a hosted Blazor WebAssembly app, the environment is determined from the server via a middleware that communicates the environment to the browser via a header named `Blazor-Environment`. The header sets the environment when the <xref:Microsoft.AspNetCore.Components.WebAssembly.Hosting.WebAssemblyHost> is created in the client-side `Program` file (<xref:Microsoft.AspNetCore.Components.WebAssembly.Hosting.WebAssemblyHostBuilder.CreateDefault%2A?displayProperty=nameWithType>).
5678

5779
For a standalone Blazor WebAssembly app running locally, the development server adds the `Blazor-Environment` header with the environment name obtained from the hosting environment. The hosting environment sets the environment from the `ASPNETCORE_ENVIRONMENT` environment variable established by the project's `Properties/launchSettings.json` file. The default value of the environment variable in a project created from the Blazor WebAssembly project template is `Development`. For more information, see the [Set the client-side environment via header](#set-the-client-side-environment-via-header) section.
5880

81+
:::moniker-end
82+
5983
For app's running locally in development, the app defaults to the `Development` environment. Publishing the app defaults the environment to `Production`.
6084

6185
:::moniker range="< aspnetcore-5.0"
@@ -111,10 +135,14 @@ Standalone Blazor WebAssembly:
111135

112136
**In the preceding example, the `{BLAZOR SCRIPT}` placeholder is the Blazor script path and file name.** For the location of the script, see <xref:blazor/project-structure#location-of-the-blazor-script>.
113137

138+
:::moniker range="< aspnetcore-10.0"
139+
114140
Using the `environment` property overrides the environment set by the [`Blazor-Environment` header](#set-the-client-side-environment-via-header).
115141

116142
The preceding approach sets the client's environment without changing the `Blazor-Environment` header's value, nor does it change the server project's console logging of the startup environment for a Blazor Web App that has adopted global Interactive WebAssembly rendering.
117143

144+
:::moniker-end
145+
118146
To log the environment to the console in either a standalone Blazor WebAssembly app or the `.Client` project of a Blazor Web App, place the following C# code in the `Program` file after the <xref:Microsoft.AspNetCore.Components.WebAssembly.Hosting.WebAssemblyHost> is created with <xref:Microsoft.AspNetCore.Components.WebAssembly.Hosting.WebAssemblyHostBuilder.CreateDefault%2A?displayProperty=nameWithType> and before the line that builds and runs the project (`await builder.Build().RunAsync();`):
119147

120148
```csharp
@@ -124,6 +152,8 @@ Console.WriteLine(
124152

125153
For more information on Blazor startup, see <xref:blazor/fundamentals/startup>.
126154

155+
:::moniker range="< aspnetcore-10.0"
156+
127157
## Set the client-side environment via header
128158

129159
Blazor WebAssembly apps can set the environment with the `Blazor-Environment` header. Specifically, the response header must be set on the `_framework/blazor.boot.json` file, but there's no harm setting the header on file server responses for other Blazor file requests or the entire Blazor deployment.
@@ -191,7 +221,7 @@ For more information, see the following resources:
191221
* [Apache documentation (search the latest release for "`mod_headers`")](https://httpd.apache.org/docs/)
192222
* <xref:blazor/host-and-deploy/webassembly/apache>
193223

194-
## Set the environment for Azure App Service
224+
### Set the environment for Azure App Service
195225

196226
<!-- UPDATE 10.0 The underlying problem with app settings filename
197227
case sensitivity is tracked for 10.0 by ...
@@ -213,6 +243,8 @@ When the app is loaded in the browser, the response header collection for `blazo
213243

214244
App settings from the `appsettings.{ENVIRONMENT}.json` file are loaded by the app, where the `{ENVIRONMENT}` placeholder is the app's environment. In the preceding example, settings from the `appsettings.Staging.json` file are loaded.
215245

246+
:::moniker-end
247+
216248
## Read the environment in a Blazor WebAssembly app
217249

218250
Obtain the app's environment in a component by injecting <xref:Microsoft.AspNetCore.Components.WebAssembly.Hosting.IWebAssemblyHostEnvironment> and reading the <xref:Microsoft.AspNetCore.Components.WebAssembly.Hosting.IWebAssemblyHostEnvironment.Environment> property.

Diff for: aspnetcore/blazor/fundamentals/static-files.md

+57-3
Original file line numberDiff line numberDiff line change
@@ -64,18 +64,21 @@ Assets are delivered via the <xref:Microsoft.AspNetCore.Components.ComponentBase
6464
<link rel="stylesheet" href="@Assets["BlazorSample.styles.css"]" />
6565
```
6666

67-
## Import maps
67+
## `ImportMap` component
6868

6969
*This section applies to server-side Blazor apps.*
7070

71-
The Import Map component (<xref:Microsoft.AspNetCore.Components.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`).
71+
The `ImportMap` component (<xref:Microsoft.AspNetCore.Components.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`).
7272

7373
```razor
7474
<ImportMap />
7575
```
7676

7777
If a custom <xref:Microsoft.AspNetCore.Components.ImportMapDefinition> isn't assigned to an Import Map component, the import map is generated based on the app's assets.
7878

79+
> [!NOTE]
80+
> <xref:Microsoft.AspNetCore.Components.ImportMapDefinition> instances are expensive to create, so we recommended caching them when creating an additional instance.
81+
7982
The following examples demonstrate custom import map definitions and the import maps that they create.
8083

8184
Basic import map:
@@ -197,9 +200,60 @@ For examples of how to address the policy violation with Subresource Integrity (
197200

198201
Configure Static File Middleware to serve static assets to clients by calling <xref:Microsoft.AspNetCore.Builder.StaticFileExtensions.UseStaticFiles%2A> in the app's request processing pipeline. For more information, see <xref:fundamentals/static-files>.
199202

203+
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.
204+
200205
:::moniker-end
201206

202-
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.
207+
:::moniker range=">= aspnetcore-10.0"
208+
209+
## Fingerprint client-side static assets in standalone Blazor WebAssembly apps
210+
211+
In standalone Blazor WebAssembly apps during build/publish, the framework overrides placeholders in `index.html` with values computed during build to fingerprint static assets for client-side rendering. A [fingerprint](https://wikipedia.org/wiki/Fingerprint_(computing)) is placed into the `blazor.webassembly.js` script file name, and an import map is generated for other .NET assets.
212+
213+
The following configuration must be present in the `wwwwoot/index.html` file of a standalone Blazor WebAssembly app to adopt fingerprinting:
214+
215+
```html
216+
<head>
217+
...
218+
<script type="importmap"></script>
219+
...
220+
</head>
221+
222+
<body>
223+
...
224+
<script src="_framework/blazor.webassembly#[.{fingerprint}].js"></script>
225+
...
226+
</body>
227+
228+
</html>
229+
```
230+
231+
In the project file (`.csproj`), the `<WriteImportMapToHtml>` property is set to `true`:
232+
233+
```xml
234+
<PropertyGroup>
235+
<WriteImportMapToHtml>true</WriteImportMapToHtml>
236+
</PropertyGroup>
237+
```
238+
239+
When resolving imports for JavaScript interop, the import map is used by the browser resolve fingerprinted files.
240+
241+
## Fingerprint client-side static assets in Blazor Web Apps
242+
243+
For client-side rendering (CSR) in Blazor Web Apps (Interactive Auto or Interactive WebAssembly render modes), static asset server-side [fingerprinting](https://wikipedia.org/wiki/Fingerprint_(computing)) is enabled by adopting [Map Static Assets routing endpoint conventions (`MapStaticAssets`)](xref:fundamentals/map-static-files), [`ImportMap` component](xref:blazor/fundamentals/static-files#importmap-component), and the <xref:Microsoft.AspNetCore.Components.ComponentBase.Assets?displayProperty=nameWithType> property (`@Assets["..."]`).
244+
245+
To fingerprint additional JavaScript modules for CSR, use the `<StaticWebAssetFingerprintPattern>` item in the app's project file (`.csproj`). In the following example, a fingerprint is added for all developer-supplied `.mjs` files in the app:
246+
247+
```xml
248+
<ItemGroup>
249+
<StaticWebAssetFingerprintPattern Include="JSModule" Pattern="*.mjs"
250+
Expression="#[.{fingerprint}]!" />
251+
</ItemGroup>
252+
```
253+
254+
When resolving imports for JavaScript interop, the import map is used by the browser resolve fingerprinted files.
255+
256+
:::moniker-end
203257

204258
## Summary of static file `<link>` `href` formats
205259

Diff for: aspnetcore/blazor/security/includes/imports-file-hosted.md

-3
This file was deleted.

Diff for: aspnetcore/blazor/security/includes/imports-file-standalone.md

-3
This file was deleted.

Diff for: aspnetcore/blazor/security/includes/imports-hosted.razor

-11
This file was deleted.

Diff for: aspnetcore/blazor/security/includes/imports-standalone.razor

-11
This file was deleted.

Diff for: aspnetcore/blazor/security/webassembly/hosted-with-azure-active-directory-b2c.md

+8-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ description: Learn how to secure a hosted ASP.NET Core Blazor WebAssembly app wi
55
monikerRange: '>= aspnetcore-3.1 < aspnetcore-8.0'
66
ms.author: riande
77
ms.custom: mvc
8-
ms.date: 11/12/2024
8+
ms.date: 04/07/2025
99
uid: blazor/security/webassembly/hosted-with-azure-active-directory-b2c
1010
---
1111
# Secure a hosted ASP.NET Core Blazor WebAssembly app with Azure Active Directory B2C
@@ -378,7 +378,13 @@ For more information, see the following sections of the *Additional scenarios* a
378378

379379
*This section pertains to the solution's **:::no-loc text="Client":::** app.*
380380

381-
[!INCLUDE[](~/blazor/security/includes/imports-file-hosted.md)]
381+
The <xref:Microsoft.AspNetCore.Components.Authorization?displayProperty=fullName> namespace is made available throughout the app via the `_Imports.razor` file:
382+
383+
```razor
384+
...
385+
@using Microsoft.AspNetCore.Components.Authorization
386+
...
387+
```
382388

383389
### Index page
384390

Diff for: aspnetcore/blazor/security/webassembly/hosted-with-identity-server.md

+8-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ description: Learn how to secure a hosted ASP.NET Core Blazor WebAssembly app wi
55
monikerRange: '>= aspnetcore-3.1 < aspnetcore-8.0'
66
ms.author: riande
77
ms.custom: mvc, linux-related-content
8-
ms.date: 11/12/2024
8+
ms.date: 04/07/2025
99
uid: blazor/security/webassembly/hosted-with-identity-server
1010
---
1111
# Secure a hosted ASP.NET Core Blazor WebAssembly app with Identity Server
@@ -292,7 +292,13 @@ Configuration for the app is loaded by convention from `_configuration/{client-i
292292

293293
*This section pertains to the solution's **:::no-loc text="Client":::** app.*
294294

295-
[!INCLUDE[](~/blazor/security/includes/imports-file-hosted.md)]
295+
The <xref:Microsoft.AspNetCore.Components.Authorization?displayProperty=fullName> namespace is made available throughout the app via the `_Imports.razor` file:
296+
297+
```razor
298+
...
299+
@using Microsoft.AspNetCore.Components.Authorization
300+
...
301+
```
296302

297303
### `Index` page
298304

Diff for: aspnetcore/blazor/security/webassembly/hosted-with-microsoft-entra-id.md

+8-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ description: Learn how to secure a hosted ASP.NET Core Blazor WebAssembly app wi
55
monikerRange: '>= aspnetcore-3.1 < aspnetcore-8.0'
66
ms.author: riande
77
ms.custom: "devx-track-csharp, mvc"
8-
ms.date: 11/12/2024
8+
ms.date: 04/07/2025
99
uid: blazor/security/webassembly/hosted-with-microsoft-entra-id
1010
---
1111
# Secure a hosted ASP.NET Core Blazor WebAssembly app with Microsoft Entra ID
@@ -384,7 +384,13 @@ For more information, see the following sections of the *Additional scenarios* a
384384

385385
*This section pertains to the solution's **:::no-loc text="Client":::** app.*
386386

387-
[!INCLUDE[](~/blazor/security/includes/imports-file-hosted.md)]
387+
The <xref:Microsoft.AspNetCore.Components.Authorization?displayProperty=fullName> namespace is made available throughout the app via the `_Imports.razor` file:
388+
389+
```razor
390+
...
391+
@using Microsoft.AspNetCore.Components.Authorization
392+
...
393+
```
388394

389395
### Index page
390396

0 commit comments

Comments
 (0)