Verwenden von Hubs in SignalR für ASP.NET Core

VonUe Appel und Kevin Griffin

Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)

Was ist ein SignalR Hub?

Mit SignalR der Hubs-API können Sie Methoden auf verbundenen Clients vom Server aufrufen. Im Servercode definieren Sie Methoden, die vom Client aufgerufen werden. Im Clientcode definieren Sie Methoden, die vom Server aufgerufen werden. SignalR übernimmt im Hintergrund alles, was die Client-zu-Server- und Server-zu-Client-Kommunikation in Echtzeit ermöglicht.

Konfigurieren von SignalR Hubs

Die SignalR Middleware erfordert einige Dienste, die durch Aufrufen von konfiguriert services.AddSignalR werden.

services.AddSignalR();

Wenn Sie SignalR einer ASP.NET Core-App Funktionen hinzufügen, richten Sie SignalR Routen ein, indem Sie im Rückruf der endpoint.MapHub Methode Startup.Configure app.UseEndpoints aufrufen.

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

Wenn Sie SignalR einer ASP.NET Core-App Funktionen hinzufügen, richten Sie SignalR Routen ein, indem Sie in der app.UseSignalR Startup.Configure -Methode aufrufen.

app.UseSignalR(route =>
{
    route.MapHub<ChatHub>("/chathub");
});

Erstellen und Verwenden von Hubs

Erstellen Sie einen Hub, indem Sie eine Klasse deklarieren, die von Hub erbt, und fügen Sie ihr öffentliche Methoden hinzu. Clients können Methoden aufrufen, die als definiert public sind.

public class ChatHub : Hub
{
    public Task SendMessage(string user, string message)
    {
        return Clients.All.SendAsync("ReceiveMessage", user, message);
    }
}

Sie können wie bei jeder C#-Methode einen Rückgabetyp und Parameter angeben, einschließlich komplexer Typen und Arrays. SignalR behandelt die Serialisierung und Deserialisierung komplexer Objekte und Arrays in Ihren Parametern und Rückgabewerten.

Hinweis

Hubs sind vorübergehend:

  • Speichern Sie den Zustand nicht in einer Eigenschaft für die Hubklasse. Jeder Hubmethodenaufruf wird auf einer neuen Hubinstanz ausgeführt.
  • Verwenden Sie await , wenn Sie asynchrone Methoden aufrufen, die davon abhängig sind, dass der Hub aktiv bleibt. Beispielsweise kann eine Methode wie Clients.All.SendAsync(...) fehlschlagen, wenn sie ohne aufgerufen await wird und die Hubmethode abgeschlossen wird, bevor SendAsync sie abgeschlossen wird.

Das Context-Objekt

Die Hub -Klasse verfügt über eine Context -Eigenschaft, die die folgenden Eigenschaften mit Informationen zur Verbindung enthält:

Eigenschaft BESCHREIBUNG
ConnectionId Ruft die eindeutige ID für die Verbindung ab, die von zugewiesen SignalR wird. Es gibt eine Verbindungs-ID für jede Verbindung.
UserIdentifier Ruft den Benutzerbezeichner ab. Standardmäßig verwendet den aus dem , SignalR der der Verbindung zugeordnet ClaimTypes.NameIdentifier ClaimsPrincipal ist, als Benutzerbezeichner.
User Ruft den ab, ClaimsPrincipal der dem aktuellen Benutzer zugeordnet ist.
Items Ruft eine Schlüssel-Wert-Auflistung ab, die zum Freigeben von Daten innerhalb des Bereichs dieser Verbindung verwendet werden kann. Daten können in dieser Sammlung gespeichert werden und bleiben für die Verbindung über verschiedene Hubmethodenaufrufe hinweg erhalten.
Features Ruft die Auflistung der für die Verbindung verfügbaren Features ab. Vorerst wird diese Sammlung in den meisten Szenarien nicht benötigt, daher ist sie noch nicht ausführlich dokumentiert.
ConnectionAborted Ruft einen ab, der CancellationToken benachrichtigt, wenn die Verbindung abgebrochen wird.

Hub.Context enthält auch die folgenden Methoden:

Methode BESCHREIBUNG
GetHttpContext Gibt den HttpContext für die Verbindung zurück, oder , wenn null die Verbindung keiner HTTP-Anforderung zugeordnet ist. Für HTTP-Verbindungen können Sie diese Methode verwenden, um Informationen wie HTTP-Header und Abfragezeichenfolgen abzurufen.
Abort Bricht die Verbindung ab.

