SignalR Basics

Back

Loading concept...

🚀 SignalR Basics: Real-Time Magic in ASP.NET

Imagine you’re at a party. Instead of everyone constantly asking “Any news? Any news?” the DJ just announces things when they happen. That’s SignalR!


🎯 What is SignalR?

SignalR is like a magical walkie-talkie for your web apps.

In normal websites, your browser has to keep asking the server: “Got anything new for me?” This is like a child in the backseat asking “Are we there yet?” every 5 seconds. Exhausting!

SignalR flips this around. The server can just tell your browser when something happens. No more asking. The server shouts, and everyone listening hears it instantly.

Why Does This Matter?

Old Way (Polling) SignalR Way (Real-Time)
Browser asks every few seconds Server tells you immediately
Wastes resources Super efficient
Delays of seconds Instant updates
Like checking mailbox 100 times Like getting a phone call

Real-Life SignalR Examples

  • 💬 Chat apps – Messages appear instantly
  • 📊 Live dashboards – Numbers update in real-time
  • 🎮 Multiplayer games – All players see the same thing
  • 📢 Notifications – Alerts pop up the moment something happens
// This one line enables the magic!
builder.Services.AddSignalR();

🏠 SignalR Hubs: The Central Meeting Room

Think of a Hub as a clubhouse where everyone gathers.

A Hub is a special class on your server. It’s the “central station” where:

  • Clients (browsers) connect
  • Messages get sent and received
  • The magic happens!

Creating Your First Hub

// ChatHub.cs
public class ChatHub : Hub
{
    // Methods go here
    // Clients can call these!
}

That’s it! You just created a meeting room. Now clients can join and talk.

Mapping Your Hub

// Program.cs
app.MapHub<ChatHub>("/chathub");

This says: “Hey, anyone who goes to /chathub can join our ChatHub meeting room!”

graph TD A["Your App"] -->|MapHub| B["ChatHub"] C["Browser 1"] -->|connects| B D["Browser 2"] -->|connects| B E["Browser 3"] -->|connects| B

📞 Hub Methods: The Conversations

Hub methods are like different phone extensions at a company.

You call a specific extension (method) to do a specific thing. Clients can call these methods from their browsers!

Example: A Simple Chat Method

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

Breaking It Down

Part What It Does
SendMessage The method clients can call
user, message Data being sent
Clients.All Send to everyone connected
SendAsync The actual sending
"ReceiveMessage" What clients listen for

The Client Side (JavaScript)

// Calling the hub method
connection.invoke("SendMessage",
    "Bob",
    "Hello everyone!");

// Listening for responses
connection.on("ReceiveMessage",
    (user, msg) => {
        console.log(`${user}: ${msg}`);
    });

🔌 Client Connections: Joining the Party

Every browser that connects gets a unique ID, like a wristband at a concert.

When someone connects, SignalR gives them a ConnectionId. This is their unique identity.

Connection Lifecycle

graph TD A["Client Opens Page"] -->|Handshake| B["Connection Established"] B --> C["ConnectionId Assigned"] C --> D["Client Can Send/Receive"] D -->|User leaves| E["OnDisconnectedAsync"]

Handling Connections in Your Hub

public class ChatHub : Hub
{
    public override async Task OnConnectedAsync()
    {
        // Someone just joined!
        string id = Context.ConnectionId;
        await Clients.All.SendAsync(
            "UserJoined", id);
        await base.OnConnectedAsync();
    }

    public override async Task OnDisconnectedAsync(
        Exception? ex)
    {
        // Someone left!
        await Clients.All.SendAsync(
            "UserLeft",
            Context.ConnectionId);
        await base.OnDisconnectedAsync(ex);
    }
}

Key Properties You Get

Property What It Is
Context.ConnectionId Unique ID for this client
Context.User The authenticated user
Context.Items Store data for this connection

👥 Groups: Private Rooms Within the Party

Groups are like chat rooms inside the main hall.

Instead of shouting to everyone, you can whisper to just the people in a specific group.

Adding Someone to a Group

public async Task JoinRoom(string roomName)
{
    // Add this connection to a group
    await Groups.AddToGroupAsync(
        Context.ConnectionId,
        roomName);

    // Tell the room someone joined
    await Clients.Group(roomName).SendAsync(
        "UserJoinedRoom",
        Context.ConnectionId);
}

