aspnetcore: (blazor) Failed to reconnect to the server

Describe the bug

When running a server-side blazor project, after some time, the SignalR connection is lost and the following overlay is displayed (“Failed to reconnect to the server”): image However, clicking the retry button does not work - the overlay is still present although the following is logged in the dev tools:

Information: Normalizing '_blazor' to 'https://localhost:44369/<APP-NAME>/_blazor'.
Information: WebSocket connected to wss://localhost:44369/<APP-NAME>/_blazor?id=eKQVfTXvMHxKidi6ivsLag.

Probably https://github.com/aspnet/AspNetCore/issues/8710 will fix this, but is there a workaround for preview 5? Also note that there times which an overlay with “Attempting to reconnect to the server” is displayed and this actually reconnects successfully. However, if the app gets to a state in which the “Failed to reconnect to the server” message is displayed, it will not reconnect from the “Retry” button.

To Reproduce

  1. Run the sample project from the default server-side blazor template
  2. Leave the browser tab without any interaction for some time until the overlay is displayed (this mimics the behavior by the end user). The alternative is to disconnect manually in order to get the notification for the connection loss. Note that calling:
window['Blazor']._internal.forceCloseConnection()

results in the "“Attempting to reconnect to the server”, which succeeds though.

Expected behavior

The retry button works.

Additional context

dotnet --info

.NET Core SDK (reflecting any global.json):
 Version:   3.0.100-preview5-011568
 Commit:    b487ff10aa

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.17134
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\3.0.100-preview5-011568\

Host (useful for support):
  Version: 3.0.0-preview5-27626-15
  Commit:  61f30f5a23

.NET Core SDKs installed:
  1.1.13 [C:\Program Files\dotnet\sdk]
  2.1.503 [C:\Program Files\dotnet\sdk]
  2.1.600-preview-009472 [C:\Program Files\dotnet\sdk]
  2.1.602 [C:\Program Files\dotnet\sdk]
  2.1.700-preview-009597 [C:\Program Files\dotnet\sdk]
  2.1.700-preview-009618 [C:\Program Files\dotnet\sdk]
  2.2.103 [C:\Program Files\dotnet\sdk]
  3.0.100-preview5-011568 [C:\Program Files\dotnet\sdk]

.NET Core runtimes installed:
  Microsoft.AspNetCore.All 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.2.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.2.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.2.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.2.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.2.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.2.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.0.0-preview5-19227-01 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 1.0.15 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 1.1.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.2.1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.2.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.2.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.0.0-preview-27324-5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.0.0-preview5-27626-15 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]

  Microsoft.WindowsDesktop.App 3.0.0-preview5-27626-15 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

To install additional .NET Core runtimes or SDKs:
  https://aka.ms/dotnet-download

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 21 (8 by maintainers)

Most upvoted comments

Hi @edgolub,

This issue is closed because there is no known Blazor work tracked here. Blazor Server apps will go into a “not connected” state if the connection is lost for any reason, including the network connection being dropped or the server being restarted. If the server is restarted then there is no way for the app to reconnect back to the same state because the server state is gone. The only way forward is to refresh the browser. Blazor won’t refresh the browser automatically, but you can setup your app to do so. For example you could add the following script to your _Host.cshtml file:

<script>
    // Wait until a 'reload' button appears
    new MutationObserver((mutations, observer) => {
        if (document.querySelector('#components-reconnect-modal h5 a')) {
            // Now every 10 seconds, see if the server appears to be back, and if so, reload
            async function attemptReload() {
                await fetch(''); // Check the server really is back
                location.reload();
            }
            observer.disconnect();
            attemptReload();
            setInterval(attemptReload, 10000);
        }
    }).observe(document.body, { childList: true, subtree: true });
</script>

This uses the JS DOM mutation observer API to detect when we’re offering a “reload” button, and automatically does a reload in that case. It has to be careful not to reload before the server actually comes back, otherwise the kiosk would get stuck displaying a “network error” type screen. There is still the potential that the refresh will fail, and if it does then there’s no way to retry without user intervention.

@Stamo-Gochev The Retry button specifically tries to reconnect back to the state (“circuit”) for the current UI session. Blazor doesn’t provide an out of the box mechanism to persist and rehydrate this state, so after a server restart the state will be gone and no amount of retrying to connect to that state will help. Instead the user will need to refresh the browser.

We have an issue open to make this clearer in the default UI (https://github.com/aspnet/AspNetCore/issues/10496). You can also customize this UI yourself: https://docs.microsoft.com/en-us/aspnet/core/blazor/hosting-models#reconnection-to-the-same-server.

Lastly, you should be able to do work in your app and components to support persisting the required state so that the app can survive a server restart. For example, the app could persist the circuit state into a memory cache, and the components could leverage local storage in the browser. We don’t have great docs or samples on how to do this yet, but it’s something we expect to provide before we ship.

Hi @edgolub,

This issue is closed because there is no known Blazor work tracked here. Blazor Server apps will go into a “not connected” state if the connection is lost for any reason, including the network connection being dropped or the server being restarted. If the server is restarted then there is no way for the app to reconnect back to the same state because the server state is gone. The only way forward is to refresh the browser. Blazor won’t refresh the browser automatically, but you can setup your app to do so. For example you could add the following script to your _Host.cshtml file:

<script>
    // Wait until a 'reload' button appears
    new MutationObserver((mutations, observer) => {
        if (document.querySelector('#components-reconnect-modal h5 a')) {
            // Now every 10 seconds, see if the server appears to be back, and if so, reload
            async function attemptReload() {
                await fetch(''); // Check the server really is back
                location.reload();
            }
            observer.disconnect();
            attemptReload();
            setInterval(attemptReload, 10000);
        }
    }).observe(document.body, { childList: true, subtree: true });
</script>

This uses the JS DOM mutation observer API to detect when we’re offering a “reload” button, and automatically does a reload in that case. It has to be careful not to reload before the server actually comes back, otherwise the kiosk would get stuck displaying a “network error” type screen. There is still the potential that the refresh will fail, and if it does then there’s no way to retry without user intervention.

If you sure you want to reload every change, you can instant reload base on @danroth27 answer:

<style>
   #components-reconnect-modal {
       display: none !important;
   }
</style>
<script>
   new MutationObserver(() => document.querySelector('#components-reconnect-modal') && location.reload())
      .observe(document.body, { childList: true });
</script>

put it right before:

</body>

@rolfik Thanks for the feedback! We are considering this as part of https://github.com/aspnet/AspNetCore/issues/9256