17

I am having a really frustrating issue that I can't seem to get to the bottom of.

I am using SignalR to push messages to a mobile device and the client method is being fired multiple times. The amount of times it fires grows when I log out which is supposed to cleanup/close/stop the connection.

My Hub looks like the following

public class MyHub:Hub
{
    private static string _groupIdentifier = "Test"
    public override Task OnConnected()
    {
        var identity =  //grab identity from auth provider
        Groups.Add(Context.ConnectionId, string.Format("{0}-{1}", _groupIdentifier, identity.UserId));
        return base.OnConnected();
    }

    public void OnMessageCreated(Message message)
    {
        IHubContext context = GlobalHost.ConnectionManager.GetHubContext<MessageCreatedEmitter>();
        context.Clients.Group(String.Format("{0}-{1}",_groupIdentifier, message.userId)).onMessageCreated(obj);
    }

    public override Task OnReconnected()
    {
        var identity = //grab identity from my auth provider
        Groups.Add(Context.ConnectionId, string.Format("{0}-{1}", _groupIdentifier, identity.UserId));
        return base.OnReconnected();
    }

    public override Task OnDisconnected(bool stopCalled)
    {
        var identity = //grab identity from my auth provider
        Groups.Remove(Context.ConnectionId, string.Format("{0}-{1}", _groupIdentifier, identity.UserId));
        return base.OnDisconnected(stopCalled);
    }
}

and my client code looks like the following:

.service('Messages',function($rootScope,$q,$log,User,ENV){
    var self = this;

    this.proxy = null;

    var initializeConnection = function(){
        self.proxy = null;
        var connection = $.hubConnection(ENV.socketEndpoint,{
            qs: {token:User.getToken()},
            logging: true,
            useDefaultPath: false
        });
        self.proxy = connection.createHubProxy('myHub');
        self.proxy.on('onMessageCreated',function(data){
          $rootScope.$emit('Messages:messageReceived',data);
        })

        connection.start().done(function(){
          $log.info('connected');
        })
    }

    var cleanupConnection = function(){
        if(self.proxy != undefined && self.proxy != null){
            self.proxy.connection.stop();
        }
    }

    $rootScope.$on('UserAuthenticated',function(event,data){
        initializeConnection();
    });

    $rootScope.$on('UserLoggedOut',function(event,data){
        cleanupConnection();
    });

    return self;
}

I have verified (or at least believe I have) the following

  1. The OnMessageCreated method on my hub is only being invoked once.
  2. When I log out of my mobile device, the connection is closed or disconnected.

From the behavior so far, it would seem like connections are being made, or the client method is being registered multiple times and sticks around after the connection is closed, but this doesn't seem right and I haven't been able to prove it.

What is causing, or could possible be causing the client method to be fired more than once given the information above?

At this point, I can't verify if it is an Angular issue or a SignalR issue

TheJediCowboy
  • 7,686
  • 27
  • 121
  • 184
  • I would put a console log in $rootScope.$on('UserAuthenticated',function(event,data){ initializeConnection(); }); – Lee.Winter Nov 27 '15 at 12:52
  • What exactly is the problem? That after logging out n times, `initializeConnection` is sending n+1 requests? – Adam Zerner Dec 01 '15 at 19:02

2 Answers2

1

It could well be that UserAuthenticated event is firing multiple times but it could be handled by placing a $.signalR.connectionState.disconnected check around the connection start

var initializeConnection = function(){
    self.proxy = null;
    var connection = $.hubConnection(ENV.socketEndpoint,{
        qs: {token:User.getToken()},
        logging: true,
        useDefaultPath: false
    });
    self.proxy = connection.createHubProxy('myHub');
    self.proxy.on('onMessageCreated',function(data){
      $rootScope.$emit('Messages:messageReceived',data);
    })

    if ($.connection.hub && $.connection.hub.state === $.signalR.connectionState.disconnected){

        connection.start().done(function(){
            $log.info('connected');
        })

    }

}

Edit: I don't actually see where you call the OnMessageCreated method?

Also have you debugged the signalR hub when calling a disconnect? I presume this gets called as normal when a user disconnects, however you also call it on $rootScope.$on('UserLoggedOut' surely your signalR hub won't be able to identify the user at this point and therefore they will remain in your Group collection? If that is the case you could expect strange behavior such as multiple calls to be raised to there residual Context.ConnectionId in the group calls.

Lee.Winter
  • 660
  • 9
  • 16
1

I would focus on creating the controller in the right way. For example, this kind of situations are there:

If the controller is specified in the $routeProvider and in the HTML template it will get create once for each declaration.

Services are by nature singletons, but what you really can mess around easily (as I have done, too) is in controllers. I once was on situation, where same data was fetched four times.

I would double check all controller calls from templates and routeprovider etc, everywhere you are referencing or needing one.

Having new instances on every logout may refer to a router issue. Maybe coming to root / context the a controller having the service gets initialized again and again. Then those controllers interpret every action you make in plural and mess is there.

Source: AngularJS Controller execute twice

Community
  • 1
  • 1
mico
  • 12,285
  • 12
  • 55
  • 91