[Validation] TempData on a streaming page, and switching to session storage
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 290
Description
**Scenario contact:** @dariatiurina
## Scenario
Cookie-backed TempData cannot be persisted after a streaming response has started, because saving it requires a response cookie. Assigning a value before an `await` does not itself save the cookie: persistence happens after rendering completes. The framework logs guidance to use session storage instead. Session-backed values can be written after a flush when the session was established early.
Validate that the warning appears and is enough to act on, and that switching to session storage fixes the streaming case.
## Minimum build
.NET 11 RC1.
## Configurations to cover
* Blazor Web App
* [x] Static SSR
* [ ] Interactive Server
* [ ] Interactive WebAssembly
* [ ] Interactive Auto
* [ ] Standalone WebAssembly
* [ ] Hybrid (MAUI)
## Also exercise
* [ ] Published output
* [ ] An existing .NET 10 app upgraded to .NET 11
* [ ] Trimming or ahead-of-time compilation
* [ ] More than one server instance, or a proxy in front
* [ ] Hot Reload
* [ ] An IDE as well as the command line
* [ ] Container
* [x] N/A
## Setup
Run with Debug logging for the Components categories. Register the session services, a backing cache, and session middleware, then keep those registrations unchanged when switching TempData storage. Start each ordering comparison with a fresh cookie jar: an existing session cookie can hide a late-establishment failure.
## What to build
A streaming page that renders a heading immediately, awaits a controllable delay, then writes a message to TempData and redirects to an ordinary consuming reader that displays it once. Access the session-backed feature before the first flush for the positive session case. Confirm that the heading actually arrives before the delayed write instead of inferring a flush from the delay alone.
Build a variant that assigns the TempData value before the delay but still streams before completing. Compare it with a nonstreaming version of the page. An early assignment and a response whose headers have not been sent are different conditions.
Add a streaming page whose `[SupplyParameterFromSession]` property is subscribed before the first flush but assigned after the delay. For the negative case, have a separate parent mount a session-using child only after streaming starts, with no earlier session-using component or established session cookie.
## Things to try
* Run the streaming page with the default cookie storage and watch the second page and the console.
* Follow the logged guidance without looking anywhere else, and see whether it is enough.
* Switch to session storage and repeat, checking the message and that the session cookie was issued with the initial response headers.
* Compare the variant that writes before the first `await` against the one that writes after it, under cookie storage.
* Compare a delayed write to an early-subscribed session property with the deferred child's first subscription after the flush.
* Turn streaming off on the same page and compare both storage options.
* Record when the response started and when the session subscription and value assignment occurred in each variant.
## Expected behavior
Cookie-backed values cannot be persisted once the response has started, even if assigned earlier. Early session establishment allows later writes to persist. First establishing a session after the flush cannot issue a new cookie, which is the distinct negative case.
### Must hold
* With cookie storage and a write after the first flush, the second page shows nothing, and a `Warning` is logged whose text names the response having already started and names session storage as the fix.
* With cookie storage, assigning before the delay does not make the message persist if the response still starts before the end-of-render save.
* With session storage and a write after the first flush, the message appears exactly once on the second page.
* An early-subscribed session property assigned after the flush persists. A deferred child that first subscribes after the flush, with no existing session cookie, produces a session-establishment warning and does not persist its value to the next request.
* With streaming turned off, cookie storage carries the value across the redirect.
### Expected differences between configurations
* For cookie storage, whether the response has started before persistence determines whether the message survives. For session storage, early versus late session establishment is the relevant distinction.
## Evidence to capture
* What the second page showed under each storage option, for a write before the first `await` and a write after it.
* The verbatim warnings, with levels and categories, and the response-start/subscription/write order for each run.
* The exact configuration change that switched the storage.
## Documentation to use
* [ASP.NET Core Blazor state management](https://learn.microsoft.com/en-us/aspnet/core/blazor/state-management/server?view=aspnetcore-11.0#temporary-data-persistence)
Report whether the streaming limitation of cookie storage is documented anywhere, or whether the runtime warning is the only place a developer learns about it.
## What to report
Report results using the format described in the [validation testing manual](https://github.com/dotnet/aspnetcore/issues/68479). Include link to a repository with the test app.
Contributor guide
Assessment
This issue has not been assessed yet.