Most Effective Methods for SignalR User Connections Management


Most Effective Methods for SignalR User Connections Management

The Importance of SignalR and Connection Management

For those developing real-time web applications, management of SignalR user connections is a key issue. Especially in systems such as instant notifications, chat or games where multiple users interact simultaneously, it is necessary for each user's connection to be secure, stable, and manageable. Managing users' connections correctly with SignalR ensures that messages reach the correct user in a scalable and consistent way.

How Is User Connections Management Done?

Creating a User and Connection ID Relationship

In SignalR, a user can connect to the system from multiple devices or browser windows. Therefore, a user often has more than one connection ID. In the example below, it is shown how user connection IDs are kept in a dictionary:


private static readonly Dictionary<string, HashSet<string>> _userConnections = new();

public override Task OnConnectedAsync()
{
    string userName = Context.User.Identity.Name;
    string connectionId = Context.ConnectionId;

    lock(_userConnections)
    {
        if (!_userConnections.ContainsKey(userName))
        {
            _userConnections[userName] = new HashSet<string>();
        }
        _userConnections[userName].Add(connectionId);
    }
    return base.OnConnectedAsync();
}

Managing When Connection Is Disconnected

When the user connection is lost or the user leaves the system, the relevant connection ID should be removed from the connection list.


public override Task OnDisconnectedAsync(Exception exception)
{
    string userName = Context.User.Identity.Name;
    string connectionId = Context.ConnectionId;

    lock(_userConnections)
    {
        if (_userConnections.ContainsKey(userName))
        {
            _userConnections[userName].Remove(connectionId);
            if (_userConnections[userName].Count == 0)
            {
                _userConnections.Remove(userName);
            }
        }
    }
    return base.OnDisconnectedAsync(exception);
}

Sending a Message to a Specific User

Within the scope of SignalR user connections management, the following approach can be used to send a private message to a user:


public Task SendMessageToUser(string userName, string message)
{
    if(_userConnections.ContainsKey(userName))
    {
        foreach(var connectionId in _userConnections[userName])
        {
            Clients.Client(connectionId).SendAsync("ReceiveMessage", message);
        }
    }
    return Task.CompletedTask;
}

Conclusion and Best Practices

When it comes to managing SignalR user connections, it is very important to update connections synchronously and to synchronize them in memory or in a distributed system. In large-scale applications, this management should be done with a distributed cache (e.g. Redis) instead of in-memory. By successfully implementing SignalR user connections management, you can provide high performance, security, and flexibility in your application.