Course contentsShow
← C#
Lesson 1439 of 1,90813. Real-time Communication with SignalRFree lesson

Establishing the SignalR Hub Lifecycle

Manage state and behavior across the connection lifecycle from OnConnectedAsync to OnDisconnectedAsync.

In this lesson, you will learn how to orchestrate stateful application logic by hooking into the specific moments when a client connects to and disconnects from your SignalR Hub.

Understanding the Hub Lifecycle

A SignalR Hub is transient—it is instantiated when a method is called and disposed of immediately after. However, the connection itself persists. To maintain state or trigger events (like updating a "Users Online" counter), we override two fundamental lifecycle methods: OnConnectedAsync and OnDisconnectedAsync.

These methods act as the bookends for the client's session. While the Hub instance is short-lived, the connection lifecycle allows you to perform cleanup tasks or state initialization that transcends a single method call.

Implementation Example

Consider a scenario where you need to track user activity in real-time. By overriding these methods, you can manage a concurrent dictionary or a cache service to track who is currently present:

public class ChatHub : Hub
{
    private static readonly ConcurrentDictionary<string, string> _connections = new();

    public override async Task OnConnectedAsync()
    {
        var userName = Context.UserIdentifier;
        _connections.TryAdd(Context.ConnectionId, userName);
        await Groups.AddToGroupAsync(Context.ConnectionId, "General");
        await base.OnConnectedAsync();
    }

    public override async Task OnDisconnectedAsync(Exception? exception)
    {
        _connections.TryRemove(Context.ConnectionId, out _);
        await Groups.RemoveFromGroupAsync(Context.ConnectionId, "General");
        await base.OnDisconnectedAsync(exception);
    }
}

Why This Matters

In advanced real-time architectures, you cannot rely on member variables within the Hub class to persist data between different method calls because the Hub is recreated every time. By hooking into the lifecycle, you effectively bridge the gap between stateless Hub invocations and the stateful nature of the long-lived WebSocket connection.

Remember: OnDisconnectedAsync is not guaranteed to fire if the client loses power or crashes abruptly, so always supplement your lifecycle management with heartbeat checks or expiration logic if absolute state accuracy is required for your business domain.

Key Takeaway: Use OnConnectedAsync and OnDisconnectedAsync to manage the session-specific state and group membership that persists beyond the transient lifetime of a single Hub invocation.