C
C#2mo ago
WhiteCharun

✅ [SignalR] How to effeciently keep track of ConnectionIds.

I'm currently trying to build a little chat room where users can send messages. The thing I can't get over my head is if this is the best way to keep track of connection Ids. Since there could be multiple tabs open i want to send the message to all the tabs so I need to make a persistant layer where I associate an id and username with the connection Id of signalR. On the client side as soon as i connect to the websocket server i call the RegisterUser
public class ChatHub : Hub
{
private readonly IConnectionManager _connectionManager;

public ChatHub(IConnectionManager connectionManager)
{
_connectionManager = connectionManager;
}

public async Task SendMessage(UserChatHubDTO user, string message)
{

await Clients.All.SendAsync("ReceiveMessage", user, message);

}
public void RegisterUser(UserChatHubDTO user)
{
_connectionManager.AddConnection(Context.ConnectionId, user);
}

public override async Task OnDisconnectedAsync(Exception exception)
{
_connectionManager.RemoveConnection(Context.ConnectionId);
await base.OnDisconnectedAsync(exception);
}
}
public class ChatHub : Hub
{
private readonly IConnectionManager _connectionManager;

public ChatHub(IConnectionManager connectionManager)
{
_connectionManager = connectionManager;
}

public async Task SendMessage(UserChatHubDTO user, string message)
{

await Clients.All.SendAsync("ReceiveMessage", user, message);

}
public void RegisterUser(UserChatHubDTO user)
{
_connectionManager.AddConnection(Context.ConnectionId, user);
}

public override async Task OnDisconnectedAsync(Exception exception)
{
_connectionManager.RemoveConnection(Context.ConnectionId);
await base.OnDisconnectedAsync(exception);
}
}
3 Replies
WhiteCharun
WhiteCharunOP2mo ago
public interface IConnectionManager
{
void AddConnection(string connectionId, UserChatHubDTO user);
void RemoveConnection(string connectionId);
IEnumerable<string> GetConnectionIds(string anonymousUserId);
}

public class ConnectionManager : IConnectionManager
{
private readonly ConcurrentDictionary<string, UserChatHubDTO> _connections = new();

public void AddConnection(string connectionId, UserChatHubDTO user)
{

_connections[connectionId] = user;
}

public void RemoveConnection(string connectionId)
{
_connections.TryRemove(connectionId, out _);
}

public IEnumerable<string> GetConnectionIds(string anonymousUserId)
{
// To implement
return [];
}
}
public class UserChatHubDTO
{
public string UserId { get; set; }
public string Username { get; set; }
public UserChatHubDTO(string userId, string username)
{
UserId = userId;
Username = username;
}
}

public interface IConnectionManager
{
void AddConnection(string connectionId, UserChatHubDTO user);
void RemoveConnection(string connectionId);
IEnumerable<string> GetConnectionIds(string anonymousUserId);
}

public class ConnectionManager : IConnectionManager
{
private readonly ConcurrentDictionary<string, UserChatHubDTO> _connections = new();

public void AddConnection(string connectionId, UserChatHubDTO user)
{

_connections[connectionId] = user;
}

public void RemoveConnection(string connectionId)
{
_connections.TryRemove(connectionId, out _);
}

public IEnumerable<string> GetConnectionIds(string anonymousUserId)
{
// To implement
return [];
}
}
public class UserChatHubDTO
{
public string UserId { get; set; }
public string Username { get; set; }
public UserChatHubDTO(string userId, string username)
{
UserId = userId;
Username = username;
}
}

Nasdack
Nasdack2mo ago
you can do in-memory storage or DB persistence the DB approach is required if you're running multiple servers each approach is documented If you want to track all connections (a single user may be opening more than one tab), you just have to make your user the key, and the value a list of connections; this is an example
WhiteCharun
WhiteCharunOP2mo ago
Thanks

Did you find this page helpful?