Verwenden von MessagePack Hub Protocol in SignalR für ASP.NET Core
In diesem Artikel wird davon ausgegangen, dass der Leser mit den Themen vertraut ist, die unter Erste Schritte mit ASP.NET Core SignalRbehandelt werden.
Was ist MessagePack?
MessagePack ist ein schnelles und kompaktes binäres Serialisierungsformat. Dieses Format ist nützlich, wenn Leistung und Bandbreite eine Rolle spielen, da in ihm kleinere Nachrichten als in JSON erstellt werden. Die binären Nachrichten sind beim Untersuchen von Netzwerkablaufverfolgungen und Protokollen nicht lesbar, es sei denn, die Bytes werden über einen MessagePack-Parser übergeben. SignalR verfügt über integrierte Unterstützung für das MessagePack-Format und stellt APIs bereit, die vom Client und Server verwendet werden können.
Konfigurieren von MessagePack auf dem Server
Installieren Sie das Microsoft.AspNetCore.SignalR.Protocols.MessagePack
-Paket in Ihrer App, um das MessagePack Hub Protocol auf dem Server zu aktivieren. Fügen Sie in der Startup.ConfigureServices
-Methode dem AddSignalR
-Aufruf AddMessagePackProtocol
hinzu, um MessagePack-Unterstützung auf dem Server zu aktivieren.
services.AddSignalR()
.AddMessagePackProtocol();
Hinweis
JSON ist standardmäßig aktiviert. Durch das Hinzufügen von MessagePack werden sowohl JSON- als auch MessagePack-Clients unterstützt.
Um anzupassen, wie MessagePack Daten formatiert, nimmt AddMessagePackProtocol
einen Delegaten zum Konfigurieren von Optionen an. In diesem Delegaten wird die SerializerOptions
-Eigenschaft verwendet, um MessagePack-Serialisierungsoptionen zu konfigurieren. Weitere Informationen zur Funktionsweise der Resolver finden Sie in der MessagePack-Bibliothek unter MessagePack-CSharp. Attribute können für die Objekte verwendet werden, die Sie serialisieren möchten, um zu definieren, wie sie behandelt werden sollen.
services.AddSignalR()
.AddMessagePackProtocol(options =>
{
options.SerializerOptions = MessagePackSerializerOptions.Standard
.WithResolver(new CustomResolver())
.WithSecurity(MessagePackSecurity.UntrustedData);
});
Warnung
Es wird dringend empfohlen, CVE-2020-5234 zu lesen und die empfohlenen Patches anzuwenden. Beispielsweise Aufrufen von .WithSecurity(MessagePackSecurity.UntrustedData)
, wenn SerializerOptions
ersetzt wird.
Konfigurieren von MessagePack auf dem Client
Hinweis
JSON ist für die unterstützten Clients standardmäßig aktiviert. Clients können nur ein einziges Protokoll unterstützen. Das Hinzufügen von MessagePack-Unterstützung ersetzt alle zuvor konfigurierten Protokolle.
.NET-Client
Um MessagePack im .NET-Client zu aktivieren, installieren Sie das Microsoft.AspNetCore.SignalR.Protocols.MessagePack
-Paket und rufen AddMessagePackProtocol
für HubConnectionBuilder
auf.
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.DependencyInjection;
var hubConnection = new HubConnectionBuilder()
.WithUrl("/chathub")
.AddMessagePackProtocol()
.Build();
Hinweis
Dieser AddMessagePackProtocol
-Aufruf nimmt einen Delegaten zum Konfigurieren von Optionen an, genau wie der Server.
JavaScript-Client
MessagePack-Unterstützung für den JavaScript-Client wird vom npm-Paket @microsoft/signalr-protocol-msgpack bereitgestellt. Installieren Sie das Paket, indem Sie den folgenden Befehl in einer Befehlsshell ausführen:
npm install @microsoft/signalr-protocol-msgpack
Nach der Installation des npm-Pakets kann das Modul direkt über einen JavaScript-Modulladeprogramm verwendet oder in den Browser importiert werden, indem auf die folgende Datei verwiesen wird:
node_modules\@microsoft\signalr-protocol-msgpack\dist\browser\signalr-protocol-msgpack.js
Auf die folgenden erforderlichen JavaScript-Dateien muss in der unten gezeigten Reihenfolge verwiesen werden:
<script src="~/lib/signalr/signalr.js"></script>
<script src="~/lib/signalr/signalr-protocol-msgpack.js"></script>
Wenn Sie .withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
zu HubConnectionBuilder
hinzufügen, wird der Client für die Verwendung des MessagePack-Protokolls konfiguriert, wenn eine Verbindung mit einem Server hergestellt wird.
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
.build();
Derzeit gibt es keine Konfigurationsoptionen für das MessagePack-Protokoll auf dem JavaScript-Client.
Java-Client
Um MessagePack mit Java zu aktivieren, installieren Sie das com.microsoft.signalr.messagepack
-Paket. Wenn Sie Gradle verwenden, fügen Sie dem Abschnitt dependencies
der Datei build.gradle die folgende Zeile hinzu:
implementation 'com.microsoft.signalr.messagepack:signalr-messagepack:5.0.0'
Wenn Sie Maven verwenden, fügen Sie die folgenden Zeilen innerhalb des <dependencies>
-Elements der Datei pom.xml
hinzu:
<dependency>
<groupId>com.microsoft.signalr.messagepack</groupId>
<artifactId>signalr</artifactId>
<version>5.0.0</version>
</dependency>
Rufen Sie withHubProtocol(new MessagePackHubProtocol())
für HubConnectionBuilder
auf.
HubConnection messagePackConnection = HubConnectionBuilder.create("YOUR HUB URL HERE")
.withHubProtocol(new MessagePackHubProtocol())
.build();
MessagePack-Überlegungen
Bei Verwendung von MessagePack Hub Protocol gibt es einige Punkte zu beachten.
Bei MessagePack wird zwischen Groß-und Kleinschreibung unterschieden.
Beim MessagePack-Protokoll wird zwischen Groß-und Kleinschreibung unterschieden. Betrachten Sie beispielsweise die folgende C#-Klasse:
public class ChatMessage
{
public string Sender { get; }
public string Message { get; }
}
Beim Senden vom JavaScript-Client müssen Sie PascalCased
-Eigenschaftennamen verwenden, da die Groß- und Kleinschreibung genau mit der C#-Klasse übereinstimmen muss. Beispiel:
connection.invoke("SomeMethod", { Sender: "Sally", Message: "Hello!" });
Bei Verwendung von camelCased
-Namen wird nicht ordnungsgemäß an die C#-Klasse gebunden. Sie können dieses Problem umgehen, indem Sie das Key
-Attribut verwenden, um einen anderen Namen für die MessagePack-Eigenschaft anzugeben. Weitere Informationen finden Sie in der Dokumentation zu MessagePack-CSharp.
DateTime.Kind wird beim Serialisieren/Deserialisieren nicht beibehalten.
Das MessagePack-Protokoll bietet keine Möglichkeit, den Kind
-Wert eines DateTime
-Elements zu codieren. Daher wird MessagePack Hub Protocol beim Deserialisieren eines Datums in das UTC-Format konvertiert, wenn DateTime.Kind
DateTimeKind.Local
ist. Andernfalls wird die Uhrzeit nicht verändert und unverändert übergeben. Wenn Sie mit DateTime
-Werten arbeiten, empfiehlt es sich, diese vor dem Senden in UTC zu konvertieren. Konvertieren Sie sie aus UTC in Ortszeit, wenn Sie sie empfangen.
MessagePack-Unterstützung in einer Vorabkompilierungsumgebung
Die MessagePack-CSharp-Bibliothek, die vom .NET-Client und -Server verwendet wird, verwendet Codegenerierung, um die Serialisierung zu optimieren. Daher wird sie in Umgebungen, in denen Vorabkompilierung verwendet wird (z. B. Xamarin iOS oder Unity), standardmäßig nicht unterstützt. Es ist möglich, MessagePack in diesen Umgebungen zu verwenden, indem der Serialisierungs-/Deserialisierungscode „vorab generiert“ wird. Weitere Informationen finden Sie in der Dokumentation zu MessagePack-CSharp. Nachdem Sie die Serialisierungsmodule vorab generiert haben, können Sie sie mithilfe des Konfigurationsdelegaten registrieren, der an AddMessagePackProtocol
übergeben wird:
services.AddSignalR()
.AddMessagePackProtocol(options =>
{
StaticCompositeResolver.Instance.Register(
MessagePack.Resolvers.GeneratedResolver.Instance,
MessagePack.Resolvers.StandardResolver.Instance
);
options.SerializerOptions = MessagePackSerializerOptions.Standard
.WithResolver(StaticCompositeResolver.Instance)
.WithSecurity(MessagePackSecurity.UntrustedData);
});
Typüberprüfungen sind in MessagePack strenger
Das JSON Hub-Protokoll führt während der Deserialisierung Typkonvertierungen durch. Wenn das eingehende Objekt beispielsweise über einen Eigenschaftswert verfügt, der eine Zahl ({ foo: 42 }
) ist, die Eigenschaft der .NET-Klasse aber vom Typ string
ist, wird der Wert konvertiert. MessagePack führt diese Konvertierung jedoch nicht durch und löst eine Ausnahme aus, die in serverseitigen Protokollen (und in der Konsole) angezeigt wird:
InvalidDataException: Error binding arguments. Make sure that the types of the provided values match the types of the hub method being invoked.
Weitere Informationen zu dieser Einschränkung finden Sie unter im GitHub-Issue aspnet/SignalR#2937.
Zeichen und Zeichenfolgen in Java
Im Java-Client werden char
-Objekte als String
-Objekte mit einem Zeichen serialisiert. Dies steht im Gegensatz zum C#- oder JavaScript-Client, der sie als short
-Objekte serialisiert. Die MessagePack-Spezifikation selbst definiert das Verhalten für char
-Objekte nicht, daher liegt es beim Autor der Bibliothek, festzulegen, wie diese serialisiert werden sollen. Der Unterschied im Verhalten zwischen unseren Clients ist ein Ergebnis der Bibliotheken, die wir für unsere Implementierungen verwendet haben.
Zusätzliche Ressourcen
In diesem Artikel wird davon ausgegangen, dass der Leser mit den Themen vertraut ist, die unter Erste Schritte mit ASP.NET Core SignalRbehandelt werden.
Was ist MessagePack?
MessagePack ist ein schnelles und kompaktes binäres Serialisierungsformat. Dieses Format ist nützlich, wenn Leistung und Bandbreite eine Rolle spielen, da in ihm kleinere Nachrichten im Vergleich zu JSON erstellt werden. Die binären Nachrichten sind beim Untersuchen von Netzwerkablaufverfolgungen und Protokollen nicht lesbar, es sei denn, die Bytes werden über einen MessagePack-Parser übergeben. SignalR verfügt über integrierte Unterstützung für das MessagePack-Format und stellt APIs bereit, die vom Client und Server verwendet werden können.
Konfigurieren von MessagePack auf dem Server
Installieren Sie das Microsoft.AspNetCore.SignalR.Protocols.MessagePack
-Paket in Ihrer App, um das MessagePack Hub Protocol auf dem Server zu aktivieren. Fügen Sie in der Startup.ConfigureServices
-Methode dem AddSignalR
-Aufruf AddMessagePackProtocol
hinzu, um MessagePack-Unterstützung auf dem Server zu aktivieren.
Hinweis
JSON ist standardmäßig aktiviert. Durch das Hinzufügen von MessagePack werden sowohl JSON- als auch MessagePack-Clients unterstützt.
services.AddSignalR()
.AddMessagePackProtocol();
Um anzupassen, wie MessagePack Daten formatiert, nimmt AddMessagePackProtocol
einen Delegaten zum Konfigurieren von Optionen an. In diesem Delegaten kann die SerializerOptions
-Eigenschaft verwendet werden, um MessagePack-Serialisierungsoptionen zu konfigurieren. Weitere Informationen zur Funktionsweise der Resolver finden Sie in der MessagePack-Bibliothek unter MessagePack-CSharp. Attribute können für die Objekte verwendet werden, die Sie serialisieren möchten, um zu definieren, wie sie behandelt werden sollen.
services.AddSignalR()
.AddMessagePackProtocol(options =>
{
options.SerializerOptions = MessagePackSerializerOptions.Standard
.WithResolver(new CustomResolver())
.WithSecurity(MessagePackSecurity.UntrustedData);
});
Warnung
Es wird dringend empfohlen, CVE-2020-5234 zu lesen und die empfohlenen Patches anzuwenden. Beispielsweise Aufrufen von .WithSecurity(MessagePackSecurity.UntrustedData)
, wenn SerializerOptions
ersetzt wird.
Konfigurieren von MessagePack auf dem Client
Hinweis
JSON ist für die unterstützten Clients standardmäßig aktiviert. Clients können nur ein einziges Protokoll unterstützen. Das Hinzufügen von MessagePack-Unterstützung ersetzt alle zuvor konfigurierten Protokolle.
.NET-Client
Um MessagePack im .NET-Client zu aktivieren, installieren Sie das Microsoft.AspNetCore.SignalR.Protocols.MessagePack
-Paket und rufen AddMessagePackProtocol
für HubConnectionBuilder
auf.
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.DependencyInjection;
var hubConnection = new HubConnectionBuilder()
.WithUrl("/chathub")
.AddMessagePackProtocol()
.Build();
Hinweis
Dieser AddMessagePackProtocol
-Aufruf nimmt einen Delegaten zum Konfigurieren von Optionen an, genau wie der Server.
JavaScript-Client
MessagePack-Unterstützung für den JavaScript-Client wird vom npm-Paket @microsoft/signalr-protocol-msgpack bereitgestellt. Installieren Sie das Paket, indem Sie den folgenden Befehl in einer Befehlsshell ausführen:
npm install @microsoft/signalr-protocol-msgpack
Nach der Installation des npm-Pakets kann das Modul direkt über einen JavaScript-Modulladeprogramm verwendet oder in den Browser importiert werden, indem auf die folgende Datei verwiesen wird:
node_modules\@microsoft\signalr-protocol-msgpack\dist\browser\signalr-protocol-msgpack.js
In einem Browser muss auch auf die msgpack5
-Bibliothek verwiesen werden. Verwenden Sie ein <script>
-Tag, um einen Verweis zu erstellen. Die Bibliothek finden Sie unter node_modules\msgpack5\dist\msgpack5.jsjs.
Hinweis
Bei Verwendung des <script>
-Elements ist die Reihenfolge wichtig. Wenn signalr-protocol-msgpack.js
vor msgpack5.js
referenziert wird, tritt beim Versuch, eine Verbindung mit MessagePack herzustellen, ein Fehler auf. signalr.js
muss auch vor signalr-protocol-msgpack.js
vorhanden sein.
<script src="~/lib/signalr/signalr.js"></script>
<script src="~/lib/msgpack5/msgpack5.js"></script>
<script src="~/lib/signalr/signalr-protocol-msgpack.js"></script>
Wenn Sie .withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
zu HubConnectionBuilder
hinzufügen, wird der Client für die Verwendung des MessagePack-Protokolls konfiguriert, wenn eine Verbindung mit einem Server hergestellt wird.
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
.build();
Hinweis
Derzeit gibt es keine Konfigurationsoptionen für das MessagePack-Protokoll auf dem JavaScript-Client.
Java-Client
Um MessagePack mit Java zu aktivieren, installieren Sie das com.microsoft.signalr.messagepack
-Paket. Wenn Sie Gradle verwenden, fügen Sie dem Abschnitt dependencies
der Datei build.gradle die folgende Zeile hinzu:
implementation 'com.microsoft.signalr.messagepack:signalr-messagepack:5.0.0'
Wenn Sie Maven verwenden, fügen Sie die folgenden Zeilen innerhalb des <dependencies>
-Elements der Datei pom.xml
hinzu:
<dependency>
<groupId>com.microsoft.signalr.messagepack</groupId>
<artifactId>signalr</artifactId>
<version>5.0.0</version>
</dependency>
Rufen Sie withHubProtocol(new MessagePackHubProtocol())
für HubConnectionBuilder
auf.
HubConnection messagePackConnection = HubConnectionBuilder.create("YOUR HUB URL HERE")
.withHubProtocol(new MessagePackHubProtocol())
.build();
MessagePack-Überlegungen
Bei Verwendung von MessagePack Hub Protocol gibt es einige Punkte zu beachten.
Bei MessagePack wird zwischen Groß-und Kleinschreibung unterschieden.
Beim MessagePack-Protokoll wird zwischen Groß-und Kleinschreibung unterschieden. Betrachten Sie beispielsweise die folgende C#-Klasse:
public class ChatMessage
{
public string Sender { get; }
public string Message { get; }
}
Beim Senden vom JavaScript-Client müssen Sie PascalCased
-Eigenschaftennamen verwenden, da die Groß- und Kleinschreibung genau mit der C#-Klasse übereinstimmen muss. Beispiel:
connection.invoke("SomeMethod", { Sender: "Sally", Message: "Hello!" });
Bei Verwendung von camelCased
-Namen wird nicht ordnungsgemäß an die C#-Klasse gebunden. Sie können dieses Problem umgehen, indem Sie das Key
-Attribut verwenden, um einen anderen Namen für die MessagePack-Eigenschaft anzugeben. Weitere Informationen finden Sie in der Dokumentation zu MessagePack-CSharp.
DateTime.Kind wird beim Serialisieren/Deserialisieren nicht beibehalten.
Das MessagePack-Protokoll bietet keine Möglichkeit, den Kind
-Wert eines DateTime
-Elements zu codieren. Daher wird MessagePack Hub Protocol beim Deserialisieren eines Datums in das UTC-Format konvertiert, wenn DateTime.Kind
DateTimeKind.Local
ist. Andernfalls wird die Uhrzeit nicht verändert und unverändert übergeben. Wenn Sie mit DateTime
-Werten arbeiten, empfiehlt es sich, diese vor dem Senden in UTC zu konvertieren. Konvertieren Sie sie aus UTC in Ortszeit, wenn Sie sie empfangen.
DateTime.MinValue wird von MessagePack in JavaScript nicht unterstützt.
Die vom SignalR-JavaScript-Client verwendete msgpack5-Bibliothek unterstützt den timestamp96
-Typ in MessagePack nicht. Dieser Typ wird verwendet, um sehr große Datumswerte zu codieren (entweder sehr früh in der Vergangenheit oder sehr weit in der Zukunft). Der Wert von DateTime.MinValue
ist January 1, 0001
, der in einem timestamp96
-Wert codiert werden muss. Aus diesem Grund wird das Senden von DateTime.MinValue
an einen JavaScript-Client nicht unterstützt. Wenn DateTime.MinValue
vom JavaScript-Client empfangen wird, wird der folgende Fehler ausgelöst:
Uncaught Error: unable to find ext type 255 at decoder.js:427
In der Regel wird DateTime.MinValue
verwendet, um einen „fehlenden“ oder null
-Wert zu codieren. Wenn Sie diesen Wert in MessagePack codieren müssen, verwenden Sie einen Nullable-DateTime
-Wert (DateTime?
), oder codieren Sie einen separaten bool
-Wert, der angibt, ob das Datum vorhanden ist.
Weitere Informationen zu dieser Einschränkung finden Sie unter im GitHub-Issue aspnet/SignalR#2228.
MessagePack-Unterstützung in einer Vorabkompilierungsumgebung
Die MessagePack-CSharp-Bibliothek, die vom .NET-Client und -Server verwendet wird, verwendet Codegenerierung, um die Serialisierung zu optimieren. Daher wird sie in Umgebungen, in denen Vorabkompilierung verwendet wird (z. B. Xamarin iOS oder Unity), standardmäßig nicht unterstützt. Es ist möglich, MessagePack in diesen Umgebungen zu verwenden, indem der Serialisierungs-/Deserialisierungscode „vorab generiert“ wird. Weitere Informationen finden Sie in der Dokumentation zu MessagePack-CSharp. Nachdem Sie die Serialisierungsmodule vorab generiert haben, können Sie sie mithilfe des Konfigurationsdelegaten registrieren, der an AddMessagePackProtocol
übergeben wird:
services.AddSignalR()
.AddMessagePackProtocol(options =>
{
StaticCompositeResolver.Instance.Register(
MessagePack.Resolvers.GeneratedResolver.Instance,
MessagePack.Resolvers.StandardResolver.Instance
);
options.SerializerOptions = MessagePackSerializerOptions.Standard
.WithResolver(StaticCompositeResolver.Instance)
.WithSecurity(MessagePackSecurity.UntrustedData);
});
Typüberprüfungen sind in MessagePack strenger
Das JSON Hub-Protokoll führt während der Deserialisierung Typkonvertierungen durch. Wenn das eingehende Objekt beispielsweise über einen Eigenschaftswert verfügt, der eine Zahl ({ foo: 42 }
) ist, die Eigenschaft der .NET-Klasse aber vom Typ string
ist, wird der Wert konvertiert. MessagePack führt diese Konvertierung jedoch nicht durch und löst eine Ausnahme aus, die in serverseitigen Protokollen (und in der Konsole) angezeigt wird:
InvalidDataException: Error binding arguments. Make sure that the types of the provided values match the types of the hub method being invoked.
Weitere Informationen zu dieser Einschränkung finden Sie unter im GitHub-Issue aspnet/SignalR#2937.
Zeichen und Zeichenfolgen in Java
Im Java-Client werden char
-Objekte als String
-Objekte mit einem Zeichen serialisiert. Dies steht im Gegensatz zum C#- oder JavaScript-Client, der sie als short
-Objekte serialisiert. Die MessagePack-Spezifikation selbst definiert das Verhalten für char
-Objekte nicht, daher liegt es beim Autor der Bibliothek, festzulegen, wie diese serialisiert werden sollen. Der Unterschied im Verhalten zwischen unseren Clients ist ein Ergebnis der Bibliotheken, die wir für unsere Implementierungen verwendet haben.
Zusätzliche Ressourcen
In diesem Artikel wird davon ausgegangen, dass der Leser mit den Themen vertraut ist, die unter Erste Schritte mit ASP.NET Core SignalRbehandelt werden.
Was ist MessagePack?
MessagePack ist ein schnelles und kompaktes binäres Serialisierungsformat. Dieses Format ist nützlich, wenn Leistung und Bandbreite eine Rolle spielen, da in ihm kleinere Nachrichten im Vergleich zu JSON erstellt werden. Die binären Nachrichten sind beim Untersuchen von Netzwerkablaufverfolgungen und Protokollen nicht lesbar, es sei denn, die Bytes werden über einen MessagePack-Parser übergeben. SignalR verfügt über integrierte Unterstützung für das MessagePack-Format und stellt APIs bereit, die vom Client und Server verwendet werden können.
Konfigurieren von MessagePack auf dem Server
Installieren Sie das Microsoft.AspNetCore.SignalR.Protocols.MessagePack
-Paket in Ihrer App, um das MessagePack Hub Protocol auf dem Server zu aktivieren. Fügen Sie in der Startup.ConfigureServices
-Methode dem AddSignalR
-Aufruf AddMessagePackProtocol
hinzu, um MessagePack-Unterstützung auf dem Server zu aktivieren.
Hinweis
JSON ist standardmäßig aktiviert. Durch das Hinzufügen von MessagePack werden sowohl JSON- als auch MessagePack-Clients unterstützt.
services.AddSignalR()
.AddMessagePackProtocol();
Um anzupassen, wie MessagePack Daten formatiert, nimmt AddMessagePackProtocol
einen Delegaten zum Konfigurieren von Optionen an. In diesem Delegaten kann die FormatterResolvers
-Eigenschaft verwendet werden, um MessagePack-Serialisierungsoptionen zu konfigurieren. Weitere Informationen zur Funktionsweise der Resolver finden Sie in der MessagePack-Bibliothek unter MessagePack-CSharp. Attribute können für die Objekte verwendet werden, die Sie serialisieren möchten, um zu definieren, wie sie behandelt werden sollen.
services.AddSignalR()
.AddMessagePackProtocol(options =>
{
options.FormatterResolvers = new List<MessagePack.IFormatterResolver>()
{
MessagePack.Resolvers.StandardResolver.Instance
};
});
Warnung
Es wird dringend empfohlen, CVE-2020-5234 zu lesen und die empfohlenen Patches anzuwenden. Legen Sie z. B. die statische MessagePackSecurity.Active
-Eigenschaft auf MessagePackSecurity.UntrustedData
fest. Das Festlegen von MessagePackSecurity.Active
erfordert die manuelle Installation einer Version 1.9.x von MessagePack. Durch Installieren von MessagePack
1.9.x erfolgt ein Upgrade der Version, die SignalR verwendet. Mit Version 2.x von MessagePack
wurden Breaking Changes eingeführt. Sie ist mit Version 3.1 und früher von SignalR nicht kompatibel. Wenn MessagePackSecurity.Active
nicht auf MessagePackSecurity.UntrustedData
festgelegt ist, kann ein böswilliger Client einen Denial-of-Service-Angriff verursachen. Legen Sie MessagePackSecurity.Active
wie im folgenden Code gezeigt auf Program.Main
fest:
using MessagePack;
public static void Main(string[] args)
{
MessagePackSecurity.Active = MessagePackSecurity.UntrustedData;
CreateHostBuilder(args).Build().Run();
}
Konfigurieren von MessagePack auf dem Client
Hinweis
JSON ist für die unterstützten Clients standardmäßig aktiviert. Clients können nur ein einziges Protokoll unterstützen. Das Hinzufügen von MessagePack-Unterstützung ersetzt alle zuvor konfigurierten Protokolle.
.NET-Client
Um MessagePack im .NET-Client zu aktivieren, installieren Sie das Microsoft.AspNetCore.SignalR.Protocols.MessagePack
-Paket und rufen AddMessagePackProtocol
für HubConnectionBuilder
auf.
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.DependencyInjection;
var hubConnection = new HubConnectionBuilder()
.WithUrl("/chathub")
.AddMessagePackProtocol()
.Build();
Hinweis
Dieser AddMessagePackProtocol
-Aufruf nimmt einen Delegaten zum Konfigurieren von Optionen an, genau wie der Server.
JavaScript-Client
MessagePack-Unterstützung für den JavaScript-Client wird vom npm-Paket @microsoft/signalr-protocol-msgpack bereitgestellt. Installieren Sie das Paket, indem Sie den folgenden Befehl in einer Befehlsshell ausführen:
npm install @microsoft/signalr-protocol-msgpack
Nach der Installation des npm-Pakets kann das Modul direkt über einen JavaScript-Modulladeprogramm verwendet oder in den Browser importiert werden, indem auf die folgende Datei verwiesen wird:
node_modules\@microsoft\signalr-protocol-msgpack\dist\browser\signalr-protocol-msgpack.js
In einem Browser muss auch auf die msgpack5
-Bibliothek verwiesen werden. Verwenden Sie ein <script>
-Tag, um einen Verweis zu erstellen. Die Bibliothek finden Sie unter node_modules\msgpack5\dist\msgpack5.jsjs.
Hinweis
Bei Verwendung des <script>
-Elements ist die Reihenfolge wichtig. Wenn signalr-protocol-msgpack.js
vor msgpack5.js
referenziert wird, tritt beim Versuch, eine Verbindung mit MessagePack herzustellen, ein Fehler auf. signalr.js
muss auch vor signalr-protocol-msgpack.js
vorhanden sein.
<script src="~/lib/signalr/signalr.js"></script>
<script src="~/lib/msgpack5/msgpack5.js"></script>
<script src="~/lib/signalr/signalr-protocol-msgpack.js"></script>
Wenn Sie .withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
zu HubConnectionBuilder
hinzufügen, wird der Client für die Verwendung des MessagePack-Protokolls konfiguriert, wenn eine Verbindung mit einem Server hergestellt wird.
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
.build();
Hinweis
Derzeit gibt es keine Konfigurationsoptionen für das MessagePack-Protokoll auf dem JavaScript-Client.
MessagePack-Überlegungen
Bei Verwendung von MessagePack Hub Protocol gibt es einige Punkte zu beachten.
Bei MessagePack wird zwischen Groß-und Kleinschreibung unterschieden.
Beim MessagePack-Protokoll wird zwischen Groß-und Kleinschreibung unterschieden. Betrachten Sie beispielsweise die folgende C#-Klasse:
public class ChatMessage
{
public string Sender { get; }
public string Message { get; }
}
Beim Senden vom JavaScript-Client müssen Sie PascalCased
-Eigenschaftennamen verwenden, da die Groß- und Kleinschreibung genau mit der C#-Klasse übereinstimmen muss. Beispiel:
connection.invoke("SomeMethod", { Sender: "Sally", Message: "Hello!" });
Bei Verwendung von camelCased
-Namen wird nicht ordnungsgemäß an die C#-Klasse gebunden. Sie können dieses Problem umgehen, indem Sie das Key
-Attribut verwenden, um einen anderen Namen für die MessagePack-Eigenschaft anzugeben. Weitere Informationen finden Sie in der Dokumentation zu MessagePack-CSharp.
DateTime.Kind wird beim Serialisieren/Deserialisieren nicht beibehalten.
Das MessagePack-Protokoll bietet keine Möglichkeit, den Kind
-Wert eines DateTime
-Elements zu codieren. Daher geht MessagePack Hub Protocol beim Deserialisieren eines Datums davon aus, dass das eingehende Datum im UTC-Format vorliegt. Wenn Sie mit DateTime
-Werten in Ortszeit arbeiten, empfiehlt es sich, diese vor dem Senden in UTC zu konvertieren. Konvertieren Sie sie aus UTC in Ortszeit, wenn Sie sie empfangen.
Weitere Informationen zu dieser Einschränkung finden Sie unter im GitHub-Issue aspnet/SignalR#2632.
DateTime.MinValue wird von MessagePack in JavaScript nicht unterstützt.
Die vom SignalR-JavaScript-Client verwendete msgpack5-Bibliothek unterstützt den timestamp96
-Typ in MessagePack nicht. Dieser Typ wird verwendet, um sehr große Datumswerte zu codieren (entweder sehr früh in der Vergangenheit oder sehr weit in der Zukunft). Der Wert von DateTime.MinValue
ist January 1, 0001
, der in einem timestamp96
-Wert codiert werden muss. Aus diesem Grund wird das Senden von DateTime.MinValue
an einen JavaScript-Client nicht unterstützt. Wenn DateTime.MinValue
vom JavaScript-Client empfangen wird, wird der folgende Fehler ausgelöst:
Uncaught Error: unable to find ext type 255 at decoder.js:427
In der Regel wird DateTime.MinValue
verwendet, um einen „fehlenden“ oder null
-Wert zu codieren. Wenn Sie diesen Wert in MessagePack codieren müssen, verwenden Sie einen Nullable-DateTime
-Wert (DateTime?
), oder codieren Sie einen separaten bool
-Wert, der angibt, ob das Datum vorhanden ist.
Weitere Informationen zu dieser Einschränkung finden Sie unter im GitHub-Issue aspnet/SignalR#2228.
MessagePack-Unterstützung in einer Vorabkompilierungsumgebung
Die MessagePack-CSharp-Bibliothek, die vom .NET-Client und -Server verwendet wird, verwendet Codegenerierung, um die Serialisierung zu optimieren. Daher wird sie in Umgebungen, in denen Vorabkompilierung verwendet wird (z. B. Xamarin iOS oder Unity), standardmäßig nicht unterstützt. Es ist möglich, MessagePack in diesen Umgebungen zu verwenden, indem der Serialisierungs-/Deserialisierungscode „vorab generiert“ wird. Weitere Informationen finden Sie in der Dokumentation zu MessagePack-CSharp. Nachdem Sie die Serialisierungsmodule vorab generiert haben, können Sie sie mithilfe des Konfigurationsdelegaten registrieren, der an AddMessagePackProtocol
übergeben wird:
services.AddSignalR()
.AddMessagePackProtocol(options =>
{
options.FormatterResolvers = new List<MessagePack.IFormatterResolver>()
{
MessagePack.Resolvers.GeneratedResolver.Instance,
MessagePack.Resolvers.StandardResolver.Instance
};
});
Typüberprüfungen sind in MessagePack strenger
Das JSON Hub-Protokoll führt während der Deserialisierung Typkonvertierungen durch. Wenn das eingehende Objekt beispielsweise über einen Eigenschaftswert verfügt, der eine Zahl ({ foo: 42 }
) ist, die Eigenschaft der .NET-Klasse aber vom Typ string
ist, wird der Wert konvertiert. MessagePack führt diese Konvertierung jedoch nicht durch und löst eine Ausnahme aus, die in serverseitigen Protokollen (und in der Konsole) angezeigt wird:
InvalidDataException: Error binding arguments. Make sure that the types of the provided values match the types of the hub method being invoked.
Weitere Informationen zu dieser Einschränkung finden Sie unter im GitHub-Issue aspnet/SignalR#2937.
Zusätzliche Ressourcen
In diesem Artikel wird davon ausgegangen, dass der Leser mit den Themen vertraut ist, die unter Erste Schritte mit ASP.NET Core SignalRbehandelt werden.
Was ist MessagePack?
MessagePack ist ein schnelles und kompaktes binäres Serialisierungsformat. Dieses Format ist nützlich, wenn Leistung und Bandbreite eine Rolle spielen, da in ihm kleinere Nachrichten im Vergleich zu JSON erstellt werden. Die binären Nachrichten sind beim Untersuchen von Netzwerkablaufverfolgungen und Protokollen nicht lesbar, es sei denn, die Bytes werden über einen MessagePack-Parser übergeben. SignalR verfügt über integrierte Unterstützung für das MessagePack-Format und stellt APIs bereit, die vom Client und Server verwendet werden können.
Konfigurieren von MessagePack auf dem Server
Installieren Sie das Microsoft.AspNetCore.SignalR.Protocols.MessagePack
-Paket in Ihrer App, um das MessagePack Hub Protocol auf dem Server zu aktivieren. Fügen Sie in der Startup.ConfigureServices
-Methode dem AddSignalR
-Aufruf AddMessagePackProtocol
hinzu, um MessagePack-Unterstützung auf dem Server zu aktivieren.
Hinweis
JSON ist standardmäßig aktiviert. Durch das Hinzufügen von MessagePack werden sowohl JSON- als auch MessagePack-Clients unterstützt.
services.AddSignalR()
.AddMessagePackProtocol();
Um anzupassen, wie MessagePack Daten formatiert, nimmt AddMessagePackProtocol
einen Delegaten zum Konfigurieren von Optionen an. In diesem Delegaten kann die FormatterResolvers
-Eigenschaft verwendet werden, um MessagePack-Serialisierungsoptionen zu konfigurieren. Weitere Informationen zur Funktionsweise der Resolver finden Sie in der MessagePack-Bibliothek unter MessagePack-CSharp. Attribute können für die Objekte verwendet werden, die Sie serialisieren möchten, um zu definieren, wie sie behandelt werden sollen.
services.AddSignalR()
.AddMessagePackProtocol(options =>
{
options.FormatterResolvers = new List<MessagePack.IFormatterResolver>()
{
MessagePack.Resolvers.StandardResolver.Instance
};
});
Warnung
Es wird dringend empfohlen, CVE-2020-5234 zu lesen und die empfohlenen Patches anzuwenden. Legen Sie z. B. die statische MessagePackSecurity.Active
-Eigenschaft auf MessagePackSecurity.UntrustedData
fest. Das Festlegen von MessagePackSecurity.Active
erfordert die manuelle Installation einer Version 1.9.x von MessagePack. Durch Installieren von MessagePack
1.9.x erfolgt ein Upgrade der Version, die SignalR verwendet. Wenn MessagePackSecurity.Active
nicht auf MessagePackSecurity.UntrustedData
festgelegt ist, kann ein böswilliger Client einen Denial-of-Service-Angriff verursachen. Legen Sie MessagePackSecurity.Active
wie im folgenden Code gezeigt auf Program.Main
fest:
using MessagePack;
public static void Main(string[] args)
{
MessagePackSecurity.Active = MessagePackSecurity.UntrustedData;
CreateHostBuilder(args).Build().Run();
}
Konfigurieren von MessagePack auf dem Client
Hinweis
JSON ist für die unterstützten Clients standardmäßig aktiviert. Clients können nur ein einziges Protokoll unterstützen. Das Hinzufügen von MessagePack-Unterstützung ersetzt alle zuvor konfigurierten Protokolle.
.NET-Client
Um MessagePack im .NET-Client zu aktivieren, installieren Sie das Microsoft.AspNetCore.SignalR.Protocols.MessagePack
-Paket und rufen AddMessagePackProtocol
für HubConnectionBuilder
auf.
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.DependencyInjection;
var hubConnection = new HubConnectionBuilder()
.WithUrl("/chathub")
.AddMessagePackProtocol()
.Build();
Hinweis
Dieser AddMessagePackProtocol
-Aufruf nimmt einen Delegaten zum Konfigurieren von Optionen an, genau wie der Server.
JavaScript-Client
MessagePack-Unterstützung für den JavaScript-Client wird vom npm-Paket @aspnet/signalr-protocol-msgpack bereitgestellt. Installieren Sie das Paket, indem Sie den folgenden Befehl in einer Befehlsshell ausführen:
npm install @aspnet/signalr-protocol-msgpack
Nach der Installation des npm-Pakets kann das Modul direkt über einen JavaScript-Modulladeprogramm verwendet oder in den Browser importiert werden, indem auf die folgende Datei verwiesen wird:
node_modules\@aspnet\signalr-protocol-msgpack\dist\browser\signalr-protocol-msgpack.js
In einem Browser muss auch auf die msgpack5
-Bibliothek verwiesen werden. Verwenden Sie ein <script>
-Tag, um einen Verweis zu erstellen. Die Bibliothek finden Sie unter node_modules\msgpack5\dist\msgpack5.jsjs.
Hinweis
Bei Verwendung des <script>
-Elements ist die Reihenfolge wichtig. Wenn signalr-protocol-msgpack.js
vor msgpack5.js
referenziert wird, tritt beim Versuch, eine Verbindung mit MessagePack herzustellen, ein Fehler auf. signalr.js
muss auch vor signalr-protocol-msgpack.js
vorhanden sein.
<script src="~/lib/signalr/signalr.js"></script>
<script src="~/lib/msgpack5/msgpack5.js"></script>
<script src="~/lib/signalr/signalr-protocol-msgpack.js"></script>
Wenn Sie .withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
zu HubConnectionBuilder
hinzufügen, wird der Client für die Verwendung des MessagePack-Protokolls konfiguriert, wenn eine Verbindung mit einem Server hergestellt wird.
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
.build();
Hinweis
Derzeit gibt es keine Konfigurationsoptionen für das MessagePack-Protokoll auf dem JavaScript-Client.
MessagePack-Überlegungen
Bei Verwendung von MessagePack Hub Protocol gibt es einige Punkte zu beachten.
Bei MessagePack wird zwischen Groß-und Kleinschreibung unterschieden.
Beim MessagePack-Protokoll wird zwischen Groß-und Kleinschreibung unterschieden. Betrachten Sie beispielsweise die folgende C#-Klasse:
public class ChatMessage
{
public string Sender { get; }
public string Message { get; }
}
Beim Senden vom JavaScript-Client müssen Sie PascalCased
-Eigenschaftennamen verwenden, da die Groß- und Kleinschreibung genau mit der C#-Klasse übereinstimmen muss. Beispiel:
connection.invoke("SomeMethod", { Sender: "Sally", Message: "Hello!" });
Bei Verwendung von camelCased
-Namen wird nicht ordnungsgemäß an die C#-Klasse gebunden. Sie können dieses Problem umgehen, indem Sie das Key
-Attribut verwenden, um einen anderen Namen für die MessagePack-Eigenschaft anzugeben. Weitere Informationen finden Sie in der Dokumentation zu MessagePack-CSharp.
DateTime.Kind wird beim Serialisieren/Deserialisieren nicht beibehalten.
Das MessagePack-Protokoll bietet keine Möglichkeit, den Kind
-Wert eines DateTime
-Elements zu codieren. Daher geht MessagePack Hub Protocol beim Deserialisieren eines Datums davon aus, dass das eingehende Datum im UTC-Format vorliegt. Wenn Sie mit DateTime
-Werten in Ortszeit arbeiten, empfiehlt es sich, diese vor dem Senden in UTC zu konvertieren. Konvertieren Sie sie aus UTC in Ortszeit, wenn Sie sie empfangen.
Weitere Informationen zu dieser Einschränkung finden Sie unter im GitHub-Issue aspnet/SignalR#2632.
DateTime.MinValue wird von MessagePack in JavaScript nicht unterstützt.
Die vom SignalR-JavaScript-Client verwendete msgpack5-Bibliothek unterstützt den timestamp96
-Typ in MessagePack nicht. Dieser Typ wird verwendet, um sehr große Datumswerte zu codieren (entweder sehr früh in der Vergangenheit oder sehr weit in der Zukunft). Der Wert von DateTime.MinValue
ist January 1, 0001
, der in einem timestamp96
-Wert codiert werden muss. Aus diesem Grund wird das Senden von DateTime.MinValue
an einen JavaScript-Client nicht unterstützt. Wenn DateTime.MinValue
vom JavaScript-Client empfangen wird, wird der folgende Fehler ausgelöst:
Uncaught Error: unable to find ext type 255 at decoder.js:427
In der Regel wird DateTime.MinValue
verwendet, um einen „fehlenden“ oder null
-Wert zu codieren. Wenn Sie diesen Wert in MessagePack codieren müssen, verwenden Sie einen Nullable-DateTime
-Wert (DateTime?
), oder codieren Sie einen separaten bool
-Wert, der angibt, ob das Datum vorhanden ist.
Weitere Informationen zu dieser Einschränkung finden Sie unter im GitHub-Issue aspnet/SignalR#2228.
MessagePack-Unterstützung in einer Vorabkompilierungsumgebung
Die MessagePack-CSharp-Bibliothek, die vom .NET-Client und -Server verwendet wird, verwendet Codegenerierung, um die Serialisierung zu optimieren. Daher wird sie in Umgebungen, in denen Vorabkompilierung verwendet wird (z. B. Xamarin iOS oder Unity), standardmäßig nicht unterstützt. Es ist möglich, MessagePack in diesen Umgebungen zu verwenden, indem der Serialisierungs-/Deserialisierungscode „vorab generiert“ wird. Weitere Informationen finden Sie in der Dokumentation zu MessagePack-CSharp. Nachdem Sie die Serialisierungsmodule vorab generiert haben, können Sie sie mithilfe des Konfigurationsdelegaten registrieren, der an AddMessagePackProtocol
übergeben wird:
services.AddSignalR()
.AddMessagePackProtocol(options =>
{
options.FormatterResolvers = new List<MessagePack.IFormatterResolver>()
{
MessagePack.Resolvers.GeneratedResolver.Instance,
MessagePack.Resolvers.StandardResolver.Instance
};
});
Typüberprüfungen sind in MessagePack strenger
Das JSON Hub-Protokoll führt während der Deserialisierung Typkonvertierungen durch. Wenn das eingehende Objekt beispielsweise über einen Eigenschaftswert verfügt, der eine Zahl ({ foo: 42 }
) ist, die Eigenschaft der .NET-Klasse aber vom Typ string
ist, wird der Wert konvertiert. MessagePack führt diese Konvertierung jedoch nicht durch und löst eine Ausnahme aus, die in serverseitigen Protokollen (und in der Konsole) angezeigt wird:
InvalidDataException: Error binding arguments. Make sure that the types of the provided values match the types of the hub method being invoked.
Weitere Informationen zu dieser Einschränkung finden Sie unter im GitHub-Issue aspnet/SignalR#2937.