Search code examples
asp.netasp.net-mvcmultithreadingsignalrsignalr-hub

Signalr - Associating usernames with connectionIds


Here is my hub:

[HubName("marketWatch")]
public class MarketWatchHub : Hub
{
    public override Task OnConnected()
    {
        SocketCommunicator.Instance.UserConnected(Context.ConnectionId, Context.User.Identity.Name);

        return base.OnConnected();
    }

    public override Task OnDisconnected()
    {
        SocketCommunicator.Instance.UserDisconnected(Context.ConnectionId);

        return base.OnDisconnected();
    }

    public override Task OnReconnected()
    {
        // TODO: implement...
        return base.OnReconnected();
    }

    public List<MarketDataResponse> GetAllMarketWatchData()
    {
        return SocketCommunicator.Instance.MarketDataList;
    }
}

And here is the simplified version of SocketCommunicator class:

public class SocketCommunicator
{
    private static SocketCommunicator _Instance = new SocketCommunicator();

    public static SocketCommunicator Instance
    {
        get { return SocketCommunicator._Instance; }
    }

    private Socket socket { get; set; }

    private readonly object lockObj = new object();

    private IHubContext hubContext;

    private List<UserDetail> connectedUsers;

    public List<MarketDataResponse> MarketDataList;

    private SocketCommunicator() { }

    public void UserConnected(string connectionId, string username)
    {
        lock (lockObj)
        {
            connectedUsers.Add(new UserDetail() { ConnectionId = connectionId, UserName = username });
        }
    }

    public void UserDisconnected(string connectionId)
    {
        lock (lockObj)
        {
            connectedUsers.RemoveAll(ud => ud.ConnectionId == connectionId);
        }
    }

    public void GetMarketData()
    {
        // Do something and set this.MarketDataList
    }        
}

When I hit F5 and debug my application it works like a charm. When user logs in, my OnConnected method in my hub is called and when user logs off OnDisconnected method is called. But if user logs in and close his/her browser, OnDisconnected method is not being called. This means in time, my connectedUsers list will contain enormous number of UserDetail objects that are not really connected. How can I avoid this situation? Is there a better way to store user - connection id association?

Thanks in advance,


Solution

  • How long are you waiting for OnDisconnect to get called? It isn't always instantaneous, especially if the client doesn't close 'cleanly' (i.e. closing the browser). It should get called eventually, once the connection times-out.

    I have a similar setup and it works fine.