SignalR Real-Time Communication, Hubs & Chat Masterclass

โšก C# 12 & .NET 8 ๐ŸŸข Chapter 45 of 35 ๐Ÿ“‚ Phase 16: Advanced .NET ๐Ÿ“… 2026 Edition
๐Ÿ“Œ Covered in this chapter: SignalR Architecture ยท Hub ยท Clients.All ยท Clients.Group ยท Groups ยท Broadcasting ยท JavaScript Client ยท Chat App ยท Live Notifications ยท WebSockets ยท Reconnect

Welcome to Phase 16 (Chapter 45): ASP.NET Core SignalR โ€” Real-Time Hubs, Chat & Live Notifications Masterclass! SignalR is Microsoft's real-time communication library for ASP.NET Core that enables servers to push data to connected clients instantly โ€” without clients polling. Built on WebSockets (with SSE and Long Polling fallbacks), SignalR powers chat apps, live dashboards, stock tickers, collaborative editing, and notification systems.

1SignalR Architecture & How It Works
SignalR Communication Model: Client Browser โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ WebSocket Connection โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ ASP.NET Core Server โ”‚ โ”‚ โ”‚ โ”€โ”€ hub.SendMessage("Hello") โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€> โ”‚ โ”‚ Hub.ReceiveMessage() โ”‚ <โ”€โ”€ Clients.All.SendAsync("ReceiveMessage", msg) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ All Clients receive message instantly!
2Creating a SignalR Hub
C# โ€” SignalR Chat Hub โ–ถ Run in Compiler
using Microsoft.AspNetCore.SignalR;

public class ChatHub : Hub
{
    // Called by a client when they send a message
    public async Task SendMessage(string user, string message)
    {
        // Broadcast to ALL connected clients
        await Clients.All.SendAsync("ReceiveMessage", user, message);
    }

    // Join a specific group (chat room)
    public async Task JoinRoom(string roomName)
    {
        await Groups.AddToGroupAsync(Context.ConnectionId, roomName);
        await Clients.Group(roomName).SendAsync("ReceiveMessage", "System",
            Context.ConnectionId + " joined " + roomName);
    }

    // Send to specific group only
    public async Task SendToRoom(string roomName, string user, string message)
    {
        await Clients.Group(roomName).SendAsync("ReceiveMessage", user, message);
    }

    // Lifecycle events
    public override async Task OnConnectedAsync()
    {
        Console.WriteLine("Client connected: " + Context.ConnectionId);
        await base.OnConnectedAsync();
    }

    public override async Task OnDisconnectedAsync(Exception? exception)
    {
        Console.WriteLine("Client disconnected: " + Context.ConnectionId);
        await base.OnDisconnectedAsync(exception);
    }
}

// Program.cs โ€” Register SignalR
builder.Services.AddSignalR();
app.MapHub<ChatHub>("/hubs/chat");
3JavaScript Client & Live Dashboard
JavaScript โ€” SignalR Chat Client
// Install: npm install @microsoft/signalr
import * as signalR from "@microsoft/signalr";

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/hubs/chat")
    .withAutomaticReconnect()
    .build();

// Listen for messages from server
connection.on("ReceiveMessage", (user, message) => {
    const li = document.createElement("li");
    li.textContent = user + ": " + message;
    document.getElementById("messagesList").appendChild(li);
});

// Start connection
await connection.start();
console.log("SignalR connected!");

// Send message
document.getElementById("sendBtn").addEventListener("click", async () => {
    const user = document.getElementById("userInput").value;
    const message = document.getElementById("messageInput").value;
    await connection.invoke("SendMessage", user, message);
});
4Technical FAQs

Q1: Does SignalR always use WebSockets?

SignalR automatically negotiates the best transport available: WebSockets (preferred, full-duplex, lowest latency), Server-Sent Events (server-to-client only), or Long Polling (HTTP fallback for restrictive environments). You can force WebSockets-only via configuration.

Q2: How does SignalR scale across multiple servers?

Use Azure SignalR Service or a Redis backplane to coordinate messages across multiple server instances. Without a backplane, clients connected to different server pods won't receive each other's messages.