CHAPTER 8
There is a slight drawback to using SendAsync in the hub. This is a bug that can easily slip in and cause a lot of frustration. You may have noticed it way back in Code Listing 5, when we created the hub. Have a look at Code Listing 15.
Code Listing 15
using Microsoft.AspNetCore.SignalR; using System.Threading.Tasks; namespace realtimechat.Hubs { public class ChatHub : Hub { public async Task MessageSender(string user, string message) { await Clients.All.SendAsync("MessageReciever", user, message); } } } |
Compare this to Code Listing 16.
Code Listing 16
using Microsoft.AspNetCore.SignalR; using System.Threading.Tasks; namespace realtimechat.Hubs { public class ChatHub : Hub { public async Task MessageSender(string user, string message) { await Clients.All.SendAsync("MessageReceiver", user, message); } } } |
Do you see the issue? The method being specified in Code Listing 15 is spelled incorrectly. Instead of MessageReceiver, the developer typed in MessageReciever. It’s an easy mistake to make because the SendAsync method relies on a string to specify the client method name to be called. Compounding this issue, the fact that this is a misspelled string leaves your application open to runtime errors, which aren’t caught at compile time.
The solution to this is to use strongly typed hubs. This means we strongly type the Hub with Hub<T>. To accomplish this, we need to extract the ChatHub client method to an interface. We will call this interface IChatClient.
Right-click your Hubs folder in your solution and add a new interface called IChatClient. When you have added your interface, your solution should look like Figure 30.

Figure 30: IChatClient Interface Added
To this interface, add the following code.
Code Listing 17
|
namespace realtimechat.Hubs { public interface IChatClient { Task MessageReceiver(string user, string message); } } |
Now go to your ChatHub class and modify your code to use Hub<T> where T is your IChatClient interface. Replace the SendAsync method to use the method defined in your IChatClient interface. After completing all this, your ChatHub code will look like Code Listing 18.
Code Listing 18
using Microsoft.AspNetCore.SignalR; using System.Threading.Tasks; namespace realtimechat.Hubs { public class ChatHub : Hub<IChatClient> { public async Task MessageSender(string user, string message) { await Clients.All.MessageReceiver(user, message); } } } |
We can see that by using Hub<IChatClient>, we allow compile-time checking of the client methods. This is because the Hub<T> can only provide access to the methods as explicitly defined in the IChatClient interface.