Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 22 additions & 6 deletions aspnetcore/blazor/components/cascading-values-and-parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ builder.Services.AddCascadingValue(sp =>
>
> 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.

## Root-level cascading values with notifications

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.

In the following example:
Expand All @@ -103,6 +105,9 @@ In the following example:

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.

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

`NotifyingDalek.cs`:

```csharp
Expand Down Expand Up @@ -143,6 +148,9 @@ public class NotifyingDalek : INotifyPropertyChanged

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

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

`CascadingStateServiceCollectionExtensions.cs`:

```csharp
Expand Down Expand Up @@ -192,17 +200,14 @@ public static class CascadingStateServiceCollectionExtensions

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.

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:
In the `Program` file, `NotifyingDalek` is passed to create a <xref:Microsoft.AspNetCore.Components.CascadingValueSource%601> with an initial `Unit` value of 888 units:

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

> [!NOTE]
> &dagger;For Blazor Web App solutions consisting of server and client (`.Client`) projects:
>
> * The preceding `NotifyingDalek.cs` and `CascadingStateServiceCollectionExtensions.cs` files are placed in the `.Client` project.
> * The preceding code is placed into each project's `Program` file.
> For a Blazor Web App solution consisting of server and client (`.Client`) projects, the preceding code is placed into each project's `Program` file.

The following component is used to demonstrate how changing the value of `NotifyingDalek.Units` notifies subscribers.

Expand Down Expand Up @@ -275,6 +280,16 @@ To demonstrate multiple subscriber notifications, the following `DaleksMain` com
<Daleks />
```

Add a navigation link to the `DaleksMain` component in `NavMenu.razor`:

```razor
<div class="nav-item px-3">
<NavLink class="nav-link" href="daleks-main">
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Daleks
</NavLink>
</div>
```

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.

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.
Expand Down Expand Up @@ -409,6 +424,7 @@ Blazor Web Apps provide alternative approaches for cascading values that apply m
For more information, see the following sections of this article:

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

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

Recommendations:

* 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.
* 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.

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

Expand Down
4 changes: 2 additions & 2 deletions aspnetcore/blazor/components/render-modes.md
Original file line number Diff line number Diff line change
Expand Up @@ -974,7 +974,7 @@ To address this scenario, inject the service in a new imports file placed in the
* <xref:blazor/fundamentals/signalr#websocket-compression-for-interactive-server-components>
* <xref:blazor/security/interactive-server-side-rendering#interactive-server-components-with-websocket-compression-enabled>
* <xref:blazor/js-interop/ssr>
* [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.
* [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.
* <xref:blazor/components/class-libraries-with-static-ssr>
* [Secure data in Blazor Web Apps with Interactive Auto rendering](xref:blazor/security/index#secure-data-in-blazor-web-apps-with-interactive-auto-rendering)

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

* <xref:blazor/js-interop/ssr>
* [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.
* [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.
* <xref:blazor/components/class-libraries-with-static-ssr>
* [Secure data in Blazor Web Apps with Interactive Auto rendering](xref:blazor/security/index#secure-data-in-blazor-web-apps-with-interactive-auto-rendering)

Expand Down
8 changes: 8 additions & 0 deletions aspnetcore/blazor/fundamentals/startup.md
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,10 @@ In a component that adopts Interactive WebAssembly rendering, wrap the component
}
```

:::moniker-end

:::moniker range=">= aspnetcore-9.0"

#### Global Interactive WebAssembly rendering with prerendering

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

:::moniker-end

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

#### Global Interactive WebAssembly rendering without prerendering

*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).*
Expand Down
2 changes: 1 addition & 1 deletion aspnetcore/blazor/state-management.md
Original file line number Diff line number Diff line change
Expand Up @@ -863,7 +863,7 @@ Use [cascading values and parameters](xref:blazor/components/cascading-values-an

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

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>.
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>.

:::moniker-end

Expand Down
2 changes: 1 addition & 1 deletion aspnetcore/migration/70-80.md
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@ Cascading parameters don't pass data across render mode boundaries, and layouts

The two approaches for migration are:

* (*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).
* (*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).
* 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).

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).
Expand Down
5 changes: 4 additions & 1 deletion aspnetcore/release-notes/aspnetcore-8.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,10 @@ For more information, see <xref:blazor/fundamentals/routing?view=aspnetcore-8.0&

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

For more information, see <xref:blazor/components/cascading-values-and-parameters?view=aspnetcore-8.0&preserve-view=true#root-level-cascading-values>.
For more information, see the following resources:

* [Root-level cascading values](xref:blazor/components/cascading-values-and-parameters?view=aspnetcore-8.0&preserve-view=true#root-level-cascading-values)
* [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)

### Virtualize empty content

Expand Down
Loading