Skip to content

TempData.Get() does not consume value when it is the first access on a request #65720

@danroth27

Description

@danroth27

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

TempData.Get() does not consume the value when it is the first access to TempData on a request. The value persists indefinitely across page refreshes instead of being deleted after the first read.

Root cause

In TempData.Get(), _retainedKeys.Remove(key) executes before the Data property is accessed:

public object? Get(string key)
{
    _retainedKeys.Remove(key);          // (1) No-op: TempData hasn't been loaded yet
    return Data.GetValueOrDefault(key); // (2) Triggers lazy Load(), which re-adds key to _retainedKeys
}

When Get() is the first access to TempData on a request:

  1. _retainedKeys is empty (lazy loading hasn't occurred), so Remove is a no-op
  2. Accessing Data triggers the lazy Load() method, which adds all keys from the cookie to _retainedKeys
  3. The key is now back in _retainedKeys, so Save() persists it — the value is never consumed

The same issue likely affects TryGetValue() and the indexer getter (which delegates to Get()).

Suggested fix

Swap the order so lazy loading is triggered before removing from _retainedKeys:

public object? Get(string key)
{
    var value = Data.GetValueOrDefault(key); // Trigger lazy load first
    _retainedKeys.Remove(key);               // Now Remove works correctly
    return value;
}

Workaround

Force TempData to load before calling Get():

_ = TempData?.ContainsKey("Message");  // triggers lazy load
message = TempData?.Get("Message") as string;  // now consumes correctly

Expected Behavior

After setting a TempData value via TempData["Message"] = "hello" and redirecting, TempData.Get("Message") should return the value once. On the next page refresh, the value should be gone.

Steps To Reproduce

  1. dotnet run the repro project
  2. Click "Set TempData & Redirect"
  3. Observe the message appears (value was read via Get())
  4. Refresh the page — the message should disappear but it persists on every refresh

Repro project

https://github.com/danroth27/BlazorTempDataBug

Exceptions (if any)

No response

.NET Version

11.0.100-preview.2.26154.117

Anything else?

The framework's E2E tests for TempData appear to avoid this issue because the test component (TempDataComponent.razor) checks if (Handler is not null) { return; } in OnInitialized(), which skips Get() during the POST request. This means TempData is always accessed at least once (during the POST render) before Get() is called on the subsequent GET, masking the lazy-loading ordering issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-blazorIncludes: Blazor, Razor Components

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions