MessagePack Hub Protocol gebruiken in SignalR voor ASP.NET Core
In dit artikel wordt ervan uitgegaan dat de lezer bekend is met de onderwerpen die worden behandeld in Aan de slag met ASP.NET Core SignalR.
Wat is MessagePack?
MessagePack is een snelle en compacte binaire serialisatieformaat. Het is handig wanneer prestaties en bandbreedte een probleem zijn omdat er kleinere berichten worden gemaakt dan JSON-. De binaire berichten zijn onleesbaar wanneer u netwerktraceringen en logboeken bekijkt, tenzij de bytes worden doorgegeven via een MessagePack-parser. SignalR heeft ingebouwde ondersteuning voor de MessagePack-indeling en biedt API's die de client en server kunnen gebruiken.
MessagePack configureren op de server
Als u het MessagePack Hub Protocol op de server wilt inschakelen, installeert u het Microsoft.AspNetCore.SignalR.Protocols.MessagePack
-pakket in uw app. Voeg in de methode Startup.ConfigureServices
AddMessagePackProtocol
toe aan de AddSignalR
aanroep om ondersteuning voor MessagePack op de server in te schakelen.
services.AddSignalR()
.AddMessagePackProtocol();
Notitie
JSON is standaard ingeschakeld. Het toevoegen van MessagePack maakt ondersteuning mogelijk voor zowel JSON- als MessagePack-clients.
Als u de indeling van gegevens in MessagePack wilt aanpassen, neemt AddMessagePackProtocol
een gemachtigde voor het configureren van opties. In deze gemachtigde wordt de eigenschap SerializerOptions
gebruikt om serialisatieopties voor MessagePack te configureren. Ga naar de MessagePack-bibliotheek op MessagePack-CSharp-voor meer informatie over de werking van de resolvers. Kenmerken kunnen worden gebruikt voor de objecten die u wilt serialiseren om te definiëren hoe ze moeten worden verwerkt.
services.AddSignalR()
.AddMessagePackProtocol(options =>
{
options.SerializerOptions = MessagePackSerializerOptions.Standard
.WithResolver(new CustomResolver())
.WithSecurity(MessagePackSecurity.UntrustedData);
});
Waarschuwing
We raden u ten zeerste aan om CVE-2020-5234 te bekijken en de aanbevolen patches toe te passen. Bijvoorbeeld het aanroepen van .WithSecurity(MessagePackSecurity.UntrustedData)
bij het vervangen van de SerializerOptions
.
MessagePack configureren op de client
Notitie
JSON is standaard ingeschakeld voor de ondersteunde clients. Clients kunnen slechts één protocol ondersteunen. Het toevoegen van MessagePack-ondersteuning vervangt eventuele eerder geconfigureerde protocollen.
.NET-client
Als u MessagePack wilt inschakelen in de .NET-client, installeert u het Microsoft.AspNetCore.SignalR.Protocols.MessagePack
-pakket en roept u AddMessagePackProtocol
aan op HubConnectionBuilder
.
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.DependencyInjection;
var hubConnection = new HubConnectionBuilder()
.WithUrl("/chathub")
.AddMessagePackProtocol()
.Build();
Notitie
Deze AddMessagePackProtocol
-oproep gebruikt een delegate om opties te configureren, net zoals de server doet.
JavaScript-client
MessagePack-ondersteuning voor de JavaScript-client wordt geleverd door het pakket @microsoft/signalr-protocol-msgpack npm. Installeer het pakket door de volgende opdracht uit te voeren in een opdrachtshell:
npm install @microsoft/signalr-protocol-msgpack
Na de installatie van het npm-pakket kan de module rechtstreeks worden gebruikt via een JavaScript-modulelaadprogramma of in de browser worden geïmporteerd door te verwijzen naar het volgende bestand:
node_modules\@microsoft\signalr-protocol-msgpack\dist\browser\signalr-protocol-msgpack.js
In de onderstaande volgorde moet worden verwezen naar de volgende vereiste JavaScript-bestanden:
<script src="~/lib/signalr/signalr.js"></script>
<script src="~/lib/signalr/signalr-protocol-msgpack.js"></script>
Door .withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
toe te voegen aan de HubConnectionBuilder
wordt de client geconfigureerd voor het gebruik van het MessagePack-protocol bij het maken van verbinding met een server.
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
.build();
Op dit moment zijn er geen configuratieopties voor het MessagePack-protocol op de JavaScript-client.
Java-client
Als u MessagePack met Java wilt inschakelen, installeert u het com.microsoft.signalr.messagepack
-pakket. Wanneer u Gradle gebruikt, voegt u de volgende regel toe aan de sectie dependencies
van het bestand build.gradle:
implementation 'com.microsoft.signalr.messagepack:signalr-messagepack:5.0.0'
Wanneer u Maven gebruikt, voegt u de volgende regels toe binnen het <dependencies>
element van het pom.xml
-bestand:
<dependency>
<groupId>com.microsoft.signalr.messagepack</groupId>
<artifactId>signalr</artifactId>
<version>5.0.0</version>
</dependency>
Bel withHubProtocol(new MessagePackHubProtocol())
op HubConnectionBuilder
.
HubConnection messagePackConnection = HubConnectionBuilder.create("YOUR HUB URL HERE")
.withHubProtocol(new MessagePackHubProtocol())
.build();
Overwegingen voor MessagePack
Er zijn enkele problemen waarmee u rekening moet houden bij het gebruik van het MessagePack Hub Protocol.
MessagePack is hoofdlettergevoelig
Het MessagePack-protocol is hoofdlettergevoelig. Denk bijvoorbeeld aan de volgende C#-klasse:
public class ChatMessage
{
public string Sender { get; }
public string Message { get; }
}
Wanneer u verzendt vanuit de JavaScript-client, moet u PascalCased
eigenschapsnamen gebruiken, omdat de behuizing exact moet overeenkomen met de C#-klasse. Bijvoorbeeld:
connection.invoke("SomeMethod", { Sender: "Sally", Message: "Hello!" });
Als u camelCased
-namen gebruikt, zullen ze niet correct worden verbonden met de C#-klasse. U kunt dit omzeilen door het kenmerk Key
te gebruiken om een andere naam op te geven voor de eigenschap MessagePack. Zie de MessagePack-CSharp documentatievoor meer informatie.
DateTime.Kind blijft niet behouden bij het serialiseren/deserialiseren
Het MessagePack-protocol biedt geen manier om de Kind
waarde van een DateTime
te coderen. Als een datum wordt gedeserialiseerd, zal het MessagePack Hub Protocol het converteren naar de UTC-indeling als DateTime.Kind
DateTimeKind.Local
is; anders zal de tijd onveranderd worden doorgegeven. Als u met DateTime
waarden werkt, raden we u aan om te converteren naar UTC voordat u ze verzendt. Converteer ze van UTC naar lokale tijd wanneer u ze ontvangt.
MessagePack-ondersteuning in van tevoren compilatieomgeving
De MessagePack-CSharp bibliotheek die wordt gebruikt door de .NET-client en -server maakt gebruik van codegeneratie om serialisatie te optimaliseren. Als gevolg hiervan wordt het niet standaard ondersteund voor omgevingen die gebruikmaken van compilatie vooraf, zoals de gebruikersinterface van de net-app met meerdere platforms (.NET MAUI) of Unity. Het is mogelijk om MessagePack in deze omgevingen te gebruiken door de serializer-/deserializer-code vooraf te genereren. Zie de MessagePack-CSharp documentatievoor meer informatie. Nadat u de serializers vooraf hebt gegenereerd, kunt u deze registreren met behulp van de configuratie-delegate die is doorgegeven aan AddMessagePackProtocol
.
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);
});
Typecontroles zijn strikter in MessagePack
Het JSON Hub Protocol voert typeconversies uit tijdens deserialisatie. Als het binnenkomende object bijvoorbeeld een eigenschapswaarde heeft die een getal ({ foo: 42 }
) is, maar de eigenschap in de .NET-klasse van het type string
is, wordt de waarde geconverteerd. MessagePack voert deze conversie echter niet uit en genereert een uitzondering die kan worden weergegeven in logboeken aan de serverzijde (en in de console):
InvalidDataException: Error binding arguments. Make sure that the types of the provided values match the types of the hub method being invoked.
Zie GitHub-probleem aspnet/SignalR#2937voor meer informatie over deze beperking.
Tekens en tekenreeksen in Java
In de Java-cliënt worden char
-objecten geserialiseerd als eenteken-String
-objecten. Dit is in tegenstelling tot de C#- en JavaScript-client, die ze serialiseert als short
objecten. De MessagePack-specificatie zelf definieert geen gedrag voor char
objecten, dus het is aan de auteur van de bibliotheek om te bepalen hoe ze moeten worden geserialiseerd. Het verschil in gedrag tussen onze klanten is het resultaat van de bibliotheken die we voor onze implementaties hebben gebruikt.
Aanvullende informatiebronnen
In dit artikel wordt ervan uitgegaan dat de lezer bekend is met de onderwerpen die worden behandeld in Aan de slag met ASP.NET Core SignalR.
Wat is MessagePack?
MessagePack is een snel en compact binair serialisatieformaat. Het is handig wanneer prestaties en bandbreedte een probleem zijn omdat er kleinere berichten worden gemaakt in vergelijking met JSON-. De binaire berichten zijn onleesbaar wanneer u netwerktraceringen en logboeken bekijkt, tenzij de bytes worden doorgegeven via een MessagePack-parser. SignalR heeft ingebouwde ondersteuning voor de MessagePack-indeling en biedt API's die de client en server kunnen gebruiken.
MessagePack configureren op de server
Als u het MessagePack Hub Protocol op de server wilt inschakelen, installeert u het Microsoft.AspNetCore.SignalR.Protocols.MessagePack
-pakket in uw app. Voeg in de methode Startup.ConfigureServices
AddMessagePackProtocol
toe aan de AddSignalR
aanroep om ondersteuning voor MessagePack op de server in te schakelen.
Notitie
JSON is standaard ingeschakeld. Het toevoegen van MessagePack maakt ondersteuning mogelijk voor zowel JSON- als MessagePack-clients.
services.AddSignalR()
.AddMessagePackProtocol();
Als u wilt aanpassen hoe Uw gegevens in MessagePack worden opgemaakt, neemt AddMessagePackProtocol
een gemachtigde voor het configureren van opties. In deze gemachtigde kan de eigenschap SerializerOptions
worden gebruikt om serialisatieopties voor MessagePack te configureren. Ga naar de MessagePack-bibliotheek op MessagePack-CSharp-voor meer informatie over de werking van de resolvers. Kenmerken kunnen worden gebruikt voor de objecten die u wilt serialiseren om te definiëren hoe ze moeten worden verwerkt.
services.AddSignalR()
.AddMessagePackProtocol(options =>
{
options.SerializerOptions = MessagePackSerializerOptions.Standard
.WithResolver(new CustomResolver())
.WithSecurity(MessagePackSecurity.UntrustedData);
});
Waarschuwing
We raden u ten zeerste aan om CVE-2020-5234 te bekijken en de aanbevolen patches toe te passen. Bijvoorbeeld het aanroepen van .WithSecurity(MessagePackSecurity.UntrustedData)
bij het vervangen van de SerializerOptions
.
MessagePack configureren op de client
Notitie
JSON is standaard ingeschakeld voor de ondersteunde clients. Clients kunnen slechts één protocol ondersteunen. Het toevoegen van MessagePack-ondersteuning vervangt alle eerder geconfigureerde protocollen.
.NET-client
Als u MessagePack wilt inschakelen in de .NET-client, installeert u het Microsoft.AspNetCore.SignalR.Protocols.MessagePack
-pakket en roept u AddMessagePackProtocol
aan op HubConnectionBuilder
.
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.DependencyInjection;
var hubConnection = new HubConnectionBuilder()
.WithUrl("/chathub")
.AddMessagePackProtocol()
.Build();
Notitie
Deze AddMessagePackProtocol
oproep neemt een gemachtigde voor het configureren van opties, net zoals de server.
JavaScript-client
MessagePack-ondersteuning voor de JavaScript-client wordt geleverd door het pakket @microsoft/signalr-protocol-msgpack npm. Installeer het pakket door de volgende opdracht uit te voeren in een opdrachtshell:
npm install @microsoft/signalr-protocol-msgpack
Na de installatie van het npm-pakket kan de module rechtstreeks worden gebruikt via een JavaScript-modulelaadprogramma of in de browser worden geïmporteerd door te verwijzen naar het volgende bestand:
node_modules\@microsoft\signalr-protocol-msgpack\dist\browser\signalr-protocol-msgpack.js
In een browser moet ook naar de msgpack5
bibliotheek worden verwezen. Gebruik een <script>
-tag om een verwijzing te maken. De bibliotheek is te vinden op node_modules\msgpack5\dist\msgpack5.js.
Notitie
Wanneer u het element <script>
gebruikt, is de volgorde belangrijk. Als signalr-protocol-msgpack.js
wordt verwezen voordat msgpack5.js
, treedt er een fout op wanneer u verbinding probeert te maken met MessagePack.
signalr.js
is ook vereist voordat signalr-protocol-msgpack.js
.
<script src="~/lib/signalr/signalr.js"></script>
<script src="~/lib/msgpack5/msgpack5.js"></script>
<script src="~/lib/signalr/signalr-protocol-msgpack.js"></script>
Door .withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
toe te voegen aan de HubConnectionBuilder
wordt de client geconfigureerd voor het gebruik van het MessagePack-protocol bij het maken van verbinding met een server.
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
.build();
Notitie
Op dit moment zijn er geen configuratieopties voor het MessagePack-protocol op de JavaScript-client.
Java client
Als u MessagePack met Java wilt inschakelen, installeert u het com.microsoft.signalr.messagepack
-pakket. Wanneer u Gradle gebruikt, voegt u de volgende regel toe aan de sectie dependencies
van het bestand build.gradle:
implementation 'com.microsoft.signalr.messagepack:signalr-messagepack:5.0.0'
Wanneer u Maven gebruikt, voegt u de volgende regels toe binnen het <dependencies>
element van het pom.xml
-bestand:
<dependency>
<groupId>com.microsoft.signalr.messagepack</groupId>
<artifactId>signalr</artifactId>
<version>5.0.0</version>
</dependency>
Bel withHubProtocol(new MessagePackHubProtocol())
op HubConnectionBuilder
.
HubConnection messagePackConnection = HubConnectionBuilder.create("YOUR HUB URL HERE")
.withHubProtocol(new MessagePackHubProtocol())
.build();
Overwegingen voor MessagePack
Er zijn enkele problemen waarmee u rekening moet houden bij het gebruik van het MessagePack Hub Protocol.
MessagePack is hoofdlettergevoelig
Het MessagePack-protocol is hoofdlettergevoelig. Denk bijvoorbeeld aan de volgende C#-klasse:
public class ChatMessage
{
public string Sender { get; }
public string Message { get; }
}
Wanneer u verzendt vanuit de JavaScript-client, moet u PascalCased
eigenschapsnamen gebruiken, omdat de behuizing exact moet overeenkomen met de C#-klasse. Bijvoorbeeld:
connection.invoke("SomeMethod", { Sender: "Sally", Message: "Hello!" });
Als u camelCased
-naam gebruikt, wordt deze niet correct gekoppeld aan de C#-klasse. U kunt dit omzeilen door het kenmerk Key
te gebruiken om een andere naam op te geven voor de eigenschap MessagePack. Zie de MessagePack-CSharp documentatievoor meer informatie.
DateTime.Kind wordt niet behouden bij het serialiseren/deserialiseren.
Het MessagePack-protocol biedt geen manier om de Kind
waarde van een DateTime
te coderen. Bij het deserialiseren van een datum, converteert het MessagePack Hub Protocol dit naar de UTC-indeling als DateTime.Kind
DateTimeKind.Local
is; anders wordt de tijd niet aangeraakt en wordt deze als zodanig doorgegeven. Als u met DateTime
waarden werkt, raden we u aan om te converteren naar UTC voordat u ze verzendt. Converteer ze van UTC naar lokale tijd wanneer u ze ontvangt.
DateTime.MinValue wordt niet ondersteund door MessagePack in JavaScript
De msgpack5-bibliotheek die wordt gebruikt door de SignalR JavaScript-client biedt geen ondersteuning voor het timestamp96
type in MessagePack. Dit type wordt gebruikt om zeer grote datumwaarden te coderen (zeer vroeg in het verleden of heel ver in de toekomst). De waarde van DateTime.MinValue
is January 1, 0001
, die moet worden gecodeerd in een timestamp96
waarde. Daarom wordt het verzenden van DateTime.MinValue
naar een JavaScript-client niet ondersteund. Wanneer DateTime.MinValue
wordt ontvangen door de JavaScript-client, wordt de volgende fout gegenereerd:
Uncaught Error: unable to find ext type 255 at decoder.js:427
Meestal wordt DateTime.MinValue
gebruikt om een 'ontbrekende' of null
waarde te coderen. Als u die waarde in MessagePack moet coderen, gebruikt u een nullable DateTime
waarde (DateTime?
) of codeert u een afzonderlijke bool
waarde die aangeeft of de datum aanwezig is.
Zie GitHub-probleem aspnet/SignalR#2228voor meer informatie over deze beperking.
Ondersteuning voor MessagePack in een "ahead-of-time" compilatieomgeving
De MessagePack-CSharp bibliotheek die wordt gebruikt door de .NET-client en -server maakt gebruik van codegeneratie om serialisatie te optimaliseren. Als gevolg hiervan wordt het niet standaard ondersteund voor omgevingen die gebruikmaken van compilatie vooraf, zoals de gebruikersinterface van de net-app met meerdere platforms (.NET MAUI) of Unity. Het is mogelijk om MessagePack in deze omgevingen te gebruiken door de serializer-/deserializer-code vooraf te genereren. Zie de MessagePack-CSharp documentatievoor meer informatie. Nadat u de serializers vooraf hebt gegenereerd, kunt u deze registreren met behulp van de configuratie-gemachtigde die is doorgegeven aan AddMessagePackProtocol
:
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);
});
Typecontroles zijn strikter in MessagePack
Het JSON Hub Protocol voert typeconversies uit tijdens deserialisatie. Als het binnenkomende object bijvoorbeeld een eigenschapswaarde heeft die een getal ({ foo: 42 }
) is, maar de eigenschap in de .NET-klasse van het type string
is, wordt de waarde geconverteerd. MessagePack voert deze conversie echter niet uit en genereert een uitzondering die kan worden weergegeven in logboeken aan de serverzijde (en in de console):
InvalidDataException: Error binding arguments. Make sure that the types of the provided values match the types of the hub method being invoked.
Zie GitHub-probleem aspnet/SignalR#2937voor meer informatie over deze beperking.
Tekens en tekenreeksen in Java
In de Java-client worden char
-objecten geserialiseerd als eenteken String
-objecten. Dit is in tegenstelling tot de C#- en JavaScript-client, die ze serialiseert als short
objecten. De MessagePack-specificatie zelf definieert geen gedrag voor char
objecten, dus het is aan de auteur van de bibliotheek om te bepalen hoe ze moeten worden geserialiseerd. Het verschil in gedrag tussen onze klanten is het resultaat van de bibliotheken die we voor onze implementaties hebben gebruikt.
Aanvullende informatiebronnen
In dit artikel wordt ervan uitgegaan dat de lezer bekend is met de onderwerpen die worden behandeld in Aan de slag met ASP.NET Core SignalR.
Wat is MessagePack?
MessagePack is een snel en compact binair serialisatieformaat. Het is handig wanneer prestaties en bandbreedte een probleem zijn omdat er kleinere berichten worden gemaakt in vergelijking met JSON-. De binaire berichten zijn onleesbaar wanneer u netwerktraceringen en logboeken bekijkt, tenzij de bytes worden doorgegeven via een MessagePack-parser. SignalR heeft ingebouwde ondersteuning voor de MessagePack-indeling en biedt API's die de client en server kunnen gebruiken.
MessagePack configureren op de server
Als u het MessagePack Hub Protocol op de server wilt inschakelen, installeert u het Microsoft.AspNetCore.SignalR.Protocols.MessagePack
-pakket in uw app. Voeg in de methode Startup.ConfigureServices
AddMessagePackProtocol
toe aan de AddSignalR
aanroep om ondersteuning voor MessagePack op de server in te schakelen.
Notitie
JSON is standaard ingeschakeld. Het toevoegen van MessagePack maakt ondersteuning mogelijk voor zowel JSON- als MessagePack-clients.
services.AddSignalR()
.AddMessagePackProtocol();
Als u wilt aanpassen hoe Uw gegevens in MessagePack worden opgemaakt, neemt AddMessagePackProtocol
een gemachtigde voor het configureren van opties. In deze gemachtigde kan de eigenschap FormatterResolvers
worden gebruikt om serialisatieopties voor MessagePack te configureren. Ga naar de MessagePack-bibliotheek op MessagePack-CSharp-voor meer informatie over de werking van de resolvers. Kenmerken kunnen worden gebruikt voor de objecten die u wilt serialiseren om te definiëren hoe ze moeten worden verwerkt.
services.AddSignalR()
.AddMessagePackProtocol(options =>
{
options.FormatterResolvers = new List<MessagePack.IFormatterResolver>()
{
MessagePack.Resolvers.StandardResolver.Instance
};
});
Waarschuwing
We raden u ten zeerste aan om CVE-2020-5234 te bekijken en de aanbevolen patches toe te passen. Stel bijvoorbeeld de statische eigenschap MessagePackSecurity.Active
in op MessagePackSecurity.UntrustedData
. Als u de MessagePackSecurity.Active
instelt, moet u handmatig een 1.9.x-versie van MessagePackinstalleren. Als u MessagePack
1.9.x installeert, wordt de versie die SignalR gebruikt, bijgewerkt.
MessagePack
versie 2.x heeft belangrijke wijzigingen geïntroduceerd en is niet compatibel met SignalR versie 3.1 en eerder. Wanneer MessagePackSecurity.Active
niet is ingesteld op MessagePackSecurity.UntrustedData
, kan een kwaadwillende client een denial of service veroorzaken. Stel MessagePackSecurity.Active
in Program.Main
in, zoals wordt weergegeven in de volgende code:
using MessagePack;
public static void Main(string[] args)
{
MessagePackSecurity.Active = MessagePackSecurity.UntrustedData;
CreateHostBuilder(args).Build().Run();
}
MessagePack configureren op de client
Notitie
JSON is standaard ingeschakeld voor de ondersteunde clients. Clients kunnen slechts één protocol ondersteunen. Het toevoegen van MessagePack-ondersteuning vervangt alle eerder geconfigureerde protocollen.
.NET client
Als u MessagePack wilt inschakelen in de .NET-client, installeert u het Microsoft.AspNetCore.SignalR.Protocols.MessagePack
-pakket en roept u AddMessagePackProtocol
aan op HubConnectionBuilder
.
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.DependencyInjection;
var hubConnection = new HubConnectionBuilder()
.WithUrl("/chathub")
.AddMessagePackProtocol()
.Build();
Notitie
Deze AddMessagePackProtocol
-oproep neemt een delegate aan om opties te configureren, net zoals de server.
JavaScript-client
MessagePack-ondersteuning voor de JavaScript-client wordt geleverd door het pakket @microsoft/signalr-protocol-msgpack npm. Installeer het pakket door de volgende opdracht uit te voeren in een opdrachtshell:
npm install @microsoft/signalr-protocol-msgpack
Na de installatie van het npm-pakket kan de module rechtstreeks worden gebruikt via een JavaScript-modulelaadprogramma of in de browser worden geïmporteerd door te verwijzen naar het volgende bestand:
node_modules\@microsoft\signalr-protocol-msgpack\dist\browser\signalr-protocol-msgpack.js
In een browser moet ook naar de msgpack5
bibliotheek worden verwezen. Gebruik een <script>
-tag om een verwijzing te maken. De bibliotheek is te vinden op node_modules\msgpack5\dist\msgpack5.js.
Notitie
Wanneer u het element <script>
gebruikt, is de volgorde belangrijk. Als signalr-protocol-msgpack.js
wordt verwezen voordat msgpack5.js
, treedt er een fout op wanneer u verbinding probeert te maken met MessagePack.
signalr.js
is ook vereist voordat signalr-protocol-msgpack.js
.
<script src="~/lib/signalr/signalr.js"></script>
<script src="~/lib/msgpack5/msgpack5.js"></script>
<script src="~/lib/signalr/signalr-protocol-msgpack.js"></script>
Door .withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
toe te voegen aan de HubConnectionBuilder
wordt de client geconfigureerd voor het gebruik van het MessagePack-protocol bij het maken van verbinding met een server.
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
.build();
Notitie
Op dit moment zijn er geen configuratieopties voor het MessagePack-protocol op de JavaScript-client.
Overwegingen voor MessagePack
Er zijn enkele problemen waarmee u rekening moet houden bij het gebruik van het MessagePack Hub Protocol.
MessagePack is hoofdlettergevoelig
Het MessagePack-protocol is hoofdlettergevoelig. Denk bijvoorbeeld aan de volgende C#-klasse:
public class ChatMessage
{
public string Sender { get; }
public string Message { get; }
}
Wanneer u verzendt vanuit de JavaScript-client, moet u PascalCased
eigenschapsnamen gebruiken, omdat de behuizing exact moet overeenkomen met de C#-klasse. Bijvoorbeeld:
connection.invoke("SomeMethod", { Sender: "Sally", Message: "Hello!" });
Als u camelCased
-namen gebruikt, zullen deze niet correct worden verbonden met de C#-klasse. U kunt dit omzeilen door het kenmerk Key
te gebruiken om een andere naam op te geven voor de eigenschap MessagePack. Zie de MessagePack-CSharp documentatievoor meer informatie.
DateTime.Kind wordt niet behouden tijdens het serialiseren en deserialiseren.
Het MessagePack-protocol biedt geen manier om de Kind
waarde van een DateTime
te coderen. Als gevolg hiervan wordt bij het deserialiseren van een datum in het MessagePack Hub-protocol ervan uitgegaan dat de binnenkomende datum de UTC-indeling heeft. Als u werkt met DateTime
waarden in lokale tijd, raden we u aan om te converteren naar UTC voordat u ze verzendt. Converteer ze van UTC naar lokale tijd wanneer u ze ontvangt.
Zie GitHub-probleem aspnet/SignalR#2632voor meer informatie over deze beperking.
DateTime.MinValue wordt niet ondersteund door MessagePack in JavaScript
De msgpack5-bibliotheek die wordt gebruikt door de SignalR JavaScript-client biedt geen ondersteuning voor het timestamp96
type in MessagePack. Dit type wordt gebruikt om zeer grote datumwaarden te coderen (zeer vroeg in het verleden of heel ver in de toekomst). De waarde van DateTime.MinValue
is January 1, 0001
, die moet worden gecodeerd in een timestamp96
waarde. Daarom wordt het verzenden van DateTime.MinValue
naar een JavaScript-client niet ondersteund. Wanneer DateTime.MinValue
wordt ontvangen door de JavaScript-client, wordt de volgende fout gegenereerd:
Uncaught Error: unable to find ext type 255 at decoder.js:427
Meestal wordt DateTime.MinValue
gebruikt om een 'ontbrekende' of null
waarde te coderen. Als u die waarde in MessagePack moet coderen, gebruikt u een nullable DateTime
waarde (DateTime?
) of codeert u een afzonderlijke bool
waarde die aangeeft of de datum aanwezig is.
Zie GitHub-probleem aspnet/SignalR#2228voor meer informatie over deze beperking.
MessagePack-ondersteuning in een voorafgaande compilatieomgeving
De MessagePack-CSharp bibliotheek die wordt gebruikt door de .NET-client en -server maakt gebruik van codegeneratie om serialisatie te optimaliseren. Als gevolg hiervan wordt het niet standaard ondersteund voor omgevingen die gebruikmaken van compilatie vooraf, zoals de gebruikersinterface van de net-app met meerdere platforms (.NET MAUI) of Unity. Het is mogelijk om MessagePack in deze omgevingen te gebruiken door de serializer-/deserializer-code vooraf te genereren. Zie de MessagePack-CSharp documentatievoor meer informatie. Nadat u de serializers vooraf hebt gegenereerd, kunt u deze registreren met behulp van de configuratie-gemachtigde die is doorgegeven aan AddMessagePackProtocol
:
services.AddSignalR()
.AddMessagePackProtocol(options =>
{
options.FormatterResolvers = new List<MessagePack.IFormatterResolver>()
{
MessagePack.Resolvers.GeneratedResolver.Instance,
MessagePack.Resolvers.StandardResolver.Instance
};
});
Typecontroles zijn strikter in MessagePack
Het JSON Hub Protocol voert typeconversies uit tijdens deserialisatie. Als het binnenkomende object bijvoorbeeld een eigenschapswaarde heeft die een getal ({ foo: 42 }
) is, maar de eigenschap in de .NET-klasse van het type string
is, wordt de waarde geconverteerd. MessagePack voert deze conversie echter niet uit en genereert een uitzondering die kan worden weergegeven in logboeken aan de serverzijde (en in de console):
InvalidDataException: Error binding arguments. Make sure that the types of the provided values match the types of the hub method being invoked.
Zie GitHub-probleem aspnet/SignalR#2937voor meer informatie over deze beperking.
Aanvullende informatiebronnen
In dit artikel wordt ervan uitgegaan dat de lezer bekend is met de onderwerpen die worden behandeld in Aan de slag met ASP.NET Core SignalR.
Wat is MessagePack?
MessagePack is een snelle en compacte binaire serialisatieformaat. Het is handig wanneer prestaties en bandbreedte een probleem zijn omdat er kleinere berichten worden gemaakt in vergelijking met JSON-. De binaire berichten zijn onleesbaar wanneer u netwerktraceringen en logboeken bekijkt, tenzij de bytes worden doorgegeven via een MessagePack-parser. SignalR heeft ingebouwde ondersteuning voor de MessagePack-indeling en biedt API's die de client en server kunnen gebruiken.
MessagePack configureren op de server
Als u het MessagePack Hub Protocol op de server wilt inschakelen, installeert u het Microsoft.AspNetCore.SignalR.Protocols.MessagePack
-pakket in uw app. Voeg in de methode Startup.ConfigureServices
AddMessagePackProtocol
toe aan de AddSignalR
aanroep om ondersteuning voor MessagePack op de server in te schakelen.
Notitie
JSON is standaard ingeschakeld. Het toevoegen van MessagePack maakt ondersteuning mogelijk voor zowel JSON- als MessagePack-clients.
services.AddSignalR()
.AddMessagePackProtocol();
Als u wilt aanpassen hoe Uw gegevens in MessagePack worden opgemaakt, neemt AddMessagePackProtocol
een gemachtigde voor het configureren van opties. In deze gemachtigde kan de eigenschap FormatterResolvers
worden gebruikt om serialisatieopties voor MessagePack te configureren. Ga naar de MessagePack-bibliotheek op MessagePack-CSharp-voor meer informatie over de werking van de resolvers. Kenmerken kunnen worden gebruikt voor de objecten die u wilt serialiseren om te definiëren hoe ze moeten worden verwerkt.
services.AddSignalR()
.AddMessagePackProtocol(options =>
{
options.FormatterResolvers = new List<MessagePack.IFormatterResolver>()
{
MessagePack.Resolvers.StandardResolver.Instance
};
});
Waarschuwing
We raden u ten zeerste aan om CVE-2020-5234 te bekijken en de aanbevolen patches toe te passen. Stel bijvoorbeeld de statische eigenschap MessagePackSecurity.Active
in op MessagePackSecurity.UntrustedData
. Als u de MessagePackSecurity.Active
instelt, moet u handmatig een 1.9.x-versie van MessagePackinstalleren. Als u MessagePack
1.9.x installeert, wordt de versie die SignalR gebruikt, bijgewerkt. Wanneer MessagePackSecurity.Active
niet is ingesteld op MessagePackSecurity.UntrustedData
, kan een kwaadwillende client een denial of service veroorzaken. Stel MessagePackSecurity.Active
in Program.Main
in, zoals wordt weergegeven in de volgende code:
using MessagePack;
public static void Main(string[] args)
{
MessagePackSecurity.Active = MessagePackSecurity.UntrustedData;
CreateHostBuilder(args).Build().Run();
}
MessagePack configureren op de client
Notitie
JSON is standaard ingeschakeld voor de ondersteunde clients. Clients kunnen slechts één protocol ondersteunen. Het toevoegen van MessagePack-ondersteuning vervangt alle eerder geconfigureerde protocollen.
.NET-client
Als u MessagePack wilt inschakelen in de .NET-client, installeert u het Microsoft.AspNetCore.SignalR.Protocols.MessagePack
-pakket en roept u AddMessagePackProtocol
aan op HubConnectionBuilder
.
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.DependencyInjection;
var hubConnection = new HubConnectionBuilder()
.WithUrl("/chathub")
.AddMessagePackProtocol()
.Build();
Notitie
Deze AddMessagePackProtocol
oproep accepteert een delegate om opties te configureren, net zoals bij de server.
JavaScript-client
MessagePack-ondersteuning voor de JavaScript-client wordt geleverd door het pakket @aspnet/signalr-protocol-msgpack npm. Installeer het pakket door de volgende opdracht uit te voeren in een opdrachtshell:
npm install @aspnet/signalr-protocol-msgpack
Na de installatie van het npm-pakket kan de module rechtstreeks worden gebruikt via een JavaScript-modulelaadprogramma of in de browser worden geïmporteerd door te verwijzen naar het volgende bestand:
node_modules\@aspnet\signalr-protocol-msgpack\dist\browser\signalr-protocol-msgpack.js
In een browser moet ook naar de msgpack5
bibliotheek worden verwezen. Gebruik een <script>
-tag om een verwijzing te maken. De bibliotheek is te vinden op node_modules\msgpack5\dist\msgpack5.js.
Notitie
Wanneer u het element <script>
gebruikt, is de volgorde belangrijk. Als signalr-protocol-msgpack.js
wordt verwezen voordat msgpack5.js
, treedt er een fout op wanneer u verbinding probeert te maken met MessagePack.
signalr.js
is ook vereist voordat signalr-protocol-msgpack.js
.
<script src="~/lib/signalr/signalr.js"></script>
<script src="~/lib/msgpack5/msgpack5.js"></script>
<script src="~/lib/signalr/signalr-protocol-msgpack.js"></script>
Door .withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
toe te voegen aan de HubConnectionBuilder
wordt de client geconfigureerd voor het gebruik van het MessagePack-protocol bij het maken van verbinding met een server.
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
.build();
Notitie
Op dit moment zijn er geen configuratieopties voor het MessagePack-protocol op de JavaScript-client.
Overwegingen voor MessagePack
Er zijn enkele problemen waarmee u rekening moet houden bij het gebruik van het MessagePack Hub Protocol.
MessagePack is hoofdlettergevoelig
Het MessagePack-protocol is hoofdlettergevoelig. Denk bijvoorbeeld aan de volgende C#-klasse:
public class ChatMessage
{
public string Sender { get; }
public string Message { get; }
}
Wanneer u verzendt vanuit de JavaScript-client, moet u PascalCased
eigenschapsnamen gebruiken, omdat de behuizing exact moet overeenkomen met de C#-klasse. Bijvoorbeeld:
connection.invoke("SomeMethod", { Sender: "Sally", Message: "Hello!" });
Het gebruik van camelCased
-namen zal niet correct binden aan de C#-klasse. U kunt dit omzeilen door het kenmerk Key
te gebruiken om een andere naam op te geven voor de eigenschap MessagePack. Zie de MessagePack-CSharp documentatievoor meer informatie.
DateTime.Kind wordt niet behouden bij het serialiseren/deserialiseren
Het MessagePack-protocol biedt geen manier om de Kind
waarde van een DateTime
te coderen. Als gevolg hiervan wordt bij het deserialiseren van een datum in het MessagePack Hub-protocol ervan uitgegaan dat de binnenkomende datum de UTC-indeling heeft. Als u werkt met DateTime
waarden in lokale tijd, raden we u aan om te converteren naar UTC voordat u ze verzendt. Converteer ze van UTC naar lokale tijd wanneer u ze ontvangt.
Zie GitHub-probleem aspnet/SignalR#2632voor meer informatie over deze beperking.
DateTime.MinValue wordt niet ondersteund door MessagePack in JavaScript
De msgpack5-bibliotheek die wordt gebruikt door de SignalR JavaScript-client biedt geen ondersteuning voor het timestamp96
type in MessagePack. Dit type wordt gebruikt om zeer grote datumwaarden te coderen (zeer vroeg in het verleden of heel ver in de toekomst). De waarde van DateTime.MinValue
is January 1, 0001
die in een timestamp96
-waarde moet worden gecodeerd. Daarom wordt het verzenden van DateTime.MinValue
naar een JavaScript-client niet ondersteund. Wanneer DateTime.MinValue
wordt ontvangen door de JavaScript-client, wordt de volgende fout gegenereerd:
Uncaught Error: unable to find ext type 255 at decoder.js:427
Meestal wordt DateTime.MinValue
gebruikt om een 'ontbrekende' of null
waarde te coderen. Als u die waarde in MessagePack moet coderen, gebruikt u een nullable DateTime
waarde (DateTime?
) of codeert u een afzonderlijke bool
waarde die aangeeft of de datum aanwezig is.
Zie GitHub-probleem aspnet/SignalR#2228voor meer informatie over deze beperking.
MessagePack-ondersteuning in "ahead-of-time" compilatieomgeving
De MessagePack-CSharp bibliotheek die wordt gebruikt door de .NET-client en -server maakt gebruik van codegeneratie om serialisatie te optimaliseren. Als gevolg hiervan wordt het niet standaard ondersteund voor omgevingen die gebruikmaken van compilatie vooraf, zoals de gebruikersinterface van de net-app met meerdere platforms (.NET MAUI) of Unity. Het is mogelijk om MessagePack in deze omgevingen te gebruiken door de serializer-/deserializer-code vooraf te genereren. Raadpleeg de MessagePack-CSharp documentatievoor meer informatie. Nadat u de serializers vooraf hebt gegenereerd, kunt u ze registreren met behulp van de configuratie-gedelegeerde die aan AddMessagePackProtocol
is doorgegeven:
services.AddSignalR()
.AddMessagePackProtocol(options =>
{
options.FormatterResolvers = new List<MessagePack.IFormatterResolver>()
{
MessagePack.Resolvers.GeneratedResolver.Instance,
MessagePack.Resolvers.StandardResolver.Instance
};
});
Typecontroles zijn strikter in MessagePack
Het JSON Hub Protocol voert typeconversies uit tijdens deserialisatie. Als het binnenkomende object bijvoorbeeld een eigenschapswaarde heeft die een getal ({ foo: 42 }
) is, maar de eigenschap in de .NET-klasse van het type string
is, wordt de waarde geconverteerd. MessagePack voert deze conversie echter niet uit en genereert een uitzondering die kan worden weergegeven in logboeken aan de serverzijde (en in de console):
InvalidDataException: Error binding arguments. Make sure that the types of the provided values match the types of the hub method being invoked.
Zie GitHub-probleem aspnet/SignalR#2937voor meer informatie over deze beperking.