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

Von Rachel Appel und Kevin Griffin

Die Hubs-API von SignalR ermöglicht es verbundenen Clients, Methoden auf dem Server aufzurufen. Der Server definiert Methoden, die vom Client aufgerufen werden, und der Client definiert Methoden, die vom Server aufgerufen werden. SignalR kümmert sich um alles, was erforderlich ist, um die Kommunikation zwischen Client und Server sowie zwischen Server und Client in Echtzeit zu ermöglichen.

Konfigurieren von SignalR-Hubs

Rufen Sie zum Registrieren der für SignalR-Hubs erforderlichen Dienste AddSignalR in Program.cs auf:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddSignalR();

Rufen Sie zum Konfigurieren von SignalR-Endpunkten MapHub (auch in Program.cs) auf:

app.MapRazorPages();
app.MapHub<ChatHub>("/Chat");

app.Run();

Hinweis

Serverseitige ASP.NET Core SignalR-Assemblys werden jetzt mit dem .NET Core SDK installiert. Weitere Informationen finden Sie unter SignalR-Assemblys im freigegebenen Framework.

Erstellen und Verwenden von Hubs

Erstellen Sie einen Hub, indem Sie eine Klasse deklarieren, die von Hub erbt. Fügen Sie der Klasse public-Methoden hinzu, um sie von Clients aus aufrufbar zu machen:

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

Hinweis

Hubs sind vorübergehende Objekte:

  • Speichern Sie den Zustand nicht in einer Eigenschaft der Hubklasse. Jeder Hubmethodenaufruf wird in einer neuen Hubinstanz ausgeführt.
  • Instanziieren Sie einen Hub nicht direkt mithilfe von Abhängigkeitsinjektion. Um Nachrichten von einer anderen Stelle in Ihrer Anwendung an einen Client zu senden, verwenden Sie IHubContext.
  • Verwenden Sie await beim Aufrufen asynchroner Methoden, die davon abhängen, dass der Hub aktiv bleibt. Eine Methode wie Clients.All.SendAsync(...) kann beispielsweise fehlschlagen, wenn sie ohne await aufgerufen wird und die Hubmethode abgeschlossen wird, bevor SendAsync abgeschlossen ist.

Das Context-Objekt

Die Hub-Klasse enthält 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 SignalR zugewiesen wird. Für jede Verbindung gibt es eine Verbindungs-ID.
UserIdentifier Ruft den Benutzerbezeichner ab. SignalR verwendet standardmäßig den ClaimTypes.NameIdentifier von ClaimsPrincipal, der der Verbindung zugeordnet ist, als Benutzerbezeichner.
User Ruft den ClaimsPrincipal ab, der dem aktuellen Benutzer zugeordnet ist.
Items Ruft eine Schlüssel-Wert-Sammlung 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 bestehen.
Features Ruft die Sammlung der Features ab, die für die Verbindung verfügbar sind. Derzeit ist diese Sammlung in den meisten Szenarien nicht erforderlich, daher wurde sie noch nicht ausführlich dokumentiert.
ConnectionAborted Ruft ein CancellationToken ab, das eine Benachrichtigung sendet, 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 null, wenn die Verbindung keiner HTTP-Anforderung zugeordnet ist. Verwenden Sie für HTTP-Verbindungen diese Methode, um Informationen wie HTTP-Header und Abfragezeichenfolgen abzurufen.
Abort Bricht die Verbindung ab.

Das Clients-Objekt

Die Hub-Klasse enthält 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, die 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 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 mit Ausnahme der angegebenen Verbindungen auf.
Groups Ruft eine Methode für mehrere Gruppen von Verbindungen auf.
OthersInGroup Ruft eine Methode für eine Gruppe von Verbindungen auf, wobei der Client, der die Hubmethode aufgerufen hat, ausgeschlossen wird.
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 vorherigen Tabellen gibt ein Objekt mit einer SendAsync-Methode zurück. Die SendAsync-Methode empfängt den Namen der aufzurufenden Clientmethode und alle Parameter.

Das von den Client und Caller-Methoden zurückgegebene Objekt enthält auch eine InvokeAsync-Methode, die verwendet werden kann, um auf ein Ergebnis vom Client zu warten.

Senden von Nachrichten an Clients

Verwenden Sie die Eigenschaften des Clients-Objekts, um Aufrufe für bestimmte Clients auszuführen. Im folgenden Beispiel gibt es drei Hubmethoden:

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

public async Task SendMessageToCaller(string user, string message)
    => await Clients.Caller.SendAsync("ReceiveMessage", user, message);

public async Task SendMessageToGroup(string user, string message)
    => await Clients.Group("SignalR Users").SendAsync("ReceiveMessage", user, message);

Stark typisierte Hubs

Ein Nachteil der Verwendung von SendAsync besteht darin, dass eine Zeichenfolge erforderlich ist, um die Clientmethode anzugeben, die aufgerufen werden soll. Dadurch kann es zu Laufzeitfehlern kommen, wenn der Methodenname falsch geschrieben ist oder im Client fehlt.

Eine Alternative zur Verwendung von SendAsync besteht darin, die Hub-Klasse mit Hub<T> stark zu typisieren. Im folgenden Beispiel wurde die ChatHub-Clientmethode in eine Schnittstelle namens IChatClient extrahiert:

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

Diese Schnittstelle kann verwendet werden, um das vorherige ChatHub-Beispiel so umzugestalten, dass es stark typisiert ist:

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

    public async Task SendMessageToCaller(string user, string message)
        => await Clients.Caller.ReceiveMessage(user, message);

    public async Task SendMessageToGroup(string user, string message)
        => await Clients.Group("SignalR Users").ReceiveMessage(user, message);
}

Die Verwendung von Hub<IChatClient> ermöglicht die Überprüfung der Clientmethoden zur Kompilierzeit. Dadurch werden Probleme verhindert, die durch die Verwendung von Zeichenfolgen verursacht werden, weil Hub<T> nur Zugriff auf die in der Schnittstelle definierten Methoden bereitstellen kann. Die Verwendung eines stark typisierten Hub<T> deaktiviert die Möglichkeit, SendAsync zu verwenden.

Hinweis

Das Async-Suffix wird nicht aus Methodennamen entfernt. Verwenden Sie MyMethodAsync nicht als Name, es sei denn, eine Clientmethode ist mit .on('MyMethodAsync') definiert.

Clientergebnisse

