Skip to content

Commit 3079647

Browse files
authored
Merge pull request #36180 from dotnet/main
2 parents 4e1bf3e + a71d134 commit 3079647

File tree

12 files changed

+267
-51
lines changed

12 files changed

+267
-51
lines changed

aspnetcore/blazor/debug.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ To break on unhandled exceptions:
444444

445445
## Browser source maps
446446

447-
Browser source maps allow the browser to map compiled files back to their original source files and are commonly used for client-side debugging. However, Blazor doesn't currently map C# directly to JavaScript/WASM. Instead, Blazor does IL interpretation within the browser, so source maps aren't relevant.
447+
Browser source maps allow the browser to map compiled files back to their original source files and are commonly used for client-side debugging. However, Blazor doesn't currently map C# directly to JavaScript/Wasm. Instead, Blazor does IL interpretation within the browser, so source maps aren't relevant.
448448

449449
## Firewall configuration
450450

aspnetcore/blazor/fundamentals/handle-errors.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -719,7 +719,7 @@ Because the approaches in this section handle errors with a [`try-catch`](/dotne
719719
If an unhandled exception occurs, the exception is logged to <xref:Microsoft.Extensions.Logging.ILogger> instances configured in the service container. Blazor apps log console output with the Console Logging Provider. Consider logging to a location on the server (or backend web API for client-side apps) with a provider that manages log size and log rotation. Alternatively, the app can use an Application Performance Management (APM) service, such as [Azure Application Insights (Azure Monitor)](/azure/azure-monitor/app/app-insights-overview).
720720

721721
> [!NOTE]
722-
> Native [Application Insights](/azure/azure-monitor/app/app-insights-overview) features to support client-side apps and native Blazor framework support for [Google Analytics](https://analytics.google.com/analytics/web/) might become available in future releases of these technologies. For more information, see [Support App Insights in Blazor WASM Client Side (microsoft/ApplicationInsights-dotnet #2143)](https://github.com/microsoft/ApplicationInsights-dotnet/issues/2143) and [Web analytics and diagnostics (includes links to community implementations) (dotnet/aspnetcore #5461)](https://github.com/dotnet/aspnetcore/issues/5461). In the meantime, a client-side app can use the [Application Insights JavaScript SDK](/azure/azure-monitor/app/javascript) with [JS interop](xref:blazor/js-interop/call-javascript-from-dotnet) to log errors directly to Application Insights from a client-side app.
722+
> Native [Application Insights](/azure/azure-monitor/app/app-insights-overview) features to support client-side apps and native Blazor framework support for [Google Analytics](https://analytics.google.com/analytics/web/) might become available in future releases of these technologies. For more information, see [Support App Insights in Blazor WASM Client Side (`microsoft/ApplicationInsights-dotnet` #2143)](https://github.com/microsoft/ApplicationInsights-dotnet/issues/2143) and [Web analytics and diagnostics (includes links to community implementations) (`dotnet/aspnetcore` #5461)](https://github.com/dotnet/aspnetcore/issues/5461). In the meantime, a client-side app can use the [Application Insights JavaScript SDK](/azure/azure-monitor/app/javascript) with [JS interop](xref:blazor/js-interop/call-javascript-from-dotnet) to log errors directly to Application Insights from a client-side app.
723723
724724
During development in a Blazor app operating over a circuit, the app usually sends the full details of exceptions to the browser's console to aid in debugging. In production, detailed errors aren't sent to clients, but an exception's full details are logged on the server.
725725

@@ -747,7 +747,7 @@ For more information, see the following articles:
747747
* <xref:fundamentals/error-handling>&Dagger;
748748
* <xref:web-api/index>
749749

750-
&dagger;Native [Application Insights](/azure/azure-monitor/app/app-insights-overview) features to support client-side apps and native Blazor framework support for [Google Analytics](https://analytics.google.com/analytics/web/) might become available in future releases of these technologies. For more information, see [Support App Insights in Blazor WASM Client Side (microsoft/ApplicationInsights-dotnet #2143)](https://github.com/microsoft/ApplicationInsights-dotnet/issues/2143) and [Web analytics and diagnostics (includes links to community implementations) (dotnet/aspnetcore #5461)](https://github.com/dotnet/aspnetcore/issues/5461). In the meantime, a client-side app can use the [Application Insights JavaScript SDK](/azure/azure-monitor/app/javascript) with [JS interop](xref:blazor/js-interop/call-javascript-from-dotnet) to log errors directly to Application Insights from a client-side app.
750+
&dagger;Native [Application Insights](/azure/azure-monitor/app/app-insights-overview) features to support client-side apps and native Blazor framework support for [Google Analytics](https://analytics.google.com/analytics/web/) might become available in future releases of these technologies. For more information, see [Support App Insights in Blazor WASM Client Side (`microsoft/ApplicationInsights-dotnet` #2143)](https://github.com/microsoft/ApplicationInsights-dotnet/issues/2143) and [Web analytics and diagnostics (includes links to community implementations) (`dotnet/aspnetcore` #5461)](https://github.com/dotnet/aspnetcore/issues/5461). In the meantime, a client-side app can use the [Application Insights JavaScript SDK](/azure/azure-monitor/app/javascript) with [JS interop](xref:blazor/js-interop/call-javascript-from-dotnet) to log errors directly to Application Insights from a client-side app.
751751

752752
&Dagger;Applies to server-side ASP.NET Core apps that are web API backend apps for Blazor apps. Client-side apps trap and send error information to a web API, which logs the error information to a persistent logging provider.
753753

aspnetcore/blazor/host-and-deploy/webassembly/deployment-layout.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ The following example `BundleBlazorAssets` class is a starting point for further
126126

127127
* In the `Execute` method, the bundle is created from the following three file types:
128128
* JavaScript files (`dotnet.js`)
129-
* WASM files (`dotnet.wasm`)
129+
* WebAssembly (Wasm) files (`dotnet.wasm`)
130130
* App DLLs (`.dll`)
131131
* A `multipart/form-data` bundle is created. Each file is added to the bundle with its respective descriptions via the [Content-Disposition header](https://developer.mozilla.org/docs/Web/HTTP/Headers/Content-Disposition) and the [Content-Type header](https://developer.mozilla.org/docs/Web/HTTP/Headers/Content-Type).
132132
* After the bundle is created, the bundle is written to a file.
@@ -135,7 +135,7 @@ The following example `BundleBlazorAssets` class is a starting point for further
135135
* The URL path relative to the root of the Blazor WebAssembly app.
136136
* The name of the extension, which groups the files produced by a given extension.
137137

138-
After accomplishing the preceding goals, the MSBuild task is created for customizing the Blazor publish output. Blazor takes care of gathering the extensions and making sure that the extensions are copied to the correct location in the publish output folder (for example, `bin\Release\net6.0\publish`). The same optimizations (for example, compression) are applied to the JavaScript, WASM, and DLL files as Blazor applies to other files.
138+
After accomplishing the preceding goals, the MSBuild task is created for customizing the Blazor publish output. Blazor takes care of gathering the extensions and making sure that the extensions are copied to the correct location in the publish output folder (for example, `bin\Release\net6.0\publish`). The same optimizations (for example, compression) are applied to the JavaScript, Wasm, and DLL files as Blazor applies to other files.
139139

140140
`Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.Tasks/BundleBlazorAssets.cs`:
141141

aspnetcore/blazor/hosting-models.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@ This article explains Blazor hosting models and how to choose which one to use.
3232

3333
:::moniker range=">= aspnetcore-6.0"
3434

35-
Blazor is a web framework for building web UI components ([Razor components](xref:blazor/components/index)) that can be hosted in different ways. Razor components can run server-side in ASP.NET Core (*Blazor Server*) versus client-side in the browser on a [WebAssembly](https://webassembly.org/)-based .NET runtime (*Blazor WebAssembly*, *Blazor WASM*). You can also host Razor components in native mobile and desktop apps that render to an embedded Web View control (*Blazor Hybrid*). Regardless of the hosting model, the way you build Razor components *is the same*. The same Razor components can be used with any of the hosting models unchanged.
35+
Blazor is a web framework for building web UI components ([Razor components](xref:blazor/components/index)) that can be hosted in different ways. Razor components can run server-side in ASP.NET Core (*Blazor Server*) versus client-side in the browser on a [WebAssembly](https://webassembly.org/)-based .NET runtime (*Blazor WebAssembly*, *Blazor Wasm*). You can also host Razor components in native mobile and desktop apps that render to an embedded Web View control (*Blazor Hybrid*). Regardless of the hosting model, the way you build Razor components *is the same*. The same Razor components can be used with any of the hosting models unchanged.
3636

3737
:::moniker-end
3838

3939
:::moniker range="< aspnetcore-6.0"
4040

41-
Blazor is a web framework for building web UI components ([Razor components](xref:blazor/components/index)) that can be hosted in different ways. Razor components can run server-side in ASP.NET Core (*Blazor Server*) versus client-side in the browser on a [WebAssembly](https://webassembly.org/)-based .NET runtime (*Blazor WebAssembly*, *Blazor WASM*). Regardless of the hosting model, the way you build Razor components *is the same*. The same Razor components can be used with any of the hosting models unchanged.
41+
Blazor is a web framework for building web UI components ([Razor components](xref:blazor/components/index)) that can be hosted in different ways. Razor components can run server-side in ASP.NET Core (*Blazor Server*) versus client-side in the browser on a [WebAssembly](https://webassembly.org/)-based .NET runtime (*Blazor WebAssembly*, *Blazor Wasm*). Regardless of the hosting model, the way you build Razor components *is the same*. The same Razor components can be used with any of the hosting models unchanged.
4242

4343
:::moniker-end
4444

@@ -203,7 +203,7 @@ Select the Blazor hosting model based on the app's feature requirements. The fol
203203

204204
Blazor Hybrid apps include .NET MAUI, WPF, and Windows Forms framework apps.
205205

206-
Feature | Blazor Server | Blazor WebAssembly (WASM) | Blazor Hybrid
206+
Feature | Blazor Server | Blazor WebAssembly (Wasm) | Blazor Hybrid
207207
--- | :---: | :---: | :---:
208208
[Complete .NET API compatibility](#complete-net-api-compatibility) | <span aria-hidden="true">✔️</span><span class="visually-hidden">Supported</span> | <span aria-hidden="true">❌</span><span class="visually-hidden">Not supported</span> | <span aria-hidden="true">✔️</span><span class="visually-hidden">Supported</span>
209209
[Direct access to server and network resources](#direct-access-to-server-and-network-resources) | <span aria-hidden="true">✔️</span><span class="visually-hidden">Supported</span> | <span aria-hidden="true">❌</span><span class="visually-hidden">Not supported</span>&dagger; | <span aria-hidden="true">❌</span><span class="visually-hidden">Not supported</span>&dagger;
@@ -223,7 +223,7 @@ Feature | Blazor Server | Blazor WebAssembly (WASM) | Blazor Hybrid
223223

224224
:::moniker range="< aspnetcore-6.0"
225225

226-
Feature | Blazor Server | Blazor WebAssembly (WASM)
226+
Feature | Blazor Server | Blazor WebAssembly (Wasm)
227227
--- | :---: | :---:
228228
[Complete .NET API compatibility](#complete-net-api-compatibility) | <span aria-hidden="true">✔️</span><span class="visually-hidden">Supported</span> | <span aria-hidden="true">❌</span><span class="visually-hidden">Not supported</span>
229229
[Direct access to server and network resources](#direct-access-to-server-and-network-resources) | <span aria-hidden="true">✔️</span><span class="visually-hidden">Supported</span> | <span aria-hidden="true">❌</span><span class="visually-hidden">Not supported</span>&dagger;

aspnetcore/blazor/performance/webassembly-runtime-performance.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ This article provides guidance on Blazor WebAssembly runtime performance.
2020

2121
## Potentially reduced performance with Microsoft Edge enhanced security
2222

23-
The Microsoft Edge browser's WebAssembly (WASM) interpreter running in [enhanced security mode](/DeployEdge/microsoft-edge-security-browse-safer) might not yield the same performance as when Blazor is running without enhanced security. If enhanced security mode is enabled and an app's performance is degraded, we recommend adding the site as an [exception](/DeployEdge/microsoft-edge-security-browse-safer#enhanced-security-sites) to opt out of enhanced security mode.
23+
The Microsoft Edge browser's WebAssembly (Wasm) interpreter running in [enhanced security mode](/DeployEdge/microsoft-edge-security-browse-safer) might not yield the same performance as when Blazor is running without enhanced security. If enhanced security mode is enabled and an app's performance is degraded, we recommend adding the site as an [exception](/DeployEdge/microsoft-edge-security-browse-safer#enhanced-security-sites) to opt out of enhanced security mode.
2424

2525
:::moniker range=">= aspnetcore-8.0"
2626

aspnetcore/blazor/state-management/prerendered-state-persistence.md

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ The first logged count occurs during prerendering. The count is set again after
3232

3333
To retain the initial value of the counter during prerendering, Blazor supports persisting state in a prerendered page using the <xref:Microsoft.AspNetCore.Components.PersistentComponentState> service (and for components embedded into pages or views of Razor Pages or MVC apps, the [Persist Component State Tag Helper](xref:mvc/views/tag-helpers/builtin-th/persist-component-state-tag-helper)).
3434

35+
By initializing components with the same state used during prerendering, any expensive initialization steps are only executed once. The rendered UI also matches the prerendered UI, so no flicker occurs in the browser.
36+
37+
The persisted prerendered state is transferred to the client, where it's used to restore the component state. During client-side rendering (CSR, `InteractiveWebAssembly`), the data is exposed to the browser and must not contain sensitive, private information. During interactive server-side rendering (interactive SSR, `InteractiveServer`), [ASP.NET Core Data Protection](xref:security/data-protection/introduction) ensures that the data is transferred securely. The `InteractiveAuto` render mode combines WebAssembly and Server interactivity, so it's necessary to consider data exposure to the browser, as in the CSR case.
38+
3539
:::moniker range=">= aspnetcore-10.0"
3640

3741
<!-- UPDATE 10.0 - API cross-links -->
@@ -136,6 +140,8 @@ In the following example that serializes state for multiple components of the sa
136140
}
137141
```
138142

143+
## Serialize state for services
144+
139145
In the following example that serializes state for a dependency injection service:
140146

141147
* Properties annotated with the `[PersistentState]` attribute are serialized during prerendering and deserialized when the app becomes interactive.
@@ -148,12 +154,19 @@ In the following example that serializes state for a dependency injection servic
148154
> [!NOTE]
149155
> Only persisting scoped services is supported.
150156
151-
<!-- UPDATE 10.0 - Flesh out with a fully-working example. -->
157+
Serialized properties are identified from the actual service instance:
152158

153-
`CounterService.cs`:
159+
* This approach allows marking an abstraction as a persistent service.
160+
* Enables actual implementations to be internal or different types.
161+
* Supports shared code in different assemblies.
162+
* Results in each instance exposing the same properties.
163+
164+
The following counter service, `CounterTracker`, marks its current count property, `CurrentCount` with the `[PersistentState]` attribute. The property is serialized during prerendering and deserialized when the app becomes interactive wherever the service is injected.
165+
166+
`CounterTracker.cs`:
154167

155168
```csharp
156-
public class CounterService
169+
public class CounterTracker
157170
{
158171
[PersistentState]
159172
public int CurrentCount { get; set; }
@@ -165,19 +178,60 @@ public class CounterService
165178
}
166179
```
167180

168-
In `Program.cs`:
181+
In the `Program` file, register the scoped service and register the service for persistence with `RegisterPersistentService`. In the following example, the `CounterTracker` service is available for both the Interactive Server and Interactive WebAssembly render modes if a component renders in either of those modes because it's registered with `RenderMode.InteractiveAuto`.
182+
183+
If the `Program` file doesn't already use the <xref:Microsoft.AspNetCore.Components.Web?displayProperty=fullName> namespace, add the following `using` statement to the top of the file:
169184

170185
```csharp
186+
using Microsoft.AspNetCore.Components.Web;
187+
```
188+
189+
Where services are registered in the `Program` file:
190+
191+
```csharp
192+
builder.Services.AddScoped<CounterTracker>();
193+
171194
builder.Services.AddRazorComponents()
172-
.RegisterPersistentService<CounterService>(RenderMode.InteractiveAuto);
195+
.RegisterPersistentService<CounterTracker>(RenderMode.InteractiveAuto);
173196
```
174197

175-
Serialized properties are identified from the actual service instance:
198+
Inject the `CounterTracker` service into a component and use it to increment a counter. For demonstration purposes in the following example, the value of the service's `CurrentCount` property is set to 10 only during prerendering.
176199

177-
* This approach allows marking an abstraction as a persistent service.
178-
* Enables actual implementations to be internal or different types.
179-
* Supports shared code in different assemblies.
180-
* Results in each instance exposing the same properties.
200+
`Pages/Counter.razor`:
201+
202+
```razor
203+
@page "/counter"
204+
@inject CounterTracker CounterTracker
205+
206+
<PageTitle>Counter</PageTitle>
207+
208+
<h1>Counter</h1>
209+
210+
<p>Rendering: @RendererInfo.Name</p>
211+
212+
<p role="status">Current count: @CounterTracker.CurrentCount</p>
213+
214+
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
215+
216+
@code {
217+
protected override void OnInitialized()
218+
{
219+
if (!RendererInfo.IsInteractive)
220+
{
221+
CounterTracker.CurrentCount = 10;
222+
}
223+
}
224+
225+
private void IncrementCount()
226+
{
227+
CounterTracker.IncrementCount();
228+
}
229+
}
230+
```
231+
232+
To use preceding component to demonstrate persisting the count of 10 in `CounterTracker.CurrentCount`, navigate to the component and refresh the browser, which triggers prerendering. When prerendering occurs, you briefly see <xref:Microsoft.AspNetCore.Components.RendererInfo.Name%2A?displayProperty=nameWithType> indicate "`Static`" before displaying "`Server`" after final rendering. The counter starts at 10.
233+
234+
## Use the `PersistentComponentState` service directly instead of the declarative model
181235

182236
As an alternative to using the declarative model for persisting state with the `[PersistentState]` attribute, you can use the <xref:Microsoft.AspNetCore.Components.PersistentComponentState> service directly, which offers greater flexibility for complex state persistence scenarios. Call <xref:Microsoft.AspNetCore.Components.PersistentComponentState.RegisterOnPersisting%2A?displayProperty=nameWithType> to register a callback to persist the component state during prerendering. The state is retrieved when the component renders interactively. Make the call at the end of initialization code in order to avoid a potential race condition during app shutdown.
183237

@@ -268,10 +322,6 @@ When the component executes, `currentCount` is only set once during prerendering
268322
269323
:::moniker-end
270324

271-
By initializing components with the same state used during prerendering, any expensive initialization steps are only executed once. The rendered UI also matches the prerendered UI, so no flicker occurs in the browser.
272-
273-
The persisted prerendered state is transferred to the client, where it's used to restore the component state. During client-side rendering (CSR, `InteractiveWebAssembly`), the data is exposed to the browser and must not contain sensitive, private information. During interactive server-side rendering (interactive SSR, `InteractiveServer`), [ASP.NET Core Data Protection](xref:security/data-protection/introduction) ensures that the data is transferred securely. The `InteractiveAuto` render mode combines WebAssembly and Server interactivity, so it's necessary to consider data exposure to the browser, as in the CSR case.
274-
275325
:::moniker range=">= aspnetcore-10.0"
276326

277327
## Serialization extensibility for persistent component state

0 commit comments

Comments
 (0)