0

I have a look at many examples on several web pages and finally getting very confused due to the different approach on each of the examples. I simply want to use a HubBase class where I define shared hub methods i.e. OnConnected(), AddToGroup()) and multiple hub classes (HubX, HubY) where I define specific methods to these hubs. Here is the basic structure I try to apply:

ITypedHubClient:

public interface ITypedHubClient
{
    Task BroadcastData(string groupName, object data);
}


HubBase:

public class HubBase : Hub<ITypedHubClient>
{
    public readonly static ConnectionMapping<string> connections =
        new ConnectionMapping<string>();

    public override async Task OnConnected()
    {
        //
    }

    public override async Task OnDisconnected(bool stopCalled)
    {
        //
    }

    public async Task AddToGroup(string connectionId, string groupName)
    {
        //
    }


    public async Task SendMessageToAll(string user, string message)
    {
        await Clients.All.SendAsync(user, message);
    }

    public async Task SendMessageToGroup(string groupName, string message)
    {
        await Clients.Group(groupName).SendAsync(message);
    }
}


HubX:

[HubName("hubX")]
public class HubX : HubBase
{
    private readonly static IHubContext context = 
        GlobalHost.ConnectionManager.GetHubContext<HubX>();

    public static async Task SendDataToGroup(string groupName, object data)
    {
        await context.Clients.Group(groupName).refreshData(data);
    }

    public static async Task BroadcastData(object data)
    {
        await context.Clients.Group("groupX").refreshData(data);
    }
}


Controller:

public class MyController : Controller

    private IHubContext<HubX> hubContext;

    public MyController(IHubContext<HubX> hubContext)
    {
        this.hubContext = hubContext;
    }

    public JsonResult Create()
    {
        //...  
        this.hubContext.Clients.Group("groupX").BroadcastData("groupX", data);
    }

My question is that:

1) What changes should be made in order to use DI and use base Hub class properly?

2) Should I call the hub methods from Controller? Or Hub class (HubX, Y)? I mean that in some examples, hubContext.Clients.All.SendMessageToAll(message) methods are called from the Controller directly while in some of them calls the method in the Hub class i.e. HubX.SendMessageToAll(message);. Any idea about which one is best practice?

3) Should I inherit Hub from Hub or HubBase class?

Note: If you have idea only one of the questions above, it is also ok for me and any help would be appreciated.

Gabriel Luci
  • 38,328
  • 4
  • 55
  • 84

1 Answers1

0

1) Don't use static methods in HubX. Then in your controller, change the type of context you're asking from DI:

public MyController(IHubContext<HubX> hubContext)

2) Use hubContext.Clients.All.SendMessageToAll(message). The other way seems like it's using static methods, which I can see going wrong sometimes. SignalR isn't designed to work that way.

3) You decide. It depends on if you want it to inherit the methods from HubBase or not.

Gabriel Luci
  • 38,328
  • 4
  • 55
  • 84
  • Dear Gabriel, many thanks for your reply. I updated ITypedHubClient and Controller according to your suggestions as shown above. Could you please have a look at and let me know is there any update needed? –  Jul 26 '19 at 06:32
  • Here is my questions: **1)** Is `HubBase : Hub` and `HubX : HubBase` inheritences in HubBase and HubX classes are true? –  Jul 26 '19 at 06:35
  • **2)** In the examples I follow, there is no implementation of `BroadcastData()` method defined in `ITypedHubClient` class. Is there any mistake? If so, should I implement it in `HubBase`? –  Jul 26 '19 at 06:35
  • **3)** How can I use the methods e.g. `SendMessageToAll()` in the `HubBase`? Should I also define them in the `ITypedHubClient` interface and access via that interface? As a result, could you please update your reply by using my code and by defining the missing parts? Thanks in advance for your cooperation. –  Jul 26 '19 at 06:35
  • 1) That's fine, if that's what you want to do. 2) That's up to you. 3) `SendMessageToAll()` is defined in `HubBase`, so there's nothing stopping you from using it in `HubBase`. Just call it: `await SendMessageToAll(something)` – Gabriel Luci Jul 26 '19 at 11:58
  • You still have static methods in `HubX`, which is unecessary. None of those methods should be static. If you remove `static`, you can just call `await Clients.Group(groupName).refreshData(data);` – Gabriel Luci Jul 26 '19 at 11:59
  • Thanks a lot for your help. I think I am really confused with the methods on Client vs Server side calls. So, the approach on the answer of that page is true (regarding to client and server side methods)? https://stackoverflow.com/questions/52717449/call-signalr-method-from-controller-net-core-2-1 –  Jul 26 '19 at 12:43
  • Right. In your case, `ITypedHubClient` defines the methods that the client accepts, and `HubX` and `HubBase` define the methods the server accepts. – Gabriel Luci Jul 26 '19 at 12:46
  • Ahaaa, for this reason the implementation of these methods in ITypedHubClient are in JavaScript side, is that true? If so, I am really surprised, because I asken this question to my self many time :)) In that example, DoSomething() method will be implemented in JavaScript side, true? –  Jul 26 '19 at 12:50
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/197050/discussion-between-hexadecimal-and-gabriel-luci). –  Jul 26 '19 at 12:55