Calling SignalR hub clients from elsewhere in system

C#Javascriptasp.net MvcSignalrSignalr Hub

C# Problem Overview


I've set up a SignalR hub to communicate between the server and client. The hub server side code is stored in a class called Hooking.cs. What I want is to be able to call a method defined in Hooking.cs to allow me to broadcast messages to any connected clients from anywhere in my application. It seems that a new instance of Hooking.cs is created for every client/server call, so I had hoped that I would be able to use something like

var hooking = new Hooking();
hooking.Test();

with the method Test() defined in Hooking.cs such as

public static void Test() {
    Clients.test()
}

and with a the client side javascript

var hooking = $.connection.hooking;
hooking.test = function() { alert("test worked"); };
$.connection.hub.start()

Unfortunately it isn't that simple, as Clients is not static, so not accessible from a static method.

Looking through the SignalR source code I came across a method that looked promising, Hubs.Invoke(string hubName, string method, params object[] args), so I would hope I could use something such as Hubs.Invoke("Hooking", "Test") but I can't make it work.

Any help with this would be hugely appreciated

C# Solutions


Solution 1 - C#

This is the correct way for SignalR 2.x:

var context = GlobalHost.ConnectionManager.GetHubContext<MyHub>();
context.Clients.All.addMessage(message);

Basically, you can use the dependency resolver for the current host to resolve the IConnectionManager interface which allows you to get ahold of the context object for a hub.

Further information can be found in the official documentation.

Solution 2 - C#

Hub.GetClients has disappeared in version 0.4.0.

From the wiki you can now use:

IConnectionManager connectionManager = AspNetHost.DependencyResolver.Resolve<IConnectionManager>();
dynamic clients = connectionManager.GetClients<MyHub>();

Solution 3 - C#

You can easily use a hub by following this 2 step-

  1. Instantiating by dependency injection like this-

     public class ClassName
     {
         ........
         ........
         private IHubContext _hub;
    
         public BulletinSenderController(IConnectionManager connectionManager)
         {
             _hub = connectionManager.GetHubContext<McpHub>();
             ........
             ........
         }
    
         ............
         ............
     }
    

2.Using the hub object like this-

_hub.Clients.All.onBulletinSent(bulletinToSend);

More can be found here.

Example code can be found in this git repo.

Solution 4 - C#

Have a look at how it's done in Chat.cs in SignalR.Samples.Hubs.Chat from https://github.com/SignalR/SignalR.

I can see in there that static Dictionary<TKey, TValue>'s are being instantiated at the top, so I imagine they are being maintained persistently too, either with the Chat class being a persisted instance (?) or that array being updated somehow.

Check it out, David Fowler would probably be the best on this.

Solution 5 - C#

This has changed in .NET Core 2, now you can use dependency injection like this:

    private readonly IHubContext<MyHub,IMyHubInterface> _hubContext;

    public MyController(MyHub,IMyHubInterface hubContext)
    {
        _hubContext = hubContext;
    }

    public bool SendViaSignalR()
    {
        _hubContext.Clients.All.MyClientSideSignalRMethod(new MyModel());
        return true;
    }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJordan WallworkView Question on Stackoverflow
Solution 1 - C#Paolo MorettiView Answer on Stackoverflow
Solution 2 - C#Greg EnnisView Answer on Stackoverflow
Solution 3 - C#Abrar JahinView Answer on Stackoverflow
Solution 4 - C#GONealeView Answer on Stackoverflow
Solution 5 - C#Ian NewsonView Answer on Stackoverflow