Skip to content

Commit bd6bd38

Browse files
authored
Merge pull request #35512 from dotnet/main
Merge to Live
2 parents 76e9e92 + 9a9d45e commit bd6bd38

File tree

6 files changed

+38
-11
lines changed

6 files changed

+38
-11
lines changed

aspnetcore/blazor/components/cascading-values-and-parameters.md

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ builder.Services.AddCascadingValue(sp =>
9494
>
9595
> Avoid using <xref:Microsoft.Extensions.DependencyInjection.CascadingValueServiceCollectionExtensions.AddCascadingValue%2A> to register a component type as a cascading value. Instead, wrap the `<Router>...</Router>` in the `Routes` component (`Components/Routes.razor`) with the component and adopt global interactive server-side rendering (interactive SSR). For an example, see the [`CascadingValue` component](#cascadingvalue-component) section.
9696
97+
## Root-level cascading values with notifications
98+
9799
Calling <xref:Microsoft.AspNetCore.Components.CascadingValueSource%601.NotifyChangedAsync%2A> to issue update notifications can be used to signal multiple Razor component subscribers that a cascading value has changed. Notifications aren't possible for subscribers that adopt static server-side rendering (static SSR), so subscribers must adopt an interactive render mode.
98100

99101
In the following example:
@@ -103,6 +105,9 @@ In the following example:
103105

104106
Keep in mind for production code that any change in state (any property value change of the class) causes all subscribed components to rerender, regardless of which part of the state they use. We recommend creating granular classes, cascading them separately with specific subscriptions to ensure that only components subscribed to a specific portion of the application state are affected by changes.
105107

108+
> [!NOTE]
109+
> For a Blazor Web App solution consisting of server and client (`.Client`) projects, the following `NotifyingDalek.cs` file is placed in the `.Client` project.
110+
106111
`NotifyingDalek.cs`:
107112

108113
```csharp
@@ -143,6 +148,9 @@ public class NotifyingDalek : INotifyPropertyChanged
143148

144149
The following `CascadingStateServiceCollectionExtensions` creates a <xref:Microsoft.AspNetCore.Components.CascadingValueSource%601> from a type that implements <xref:System.ComponentModel.INotifyPropertyChanged>.
145150

151+
> [!NOTE]
152+
> For a Blazor Web App solution consisting of server and client (`.Client`) projects, the following `CascadingStateServiceCollectionExtensions.cs` file is placed in the `.Client` project.
153+
146154
`CascadingStateServiceCollectionExtensions.cs`:
147155

148156
```csharp
@@ -192,17 +200,14 @@ public static class CascadingStateServiceCollectionExtensions
192200

193201
The type's <xref:System.ComponentModel.PropertyChangedEventHandler> (`HandlePropertyChanged`) calls the <xref:Microsoft.AspNetCore.Components.CascadingValueSource%601>'s <xref:Microsoft.AspNetCore.Components.CascadingValueSource%601.NotifyChangedAsync%2A> method to notify subscribers that the cascading value has changed. The <xref:System.Threading.Tasks.Task> is discarded when calling <xref:Microsoft.AspNetCore.Components.CascadingValueSource%601.NotifyChangedAsync%2A> because the call only represents the duration of the dispatch to the synchronous context. Exceptions are handled internally by dispatching them to the renderer within the context of whichever component threw when receiving the update. This is the same way that exceptions are processed with a <xref:Microsoft.AspNetCore.Components.CascadingValue%601>, which isn't notified about exceptions that happen inside notification recipients. The event handler is disconnected in the `Dispose` method to prevent a memory leak.
194202

195-
In the `Program` file&dagger;, `NotifyingDalek` is passed to create a <xref:Microsoft.AspNetCore.Components.CascadingValueSource%601> with an initial `Unit` value of 888 units:
203+
In the `Program` file, `NotifyingDalek` is passed to create a <xref:Microsoft.AspNetCore.Components.CascadingValueSource%601> with an initial `Unit` value of 888 units:
196204

197205
```csharp
198206
builder.Services.AddNotifyingCascadingValue(new NotifyingDalek() { Units = 888 });
199207
```
200208

201209
> [!NOTE]
202-
> &dagger;For Blazor Web App solutions consisting of server and client (`.Client`) projects:
203-
>
204-
> * The preceding `NotifyingDalek.cs` and `CascadingStateServiceCollectionExtensions.cs` files are placed in the `.Client` project.
205-
> * The preceding code is placed into each project's `Program` file.
210+
> For a Blazor Web App solution consisting of server and client (`.Client`) projects, the preceding code is placed into each project's `Program` file.
206211
207212
The following component is used to demonstrate how changing the value of `NotifyingDalek.Units` notifies subscribers.
208213

@@ -275,6 +280,16 @@ To demonstrate multiple subscriber notifications, the following `DaleksMain` com
275280
<Daleks />
276281
```
277282

283+
Add a navigation link to the `DaleksMain` component in `NavMenu.razor`:
284+
285+
```razor
286+
<div class="nav-item px-3">
287+
<NavLink class="nav-link" href="daleks-main">
288+
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Daleks
289+
</NavLink>
290+
</div>
291+
```
292+
278293
Because the <xref:Microsoft.AspNetCore.Components.CascadingValueSource%601>'s type in this example (`NotifyingDalek`) is a class type, you can meet virtually any state management feature specification requirement. However, subscriptions create overhead and reduce performance, so benchmark the performance of this approach in your app and compare it to other [state management approaches](xref:blazor/state-management) before adopting it in a production app with constrained processing and memory resources.
279294

280295
Any change in state (any property value change of the class) causes all subscribed components to rerender, regardless of which part of the state they use. **Avoid creating a single large class representing the entire global application state.** Instead, create granular classes and cascade them separately with specific subscriptions to cascading parameters, ensuring that only components subscribed to a specific portion of the application state are affected by changes.
@@ -409,6 +424,7 @@ Blazor Web Apps provide alternative approaches for cascading values that apply m
409424
For more information, see the following sections of this article:
410425

411426
* [Root-level cascading values](#root-level-cascading-values)
427+
* [Root-level cascading values with notifications](#root-level-cascading-values-with-notifications)
412428
* [Cascading values/parameters and render mode boundaries](#cascading-valuesparameters-and-render-mode-boundaries)
413429

414430
:::moniker-end
@@ -507,7 +523,7 @@ Cascading parameters aren't JSON-serializable because the typical usage patterns
507523

508524
Recommendations:
509525

510-
* If you need to make state available to all interactive components as a cascading parameter, we recommend using [root-level cascading values](#root-level-cascading-values). A factory pattern is available, and the app can emit updated values after app startup. Root-level cascading values are available to all components, including interactive components, since they're processed as DI services.
526+
* If you need to make state available to all interactive components as a cascading parameter, we recommend using [root-level cascading values](#root-level-cascading-values) or [root-level cascading values with notifications](#root-level-cascading-values-with-notifications). A factory pattern is available, and the app can emit updated values after app startup. Root-level cascading values are available to all components, including interactive components, since they're processed as DI services.
511527

512528
* For component library authors, you can create an extension method for library consumers similar to the following:
513529

aspnetcore/blazor/components/render-modes.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -974,7 +974,7 @@ To address this scenario, inject the service in a new imports file placed in the
974974
* <xref:blazor/fundamentals/signalr#websocket-compression-for-interactive-server-components>
975975
* <xref:blazor/security/interactive-server-side-rendering#interactive-server-components-with-websocket-compression-enabled>
976976
* <xref:blazor/js-interop/ssr>
977-
* [Cascading values/parameters and render mode boundaries](xref:blazor/components/cascading-values-and-parameters#cascading-valuesparameters-and-render-mode-boundaries): Also see the [Root-level cascading parameters](xref:blazor/components/cascading-values-and-parameters#root-level-cascading-parameters) section earlier in the article.
977+
* [Cascading values/parameters and render mode boundaries](xref:blazor/components/cascading-values-and-parameters#cascading-valuesparameters-and-render-mode-boundaries): Also see the [Root-level cascading values](xref:blazor/components/cascading-values-and-parameters#root-level-cascading-values) and [Root-level cascading values with notifications](xref:blazor/components/cascading-values-and-parameters#root-level-cascading-values-with-notifications) sections earlier in the article.
978978
* <xref:blazor/components/class-libraries-with-static-ssr>
979979
* [Secure data in Blazor Web Apps with Interactive Auto rendering](xref:blazor/security/index#secure-data-in-blazor-web-apps-with-interactive-auto-rendering)
980980

@@ -983,7 +983,7 @@ To address this scenario, inject the service in a new imports file placed in the
983983
:::moniker range="< aspnetcore-9.0"
984984

985985
* <xref:blazor/js-interop/ssr>
986-
* [Cascading values/parameters and render mode boundaries](xref:blazor/components/cascading-values-and-parameters#cascading-valuesparameters-and-render-mode-boundaries): Also see the [Root-level cascading parameters](xref:blazor/components/cascading-values-and-parameters#root-level-cascading-parameters) section earlier in the article.
986+
* [Cascading values/parameters and render mode boundaries](xref:blazor/components/cascading-values-and-parameters#cascading-valuesparameters-and-render-mode-boundaries): Also see the [Root-level cascading values](xref:blazor/components/cascading-values-and-parameters#root-level-cascading-values) and [Root-level cascading values with notifications](xref:blazor/components/cascading-values-and-parameters#root-level-cascading-values-with-notifications) sections earlier in the article.
987987
* <xref:blazor/components/class-libraries-with-static-ssr>
988988
* [Secure data in Blazor Web Apps with Interactive Auto rendering](xref:blazor/security/index#secure-data-in-blazor-web-apps-with-interactive-auto-rendering)
989989

aspnetcore/blazor/fundamentals/startup.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,10 @@ In a component that adopts Interactive WebAssembly rendering, wrap the component
676676
}
677677
```
678678

679+
:::moniker-end
680+
681+
:::moniker range=">= aspnetcore-9.0"
682+
679683
#### Global Interactive WebAssembly rendering with prerendering
680684

681685
*This scenario applies to global Interactive WebAssembly rendering with prerendering (`@rendermode="InteractiveWebAssembly"` on the `HeadOutlet` and `Routes` components in the `App` component).*
@@ -722,6 +726,10 @@ In `Layout/MainLayout.razor`:
722726
+ </ContentLoading>
723727
```
724728

729+
:::moniker-end
730+
731+
:::moniker range=">= aspnetcore-8.0"
732+
725733
#### Global Interactive WebAssembly rendering without prerendering
726734

727735
*This scenario applies to global Interactive WebAssembly rendering without prerendering (`@rendermode="new InteractiveWebAssemblyRenderMode(prerender: false)"` on the `HeadOutlet` and `Routes` components in the `App` component).*

aspnetcore/blazor/state-management.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -863,7 +863,7 @@ Use [cascading values and parameters](xref:blazor/components/cascading-values-an
863863

864864
:::moniker range=">= aspnetcore-8.0"
865865

866-
Root-level cascading values with a <xref:Microsoft.AspNetCore.Components.CascadingValueSource%601> permit Razor component subscriber notifications of changed cascading values. For more information and a working example, see the `NotifyingDalek` example in <xref:blazor/components/cascading-values-and-parameters#root-level-cascading-values>.
866+
Root-level cascading values with a <xref:Microsoft.AspNetCore.Components.CascadingValueSource%601> permit Razor component subscriber notifications of changed cascading values. For more information and a working example, see the `NotifyingDalek` example in <xref:blazor/components/cascading-values-and-parameters#root-level-cascading-values-with-notifications>.
867867

868868
:::moniker-end
869869

aspnetcore/migration/70-80.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,7 @@ Cascading parameters don't pass data across render mode boundaries, and layouts
495495

496496
The two approaches for migration are:
497497

498-
* (*Recommended*) Pass the state as a root-level cascading value. For more information, see [Root-level cascading values](xref:blazor/components/cascading-values-and-parameters#root-level-cascading-values).
498+
* (*Recommended*) Pass the state as a root-level cascading value. For more information, see the guidance on [root-level cascading values](xref:blazor/components/cascading-values-and-parameters#root-level-cascading-values) and [root-level cascading values with notifications](xref:blazor/components/cascading-values-and-parameters#root-level-cascading-values-with-notifications).
499499
* Wrap the router in the `Routes` component with the [`CascadingValue`](xref:Microsoft.AspNetCore.Components.CascadingValue%601) component and make the `Routes` component interactively rendered. For an example, see [`CascadingValue` component](xref:blazor/components/cascading-values-and-parameters?view=aspnetcore-8.0&preserve-view=true#cascadingvalue-component).
500500

501501
For more information, see [Cascading values/parameters and render mode boundaries](xref:blazor/components/cascading-values-and-parameters?view=aspnetcore-8.0&preserve-view=true#cascading-valuesparameters-and-render-mode-boundaries).

aspnetcore/release-notes/aspnetcore-8.0.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,10 @@ For more information, see <xref:blazor/fundamentals/routing?view=aspnetcore-8.0&
179179

180180
Root-level cascading values can be registered for the entire component hierarchy. Named cascading values and subscriptions for update notifications are supported.
181181

182-
For more information, see <xref:blazor/components/cascading-values-and-parameters?view=aspnetcore-8.0&preserve-view=true#root-level-cascading-values>.
182+
For more information, see the following resources:
183+
184+
* [Root-level cascading values](xref:blazor/components/cascading-values-and-parameters?view=aspnetcore-8.0&preserve-view=true#root-level-cascading-values)
185+
* [Root-level cascading values with notifications](xref:blazor/components/cascading-values-and-parameters?view=aspnetcore-8.0&preserve-view=true#root-level-cascading-values-with-notifications)
183186

184187
### Virtualize empty content
185188

0 commit comments

Comments
 (0)