SignalR: How to truly call a hub's method from the server / C#

In order to truly call a hub method, as you call it, you have to be connected to it, and call over that connection. By calling something different (your API) you cannot do that kind of call, and therefore you have to resort to the server initiated broadcasting capabilities, which by nature cannot know about what the Caller is because there's no SignalR's caller.

That said, if your client calling the API (no matter if it's Javascript or C#) is already connected to the hub when performing the call, you can always decorate your call towards the API with the connectionId of your hub's connection (by query string, by headers, ...). If your API receives that information, it can then simulate the Caller API with

Clients.Client(connectionId)

and it can do the same for Others with

Clients.AllExcept(connectionId)

over a IHubContext instance. Check the official docs.

You can then follow the suggestion from DDan about encapsulating the IHubContext usage in a convenient centralized way, or even restructure it a bit to make it easily DI-compliant.


I am using the method explained in this answer.

public class NewsFeedHub : Hub 
{
    private static IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext<NewsFeedHub>();

    // Call this from JS: hub.client.send(channel, content)
    public void Send(string groupName, string content)
    {
        Clients.Group(groupName).addMessage(content);
    }

    // Call this from C#: NewsFeedHub.Static_Send(groupName, content)
    public static void Static_Send(string groupName, string content)
    {
        hubContext.Clients.Group(groupName).addMessage(content);
    }

}

The hub defines and uses its hubContext, so you can do:

var newsFeedHub = new NewsFeedHub();
var newsFeedHub.Static_Send("ch1", "HELLO");

Or:

var taskHub = new TaskHub();
var taskHub.InsertTask(task);

If you prefer that, based on your method naming.

Tags:

C#

Signalr