Aspnetcore: Circuit not disconnected properly on all browsers when navigating away from page

Created on 14 Feb 2020  路  50Comments  路  Source: dotnet/aspnetcore

Describe the bug

I have a Blazor Server project running on ASP.NET Core 3.1 with a problem that is exhibited both when:

  1. I debug with VS 2019 (16.4 and 16.5) using IIS, and
  2. Deployed to an Azure Web App running Linux and within a Docker container.

The issue is that certain actions that I take that call NavigationManager.NavigateTo("/my-page"); causes the signalr connection between the Blazor app and my browser to drop for a couple of seconds and then re-establish itself to the state as it was before I pressed the relevant button. The next time I try everything works as intended.

This has different behaviour depending upon my browser:

  1. Chromium Edge is the worst. When the lost connection happens, it resumes as if the relevant event had never happened.
  2. Google Chrome never seems to experience the lost connection.
  3. Firefox is a halfway house. It has the problem a little less frequently than Chromium Edge, and when it does, after the signalr connection resumes the app has recognised the event and changed its state accordingly.

There is no output to be seen in the VS Debug output window. No information, warnings or errors. Also no indication that the router wants to navigate to /my-page.

The NavigationManager call is in a one-line function in the @code block of a .razor file. When I use the debugger, I step over the call successfully but then once the function I'm debugging exits, the signalr connnection is lost.

To Reproduce

I don't know how to reproduce this. It's in an app I'm writing for commercial purposes. I would be happy to show a Microsoft engineer what's going on.

Further technical details

  • ASP.NET Core version: 3.1
  • Include the output of dotnet --info see below
  • The IDE (VS / VS Code/ VS4Mac) you're running on, and it's version 16.4 and 16.5
PM> dotnet --info
.NET Core SDK (reflecting any global.json):
 Version:   3.1.200-preview-014883
 Commit:    4e2a0ee959

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.19041
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\3.1.200-preview-014883\

Host (useful for support):
  Version: 3.1.1
  Commit:  a1388f194c

.NET Core SDKs installed:
  2.1.602 [C:\Program Files\dotnet\sdk]
  2.1.604 [C:\Program Files\dotnet\sdk]
  2.1.700 [C:\Program Files\dotnet\sdk]
  2.1.801 [C:\Program Files\dotnet\sdk]
  3.0.100-preview7-012821 [C:\Program Files\dotnet\sdk]
  3.0.100-preview8-013656 [C:\Program Files\dotnet\sdk]
  3.0.100-preview9-014004 [C:\Program Files\dotnet\sdk]
  3.1.101 [C:\Program Files\dotnet\sdk]
  3.1.200-preview-014883 [C:\Program Files\dotnet\sdk]

.NET Core runtimes installed:
  Microsoft.AspNetCore.All 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.11 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.14 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.15 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.11 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.14 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.15 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.0.0-preview8.19405.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.11 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.14 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.15 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.0.0-preview8-28405-07 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 3.0.0-preview8-28405-07 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.1 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

To install additional .NET Core runtimes or SDKs:
  https://aka.ms/dotnet-download
Done Servicing-consider area-blazor bug

Most helpful comment

Closing this as the servicing PR has been merged and it will ship in 3.1.8.

All 50 comments

@simonziegler thanks for contacting us.

We will look into this issue and get back to you.

Thanks all and best of luck. Please let me know if you need to see this happening. As an aside, the Brave browser works as well as Chrome.

IMPORTANT UPDATE

My PC updated for windows insider last night (KB4539080) and Edge Chromium no longer crashes! Firefox v 72.0.2 and 73.0 do though - and that's a common browser.

Hi, I'm wondering if you had a chance to look at this? I'm a bit concerned about what happens when somebody decides to use Firefox with my app.

Thanks!

Hi, is this still on your radar? I think the issue seems less problematic now. I tested a Blazor server app of mine built with your latest release and using a fresh firefox installation and didn't suffer any undue issue. I do notice however that when I click a button that redirects to Azure B2C for login there is a brief flash of SignalR's disconnected state, however subsequent functionality is correct. Previously I would have got this flash of disconnection and then the window would behave as if I hadn't pressed the button.

So to conclude, things seem much improved but there's still a little bit of a residual issue.

@simonziegler we didn't have a chance to look into this issue yet since we are busy with other work. I'm not sure about the "disconected" flash that you mention, but when redirecting to an external page it is expected for the Blazor session to end and for a new session to be started after the user has authenticated. I'm not sure if that is what you are referring to or if there's anything else.

Hi Javier - I didn't see your message earlier - sorry. The problem seems to be subsiding as browser updates are being released, however originally just calling NavigateTo either within the app (controlled by Blazor router) or outside would cause the issue. I've just been wondering if there is a problem in the Blazor SignalR js causing this. I have decided not to use Firefox at all the last 3 months because of the risk of this issue cropping up while my focus is core app development right now.

I think until you get an opportunity to investigate there isn't an awful lot more to say. I am considering a complete refactor of my app once Blazor 3.2 is released in final form and will look to see whether this issue is apparent at that time. I guess my final point is to reiterate that it was concerning that Blazor Server behaved differently depending upon the browser you used, with the issue appearing to arise from the Blazor js.

I'll update once I've refactored in a few weeks but obviously would be interested to hear if the ASP.NET team get to investigate this.

Good day!
Faced a similar problem when placing the application on a real hosting.
The application constantly loses connection with the server, reporting an error "websocket closed with status code 1006".
Already broke his head in search of a cause.
At the same time, the application works without problems on the local computer.
It got to the point that I decided to simulate everything from scratch.
It turned out that any blazor application loses its connection in the conditions of limitations of the iis server dedicated vitrual memory.
I created the start-up template of the blazor-server side application, didn鈥檛 add anything, published it on the local iis, in the iis settings I set 20Gb for virtual memory and 2Gb for allocated memory and I get websocket disconnections when the Click button on the Count page is clicked actively.
Friends, what's the problem?

I created the start-up template of the blazor-server side application, didn鈥檛 add anything, published it on the local iis, in the iis settings I set 20Gb for virtual memory and 2Gb for allocated memory and I get websocket disconnections when the Click button on the Count page is clicked actively.
Friends, what's the problem?

I see that you opened another issue with this problem. Please use the other issue for your particular scenario so we can keep this bug report focused on the original problem.

I don't know how to reproduce this. It's in an app I'm writing for commercial purposes. I would be happy to show a Microsoft engineer what's going on.

@simonziegler Bummer that you are unable to produce a repro. Does this issue not occur in a minimal reproduction with page navigation logic? The fact that the behavior is inconsistent and evolving across different browsers is strange. Considering that this issue arises as part of the a larger application, the navigation issue might be a red herring to a real problem underneath the hood.

If you're able to reproduce a minimal repro or provide access to a private repo with screenshots/debug messages that would be helpful.

In addition to that, some questions that would be helpful to answer:

  • What version of Firefox is still experiencing connection drops during navigation?
  • Are there certain things you have to do to reproduce this issue (e.g. have the application running for a while, click on a certain set of components, etc.)?

Hey @captainsafia, sorry I didn't notice your comments here.

I didn't get a chance to look at this for some months now having first reported the issue back in February with little response until this month. Given that it went quiet back then I wasn't in a position to put much effort into reproducing the issue.

I will give a little time to see if I can create a stand alone issue for you, however I rather think that the opportunity to find this problem may have been and gone with intervening ASP.NET development. I'll let you know.

No problem, @simonziegler! I'll close this issue for now but feel free to re-open with a repro if you find the time to do that on the latest bits.

Oh, does that mean that the enquiry is dead unless I work on it myself? Did you folks manage to investigate this at any point? Tx

Actually my commercial app exhibits this behaviour still. I would rather not post the url in public here for now. Can we message directly to discuss?

The crux of the matter is that the lost connect happens when my app navigates externally to Azure B2C either to log in or log out.

I would be more than happy to demonstrate this to a member of your team on a Teams or WhatsApp call. I am concerned that this is a general issue with Blazor Server that has gone unnoticed. I will also be refactoring my app in the coming month or so but will probably not know whether the issue persists after the refactor until July.

Oh, does that mean that the enquiry is dead unless I work on it myself? Did you folks manage to investigate this at any point? Tx

To investigate, we'll need a minimal reproduction that showcases the issue. From previous messages, it appears that the behavior is rather inconsistent across different browsers.

If you can provide a minimal repro and the browsers that it currently fails on, that would help start the investigation.

The crux of the matter is that the lost connect happens when my app navigates externally to Azure B2C either to log in or log out.

Can you clarify what you mean by "lost connect". External navigation are expected to terminate a session and restart a new one.

