7

I'm having trouble getting SignalR server-side Hub code to invoke JS client methods. The reverse is working fine - so when my client sends a message to the server it is delivered as expected. I've been fairly careful to avoid obvious traps but I guess I'm still overlooking something. Here's my code:

From MessageHub.cs:

public bool SendMessage( ClientMessage message )
{
    ...
    Clients.All.addMessage("my message");
    ...
}

Javascript:

$.connection.hub.start()
    .done(function () {
        messageHub = $.connection.message;

        // addMessage is never invoked.
        messageHub.client.addMessage = function (message) {
            alert('message added');
        };

        /* // I tried this based on some sample code but still not invoked.
        messageHub.addMessage = function (message) {
            alert('message added');
        };
        */

        // This works as expected.
        messageHub.server.registerUser(userId);
        ...
    });

As mentioned above, I can't find any obvious deficiencies with the setup but here are a few possibly relevant points:

  • The connection is established and server-side methods are invoked.
  • It's probably irrelevant, but I've tried forcing different transports with no change in behaviour.
  • The client method names do not conflict with the server method names at any point.
  • I've also tried sending messages to specific client connections (which is actually the goal, in this case).
  • I have logging enabled on both the client and server but don't see anything relevant in either case.

So, given the above, am I missing something obvious? If not, what is the best way to identify the failure point?

P.S. This isn't specifically related to the question, however, for some reason Fiddler is no longer capturing any traffic from any of my browsers, which makes debugging WS or HTTP traffic a bit challenging - I'm guessing that's a Windows 8 thing...

Zac Seth
  • 2,742
  • 5
  • 37
  • 56

2 Answers2

37

So, the answer was actually quite simple (though since the last release I have upgraded from 1.0.0.0-rc1 to 1.0.0.0 - but I'm fairly certain that didn't change this scenario signficantly).

I found the answer here: https://stackoverflow.com/a/15074002/32935 (note, specifically, my solution was for the first answer provided - though the second helped me identify the cause).

Essentially, for those who don't want to go over to the original answer, I had to setup my client methods before calling the start() method against the connection as opposed to in the done() callback as I was doing. Here's an example:

$.connection.message.client.addMessage = function (message) {
    alert( 'Now it works!' );
};

$.connection.hub.start()
    .done(function () {
        console.log( 'Connection established!' );
    });
Community
  • 1
  • 1
Zac Seth
  • 2,742
  • 5
  • 37
  • 56
  • this is very important tip!! you saved me days :) thank you! – Guy Bertental Jun 21 '15 at 17:47
  • Thanks for saving my hours today. – Konrad Aug 21 '15 at 10:14
  • Thanks, I was trying it in angularjs in wrong order – cdiazal Feb 10 '16 at 19:52
  • 1
    I had the same issue bought on by upgrading my SignalR version to 2.2.1, it appears that now you must specify the client actions/methods before starting the connection, whereas previously it didn't matter. – A. Murray Jan 17 '17 at 14:42
  • Life saver. My Angular app was loading child controllers at different times between Chrome and IE (ie11), so in some cases the hub was started before the client function definitions. I thought it was a browser-specific problem. Thank you! – Nexxas Apr 19 '17 at 18:50
-2

When you hover over the Clients object, do you see all the functions you defined in JS?

Anyway,I'm not sure why your way doesn't work, but this is how I wrote my client side, and it works. Maybe you could try this way.

$(function () {

    var hub = $.connection.RatesHub;


    $.connection.hub.start().done(function () {
        /*Logic goes here*/
    });

    $.extend(hub.client, {
        FuncName: function (msg) {
            /*Logic goes here*/
        }
    });

}

Any function you want to be recognized in your server, use $.extend.

Hope that helps.

user1919071
  • 93
  • 2
  • 4
  • The reason this works in your situation is because $.extend is finishing before the done method's callback is called. This leads to a race condition that if any events happen to block execution between the start() call and $.extend (which can happen), none of the methods will be accessible to SignalR. – Joe the Coder Dec 20 '16 at 15:20