Das Clients-Objekt

Die -Klasse verfügt über Hub eine Clients -Eigenschaft, die die folgenden Eigenschaften für die Kommunikation zwischen Server und Client enthält:

Eigenschaft BESCHREIBUNG
All Ruft eine Methode auf allen verbundenen Clients auf.
Caller Ruft eine Methode auf dem Client auf, der die Hubmethode aufgerufen hat.
Others Ruft eine Methode auf allen verbundenen Clients mit Ausnahme des Clients auf, der die Methode aufgerufen hat.

Hub.Clients enthält auch die folgenden Methoden:

Methode BESCHREIBUNG
AllExcept Ruft eine Methode auf allen verbundenen Clients mit Ausnahme der angegebenen Verbindungen auf.
Client Ruft eine Methode auf einem bestimmten verbundenen Client auf.
Clients Ruft eine Methode auf bestimmten verbundenen Clients auf.
Group Ruft eine Methode für alle Verbindungen in der angegebenen Gruppe auf.
GroupExcept Ruft eine Methode für alle Verbindungen in der angegebenen Gruppe auf, mit Ausnahme der angegebenen Verbindungen.
Groups Ruft eine Methode für mehrere Gruppen von Verbindungen auf.
OthersInGroup Ruft eine Methode für eine Gruppe von Verbindungen auf, mit Ausnahme des Clients, der die Hubmethode aufgerufen hat.
User Ruft eine Methode für alle Verbindungen auf, die einem bestimmten Benutzer zugeordnet sind.
Users Ruft eine Methode für alle Verbindungen auf, die den angegebenen Benutzern zugeordnet sind.

Jede Eigenschaft oder Methode in den vorangehenden Tabellen gibt ein -Objekt mit einer SendAsync -Methode zurück. Mit SendAsync der -Methode können Sie den Namen und die Parameter der aufzurufende Clientmethode bereitstellen.

Senden von Nachrichten an Clients

Verwenden Sie zum Aufrufen bestimmter Clients die Eigenschaften des Clients -Objekts. Im folgenden Beispiel gibt es drei Hub-Methoden:

  • SendMessage sendet mithilfe von eine Nachricht an alle verbundenen Clients.All Clients.
  • SendMessageToCaller sendet mithilfe von eine Nachricht zurück an den Clients.Caller Aufrufer.
  • SendMessageToGroup sendet eine Nachricht an alle Clients in der SignalR Users Gruppe.
public Task SendMessage(string user, string message)
{
    return Clients.All.SendAsync("ReceiveMessage", user, message);
}

public Task SendMessageToCaller(string user, string message)
{
    return Clients.Caller.SendAsync("ReceiveMessage", user, message);
}

public Task SendMessageToGroup(string user, string message)
{
    return Clients.Group("SignalR Users").SendAsync("ReceiveMessage", user, message);
}

Stark typisierte Hubs

Ein Nachteil der Verwendung von SendAsync ist, dass sie auf einer magischen Zeichenfolge basiert, um die client-Methode anzugeben, die aufgerufen werden soll. Dadurch bleibt Code für Laufzeitfehler offen, wenn der Methodenname falsch geschrieben ist oder auf dem Client fehlt.

Eine Alternative zur Verwendung von SendAsync ist die starke Eingabe von mit Hub Hub<T> . Im folgenden Beispiel wurden die ChatHub Clientmethoden in eine Schnittstelle namens IChatClient extrahiert.

public interface IChatClient
{
    Task ReceiveMessage(string user, string message);
}

Diese Schnittstelle kann zum Umgestalten des vorherigen Beispiels verwendet ChatHub werden.

public class StronglyTypedChatHub : Hub<IChatClient>
{
    public async Task SendMessage(string user, string message)
    {
        await Clients.All.ReceiveMessage(user, message);
    }

    public Task SendMessageToCaller(string user, string message)
    {
        return Clients.Caller.ReceiveMessage(user, message);
    }
}

Die Verwendung von ermöglicht die Überprüfung der Clientmethoden zur Hub<IChatClient> Kompilierzeit. Dadurch werden Probleme verhindert, die durch die Verwendung von magic-Zeichenfolgen verursacht werden, da Hub<T> nur Zugriff auf die in der -Schnittstelle definierten Methoden bieten kann.