Zusätzlich zu Aufrufen von Clients kann der Server ein Ergebnis von einem Client anfordern. Dazu muss der Server ISingleClientProxy.InvokeAsync verwenden, und der Client muss ein Ergebnis aus seinem .On-Handler zurückzugeben.

Es gibt zwei Möglichkeiten, die API auf dem Server zu verwenden: Die erste besteht darin, Client(...) oder Caller für die Clients-Eigenschaft in einer Hub-Methode aufzurufen:

public class ChatHub : Hub
{
    public async Task<string> WaitForMessage(string connectionId)
    {
        var message = await Clients.Client(connectionId).InvokeAsync<string>(
            "GetMessage");
        return message;
    }
}

Die zweite Möglichkeit besteht darin, Client(...) für eine Instanz von IHubContext<T> aufzurufen:

async Task SomeMethod(IHubContext<MyHub> context)
{
    string result = await context.Clients.Client(connectionID).InvokeAsync<string>(
        "GetMessage");
}

Stark typisierte Hubs können auch Werte aus Schnittstellenmethoden zurückgeben:

public interface IClient
{
    Task<string> GetMessage();
}

public class ChatHub : Hub<IClient>
{
    public async Task<string> WaitForMessage(string connectionId)
    {
        string message = await Clients.Client(connectionId).GetMessage();
        return message;
    }
}

Clients geben Ergebnisse in ihren .On(...)-Handlern zurück, wie unten gezeigt:

.NET-Client

hubConnection.On("GetMessage", async () =>
{
    Console.WriteLine("Enter message:");
    var message = await Console.In.ReadLineAsync();
    return message;
});

TypeScript-Client

hubConnection.on("GetMessage", async () => {
    let promise = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve("message");
        }, 100);
    });
    return promise;
});

Java-Client

hubConnection.onWithResult("GetMessage", () -> {
    return Single.just("message");
});

Ändern des Namens einer Hubmethode

Standardmäßig ist der Name einer Serverhubmethode der Name der .NET-Methode. Um dieses Standardverhalten für eine bestimmte Methode zu ändern, verwenden Sie das HubMethodName-Attribut. Der Client sollte diesen Namen anstelle des .NET-Methodennamens verwenden, wenn die Methode aufgerufen wird:

[HubMethodName("SendMessageToUser")]
public async Task DirectMessage(string user, string message)
    => await Clients.User(user).SendAsync("ReceiveMessage", user, message);

Einfügen von Diensten in einen Hub

Hubkonstruktoren können Dienste der Abhängigkeitsinjektion als Parameter akzeptieren, die in Eigenschaften der Klasse zur Verwendung in einer Hubmethode gespeichert werden können.

Beim Einfügen mehrerer Dienste für verschiedene Hubmethoden oder als alternatives Verfahren zum Schreiben von Code können Hubmethoden auch Dienste von DI akzeptieren. Standardmäßig werden Hubmethodenparameter überprüft und nach Möglichkeit von DI aufgelöst.

services.AddSingleton<IDatabaseService, DatabaseServiceImpl>();

// ...

public class ChatHub : Hub
{
    public Task SendMessage(string user, string message, IDatabaseService dbService)
    {
        var userName = dbService.GetUserName(user);
        return Clients.All.SendAsync("ReceiveMessage", userName, message);
    }
}

Wenn die implizite Auflösung von Parametern aus Diensten nicht gewünscht ist, deaktivieren Sie sie mit DisableImplicitFromServicesParameters. Um explizit anzugeben, welche Parameter in Hubmethoden von DI aufgelöst werden, verwenden Sie die Option DisableImplicitFromServicesParameters und das Attribut [FromServices] oder ein benutzerdefiniertes Attribut, das IFromServiceMetadata implementiert, für die Parameter der Hubmethode, die von DI aufgelöst werden sollen.

services.AddSingleton<IDatabaseService, DatabaseServiceImpl>();
services.AddSignalR(options =>
{
    options.DisableImplicitFromServicesParameters = true;
});

// ...

public class ChatHub : Hub
{
    public Task SendMessage(string user, string message,
        [FromServices] IDatabaseService dbService)
    {
        var userName = dbService.GetUserName(user);
        return Clients.All.SendAsync("ReceiveMessage", userName, message);
    }
}

Hinweis

Dieses Feature verwendet das IServiceProviderIsService-Element, das optional von DI-Implementierungen implementiert wird. Wenn der DI-Container der App dieses Feature nicht unterstützt, wird das Einfügen von Diensten in Hubmethoden nicht unterstützt.

Unterstützung von Schlüsseldiensten in Abhängigkeitsinjektion

Schlüsseldienste bezieht sich auf einen Mechanismus für die Registrierung und den Abruf von Dependency Injection (DI) Services unter Verwendung von Schlüsseln. Ein Dienst wird mit einem Schlüssel verknüpft, indem Sie AddKeyedSingleton (oder AddKeyedScoped oder AddKeyedTransient) aufrufen, um ihn zu registrieren. Greifen Sie auf einen registrierten Dienst zu, indem Sie den Schlüssel mit dem [FromKeyedServices] Attribut angeben. Der folgende Code zeigt, wie Sie Schlüsseldienste verwenden können:

using Microsoft.AspNetCore.SignalR;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddKeyedSingleton<ICache, BigCache>("big");
builder.Services.AddKeyedSingleton<ICache, SmallCache>("small");

builder.Services.AddRazorPages();
builder.Services.AddSignalR();

var app = builder.Build();

app.MapRazorPages();
app.MapHub<MyHub>("/myHub");

app.Run();

public interface ICache
{
    object Get(string key);
}
public class BigCache : ICache
{
    public object Get(string key) => $"Resolving {key} from big cache.";
}

public class SmallCache : ICache
{
    public object Get(string key) => $"Resolving {key} from small cache.";
}

public class MyHub : Hub
{
    public void SmallCacheMethod([FromKeyedServices("small")] ICache cache)
    {
        Console.WriteLine(cache.Get("signalr"));
    }

    public void BigCacheMethod([FromKeyedServices("big")] ICache cache)
    {
        Console.WriteLine(cache.Get("signalr"));
    }
}

Behandeln von Ereignissen für eine Verbindung

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

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

Überschreiben Sie die virtuelle OnDisconnectedAsync-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(), wird der exception-Parameter auf null festgelegt. Wenn der Client jedoch aufgrund eines Fehlers (z. B. eines Netzwerkfehlers) die Verbindung trennt, enthält der exception-Parameter eine Ausnahme, die den Fehler beschreibt:

public override async Task OnDisconnectedAsync(Exception? exception)
{
    await base.OnDisconnectedAsync(exception);
}

RemoveFromGroupAsync muss in OnDisconnectedAsync nicht aufgerufen werden, es wird automatisch für Sie verarbeitet.

Umgang mit Fehlern

Ausnahmen, die in Hubmethoden ausgelöst werden, werden an den Client gesendet, der die Methode aufgerufen hat. Auf dem JavaScript-Client gibt die invoke-Methode eine JavaScript-Promise zurück. Clients können einen catch-Handler an die zurückgegebene Zusage anfügen oder try/catch mit async/await verwenden, um Ausnahmen zu behandeln:

try {
  await connection.invoke("SendMessage", user, message);
} catch (err) {
  console.error(err);
}

Verbindungen werden nicht geschlossen, wenn ein Hub eine Ausnahme auslöst. SignalR gibt standardmäßig eine generische Fehlermeldung an den Client zurück, wie im folgenden Beispiel gezeigt:

Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'SendMessage' 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 stellt diese detaillierten Fehlermeldungen als Sicherheitsmaßnahme standardmäßig nicht zur Verfügung. Weitere Informationen dazu, warum Ausnahmedetails unterdrückt werden, finden Sie unter Sicherheitsüberlegungen in ASP.NET Core SignalR.

Wenn eine Ausnahmebedingung an den Client weitergegeben werden muss, verwenden Sie die HubException-Klasse. Wenn eine HubException in einer Hubmethode ausgelöst wird, SignalRsendet die gesamte Ausnahmemeldung an den Client (unverändert):

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 Stapelablaufverfolgung und andere Eigenschaften für die Ausnahme stehen dem Client nicht zur Verfügung.

Zusätzliche Ressourcen

Von Rachel Appel und Kevin Griffin

Die Hubs-API von SignalR ermöglicht es verbundenen Clients, Methoden auf dem Server aufzurufen. Der Server definiert Methoden, die vom Client aufgerufen werden, und der Client definiert Methoden, die vom Server aufgerufen werden. SignalR kümmert sich um alles, was erforderlich ist, um die Kommunikation zwischen Client und Server sowie zwischen Server und Client in Echtzeit zu ermöglichen.

Konfigurieren von SignalR-Hubs

Rufen Sie zum Registrieren der für SignalR-Hubs erforderlichen Dienste AddSignalR in Program.cs auf:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddSignalR();

Rufen Sie zum Konfigurieren von SignalR-Endpunkten MapHub (auch in Program.cs) auf:

app.MapRazorPages();
app.MapHub<ChatHub>("/Chat");

app.Run();

Hinweis

Serverseitige ASP.NET Core SignalR-Assemblys werden jetzt mit dem .NET Core SDK installiert. Weitere Informationen finden Sie unter SignalR-Assemblys im freigegebenen Framework.

Erstellen und Verwenden von Hubs

Erstellen Sie einen Hub, indem Sie eine Klasse deklarieren, die von Hub erbt. Fügen Sie der Klasse public-Methoden hinzu, um sie von Clients aus aufrufbar zu machen:

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

Hinweis

Hubs sind vorübergehende Objekte:

  • Speichern Sie den Zustand nicht in einer Eigenschaft der Hubklasse. Jeder Hubmethodenaufruf wird in einer neuen Hubinstanz ausgeführt.
  • Instanziieren Sie einen Hub nicht direkt mithilfe von Abhängigkeitsinjektion. Um Nachrichten von einer anderen Stelle in Ihrer Anwendung an einen Client zu senden, verwenden Sie IHubContext.
  • Verwenden Sie await beim Aufrufen asynchroner Methoden, die davon abhängen, dass der Hub aktiv bleibt. Eine Methode wie Clients.All.SendAsync(...) kann beispielsweise fehlschlagen, wenn sie ohne await aufgerufen wird und die Hubmethode abgeschlossen wird, bevor SendAsync abgeschlossen ist.

Das Context-Objekt

Die Hub-Klasse enthält 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 SignalR zugewiesen wird. Für jede Verbindung gibt es eine Verbindungs-ID.
UserIdentifier Ruft den Benutzerbezeichner ab. SignalR verwendet standardmäßig den ClaimTypes.NameIdentifier von ClaimsPrincipal, der der Verbindung zugeordnet ist, als Benutzerbezeichner.
User Ruft den ClaimsPrincipal ab, der dem aktuellen Benutzer zugeordnet ist.
Items Ruft eine Schlüssel-Wert-Sammlung 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 bestehen.
Features Ruft die Sammlung der Features ab, die für die Verbindung verfügbar sind. Derzeit ist diese Sammlung in den meisten Szenarien nicht erforderlich, daher wurde sie noch nicht ausführlich dokumentiert.
ConnectionAborted Ruft ein CancellationToken ab, das eine Benachrichtigung sendet, 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 null, wenn die Verbindung keiner HTTP-Anforderung zugeordnet ist. Verwenden Sie für HTTP-Verbindungen diese Methode, um Informationen wie HTTP-Header und Abfragezeichenfolgen abzurufen.
Abort Bricht die Verbindung ab.

Das Clients-Objekt

Die Hub-Klasse enthält 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, die 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 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 mit Ausnahme der angegebenen Verbindungen auf.
Groups Ruft eine Methode für mehrere Gruppen von Verbindungen auf.
OthersInGroup Ruft eine Methode für eine Gruppe von Verbindungen auf, wobei der Client, der die Hubmethode aufgerufen hat, ausgeschlossen wird.
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 vorherigen Tabellen gibt ein Objekt mit einer SendAsync-Methode zurück. Die SendAsync-Methode empfängt den Namen der aufzurufenden Clientmethode und alle Parameter.

Das von den Client und Caller-Methoden zurückgegebene Objekt enthält auch eine InvokeAsync-Methode, die verwendet werden kann, um auf ein Ergebnis vom Client zu warten.

Senden von Nachrichten an Clients

Verwenden Sie die Eigenschaften des Clients-Objekts, um Aufrufe für bestimmte Clients auszuführen. Im folgenden Beispiel gibt es drei Hubmethoden:

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

public async Task SendMessageToCaller(string user, string message)
    => await Clients.Caller.SendAsync("ReceiveMessage", user, message);

public async Task SendMessageToGroup(string user, string message)
    => await Clients.Group("SignalR Users").SendAsync("ReceiveMessage", user, message);

Stark typisierte Hubs

Ein Nachteil der Verwendung von SendAsync besteht darin, dass eine Zeichenfolge erforderlich ist, um die Clientmethode anzugeben, die aufgerufen werden soll. Dadurch kann es zu Laufzeitfehlern kommen, wenn der Methodenname falsch geschrieben ist oder im Client fehlt.

Eine Alternative zur Verwendung von SendAsync besteht darin, die Hub-Klasse mit Hub<T> stark zu typisieren. Im folgenden Beispiel wurde die ChatHub-Clientmethode in eine Schnittstelle namens IChatClient extrahiert:

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

Diese Schnittstelle kann verwendet werden, um das vorherige ChatHub-Beispiel so umzugestalten, dass es stark typisiert ist:

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

    public async Task SendMessageToCaller(string user, string message)
        => await Clients.Caller.ReceiveMessage(user, message);

    public async Task SendMessageToGroup(string user, string message)
        => await Clients.Group("SignalR Users").ReceiveMessage(user, message);
}

Die Verwendung von Hub<IChatClient> ermöglicht die Überprüfung der Clientmethoden zur Kompilierzeit. Dadurch werden Probleme verhindert, die durch die Verwendung von Zeichenfolgen verursacht werden, weil Hub<T> nur Zugriff auf die in der Schnittstelle definierten Methoden bereitstellen kann. Die Verwendung eines stark typisierten Hub<T> deaktiviert die Möglichkeit, SendAsync zu verwenden.

Hinweis

Das Async-Suffix wird nicht aus Methodennamen entfernt. Verwenden Sie MyMethodAsync nicht als Name, es sei denn, eine Clientmethode ist mit .on('MyMethodAsync') definiert.

Clientergebnisse

Zusätzlich zu Aufrufen von Clients kann der Server ein Ergebnis von einem Client anfordern. Dazu muss der Server ISingleClientProxy.InvokeAsync verwenden, und der Client muss ein Ergebnis aus seinem .On-Handler zurückzugeben.

Es gibt zwei Möglichkeiten, die API auf dem Server zu verwenden: Die erste besteht darin, Client(...) oder Caller für die Clients-Eigenschaft in einer Hub-Methode aufzurufen:

public class ChatHub : Hub
{
    public async Task<string> WaitForMessage(string connectionId)
    {
        var message = await Clients.Client(connectionId).InvokeAsync<string>(
            "GetMessage");
        return message;
    }
}

Die zweite Möglichkeit besteht darin, Client(...) für eine Instanz von IHubContext<T> aufzurufen:

async Task SomeMethod(IHubContext<MyHub> context)
{
    string result = await context.Clients.Client(connectionID).InvokeAsync<string>(
        "GetMessage");
}

Stark typisierte Hubs können auch Werte aus Schnittstellenmethoden zurückgeben:

public interface IClient
{
    Task<string> GetMessage();
}

public class ChatHub : Hub<IClient>
{
    public async Task<string> WaitForMessage(string connectionId)
    {
        string message = await Clients.Client(connectionId).GetMessage();
        return message;
    }
}

Clients geben Ergebnisse in ihren .On(...)-Handlern zurück, wie unten gezeigt:

.NET-Client

hubConnection.On("GetMessage", async () =>
{
    Console.WriteLine("Enter message:");
    var message = await Console.In.ReadLineAsync();
    return message;
});

TypeScript-Client

hubConnection.on("GetMessage", async () => {
    let promise = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve("message");
        }, 100);
    });
    return promise;
});

Java-Client

hubConnection.onWithResult("GetMessage", () -> {
    return Single.just("message");
});

Ändern des Namens einer Hubmethode

Standardmäßig ist der Name einer Serverhubmethode der Name der .NET-Methode. Um dieses Standardverhalten für eine bestimmte Methode zu ändern, verwenden Sie das HubMethodName-Attribut. Der Client sollte diesen Namen anstelle des .NET-Methodennamens verwenden, wenn die Methode aufgerufen wird:

[HubMethodName("SendMessageToUser")]
public async Task DirectMessage(string user, string message)
    => await Clients.User(user).SendAsync("ReceiveMessage", user, message);

Einfügen von Diensten in einen Hub

Hubkonstruktoren können Dienste der Abhängigkeitsinjektion als Parameter akzeptieren, die in Eigenschaften der Klasse zur Verwendung in einer Hubmethode gespeichert werden können.

Beim Einfügen mehrerer Dienste für verschiedene Hubmethoden oder als alternatives Verfahren zum Schreiben von Code können Hubmethoden auch Dienste von DI akzeptieren. Standardmäßig werden Hubmethodenparameter überprüft und nach Möglichkeit von DI aufgelöst.

services.AddSingleton<IDatabaseService, DatabaseServiceImpl>();

// ...

public class ChatHub : Hub
{
    public Task SendMessage(string user, string message, IDatabaseService dbService)
    {
        var userName = dbService.GetUserName(user);
        return Clients.All.SendAsync("ReceiveMessage", userName, message);
    }
}

Wenn die implizite Auflösung von Parametern aus Diensten nicht gewünscht ist, deaktivieren Sie sie mit DisableImplicitFromServicesParameters. Um explizit anzugeben, welche Parameter in Hubmethoden von DI aufgelöst werden, verwenden Sie die Option DisableImplicitFromServicesParameters und das Attribut [FromServices] oder ein benutzerdefiniertes Attribut, das IFromServiceMetadata implementiert, für die Parameter der Hubmethode, die von DI aufgelöst werden sollen.

services.AddSingleton<IDatabaseService, DatabaseServiceImpl>();
services.AddSignalR(options =>
{
    options.DisableImplicitFromServicesParameters = true;
});

// ...

public class ChatHub : Hub
{
    public Task SendMessage(string user, string message,
        [FromServices] IDatabaseService dbService)
    {
        var userName = dbService.GetUserName(user);
        return Clients.All.SendAsync("ReceiveMessage", userName, message);
    }
}

Hinweis

Dieses Feature verwendet das IServiceProviderIsService-Element, das optional von DI-Implementierungen implementiert wird. Wenn der DI-Container der App dieses Feature nicht unterstützt, wird das Einfügen von Diensten in Hubmethoden nicht unterstützt.

Behandeln von Ereignissen für eine Verbindung

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

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

