Skip to content
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

Enable navigation when RenderModeServer #49768

Merged
merged 5 commits into from
Aug 10, 2023

Conversation

surayya-MS
Copy link
Member

Enable navigation when RenderModeServer

Fixes #49142

@surayya-MS surayya-MS requested a review from a team as a code owner August 1, 2023 11:17
@dotnet-issue-labeler dotnet-issue-labeler bot added the area-blazor Includes: Blazor, Razor Components label Aug 1, 2023
@ghost ghost added the area-blazor Includes: Blazor, Razor Components label Aug 1, 2023
@@ -115,7 +115,7 @@ function navigateToFromDotNet(uri: string, options: NavigationOptions): void {
function navigateToCore(uri: string, options: NavigationOptions, skipLocationChangingCallback = false): void {
const absoluteUri = toAbsoluteUri(uri);

if (!options.forceLoad && isWithinBaseUriSpace(absoluteUri)) {
if (!options.forceLoad && isWithinBaseUriSpace(absoluteUri) && hasInteractiveRouter()) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some tests are failing. I'll find another fix

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect this might not be a sufficient solution anyway because if it uses performExternalNavigation then it won't do enhanced navigation. We would still want enhanced navigation in this case. You can trigger that by calling performEnhancedPageLoad.

@ghost
Copy link

ghost commented Aug 8, 2023

Looks like this PR hasn't been active for some time and the codebase could have been changed in the meantime.
To make sure no conflicting changes have occurred, please rerun validation before merging. You can do this by leaving an /azp run comment here (requires commit rights), or by simply closing and reopening.

@ghost ghost added the pending-ci-rerun When assigned to a PR indicates that the CI checks should be rerun label Aug 8, 2023
surayya-MS and others added 4 commits August 9, 2023 15:18
…onents/Pages/EnhancedNav/PageWithServerRenderModeCanNavigate.razor

Co-authored-by: Steve Sanderson <SteveSandersonMS@users.noreply.github.com>
…azorComponents/Pages/EnhancedNav/PageWithServerRenderModeCanNavigate.razor"

This reverts commit 01ee2e9.
@MackinnonBuck MackinnonBuck removed the pending-ci-rerun When assigned to a PR indicates that the CI checks should be rerun label Aug 9, 2023
Comment on lines +47 to +61
export function hasProgrammaticEnhancedNavigationHandler(): boolean {
return programmaticEnhancedNavigationHandler !== undefined;
}

export function attachProgrammaticEnhancedNavigationHandler(handler: typeof programmaticEnhancedNavigationHandler) {
programmaticEnhancedNavigationHandler = handler;
}

export function performProgrammaticEnhancedNavigation(absoluteInternalHref: string, replace: boolean): void {
if (!programmaticEnhancedNavigationHandler) {
throw new Error('No enhanced programmatic navigation handler has been attached');
}

programmaticEnhancedNavigationHandler(absoluteInternalHref, replace);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This dance is to avoid NavigationEnhancement.ts and NavigationManager.ts from importing each other. That way, blazor.server.js and blazor.webassembly.js don't pay the cost of SSR features that they don't use.

@MackinnonBuck
Copy link
Member

Here's a summary of how NavigationManager.NavigateTo() now behaves when 1.) it's called from within an interactive context, 2.) there is no interactive router present, and 3.) enhanced navigation can be performed:

  • If the ForceLoad option is false, an enhanced navigation is performed
  • If the ForceLoad option is true, a full page reload occurs
  • The ReplaceHistoryEntry option is always respected
  • The LocationChanged event will not get invoked
  • The LocationChanging event will get invoked. This allows interception of programmatically initiated navigations.
    • Note that this is inconsistent with browser-initiated navigations, which won't invoke the LocationChanging event if an interactive router is present and enhanced navigation can be performed
    • If we wanted to completely disable this event for consistency's sake, we could probably do so
      • It just adds a tiny bit more complexity because it requires interactive .NET contexts to know whether enhanced navigations can occur
  • The HistoryEntryState property is not saved in browser history
    • This is because it's not a useful thing to do unless LocationChanged/LocationChanging events get fired from browser-initiated navigations, and in the current approach, they don't

IMO, the big question mark in the current approach is the decision to not invoke the LocationChanged/LocationChanging events during programmatic navigations when an interactive router is not present. This decision means:

  • It might not make sense to implement Trigger LocationChanging callbacks on enhanced navigation #48766 because if a navigation callback occurs, we know the router is also interactive and has the same render mode. If a component with another interactive render mode is present on the page, it would have to be in a totally separate component hierarchy from the interactive router. Should it really receive navigation events at that point?
  • The behavior of programmatically initiated navigations is consistent with the existing behavior of browser-initiated navigations when an interactive router does not exist (aside from the aforementioned LocationChanging caveat).

The alternative approach would be to invoke navigation events for programmatically initiated navigations. That would mean:

  • We have to change browser-initiated navigations to also always invoke navigation callbacks, even if no interactive router is present (this differs from the behavior of .NET 7 and earlier, but we could add a check to only enable this behavior when enhanced navigation is available).
  • We incur additional complexity:

Which behavior do you all think is more preferable? Should we never invoke navigation events when an interactive router isn't present, or should we always invoke navigation events?

@SteveSandersonMS's comment here contains some additional rationale regarding why never invoking navigation events is a viable option.

@danroth27 @captainsafia @surayya-MS

@MackinnonBuck
Copy link
Member

MackinnonBuck commented Aug 10, 2023

Note that, no matter which of those approaches we take, this PR might implement everything necessary for #49414. Rather than introducing a new API for an enhanced page refresh, we could recommend that customers do:

NavigationManager.NavigateTo(NavigationManager.Uri, replace: true);

We could still introduce a helper if we think it would be useful. Something like:

NavigationManager.EnhancedRefresh();

@MackinnonBuck
Copy link
Member

From offline discussion, it sounds like we're going to:

  • Keep the current behavior, where LocationChanged/LocationChanging events do not get emitted from JS when an enhanced navigation occurs.
  • Revisit potentially enabling navigation events for enhanced navigations in RC2

Therefore, I declare this PR ready for review

@surayya-MS
Copy link
Member Author

LGTM!

@MackinnonBuck MackinnonBuck merged commit 4cc5f02 into dotnet:main Aug 10, 2023
@ghost ghost added this to the 8.0-rc1 milestone Aug 10, 2023
@surayya-MS surayya-MS deleted the rmServerNav branch November 27, 2023 16:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-blazor Includes: Blazor, Razor Components
Projects
None yet
Development

Successfully merging this pull request may close these issues.

NavigationManager.NavigateTo doesn't navigate in Blazor Web App
4 participants