-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Closed
Labels
area-blazorIncludes: Blazor, Razor ComponentsIncludes: Blazor, Razor ComponentsbugThis issue describes a behavior which is not expected - a bug.This issue describes a behavior which is not expected - a bug.
Milestone
Description
Currently it doesn't work to do this:
app.UseExceptionHandler("/Error");... where /Error corresponds to a Razor Component like:
@page "/Error"
<h1>This is the error page</h1>In practice what happens is that:
- Assume some other Razor Component endpoint (SSR) throws an unhandled exception during rendering
ExceptionHandlerMiddlewareImplcatches the original unhandled exception, changes the endpoint to/Error(a Razor Component endpoint), and re-runs the pipeline- We get back into
EndpointHtmlRenderer.InitializeStandardComponentServicesAsyncwhich tries to initialize the same scoped services for a second time. - They don't support being initialized for a second time. The first thing that happens to throw is
NavigationManager.Initialize(as reported at HttpNavigationManager already initialized on Blazor SSR. #49456) - The system falls back on showing the standard error page
Difficulties
This isn't straightforward to resolve for two main reasons:
- It really isn't valid to reinitialize or even reuse the same scoped services when re-running the pipeline. The concept of re-running the pipeline without creating a new DI scope is extremely dubious since by definition, the old DI scope is now in an undefined error state - for security, Blazor Server is extremely careful not to let things keep running once they get into an undefined state.
- Possible solution: We could change
RazorComponentEndpointInvokerto guarantee we create a new DI scope for the error endpoint. This would be inconsistent with MVC etc but at least safer. And would solve the double-initialization exceptions.
- Possible solution: We could change
- Even if we can make the endpoint render, it's going to behave badly if you have an interactive router in your layout. Consider:
- Some Razor Component endpoint at
/MyComponentThatThrowsthrows an unhandled exception - The error middleware runs
Error.razor, which uses the sameLayout.razor, which contains a@rendermode=Serverrouter and<script src="blazor.web.js"></script> - The error page starts up a new circuit and runs the router on the server.
- It will still see the current URL
/MyComponentThatThrowsand hence now re-runs the same component that throws a second time - Possible solution: We somehow would have to emit info into the error page markup to tell the JS-side code not to start any interactive runtime. We might get away with just putting that into the default project template but it would be nasty and error prone if people try to create their own error page from scratch.
- Some Razor Component endpoint at
Metadata
Metadata
Assignees
Labels
area-blazorIncludes: Blazor, Razor ComponentsIncludes: Blazor, Razor ComponentsbugThis issue describes a behavior which is not expected - a bug.This issue describes a behavior which is not expected - a bug.