Hi @captainsafia, this repo shows the issue: https://github.com/simonziegler/SSB-signalr-issue.

  • Clarifying what I mean by "lost connection", please reference the original issue as logged on 14 Feb, plus and update on April 8 above. However when you navigate by pressing the button on the test repo's index page you will see that the page whites out momentarily before arriving at google.com. The attached picture shows the console logging an exception.
  • Browser: Firefox as described above, plus originally in February the then current version of Edge Chromium. Please refer above for a detailed explanation of the issue as it stood 3 months ago.

Can I please suggest that you also review this with prior versions of ASP.NET again as referenced above because the issue was more pronounced at that stage. I suspect that this will help you finding the problem.

Kind regards, Simon

image

I think @simonziegler 's problem would go away if the ReconnectionHandler was disposed just before a navigate away from the page.

Hi, @captainsafia given that Blazor 3.2 has just been released, should I assume that fixing this bug is firmly on the back burner? If so I have to say that I am actually a bit disappointed, because I'm about to launch a Blazor Server app into the wild with clients, some of whom I know use Firefox. After having reported this first three months ago, it would be really nice to have a sense at to your ETA to review.

Thank you, Simon

@simonziegler Blazor 3.2.0 relates only to WebAssembly, there was no 3.2.0 associated server release.

Got it. Unfortunately my users have been seeing this for a few months already. I hear that you are looking into the issue which is good, however it would be great to be kept informed of progress and likely time to resolution.

Thanks for providing the repro, @simonziegler! Having it is a helpful way to speed up investigations for these kinds of things.

It looks like this issue is a dupe of It looks like this issue is a dupe of https://github.com/dotnet/aspnetcore/issues/16739. I suspect that this is related to the way each browser handles pushing/popping pages out of the navigation history. Making the ReconnectionHandler more resilient to these types of things might be an option here.

I hear that you are looking into the issue which is good, however it would be great to be kept informed of progress and likely time to resolution.

I'm marking this as a bug for now and putting it into our sprint planning queue. The other issue was backlogged but it looks like this bug has been around for quite a bit. The issue milestone will be updated with the expected release date once it is prioritized.

With regard to work arounds, it appears that this issue generally affects any type of page navigation on Firefox (location.href, location.assign, location.replace), which would make sense if it had more to do with how the way the browser's navigation handling and the lifecycle of the SignalR connection intersect than specifically with the NavigateTo call.

As a workaround (if applicable for your app), you can try triggering the route navigation through an anchor reference with target="_blank". To trigger navigation programmatically, you can hide the link element and programmatically trigger click on it as needed.

Thanks @captainsafia, much appreciated. I'll look at this in the coming days, however I hit this when I need to navigate externally to log in with Azure B2C. So the bug hits just at the moment my users first try to do something with the app. This will be common to anybody using B2C or other similar authentication providers.

@simonziegler I'm using Blazor Server-Size with Azure B2C. Are you not using a Challange() along with the AddAzureADB2C() extension to redirect your users to login?

you should have something in your startup that looks like this

services.AddAuthentication(AzureADB2CDefaults.AuthenticationScheme).AddAzureADB2C(options => configuration.Bind("AzureADB2C", options));

Let me know if you need more detail on my implantation of AzureB2C with Blazor?

Challenge only works in the context of an HTTP request, not in Blazor, since there is no http request/response available.

The way to achieve something similar in Blazor is to create an endpoint that does the challenge and call NavigationManager.NavigateTo("endpoint") to redirect the user there and cause the challenge to start.

Thanks @robdavey555 and @javiercn. Javier, I use NavigationManager.NavigateTo("AzureADB2C/Account/SignIn", true); - is that they way you would go about this? Tx

@simonziegler something like that would work I think.

@simonziegler Turns out the issue was actually the other way around.

We were properly disconnecting the circuit on Firefox, but not any other browser. I've pushed to make sure that we are actually disconnecting the circuit on all browsers.

The inconsistencies that you were seeing in different versions of Chrome were a result of Chrome changing their page lifecycle APIs so that unloads weren't always emitted.

As for the modal that you are seeing, you can try adjusting the retryIntervalMilliseconds in reconnectionSettings to a smaller interval to see if that resolves the issue.

Cross-browser consistency is good news, but how are we now meant to do external redirects or downloads without seeing the "disconnected" message in all browsers? That's the problem described in https://github.com/dotnet/aspnetcore/issues/16739, which was a dupe of this issue.

