7

This is related to SignalR + posting a message to a Hub via an action method, but my question is a bit different:

I'm on version 0.5.2 of signalr, using hubs. In older versions, you were encouraged to create methods on the hub to send messages to all clients, which is what I have:

public class MyHub : Hub
{
    public void SendMessage(string message)
    {
        // Any other logic here
        Clients.messageRecieved(message);
    }

    ...
}

So in 0.5.2, I want to send a message to all the clients (say from somewhere in the controller). How can I get access to the MyHub instance?

The only way I've seen referenced is:

var hubContext = GlobalHost.ConnectionManager.GetHubContext<MyHub>();
hubContext.Clients.messageRecieved("hello");

Which is fine, but I want to call the method on my hub.

Community
  • 1
  • 1
Matt Roberts
  • 26,371
  • 31
  • 103
  • 180
  • This is now possible in ASP.NET Core as well (although SignalR itself is still in alpha at the current time). See [this detailed answer](http://stackoverflow.com/a/38832879/957950) on the Core version of this question. – brichins Mar 08 '17 at 22:51

3 Answers3

20

You can do this by using a static method:

SignalR v.04-

public class MyHub : Hub
{
    internal static void SendMessage(string message)
    {
        var connectionManager = (IConnectionManager)AspNetHost.DependencyResolver.GetService(typeof(IConnectionManager));
        dynamic allClients = connectionManager.GetClients<MyHub>();
        allClients.messageRecieved(message);
    }

    ...
}

SignalR 0.5+

public class MyHub : Hub
{
    internal static void SendMessage(string message)
    {
        IHubContext context = GlobalHost.ConnectionManager.GetHubContext<MyHub>();
        context.Clients.messageRecieved(message);
    }

    ...
}

You can then call this like so:

MyHub.SendMessage("The Message!");

Good article on the SignalR API: http://weblogs.asp.net/davidfowler/archive/2012/05/04/api-improvements-made-in-signalr-0-5.aspx

Provided by Paolo Moretti in comments

Paul
  • 12,392
  • 4
  • 48
  • 58
  • 1
    `AspNetHost.DependencyResolver` has disappeared in SignalR 0.5+. See [here](http://weblogs.asp.net/davidfowler/archive/2012/05/04/api-improvements-made-in-signalr-0-5.aspx) (Getting a reference to the connection/hub outside of a connection or hub) – Paolo Moretti Jul 13 '12 at 16:27
4

I had same problem, in my example addNotification is client-side method:

var hubContext = GlobalHost.ConnectionManager.GetHubContext<SignalR.NotificationsHub>();
hubContext.Clients.addNotification("Text here");

On you client side you can add code to call your hub method in addNotification:

var notification = $.connection.notificationHub;
notification.addNotification = function (message) {
 notification.addServerNotification(message); // Server Side method
}

$.connection.hub.start();

Hub:

 [HubName("notificationHub")]
    public class NotificationsHub : Hub
    {
        public void addServerNotification(string message)
        {
          //do your thing
        }
    }

UPDATE: Reading your question over and over agian I really don't find a reason to do that. Hub methods are usually there to be called from client side, or I misunderstood you, anyway here is an update. If you want to do a server side thing and then notify clients.

  [HttpPost]
  [Authorize]
  public ActionResult Add(Item item)
  {
      MyHubMethodCopy(item);
      var hubContext = GlobalHost.ConnectionManager.GetHubContext<SignalR.NotificationsHub>();
    hubContext.Clients.addNotification("Items were added");

  }

  private void MyHubMethodCopy(Item item)
  {
      itemService.AddItem(item);
  }
formatc
  • 4,261
  • 7
  • 43
  • 81
2

Update for ASP.NET Core 2.x and 3.x:

You can easily access the Hub instance anywhere that you have Dependency Injection:

public class HomeController : Controller
{
    private readonly IHubContext<MyHub> _myHubContext;

    public HomeController(IHubContext<MyHub> myHubContext)
    {
        _myHubContext = myHubContext;
    }

    public void SendMessage(string msg)
    {
        _myHubContext.Clients.All.SendAsync("MessageFromServer", msg);
    }
}

If it gives you syntax errors, make sure you have:

using Microsoft.AspNetCore.SignalR;

and that you do NOT HAVE:

using Microsoft.AspNet.SignalR;
Josh Withee
  • 9,922
  • 3
  • 44
  • 62