6

From here, it states that

All clients will use the same URL to establish a SignalR connection with your service ("/signalr" or your custom URL if you specified one), and that connection is used for all Hubs defined by the service.

There is no performance difference for multiple Hubs compared to defining all Hub functionality in a single class.

The reason I want to do this just because my only Hub is becoming god class, however, I can't find a way to do multiple hubs in .NET Core (while sharing one connection). I wish I could do so, then I could manage my code like how I did in Web APIs.

One possible solution may create multiple connections, but I have to manage different connections on my client side, just to prevent god class on the server code.

From here, someone states that mapping methods to external classes is a workaround. Is that the only workaround?

Community
  • 1
  • 1
Lee Song
  • 601
  • 1
  • 5
  • 17

2 Answers2

4

Since SignalR has been integrated within ASP.NET Core, it is not possible any more to use one connection for multiple hubs:

In ASP.NET Core SignalR, the connection model has been simplified. Connections are made directly to a single hub, rather than a single connection being used to share access to multiple hubs.


As a workaround for a god class, you could make use of #region's to structure your code, if you want to use a single hub.

However, I do recommend to use different hubs for each purpose. For example: if I have a chat system, I would use a specific hub (ChatHub) for the chat. If I also have a quiz system, I would use a QuizHub, etc...

I don't really see the problem of handling multiple connections. Because there will be no performance issues. By seperating the code for each purpose, you are implementing separation of concerns (correct me if I'm wrong).

If you can, only initialize the client code (connection) on the pages where you actually use it, by dividing the SignalR client code (per hub) into its own file.

Let's take my last example: if the quiz has its own page, only load the SignalR client-side code on that page only.


Another thing you could try, is AJAX requests. Sometimes, I separate my code into different API controllers, and simply make an AJAX request to my API controller, to handle database transactions, for example.

You can also use some SignalR features inside that controller, by using IHubContext<T>.

In ASP.NET Core SignalR, you can access an instance of IHubContext via dependency injection. You can inject an instance of IHubContext into a controller, middleware, or other DI service. Use the instance to send messages to clients.

class SomeController : Controller
{
    private readonly IHubContext<MyHub> _hubContext;

    public SomeController(IHubContext<MyHub> hubContext)
    {
        _hubContext = hubContext;
    }
}

The documentation of using SignalR functions outside the hub, has more examples.

The downside is that you can't use all the nice features of SignalR, like adding connections to groups. It is possible to use the within your controller.

Matthijs
  • 2,483
  • 5
  • 22
  • 33
  • 4
    `Because there will be no performance issues.` Dont fully agree. Every hub opens his own connection, so 100 users will generate 200 connections instead of only 100. If some kind of sessions were used, this has to be fetched 200 times instead of only 100 times. It could also affect the battery of mobile devices when multiple connections were keepd open. I agree for a separation of concerns. But I think the old approach is better here: You have a clean seperation between hubs, without having to worry about too much connections. – Lion Sep 05 '19 at 00:46
  • 3
    According to [this post](https://stackoverflow.com/a/54285137/3276634), Apple systems seems having a limit of four connections per server. This could be easily reached with multiple hubs on SignalR Core, but would be no problem on the old approach of a single connection. – Lion Sep 05 '19 at 00:49
3

How about using partial classes. Not sure if there's any downside for this approach.

    public partial class TestHub : Hub
    {

    }

    public  partial class TestHub {

    }


David Blay
  • 527
  • 1
  • 3
  • 14