Fix TempData and SupplyParameterFromSession persistence for streaming SSR case#66832
Open
dariatiurina wants to merge 5 commits into
Open
Fix TempData and SupplyParameterFromSession persistence for streaming SSR case#66832dariatiurina wants to merge 5 commits into
dariatiurina wants to merge 5 commits into
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes persistence timing for [SupplyParameterFromSession] and TempData during streaming server-side rendering (SSR) by moving persistence from HttpResponse.OnStarting callbacks to explicit persistence calls made after rendering/streaming completes.
Changes:
- Added explicit post-render persistence calls for session-supplied cascading values and TempData in
RazorComponentEndpointInvoker. - Removed
Response.OnStarting-based persistence registration fromSessionCascadingValueSupplierand TempData creation. - Updated session-related unit tests to call
PersistAllValues()explicitly.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Components/Endpoints/src/RazorComponentEndpointInvoker.cs | Adds explicit session + TempData persistence after rendering/streaming completes. |
| src/Components/Endpoints/src/SessionCascadingValueSupplier.cs | Removes OnStarting registration so persistence is driven externally. |
| src/Components/Endpoints/src/TempData/TempDataProviderServiceCollectionExtensions.cs | Removes OnStarting persistence and adds PersistTempData(HttpContext) helper. |
| src/Components/Endpoints/test/Session/SessionSubscriptionTest.cs | Updates subscription test to use explicit persistence instead of firing OnStarting. |
| src/Components/Endpoints/test/Session/SessionCascadingValueSupplierTest.cs | Renames/updates test to validate explicit persistence behavior. |
This was referenced May 27, 2026
Open
…hub.com/dariatiurina/aspnetcore into 66745-streamingssr-tempdata-sessiondata
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fix TempData and SupplyParameterFromSession persistence for streaming SSR case
Description
Fixes a bug where
[SupplyParameterFromSession]and session-basedTempDatavalues set during streaming SSR were silently lost. Both mechanisms previously relied exclusively onResponse.OnStartingcallbacks to persist state, which fire before the response starts — meaning any values modified during async/streaming rendering (after anawaitinOnInitializedAsync) were never captured.This PR adds explicit persistence calls in
RazorComponentEndpointInvokerthat run after all rendering (including streaming) completes, ensuring values set during the streaming phase are persisted.Changes
RazorComponentEndpointInvoker.cs: Added explicit calls toSessionCascadingValueSupplier.PersistAllValues(clean: true)andTempDataProviderServiceCollectionExtensions.PersistTempData()after rendering completes (afterSendStreamingUpdatesAsync/EmitInitializersIfNecessary), but before persisted component state is emitted and beforeBufferedTextWriter.FlushAsync().SessionCascadingValueSupplier.cs: Added acleanparameter toPersistAllValues(). Whencleanisfalse(the default, used by the existingOnStartingcallback), null values write empty strings to the session to ensure the session cookie is established before the response starts. Whencleanistrue(used by the explicit post-render call), null keys are removed from session. TheOnStartingcallback is retained specifically to ensure the session cookie is registered before the response begins.TempDataCascadingValueSupplier.cs: Retains the existingOnStartingcallback for the non-streaming case. The invoker's explicitPersistTempData()call after streaming ensures values set during async rendering are also captured.TempDataProviderServiceCollectionExtensions.cs: Added aPersistTempData(HttpContext)static method that saves TempData on demand, called by the endpoint invoker at the right time.New E2E tests (
StreamingSessionPersistenceTest): Three tests verifying that values set during streaming SSR survive across request boundaries:StreamingSSR_PersistsSupplyParameterFromSession_AfterAsyncRenderingStreamingSSR_PersistsSupplyParameterFromTempData_AfterAsyncRenderingStreamingSSR_PersistsTempDataCascadingParameter_AfterAsyncRenderingNew test pages:
StreamingSessionPersistence.razor(writes values afterawait Task.Delayto enter the streaming phase) andStreamingSessionPersistenceRead.razor(reads values on a subsequent request to verify persistence).Updated unit tests:
SessionCascadingValueSupplierTestandSessionSubscriptionTestwith comprehensive coverage of the explicit persistence model (registering callbacks, duplicate key detection, null handling, serialization errors, key case normalization, etc.).How persistence timing works
The key to understanding this change is the
BufferedTextWriterused byRenderComponentCore. This writer accumulates all HTML output in memory and only flushes toResponse.Body(starting the HTTP response) whenFlushAsync()is explicitly called at the very end of the method.Non-streaming case
In the non-streaming path, both the
OnStartingcallbacks and the new explicit calls execute beforeResponse.HasStarted:Cookie-based
TempDataworks here becauseSet-Cookieheaders can still be added before the flush.Streaming case
In the streaming path,
SendStreamingUpdatesAsyncflushes the buffer internally, starting the response mid-render. The explicit persistence calls happen after streaming completes:This is why the fix matters for streaming:
OnStartingonly): Fired before the response started, so it ran before streaming components finished — values modified during streaming were silently lost.Note on cookie-based
TempData: Cookie-based TempData cannot work in the streaming case regardless of approach — HTTP headers (Set-Cookie) cannot be set after the response body has started. This is not a regression; cookies are fundamentally incompatible with streaming SSR. Session-based persistence ([SupplyParameterFromSession]and session-basedTempData) works correctly because session state is stored server-side and doesn't depend on response headers.Testing
E2E tests (
StreamingSessionPersistenceTest):[StreamRendering]pages that set values after anawait(entering the streaming phase), then navigates to a read page to verify values survived the request boundary.[SupplyParameterFromSession],[SupplyParameterFromTempData], andITempDatacascading parameter.Fixes #66745