From 1964750605fd5405cee6483d60f689c205a8b937 Mon Sep 17 00:00:00 2001
From: guardrex <1622880+guardrex@users.noreply.github.com>
Date: Wed, 14 Jul 2021 15:11:06 -0500
Subject: [PATCH 1/2] Blazor preserve state during prerendering
---
.../prerendering-and-integration.md | 137 +++++++++++++++---
.../built-in/component-tag-helper.md | 3 +-
.../mvc/views/tag-helpers/built-in/index.md | 1 -
.../built-in/preserve-component-state.md | 103 +++++++++++++
aspnetcore/toc.yml | 2 +
5 files changed, 222 insertions(+), 24 deletions(-)
create mode 100644 aspnetcore/mvc/views/tag-helpers/built-in/preserve-component-state.md
diff --git a/aspnetcore/blazor/components/prerendering-and-integration.md b/aspnetcore/blazor/components/prerendering-and-integration.md
index 67182a576d09..ea5206a797df 100644
--- a/aspnetcore/blazor/components/prerendering-and-integration.md
+++ b/aspnetcore/blazor/components/prerendering-and-integration.md
@@ -258,27 +258,6 @@ Additional work might be required depending on the static resources that compone
>
> This is normal behavior because prerendering and integrating a Blazor WebAssembly app with routable Razor components is incompatible with the use of CSS selectors.
-## Additional Blazor WebAssembly resources
-
-* [Hosted Blazor WebAssembly logging](xref:blazor/fundamentals/logging#hosted-blazor-webassembly-logging)
-* [State management: Handle prerendering](xref:blazor/state-management#handle-prerendering)
-* [Prerendering support with assembly lazy loading](xref:blazor/webassembly-lazy-load-assemblies#lazy-load-assemblies-in-a-hosted-blazor-webassembly-solution)
-* Razor component lifecycle subjects that pertain to prerendering
- * [Component initialization (`OnInitialized{Async}`)](xref:blazor/components/lifecycle#component-initialization-oninitializedasync)
- * [After component render (`OnAfterRender{Async}`)](xref:blazor/components/lifecycle#after-component-render-onafterrenderasync)
- * [Stateful reconnection after prerendering](xref:blazor/components/lifecycle#stateful-reconnection-after-prerendering): Although the content in the section focuses on Blazor Server and stateful SignalR *reconnection*, the scenario for prerendering in hosted Blazor WebAssembly apps () involves similar conditions and approaches to prevent executing developer code twice. A *new state preservation feature* is planned for the ASP.NET Core 6.0 release that will improve the management of initialization code execution during prerendering.
- * [Detect when the app is prerendering](xref:blazor/components/lifecycle#detect-when-the-app-is-prerendering)
-* Authentication and authorization subjects that pertain to prerendering
- * [General aspects](xref:blazor/security/index#aspnet-core-blazor-authentication-and-authorization)
- * [Support prerendering with authentication](xref:blazor/security/webassembly/additional-scenarios#support-prerendering-with-authentication)
-* [Host and deploy: Blazor WebAssembly](xref:blazor/host-and-deploy/webassembly)
-
-::: moniker-end
-
-::: moniker range="< aspnetcore-5.0"
-
-Integrating Razor components into Razor Pages and MVC apps in a hosted Blazor WebAssembly solution is supported in ASP.NET Core in .NET 5 or later. Select a .NET 5 or later version of this article.
-
::: moniker-end
::: zone-end
@@ -676,6 +655,122 @@ The `_ViewImports.cshtml` file is located in the `Pages` folder of a Razor Pages
For more information, see .
+::: zone-end
+
+::: moniker range=">= aspnetcore-6.0"
+
+## Preserve prerendered state
+
+Without preserving prerendered state, any state that was used during prerendering is lost and must be recreated when the app is fully loaded. If any state is setup asynchronously, then the UI may flicker as the the prerendered UI is replaced with temporary placeholders and then fully rendered again.
+
+To solve this problem, Blazor supports persisting state into the prerendered page using the [Preserve Component State Tag Helper](xref:mvc/views/tag-helpers/builtin-th/preserve-component-state-tag-helper) (``).
+
+::: zone pivot="webassembly"
+
+`Pages/_Host.cshtml`:
+
+```cshtml
+
+
+
+ ...
+
+
+
+```
+
+::: zone-end
+
+::: zone pivot="server"
+
+`Pages/_Host.cshtml`:
+
+```cshtml
+
+
+
+ ...
+
+
+
+```
+
+::: zone-end
+
+In the app, you decide what state to persist using the `ComponentApplicationState` service. The `ComponentApplicationState.OnPersisting` event is fired just before the state is persisted into the prerendered page, which allows you to retrieve any persisted state when initializing a component.
+
+The following example below shows how the weather forecasts in the `FetchData` component from an app based on the Blazor project template can be persisted during prerendering and then retrieved to initialize the component. The Persist Component State Tag Helper persists the component state after all component invocations.
+
+`FetchData.razor`:
+
+```razor
+@page "/fetchdata"
+@implements IDisposable
+@inject ComponentApplicationState ApplicationState
+
+...
+
+@code {
+ protected override async Task OnInitializedAsync()
+ {
+ ApplicationState.OnPersisting += PersistForecasts;
+
+ if (!ApplicationState
+ .TryRedeemFromJson("fetchdata", out var forecasts))
+ {
+ forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
+ }
+ }
+
+ private Task PersistForecasts()
+ {
+ ApplicationState.PersistAsJson("fetchdata", forecasts);
+
+ return Task.CompletedTask;
+ }
+
+ void IDisposable.Dispose()
+ {
+ ApplicationState.OnPersisting -= PersistForecasts;
+ }
+}
+```
+
+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.
+
+::: moniker-end
+
+::: zone pivot="webassembly"
+
+::: moniker range=">= aspnetcore-5.0"
+
+## Additional Blazor WebAssembly resources
+
+* [Hosted Blazor WebAssembly logging](xref:blazor/fundamentals/logging#hosted-blazor-webassembly-logging)
+* [State management: Handle prerendering](xref:blazor/state-management#handle-prerendering)
+* [Prerendering support with assembly lazy loading](xref:blazor/webassembly-lazy-load-assemblies#lazy-load-assemblies-in-a-hosted-blazor-webassembly-solution)
+* Razor component lifecycle subjects that pertain to prerendering
+ * [Component initialization (`OnInitialized{Async}`)](xref:blazor/components/lifecycle#component-initialization-oninitializedasync)
+ * [After component render (`OnAfterRender{Async}`)](xref:blazor/components/lifecycle#after-component-render-onafterrenderasync)
+ * [Stateful reconnection after prerendering](xref:blazor/components/lifecycle#stateful-reconnection-after-prerendering): Although the content in the section focuses on Blazor Server and stateful SignalR *reconnection*, the scenario for prerendering in hosted Blazor WebAssembly apps () involves similar conditions and approaches to prevent executing developer code twice. A *new state preservation feature* is planned for the ASP.NET Core 6.0 release that will improve the management of initialization code execution during prerendering.
+ * [Detect when the app is prerendering](xref:blazor/components/lifecycle#detect-when-the-app-is-prerendering)
+* Authentication and authorization subjects that pertain to prerendering
+ * [General aspects](xref:blazor/security/index#aspnet-core-blazor-authentication-and-authorization)
+ * [Support prerendering with authentication](xref:blazor/security/webassembly/additional-scenarios#support-prerendering-with-authentication)
+* [Host and deploy: Blazor WebAssembly](xref:blazor/host-and-deploy/webassembly)
+
+::: moniker-end
+
+::: moniker range="< aspnetcore-5.0"
+
+Integrating Razor components into Razor Pages and MVC apps in a hosted Blazor WebAssembly solution is supported in ASP.NET Core in .NET 5 or later. Select a .NET 5 or later version of this article.
+
+::: moniker-end
+
+::: zone-end
+
+::: zone pivot="server"
+
## Additional Blazor Server resources
* [State management: Handle prerendering](xref:blazor/state-management#handle-prerendering)
diff --git a/aspnetcore/mvc/views/tag-helpers/built-in/component-tag-helper.md b/aspnetcore/mvc/views/tag-helpers/built-in/component-tag-helper.md
index 18132aff931b..13f23a4e8b45 100644
--- a/aspnetcore/mvc/views/tag-helpers/built-in/component-tag-helper.md
+++ b/aspnetcore/mvc/views/tag-helpers/built-in/component-tag-helper.md
@@ -3,6 +3,7 @@ title: Component Tag Helper in ASP.NET Core
author: guardrex
ms.author: riande
description: Learn how to use the ASP.NET Core Component Tag Helper to render Razor components in pages and views.
+monikerRange: '>= aspnetcore-3.1'
ms.custom: mvc
ms.date: 10/29/2020
no-loc: [Home, Privacy, Kestrel, appsettings.json, "ASP.NET Core Identity", cookie, Cookie, Blazor, "Blazor Server", "Blazor WebAssembly", "Identity", "Let's Encrypt", Razor, SignalR]
@@ -10,8 +11,6 @@ uid: mvc/views/tag-helpers/builtin-th/component-tag-helper
---
# Component Tag Helper in ASP.NET Core
-By [Daniel Roth](https://github.com/danroth27) and [Luke Latham](https://github.com/guardrex)
-
## Prerequisites
::: moniker range=">= aspnetcore-5.0"
diff --git a/aspnetcore/mvc/views/tag-helpers/built-in/index.md b/aspnetcore/mvc/views/tag-helpers/built-in/index.md
index 253602df4cb6..5b08fa82d398 100644
--- a/aspnetcore/mvc/views/tag-helpers/built-in/index.md
+++ b/aspnetcore/mvc/views/tag-helpers/built-in/index.md
@@ -8,7 +8,6 @@ ms.date: 10/10/2018
no-loc: [Home, Privacy, Kestrel, appsettings.json, "ASP.NET Core Identity", cookie, Cookie, Blazor, "Blazor Server", "Blazor WebAssembly", "Identity", "Let's Encrypt", Razor, SignalR]
uid: mvc/views/tag-helpers/builtin-th/Index
---
-
# ASP.NET Core built-in Tag Helpers
By [Peter Kellner](https://peterkellner.net)
diff --git a/aspnetcore/mvc/views/tag-helpers/built-in/preserve-component-state.md b/aspnetcore/mvc/views/tag-helpers/built-in/preserve-component-state.md
new file mode 100644
index 000000000000..1aa0f0898b17
--- /dev/null
+++ b/aspnetcore/mvc/views/tag-helpers/built-in/preserve-component-state.md
@@ -0,0 +1,103 @@
+---
+title: Preserve Component State Tag Helper in ASP.NET Core
+author: guardrex
+ms.author: riande
+description: Learn how to use the ASP.NET Core Preserve Component State Tag Helper to preserve state when prerendering components.
+monikerRange: '>= aspnetcore-6.0'
+ms.custom: mvc
+ms.date: 07/14/2021
+no-loc: [Home, Privacy, Kestrel, appsettings.json, "ASP.NET Core Identity", cookie, Cookie, Blazor, "Blazor Server", "Blazor WebAssembly", "Identity", "Let's Encrypt", Razor, SignalR]
+uid: mvc/views/tag-helpers/builtin-th/preserve-component-state-tag-helper
+zone_pivot_groups: blazor-hosting-models
+---
+# Preserve Component State Tag Helper in ASP.NET Core
+
+## Prerequisites
+
+Follow the guidance in the *Configuration* section for either:
+
+* [Blazor WebAssembly](xref:blazor/components/prerendering-and-integration?pivots=webassembly)
+* [Blazor Server](xref:blazor/components/prerendering-and-integration?pivots=server)
+
+## Preserve Component State Tag Helper
+
+To preserve state into prerendered components, use the Preserve Component State Tag Helper (). Add the `` tag inside the closing `
+
+
+ ...
+
+
+
+
+
+ ...
+
+
+