Die Verwendung eines stark Hub<T> typisierten deaktiviert die Verwendung von SendAsync . Alle für die Schnittstelle definierten Methoden können weiterhin als asynchron definiert werden. Tatsächlich sollte jede dieser Methoden eine Task zurückgeben. Da es sich um eine Schnittstelle handelt, verwenden Sie nicht das async Schlüsselwort . Beispiel:

public interface IClient
{
    Task ClientMethod();
}

Hinweis

Das Async Suffix wird nicht aus dem Methodennamen entfernt. Sofern Ihre Clientmethode nicht mit definiert .on('MyMethodAsync') ist, sollten Sie nicht MyMethodAsync als Namen verwenden.

Ändern des Namens einer Hubmethode

Standardmäßig ist der Name einer Serverhubmethode der Name der .NET-Methode. Sie können jedoch das HubMethodName-Attribut verwenden, um diesen Standardwert zu ändern und manuell einen Namen für die Methode anzugeben. Der Client sollte diesen Namen anstelle des .NET-Methodennamens verwenden, wenn er die Methode aufruft.

[HubMethodName("SendMessageToUser")]
public Task DirectMessage(string user, string message)
{
    return Clients.User(user).SendAsync("ReceiveMessage", user, message);
}

Behandeln von Ereignissen für eine Verbindung

Die SignalR Hubs-API stellt die OnConnectedAsync virtuellen Methoden und OnDisconnectedAsync zum Verwalten und Nachverfolgen von Verbindungen bereit. Überschreiben Sie die OnConnectedAsync virtuelle Methode, um Aktionen auszuführen, wenn ein Client eine Verbindung mit dem Hub herstellt, z. B. wenn er einer Gruppe hinzugefügt wird.

public override async Task OnConnectedAsync()
{
    await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
    await base.OnConnectedAsync();
}

Überschreiben Sie die OnDisconnectedAsync virtuelle Methode, um Aktionen auszuführen, wenn ein Client die Verbindung trennt. Wenn der Client die Verbindung absichtlich trennt (z. B. durch Aufrufen von connection.stop() ), ist der Parameter exception null . Wenn der Client jedoch aufgrund eines Fehlers (z. B. eines Netzwerkfehlers) getrennt wird, enthält der exception Parameter eine Ausnahme, die den Fehler beschreibt.

public override async Task OnDisconnectedAsync(Exception exception)
{
    await Groups.RemoveFromGroupAsync(Context.ConnectionId, "SignalR Users");
    await base.OnDisconnectedAsync(exception);
}

Warnung

Sicherheitswarnung: Die Offenlegung ConnectionId kann zu böswilligem Identitätswechsel führen, wenn die SignalR Server- oder Clientversion ASP.NET Core 2.2 oder früher ist.

Fehlerbehandlung

Ausnahmen, die in Ihren Hubmethoden ausgelöst werden, werden an den Client gesendet, der die Methode aufgerufen hat. Auf dem JavaScript-Client gibt die invoke -Methode eine JavaScript-Zusage zurück. Wenn der Client einen Fehler mit einem Handler empfängt, der mit an die Zusage angefügt catch ist, wird er aufgerufen und als JavaScript-Objekt Error übergeben.

connection.invoke("SendMessage", user, message).catch(err => console.error(err));

Wenn Ihr Hub eine Ausnahme auslöst, werden Verbindungen nicht geschlossen. Standardmäßig SignalR gibt eine generische Fehlermeldung an den Client zurück. Beispiel:

Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'MethodName' on the server.

Unerwartete Ausnahmen enthalten häufig vertrauliche Informationen, z. B. den Namen eines Datenbankservers in einer Ausnahme, die ausgelöst wird, wenn die Datenbankverbindung fehlschlägt. SignalR macht diese detaillierten Fehlermeldungen standardmäßig nicht als Sicherheitsmaßnahme verfügbar. Weitere Informationen dazu, warum Ausnahmedetails unterdrückt werden, finden Sie im Artikel Sicherheitsüberlegungen.

Wenn Sie eine Ausnahmebedingung haben, die Sie an den Client weiter geben möchten, können Sie die HubException -Klasse verwenden. Wenn Sie eine HubException von Ihrer Hubmethode auslösen, SignalR sendet die gesamte Nachricht unverändert an den Client.

public Task ThrowException()
{
    throw new HubException("This error will be sent to the client!");
}

Hinweis

SignalR sendet nur die Message -Eigenschaft der Ausnahme an den Client. Die Stapelüberwachung und andere Eigenschaften für die Ausnahme sind für den Client nicht verfügbar.