Realtime webapps in .NET met SignalR
Stuur updates van je ASP.NET Core-server meteen naar elke verbonden browser. We bouwen stap voor stap een kleine realtime chatapp met SignalR.
Bijgewerkt op 1 november 20264 min lezen
Er zijn een paar manieren om een webpagina zichzelf te laten bijwerken. Je kunt een vernieuwknop toevoegen, of de server elke paar seconden pollen met setInterval en fetch. Pollen werkt, maar het verspilt requests en is nooit echt realtime: er zit altijd vertraging tot de volgende controle.
De betere optie is een WebSocket: een verbinding tussen browser en server die open blijft, zodat de server data naar de browser kan sturen op het moment dat er iets gebeurt, zonder dat de browser erom vraagt.
In .NET doe je dat het makkelijkst met SignalR. SignalR is onderdeel van ASP.NET Core en geeft je een eenvoudige API om vanuit je servercode methodes aan te roepen op verbonden clients (en omgekeerd). Het gebruikt WebSockets wanneer die beschikbaar zijn en valt automatisch terug op Server-Sent Events of long polling wanneer dat niet zo is.
Een realtime chat bouwen met SignalR
We bouwen een kleine chatapp waarin elk bericht meteen verschijnt bij iedereen die de pagina open heeft.
Maak in Visual Studio een nieuwe ASP.NET Core Web App (Model-View-Controller) met de naam ChatApp, of gebruik de CLI:
dotnet new mvc -n ChatAppDe SignalR-server zit al in ASP.NET Core, dus je hoeft geen NuGet-package te installeren.
Serverkant
Een hub is de klasse waarmee clients verbinden. Maak een map Hubs met een klasse ChatHub die overerft van Hub:
using Microsoft.AspNetCore.SignalR;
namespace ChatApp.Hubs;
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
{
// Stuur een "ReceiveMessage"-event naar elke verbonden client
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
}Clients kunnen SendMessage aanroepen, en de hub stuurt het bericht door naar alle verbonden clients via het event ReceiveMessage.
Registreer daarna SignalR en de hub in Program.cs:
using ChatApp.Hubs;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
builder.Services.AddSignalR(); // Voeg de SignalR-services toe
var app = builder.Build();
// ... de standaard middleware en routes uit de template ...
app.MapHub<ChatHub>("/chat"); // Clients verbinden met de hub op /chat
app.Run();Clientkant
De browser heeft de SignalR-JavaScriptclient nodig. Klik in Visual Studio met de rechtermuisknop op het project en kies Add > Client-Side Library.... Kies de provider unpkg, zoek naar @microsoft/signalr, kies Choose specific files, selecteer dist/browser/signalr.js en signalr.min.js, en zet de doellocatie op wwwroot/js/signalr/.
Geen Visual Studio? De LibMan-CLI doet hetzelfde:
libman install @microsoft/signalr@latest -p unpkg -d wwwroot/js/signalr --files dist/browser/signalr.js --files dist/browser/signalr.min.jsMaak nu wwwroot/js/chat.js. Het verbindt met de hub, toont binnenkomende berichten en verstuurt nieuwe:
"use strict";
// Verbind met de hub op het pad /chat dat we in Program.cs gemapt hebben
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chat")
.withAutomaticReconnect()
.build();
const sendButton = document.getElementById("sendButton");
sendButton.disabled = true; // Wordt actief zodra we verbonden zijn
// Wordt uitgevoerd telkens de hub een "ReceiveMessage"-event stuurt
connection.on("ReceiveMessage", (user, message) => {
const li = document.createElement("li");
li.textContent = `${user} says: ${message}`; // textContent, zodat berichten geen HTML kunnen injecteren
document.getElementById("messagesList").appendChild(li);
});
sendButton.addEventListener("click", async (event) => {
event.preventDefault();
const user = document.getElementById("userInput").value;
const message = document.getElementById("messageInput").value;
try {
await connection.invoke("SendMessage", user, message);
} catch (err) {
console.error(err);
}
});
async function start() {
try {
await connection.start();
sendButton.disabled = false;
} catch (err) {
console.error(err);
setTimeout(start, 5000); // Probeer opnieuw na 5 seconden
}
}
start();Enkele dingen om op te letten:
withAutomaticReconnect()verbindt vanzelf opnieuw wanneer de verbinding wegvalt, bijvoorbeeld wanneer de server herstart.- De verstuurknop blijft uitgeschakeld tot de verbinding open is, zodat je geen berichten in het niets verstuurt.
- We gebruiken
textContentin plaats vaninnerHTML, zodat niemand HTML of scripts kan injecteren via een chatbericht.
Vervang tot slot de inhoud van Views/Home/Index.cshtml door de chat-UI. Die gebruikt de Bootstrap 5-klassen die bij de template horen, en laadt de scripts alleen op deze pagina:
<div class="card">
<div class="card-header">
<h3>Chat</h3>
</div>
<div class="card-body">
<!-- Binnenkomende berichten komen hier -->
<ul id="messagesList"></ul>
</div>
<div class="card-footer">
<div class="input-group">
<input type="text" id="userInput" class="form-control" placeholder="Username" />
<input type="text" id="messageInput" class="form-control" placeholder="Message" />
<button id="sendButton" class="btn btn-primary">Send</button>
</div>
</div>
</div>
@section Scripts {
<script src="~/js/signalr/dist/browser/signalr.min.js"></script>
<script src="~/js/chat.js"></script>
}Testen
Dat was het! Start de app met dotnet run (of F5) en open hem in twee browsertabbladen. Typ een bericht in het ene tabblad en het verschijnt meteen in allebei:
Hoe verder?
Clients.All is nog maar het begin. Een hub kan ook naar één verbinding sturen (Clients.Client(id)), naar iedereen behalve de verzender (Clients.Others), of naar benoemde groepen (Groups.AddToGroupAsync). Dat is ideaal voor chatrooms of meldingen per gebruiker. Zet [Authorize] op een hub om alleen aangemelde gebruikers toe te laten.
Conclusie
Je weet nu hoe SignalR werkt en hoe je updates realtime van je server naar de browser stuurt. Hetzelfde patroon werkt voor live dashboards, meldingen, multiplayergames en samen bewerken. Lees meer in de officiële SignalR-documentatie van Microsoft.
Veelgestelde vragen
Moet ik een NuGet-package installeren voor SignalR in ASP.NET Core?
Nee. De SignalR-server is onderdeel van het gedeelde ASP.NET Core-framework. Je voegt alleen de JavaScriptclient @microsoft/signalr toe aan de browserkant.
Wat gebeurt er als WebSockets niet beschikbaar zijn?
SignalR valt automatisch terug op Server-Sent Events of long polling, zodat dezelfde code blijft werken.
- .NET
- SignalR
- JavaScript
- ASP.NET Core