Signalr doesn't call client side functions

mhu picture mhu · Feb 25, 2013 · Viewed 10.9k times · Source

I'm using the VS2012 "Fall" Update with the Signalr 1.0.0 package. Calling server side functions works fine. However client functions are not called. Nothing seems to happen when onBroadcastMessage() (see below) is called.

Questions:

  • What am I missing?
  • Is there a way to debug the client call?

Thanks!

Server code:

using Microsoft.AspNet.SignalR;

namespace KPMain
{
    public class RealtimeConnectionHub : Hub
    {
        public void BroadcastMessage(string name, string message) {
            Clients.All.onBroadcastMessage(name, message);
        }
    }
}

Route registration:

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes) {
        HubConfiguration hubConfig = new HubConfiguration();
#if DEBUG
        hubConfig.EnableDetailedErrors = true;
#endif
        routes.MapHubs(hubConfig);

        ...
    }
}

Client code (simplified):

var rtcom = new RealtimeConnection();
rtcom.init({debug: true}, function () {
    rtcom.subscribe(function (sender, message) {
        if (message) {
            alert("message");
        }
    });
});

RealtimeConnection: function () {    
    var
        _rtHub = $.connection.realtimeConnectionHub,
        _initialized = false,                
        _init = function (options, cb) {
            options = options || {};

            $.connection.hub.logging = options.debug;
            $.connection.hub.start().done(function () {
                _initialized = true;

                if (cb) { cb(); }
            });
        },

        _broadcast = function (message) {
            if (_initialized) {
                _rtHub.server.broadcastMessage("testuser", message);
            }
        },

        _subscribe = function (cb) {
            if (_initialized) {
                _rtHub.client.onBroadcastMessage = cb;
            }
        };

    return {
        initialized: _initialized,
        broadcast: _broadcast,
        subscribe: _subscribe,
        init: _init
    };
}

$("#container").on("click", "button.chat-btnSendMessage", function () {
    rtcom.broadcast($(this).parent().find("input").val());
});

Log (using chrome):

[16:58:01 GMT+0100 (W. Europe Standard Time)] SignalR: Negotiating with '/signalr/negotiate'. jquery.signalR-1.0.0.js:54
[16:58:02 GMT+0100 (W. Europe Standard Time)] SignalR: Attempting to connect to SSE endpoint 'http://w2008r2portal/signalr/connect?transport=serverSentEvents&connectionT…EgDDEU0WLhHVzI7ZUnA0impltR7HYNTGHUJJYAXew1Leg2&connectionData=%5B%5D&tid=0' jquery.signalR-1.0.0.js:54
[16:58:03 GMT+0100 (W. Europe Standard Time)] SignalR: EventSource connected jquery.signalR-1.0.0.js:54
[16:58:03 GMT+0100 (W. Europe Standard Time)] SignalR: Now monitoring keep alive with a warning timeout of 13333.333333333332 and a connection lost timeout of 20000 


Request URL:http://xxx/signalr/send?transport=serverSentEvents&connectionToken=lnTczBgQB0dj...
Request Method:POST
Status Code:200 OK

Request Headers
Accept:application/json, text/javascript, */*; q=0.01
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Authorization:Negotiate YIIFXQYGKwYBBQUCoIIFUTCCBU2...
Connection:keep-alive
Content-Length:148
Content-Type:application/x-www-form-urlencoded; charset=UTF-8
Host:w2008r2portal
Origin:http://w2008r2portal
Referer:http://w2008r2portal/?tab=Start
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.57 Safari/537.17
X-Requested-With:XMLHttpRequest

Query String Parameters
transport:serverSentEvents
connectionToken:lnTczB...

Form Data
data:{"H":"realtimeconnectionhub","M":"BroadcastMessage","A":["testuser","test"],"I":0}

Response Headers
Cache-Control:no-cache
Content-Type:application/json; charset=UTF-8
Date:Mon, 25 Feb 2013 15:58:04 GMT
Expires:-1
Persistent-Auth:false
Pragma:no-cache
Server:Microsoft-IIS/7.5
Transfer-Encoding:chunked
WWW-Authenticate:Negotiate oYGyMIGvoAMKAQChCwY...
X-AspNet-Version:4.0.30319
X-Content-Type-Options:nosniff
X-Powered-By:ASP.NET

Answer

N. Taylor Mullen picture N. Taylor Mullen · Feb 25, 2013

So your issue lies in the fact that you're starting your connection before you have any client side methods registered with your hub proxy.

There are two ways to solve this.

  1. In your init prior to $.connection.hub.start call your _subscribe method.
  2. Ensure that you have at least 1 client side method defined prior to start (required to be "subscribed" to incoming messages). Use .on to subscribe hub methods after start.

So here's the two approaches in code.

1:

var rtcom = new RealtimeConnection();
rtcom.init({debug: true});

RealtimeConnection: function () {    
    var
        _rtHub = $.connection.realtimeConnectionHub,
        _initialized = false,                
        _init = function (options, cb) {
            options = options || {};

            $.connection.hub.logging = options.debug;

            _rtHub.client.onBroadcastMessage = function() {
                alert("message");
            };

            $.connection.hub.start().done(function () {
                _initialized = true;

                if (cb) { cb(); }
            });
        },

        _broadcast = function (message) {
            if (_initialized) {
                _rtHub.server.broadcastMessage("testuser", message);
            }
        },

    return {
        initialized: _initialized,
        broadcast: _broadcast,
        init: _init
    };
}

$("#container").on("click", "button.chat-btnSendMessage", function () {
    rtcom.broadcast($(this).parent().find("input").val());
});

2:

var rtcom = new RealtimeConnection();
rtcom.init({debug: true}, function () {
    rtcom.subscribe(function (sender, message) {
        if (message) {
            alert("message");
        }
    });
});

RealtimeConnection: function () {    
    var
        _rtHub = $.connection.realtimeConnectionHub,
        _initialized = false,                
        _init = function (options, cb) {
            options = options || {};

            // Need to have at least 1 function registered to be subscribed to hub
            _rtHub.client.foo = function() {};

            $.connection.hub.logging = options.debug;
            $.connection.hub.start().done(function () {
                _initialized = true;

                if (cb) { cb(); }
            });
        },

        _broadcast = function (message) {
            if (_initialized) {
                _rtHub.server.broadcastMessage("testuser", message);
            }
        },

        _subscribe = function (cb) {
            if (_initialized) {
                _rtHub.on("onBroadcastMessage", cb);
            }
        };

    return {
        initialized: _initialized,
        broadcast: _broadcast,
        subscribe: _subscribe,
        init: _init
    };
}

$("#container").on("click", "button.chat-btnSendMessage", function () {
    rtcom.broadcast($(this).parent().find("input").val());
});

Hope this helps!