Implementing Real Time Functionality Using SignalR In Dot NET Applications

Picture of Vivasoft Team
Vivasoft Team
Published on
16.07.2024
Time to Read
5 min

[rank_math_breadcrumb]

Real-Time Functionality Using SignalR In Dot NET
Table of Contents

In today’s rapidly evolving digital landscape, users demand seamless and interactive experiences from their applications. Traditional web applications often fall short in providing real-time updates and interactivity, leading developers to seek innovative solutions.

To implement real-time functionalities in .Net applications, there is a popular library which most developers prefer: SignalR.

Understanding SignalR

SignalR is a real-time web application framework built on the ASP.NET Core platform, empowering developers to add real-time functionality to their .NET applications effortlessly.

It allows us to push content from server side to any connected clients as changes happen in real-time. It abstracts away the complexities of building a real-time communication system, allowing developers to focus on delivering engaging user experiences.

In this article, we will cover the followings:

  1. Creating a SignalR hub and testing it
  2. How to create strongly typed hubs

Setting up SignalR in .NET Applications

Integrating SignalR into a .NET application is a straightforward process. To start using SignalR we need to do the followings:

  • Install the SignalR NuGet package
  • Create the hub class
  • Register the SignalR services in Program.cs
  • Map and expose the hub endpoint so clients can connect to it

First, we need to install the Microsoft.AspNetCore.SignalR.Client NuGet package:

install the Microsoft.AspNetCore.SignalR.Client NuGet package

After installing the package, we need to write a SignalR Hub. Central to SignalR’s functionality are hubs, which act as communication endpoints for clients to connect with the server.

Hubs facilitate bi-directional communication, enabling server-to-client and client-to-server communication seamlessly. Developers define hub classes that contain methods invoked by clients and handle incoming messages from clients.

So, Let’s create a SignalRHub by inheriting from the base Hub class:

				
					public class SignalRHub : Hub
{
    public async Task SendMessage(string user, string message)
    {
        await Clients.All.SendAsync("ReceiveMessage", DateTime.Now.ToShortTimeString(), user, message);
    }
}
				
			

There are some useful properties of SignalR Hub:

Clients: The Clients property in SignalR serves as a gateway for server-side code to communicate with connected clients. It provides methods for invoking client-side functions from the server, enabling bi-directional communication. Developers can use the Clients property to send real-time updates, notifications, and data to specific clients or groups of clients.

				
					// Sending a message to a specific client
await Clients.Client(connectionId).SendAsync("ReceiveMessage", message);

// Sending a message to all clients in a group
await Clients.Group(groupName).SendAsync("ReceiveGroupMessage", message);
				
			
  • Groups: SignalR allows clients to be organized into groups, enabling targeted communication with specific subsets of connected clients.

    The Groups property provides methods for managing groups and sending messages to all clients within a particular group. This feature is particularly useful for implementing features like group chat, where messages are shared among members of a specific group
				
					// Adding a client to a group
await Groups.AddToGroupAsync(connectionId, groupName);

// Removing a client from a group
await Groups.RemoveFromGroupAsync(connectionId, groupName);
				
			
  • Context: The Context property encapsulates information about the current SignalR connection, providing access to various contextual data and features. It includes details such as the connection ID, user identity, connection metadata, and connection-specific settings. Developers can leverage the Context property to customize the behavior of SignalR hubs and tailor real-time communication based on the connection context.
				
					// Accessing connection ID
var connectionId = Context.ConnectionId;
// Accessing user identity
var user = Context.User.Identity.Name;
// Accessing connection-specific settings
var queryStringValue = Context.GetHttpContext().Request.Query["key"];
				
			

Now, we need to register the SignalR services in our Program.cs class by calling the AddSignalR() method. We also need to call the MapHub<T> method, where we specify the hub class and the path that clients will use to connect to the hub.

				
					WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
builder.Services.AddSignalR();

WebApplication app = builder.Build();
app.MapHub<SignalRHub>("/signalrHub");
app.Run();
				
			

Testing the SignalRHub

For testing purposes, we have built a simple ASP.NET MVC application with a razor page to send and show real-time messages.

Here, we have two simple input fields: User and Message and a button to send the message to our Hub. First we have established a connection with our Hub. We have disabled the send button until connection is successfully established and initiated.

				
					var connection = new signalR.HubConnectionBuilder().withUrl("/signalrHub").build();
document.getElementById("sendButton").disabled = true;
				
			

Then, we set up an event listener for a “ReceiveMessage” event. When this event occurs, it creates a new list item in the HTML document, populates it with the received message data (including datetime, user, and message content), and then appends it to an existing list of messages. Finally, we applied a specific CSS class to style the message item.

				
					connection.on("ReceiveMessage", function (datetime, user, message) {
    var li = document.createElement("li");
    document.getElementById("messagesList").appendChild(li);
    li.innerHTML = `[${datetime}] <b>${user}:</b><br />${message}`;
    li.className = "list-group-item";
});
				
			