Hi @captainsafia thanks for getting back to me. I think your resolution misses the point however. The result is a poor user experience out of the box for anybody, for instance using external auth such as Microsoft Azure AD or B2C. Microsoft products.

As @gulbanana notes this flash of ugliness just should not be there in the first place. I can鈥檛 say that I鈥檓 satisfied with the notion that as an app developer I need to fiddle with some settings to avoid what strikes me as a fundamentally wrong visual behaviour in Blazor Server.

Sorry for being a bit blunt here but this needs to be better. I would like to see this issue reopened and dealt with properly.

@danroth27 may I draw your attention to this again please?

Simon

PS, I have not had the opportunity to test this yet, but I doubt I鈥檓 the right person to do this anyway - I don鈥檛 understand the technicalities of these connections, but I do understand what looks bad for a user, and that my users will blame me.

I don't do server side at all, but I wouldn't like my users to see something that indicates something is broken every time they need to sign in.

@captainsafia Perhaps there is something in the JS you can change so that doesn't appear if the circuit was deliberately disconnected?

@captainsafia It is possible to hide the ReconnectionDisplay in user code like this - but it seems pretty bad to make every developer repeat this code - could you do something similar to nullify the ReconnectionHandler just before you close the connection - as a deliberate close does not require a reconnection?

<script src="_framework\blazor.server.js"></script>
<script>
  window.addEventListener('beforeunload', function () {
    Blazor.defaultReconnectionHandler._reconnectionDisplay = { };
  });
</script>

I'm a bit confused, this issue was about a problem with a behavior that we had since 3.0 (graceful disconnections) due to a change in chromium behavior. I don't see how this has anything to do with what we are talking about here.

It would help us if instead of adding comments to this closed issue (which we are likely to miss) you open a separate issue explaining the problem you are facing in detail so that we can better determine what the issue if any is and decide a course of action.

@javiercn It is directly related to the original issue (the description has been changed to match what was discovered) - one could argue that this issue was not the correct place to deal with connections not always being closed.

The author of this issue refined the problem here and here where they also provided a repro which demonstrates the problem.

The flash of "reconnection attempt" when you navigate away from a Blazor Server app was the issue and it remains after this fix, but now happens on all browsers, so the fix applied was not really addressing the issue - although very useful and much appreciated for other problems, it actually makes this problem more prevalent.

That's why the messages are still being added here - the original problem remains.

@javiercn I think the issue was closed prematurely. At the most, it should probably have been set to awaiting feedback so the bot could close it automatically after X days if no repro was produced.

However, @captainsafia has managed to reproduce the problem - so this should surely be reopened now as per the statement that it was only being closed until there is a repro?

Please re-open this issue, the current behavior is confusing for end users.

As for the modal that you are seeing, you can try adjusting the retryIntervalMilliseconds in reconnectionSettings to a smaller interval to see if that resolves the issue.

@simonziegler Did you try the recommendation made above?

The flash of "reconnection attempt" when you navigate away from a Blazor Server app was the issue and it remains after this fix, but now happens on all browsers, so the fix applied was not really addressing the issue - although very useful and much appreciated for other problems, it actually makes this problem more prevalent.

From the validations I've done, the reconnect flash is still only an issue on Firefox. On Chrome/Safari/Edge, this doesn't reproduce under the old and new model. This is likely a result of the way page lifecycle events are handled on each browser.

Because the behavior isn't reproable across all browsers, I hesitate to include something in the framework to address this. You can control the reconnection behavior using some pre-existing options that we expose in the our API, including:

  • Adding a custom reconnection handler
  • Modifying the retry interval for reconnections
  • Changing the type of dialog that is shown to something more discrete

The options are documented here.

Hi @captainsafia, no I unfortunately have not had the opportunity to try this. Part of the reason is that I don't know Javascript and have no idea where and how to apply your referenced code. My lack of JS why I am so excited to have Blazor to hand!

However I agree with @mrpmorris, @SQL-MisterMagoo and @pm64 that this is an issue that (i) is not resolved properly and (ii) should not have been closed. I did put a lot of effort into describing this for your team multiple times, along with finally managing to prepare the repo to demonstrate what is a hard-to-identify issue. That's where my skillset for helping out trails off.