Überschreiben Sie die virtuelle OnDisconnectedAsync-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(), wird der exception-Parameter auf null festgelegt. Wenn der Client jedoch aufgrund eines Fehlers (z. B. eines Netzwerkfehlers) die Verbindung trennt, enthält der exception-Parameter eine Ausnahme, die den Fehler beschreibt:

public override async Task OnDisconnectedAsync(Exception? exception)
{
    await base.OnDisconnectedAsync(exception);
}

RemoveFromGroupAsync muss nicht in OnDisconnectedAsync aufgerufen werden, das Element wird automatisch für Sie verarbeitet.

Umgang mit Fehlern

Ausnahmen, die in Hubmethoden ausgelöst werden, werden an den Client gesendet, der die Methode aufgerufen hat. Auf dem JavaScript-Client gibt die invoke-Methode eine JavaScript-Promise zurück. Clients können einen catch-Handler an die zurückgegebene Zusage anfügen oder try/catch mit async/await verwenden, um Ausnahmen zu behandeln:

try {
  await connection.invoke("SendMessage", user, message);
} catch (err) {
  console.error(err);
}

Verbindungen werden nicht geschlossen, wenn ein Hub eine Ausnahme auslöst. SignalR gibt standardmäßig eine generische Fehlermeldung an den Client zurück, wie im folgenden Beispiel gezeigt:

Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'SendMessage' 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 stellt diese detaillierten Fehlermeldungen als Sicherheitsmaßnahme standardmäßig nicht zur Verfügung. Weitere Informationen dazu, warum Ausnahmedetails unterdrückt werden, finden Sie unter Sicherheitsüberlegungen in ASP.NET Core SignalR.

Wenn eine Ausnahmebedingung an den Client weitergegeben werden muss, verwenden Sie die HubException-Klasse. Wenn eine HubException in einer Hubmethode ausgelöst wird, SignalRsendet die gesamte Ausnahmemeldung an den Client (unverändert):

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 Stapelablaufverfolgung und andere Eigenschaften für die Ausnahme stehen dem Client nicht zur Verfügung.

Zusätzliche Ressourcen

Von Rachel Appel und Kevin Griffin

Die Hubs-API von SignalR ermöglicht es verbundenen Clients, Methoden auf dem Server aufzurufen. Der Server definiert Methoden, die vom Client aufgerufen werden, und der Client definiert Methoden, die vom Server aufgerufen werden. SignalR kümmert sich um alles, was erforderlich ist, um die Kommunikation zwischen Client und Server sowie zwischen Server und Client in Echtzeit zu ermöglichen.

Konfigurieren von SignalR-Hubs

Rufen Sie zum Registrieren der für SignalR-Hubs erforderlichen Dienste AddSignalR in Program.cs auf:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddSignalR();

Rufen Sie zum Konfigurieren von SignalR-Endpunkten MapHub (auch in Program.cs) auf:

app.MapRazorPages();
app.MapHub<ChatHub>("/Chat");

app.Run();

Hinweis

Serverseitige ASP.NET Core SignalR-Assemblys werden jetzt mit dem .NET Core SDK installiert. Weitere Informationen finden Sie unter SignalR-Assemblys im freigegebenen Framework.

Erstellen und Verwenden von Hubs

Erstellen Sie einen Hub, indem Sie eine Klasse deklarieren, die von Hub erbt. Fügen Sie der Klasse public-Methoden hinzu, um sie von Clients aus aufrufbar zu machen:

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

Hinweis

Hubs sind vorübergehende Objekte:

  • Speichern Sie den Zustand nicht in einer Eigenschaft der Hubklasse. Jeder Hubmethodenaufruf wird in einer neuen Hubinstanz ausgeführt.
  • Instanziieren Sie einen Hub nicht direkt mithilfe von Abhängigkeitsinjektion. Um Nachrichten von einer anderen Stelle in Ihrer Anwendung an einen Client zu senden, verwenden Sie IHubContext.
  • Verwenden Sie await beim Aufrufen asynchroner Methoden, die davon abhängen, dass der Hub aktiv bleibt. Eine Methode wie Clients.All.SendAsync(...) kann beispielsweise fehlschlagen, wenn sie ohne await aufgerufen wird und die Hubmethode abgeschlossen wird, bevor SendAsync abgeschlossen ist.

Das Context-Objekt

Die Hub-Klasse enthält 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 SignalR zugewiesen wird. Für jede Verbindung gibt es eine Verbindungs-ID.
UserIdentifier Ruft den Benutzerbezeichner ab. SignalR verwendet standardmäßig den ClaimTypes.NameIdentifier von ClaimsPrincipal, der der Verbindung zugeordnet ist, als Benutzerbezeichner.
User Ruft den ClaimsPrincipal ab, der dem aktuellen Benutzer zugeordnet ist.
Items Ruft eine Schlüssel-Wert-Sammlung 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 bestehen.
Features Ruft die Sammlung der Features ab, die für die Verbindung verfügbar sind. Derzeit ist diese Sammlung in den meisten Szenarien nicht erforderlich, daher wurde sie noch nicht ausführlich dokumentiert.
ConnectionAborted Ruft ein CancellationToken ab, das eine Benachrichtigung sendet, 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 null, wenn die Verbindung keiner HTTP-Anforderung zugeordnet ist. Verwenden Sie für HTTP-Verbindungen diese Methode, um Informationen wie HTTP-Header und Abfragezeichenfolgen abzurufen.
Abort Bricht die Verbindung ab.

Das Clients-Objekt

Die Hub-Klasse enthält 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, die 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 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 mit Ausnahme der angegebenen Verbindungen auf.
Groups Ruft eine Methode für mehrere Gruppen von Verbindungen auf.
OthersInGroup Ruft eine Methode für eine Gruppe von Verbindungen auf, wobei der Client, der die Hubmethode aufgerufen hat, ausgeschlossen wird.
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 vorherigen Tabellen gibt ein Objekt mit einer SendAsync-Methode zurück. Die SendAsync-Methode empfängt den Namen der aufzurufenden Clientmethode und alle Parameter.

Senden von Nachrichten an Clients

Verwenden Sie die Eigenschaften des Clients-Objekts, um Aufrufe für bestimmte Clients auszuführen. Im folgenden Beispiel gibt es drei Hubmethoden:

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

public async Task SendMessageToCaller(string user, string message)
    => await Clients.Caller.SendAsync("ReceiveMessage", user, message);

public async Task SendMessageToGroup(string user, string message)
    => await Clients.Group("SignalR Users").SendAsync("ReceiveMessage", user, message);

