Additional programmatic render mode guidance#31405
Conversation
It sounds like your understanding is pretty accurate - as soon as the router becomes interactive, it will stay that way until the page gets reloaded. That's because the logic determining the The way we've handled this in the Blazor Web app template (with individual auth and app-level interactivity) is we have a layout component that applies to all the "Account" pages whose purpose is to do a full page reload when the page gets navigated to interactively: @inherits LayoutComponentBase
@layout MainLayout
@inject NavigationManager NavigationManager
@if (HttpContext is null)
{
<p>Loading...</p>
}
else
{
@Body
}
@code {
[CascadingParameter]
private HttpContext? HttpContext { get; set; }
protected override void OnParametersSet()
{
if (HttpContext is null)
{
// If this code runs, we're currently rendering in interactive mode, so there is no HttpContext.
// The identity pages need to set cookies, so they require an HttpContext. To achieve this we
// must transition back from interactive mode to a server-rendered page.
NavigationManager.Refresh(forceReload: true);
}
}
}Customers will likely need to do something similar if they want part of their app to have top-level interactivity and the rest to using static server rendering.
The best real-world example I can think of is the Blazor Web app template with Identity pages and top level interactivity enabled. In that template, the developer expressed that their desired rendering strategy is to have top-level interactivity. Maybe the customer's app is highly interactive, so it doesn't make sense to add the complexity of SSR when it doesn't provide much benefit. However, the identity pages are incompatible with interactive rendering - they rely heavily on the So now you have two parts of the app that have fundamentally different requirements and rendering strategies, and you need a way to transition from one style to another. That's where this approach would be useful. |
For completeness in the discussion, here's the other piece to make it static SSR on the reload ... <Routes @rendermode="@RenderModeForPage" />
...
@code {
...
private IComponentRenderMode? RenderModeForPage => HttpContext.Request.Path.StartsWithSegments("/Account")
? null
: InteractiveServer;
}
Yes, I think this whole technique should be described. I'll work on it. |
|
@MackinnonBuck ... You know what .... this approach ... <Routes @rendermode="@RenderModeForPage" />[CascadingParameter]
private HttpContext HttpContext { get; set; } = default!;
private IComponentRenderMode? RenderModeForPage =>
HttpContext.GetEndpoint()?.Metadata.GetMetadata<RenderModeAttribute>()?.Mode;... 🤔... kind'a looks really good for the per-component approach. The project template is saying that if the static SSR component is in a defined area of the app (i.e., the UPDATE: Yep! It composed well on the PR at #31497 ... but don't look at that today (Thursday). I'm bound to make further updates to it Friday morning. I'll ping u for review tomorrow. |
|
I'm going to reconstitute this on a local branch for further work. |
Addresses #31403
Addresses #28161
Follow-up to PR earlier this morning #31404 that added a new section on programmatic render modes. There are some additional scenarios to cover in the section.
Mackinnon ... two problems with what I'm adding ...
The description of the code is very likely incorrect 🙈 (or at least incomplete) ...
What is this code doing? ... because when the router becomes interactive it seems like whatever was set on
Routesis what is then going to be used thereafter for each navigation ... well 🤔 ... is it that the router will continue working interactively until a route for a static SSR component can't be matched? ... and then a request is made back to the server, where the root component re-renders and then sucks in the render mode of the requested component and applies that to theRoutescomponent?Why bother? 😄 ... I don't understand what this approach going to do for devs? I think we need to tell devs exactly what scenario(s) this approach applies to.
This PR is based on the cross-linked discussion between a dev and Javier at Clarify Blazor Web Route behavior aspnetcore#52176. It looks like a workaround to avoid the flash-over from the server-rendered error page to the
NotFoundrouter content. Also possibly related are these variousNotFound/NotAuthorizedno-op situations, where under static SSR the server isn't going to render content from those components ... described by Javier at Clarify Blazor Web Route behavior aspnetcore#52176 (comment).If you look just above what this PR is adding, I placed some content earlier this morning on what seems like a simpler scenario where there's an app that defaults to static SSR components or per-component render modes but has this one area of components that you would like to explicitly configure globally for interactive SSR. Let me know if that bit is correct, but I want to mention that it seems simpler to understand why one would do that ... e.g., the
Adminarea of pages/components that the example uses. The dev wants to globally apply interactive SSR to that area of administrator pages and default the rest to static SSR or per-component render mode assignment. For the new content that I'm seeking to add on this PR, it's not as clear why one would adopt it, and I hope we can add a why to the approach.I'll also mention that I'm working a related issue at #31402. I'm going sleep on it because I just hit a brain fry 🧠🔥. I'll test locally soon with some scenarios to experience what's being discussed in PU issues (not authorized and not found scenarios) and figure out what updates to draft.
Internal previews