0

I'm using the latest version of SignalR with jQuery and getting some odd behavior where a user disconnects, but still hangs around in my "UserQueue" despite having disconnected.

I think this may be related to the fact that a page refresh appears to trigger the OnDisconnected and OnConnected events almost simultaneously. When I set a break point in one of these methods and step through, my pointer bounces back and forth between the two methods with each step (F10).

I'd like to run a check with each OnConnected event to find out who is actually connected to my app. I want to fire a JS event from my C# code in the OnConnected event, and then allow the client/front end to fire back a confirmation of the user being present:

public override Task OnConnected()
{
    // Check for other users:
    Clients.All.checkForOtherUsers();

    // Do stuff with my user queue
    var curmodelId = GetModelId(Context);
    var curUserConnection = GetCurrentUser(Context);
    // First create the ledger is missing, setting the modelId as the first key
    if (_ledger == null)
    {
        _ledger = new ConnectionLedger(curmodelId, curUserConnection);
    }
    else
    {
        // key not found, create new connection pool this model
        if (!_ledger.PoolIds.Contains(curmodelId))
        {
            _ledger.AddConnectionPool(curmodelId, curUserConnection);
        }
        else
        {
            var curModelPool = _ledger.ConnectionPools.First(x => x.Id == curmodelId);
            curModelPool.UserQueue.Enqueue(curUserConnection);
        }
    }

    return base.OnConnected();
}   

Now in the client JS, if I have this code:

modelHub.client.checkForOtherUsers = function () {
    // I can see logging here if I add console.log("checking for other users...")
    modelHub.server.send();
}

...I'm expecting my C# Send method to receive back the context (if the user is actually present at the client for the JS to execute) and update my UserQueue:

public void Send()
{
    var curmodelId = GetModelId(Context);
    var curModelPool = _ledger.ConnectionPools.First(x => x.Id == curmodelId);
    var curUserConnection = GetCurrentUser(Context);
    curModelPool.UserQueue.Enqueue(curUserConnection);
}

... but my Send method never gets fired, even when I fire it from the JS Console directly $.connection.modelingHub.server.send().

Why doesn't the Send method fire? Is there something about the order of events / async nature of the SignalR library that causes this?

Comments on the overall design are welcome too (since I suspect it could be stupid), but note that I cannot access Context.User or Clients.User because of my customized Authentication config.

JacobIRR
  • 8,545
  • 8
  • 39
  • 68

1 Answers1

1

Seems to be two causes below.

Server-side
Not good to call Clients.All.checkForOtherUsers(); within OnConnected().
I would recommend calling it after connected.

Please refer to SignalR - Send message OnConnected

Client-side
Might need to regist modelHub.client.checkForOtherUsers = function () { before calling start method.

Normally you register event handlers before calling the start method to establish the connection. If you want to register some event handlers after establishing the connection, you can do that, but you must register at least one of your event handler(s) before calling the start method.
- How to establish a connection

idubnori
  • 997
  • 9
  • 21
  • Thanks for your input. The server part is already using that pattern. For the client, how do I "register event handlers before calling the start method" ? – JacobIRR Jan 24 '18 at 18:04
  • It means follows. (I am not sure since I can't see your all client side code.) `modelHub.client.checkForOtherUsers = function () { modelHub.server.send(); } $.connection.hub.start()` – idubnori Jan 25 '18 at 09:13