In this article, we are going to learn how to implement Automatic Reconnect in SignalR. We have already discussed how to implement a real-time chart using ASP.NET Core SignalR on the server-side and Angular on the client-side in our .NET Core with SignalR and Angular – Real-Time charts article.
Furthermore, we have learned how to send messages to a specific client in the SignalR- Send Client-Specific messages article. However, while implementing a SignalR solution, we often come across an issue of connection getting lost intermittently. Once the SignalR disconnects, we lose the real-time behavior of our application. Then, we need to establish the connection again for the application to function properly. SignalR does not reconnect automatically after a disconnection.
Previously, we had to implement custom mechanisms for the automatic reconnection of SignalR. But that is not a straightforward task. We need to take many things into account while implementing such a solution. The good news is that, in ASP.NET Core 3.0, SignalR introduced the automatic reconnect feature which will help us to solve this problem. In this article, we are going to look at that feature and how to implement that in our SignalR app.
Let’s move on.
The SignalR Disconnection Problem
SignalR uses WebSockets under the hood which enables two-way communication between the browser and the server. That means it will use WebSockets whenever available, and gracefully fall back to other techniques when a WebSocket connection cannot be established. Generally, WebSocket connections get disconnected automatically after a while.
Let’s take a look at the SignalR app that we created in the previous article:
We can see that once we run the app and keep it idle, the SignalR disconnects after some time. Once it disconnects, we can see an error message in the browser console.
On losing the connection, SignalR does not automatically attempt to reconnect. So we’ll lose the real-time behavior of our app. Then, the only way to re-establish the connection is by refreshing the page. This presents an unpleasant experience for the users.
SignalR Automatic Reconnect Option
As we discussed in the introduction, SignalR has added the support for automatic reconnect in ASP.NET Core 3.0. For this to work, the SignalR Javascript Client version should be 3.0.0 or above. We can configure the Javascript client for SignalR to automatically reconnect using the withAutomaticReconnect()
method on HubConnectionBuilder
. However, it is not the default behavior and we need to call this method explicitly.
We can customize the behavior of withAutomaticReconnect()
by providing an argument. It accepts an array of millisecond values as an argument. This denotes the time the client waits before it attempts each reconnection. If we do not pass any parameters, withAutomaticReconnect()
configures the client to wait for 0, 2, 10, and 30 seconds respectively before attempting each reconnection. Finally, it will stop after four failed attempts.
This is equivalent to passing [0, 2000, 10000, 30000, null]
as the argument. We can customize the number of retry attempts and delays by passing the desired values as an array in the argument.
Implementing SignalR Automatic Reconnect
We have looked at the automatic reconnect option available in SignalR. Now, without any further ado, let’s implement the same in our project. We are going to modify the project that we created in the linked article.
So, we are going to modify the startConnection()
method of the SignalRService
class to enable automatic reconnect:
this.hubConnection = new signalR.HubConnectionBuilder() .withUrl('https://localhost:5001/chart') .withAutomaticReconnect() .configureLogging(signalR.LogLevel.Information) .build();
Here, we call the withAutomaticReconnect()
method without any parameters. So this will wait for 0, 2, 10, and 30 seconds respectively before attempting each reconnection. Finally, it will stop after four failed attempts. Of course, we can customize this by passing a set of custom values as the argument.
Furthermore, we have made a call to the configureLogging()
method by passing the LogLevel
argument as LogLevel.Information
. This will configure console logging for the HubConnection
instance. The LogLevel.Information
argument will enable logging of all events of severity Information or more into the console. We’ve done this so that we can get a log of all events happening in the background.
That’s it. We have configured our SignalR app for automatic reconnection.
Testing The SignalR Automatic Reconnect Feature
Now, let’s test the automatic reconnection behavior of our SignalR app.
For that, we have to run both our server and client app. We can see that the Angular app displays the chart. The server-side application keeps on updating the chart values at regular intervals:
Now, we are going to simulate a WebSocket disconnection scenario. For that, we just need to stop our server application for a few seconds and start it again. We can see that the real-time updates on our Angular app stop for some time when the server application is stopped. But, once our server application is back online, the WebSocket connection will be automatically established again. Cool!
Let’s observe the console to understand the events happening in the background:
Here, we can see that initially the WebSocket connection is established and our client app gets real-time data from the server application.
Then, once we stop the server application, the WebSocket gets disconnected. It immediately makes the first attempt to reconnect, but fails.
After that, it attempts another reconnect in 2 seconds, which fails as well. We can see that the next attempt is made after 10 seconds and by that time, our server application is back online and then the connection becomes successful.
Requesting Real Time Data After Reconnection
At this point, we have enabled our client app to automatically reconnect to our server app using SignalR, but we don’t get real-time data now. The connection is back again, as we can see in our presentation, but the chart is frozen since we don’t get any new data from the server.
To enable the data flow once the connection is alive again, we have to use the onreconnected
function that we can call with our hubConnection
property inside the Signalr service:
this.hubConnection.onreconnected(() => { this.http.get('https://localhost:5001/api/chart') .subscribe(res => { console.log(res); }) })
This time, as soon as our app is reconnected, we will receive the data from the server.
Conclusion
In this article we looked at the following topics:
- The disconnection problem of SignalR
- Automatic Reconnect feature of SignalR
- How to implement the automatic reconnection in our SignalR app