3

I am using SignalR on different places of my web project. In my Controllers and HostedService this seems to be working fine. Clients instantiate connections with my hub and I can communicate with them back using an IHubContext instance, injected in the constructor of every controller/hostedservice.

I am having another singleton, running in Background (No HosteService or BackgroundTask). This class is getting IHubContext injected in the constructor also. Still every time it gets called, it seems like this singleton is having a different instance of IHubContext, since this context has no clients/groups connected to it.

This class is being registered as this in the startup function:

services.AddSingleton<IServiceEventHandler<TourMonitorEvent>, TourMonitorEventHandler>();

To configure SignalR I am doing the following in ConfigureServices:

services.AddSignalR().AddNewtonsoftJsonProtocol();

and the following in configure:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHub<MyHubClass>("/hubEndpoint");
    endpoints.MapControllers();
});

the IHubContext ist bein injected as following in both Controllers/Hostedservices and the singleton:

public class MySingleton : IHandler<SomeGenericClass>
{
    private readonly IHubContext<MyHubClass> _hubContext;

    public MySingleton(IHubContext<MyHubClass> hubContext)
    {
        _hubContext = hubContext;
    } 
}

Are Controllers/HosteService being instantiated differently than my Singleton, in a way that might affect IHubContext instantiation?

Kiril1512
  • 3,231
  • 3
  • 16
  • 41
mh133
  • 135
  • 12

1 Answers1

1

As said in the documentation:

Hubs are transient.

So since you Singleton is not a HostedService or a BackgroundTask, I would recomend to inject the hub using a DI.

private IHubContext<MyHubClass, IMyHubClass> MyHubClass
{
    get
    {
        return this.serviceProvider.GetRequiredService<IHubContext<MyHubClass, IMyHubClass>>();
    }
}

Try this and verify if the context now is as you expected.

Kiril1512
  • 3,231
  • 3
  • 16
  • 41
  • I see. So if Hubs are transient, how is it that I get the same hub (I assume that, since both have the same state) on two different Controllers in two different calls? – mh133 Mar 20 '20 at 16:54
  • What you got is the context, not the hub. – Kiril1512 Mar 20 '20 at 17:10
  • Exactly, and the context is a singleton, right? Doesn't that mean, that I am having the same object (context), instantiated one time and thus having the same hub (transient)? This is at least, the behavior I am having in the Controllers/Hostedservices. I am having the same singleton with the same hub (state). – mh133 Mar 20 '20 at 17:17
  • ASP.NET Core has a dependency injection framework that removes the need for this global singleton. When hub methods are called from outside of the Hub class, there's no caller associated with the invocation. Therefore, there's no access to the ConnectionId, Caller, and Others properties. – Kiril1512 Mar 20 '20 at 18:02