Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Dieser Artikel enthält Anleitungen für das Erstellen von auf SignalR-basierten APIs.
Verwenden von benutzerdefinierten Objektparametern, um die Abwärtskompatibilität sicherzustellen
Das Hinzufügen von Parametern zu einer SignalR Hubmethode (entweder auf dem Client oder dem Server) ist eine bedeutende Änderung. Dies bedeutet, dass ältere Clients/Server Fehler erhalten, wenn sie versuchen, die Methode ohne die entsprechende Anzahl von Parametern aufzurufen. Das Hinzufügen von Eigenschaften zu einem benutzerdefinierten Objektparameter ist jedoch keine bedeutende Änderung. Dies kann verwendet werden, um kompatible APIs zu entwerfen, die für Änderungen auf dem Client oder auf dem Server widerstandsfähig sind.
Betrachten Sie z. B. eine serverseitige API wie die folgende:
public int GetTotalLength(string param1)
{
return param1.Length;
}
Der JavaScript-Client ruft diese Methode wie folgt auf: invoke
connection.invoke("GetTotalLength", "value1");
Wenn Sie der Servermethode später einen zweiten Parameter hinzufügen, geben ältere Clients diesen Parameterwert nicht an. Beispiel:
public int GetTotalLength(string param1, string param2)
{
return param1.Length + param2.Length;
}
Wenn der alte Client versucht, diese Methode aufzurufen, wird ein Fehler wie folgt angezeigt:
Microsoft.AspNetCore.SignalR.HubException: Failed to invoke 'GetTotalLength' due to an error on the server.
Auf dem Server wird eine Protokollmeldung wie folgt angezeigt:
System.IO.InvalidDataException: Invocation provides 1 argument(s) but target expects 2.
Der alte Client hat nur einen Parameter gesendet, aber die neuere Server-API erforderte zwei Parameter. Die Verwendung von benutzerdefinierten Objekten als Parameter bietet Ihnen mehr Flexibilität. Lassen Sie uns die ursprüngliche API neu gestalten, um ein benutzerdefiniertes Objekt zu verwenden:
public class TotalLengthRequest
{
public string Param1 { get; set; }
}
public int GetTotalLength(TotalLengthRequest req)
{
return req.Param1.Length;
}
Nun verwendet der Client ein Objekt, um die Methode aufzurufen:
connection.invoke("GetTotalLength", { param1: "value1" });
Anstatt einen Parameter hinzuzufügen, fügen Sie dem TotalLengthRequest Objekt eine Eigenschaft hinzu:
public class TotalLengthRequest
{
public string Param1 { get; set; }
public string Param2 { get; set; }
}
public int GetTotalLength(TotalLengthRequest req)
{
var length = req.Param1.Length;
if (req.Param2 != null)
{
length += req.Param2.Length;
}
return length;
}
Wenn der alte Client einen einzelnen Parameter sendet, bleibt die zusätzliche Param2 Eigenschaft erhalten null. Sie können eine von einem älteren Klienten gesendete Nachricht erkennen, indem Sie Param2 auf null überprüfen und einen Standardwert anwenden. Ein neuer Client kann beide Parameter senden.
connection.invoke("GetTotalLength", { param1: "value1", param2: "value2" });
Die gleiche Technik funktioniert für Methoden, die auf dem Client definiert sind. Sie können ein benutzerdefiniertes Objekt von der Serverseite senden:
public async Task Broadcast(string message)
{
await Clients.All.SendAsync("ReceiveMessage", new
{
Message = message
});
}
Auf der Clientseite greifen Sie auf die Message Eigenschaft zu, anstatt einen Parameter zu verwenden:
connection.on("ReceiveMessage", (req) => {
appendMessageToChatWindow(req.message);
});
Wenn Sie sich später entscheiden, den Absender der Nachricht zur Nutzlast hinzuzufügen, fügen Sie dem Objekt eine Eigenschaft hinzu:
public async Task Broadcast(string message)
{
await Clients.All.SendAsync("ReceiveMessage", new
{
Sender = Context.User.Identity.Name,
Message = message
});
}
Die älteren Clients erwarten den Sender Wert nicht, sodass sie ihn ignorieren. Ein neuer Client kann die neue Eigenschaft annehmen, indem er ein Update durchführt, um sie zu lesen.
connection.on("ReceiveMessage", (req) => {
let message = req.message;
if (req.sender) {
message = req.sender + ": " + message;
}
appendMessageToChatWindow(message);
});
In diesem Fall ist der neue Client auch tolerant von einem alten Server, der den Sender Wert nicht bereitstellt. Da der alte Server den Sender Wert nicht bereitstellt, überprüft der Client, ob er vorhanden ist, bevor er darauf zugreift.