-
Notifications
You must be signed in to change notification settings - Fork 10k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Per-page opt out from interactive routing #55157
Per-page opt out from interactive routing #55157
Conversation
6a4a350
to
7f78bc7
Compare
src/Components/Endpoints/src/Builder/RazorComponentsEndpointHttpContextExtensions.cs
Outdated
Show resolved
Hide resolved
if (typeof(IComponent).IsAssignableFrom(type) && type.IsDefined(typeof(RouteAttribute))) | ||
if (typeof(IComponent).IsAssignableFrom(type) | ||
&& type.IsDefined(typeof(RouteAttribute)) | ||
&& type.GetCustomAttribute<AllowInteractiveRoutingAttribute>() is not { Allow: false }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could end up giving different results than the HttpContext.AllowsInteractiveRouting()
extension method if someone does something like MapRazorComponents<App>()...WithMetadata(new AllowInteractiveRoutingAttribute(false))
. This could lead people to think things are working at first only to realize it's broken later when they attempt an interactive navigation. Is there a way we can look at the final metadata from the potentially routable component's Endpoint
?
I know this is a problem for other metadata like [AllowAnonymous]
. Blazor not being able to "see" all the endpoint metadata can be helpful for working around the issue many people are facing in .NET 8 where the authorization middleware rejects requests before Blazor's AuthorizeRouteView
can handle it. That's because the authorization middleware will "see" the [AllowAnonymous]
metadata added by MapRazorComponents<App>()...AllowAnonymous()
and let the request through while AuthorizeRouteView
cannot. However, I think we should fix that. And I certainly don't think we should be adding new attributes that can be interpreted one way by Blazor's core components and another way by code checking the Endpoint
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a way we can look at the final metadata from the potentially routable component's Endpoint?
No, this code runs client-side (e.g., on WebAssembly), and can't see the server-side endpoint table.
If we later create some bigger mechanism for supplying extra info from the server-side endpoint table to the client, then we could use that here. But a new mechanism like that would be well out of scope for this issue. Until something like that exists, it's up to the developer not to cause themselves any extra problems here by thinking they can change the server-side metadata and the client would somehow know about that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we wanted to absolutely ensure consistency in this case, the only reasonable option I can think of is for the server not to read the attribute from endpoint metadata at all, but instead to read it from the component type directly, so you can't customize it using WithMetadata
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we wanted to absolutely ensure consistency in this case, the only reasonable option I can think of is for the server not to read the attribute from endpoint metadata at all, but instead to read it from the component type directly, so you can't customize it using
WithMetadata
.
I think that's how it should work for now. I like the cleanliness of just reading the metadata directly on the server side, but not if it's inconsistent with what the route table sees. If we figure out how to easily read the final metadata in both places later, we can make that change then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fine with me. It's how I implemented it originally 😄
@SteveSandersonMS I left a comment (last one) in #51046 giving more feedback from a blazor dev pov, but i saw a few discussions that got me wandering if its going to be the way people expect, so im going to ask here directly to clarify. With the new atrribute [StaticPage] and using a global render mode InteractiveWebassembly, will the wasm routes need to hit the server after the wasm is downloaded? This is the most annoying issue that devs are currently trying to solve, because this way we can have areas with SSR dumb pages and areas with smart Wasm pages, but this is beneficial compared to the current options only if the wasm routes don't need to hit the server after the wasm is downloaded. The exceptions would be the ones marked with [StaticPage], as in, a route that dont exist in wasm, will hit the server. Can you confirm this? and also, when can we expect this feature? Waiting for .net 9 for something like this is a long wait. |
@michelkommers You'll get to choose the render mode you use based on the attribute within your app (so its clear what mode and why its rendering) on a per endpoint (page) basis. The logic is something like:
Any page that has [ExcludeFromInteractiveRouting] will be excluded from the interactive router and will always render SSR via an enhanced nav. If you start a webassembly session and navigate between pages without [ExcludeFromInteractiveRouting] the navigations will be client-side navigations. If you navigate to a page with [ExcludeFromInteractiveRouting] we will perform an enhanced nav. If you navigate within pages with [ExcludeFromInteractiveRouting] we will perform an enhanced nav. |
Thanks @javiercn for taking the time to reply, this will work perfectly, this is exactly the behavior that people are waiting to be able to do. Thanks again and now I'm anxiously waiting for its release :) Keep up the good work |
This reverts commit a488faa.
Just a clarification on that, navigations from interactive to static will actually be full page loads, not enhanced nav. This is because we don't support detaching an interactive router once it's been attached. On the other hand, navigations from static to interactive will be enhanced navs, because we do support attaching interactive routers at any time.
This is true. I'm just confirming that in case my comment above makes it seem unclear! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great!
@guardrex I think would be good to add this feature to the official documentation and add an example of use of this feature under 'advanced scenarios'. |
@michelkommers ... No worries. All new features are tracked for docs 😉. |
@guardrex @michelkommers As a starting point, I added some content at dotnet/AspNetCore.Docs#32361 (comment). Please feel free to use or not use this! |
This allows page components to exclude themselves from interactive routing.
This is not a feature about rendermodes, but it's all we need to add into the framework for #51046, since the rest is achievable in a few lines of application code (as validated in the E2E tests in this PR).