0Pricing
C# Academy · Lektion

Gruppen, Benutzer und Verbindungsverwaltung

Verwalten Sie Gruppen, richten Sie Nachrichten an bestimmte Benutzer oder Verbindungen und behandeln Sie Ereignisse im Verbindungslebenszyklus.

Gruppen, Benutzer und Verbindungsverwaltung ist eine kostenlose C# Academy-Lektion auf CoddyKit. Dies ist Lektion 2 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des C# Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der C# Academy-Kurs umfasst insgesamt 4 Lektionen.

Warum Gruppen und Benutzer?

In echten Anwendungen möchten Sie nur selten an ALLE Clients senden. Mit den Gruppen von SignalR können Sie Teilmengen von Verbindungen ansprechen (z. B. einen Chatraum), und mit Benutzern können Sie alle Verbindungen eines bestimmten authentifizierten Benutzers adressieren.

Verbindungen zu Gruppen hinzufügen

Rufen Sie Groups.AddToGroupAsync() mit der Verbindungs-ID und einem Gruppennamen auf. Eine Verbindung kann gleichzeitig mehreren Gruppen angehören.

public class ChatHub : Hub
{
    public async Task JoinRoom(string roomName)
    {
        await Groups.AddToGroupAsync(Context.ConnectionId, roomName);
        await Clients.Group(roomName)
                     .SendAsync("UserJoined", Context.User!.Identity!.Name);
    }

    public async Task LeaveRoom(string roomName)
    {
        await Groups.RemoveFromGroupAsync(Context.ConnectionId, roomName);
        await Clients.Group(roomName)
                     .SendAsync("UserLeft", Context.User!.Identity!.Name);
    }
}

An Gruppen senden

Verwenden Sie Clients.Group(name), um an alle Verbindungen in einer Gruppe zu senden. Weitere Optionen zur Zieladressierung sind GroupExcept und Groups (mehrere gleichzeitig).

public async Task SendToRoom(string roomName, string message)
{
    var sender = Context.User!.Identity!.Name;

    // Everyone in the room
    await Clients.Group(roomName)
                 .SendAsync("ReceiveMessage", sender, message);

    // Everyone in the room except the sender
    await Clients.GroupExcept(roomName, Context.ConnectionId)
                 .SendAsync("ReceiveMessage", sender, message);
}

Benutzerbasierte Zieladressierung

Wenn ein Benutzer mehrere Browser-Tabs oder Geräte geöffnet hat, verfügt er über mehrere Verbindungen. Clients.User(userId) sendet gleichzeitig an ALLE Verbindungen dieses Benutzers.

// Send to all connections of user with ID "user-123"
await Clients.User("user-123")
             .SendAsync("Notification", "Your order has shipped!");

// SignalR uses the NameIdentifier claim by default.
// Context.UserIdentifier returns the current user's ID.
var myId = Context.UserIdentifier;
await Clients.User(myId!).SendAsync("Ack", "Server received your message");

Benutzerdefinierter User-ID-Provider

Standardmäßig verwendet SignalR den NameIdentifier-Claim als Benutzer-ID. Implementieren Sie IUserIdProvider, um einen anderen Claim oder eine benutzerdefinierte Logik zu verwenden.

public class EmailUserIdProvider : IUserIdProvider
{
    public string? GetUserId(HubConnectionContext connection)
    {
        return connection.User?.FindFirst(ClaimTypes.Email)?.Value;
    }
}

// Register:
builder.Services.AddSingleton<IUserIdProvider, EmailUserIdProvider>();

Den Verbindungszustand verfolgen

SignalR speichert den Verbindungszustand zwischen Verbindungsabbrüchen nicht. Verwalten Sie Ihre eigene Zuordnung von Benutzer-IDs zu Verbindungs-IDs in einem threadsicheren Wörterbuch (ein Server) oder in Redis (mehrere Server).

public class ConnectionTracker
{
    private readonly ConcurrentDictionary<string, HashSet<string>> _userConnections
        = new();

    public void AddConnection(string userId, string connectionId)
        => _userConnections.GetOrAdd(userId, _ => new()).Add(connectionId);

    public void RemoveConnection(string userId, string connectionId)
    {
        if (_userConnections.TryGetValue(userId, out var conns))
        {
            conns.Remove(connectionId);
            if (conns.Count == 0) _userConnections.TryRemove(userId, out _);
        }
    }

    public IEnumerable<string> GetConnections(string userId)
        => _userConnections.TryGetValue(userId, out var c) ? c : Enumerable.Empty<string>();
}

Gruppen in OnConnected/OnDisconnected automatisch verwalten

Ein gängiges Muster besteht darin, authentifizierte Benutzer in OnConnectedAsync automatisch ihrer persönlichen Gruppe hinzuzufügen. So können Sie sie über den Gruppennamen ansprechen, ohne eine eigene Zuordnung verwalten zu müssen.

