-
Notifications
You must be signed in to change notification settings - Fork 10.6k
Description
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:
_retainedKeysis empty (lazy loading hasn't occurred), soRemoveis a no-op- Accessing
Datatriggers the lazyLoad()method, which adds all keys from the cookie to_retainedKeys - The key is now back in
_retainedKeys, soSave()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 correctlyExpected 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
dotnet runthe repro project- Click "Set TempData & Redirect"
- Observe the message appears (value was read via
Get()) - 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.