Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get SignalR Hub Context in a ASP.NET Core?

IConnectionManager does not exist any more in SignalR for ASP.Net Core.
I've been using HubContext for getting access to a hub.

public class HomeController : Controller
{
    private readonly IHubContext<LiveHub> _hubContext;

    public HomeController(IHubContext<LiveHub> hubContext)
    {
        _hubContext = hubContext;
    }

    public void SendToAll(string message)
    {
        _hubContext.Clients.All.InvokeAsync("Send", message);
    }
}

I'm using .net core 2.0.0 and SignalR 1.0.0-alpha1-final


Microsoft.AspNet.SignalR.Infrastructure.IConnectionManager is a DI injected service through which you can get the hub context...For example:

using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Infrastructure;
using Microsoft.AspNet.Mvc;

public class TestController : Controller
{
     private IHubContext testHub;

     public TestController(IConnectionManager connectionManager)
     {
         testHub = connectionManager.GetHubContext<TestHub>();
     }
 .....

To use the hub in a backgroud service, in addition to controllers, you must use the IHostedService interface and get the hub by DI.

public class MyBackgroundService : IHostedService, IDisposable
{
    public static IHubContext<NotifierHub> HubContext;

    public MyBackgroundService(IHubContext<NotifierHub> hubContext)
    {
        HubContext = hubContext;
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        //TODO: your start logic, some timers, singletons, etc
        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        //TODO: your stop logic
        return Task.CompletedTask;
    }

    public void Dispose()
    {
    }
}

Then you can call your hub from anywhere in your code from HubContext static field:

MyBackgroundService.HubContext.Clients.All.SendAsync("UpdateData", myData).Wait();

Learn more about IHostedService: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-2.1

You can create and start a timer in MyBackgroundService and call the hub in ElapsedEvent.


I added some code to my Startup.cs to grab reference to the ConnectionManager which you can then use to do a GetHubContext at anytime from anywhere in your code. Similar to Nimo's answer but a little different, maybe simpler.

services.AddSignalR(options =>
{
    options.Hubs.EnableDetailedErrors = true;
});

var provider = services.BuildServiceProvider();

//Hold on to the reference to the connectionManager
var connManager = provider.GetService(typeof(IConnectionManager)) as IConnectionManager;

//Use it somewhere else
var hub = connManager.GetHubContext<SignalHub>();

I needed to be able to access the Hub Context from outside the app request thread - because I was subscribing to NServicebus messages, and needed to be able to trigger a client function when I received a message.

Here's how I got it sorted:

public static IServiceProvider __serviceProvider;

then during startup configuration

app.UseServices(services =>
        {
            __serviceProvider = new ServiceCollection()
            .BuildServiceProvider(CallContextServiceLocator.Locator.ServiceProvider);
        });

Then anywhere else in the vNext asp.net application (any other thread)

 var manager = Startup.__serviceProvider.GetRequiredService<IConnectionManager>();
            var hub = manager.GetHubContext<ChatHub>();

Hope this helps!