Skip to content

PersistentStateAttribute not working in Blazor when server and client have different trimming settings #64693

@StefanOverHaevgRZ

Description

@StefanOverHaevgRZ

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

Observations

The AntiforgeryToken in the logout form does not always render:

Image

The antiforgery token was correctly "rendered" with .NET 9. The issue only appeared after migrating to .NET 10.
After investigating for several hours, we noticed the issue only appears when the app is running in Docker.
We created a minimalistic project based on the offical Blazor project template and could reproduce the issue there.

After further investigation, we assume that the issue is caused by the new declarative model for persisting state from components and services.

With .NET 9, the antiforgery token was retrieved using PersistentComponentState. With .NET 10 it's using the PersistentState attribute on the DefaultAntiforgeryStateProvider.CurrentToken.

✅ The antiforgery token gets correctly generated and persisted to the component state during the prerendering, both for normal debugging (without Docker) and Docker debugging.
✅ When inspecting the persistent state in WASM, the antiforgery token is part of the payload, both for normal and Docker debugging.
❌ The CurrentToken property does not get populated with the payload during Docker debugging (nor hosting on a server).

Assumption

During docker compilation, something gets trimmed/modfied, causing the key generation to be different.

Workaround

We created a custom implementation of the AntiforgeryStateProvider and registered it in the client with a constant key, circumventing the key generation:

// Program.cs
builder.Services.AddSingleton<AntiforgeryStateProvider, WorkaroundAntiforgeryStateProvider>();

// WorkaroundAntiforgeryStateProvider
public class WorkaroundAntiforgeryStateProvider : AntiforgeryStateProvider
{
    private readonly PersistentComponentState _persistentComponentState;

    public WorkaroundAntiforgeryStateProvider(PersistentComponentState persistentComponentState)
    {
        _persistentComponentState = persistentComponentState;
    }

    public override AntiforgeryRequestToken? GetAntiforgeryToken()
    {
        _persistentComponentState.TryTakeFromJson<AntiforgeryRequestToken>(
            "KSztT84gAiV0IO/UBRRpOm8K4jqEf\u002B1JzvVOCMBlsiU=",
            out var token);
        return token;
    }
}

Correlations

Issue #63928 might have the same underlying issue.

Expected Behavior

The hidden antiforgery token input field should be rendered when running in Docker:

Image

Steps To Reproduce

Repository to reproduce the issue: https://github.com/StefanOverHaevgRZ/dotnet-antiforgerytoken-issue
The repo is basically the standard .NET 10 Blazor Web App template, with individual accounts + .NET SDK Container support.

Steps to reproduce:

  1. Prepare SQL server (either by the docker-compose.yml or manually).
    1. Create Docker network sqlserver for the container and the SQL server.
    2. Start SQL Server in a separate Docker container called sqlserver (or adjust connection string), attached to the sqlserver network.
  2. Start the app with Container (.NET SDK) profile.
  3. Register a new account and confirm the registration.
  4. Go to login page and login with the new account.
  5. Inspect logout button --> No antiforgery token rendered.

Exceptions (if any)

No response

.NET Version

10.0.100

Anything else?

  • Visual Studio 2026 (18.0.2)
  • Docker Desktop 4.53.0

Metadata

Metadata

Assignees

Labels

area-blazorIncludes: Blazor, Razor Components

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions