Skip to content

Commit 3ff48fe

Browse files
committed
Fix: move setting response dispatch to invoker.
1 parent f078428 commit 3ff48fe

File tree

6 files changed

+37
-31
lines changed

6 files changed

+37
-31
lines changed

src/Components/Components/src/Routing/Router.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -384,12 +384,12 @@ private void OnLocationChanged(object sender, LocationChangedEventArgs args)
384384

385385
private void OnNotFound(object sender, NotFoundEventArgs args)
386386
{
387-
if (_renderHandle.IsInitialized)
387+
if (_renderHandle.IsInitialized && NotFoundPage != null)
388388
{
389+
// setting the path signals to the endpoint renderer that router handled rendering
390+
args.Path = _notFoundPageRoute;
389391
Log.DisplayingNotFound(_logger);
390392
RenderNotFound();
391-
// setting the path signals to the endpoint renderer that router handled rendering
392-
args.Path = _notFoundPageRoute ?? "not-found-handled-by-router";
393393
}
394394
}
395395

src/Components/Endpoints/src/RazorComponentEndpointInvoker.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,11 @@ await _renderer.InitializeStandardComponentServicesAsync(
136136
}
137137
}
138138

139+
if (_renderer.NotFoundEventArgs != null)
140+
{
141+
_renderer.SetNotFoundWhenResponseNotStarted();
142+
}
143+
139144
if (!quiesceTask.IsCompleted)
140145
{
141146
// An incomplete QuiescenceTask indicates there may be streaming rendering updates.
@@ -155,6 +160,10 @@ await _renderer.InitializeStandardComponentServicesAsync(
155160
if (!quiesceTask.IsCompletedSuccessfully)
156161
{
157162
await _renderer.SendStreamingUpdatesAsync(context, quiesceTask, bufferWriter);
163+
if (_renderer.NotFoundEventArgs != null)
164+
{
165+
await _renderer.SetNotFoundWhenResponseHasStarted();
166+
}
158167
}
159168
else
160169
{

src/Components/Endpoints/src/Rendering/EndpointHtmlRenderer.EventDispatch.cs

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -79,37 +79,38 @@ private Task ReturnErrorResponse(string detailedMessage)
7979
: Task.CompletedTask;
8080
}
8181

82-
internal async Task SetNotFoundResponseAsync(string baseUri, NotFoundEventArgs args)
82+
internal void SetNotFoundWhenResponseNotStarted()
8383
{
84-
if (_httpContext.Response.HasStarted ||
85-
// POST waits for quiescence -> rendering the NotFoundPage would be queued for the next batch
86-
// but we want to send the signal to the renderer to stop rendering future batches -> use client rendering
87-
HttpMethods.IsPost(_httpContext.Request.Method))
88-
{
89-
if (string.IsNullOrEmpty(_notFoundUrl))
90-
{
91-
_notFoundUrl = GetNotFoundUrl(baseUri, args);
92-
}
93-
var defaultBufferSize = 16 * 1024;
94-
await using var writer = new HttpResponseStreamWriter(_httpContext.Response.Body, Encoding.UTF8, defaultBufferSize, ArrayPool<byte>.Shared, ArrayPool<char>.Shared);
95-
using var bufferWriter = new BufferedTextWriter(writer);
96-
HandleNotFoundAfterResponseStarted(bufferWriter, _httpContext, _notFoundUrl);
97-
await bufferWriter.FlushAsync();
98-
}
99-
else
84+
_httpContext.Response.StatusCode = StatusCodes.Status404NotFound;
85+
86+
// When the application triggers a NotFound event, we continue rendering the current batch.
87+
// However, after completing this batch, we do not want to process any further UI updates,
88+
// as we are going to return a 404 status and discard the UI updates generated so far.
89+
SignalRendererToFinishRendering();
90+
}
91+
92+
internal async Task SetNotFoundWhenResponseHasStarted()
93+
{
94+
if (string.IsNullOrEmpty(_notFoundUrl))
10095
{
101-
_httpContext.Response.StatusCode = StatusCodes.Status404NotFound;
96+
var baseUri = $"{_httpContext.Request.Scheme}://{_httpContext.Request.Host}{_httpContext.Request.PathBase}/";
97+
_notFoundUrl = GetNotFoundUrl(baseUri, NotFoundEventArgs);
10298
}
99+
var defaultBufferSize = 16 * 1024;
100+
await using var writer = new HttpResponseStreamWriter(_httpContext.Response.Body, Encoding.UTF8, defaultBufferSize, ArrayPool<byte>.Shared, ArrayPool<char>.Shared);
101+
using var bufferWriter = new BufferedTextWriter(writer);
102+
HandleNotFoundAfterResponseStarted(bufferWriter, _httpContext, _notFoundUrl);
103+
await bufferWriter.FlushAsync();
103104

104105
// When the application triggers a NotFound event, we continue rendering the current batch.
105106
// However, after completing this batch, we do not want to process any further UI updates,
106107
// as we are going to return a 404 status and discard the UI updates generated so far.
107108
SignalRendererToFinishRendering();
108109
}
109110

110-
private string GetNotFoundUrl(string baseUri, NotFoundEventArgs args)
111+
private string GetNotFoundUrl(string baseUri, NotFoundEventArgs? args)
111112
{
112-
string? path = args.Path;
113+
string? path = args?.Path;
113114
if (string.IsNullOrEmpty(path))
114115
{
115116
var pathFormat = _httpContext.Items[nameof(StatusCodePagesOptions)] as string;

src/Components/Endpoints/src/Rendering/EndpointHtmlRenderer.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public EndpointHtmlRenderer(IServiceProvider serviceProvider, ILoggerFactory log
6363
}
6464

6565
internal HttpContext? HttpContext => _httpContext;
66-
internal NotFoundEventArgs? NotFoundEventArgs { get; set; }
66+
internal NotFoundEventArgs? NotFoundEventArgs { get; private set; }
6767

6868
internal void SetHttpContext(HttpContext httpContext)
6969
{
@@ -86,11 +86,7 @@ internal async Task InitializeStandardComponentServicesAsync(
8686
var navigationManager = httpContext.RequestServices.GetRequiredService<NavigationManager>();
8787
((IHostEnvironmentNavigationManager)navigationManager)?.Initialize(GetContextBaseUri(httpContext.Request), GetFullUri(httpContext.Request), OnNavigateTo);
8888

89-
navigationManager?.OnNotFound += (sender, args) =>
90-
{
91-
NotFoundEventArgs = args;
92-
_ = GetErrorHandledTask(SetNotFoundResponseAsync(navigationManager.BaseUri, args));
93-
};
89+
navigationManager?.OnNotFound += (sender, args) => NotFoundEventArgs = args;
9490

9591
var authenticationStateProvider = httpContext.RequestServices.GetService<AuthenticationStateProvider>();
9692
if (authenticationStateProvider is IHostEnvironmentAuthenticationStateProvider hostEnvironmentAuthenticationStateProvider)

src/Components/Endpoints/test/EndpointHtmlRendererTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1823,7 +1823,7 @@ protected override void ProcessPendingRender()
18231823
public async Task SetNotFoundResponseAsync(HttpContext httpContext, NotFoundEventArgs args)
18241824
{
18251825
SetHttpContext(httpContext);
1826-
await SetNotFoundResponseAsync(httpContext.Request.PathBase, args);
1826+
await SetNotFoundWhenResponseHasStarted();
18271827
}
18281828
}
18291829

src/Components/test/E2ETest/ServerRenderingTests/NoInteractivityTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ private void AssertNotFoundRendered_ResponseStarted_Or_POST(bool hasReExecutionM
239239
public void NotFoundSetOnFormSubmit_ResponseNotStarted_SSR(bool hasReExecutionMiddleware, bool hasCustomNotFoundPageSet)
240240
{
241241
string reexecution = hasReExecutionMiddleware ? "/reexecution" : "";
242-
string testUrl = $"{ServerPathBase}{reexecution}/post-not-found-ssr-streaming?useCustomNotFoundPage={hasCustomNotFoundPageSet}";
242+
string testUrl = $"{ServerPathBase}{reexecution}/post-not-found-ssr?useCustomNotFoundPage={hasCustomNotFoundPageSet}";
243243
Navigate(testUrl);
244244
Browser.FindElement(By.Id("not-found-form")).FindElement(By.TagName("button")).Click();
245245

0 commit comments

Comments
 (0)