Stark typisierte Hubs

Ein Nachteil der Verwendung von SendAsync besteht darin, dass eine Zeichenfolge erforderlich ist, um die Clientmethode anzugeben, die aufgerufen werden soll. Dadurch kann es zu Laufzeitfehlern kommen, wenn der Methodenname falsch geschrieben ist oder im Client fehlt.

Eine Alternative zur Verwendung von SendAsync besteht darin, die Hub-Klasse mit Hub<T> stark zu typisieren. Im folgenden Beispiel wurde die ChatHub-Clientmethode in eine Schnittstelle namens IChatClient extrahiert:

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

Diese Schnittstelle kann verwendet werden, um das vorherige ChatHub-Beispiel so umzugestalten, dass es stark typisiert ist:

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

    public async Task SendMessageToCaller(string user, string message)
        => await Clients.Caller.ReceiveMessage(user, message);

    public async Task SendMessageToGroup(string user, string message)
        => await Clients.Group("SignalR Users").ReceiveMessage(user, message);
}

Die Verwendung von Hub<IChatClient> ermöglicht die Überprüfung der Clientmethoden zur Kompilierzeit. Dadurch werden Probleme verhindert, die durch die Verwendung von Zeichenfolgen verursacht werden, weil Hub<T> nur Zugriff auf die in der Schnittstelle definierten Methoden bereitstellen kann. Die Verwendung eines stark typisierten Hub<T> deaktiviert die Möglichkeit, SendAsync zu verwenden.

Hinweis

Das Async-Suffix wird nicht aus Methodennamen entfernt. Verwenden Sie MyMethodAsync nicht als Name, es sei denn, eine Clientmethode ist mit .on('MyMethodAsync') definiert.

Ändern des Namens einer Hubmethode

Standardmäßig ist der Name einer Serverhubmethode der Name der .NET-Methode. Um dieses Standardverhalten für eine bestimmte Methode zu ändern, verwenden Sie das HubMethodName-Attribut. Der Client sollte diesen Namen anstelle des .NET-Methodennamens verwenden, wenn die Methode aufgerufen wird:

[HubMethodName("SendMessageToUser")]
public async Task DirectMessage(string user, string message)
    => await Clients.User(user).SendAsync("ReceiveMessage", user, message);

Behandeln von Ereignissen für eine Verbindung

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

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

Überschreiben Sie die virtuelle OnDisconnectedAsync-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(), wird der exception-Parameter auf null festgelegt. Wenn der Client jedoch aufgrund eines Fehlers (z. B. eines Netzwerkfehlers) die Verbindung trennt, enthält der exception-Parameter eine Ausnahme, die den Fehler beschreibt:

public override async Task OnDisconnectedAsync(Exception? exception)
{
    await base.OnDisconnectedAsync(exception);
}

RemoveFromGroupAsync muss nicht in OnDisconnectedAsync aufgerufen werden, das Element wird automatisch für Sie verarbeitet.

Umgang mit Fehlern

Ausnahmen, die in Hubmethoden ausgelöst werden, werden an den Client gesendet, der die Methode aufgerufen hat. Auf dem JavaScript-Client gibt die invoke-Methode eine JavaScript-Promise zurück. Clients können einen catch-Handler an die zurückgegebene Zusage anfügen oder try/catch mit async/await verwenden, um Ausnahmen zu behandeln:

try {
  await connection.invoke("SendMessage", user, message);
} catch (err) {
  console.error(err);
}

Verbindungen werden nicht geschlossen, wenn ein Hub eine Ausnahme auslöst. SignalR gibt standardmäßig eine generische Fehlermeldung an den Client zurück, wie im folgenden Beispiel gezeigt:

Microsoft.AspNetCore.SignalR.HubException: An unexpected error occurred invoking 'SendMessage' 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 stellt diese detaillierten Fehlermeldungen als Sicherheitsmaßnahme standardmäßig nicht zur Verfügung. Weitere Informationen dazu, warum Ausnahmedetails unterdrückt werden, finden Sie unter Sicherheitsüberlegungen in ASP.NET Core SignalR.

Wenn eine Ausnahmebedingung an den Client weitergegeben werden muss, verwenden Sie die HubException-Klasse. Wenn eine HubException in einer Hubmethode ausgelöst wird, SignalRsendet die gesamte Ausnahmemeldung an den Client (unverändert):

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 Stapelablaufverfolgung und andere Eigenschaften für die Ausnahme stehen dem Client nicht zur Verfügung.

Zusätzliche Ressourcen

Von Rachel Appel und Kevin Griffin

Beispielcode anzeigen oder herunterladen (Vorgehensweise zum Herunterladen)

Was ist ein SignalR-Hub?

Die Hubs-API von SignalR ermöglicht es Ihnen, Methoden auf verbundenen Clients vom Server aus aufzurufen. Im Servercode definieren Sie Methoden, die vom Client aufgerufen werden. Im Clientcode definieren Sie Methoden, die vom Server aufgerufen werden. SignalR kümmert sich hinter den Kulissen um 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 Aufrufe von AddSignalR konfiguriert werden:

services.AddSignalR();

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

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

Hinweis

Serverseitige ASP.NET Core SignalR-Assemblys werden jetzt mit dem .NET Core SDK installiert. Weitere Informationen finden Sie unter SignalR-Assemblys im freigegebenen Framework.

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 public definiert sind:

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

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

Hinweis