Respectfully I have to suggest that Blazor should "just work" in all major browsers of which Firefox is obviously one. I found the issue originally because I have the discipline to check that my app works across all browsers that I have to hand. In this thread we all know that the flash isn't an actual problem per se - no data will get corrupted. However but users will not see it that way - their interpretation will be that "something is broken" because of the flash, and that is guaranteed. Furthermore, there will be many devs who, like me, may have a whole bunch of skills to hand but not the relevant skill to apply the javascript that you reference. That's even if they find it: I doubt more than a handful of people have read this thread.

So please, consider working further on Blazor to remove the problem at source.

Lastly @javiercn, I have to agree with @SQL-MisterMagoo that this is the same issue that I originally reported, notwithstanding that we all managed to focus in on what was going on, and your team consequently chose to change the title for greater accuracy.

Simon

Hi @captainsafia, no I unfortunately have not had the opportunity to try this. Part of the reason is that I don't know Javascript and have no idea where and how to apply your referenced code. My lack of JS why I am so excited to have Blazor to hand!

This documentation page has more information. I've opened https://github.com/dotnet/AspNetCore.Docs/issues/19153 to tackle adding more code samples on how to do this to benefit developers.

Respectfully I have to suggest that Blazor should "just work" in all major browsers of which Firefox is obviously one.

With regard to the "disconnect when user navigates away" behavior, Blazor does the correct thing across all browsers now.

I understand your reservations about the flash being alarming to users. However, there's not much we can do within the framework (that wouldn't be a total hack) to remedy this issue as it only occurs on certain versions of Firefox.

We do have an existing set of APIs that can be used to modify the reconnection experience, which is what I'm recommending here.

@captainsafia The change suggested by @SQL-MisterMagoo seems reasonable, does that work? https://github.com/dotnet/aspnetcore/issues/19050#issuecomment-653953887

@simonziegler @mrpmorris @SQL-MisterMagoo @pm64 I'm sorry for the confusion here, sometimes as issues evolve we loose context on them and this seems to have been the case.

@captainsafia I think the concern here is that the experience is not great. I'm going to reopen the issue and put it up for triage again to see what we can do about it here.

Thanks @javiercn - you have a million and one things to track, so I get it!

@javiercn I'm happy to look at this later today

I will locate the relevant code and post a suggested fix here first.

@SQL-MisterMagoo sounds great. If you get stuck let me know and I can help

I don't think there is actually going to be a better "fix" for the "unwanted flash of UI" when you navigate away (e.g. for auth) than @SteveSandersonMS suggested longer delay before showing the UI - through a bit of CSS.

The problem is Browsers and the way they behave.

The "onbeforeunload" event allows you to stop the unload and prompt the user to choose whether to stay on the page or not.
( it doesn't always fire though - especially in Firefox : because Browsers )

There is no way to run anything after the user makes their choice - except if they decide to leave the page, when the "onunload" event _should_ fire.
Unfortunately, the "onunload" event fires after the page UI has hidden - which is too late to prevent the "reconnecting" display.
( it doesn't always fire though : because Browsers )

You can't disable the Reconnection UI in "onbeforeunload" because they might choose to stay - and there is nothing that runs after that choice. (And it is unreliable)
_Ok, you could disable it, and schedule it to re-enable x milliseconds later, but that is terrible._

So, in the end - probably the best - most reliable option is just to delay the UI popup - and in 99% of the cases that should be enough - sadly.

Unless anyone has a better idea... I think Steve was right.

@SQL-MisterMagoo thanks for the thorough summary. It helps inform the decision here. I think that you and @SteveSandersonMS are right here. Given that we can't prevent onbeforeunload from being cancelled and that onunload is too late, the best option might likely be to just delay the dialog as Steve suggested.

Thanks all for the attention here. I wasn't following things yesterday, but Magoo did tell me today that a "fix" seemed unlikely. When you talk about delaying the dialog, is that the one with the white scrim that end up looking odd? If so, it seems like a good resolution. Is that delay something that I would need to do, or would it be baked into Blazor? I'd far prefer the latter.

Thanks!

@simonziegler The delay would involve delaying when the reconnection modal gets displayed. The change would need to be made somewhere here.

@captainsafia can you please prepare a patch PR for this? Thanks!

Can do! Note: we'll probably want to wait and prepare a patch with both my fix and #24137.

Closing this as the servicing PR has been merged and it will ship in 3.1.8.

Was this page helpful?
0 / 5 - 0 ratings