- Home
- .NET tutorials
- Add a SignalR hub to ASP.NET Core & connect using JavaScript
Add a SignalR hub to ASP.NET Core & connect using JavaScript
Published: Monday 22 July 2024
SignalR is a powerful software library that allows you to send and receive messages from a client and server in real-time.
Create a SignalR hub
The first steps involve creating a SignalR hub.
ChatHub. To make this a SignalR hub, we need to inherit the Hub class which is imported from the Microsoft.AspNetCore.SignalR namespace.
Hub class has a virtual method called OnConnectedAsync. We are going to override this and send a messages to all connected clients when a new client has connected.
ReceiveMessage and we'll pass in a parameter with the message. The client will listen out for this method to be invoked.
SendMessage method. This will be invoked from the client and it will send a message back to that particular client saying that the message has been received.
// ChatHub.cs
using Microsoft.AspNetCore.SignalR;
public class ChatHub : Hub
{
public override async Task OnConnectedAsync()
{
await Clients.All.SendAsync("ReceiveMessage", $"Received the message: Another connection has been added.");
}
public async Task SendMessage(string message)
{
await Clients.Client(Context.ConnectionId).SendAsync("ReceiveMessage", $"Received the message: {message}");
}
}
Sending messages to clients
If we want to send a message to all clients, we can call Clients.All and then the SendAsync method to invoke a method with parameters.
Clients.Client.
Clients.Client(Context.ConnectionId), followed by the SendAsync method and then the method and parameters that we wish to invoke.
Add SignalR to services and map the hub
SignalR needs to be added to the services in the ASP.NET Core app. As well as that, the SignalR hub needs to be mapped with an endpoint.
Program.cs and we call the AddSignalR extension method that is part of the IServiceCollection instance.
MapHub extension method from the WebApplication instance. We pass in the SignalR hub as the generic type. In this instance, that would be ChatHub. Then it needs to be mapped to a pattern or endpoint. This will be specified as /chathub and will be used to connect to the SignalR hub from the client.
// Program.cs
using RoundTheCode.SignalR.Hubs;
var builder = WebApplication.CreateBuilder(args);
...
builder.Services.AddSignalR(); // Adds SignalR to the IServiceCollection instance
var app = builder.Build();
...
app.MapHub<ChatHub>("/chathub"); // Maps the ChatHub with a endpoint of /chathub.
...
app.Run();
Front-end set up
We have an HTML page that will be responsible for sending and receiving messages back from the server.
Message. As well as that, there is a Send Message button to send the message to the server which has an ID of SendMessage.
<ul> tag that will store all the messages and has an ID of Messages.
signalr.js) which we will use to code the SignalR functionality.
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css"
>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-12">
<input id="Message" value="" />
<button class="btn btn-primary" id="SendMessage"
type="button">Send message</button>
</div>
</div>
<div class="row">
<div class="col-12">
<ul id="Messages">
</ul>
</div>
</div>
</div>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/6.0.1/signalr.js">
</script>
<script src="/js/signalr.js"></script>
</body>
</html>
Send a message using SignalR
Connecting to SignalR hub
As stated, the index.html page has a reference to the signalr.js JavaScript file. We'll use this JavaScript file to connect to the SignalR hub.
signalR.HubConnectionBuilder and specify a URL. This will be set as /chathub so it's the same URL that we mapped the SignalR hub in the ASP.NET Core app.
start method that is in the connection instance.
onclose method in the connection instance, and restart it from there.
// signalr.js
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.configureLogging(signalR.LogLevel.Information)
.build();
var Start = async () => {
try {
await connection.start();
console.log("SignalR Connected.");
} catch (err) {
console.log(err);
setTimeout(Start, 5000);
}
};
// Start the connection.
Start();
connection.onclose(async () => {
await Start();
});
A message stating SignalR Connected should be logged to the console application. If it doesn't, the client has been unable to connect to SignalR meaning that something is not set up correctly.
Sending a message to the SignalR hub
With the connection established, we can now send a message to the SignalR hub.
connection instance and call the invoke method. The invoke method allows you to pass in the method name as a parameter, followed by any other parameters for that method.
ChatHub class, we created the SendMessage method:
// ChatHub.cs
public class ChatHub : Hub
{
...
public async Task SendMessage(string message)
{
await Clients.Client(Context.ConnectionId).SendAsync("ReceiveMessage", $"Received the message: {message}");
}
}
We are now going to invoke this method by calling connection.invoke, adding SendMessage as the method name and the message we inputted into the input box as the message.
SendMessage ID element in JavaScript and add a click listener. We get the Message ID element which is the input box and check it has a value. If it does, we send the message.
// signalr.js
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.configureLogging(signalR.LogLevel.Information)
.build();
var Start = async () => {
try {
await connection.start();
console.log("SignalR Connected.");
} catch (err) {
console.log(err);
setTimeout(Start, 5000);
}
};
// Start the connection.
Start();
connection.onclose(async () => {
await Start();
});
// Sends the message to SignalR
var SendMessage = async (message) => {
await connection.invoke("SendMessage", message);
}
// Sends the message when the SendMessage ID element has been clicked
document.getElementById('SendMessage').addEventListener('click', async () => {
var message = document.getElementById('Message');
if (message && message.value) {
await SendMessage(message.value);
message.value = '';
}
});
Receiving a message back from the server
We also want to be able to receive a message back from the server.
ChatHub class, we called SendAsync("ReceiveMessage", message) which invokes the ReceiveMessage method to the clients specified. We need to set up the client so it can listen out for calls from the ReceiveMessage method.
on method in the connection instance, specifying the method name and any parameters we are expecting.
li element and add the message as the inner text. Then we append the li element to the Messages ID element which adds it as a bullet point.
// signalr.js
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.configureLogging(signalR.LogLevel.Information)
.build();
var Start = async () => {
try {
await connection.start();
console.log("SignalR Connected.");
} catch (err) {
console.log(err);
setTimeout(Start, 5000);
}
};
// Start the connection.
Start();
connection.onclose(async () => {
await Start();
});
var SendMessage = async (message) => {
await connection.invoke("SendMessage", message);
}
document.getElementById('SendMessage').addEventListener('click', async () => {
var message = document.getElementById('Message');
if (message && message.value) {
await SendMessage(message.value);
message.value = '';
}
});
connection.on("ReceiveMessage", (message) => {
var messages = document.getElementById('Messages');
if (messages) {
var bulletPoint = document.createElement('li');
bulletPoint.innerText = message;
messages.appendChild(bulletPoint);
}
});
Watch the video
Watch the video where we show you how to create a SignalR hub, add it to ASP.NET Core and connect to it from the client so we can send and receive messages.
Related tutorials