[Blazor] SSR Error page gets overwritten by NotFound WASM component on InteractiveWebAssembly handoff
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 290
Description
### Is there an existing issue for this?
- [x] I have searched the existing issues
### Describe the bug
Using the default template with `InteractiveWebAssembly` in .NET 10 (or earlier), the Error page is defined on the Server project, and the Routes are defined in the Client project. When navigating to `/error`, the Error page is rendered statically on the server, then when the client app starts, overwrites the Error page with the NotFound page content on the client.
### Expected Behavior
The default project should demonstrate how to mix server-rendered and client-rendered content properly in the same app. Currently, the default project itself demonstrates mixing the render modes incorrectly.
While putting `@attribute [ExcludeFromInteractiveRouting]` can be considered a workaround, it is undesirable: the layout of the application itself might still be using WebAssembly for even simple interactivity, like collapsing menus. `ExcludeFromInteractiveRouting` bypasses starting the WebAssembly runtime altogether.
Possible solutions:
- Mark server-rendered content to persist on the client after client interactive routing kicks in. Possibly a marker attribute on the element, a directive, or an `@attribute` similar to `ExcludeFromInteractiveRoutingAttribute`.
- Allow `ExcludeFromInteractiveRoutingAttribute` to actually initialize the WebAssembly app, but leave the components marked with this attribute as-is in the DOM. Consider renaming the attribute if so. This might be easy to do using similar mechanics as seen in `PersistentState`
- Allow customizing the `Router`. For example, allow a behavior that lets the router "keep" the content as-is when a navigation event occurs, by overriding/passing `OnNavigatingAsync` or similar, or by inheriting from the built-in `Router`.
- Allow supplying a custom `Router` altogether. This would also allow multiple additional scenarios if community-built routers were to show up: handling localization in the URL, multiple hierarchic routers, etc.
- Allow rendering content on the server and let the client WebAssembly app "consume" the rendered static HTML as interactive. This might be a stretch, but for some simple cases, it can work.
- Modify/implement a new `RenderMode` that allows server-client handoff.
### Steps To Reproduce
`dotnet new blazor --name BlazorSSRCSR --all-interactive --interactivity WebAssembly`
`cd BlazorSSRCSR`
`dotnet run`
Navigate to the created app's `/error` endpoint. The endpoint will show the server side error, then after a short time, the client side router overwrites the content with the client side `NotFound` page content.
### Exceptions (if any)
_No response_
### .NET Version
10.0.100-rc.1.25451.107
### Anything else?
This is NOT the same as similar (possibly slightly related) issues:
- https://github.com/dotnet/aspnetcore/issues/38128
- https://github.com/dotnet/aspnetcore/issues/42561
Note that there's also the implication that if this is done, "mixing" render modes across a hierarchy might become possible. That would also require the user be able to set `RenderMode` to `Static` explicitly, which is currently not possible because it's not even defined in `RenderMode`: it's condered `Static` rendering when the `RenderMode` evaluates to `null`.
Contributor guide
Assessment
This issue has not been assessed yet.