---
title: "How do you implement private messaging between two users in a SignalR chat application?"  
description: "How do you implement private messaging between two users in a SignalR chat application?"  
author: "ICSM Computer"  
published: 2025-05-22  
updated: 2025-05-22  
canonical: https://www.mindstick.com/interview/34154/how-do-you-implement-private-messaging-between-two-users-in-a-signalr-chat-application  
category: "c#"  
tags: ["c#", "signalr"]  
reading_time: 4 minutes  

---

# How do you implement private messaging between two users in a SignalR chat application?

1. **Identify users uniquely**.
2. **Map each connected user to a SignalR connection**.
3. **Send a message to a specific user’s connection** instead of broadcasting to all clients.

Here’s a step-by-step guide:

## 1. Setup SignalR Hub

```cs
public class ChatHub : Hub
{
    // Static dictionary to keep track of userId and connectionId
    private static readonly Dictionary<string, string> _userConnections = new();

    // Called when a client connects
    public override Task OnConnectedAsync()
    {
        var userId = Context.UserIdentifier; // Must be set by authentication middleware
        if (!string.IsNullOrEmpty(userId))
        {
            lock (_userConnections)
            {
                _userConnections[userId] = Context.ConnectionId;
            }
        }

        return base.OnConnectedAsync();
    }

    // Called when a client disconnects
    public override Task OnDisconnectedAsync(Exception exception)
    {
        var userId = Context.UserIdentifier;
        if (!string.IsNullOrEmpty(userId))
        {
            lock (_userConnections)
            {
                _userConnections.Remove(userId);
            }
        }

        return base.OnDisconnectedAsync(exception);
    }

    // Private messaging method
    public async Task SendPrivateMessage(string recipientUserId, string message)
    {
        if (_userConnections.TryGetValue(recipientUserId, out string connectionId))
        {
            await Clients.Client(connectionId).SendAsync("ReceivePrivateMessage", Context.UserIdentifier, message);
        }
    }
}
```

## 2. Configure Authentication Middleware

Ensure that `UserIdentifier` is set — typically the username or user ID from your authentication system.

In `Startup.cs` (for .NET Core):

```cs
services.AddSignalR();

services.AddAuthentication(...);
services.AddAuthorization();

app.UseAuthentication();
app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
    endpoints.MapHub<ChatHub>("/chatHub");
});
```

If you're not using full authentication, override `UserIdentifier` manually:

```cs
public class CustomUserIdProvider : IUserIdProvider
{
    public string GetUserId(HubConnectionContext connection)
    {
        // Use connection.User.Identity.Name or a query string, etc.
        return connection.User?.Identity?.Name;
    }
}
```

Register it:

```plaintext
services.AddSingleton<IUserIdProvider, CustomUserIdProvider>();
```

## 3. Client-Side JavaScript Example

```javascript
const connection = new signalR.HubConnectionBuilder()
    .withUrl("/chatHub")
    .build();

connection.on("ReceivePrivateMessage", (senderUserId, message) => {
    console.log(`Message from ${senderUserId}: ${message}`);
});

connection.start().then(() => {
    // Example: send a private message
    const recipientUserId = "user456";
    connection.invoke("SendPrivateMessage", recipientUserId, "Hello in private!");
});
```

## Tips

1. **Use a persistent store** instead of an in-memory dictionary (`_userConnections`) for scalability.
2. For **multiple connections per user** (multiple browser tabs), use `ConcurrentDictionary<string, HashSet<string>>`.
3. For group chat, use `Groups.AddToGroupAsync(connectionId, groupName)`.

## Answers

### Answer by ICSM Computer

1. **Identify users uniquely**.
2. **Map each connected user to a SignalR connection**.
3. **Send a message to a specific user’s connection** instead of broadcasting to all clients.

Here’s a step-by-step guide:

## 1. Setup SignalR Hub

```cs
public class ChatHub : Hub
{
    // Static dictionary to keep track of userId and connectionId
    private static readonly Dictionary<string, string> _userConnections = new();

    // Called when a client connects
    public override Task OnConnectedAsync()
    {
        var userId = Context.UserIdentifier; // Must be set by authentication middleware
        if (!string.IsNullOrEmpty(userId))
        {
            lock (_userConnections)
            {
                _userConnections[userId] = Context.ConnectionId;
            }
        }

        return base.OnConnectedAsync();
    }

    // Called when a client disconnects
    public override Task OnDisconnectedAsync(Exception exception)
    {
        var userId = Context.UserIdentifier;
        if (!string.IsNullOrEmpty(userId))
        {
            lock (_userConnections)
            {
                _userConnections.Remove(userId);
            }
        }

        return base.OnDisconnectedAsync(exception);
    }

    // Private messaging method
    public async Task SendPrivateMessage(string recipientUserId, string message)
    {
        if (_userConnections.TryGetValue(recipientUserId, out string connectionId))
        {
            await Clients.Client(connectionId).SendAsync("ReceivePrivateMessage", Context.UserIdentifier, message);
        }
    }
}
```

## 2. Configure Authentication Middleware

Ensure that `UserIdentifier` is set — typically the username or user ID from your authentication system.

In `Startup.cs` (for .NET Core):

```cs
services.AddSignalR();

services.AddAuthentication(...);
services.AddAuthorization();

app.UseAuthentication();
app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
    endpoints.MapHub<ChatHub>("/chatHub");
});
```

If you're not using full authentication, override `UserIdentifier` manually:

```cs
public class CustomUserIdProvider : IUserIdProvider
{
    public string GetUserId(HubConnectionContext connection)
    {
        // Use connection.User.Identity.Name or a query string, etc.
        return connection.User?.Identity?.Name;
    }
}
```

Register it:

```plaintext
services.AddSingleton<IUserIdProvider, CustomUserIdProvider>();
```

## 3. Client-Side JavaScript Example

```javascript
const connection = new signalR.HubConnectionBuilder()
    .withUrl("/chatHub")
    .build();

connection.on("ReceivePrivateMessage", (senderUserId, message) => {
    console.log(`Message from ${senderUserId}: ${message}`);
});

connection.start().then(() => {
    // Example: send a private message
    const recipientUserId = "user456";
    connection.invoke("SendPrivateMessage", recipientUserId, "Hello in private!");
});
```

## Tips

1. **Use a persistent store** instead of an in-memory dictionary (`_userConnections`) for scalability.
2. For **multiple connections per user** (multiple browser tabs), use `ConcurrentDictionary<string, HashSet<string>>`.
3. For group chat, use `Groups.AddToGroupAsync(connectionId, groupName)`.


---

Original Source: https://www.mindstick.com/interview/34154/how-do-you-implement-private-messaging-between-two-users-in-a-signalr-chat-application

Copyright © MindStick Software Pvt. Ltd. This Markdown version is provided for developers, AI systems, and offline reading.
