Skip to content

[Blazor] each navigation to external logs 2 errors a minute later #53271

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

Merged
merged 5 commits into from
Jan 11, 2024

Conversation

javiercn
Copy link
Member

@javiercn javiercn commented Jan 10, 2024

Scenario

This happens on navigations that are not part of Blazor Server, like a navigation to a Razor Page, or similar, but not to navigations to other origins.

Explanation

  • What happens is that the user clicks the link to the target URL.
  • We intercept that link in the JS.
  • Call .NET to determine if we need to prevent navigation to the URL.
  • We determine we don't need to and call "navigateTo" via JS interop in NavigationManager.ts.
  • "navigateTo" determines the URL is external at that point and sets the location to the new URL.
  • That automatically triggers the unload event in the browser, which in turn triggers the call to _disconnect.
  • The result is that the promise to "navigateTo" never completes (the page gets unloaded before that) and as a result, the associated task in .NET ends up getting cancelled with a timeout.

Fix

There were two possible fixes:

  • Defer the call to location.url via setTimeout. This allows the call to "navigateTo" to complete (and we log a message on the server to reflect that).
  • Catch TaskCancelledException on the server and "swallow" the exception when !JSRuntime.IsInitialized.
    • I chose not to do it this way because it's potentially problematic and I'm not 100% confident on the impact on other scenarios (like the circuit is disconnected but not disposed).

@javiercn javiercn requested a review from a team as a code owner January 10, 2024 16:33
@ghost ghost added the area-blazor Includes: Blazor, Razor Components label Jan 10, 2024
Copy link
Member

@MackinnonBuck MackinnonBuck left a comment

Choose a reason for hiding this comment

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

Just a small question, but I think this looks good regardless of its answer 🙂

}
// If we are navigating to an external URI, defer setting the URL so that we can
// complete the current navigation operation if the request comes from .NET.
setTimeout(() => {
Copy link
Member

Choose a reason for hiding this comment

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

Is one downside to this approach (compared to the other one you proposed) that we don't actually wait for the "end .NET->JS interop" message to be sent across the wire before tearing down the page? i.e., there's still a possibility that the bug appears, especially when the user has an unreliable connection?

Copy link
Member Author

Choose a reason for hiding this comment

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

We don't want to swallow the exception when the circuit just gets disconnected, do we?

Copy link
Member Author

Choose a reason for hiding this comment

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

That's my reasoning for it. It's better to support the call finishing than to catch the exception on the server at the risk of catching exceptions that we don't want to catch. Specially since the outcome of navigation can't be observed by the user.

Copy link
Member Author

Choose a reason for hiding this comment

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

Turns out that I still found cases where this can happen, even with the JS bits. So I switched to catching on the server with a new strategy
image

The browser used matters here. Chrome/Edge complete the navigation, but firefox doesn't.

@javiercn javiercn merged commit d5108c9 into main Jan 11, 2024
@javiercn javiercn deleted the javiercn/issue-45267 branch January 11, 2024 08:00
@ghost ghost added this to the 9.0-preview1 milestone Jan 11, 2024
@javiercn
Copy link
Member Author

/backport to release/8.0

Copy link
Contributor

Started backporting to release/8.0: https://github.com/dotnet/aspnetcore/actions/runs/7485830357

mkArtakMSFT pushed a commit that referenced this pull request Jan 16, 2024
…nute later (#53297)

Backport of #53271 to release/8.0

/cc @javiercn

# [Blazor] each navigation to external logs 2 errors a minute later

Capture an exception and log a message when navigation fails because the session has ended.

## Description

- The user clicks the link to the target URL.
- That link is intercepted in the JavaScript.
- .NET is called to determine if navigation to the URL needs to be prevented.
- It is determined that there is no need to prevent navigation and "navigateTo" is called via JS interop in NavigationManager.ts.
- The URL is determined to be external by "navigateTo" and the location is set to the new URL.
- The unload event in the browser is automatically triggered, which in turn triggers the call to _disconnect.
- As a result, the promise to "navigateTo" never completes (the page gets unloaded before that) and the associated task in .NET ends up getting cancelled with a timeout.

Fixes #45267

## Customer Impact

Customers see a large number of errors in their logs when their sites contain links to external sites, which in turn can trigger alerts in their incident monitoring systems.

## Regression?

- [ ] Yes
- [X] No

## Risk

- [ ] High
- [ ] Medium
- [X] Low

The scenario in which the issue happens is well defined and the fix is simple.

## Verification

- [X] Manual (required)
- [ ] Automated

![image](https://github.com/dotnet/aspnetcore/assets/6995051/a61a9898-771a-414c-a83c-7836bf88697c)

## Packaging changes reviewed?

- [ ] Yes
- [ ] No
- [X] N/A

----

## When servicing release/2.1

- [ ] Make necessary changes in eng/PatchConfig.props

---------

Co-authored-by: jacalvar <[email protected]>
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.

2 participants