ASP.​NET Core in .NET 6 - Preserve prerendered state in Blazor apps

This is the next part of the ASP.NET Core on .NET 6 series. In this post, I'd like to have a look into preserve prerendered state in Blazor apps.

In Blazor apps can be prerendered on the server to optimize the load time. The app gets rendered immediately in the browser and is available for the user. Unfortunately, the state that is used on while prerendering on the server is lost on the client and needs to be recreated if the page is fully loaded and the UI may flicker, if the state is recreated and the prerendered HTML will be replaced by the HTML that is rendered again on the client.

To solve that, Microsoft adds support to persist the state into the prerendered page using the <preserve-component-state /> tag helper. This helps to set a stage that is identically on the server and on the client.

Actually, I have no idea why this isn't implemented as a default behavior in case the app get's prerendered. It should be done easily and wouldn't break anything, I guess.

Try to preserve prerendered states

I tried it with a new Blazor app and it worked quite well on the FetchData page. The important part is, to add the preserve-component-state tag helper after all used components in the _Host.cshtml. I placed it right before the script reference to the blazor.server.js:

    <component type="typeof(App)" render-mode="ServerPrerendered" />

    <div id="blazor-error-ui">
        <environment include="Staging,Production">
            An error has occurred. This application may no longer respond until reloaded.
        <environment include="Development">
            An unhandled exception has occurred. See browser dev tools for details.
        <a href="" class="reload">Reload</a>
        <a class="dismiss">🗙</a>

    <persist-component-state /> <!-- <== relevant tag helper -->
    <script src="_framework/blazor.server.js"></script>

The next snippet is more or less the same as on Microsoft's blog post, except that the forecast variable is missing there and System.Text.Json should be in the usings as well

@page "/fetchdata"
@implements IDisposable

@using PrerenderedState.Data
@using System.Text.Json
@inject WeatherForecastService ForecastService
@inject ComponentApplicationState ApplicationState


@code {
    private WeatherForecast[] forecasts;
    protected override async Task OnInitializedAsync()
        ApplicationState.OnPersisting += PersistForecasts;
        if (!ApplicationState.TryTakePersistedState("fetchdata", out var data))
            forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
            var options = new JsonSerializerOptions
                PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
                PropertyNameCaseInsensitive = true,
            forecasts = JsonSerializer.Deserialize<WeatherForecast[]>(data, options);

    private Task PersistForecasts()
        ApplicationState.PersistAsJson("fetchdata", forecasts);
        return Task.CompletedTask;

    void IDisposable.Dispose()
        ApplicationState.OnPersisting -= PersistForecasts;

What is the tag helper doing?

It renders an HTML comment to the page that contains the state in an encoded format:


(I added some line breaks here)

This reminds me of the ViewState we had in ASP.NET WebForms. Does this make Blazor Server the successor of ASP.NET WebForms? Just kidding.

Actually, it is not really the ViewState, because it not gets sent back to the server. It just helps the client restore the state created on the server initially while it was prerendered.

What's next?

In the next part In going to look into the support for HTTP/3 endpoint TLS configuration in ASP.NET Core.