Hubs sind vorübergehende Objekte:

  • Speichern Sie den Zustand nicht in einer Eigenschaft in der Hubklasse. Jeder Hubmethodenaufruf wird in einer neuen Hubinstanz ausgeführt.
  • Instanziieren Sie einen Hub nicht direkt mithilfe von Abhängigkeitsinjektion. Um Nachrichten von einer anderen Stelle in Ihrer Anwendung an einen Client zu senden, verwenden Sie IHubContext.
  • Verwenden Sie await beim Aufrufen asynchroner Methoden, die davon abhängen, dass der Hub aktiv bleibt. Eine Methode wie Clients.All.SendAsync(...) kann beispielsweise fehlschlagen, wenn sie ohne await aufgerufen wird und die Hubmethode abgeschlossen wird, bevor SendAsync abgeschlossen ist.

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 SignalR zugewiesen wird. Für jede Verbindung gibt es eine Verbindungs-ID.
UserIdentifier Ruft den Benutzerbezeichner ab. SignalR verwendet standardmäßig den ClaimTypes.NameIdentifier von ClaimsPrincipal, der der Verbindung zugeordnet ist, als Benutzerbezeichner.
User Ruft den ClaimsPrincipal ab, der dem aktuellen Benutzer zugeordnet ist.
Items Ruft eine Schlüssel-Wert-Sammlung 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 bestehen.
Features Ruft die Sammlung der Features ab, die für die Verbindung verfügbar sind. Derzeit ist diese Sammlung in den meisten Szenarien nicht erforderlich, daher wurde sie noch nicht ausführlich dokumentiert.
ConnectionAborted Ruft ein CancellationToken ab, das eine Benachrichtigung sendet, 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 null, wenn 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 Hub-Klasse verfügt über 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, die 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 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 mit Ausnahme der angegebenen Verbindungen auf.
Groups Ruft eine Methode für mehrere Gruppen von Verbindungen auf.
OthersInGroup Ruft eine Methode für eine Gruppe von Verbindungen auf, wobei der Client, der die Hubmethode aufgerufen hat, ausgeschlossen wird.
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 vorherigen Tabellen gibt ein Objekt mit einer SendAsync-Methode zurück. Mit der SendAsync-Methode können Sie den Namen und die Parameter der Clientmethode angeben, die aufgerufen werden soll.

Senden von Nachrichten an Clients

Verwenden Sie die Eigenschaften des Clients-Objekts, um Aufrufe für bestimmte Clients auszuführen. Im folgenden Beispiel gibt es drei Hubmethoden:

  • SendMessage sendet mithilfe von Clients.All eine Nachricht an alle verbundenen Clients .
  • SendMessageToCaller sendet mithilfe von Clients.Caller eine Nachricht zurück an den 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 besteht darin, dass eine magische Zeichenfolge erforderlich ist, um die Clientmethode anzugeben, die aufgerufen werden soll. Dadurch kann es zu Laufzeitfehlern kommen, wenn der Methodenname falsch geschrieben ist oder im Client fehlt.

Eine Alternative zur Verwendung von SendAsync besteht darin, die Hub-Klasse mit Hub<T> stark zu typisieren. 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 verwendet werden, um das vorherige ChatHub-Beispiel umzugestalten:

    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 Hub<IChatClient> ermöglicht die Überprüfung der Clientmethoden zur Kompilierzeit. Dadurch werden Probleme verhindert, die durch die Verwendung von magischen Zeichenfolgen verursacht werden, weil Hub<T> nur Zugriff auf die in der Schnittstelle definierten Methoden bereitstellen kann.

Die Verwendung eines stark typisierten Hub<T> deaktiviert die Möglichkeit, SendAsync zu verwenden. Alle Methoden, die für die Schnittstelle definiert sind, können weiterhin als asynchron definiert werden. Tatsächlich sollte jede dieser Methoden einen 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. Wenn Ihre Client-Methode nicht mit .on('MyMethodAsync') definiert 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 diese Standardeinstellung zu ändern und manuell einen Namen für die Methode anzugeben. Der Client sollte diesen Namen anstelle des .NET-Methodennamens verwenden, wenn die Methode aufgerufen wird:

[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 Hubs-API von SignalR stellt die virtuellen OnConnectedAsync- und OnDisconnectedAsync-Methoden zum Verwalten und Nachverfolgen von Verbindungen bereit. Überschreiben Sie die virtuelle OnConnectedAsync-Methode, um Aktionen auszuführen, wenn ein Client eine Verbindung mit dem Hub herstellt, ihn z. B. einer Gruppe hinzufügt:

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

Überschreiben Sie die virtuelle OnDisconnectedAsync-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()), lautet der exception-Parameter null. Wenn der Client jedoch aufgrund eines Fehlers getrennt wird (z. B. durch einen Netzwerkfehler), enthält der exception-Parameter eine Ausnahme, die den Fehler beschreibt:

public override async Task OnDisconnectedAsync(Exception exception)
{
    await Clients.Group("SignalR Users").SendAsync("ReceiveMessage", "I", "disconnect");
    await base.OnDisconnectedAsync(exception);
}

RemoveFromGroupAsync muss nicht in OnDisconnectedAsync aufgerufen werden, das Element wird automatisch für Sie verarbeitet.

Warnung

Sicherheitswarnung: Das Verfügbarmachen von ConnectionId kann zu einem böswilligen Identitätswechsel führen, wenn die Version des SignalR-Servers oder Clients ASP.NET Core Version 2.2 oder früher ist.

Umgang mit Fehlern

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-Promise zurück. Wenn der Client einen Fehler mit einem an die Zusage angefügten Handler mit catch empfängt, wird er aufgerufen und als JavaScript-Error-Objekt übergeben:

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

Wenn Ihr Hub eine Ausnahme auslöst, werden Verbindungen nicht geschlossen. SignalR gibt standardmäßig 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 stellt diese detaillierten Fehlermeldungen als Sicherheitsmaßnahme standardmäßig nicht zur Verfügung. Weitere Informationen dazu, warum Ausnahmedetails unterdrückt werden, finden Sie unter Sicherheitsüberlegungen in ASP.NET Core SignalR.

Wenn Sie eine außergewöhnliche Bedingung haben, die Sie an den Client weitergeben möchten, können Sie die HubException-Klasse verwenden. Wenn Sie eine HubException aus Ihrer Hubmethode auslösen, sendetSignalR 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 Stapelablaufverfolgung und andere Eigenschaften für die Ausnahme stehen dem Client nicht zur Verfügung.

Zusätzliche Ressourcen

Von Rachel Appel und Kevin Griffin

Beispielcode anzeigen oder herunterladen (Vorgehensweise zum Herunterladen)

Was ist ein SignalR-Hub?

Die Hubs-API von SignalR ermöglicht es Ihnen, Methoden auf verbundenen Clients vom Server aus aufzurufen. Im Servercode definieren Sie Methoden, die vom Client aufgerufen werden. Im Clientcode definieren Sie Methoden, die vom Server aufgerufen werden. SignalR kümmert sich hinter den Kulissen um 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 Aufrufe von AddSignalR konfiguriert werden:

services.AddSignalR();

Wenn Sie einer ASP.NET Core-App SignalR-Funktionen hinzufügen, richten Sie SignalR-Routen ein, indem Sie UseSignalR in der 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 public definiert sind:

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

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

Hinweis