After that, we initiated the connection and if it’s successful then we set the send button enabled to send further messages.

				
					connection.start().then(function () {
    document.getElementById("sendButton").disabled = false;
}).catch(function (err) {
    return console.error(err.toString());
});
				
			

Finally we set up an event listener for a click event on an HTML element with the button Id.

When the button is clicked, the listener executes a function. Within this function: First, It retrieves the values entered in two input fields with IDs “userInput” and “messageInput”, representing the user’s name and message, respectively. Then it uses the invoke() method on the connection object to send a message to the server to be processed and broadcasted to other clients.

The method is invoked with our “SendMessage” Hub method and passes the user’s name and message as parameters. If there’s an error during this invocation, it logs the error message to the console.

				
					document.getElementById("sendButton").addEventListener("click", function (event) {
    var user = document.getElementById("userInput").value;
    var message = document.getElementById("messageInput").value;
    connection.invoke("SendMessage", user, message).catch(function (err) {
        return console.error(err.toString());
    });
    event.preventDefault();
});
				
			
				
					public class SignalRHub : Hub
{
    public async Task SendMessage(string user, string message)
    {
        await Clients.All.SendAsync("ReceiveMessage", DateTime.Now.ToShortTimeString(), user, message);
    }
}
				
			

Strongly Typed Hubs

Messages are sent to connected clients via the SendAsync function by the main Hub class. Unfortunately, specifying which client-side functions to invoke requires the usage of strings, and errors are easily made in this regard. Furthermore, there is no rule dictating which parameters must be used.

To address this, SignalR provides strongly typed hub support.

First, we need to define a client interface, so let’s create a simple ISignalRClient abstraction:

				
					public interface ISignalRClient
{
    Task ReceiveMessage(string user, string message);
}
				
			

The arguments can also be objects. SignalR will take care of serialization on the client side.

After that, we need to update the SignalHub class to inherit from the Hub<T> class to make it strongly typed:

				
					public class SignalRHub : Hub<ISignalRClient>
{
    public async Task SendMessage(string user, string message)
    {
        await Clients.All.ReceiveMessage(user, message);
    }
}
				
			

In this way, we’ll lose access to the SendAsync method. Only defined methods in the client interface will be available.

Sending Server-Side Messages With HubContext

If we can’t send notifications to connected clients from the backend, what good is a NotificationsHub? Not a lot.

We can use the Hub instance’s IHubContext<THub> interface access in our backend code.

For a highly typed hub, we can use IHubContext<THub, TClient>.

This is a basic Minimal API endpoint that uses our strongly typed hub’s IHubContext<SignalRHub, ISignalRClient> to deliver a notice to every client that is connected:

				
					app.MapPost("messages/all", async (
    string user, string message,
    IHubContext<SignalRHub, ISignalRClient> context) =>
{
    await context.Clients.All.ReceiveMessage(user, message);
    return Results.NoContent();
});
				
			

Scaling SignalR Applications

As applications grow in complexity and user base, scaling becomes a crucial consideration. SignalR provides built-in support for scaling out to multiple servers using backplanes such as Azure SignalR Service or Redis. This ensures that real-time communication remains robust and responsive even under heavy load conditions.

Security Considerations

When implementing real-time functionality, security is paramount. SignalR offers various mechanisms for securing connections and authorizing users, including authentication middleware and authorization filters. By enforcing security best practices, developers can safeguard sensitive data and protect their applications from potential threats.

Summary

Including real-time functionality in application allows for more creativity and benefits users. Hire .NET developers to begin developing real-time .

Developers may begin developing real-time.NET apps with SignalR in a matter of minutes.

One idea that we must understand is the Hub class. We don’t need to worry about the message transmission mechanism because SignalR abstracts it away.

Ensure that the authentication on the Hub is enabled and authenticated requests to SignalR hubs are transmitted. By using the user identity to track users connecting to hubs internally, SignalR enables sending them messages.

50+ companies rely on our top 1% talent to scale their dev teams.
Excellence Our minimum bar.
It has become a prerequisite for companies to develop custom software.
We've stopped counting. Over 50 brands count on us.
Our company specializes in software outsourcing and provides robust, scalable, and efficient solutions to clients around the world.
klikit

Chris Withers

CEO & Founder, Klikit

Klikit-logo
Heartfelt appreciation to Vivasoft Limited for believing in my vision. Their talented developers can take any challenges against all odds and helped to bring Klikit into life.appreciation to Vivasoft Limited for believing in my vision. Their talented developers can take any challenges.
Start with a dedicated squad in 7 days

NDA first, transparent rates, agile delivery from day one.

Where We Build the Future
Scale Engineering Without the Overhead

Elastic offshore teams that integrate with your processes and timezone.

Tech Stack
0 +
Blogs You May Love

Don’t let understaffing hold you back. Maximize your team’s performance and reach your business goals with the best IT Staff Augmentation

let's build our future together

Get to Know Us Better

Explore our expertise, projects, and vision.