CHAPTER 1
The ASP.NET Core SignalR library is open source and allows developers to simplify adding real-time web functionality to applications. This means that the server-side code can instantly push content to connected clients.
Examples of applications that would be a good fit for SignalR include:
In essence, the SignalR API allows server-side code to call JavaScript functions on connected clients via remote procedure calls (RPCs).
SignalR for ASP.NET Core automatically takes care of connection management. If you think of a chat room example, SignalR can send messages to all connected clients at the same time. It can also send messages to a specific client or group of clients.
Later on, you will see how this is done when we look at the IHubCallerClients interface properties and methods.
SignalR for ASP.NET Core can automatically scale to allow it to handle increasing traffic.
Note: You can find the SignalR repository on GitHub.
To handle real-time communication, SignalR supports:
These are called transports. As shown in Figure 1, SignalR lies on top of the lower-level transports.

Figure 1: SignalR Layer and Transports Layer
Transports allow developers to focus on the business process instead of how the messages are sent (or deciding what transport to use). SignalR can dynamically evaluate the supported transports. In other words, SignalR will automatically choose which transport method is best suited, based on the capabilities of the client and server.

Figure 2: SignalR Transports
This can be illustrated as seen in Figure 2. If WebSockets (the most efficient of the transports) are not supported by the server or browser, SignalR will fall back on Server-Sent Events. If Server-Sent Events are not supported, SignalR will fall back on Long Polling.
Note: According to the Internet Engineering Task Force (IETF) Internet Standards track document, the WebSocket protocol enables two-way, real-time communication between clients and servers in web-based applications.
When SignalR establishes a connection, it will start sending keep-alive messages to verify that the connection is still alive. If the connection is not alive, SignalR will throw an exception.
Referring back to Figure 1, you will remember that SignalR lies on top of the transports. This allows developers to work in a consistent manner, regardless of which transport SignalR is using.
Hubs are used by SignalR to communicate between servers and clients. Later in this book, you will create a ChatHub class that inherits from the SignalR Hub class. The hub allows a client and server to call methods on each other.

Figure 3: Hub Messaging All Clients
Inside the methods of this Hub class, you can call a method on all the connected clients, as seen in Figure 3.

Figure 4: Hub Messaging a Single Client
The hub can also call a method on a specific client, as illustrated in Figure 4.

Figure 5: Hub Messaging a Group of Clients
The hub can also call a method on a group of clients, as illustrated in Figure 5.

Figure 6: Client Calling Hub Method
Additionally, the client can call a method on the hub, as illustrated in Figure 6.
You will see the code in action later in this book, but I want to briefly discuss the configuration of SignalR hubs.
Note: In ASP.NET Core, the Startup class configures services, as well as the application’s request pipeline. To configure these services, you must register them in the ConfigureServices method. Registered services are then used throughout the app via dependency injection.
We configure the SignalR middleware by registering the following service in the ConfigureServices method of the Startup class.
Code Listing 1
services.AddSignalR(); |
We then need to set up the SignalR routes by calling endpoints.MapHub in the Configure method of the Startup class.
Code Listing 2
app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); endpoints.MapHub<ChatHub>("/chatHub"); }); |
The Hub class also has a Context property containing the following properties, which provide information about the connection:
The Context also contains an Abort method, as well as a GetHttpContext extension method. The HubCallerContext abstract class metadata is shown in Code Listing 3.
Code Listing 3
namespace Microsoft.AspNetCore.SignalR { // // Summary: // A context abstraction for accessing information about the hub // caller connection. public abstract class HubCallerContext { protected HubCallerContext(); // // Summary: // Gets a System.Threading.CancellationToken that notifies when // the connection is // aborted. public abstract CancellationToken ConnectionAborted { get; } // // Summary: // Gets the connection ID. public abstract string ConnectionId { get; } // // Summary: // Gets the collection of HTTP features available on the connection. public abstract IFeatureCollection Features { get; } // // Summary: // Gets a key/value collection that can be used to share data within // the scope of // this connection. public abstract IDictionary<object, object> Items { get; } // // Summary: // Gets the user. public abstract ClaimsPrincipal User { get; } // // Summary: // Gets the user identifier. public abstract string UserIdentifier { get; } // // Summary: // Aborts the connection. public abstract void Abort(); } } |
The GetHttpContext method signature metadata is shown in Code Listing 4.
Code Listing 4
namespace Microsoft.AspNetCore.SignalR { // // Summary: // Extension methods for accessing Microsoft.AspNetCore.Http.HttpContext // from a hub context. public static class GetHttpContextExtensions { // // Summary: // Gets Microsoft.AspNetCore.Http.HttpContext from the specified // connection, or // null if the connection is not associated with an HTTP request. // // Parameters: // connection: // The connection. // // Returns: // The Microsoft.AspNetCore.Http.HttpContext for the connection, // or null if the // connection is not associated with an HTTP request. public static HttpContext GetHttpContext(this HubCallerContext connection); // // Summary: // Gets Microsoft.AspNetCore.Http.HttpContext from the specified // connection, or // null if the connection is not associated with an HTTP request. // // Parameters: // connection: // The connection. // // Returns: // The Microsoft.AspNetCore.Http.HttpContext for the connection, // or null if the // connection is not associated with an HTTP request. public static HttpContext GetHttpContext(this HubConnectionContext connection); } } |
The Hub class has a Clients property, but we will have a look at this in more detail when we create our real-time chat application.
One thing to note is that hubs are impermanent, which is to say that they only last for a short time. Because hubs are transient, you should not store state in a property on the hub class. This is because every hub method call is executed on a new instance of the hub.
When we create our ChatHub class later on, you will see that we use the syntactically required await keyword when calling Clients.All.SendAsync. This is because the SendAsync method could potentially fail if the hub method completes before the SendAsync finishes.