Sending to a Group

public async Task SendToRoom(
    string room,
    string message)
{
    // Only people in this room hear it
    await Clients.Group(room).SendAsync(
        "RoomMessage",
        message);
}

Leaving a Group

public async Task LeaveRoom(string roomName)
{
    await Groups.RemoveFromGroupAsync(
        Context.ConnectionId,
        roomName);
}
graph TD H["ChatHub"] --> G1["Group: Sports"] H --> G2["Group: Music"] H --> G3["Group: Gaming"] G1 --> U1["User A"] G1 --> U2["User B"] G2 --> U3["User C"] G2 --> U4["User D"] G3 --> U1 G3 --> U4

Notice: Users can be in multiple groups!


🌊 Streaming: The River of Data

Streaming is like watching a live video instead of waiting for the whole thing to download.

Sometimes you don’t want to send all data at once. You want to send it piece by piece, like a video stream.

Server-to-Client Streaming

public async IAsyncEnumerable<int> Counter(
    int count,
    int delay)
{
    for (var i = 0; i < count; i++)
    {
        yield return i;
        await Task.Delay(delay);
    }
}

Client Receiving the Stream

connection.stream("Counter", 10, 500)
    .subscribe({
        next: (item) => {
            console.log("Got:", item);
        },
        complete: () => {
            console.log("Stream done!");
        },
        error: (err) => {
            console.error(err);
        }
    });

Client-to-Server Streaming

The client can also stream data TO the server!

public async Task UploadStream(
    ChannelReader<string> stream)
{
    while (await stream.WaitToReadAsync())
    {
        while (stream.TryRead(out var item))
        {
            // Process each item
            Console.WriteLine(item);
        }
    }
}

When to Use Streaming?

Use Case Why Streaming?
Live charts Data keeps flowing
File uploads Send chunks
Progress updates Piece by piece
Game positions Constant updates

🔄 Automatic Reconnection: Never Miss a Beat

Life happens. WiFi drops. Tunnels exist. SignalR handles it!

By default, if the connection drops, SignalR can automatically try to reconnect. Your users won’t even notice the blip!

Enabling Auto-Reconnect (Client)

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

Custom Retry Delays

.withAutomaticReconnect([0, 2000, 10000, 30000])
// Retry immediately, then 2s, 10s, 30s

Handling Reconnection Events

connection.onreconnecting(error => {
    console.log("Trying to reconnect...");
    // Show "reconnecting" message
});

connection.onreconnected(connectionId => {
    console.log("We're back! ID:", connectionId);
    // Rejoin groups, refresh data
});

connection.onclose(error => {
    console.log("Connection closed.");
    // Show "disconnected" message
});

The Reconnection Flow

graph TD A["Connected"] -->|Connection Lost| B["Reconnecting"] B -->|Success| C["Reconnected"] B -->|Failed| D["Try Again"] D -->|Success| C D -->|Max Retries| E["Closed"] C --> A

Pro Tip: Rejoin Groups After Reconnect

When you reconnect, you get a NEW ConnectionId. That means you’re not in your old groups anymore!

connection.onreconnected(async () => {
    // Rejoin your rooms
    await connection.invoke("JoinRoom", "Gaming");
});

🎁 Putting It All Together

Here’s a complete mini-example:

Server (ChatHub.cs)

public class ChatHub : Hub
{
    public async Task JoinRoom(string room)
    {
        await Groups.AddToGroupAsync(
            Context.ConnectionId, room);
    }

    public async Task SendToRoom(
        string room,
        string user,
        string msg)
    {
        await Clients.Group(room).SendAsync(
            "NewMessage", user, msg);
    }
}

Client (JavaScript)

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

connection.on("NewMessage", (user, msg) => {
    console.log(`${user}: ${msg}`);
});

await connection.start();
await connection.invoke("JoinRoom", "Lobby");

🌟 Key Takeaways

  1. SignalR = Real-time, two-way communication
  2. Hubs = Central meeting points for clients
  3. Hub Methods = Actions clients can call
  4. Connections = Each client has a unique ID
  5. Groups = Private rooms within the hub
  6. Streaming = Send data piece by piece
  7. Auto-Reconnect = Handle network hiccups gracefully

You’re no longer building websites. You’re building living, breathing, real-time experiences! 🚀


Now go build something amazing that updates instantly!

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.