public override async Task OnConnectedAsync()
{
    // Add to a personal group named by user ID
    var userId = Context.UserIdentifier;
    if (userId is not null)
        await Groups.AddToGroupAsync(Context.ConnectionId, userId);
    await base.OnConnectedAsync();
}

// Now send to a user by their personal group:
await _hub.Clients.Group(userId)
           .SendAsync("Update", payload);

Aus Hintergrunddiensten mit Gruppen senden

Mit IHubContext können Sie aus Hintergrunddiensten Gruppen und Benutzer ansprechen – ideal für asynchrone Benachrichtigungen, die durch Ereignisse in Ihrem System ausgelöst werden.

public class OrderShippedHandler : INotificationHandler<OrderShipped>
{
    private readonly IHubContext<OrderHub> _hub;
    public OrderShippedHandler(IHubContext<OrderHub> hub) => _hub = hub;

    public async Task Handle(OrderShipped notification, CancellationToken ct)
    {
        // Push to the customer's personal group
        await _hub.Clients.Group(notification.CustomerId.ToString())
                  .SendAsync("OrderShipped",
                      new { notification.OrderId, notification.TrackingNumber },
                      ct);
    }
}

Dauerhafte Speicherung der Gruppenmitgliedschaft

Die Gruppenmitgliedschaft wird nicht dauerhaft gespeichert – bei einem Neustart des Servers oder wenn ein Redis-Backplane seinen Zustand verliert, sind die Gruppen leer. Treten Sie Gruppen beim Wiederverbinden über das Clientereignis onreconnected erneut bei.

// JavaScript client: re-join groups after reconnect
connection.onreconnected(async connectionId => {
    console.log(`Reconnected as ${connectionId}`);
    // Re-join previously joined rooms
    for (const room of joinedRooms) {
        await connection.invoke("JoinRoom", room);
    }
});

Presence: Erkennung von Online-/Offline-Status

Verfolgen Sie den Onlinestatus, indem Sie die Verbindungen pro Benutzer in OnConnected/OnDisconnected zählen und Presence-Ereignisse an relevante Gruppen senden.

public override async Task OnConnectedAsync()
{
    var userId = Context.UserIdentifier!;
    var count = _tracker.AddConnection(userId, Context.ConnectionId);
    if (count == 1) // first connection for this user
        await Clients.Others.SendAsync("UserOnline", userId);
    await base.OnConnectedAsync();
}

public override async Task OnDisconnectedAsync(Exception? ex)
{
    var userId = Context.UserIdentifier!;
    var count = _tracker.RemoveConnection(userId, Context.ConnectionId);
    if (count == 0) // no more connections
        await Clients.Others.SendAsync("UserOffline", userId);
    await base.OnDisconnectedAsync(ex);
}

Kurze Überprüfung

Was bewirkt Clients.User(userId), wenn ein Benutzer drei Browser-Tabs geöffnet hat?

Zusammenfassung: Gruppen, Benutzer und Verbindungsverwaltung

Wichtigste Erkenntnisse:

  • Groups.AddToGroupAsync/RemoveFromGroupAsync: Gruppenmitgliedschaften verwalten
  • Clients.Group(name): an eine Teilmenge von Verbindungen senden
  • Clients.User(userId): an alle Verbindungen eines Benutzers senden
  • IUserIdProvider für benutzerdefinierte Benutzer-ID-Claims implementieren
  • Gruppen werden nicht dauerhaft gespeichert – bei einer erneuten Verbindung wieder beitreten
  • Verbindungsanzahlen in ConcurrentDictionary für die Presence-Erkennung verfolgen

Häufig gestellte Fragen

Ist die Lektion „Gruppen, Benutzer und Verbindungsverwaltung“ kostenlos?

Ja — der vollständige Text von „Gruppen, Benutzer und Verbindungsverwaltung“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des C# Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der C# Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Gruppen, Benutzer und Verbindungsverwaltung“?

Verwalten Sie Gruppen, richten Sie Nachrichten an bestimmte Benutzer oder Verbindungen und behandeln Sie Ereignisse im Verbindungslebenszyklus. Du übst C# Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um C# Academy zu starten?

Keine Vorkenntnisse erforderlich. C# Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 2 von 4.

Wie lange dauert die Lektion „Gruppen, Benutzer und Verbindungsverwaltung“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser C# Academy-Lektion Code schreiben und ausführen?

Ja. Jede C# Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. SignalR-Hubs und Verbindungen
  2. Gruppen, Benutzer und Verbindungsverwaltung
  3. Typsichere Hubs
  4. Skalierung mit Redis-Backplane
← Zurück zu C# Academy