In this lesson, you will learn how to hook into SignalR’s built-in lifecycle events to accurately track user presence and manage real-time connectivity status.
When working with real-time systems, knowing exactly when a user connects or disconnects is critical for features like "online status" indicators or active session tracking. SignalR provides two primary hooks within your Hub class: OnConnectedAsync and OnDisconnectedAsync. These methods are automatically triggered by the SignalR infrastructure whenever a client establishes or terminates a connection.
Implementing Presence Tracking
To track user presence, you can override these methods to update your backing store—such as a database via Entity Framework or a distributed cache like Redis.
public class PresenceHub : Hub
{
private readonly IUserPresenceService _presenceService;
public PresenceHub(IUserPresenceService presenceService)
{
_presenceService = presenceService;
}
public override async Task OnConnectedAsync()
{
var userId = Context.UserIdentifier;
await _presenceService.MarkOnline(userId, Context.ConnectionId);
await base.OnConnectedAsync();
}
public override async Task OnDisconnectedAsync(Exception exception)
{
var userId = Context.UserIdentifier;
await _presenceService.MarkOffline(userId);
await base.OnDisconnectedAsync(exception);
}
}
Critical Considerations
When managing these events, keep in mind that OnDisconnectedAsync is not guaranteed to fire if the server process crashes or the network interface suddenly fails. Furthermore, because a single user might open multiple browser tabs, you may have multiple ConnectionId values associated with one UserIdentifier.
To maintain an accurate state, you should track these connections in a collection. When OnConnectedAsync triggers, increment a count or add the ConnectionId to a set; when OnDisconnectedAsync triggers, remove the specific ConnectionId. Only consider the user "offline" once their set of active connections is empty. This granular approach prevents a user from appearing offline simply because they closed one of three open browser tabs.
Key Takeaway: Use OnConnectedAsync and OnDisconnectedAsync to intercept connection state changes, but always account for multi-tab scenarios to ensure your user presence logic remains robust and accurate.