简体   繁体   中英

Calling one hub from another hub with the correct context in SignalR

I have two Hubs, one which is used to track users (chatHub), and another hub which is used for dashboard (dashHub).

When a new user connects to the website it triggers Server.Connect method which tracks the user ID's and groups. Then I want to call DashHub.Update() from ChatHub, so that all the dash subscribers get new data pushed to them.

I have read this on the official documentation and understand what is going on there fine, but I really want to call the DashHub.Update() method which has some logic in there, not just send a message via the context. Looking around Stackoverflow and other examples I have got to this, working solution, but it just doesn't look correct.

ChatHub.cs - UpdateDashboardClients() gets called each time I need to push data to the dashboard. Its private.

private void UpdateDashboardClients()
{
      DashHub dh = new DashHub();
      dh.SendNew();
} 

DashHub.cs - This works fine on the dashbpaord client side and my solution to fix the Context == null problem when calling from outside the Hub, from another Hub I used this.

 public void SendNew()
 {
    if (Context == null)
    {
       IHubContext contextDashHub =  GlobalHost.ConnectionManager.GetHubContext<DashHub>();
       contextDashHub.Clients.Clients(<clients>).PushNew(<data>)
    }
    else
    {
        Clients.Clients(<clients>).PushNew(<data>);
    }

 }

I tried to set the resolved IHubContext contextDashHub to the this.Context with a cast but that fails, because this.Context is of type HubCallerContext .

If I could just make another constructor that takes the context, or just a method that takes the context, and assigns it to dashhub context that would be great.

I read something about Proxies on the server but not to sure about how that works either and if its even the correct way to go.

This "workaround" works for me now, but its not very reusable and it repeats code, which makes it very stinky.

I suppose I need to use DI somehow from the ChatHub (Similar to getting the context) to do this properly but I am also fairly new at DI still and not sure exactly how to do that.

Could anybody please provide the correct way to do this.

As you already noticed, what you are trying to do is not the correct approach. The fact that you really want to instantiate a hub on your own and call a method on it is wrong. The life-cycle of hub instances should be left under the control of SignalR's runtime.

The fact that you get an empty context is perfectly logic and you should not try to change that, it would not make sense otherwise. For example, if you have code in your hub that is checking for the Caller endpoint, that cannot possibly work even from a logical point of view (there's no caller in such a case). You should never try such a hack, because there's no way you can build a context which would work for every case.

You should review your architecture separating what's about handling requests from clients and what relates to broadcasts originated directly on the server. Think about those as 2 different responsibility and structure your code accordingly. You might introduce a "broadcast service" for the server side messages based on IHubContext , and you might for example have code from hubs methods calling into this service by passing their own context into it. The service wouldn't know if the call has been originated by a client or by the server code, it would be reusable and without duplication.

DI can help you in keeping such code clean, but it's not strictly necessary. It also depend on the size of your application, but if it's just a bunch of types you can take some shortcuts and still keep the code under control. Otherwise, DI support from SignalR is not hard to manage, read about it and you'll find out it's pretty easy. If you go with DI, you might have your hubs receive an instance of the broadcast service (always the same instance or always new? it could work both ways, it depend on how it's implemented) and use it in their method calls accordingly, passing in the right contexts for each case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM