Many of you might have heard about ASP.NET Core SignalR, an open-source library to send real-time web-based notifications. This article will help you build or integrate SignalR based notification in your ASP.NET Core web application.
Before we get into detail, let’s first look at what features it provides?
- Handles connection management automatically.
- Sends messages to all connected clients simultaneously. For example, a chat room.
- Allow to send messages to specific clients or groups of clients.
- Scales to handle increasing traffic.
- SignalR for ASP.NET Core supports any server platform that ASP.NET Core supports.
How does it work?
SignalR provides API for creating server-to-client remote procedure calls (RPC) that call JavaScript functions in client browsers (and other client platforms) from server-side .NET code. SignalR also includes API for connection management (for instance, connect and disconnect events), and grouping connections.
Using SignalR you can send broadcast messages to all connected clients simultaneously or target a specific client or a group of clients.
A hub is a pipeline build over connection API that allows your client and server to call methods and communicate with each other. Using hub you can pass strongly typed parameters & enable model binding. SignalR is capable of handling serialization and deserialization of complex objects and arrays.
SignalR supports more than 1 transport techniques for handling real-time communication between client & server.
The interesting fact is, SignalR automatically chooses the best transport technique depending on server & client capabilities.
Example
In this example we will send real-time notification to all online users when a new article is added by the admin. Users will instantly see the newly added article data.
- When a user opens the page, a random number between 1 to 100 will be generated and we will send the generated number to the server to create a new hub connection.
- Server will create a connection and return the new connection id to client hub proxy.
- If the server wants to send the Notification to a user, it will find all the connectionId of a user and send it to the clients (by the connectionId).
We will do the example in two parts
- Send real-time notification to all users
- Send real-time notification to specific user
Let’s start:
1) Send real-time notification to all users
Step 1: Create ASP.NET Core web application.
I have used .NET core 3.1 but you can use a different version of .NET Core as far as it supports SignalR.
Step 2: Install Microsoft.AspNetCore.SignalR.Core from Nuget Package Manager.
Step 3: Create a new folder named “Hubs” and a class named NotificationHub.cs.
using Microsoft.AspNetCore.SignalR; namespace SignalRDemo.Hubs { public class NotificationHub : Hub { } }
Step 4: To register SignalR open Startup.cs file, add below line under ConfigureServices method.
services.AddSignalR();
Step 5: And add below code inside Configure method.
app.UseSignalR(routes => { routes.MapHub<NotificationHub>(“/NotificationHub”); });
Step 7: Create Article.cs class file under Models folder and replace it with below code.
namespace SignalRDemo.Models { public class Article { public string articleHeading { get; set; } public string articleContent { get; set; } public string userId { get; set; } } } “use strict”; var connection = new signalR.HubConnectionBuilder().withUrl(“/NotificationHub”).build(); connection.on(“sendToUser”, (articleHeading, articleContent) => { var heading = document.createElement(“h3”); heading.textContent = articleHeading; var p = document.createElement(“p”); p.innerText = articleContent; var div = document.createElement(“div”); div.appendChild(heading); div.appendChild(p); document.getElementById(“articleList”).appendChild(div); }); connection.start().catch(function (err) { return console.error(err.toString()); });
Step 9: Open Index.cshtm l file and replace it with below code.
Step 10: Create AdminController.cs inside controller folder and add below code.
using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using SignalRDemo.Hubs; using Microsoft.AspNetCore.SignalR;
Step 11: Inside Views -> Admin -> Index.cshtml file add below code.
Step 12: You can add some style to make it look good.
#articleList div { text-align: left; margin-bottom: 20px; border-bottom: 1px solid #ccc; } #articleList div h3 { margin-bottom:5px; } #articleList div p { margin-bottom:5px; }
2) Send real-time notification to specific user
Now, if you want to send notification to any specific user you have to make some tweaks in the code. And use Clients. Client method & pass connectionId of a specific user whom you want to send notification.
using System.Collections.Generic; namespace NotificationMvcDemo.Interface { public interface IUserConnectionManager { void KeepUserConnection(string userId, string connectionId); void RemoveUserConnection(string connectionId); List<string> GetUserConnections(string userId); } } using Microsoft.AspNetCore.SignalR; using System; using SignalRDemo.Interface; using System.Threading.Tasks; namespace SignalRDemo.Hubs { public class NotificationUserHub : Hub { private readonly IUserConnectionManager _userConnectionManager; public NotificationUserHub(IUserConnectionManager userConnectionManager) { _userConnectionManager = userConnectionManager; } public string GetConnectionId() { var httpContext = this.Context.GetHttpContext(); var userId = httpContext.Request.Query[“userId”]; _userConnectionManager.KeepUserConnection(userId, Context.ConnectionId); return Context.ConnectionId; } //Called when a connection with the hub is terminated. public async override Task OnDisconnectedAsync(Exception exception) { //get the connectionId var connectionId = Context.ConnectionId; _userConnectionManager.RemoveUserConnection(connectionId); var value = await Task.FromResult(0); } } }
Step 3: Create UserConnectionManager.cs class under Interface folder and add below code.
Step 4: Go to Startup.cs file and add below line of code insider ConfigureServices method.
services.AddSingleton<IUserConnectionManager, UserConnectionManager>(); And go to Configure method and replace UseSignalR method with below line of code app.UseSignalR(routes => { routes.MapHub<NotificationHub>(“/NotificationHub”); routes.MapHub<NotificationUserHub>(“/NotificationUserHub”); });
Step 5: Go to AdminController.cs file and add below line of code with other declaration at the top.
private readonly IHubContext<NotificationUserHub> _notificationUserHubContext; private readonly IUserConnectionManager _userConnectionManager;
Step 6: In the AdminController.cs file replace the constructor method code with the code below.
public AdminController(IHubContext<NotificationHub> notificationHubContext, IHubContext<NotificationUserHub> notificationUserHubContext, IUserConnectionManager userConnectionManager) { _notificationHubContext = notificationHubContext; _notificationUserHubContext = notificationUserHubContext; _userConnectionManager = userConnectionManager; }
Step 7: We will be using the same Article class model. Open Article.cs file and add below line of code.
public string userId { get; set; }
Step 8: Go to AdminContrller.cs file and add the new method which will send notification to a specific user.
[HttpPost] public async Task<ActionResult> SendToSpecificUser(Article model) { var connections = _userConnectionManager.GetUserConnections(model.userId); if (connections != null && connections.Count > 0) { foreach (var connectionId in connections) { await _notificationUserHubContext.Clients.Client(connectionId).SendAsync(“sendToUser”, model.articleHeading, model.articleContent); } } return View(); }
Add <p> tag in which we will print generate user id.
In the same file add the below line of code at the bottom of the <script> tag.
document.getElementById(“user”).innerHTML = “UserId: “ + userId;
“use strict”; var connection = new signalR.HubConnectionBuilder().withUrl(“/NotificationUserHub?userId=” + userId).build(); connection.on(“sendToUser”, (articleHeading, articleContent) => { var heading = document.createElement(“h3”); heading.textContent = articleHeading; var p = document.createElement(“p”); p.innerText = articleContent; var div = document.createElement(“div”); div.appendChild(heading); div.appendChild(p); document.getElementById(“articleList”).appendChild(div); }); connection.start().catch(function (err) { return console.error(err.toString()); }).then(function () { document.getElementById(“user”).innerHTML = “UserId: “ + userId; connection.invoke(‘GetConnectionId’).then(function (connectionId) { document.getElementById(‘signalRConnectionId’).innerHTML=connectionId; }) });
Now you can input the userId and send notification to the user. As you can see in the below screenshots only the user with given id will receive the notification.
Conclusion
Done. We hope that article above help to explain more about SignalR Asp.net Core. If you are interested with Asp.net core, then you can always read our blog.
Javier is Content Specialist and also .NET developer. He writes helpful guides and articles, assist with other marketing and .NET community work