How can I get a SignalR HubContext using a base hub type to access the same derived hub instance?

See original GitHub issue

I apologise for the somewhat confusing nature of the title; I was unsure how to properly word it. If there’s a better way of classifying what I’m trying to do, I will try to reword the title (and this post) for greater clarity.

The Hub

I have a SignalR hub, BaseHub, that inherits from Hub<T>. BaseHub is then inherited by TestHub. This hub is mapped via `routes.MapHub<TestHub>(“/hub”).

The BaseHub class is stored in a library, along with some controllers. The TestHub class is stored in the ASP.NET Core API project itself, which contains more controllers.

The Problem

When injecting the HubContext into one of my controllers in the API project I specify IHubContext<TestHub, ITestClient> hubContext as the constructor parameter, which works as expected.

When injecting the HubContext into one of my controllers in the library project I specify IHubContext<BaseHub, ITestClient> hubContext as the constructor parameter, which does not work as expected. There are no exceptions thrown, and a HubContext instance is supplied, but SignalR notifications are not sent using this instance.

When looking at the non-public members of this HubContext instance in the watch window, I can see that HubContext.Clients._lifetimeManager._connections.Count is 0 even though I know there are definitely connections to the hub (for the one that works, this figure is above zero when I inspect the HubContext instance using the watch window).

My best guess is it’s expecting there to be a different hub instance available of type BaseHub.

The Question

What can I do to ensure that injections of IHubContext<TestHub, ITestClient> and IHubContext<BaseHub, ITestClient> reference the same hub instance?

For example, with my DbContext classes, I am able to do services.AddScoped<BaseDbContext>(f => f.GetRequiredService<DerivedDbContext>());, however that doesn’t seem possible here. For starters, the MapHub() part happens in Configure() rather than ConfigureServices(). Even if I ignore that, and attempt to add the service regardless, it looks like IHubContext doesn’t support covariance (I think that’s the correct term?), so the following throws an InvalidCastException:

services.AddScoped<IHubContext<BaseHub<ITestClient>>>(f => (IHubContext<BaseHub<ITestClient>>)f.GetRequiredService<IHubContext<TestHub>>());

Is what I am attempting possible? Or is my only alternative to either move those shared controllers out of the library project, or to create derived controllers that inject the correct HubContext?

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:2
  • Comments:13 (3 by maintainers)

github_iconTop GitHub Comments

2reactions
renanrcpcommented, Jul 1, 2020

Hey, @Metritutus when you use MapHub<THub> it will add a connection middleware, it uses ActivatorUtilities.GetServiceOrCreateInstance<T>() for create or get your hub one time (when you add);

With this you can inject in D.I a singleton like that: <BaseHub, TestHub> and instead use MapHub<TestHub> you can use MapHub<BaseHub> and it will get your hub from the dependency container.

I don’t know why when you requested an IHubContext<BaseHub, ITestClient> it doesn’t throw an exception, probably because IHubContext is injected in D.I in this way:

services.TryAddSingleton(typeof(IHubContext<>), typeof(HubContext<>));
services.TryAddSingleton(typeof(IHubContext<,>), typeof(HubContext<,>));
1reaction
BrennanConroycommented, Jul 1, 2020

By default this wont work, but you might be able to set it up to work this way by doing something like: services.AddSingleton<IHubContext<BaseHub>, IHubContext<TestHub>>();

Read more comments on GitHub >

github_iconTop Results From Across the Web

SignalR HubContext
Learn how to use the ASP.NET Core SignalR HubContext service for sending notifications to clients from outside a hub.
Read more >
Dependency Injection in SignalR
This tutorial shows how to perform dependency injection on SignalR hubs. It also shows how to use IoC containers with SignalR.
Read more >
Call SignalR Core Hub method from Controller
Solution 1. Another possibility is to inject your HubContext into your controller like:
Read more >
SignalR modules with a shared connection using a C# ...
This sample shows how to build SignalR modules with a shared connection using a C# Source Generator. The source is available on GitHub....
Read more >
Practical ASP.NET Core SignalR: HubContext
The HubContext allows you to send messages to connected clients from outside of your ASP.NET Core SignalR, such as Controllers or any other ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found