Hubs sind vorübergehende Objekte:

  • Speichern Sie den Zustand nicht in einer Eigenschaft in der Hubklasse. Jeder Hubmethodenaufruf wird in einer neuen Hubinstanz ausgeführt.
  • Instanziieren Sie einen Hub nicht direkt mithilfe von Abhängigkeitsinjektion. Um Nachrichten von einer anderen Stelle in Ihrer Anwendung an einen Client zu senden, verwenden Sie IHubContext.
  • Verwenden Sie await beim Aufrufen asynchroner Methoden, die davon abhängen, dass der Hub aktiv bleibt. Eine Methode wie Clients.All.SendAsync(...) kann beispielsweise fehlschlagen, wenn sie ohne await aufgerufen wird und die Hubmethode abgeschlossen wird, bevor SendAsync abgeschlossen ist.

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 SignalR zugewiesen wird. Für jede Verbindung gibt es eine Verbindungs-ID.
UserIdentifier Ruft den Benutzerbezeichner ab. SignalR verwendet standardmäßig den ClaimTypes.NameIdentifier von ClaimsPrincipal, der der Verbindung zugeordnet ist, als Benutzerbezeichner.
User Ruft den ClaimsPrincipal ab, der dem aktuellen Benutzer zugeordnet ist.
Items Ruft eine Schlüssel-Wert-Sammlung 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 bestehen.
Features Ruft die Sammlung der Features ab, die für die Verbindung verfügbar sind. Derzeit ist diese Sammlung in den meisten Szenarien nicht erforderlich, daher wurde sie noch nicht ausführlich dokumentiert.
ConnectionAborted Ruft ein CancellationToken ab, das eine Benachrichtigung sendet, 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 null, wenn 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 Hub-Klasse verfügt über 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, die 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 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 mit Ausnahme der angegebenen Verbindungen auf.
Groups Ruft eine Methode für mehrere Gruppen von Verbindungen auf.
OthersInGroup Ruft eine Methode für eine Gruppe von Verbindungen auf, wobei der Client, der die Hubmethode aufgerufen hat, ausgeschlossen wird.
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 vorherigen Tabellen gibt ein Objekt mit einer SendAsync-Methode zurück. Mit der SendAsync-Methode können Sie den Namen und die Parameter der Clientmethode angeben, die aufgerufen werden soll.

Senden von Nachrichten an Clients

Verwenden Sie die Eigenschaften des Clients-Objekts, um Aufrufe für bestimmte Clients auszuführen. Im folgenden Beispiel gibt es drei Hubmethoden:

  • SendMessage sendet mithilfe von Clients.All eine Nachricht an alle verbundenen Clients .
  • SendMessageToCaller sendet mithilfe von Clients.Caller eine Nachricht zurück an den 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 besteht darin, dass eine magische Zeichenfolge erforderlich ist, um die Clientmethode anzugeben, die aufgerufen werden soll. Dadurch kann es zu Laufzeitfehlern kommen, wenn der Methodenname falsch geschrieben ist oder im Client fehlt.

Eine Alternative zur Verwendung von SendAsync besteht darin, die Hub-Klasse mit Hub<T> stark zu typisieren. 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 verwendet werden, um das vorherige ChatHub-Beispiel umzugestalten:

    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 Hub<IChatClient> ermöglicht die Überprüfung der Clientmethoden zur Kompilierzeit. Dadurch werden Probleme verhindert, die durch die Verwendung von magischen Zeichenfolgen verursacht werden, weil Hub<T> nur Zugriff auf die in der Schnittstelle definierten Methoden bereitstellen kann.

Die Verwendung eines stark typisierten Hub<T> deaktiviert die Möglichkeit, SendAsync zu verwenden. Alle Methoden, die für die Schnittstelle definiert sind, können weiterhin als asynchron definiert werden. Tatsächlich sollte jede dieser Methoden einen 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. Wenn Ihre Client-Methode nicht mit .on('MyMethodAsync') definiert 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 diese Standardeinstellung zu ändern und manuell einen Namen für die Methode anzugeben. Der Client sollte diesen Namen anstelle des .NET-Methodennamens verwenden, wenn die Methode aufgerufen wird:

[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 Hubs-API von SignalR stellt die virtuellen OnConnectedAsync- und OnDisconnectedAsync-Methoden zum Verwalten und Nachverfolgen von Verbindungen bereit. Überschreiben Sie die virtuelle OnConnectedAsync-Methode, um Aktionen auszuführen, wenn ein Client eine Verbindung mit dem Hub herstellt, ihn z. B. einer Gruppe hinzufügt:

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

Überschreiben Sie die virtuelle OnDisconnectedAsync-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()), lautet der exception-Parameter null. Wenn der Client jedoch aufgrund eines Fehlers getrennt wird (z. B. durch einen Netzwerkfehler), enthält der exception-Parameter eine Ausnahme, die den Fehler beschreibt:

public override async Task OnDisconnectedAsync(Exception exception)
{
    await Clients.Group("SignalR Users").SendAsync("ReceiveMessage", "I", "disconnect");
    await base.OnDisconnectedAsync(exception);
}

RemoveFromGroupAsync muss nicht in OnDisconnectedAsync aufgerufen werden, das Element wird automatisch für Sie verarbeitet.

Warnung

Sicherheitswarnung: Das Verfügbarmachen von ConnectionId kann zu einem böswilligen Identitätswechsel führen, wenn die Version des SignalR-Servers oder Clients ASP.NET Core Version 2.2 oder früher ist.

Umgang mit Fehlern

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-Promise zurück. Wenn der Client einen Fehler mit einem an die Zusage angefügten Handler mit catch empfängt, wird er aufgerufen und als JavaScript-Error-Objekt übergeben:

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

Wenn Ihr Hub eine Ausnahme auslöst, werden Verbindungen nicht geschlossen. SignalR gibt standardmäßig 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 stellt diese detaillierten Fehlermeldungen als Sicherheitsmaßnahme standardmäßig nicht zur Verfügung. Weitere Informationen dazu, warum Ausnahmedetails unterdrückt werden, finden Sie unter Sicherheitsüberlegungen in ASP.NET Core SignalR.

Wenn Sie eine außergewöhnliche Bedingung haben, die Sie an den Client weitergeben möchten, können Sie die HubException-Klasse verwenden. Wenn Sie eine HubException aus Ihrer Hubmethode auslösen, sendetSignalR 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 Stapelablaufverfolgung und andere Eigenschaften für die Ausnahme stehen dem Client nicht zur Verfügung.

Zusätzliche Ressourcen