C# Academy · Lektion

Grupper, brugere og forbindelseshåndtering

Håndtér grupper, målret bestemte brugere eller forbindelser, og håndtér hændelser i forbindelsernes livscyklus ved tilslutning og afbrydelse.

Lektion 2 af 412 trin

Grupper, brugere og forbindelseshåndtering er en gratis C# Academy-lektion på CoddyKit. Dette er lektion 2 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i C# Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. C# Academy-kurset indeholder 4 lektioner i alt.

Hvorfor grupper og brugere?

I virkelige programmer vil du sjældent udsende til ALLE klienter. SignalR's grupper lader dig målrette delmængder af forbindelser (f.eks. et chatrum), og brugere gør det muligt at adressere alle forbindelser, der tilhører en bestemt godkendt bruger.

Tilføjelse af forbindelser til grupper

Kald Groups.AddToGroupAsync() med forbindelses-id'et og et gruppenavn. En forbindelse kan tilhøre flere grupper samtidig.

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);
    }
}

Afsendelse til grupper

Brug Clients.Group(name) til at sende til alle forbindelser i en gruppe. Andre målretningsmuligheder omfatter GroupExcept og Groups (flere på én gang).

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);
}

Brugerbaseret målretning

Når en bruger har flere browserfaner eller enheder åbne, har brugeren flere forbindelser. Clients.User(userId) sender til ALLE forbindelser for denne bruger samtidigt.

// 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");

Tilpasset bruger-id-udbyder

Som standard bruger SignalR NameIdentifier-claimet som bruger-id. Implementér IUserIdProvider for at bruge en anden claim eller tilpasset logik.

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

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

Sporing af forbindelsestilstand

SignalR gemmer ikke forbindelsestilstand mellem afbrydelser. Vedligehold din egen tilknytning mellem bruger-id'er og forbindelses-id'er i en trådsikker ordbog (én server) eller Redis (flere servere).

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>();
}

Automatisk håndtering af grupper i OnConnected/OnDisconnected

Et almindeligt mønster er automatisk at føje godkendte brugere til deres personlige gruppe i OnConnectedAsync, så du kan målrette dem via gruppenavnet uden selv at skulle holde styr på forbindelserne.

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);

Afsendelse fra baggrundstjenester med grupper

Med IHubContext kan du målrette grupper og brugere fra baggrundstjenester — perfekt til asynkrone notifikationer udløst af hændelser i systemet.

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);
    }
}

Persistens for gruppemedlemskab

Gruppemedlemskab gemmes ikke — hvis serveren genstarter, eller en Redis-backplane mister sin tilstand, er grupperne tomme. Meld klienten ind i grupperne igen ved genforbindelse ved hjælp af klientens onreconnected-hændelse.

// 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);
    }
});

Tilstedeværelse: registrering af online- og offlinestatus

Spor onlinestatus ved at tælle forbindelser pr. bruger i OnConnected/OnDisconnected og udsende tilstedeværelseshændelser til relevante grupper.

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);
}

Hurtigt tjek

Når en bruger har tre browserfaner åbne, hvad gør Clients.User(userId)?

Opsamling: Grupper, brugere og forbindelsesstyring

Vigtigste pointer:

  • Groups.AddToGroupAsync/RemoveFromGroupAsync: administrerer gruppemedlemskab
  • Clients.Group(name): sender til en delmængde af forbindelser
  • Clients.User(userId): sender til alle en brugers forbindelser
  • Implementer IUserIdProvider for brugerdefinerede claims for bruger-id'er
  • Grupper gemmes ikke — meld dig ind igen ved genforbindelse
  • Spor antal forbindelser i ConcurrentDictionary for at registrere tilstedeværelse
Gratis at komme i gang

Lær C# med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
93
Lektioner
346

Ofte stillede spørgsmål

Er lektionen “Grupper, brugere og forbindelseshåndtering” gratis?

Ja — hele teksten til “Grupper, brugere og forbindelseshåndtering” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af C# Academy-kurset, skal du opgradere til CoddyKit PRO. C# Academy-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “Grupper, brugere og forbindelseshåndtering”?

Håndtér grupper, målret bestemte brugere eller forbindelser, og håndtér hændelser i forbindelsernes livscyklus ved tilslutning og afbrydelse. Du øver dig i C# Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på C# Academy?

Der kræves ingen tidligere erfaring. C# Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 2 af 4.

Hvor lang tid tager lektionen “Grupper, brugere og forbindelseshåndtering”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne C# Academy-lektion?

Ja. Alle C# Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. SignalR-hubs og forbindelser
  2. Grupper, brugere og forbindelseshåndtering
  3. Stærkt typede hubs
  4. Skalering med Redis-backplane
← Tilbage til C# Academy