Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SignalR Client Method Fired Multiple Times in Angular Service

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

like image 791
TheJediCowboy Avatar asked Nov 21 '15 06:11

TheJediCowboy


People also ask

How do I stop SignalR connection?

A SignalR connection can end in any of the following ways: If the client calls the Stop method, a stop message is sent to the server, and both client and server end the SignalR connection immediately.

Can you use SignalR with angular?

Microsoft's @aspnet/signalr package makes it possible to leverage both Azure and Angular to create applications that utilize SignalR.

How do I check if my SignalR is reconnecting?

To test reconnect after the server goes down use iisreset. To simulate client connection dropping (good luck) pull the network cable :) Pulling the network cable won't accurately simulate a client connection dropping when you're using Azure SignalR Service.


2 Answers

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

like image 73
mico Avatar answered Oct 10 '22 12:10

mico


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.

like image 1
Lee.Winter Avatar answered Oct 10 '22 14:10

Lee.Winter