Setting up SignalR Hub
Explore how to set up a SignalR Hub in an ASP.NET Core project by creating the Hub class, adding essential methods like BroadcastMessage, and enabling the Hub endpoint. Learn the role of key members such as Clients, Groups, and Context to manage connections and broadcast messages effectively.
Overview
The server-side SignalR components center around the so-called Hub. SignalR Hub is equivalent to MVC or Web API controller. It is identical to gRPC (Remote Procedure Calls) service implementation. It’s a class with a collection of methods that SignalR clients will be able to trigger remotely.
We’ll add a basic example of a Hub to our project and register all necessary dependencies. Then, we’ll go through its structure in a little more detail.
Adding SignalR Hub to the project
We’ll follow similar conventions to MVC. As we have Models, Views, and Controllers folders inside the SignalRServer project, we will add another folder and call it Hubs, then we’ll create a LearningHub.cs file inside this folder.
-LearningSignalR-DotnetClient-DotnetClient.csproj-Program.cs
Next, we'll populate the LearningHub.cs file with the following content:
Note: You can use the terminal below for this task and use the
nanocommand for file editing.
SignalR Hub overview
So, let’s go through the structure of the class. This is a basic example, so don’t worry, we won’t be overwhelmed with the information.
Add the Hubclass
First, a class that we want to use as a SignalR Hub needs to inherit from the Hub class, which is a part of Microsoft.AspNetCore.SignalR namespace. This namespace is included in the standard ASP.NET Core libraries, so we won’t have to add any external references. But we still need to reference this namespace somewhere. We can either do it in the file containing the class, as we've done in the above example, or we can just add the using statement anywhere in our application and prepend the global keyword to make it available everywhere within the project. There's no difference between these two ways of referencing namespaces. we can choose either, depending on our personal preferences or any specific guidelines that we follow.
The BroadcastMessage method
Inside the hub, we have the BroadcastMessage method that accepts a string parameter. This is an example of a method that clients will be able to call once they are connected to the Hub. There’s nothing special about this method other than it needs to return a Task. It can have any parameters of any data type. The messages are sent and received in the form of JSON, so any data that gets transferred can be easily deserialized either into basic data types, like string or int, or more complex types, like class or struct.
There’s a limit to how many parameters we can have. But the number is reasonably large, so as long as we write clean code and follow best practices, we shouldn’t worry about running out of available parameters.
So, the BroadcastMessage method receives a string message from a client. Then, inside the method, this message gets re-sent to all clients, including the one that has sent it. Sending a message to any entity that has tuned in is known as broadcasting. And this is precisely why the method is called BroadcastMessage.
But how does the Hub know what clients are connected to it? Well, that’s easy. The base Hub class has a property called Clients. This property has the details of all the connected clients. Plus, we can use this property to choose which clients to send the message to.
In our case, to make things as simple as possible, we’re choosing to send the message to all clients. We do so by accessing All property. But there are multiple ways of selecting specific clients to send the message to.
The SendAsync method
To actually send the message and trigger a specific event in the client code, we call the SendAsync method. The first parameter of this method is the event name in the client code.
Note: The spelling has to be exactly the same as it’s spelled on the client. Otherwise, the event won’t be triggered. The other parameters are the input parameters for the event.
The OnConnectedAsync and OnDisconnectedAsync methods
Next, we have overrides of the OnConnectedAsync and the OnDisconnectedAsync methods from the original Hub class. In our example, we aren’t doing anything with them. But these are the methods that get triggered when a client establishes a connection or disconnects. Because disconnection can happen due to an error, the OnDisconnectedAsync methods also have a nullable Exception parameter.
More Hub class members
There are also some other public members of the Hub class that we haven’t covered.
- There is a
Groupsproperty, which allows us to assign individual clients to groups and then broadcast messages to the members of a particular group. - There is also the
Contextproperty, which contains information about the current session. For example, we can extract a unique client identifier from this property, which gets auto-generated when the client connects and remains constant until the client disconnects.Contextproperty is conceptually similar toHttpContextfrom Web API controllers.
Note: One important thing to remember about a SignalR Hub is that its lifetime is restricted to a single call. So, don’t store any durable data in it. It will all disappear once the next call is executed.
This completes a basic overview of SignalR Hub. Now, we need to enable it, so our clients can actually access it.
Enabling SignalR Hub endpoint
Enabling the SignalR Hub is simple. All we have to do is add a couple of lines to our Program.cs file.
-SignalRServer-Models-Views-Controllers-Hubs-Program.cs
Step 1: First, we'll need to reference the Hub namespace by adding this using statement to the file:
using SignalRServer.Hubs
We can prepend it with a global keyword to make it universally accessible to all files, so we won’t have to insert the using statement again.
Step 2: We'll need to add the following line just before app variable gets instantiated:
builder.Services.AddSignalR();
Step 3: Finally, we need to add the following line before Run method is called on the app variable:
app.MapHub<LearningHub>("/learningHub");
In this line, we've mapped our SignalR Hub to a specific path in the URL. So, a client is now able to register with the Hub by submitting an HTTP request to the {Base URL}/learningHub address. The initial request is made via the standard HTTP protocol. But then, if the protocol needs to change (for example, to WS, which represents WebSocket), this will happen under the hood. As developers, we won’t have to worry about it.
That’s it. Our Hub is now registered, and our SignalR server is ready to accept client connections. However, we can apply one additional modification to the Hub to minimize the risk of misspelling the client event names.
You can perform the above changes using the given terminal in the code already added on the backend.