Używanie protokołu MessagePack Hub w programie SignalR dla platformy ASP.NET Core
W tym artykule założono, że czytelnik jest zaznajomiony z tematami opisanymi w temacie Wprowadzenie do platformy ASP.NET Core SignalR.
Co to jest MessagePack?
MessagePack to szybki i kompaktowy format serializacji binarnej. Jest to przydatne, gdy wydajność i przepustowość są problemem, ponieważ tworzy mniejsze komunikaty niż JSWŁĄCZONE. Komunikaty binarne są nieczytelne podczas przeglądania śladów sieci i dzienników, chyba że bajty są przekazywane za pośrednictwem analizatora MessagePack. SignalR Ma wbudowaną obsługę formatu MessagePack i udostępnia interfejsy API dla klienta i serwera do użycia.
Konfigurowanie pakietu MessagePack na serwerze
Aby włączyć protokół Centrum MessagePack na serwerze, zainstaluj Microsoft.AspNetCore.SignalR.Protocols.MessagePack
pakiet w aplikacji. W metodzie dodaj AddMessagePackProtocol
metodę Startup.ConfigureServices
do wywołania AddSignalR
, aby włączyć obsługę pakietu MessagePack na serwerze.
services.AddSignalR()
.AddMessagePackProtocol();
Uwaga
JSWłączone jest domyślnie włączone. Dodanie pakietu MessagePack umożliwia obsługę zarówno JSklientów ON, jak i MessagePack.
Aby dostosować sposób formatowania danych pakietu MessagePack, AddMessagePackProtocol
przyjmuje delegata do konfigurowania opcji. W tym delegatu SerializerOptions
właściwość jest używana do konfigurowania opcji serializacji MessagePack. Aby uzyskać więcej informacji na temat sposobu działania funkcji rozpoznawania nazw, odwiedź bibliotekę MessagePack w witrynie MessagePack-CSharp. Atrybuty mogą być używane w obiektach, które chcesz serializować, aby zdefiniować sposób ich obsługi.
services.AddSignalR()
.AddMessagePackProtocol(options =>
{
options.SerializerOptions = MessagePackSerializerOptions.Standard
.WithResolver(new CustomResolver())
.WithSecurity(MessagePackSecurity.UntrustedData);
});
Ostrzeżenie
Zdecydowanie zalecamy przejrzenie luki CVE-2020-5234 i zastosowanie zalecanych poprawek. Na przykład wywołanie .WithSecurity(MessagePackSecurity.UntrustedData)
podczas zastępowania elementu SerializerOptions
.
Konfigurowanie pakietu MessagePack na kliencie
Uwaga
JSOpcja WŁ. jest domyślnie włączona dla obsługiwanych klientów. Klienci mogą obsługiwać tylko jeden protokół. Dodanie obsługi pakietu MessagePack zastępuje wszystkie wcześniej skonfigurowane protokoły.
Klient .NET
Aby włączyć pakiet MessagePack w kliencie .NET, zainstaluj Microsoft.AspNetCore.SignalR.Protocols.MessagePack
pakiet i wywołaj polecenie AddMessagePackProtocol
na .HubConnectionBuilder
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.DependencyInjection;
var hubConnection = new HubConnectionBuilder()
.WithUrl("/chathub")
.AddMessagePackProtocol()
.Build();
Uwaga
To AddMessagePackProtocol
wywołanie pobiera delegata do konfigurowania opcji tak jak serwer.
Klient środowiska JavaScript
Obsługa pakietu MessagePack dla klienta JavaScript jest zapewniana przez pakiet npm @microsoft/signalr-protocol-msgpack . Zainstaluj pakiet, wykonując następujące polecenie w powłoce poleceń:
npm install @microsoft/signalr-protocol-msgpack
Po zainstalowaniu pakietu npm moduł może być używany bezpośrednio za pośrednictwem modułu ładującego modułu JavaScript lub zaimportowany do przeglądarki, odwołując się do następującego pliku:
node_modules\@microsoft\signalr-protocol-msgpack\dist\browser\signalr-protocol-msgpack.js
W poniższej kolejności należy odwołać się do następujących wymaganych plików javaScript:
<script src="~/lib/signalr/signalr.js"></script>
<script src="~/lib/signalr/signalr-protocol-msgpack.js"></script>
Dodanie .withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
do programu HubConnectionBuilder
konfiguruje klienta do używania protokołu MessagePack podczas nawiązywania połączenia z serwerem.
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
.build();
Obecnie nie ma opcji konfiguracji protokołu MessagePack na kliencie JavaScript.
Klienta środowiska Java
Aby włączyć pakiet MessagePack za pomocą języka Java, zainstaluj com.microsoft.signalr.messagepack
pakiet. W przypadku korzystania z narzędzia Gradle dodaj następujący wiersz do dependencies
sekcji pliku build.gradle :
implementation 'com.microsoft.signalr.messagepack:signalr-messagepack:5.0.0'
W przypadku korzystania z narzędzia Maven dodaj następujące wiersze wewnątrz <dependencies>
elementu pom.xml
pliku:
<dependency>
<groupId>com.microsoft.signalr.messagepack</groupId>
<artifactId>signalr</artifactId>
<version>5.0.0</version>
</dependency>
Wywołaj metodę withHubProtocol(new MessagePackHubProtocol())
na HubConnectionBuilder
.
HubConnection messagePackConnection = HubConnectionBuilder.create("YOUR HUB URL HERE")
.withHubProtocol(new MessagePackHubProtocol())
.build();
Zagadnienia dotyczące pakietu MessagePack
Podczas korzystania z protokołu Centrum MessagePack należy pamiętać o kilku problemach.
Funkcja MessagePack uwzględnia wielkość liter
W protokole MessagePack jest rozróżniana wielkość liter. Rozważmy na przykład następującą klasę języka C#:
public class ChatMessage
{
public string Sender { get; }
public string Message { get; }
}
Podczas wysyłania z klienta JavaScript należy używać PascalCased
nazw właściwości, ponieważ wielkość liter musi być dokładnie zgodna z klasą języka C#. Przykład:
connection.invoke("SomeMethod", { Sender: "Sally", Message: "Hello!" });
Użycie camelCased
nazw nie będzie poprawnie wiązać się z klasą C#. Można to obejść, używając atrybutu Key
, aby określić inną nazwę właściwości MessagePack. Aby uzyskać więcej informacji, zobacz dokumentację MessagePack-CSharp.
Parametr DateTime.Kind nie jest zachowywany podczas serializacji/deserializacji
Protokół MessagePack nie zapewnia sposobu kodowania Kind
wartości elementu DateTime
. W związku z tym podczas deserializacji daty protokół centrum MessagePack zostanie przekonwertowany na format UTC, jeśli DateTime.Kind
w DateTimeKind.Local
przeciwnym razie nie będzie dotykać czasu i przekazywać go w taki sposób, jak jest. Jeśli pracujesz z wartościami DateTime
, zalecamy przekonwertowanie na czas UTC przed ich wysłaniem. Przekonwertuj je z czasu UTC na czas lokalny, gdy je otrzymasz.
Obsługa pakietu MessagePack w środowisku kompilacji "przed czasem"
Biblioteka MessagePack-CSharp używana przez klienta i serwer platformy .NET używa generowania kodu do optymalizacji serializacji. W związku z tym nie jest ona domyślnie obsługiwana w środowiskach korzystających z kompilacji "przed czasem" (np. Xamarin iOS lub Unity). W tych środowiskach można użyć pakietu MessagePack przez "wstępne generowanie" kodu serializatora/deserializatora. Aby uzyskać więcej informacji, zobacz dokumentację MessagePack-CSharp. Po wstępnie wygenerowanym serializatorach można je zarejestrować przy użyciu delegata konfiguracji przekazanego do :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);
});
Kontrole typów są bardziej rygorystyczne w usłudze MessagePack
JSProtokół ON Hub będzie wykonywać konwersje typów podczas deserializacji. Jeśli na przykład obiekt przychodzący ma wartość właściwości , która jest liczbą ({ foo: 42 }
), ale właściwość klasy .NET jest typu string
, wartość zostanie przekonwertowana. Jednak pakiet MessagePack nie wykonuje tej konwersji i zgłosi wyjątek, który można zobaczyć w dziennikach po stronie serwera (i w konsoli):
InvalidDataException: Error binding arguments. Make sure that the types of the provided values match the types of the hub method being invoked.
Aby uzyskać więcej informacji na temat tego ograniczenia, zobacz problem z usługą GitHub aspnet/SignalR#2937.
Znaki i ciągi w języku Java
W kliencie char
java obiekty będą serializowane jako obiekty jednoznakowe String
. Jest to w przeciwieństwie do klienta C# i JavaScript, który serializuje je jako short
obiekty. Specyfikacja pakietu MessagePack nie definiuje zachowania dla char
obiektów, dlatego autor biblioteki decyduje o tym, jak je serializować. Różnica w zachowaniu naszych klientów jest wynikiem bibliotek używanych do implementacji.
Dodatkowe zasoby
W tym artykule założono, że czytelnik jest zaznajomiony z tematami opisanymi w temacie Wprowadzenie do platformy ASP.NET Core SignalR.
Co to jest MessagePack?
MessagePack to szybki i kompaktowy format serializacji binarnej. Jest to przydatne, gdy wydajność i przepustowość są problemem, ponieważ tworzy mniejsze komunikaty w porównaniu z JSwłączonym. Komunikaty binarne są nieczytelne podczas przeglądania śladów sieci i dzienników, chyba że bajty są przekazywane za pośrednictwem analizatora MessagePack. SignalR Ma wbudowaną obsługę formatu MessagePack i udostępnia interfejsy API dla klienta i serwera do użycia.
Konfigurowanie pakietu MessagePack na serwerze
Aby włączyć protokół Centrum MessagePack na serwerze, zainstaluj Microsoft.AspNetCore.SignalR.Protocols.MessagePack
pakiet w aplikacji. W metodzie dodaj AddMessagePackProtocol
metodę Startup.ConfigureServices
do wywołania AddSignalR
, aby włączyć obsługę pakietu MessagePack na serwerze.
Uwaga
JSWłączone jest domyślnie włączone. Dodanie pakietu MessagePack umożliwia obsługę zarówno JSklientów ON, jak i MessagePack.
services.AddSignalR()
.AddMessagePackProtocol();
Aby dostosować sposób formatowania danych przez pakiet MessagePack, AddMessagePackProtocol
przyjmuje delegata do konfigurowania opcji. W tym delegatu SerializerOptions
właściwość może służyć do konfigurowania opcji serializacji MessagePack. Aby uzyskać więcej informacji na temat sposobu działania funkcji rozpoznawania nazw, odwiedź bibliotekę MessagePack w witrynie MessagePack-CSharp. Atrybuty mogą być używane w obiektach, które chcesz serializować, aby zdefiniować sposób ich obsługi.
services.AddSignalR()
.AddMessagePackProtocol(options =>
{
options.SerializerOptions = MessagePackSerializerOptions.Standard
.WithResolver(new CustomResolver())
.WithSecurity(MessagePackSecurity.UntrustedData);
});
Ostrzeżenie
Zdecydowanie zalecamy przejrzenie luki CVE-2020-5234 i zastosowanie zalecanych poprawek. Na przykład wywołanie .WithSecurity(MessagePackSecurity.UntrustedData)
podczas zastępowania elementu SerializerOptions
.
Konfigurowanie pakietu MessagePack na kliencie
Uwaga
JSOpcja WŁ. jest domyślnie włączona dla obsługiwanych klientów. Klienci mogą obsługiwać tylko jeden protokół. Dodanie obsługi pakietu MessagePack spowoduje zastąpienie wszystkich wcześniej skonfigurowanych protokołów.
Klient .NET
Aby włączyć pakiet MessagePack w kliencie .NET, zainstaluj Microsoft.AspNetCore.SignalR.Protocols.MessagePack
pakiet i wywołaj polecenie AddMessagePackProtocol
na .HubConnectionBuilder
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.DependencyInjection;
var hubConnection = new HubConnectionBuilder()
.WithUrl("/chathub")
.AddMessagePackProtocol()
.Build();
Uwaga
To AddMessagePackProtocol
wywołanie pobiera delegata do konfigurowania opcji tak jak serwer.
Klient środowiska JavaScript
Obsługa pakietu MessagePack dla klienta JavaScript jest zapewniana przez pakiet npm @microsoft/signalr-protocol-msgpack . Zainstaluj pakiet, wykonując następujące polecenie w powłoce poleceń:
npm install @microsoft/signalr-protocol-msgpack
Po zainstalowaniu pakietu npm moduł może być używany bezpośrednio za pośrednictwem modułu ładującego modułu JavaScript lub zaimportowany do przeglądarki, odwołując się do następującego pliku:
node_modules\@microsoft\signalr-protocol-msgpack\dist\browser\signalr-protocol-msgpack.js
W przeglądarce msgpack5
należy również odwołać się do biblioteki. Użyj tagu <script>
, aby utworzyć odwołanie. Bibliotekę można znaleźć w node_modules\msgpack5\dist\msgpack5.js.
Uwaga
W przypadku korzystania z <script>
elementu kolejność jest ważna. Jeśli signalr-protocol-msgpack.js
wystąpi odwołanie przed msgpack5.js
, podczas próby nawiązania połączenia z pakietem MessagePack wystąpi błąd. signalr.js
jest również wymagany przed 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>
Dodanie .withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
do programu HubConnectionBuilder
spowoduje skonfigurowanie klienta do używania protokołu MessagePack podczas nawiązywania połączenia z serwerem.
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
.build();
Uwaga
Obecnie nie ma opcji konfiguracji protokołu MessagePack na kliencie JavaScript.
Klienta środowiska Java
Aby włączyć pakiet MessagePack za pomocą języka Java, zainstaluj com.microsoft.signalr.messagepack
pakiet. W przypadku korzystania z narzędzia Gradle dodaj następujący wiersz do dependencies
sekcji pliku build.gradle :
implementation 'com.microsoft.signalr.messagepack:signalr-messagepack:5.0.0'
W przypadku korzystania z narzędzia Maven dodaj następujące wiersze wewnątrz <dependencies>
elementu pom.xml
pliku:
<dependency>
<groupId>com.microsoft.signalr.messagepack</groupId>
<artifactId>signalr</artifactId>
<version>5.0.0</version>
</dependency>
Wywołaj metodę withHubProtocol(new MessagePackHubProtocol())
na HubConnectionBuilder
.
HubConnection messagePackConnection = HubConnectionBuilder.create("YOUR HUB URL HERE")
.withHubProtocol(new MessagePackHubProtocol())
.build();
Zagadnienia dotyczące pakietu MessagePack
Podczas korzystania z protokołu Centrum MessagePack należy pamiętać o kilku problemach.
Funkcja MessagePack uwzględnia wielkość liter
W protokole MessagePack jest rozróżniana wielkość liter. Rozważmy na przykład następującą klasę języka C#:
public class ChatMessage
{
public string Sender { get; }
public string Message { get; }
}
Podczas wysyłania z klienta JavaScript należy używać PascalCased
nazw właściwości, ponieważ wielkość liter musi być dokładnie zgodna z klasą języka C#. Przykład:
connection.invoke("SomeMethod", { Sender: "Sally", Message: "Hello!" });
Użycie camelCased
nazw nie będzie poprawnie wiązać się z klasą C#. Można to obejść, używając atrybutu Key
, aby określić inną nazwę właściwości MessagePack. Aby uzyskać więcej informacji, zobacz dokumentację MessagePack-CSharp.
Parametr DateTime.Kind nie jest zachowywany podczas serializacji/deserializacji
Protokół MessagePack nie zapewnia sposobu kodowania Kind
wartości elementu DateTime
. W związku z tym podczas deserializacji daty protokół centrum MessagePack zostanie przekonwertowany na format UTC, jeśli DateTime.Kind
w DateTimeKind.Local
przeciwnym razie nie będzie dotykać czasu i przekazywać go w taki sposób, jak jest. Jeśli pracujesz z wartościami DateTime
, zalecamy przekonwertowanie na czas UTC przed ich wysłaniem. Przekonwertuj je z czasu UTC na czas lokalny, gdy je otrzymasz.
Wartość DateTime.MinValue nie jest obsługiwana przez pakiet MessagePack w języku JavaScript
Biblioteka msgpack5 używana przez klienta JavaScript nie obsługuje typu w elemecie SignalRtimestamp96
MessagePack. Ten typ służy do kodowania bardzo dużych wartości dat (bardzo wcześnie w przeszłości lub bardzo daleko w przyszłości). Wartość to DateTime.MinValue
January 1, 0001
, która musi być zakodowana timestamp96
w wartości. W związku z tym wysyłanie DateTime.MinValue
do klienta JavaScript nie jest obsługiwane. Po DateTime.MinValue
odebraniu przez klienta języka JavaScript zgłaszany jest następujący błąd:
Uncaught Error: unable to find ext type 255 at decoder.js:427
DateTime.MinValue
Zwykle służy do kodowania "brakującej" lub null
wartości. Jeśli chcesz zakodować tą wartość w usłudze MessagePack, użyj wartości dopuszczalnej DateTime
wartości null (DateTime?
) lub zakoduj oddzielną bool
wartość wskazującą, czy data jest obecna.
Aby uzyskać więcej informacji na temat tego ograniczenia, zobacz problem z usługą GitHub aspnet/SignalR#2228.
Obsługa pakietu MessagePack w środowisku kompilacji "przed czasem"
Biblioteka MessagePack-CSharp używana przez klienta i serwer platformy .NET używa generowania kodu do optymalizacji serializacji. W związku z tym nie jest ona domyślnie obsługiwana w środowiskach korzystających z kompilacji "przed czasem" (np. Xamarin iOS lub Unity). W tych środowiskach można użyć pakietu MessagePack przez "wstępne generowanie" kodu serializatora/deserializatora. Aby uzyskać więcej informacji, zobacz dokumentację MessagePack-CSharp. Po wstępnie wygenerowanym serializatorach można je zarejestrować przy użyciu delegata konfiguracji przekazanego do :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);
});
Kontrole typów są bardziej rygorystyczne w usłudze MessagePack
JSProtokół ON Hub będzie wykonywać konwersje typów podczas deserializacji. Jeśli na przykład obiekt przychodzący ma wartość właściwości , która jest liczbą ({ foo: 42 }
), ale właściwość klasy .NET jest typu string
, wartość zostanie przekonwertowana. Jednak pakiet MessagePack nie wykonuje tej konwersji i zgłosi wyjątek, który można zobaczyć w dziennikach po stronie serwera (i w konsoli):
InvalidDataException: Error binding arguments. Make sure that the types of the provided values match the types of the hub method being invoked.
Aby uzyskać więcej informacji na temat tego ograniczenia, zobacz problem z usługą GitHub aspnet/SignalR#2937.
Znaki i ciągi w języku Java
W kliencie char
java obiekty będą serializowane jako obiekty jednoznakowe String
. Jest to w przeciwieństwie do klienta C# i JavaScript, który serializuje je jako short
obiekty. Specyfikacja pakietu MessagePack nie definiuje zachowania dla char
obiektów, dlatego autor biblioteki decyduje o tym, jak je serializować. Różnica w zachowaniu naszych klientów jest wynikiem bibliotek używanych do implementacji.
Dodatkowe zasoby
W tym artykule założono, że czytelnik jest zaznajomiony z tematami opisanymi w temacie Wprowadzenie do platformy ASP.NET Core SignalR.
Co to jest MessagePack?
MessagePack to szybki i kompaktowy format serializacji binarnej. Jest to przydatne, gdy wydajność i przepustowość są problemem, ponieważ tworzy mniejsze komunikaty w porównaniu z JSwłączonym. Komunikaty binarne są nieczytelne podczas przeglądania śladów sieci i dzienników, chyba że bajty są przekazywane za pośrednictwem analizatora MessagePack. SignalR Ma wbudowaną obsługę formatu MessagePack i udostępnia interfejsy API dla klienta i serwera do użycia.
Konfigurowanie pakietu MessagePack na serwerze
Aby włączyć protokół Centrum MessagePack na serwerze, zainstaluj Microsoft.AspNetCore.SignalR.Protocols.MessagePack
pakiet w aplikacji. W metodzie dodaj AddMessagePackProtocol
metodę Startup.ConfigureServices
do wywołania AddSignalR
, aby włączyć obsługę pakietu MessagePack na serwerze.
Uwaga
JSWłączone jest domyślnie włączone. Dodanie pakietu MessagePack umożliwia obsługę zarówno JSklientów ON, jak i MessagePack.
services.AddSignalR()
.AddMessagePackProtocol();
Aby dostosować sposób formatowania danych przez pakiet MessagePack, AddMessagePackProtocol
przyjmuje delegata do konfigurowania opcji. W tym delegatu FormatterResolvers
właściwość może służyć do konfigurowania opcji serializacji MessagePack. Aby uzyskać więcej informacji na temat sposobu działania funkcji rozpoznawania nazw, odwiedź bibliotekę MessagePack w witrynie MessagePack-CSharp. Atrybuty mogą być używane w obiektach, które chcesz serializować, aby zdefiniować sposób ich obsługi.
services.AddSignalR()
.AddMessagePackProtocol(options =>
{
options.FormatterResolvers = new List<MessagePack.IFormatterResolver>()
{
MessagePack.Resolvers.StandardResolver.Instance
};
});
Ostrzeżenie
Zdecydowanie zalecamy przejrzenie luki CVE-2020-5234 i zastosowanie zalecanych poprawek. Na przykład ustawienie właściwości statycznej MessagePackSecurity.Active
na MessagePackSecurity.UntrustedData
. MessagePackSecurity.Active
Ustawienie elementu wymaga ręcznego zainstalowania wersji 1.9.x pakietu MessagePack. Instalowanie MessagePack
wersji 1.9.x uaktualnia używaną wersję SignalR . MessagePack
Wersja 2.x wprowadziła zmiany powodujące niezgodność i jest niezgodna z wersjami SignalR 3.1 i starszymi. Jeśli MessagePackSecurity.Active
wartość nie jest ustawiona na MessagePackSecurity.UntrustedData
, złośliwy klient może spowodować odmowę usługi. Ustaw MessagePackSecurity.Active
w pliku Program.Main
, jak pokazano w poniższym kodzie:
using MessagePack;
public static void Main(string[] args)
{
MessagePackSecurity.Active = MessagePackSecurity.UntrustedData;
CreateHostBuilder(args).Build().Run();
}
Konfigurowanie pakietu MessagePack na kliencie
Uwaga
JSOpcja WŁ. jest domyślnie włączona dla obsługiwanych klientów. Klienci mogą obsługiwać tylko jeden protokół. Dodanie obsługi pakietu MessagePack spowoduje zastąpienie wszystkich wcześniej skonfigurowanych protokołów.
Klient .NET
Aby włączyć pakiet MessagePack w kliencie .NET, zainstaluj Microsoft.AspNetCore.SignalR.Protocols.MessagePack
pakiet i wywołaj polecenie AddMessagePackProtocol
na .HubConnectionBuilder
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.DependencyInjection;
var hubConnection = new HubConnectionBuilder()
.WithUrl("/chathub")
.AddMessagePackProtocol()
.Build();
Uwaga
To AddMessagePackProtocol
wywołanie pobiera delegata do konfigurowania opcji tak jak serwer.
Klient środowiska JavaScript
Obsługa pakietu MessagePack dla klienta JavaScript jest zapewniana przez pakiet npm @microsoft/signalr-protocol-msgpack . Zainstaluj pakiet, wykonując następujące polecenie w powłoce poleceń:
npm install @microsoft/signalr-protocol-msgpack
Po zainstalowaniu pakietu npm moduł może być używany bezpośrednio za pośrednictwem modułu ładującego modułu JavaScript lub zaimportowany do przeglądarki, odwołując się do następującego pliku:
node_modules\@microsoft\signalr-protocol-msgpack\dist\browser\signalr-protocol-msgpack.js
W przeglądarce msgpack5
należy również odwołać się do biblioteki. Użyj tagu <script>
, aby utworzyć odwołanie. Bibliotekę można znaleźć w node_modules\msgpack5\dist\msgpack5.js.
Uwaga
W przypadku korzystania z <script>
elementu kolejność jest ważna. Jeśli signalr-protocol-msgpack.js
wystąpi odwołanie przed msgpack5.js
, podczas próby nawiązania połączenia z pakietem MessagePack wystąpi błąd. signalr.js
jest również wymagany przed 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>
Dodanie .withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
do programu HubConnectionBuilder
spowoduje skonfigurowanie klienta do używania protokołu MessagePack podczas nawiązywania połączenia z serwerem.
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
.build();
Uwaga
Obecnie nie ma opcji konfiguracji protokołu MessagePack na kliencie JavaScript.
Zagadnienia dotyczące pakietu MessagePack
Podczas korzystania z protokołu Centrum MessagePack należy pamiętać o kilku problemach.
Funkcja MessagePack uwzględnia wielkość liter
W protokole MessagePack jest rozróżniana wielkość liter. Rozważmy na przykład następującą klasę języka C#:
public class ChatMessage
{
public string Sender { get; }
public string Message { get; }
}
Podczas wysyłania z klienta JavaScript należy używać PascalCased
nazw właściwości, ponieważ wielkość liter musi być dokładnie zgodna z klasą języka C#. Przykład:
connection.invoke("SomeMethod", { Sender: "Sally", Message: "Hello!" });
Użycie camelCased
nazw nie będzie poprawnie wiązać się z klasą C#. Można to obejść, używając atrybutu Key
, aby określić inną nazwę właściwości MessagePack. Aby uzyskać więcej informacji, zobacz dokumentację MessagePack-CSharp.
Parametr DateTime.Kind nie jest zachowywany podczas serializacji/deserializacji
Protokół MessagePack nie zapewnia sposobu kodowania Kind
wartości elementu DateTime
. W związku z tym w przypadku deserializacji daty protokół MessagePack Hub zakłada, że data przychodząca jest w formacie UTC. Jeśli pracujesz z wartościami DateTime
w czasie lokalnym, zalecamy przekonwertowanie na czas UTC przed ich wysłaniem. Przekonwertuj je z czasu UTC na czas lokalny, gdy je otrzymasz.
Aby uzyskać więcej informacji na temat tego ograniczenia, zobacz Problem z usługą GitHub aspnet/SignalR#2632.
Wartość DateTime.MinValue nie jest obsługiwana przez pakiet MessagePack w języku JavaScript
Biblioteka msgpack5 używana przez klienta JavaScript nie obsługuje typu w elemecie SignalRtimestamp96
MessagePack. Ten typ służy do kodowania bardzo dużych wartości dat (bardzo wcześnie w przeszłości lub bardzo daleko w przyszłości). Wartość to DateTime.MinValue
January 1, 0001
, która musi być zakodowana timestamp96
w wartości. W związku z tym wysyłanie DateTime.MinValue
do klienta JavaScript nie jest obsługiwane. Po DateTime.MinValue
odebraniu przez klienta języka JavaScript zgłaszany jest następujący błąd:
Uncaught Error: unable to find ext type 255 at decoder.js:427
DateTime.MinValue
Zwykle służy do kodowania "brakującej" lub null
wartości. Jeśli chcesz zakodować tą wartość w usłudze MessagePack, użyj wartości dopuszczalnej DateTime
wartości null (DateTime?
) lub zakoduj oddzielną bool
wartość wskazującą, czy data jest obecna.
Aby uzyskać więcej informacji na temat tego ograniczenia, zobacz problem z usługą GitHub aspnet/SignalR#2228.
Obsługa pakietu MessagePack w środowisku kompilacji "przed czasem"
Biblioteka MessagePack-CSharp używana przez klienta i serwer platformy .NET używa generowania kodu do optymalizacji serializacji. W związku z tym nie jest ona domyślnie obsługiwana w środowiskach korzystających z kompilacji "przed czasem" (np. Xamarin iOS lub Unity). W tych środowiskach można użyć pakietu MessagePack przez "wstępne generowanie" kodu serializatora/deserializatora. Aby uzyskać więcej informacji, zobacz dokumentację MessagePack-CSharp. Po wstępnie wygenerowanym serializatorach można je zarejestrować przy użyciu delegata konfiguracji przekazanego do :AddMessagePackProtocol
services.AddSignalR()
.AddMessagePackProtocol(options =>
{
options.FormatterResolvers = new List<MessagePack.IFormatterResolver>()
{
MessagePack.Resolvers.GeneratedResolver.Instance,
MessagePack.Resolvers.StandardResolver.Instance
};
});
Kontrole typów są bardziej rygorystyczne w usłudze MessagePack
JSProtokół ON Hub będzie wykonywać konwersje typów podczas deserializacji. Jeśli na przykład obiekt przychodzący ma wartość właściwości , która jest liczbą ({ foo: 42 }
), ale właściwość klasy .NET jest typu string
, wartość zostanie przekonwertowana. Jednak pakiet MessagePack nie wykonuje tej konwersji i zgłosi wyjątek, który można zobaczyć w dziennikach po stronie serwera (i w konsoli):
InvalidDataException: Error binding arguments. Make sure that the types of the provided values match the types of the hub method being invoked.
Aby uzyskać więcej informacji na temat tego ograniczenia, zobacz problem z usługą GitHub aspnet/SignalR#2937.
Dodatkowe zasoby
W tym artykule założono, że czytelnik jest zaznajomiony z tematami opisanymi w temacie Wprowadzenie do platformy ASP.NET Core SignalR.
Co to jest MessagePack?
MessagePack to szybki i kompaktowy format serializacji binarnej. Jest to przydatne, gdy wydajność i przepustowość są problemem, ponieważ tworzy mniejsze komunikaty w porównaniu z JSwłączonym. Komunikaty binarne są nieczytelne podczas przeglądania śladów sieci i dzienników, chyba że bajty są przekazywane za pośrednictwem analizatora MessagePack. SignalR Ma wbudowaną obsługę formatu MessagePack i udostępnia interfejsy API dla klienta i serwera do użycia.
Konfigurowanie pakietu MessagePack na serwerze
Aby włączyć protokół Centrum MessagePack na serwerze, zainstaluj Microsoft.AspNetCore.SignalR.Protocols.MessagePack
pakiet w aplikacji. W metodzie dodaj AddMessagePackProtocol
metodę Startup.ConfigureServices
do wywołania AddSignalR
, aby włączyć obsługę pakietu MessagePack na serwerze.
Uwaga
JSWłączone jest domyślnie włączone. Dodanie pakietu MessagePack umożliwia obsługę zarówno JSklientów ON, jak i MessagePack.
services.AddSignalR()
.AddMessagePackProtocol();
Aby dostosować sposób formatowania danych przez pakiet MessagePack, AddMessagePackProtocol
przyjmuje delegata do konfigurowania opcji. W tym delegatu FormatterResolvers
właściwość może służyć do konfigurowania opcji serializacji MessagePack. Aby uzyskać więcej informacji na temat sposobu działania funkcji rozpoznawania nazw, odwiedź bibliotekę MessagePack w witrynie MessagePack-CSharp. Atrybuty mogą być używane w obiektach, które chcesz serializować, aby zdefiniować sposób ich obsługi.
services.AddSignalR()
.AddMessagePackProtocol(options =>
{
options.FormatterResolvers = new List<MessagePack.IFormatterResolver>()
{
MessagePack.Resolvers.StandardResolver.Instance
};
});
Ostrzeżenie
Zdecydowanie zalecamy przejrzenie luki CVE-2020-5234 i zastosowanie zalecanych poprawek. Na przykład ustawienie właściwości statycznej MessagePackSecurity.Active
na MessagePackSecurity.UntrustedData
. MessagePackSecurity.Active
Ustawienie elementu wymaga ręcznego zainstalowania wersji 1.9.x pakietu MessagePack. Instalowanie MessagePack
wersji 1.9.x uaktualnia używaną wersję SignalR . Jeśli MessagePackSecurity.Active
wartość nie jest ustawiona na MessagePackSecurity.UntrustedData
, złośliwy klient może spowodować odmowę usługi. Ustaw MessagePackSecurity.Active
w pliku Program.Main
, jak pokazano w poniższym kodzie:
using MessagePack;
public static void Main(string[] args)
{
MessagePackSecurity.Active = MessagePackSecurity.UntrustedData;
CreateHostBuilder(args).Build().Run();
}
Konfigurowanie pakietu MessagePack na kliencie
Uwaga
JSOpcja WŁ. jest domyślnie włączona dla obsługiwanych klientów. Klienci mogą obsługiwać tylko jeden protokół. Dodanie obsługi pakietu MessagePack spowoduje zastąpienie wszystkich wcześniej skonfigurowanych protokołów.
Klient .NET
Aby włączyć pakiet MessagePack w kliencie .NET, zainstaluj Microsoft.AspNetCore.SignalR.Protocols.MessagePack
pakiet i wywołaj polecenie AddMessagePackProtocol
na .HubConnectionBuilder
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.DependencyInjection;
var hubConnection = new HubConnectionBuilder()
.WithUrl("/chathub")
.AddMessagePackProtocol()
.Build();
Uwaga
To AddMessagePackProtocol
wywołanie pobiera delegata do konfigurowania opcji tak jak serwer.
Klient środowiska JavaScript
Obsługa pakietu MessagePack dla klienta JavaScript jest zapewniana przez pakiet npm @aspnet/signalr-protocol-msgpack . Zainstaluj pakiet, wykonując następujące polecenie w powłoce poleceń:
npm install @aspnet/signalr-protocol-msgpack
Po zainstalowaniu pakietu npm moduł może być używany bezpośrednio za pośrednictwem modułu ładującego modułu JavaScript lub zaimportowany do przeglądarki, odwołując się do następującego pliku:
node_modules\@aspnet\signalr-protocol-msgpack\dist\browser\signalr-protocol-msgpack.js
W przeglądarce msgpack5
należy również odwołać się do biblioteki. Użyj tagu <script>
, aby utworzyć odwołanie. Bibliotekę można znaleźć w node_modules\msgpack5\dist\msgpack5.js.
Uwaga
W przypadku korzystania z <script>
elementu kolejność jest ważna. Jeśli signalr-protocol-msgpack.js
wystąpi odwołanie przed msgpack5.js
, podczas próby nawiązania połączenia z pakietem MessagePack wystąpi błąd. signalr.js
jest również wymagany przed 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>
Dodanie .withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
do programu HubConnectionBuilder
spowoduje skonfigurowanie klienta do używania protokołu MessagePack podczas nawiązywania połączenia z serwerem.
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
.build();
Uwaga
Obecnie nie ma opcji konfiguracji protokołu MessagePack na kliencie JavaScript.
Zagadnienia dotyczące pakietu MessagePack
Podczas korzystania z protokołu Centrum MessagePack należy pamiętać o kilku problemach.
Funkcja MessagePack uwzględnia wielkość liter
W protokole MessagePack jest rozróżniana wielkość liter. Rozważmy na przykład następującą klasę języka C#:
public class ChatMessage
{
public string Sender { get; }
public string Message { get; }
}
Podczas wysyłania z klienta JavaScript należy używać PascalCased
nazw właściwości, ponieważ wielkość liter musi być dokładnie zgodna z klasą języka C#. Przykład:
connection.invoke("SomeMethod", { Sender: "Sally", Message: "Hello!" });
Użycie camelCased
nazw nie będzie poprawnie wiązać się z klasą C#. Można to obejść, używając atrybutu Key
, aby określić inną nazwę właściwości MessagePack. Aby uzyskać więcej informacji, zobacz dokumentację MessagePack-CSharp.
Parametr DateTime.Kind nie jest zachowywany podczas serializacji/deserializacji
Protokół MessagePack nie zapewnia sposobu kodowania Kind
wartości elementu DateTime
. W związku z tym w przypadku deserializacji daty protokół MessagePack Hub zakłada, że data przychodząca jest w formacie UTC. Jeśli pracujesz z wartościami DateTime
w czasie lokalnym, zalecamy przekonwertowanie na czas UTC przed ich wysłaniem. Przekonwertuj je z czasu UTC na czas lokalny, gdy je otrzymasz.
Aby uzyskać więcej informacji na temat tego ograniczenia, zobacz Problem z usługą GitHub aspnet/SignalR#2632.
Wartość DateTime.MinValue nie jest obsługiwana przez pakiet MessagePack w języku JavaScript
Biblioteka msgpack5 używana przez klienta JavaScript nie obsługuje typu w elemecie SignalRtimestamp96
MessagePack. Ten typ służy do kodowania bardzo dużych wartości dat (bardzo wcześnie w przeszłości lub bardzo daleko w przyszłości). Wartość DateTime.MinValue
elementu musi January 1, 0001
być zakodowana timestamp96
w wartości. W związku z tym wysyłanie DateTime.MinValue
do klienta JavaScript nie jest obsługiwane. Po DateTime.MinValue
odebraniu przez klienta języka JavaScript zgłaszany jest następujący błąd:
Uncaught Error: unable to find ext type 255 at decoder.js:427
DateTime.MinValue
Zwykle służy do kodowania "brakującej" lub null
wartości. Jeśli chcesz zakodować tą wartość w usłudze MessagePack, użyj wartości dopuszczalnej DateTime
wartości null (DateTime?
) lub zakoduj oddzielną bool
wartość wskazującą, czy data jest obecna.
Aby uzyskać więcej informacji na temat tego ograniczenia, zobacz problem z usługą GitHub aspnet/SignalR#2228.
Obsługa pakietu MessagePack w środowisku kompilacji "przed czasem"
Biblioteka MessagePack-CSharp używana przez klienta i serwer platformy .NET używa generowania kodu do optymalizacji serializacji. W związku z tym nie jest ona domyślnie obsługiwana w środowiskach korzystających z kompilacji "przed czasem" (np. Xamarin iOS lub Unity). W tych środowiskach można użyć pakietu MessagePack przez "wstępne generowanie" kodu serializatora/deserializatora. Aby uzyskać więcej informacji, zobacz dokumentację MessagePack-CSharp. Po wstępnie wygenerowanym serializatorach można je zarejestrować przy użyciu delegata konfiguracji przekazanego do :AddMessagePackProtocol
services.AddSignalR()
.AddMessagePackProtocol(options =>
{
options.FormatterResolvers = new List<MessagePack.IFormatterResolver>()
{
MessagePack.Resolvers.GeneratedResolver.Instance,
MessagePack.Resolvers.StandardResolver.Instance
};
});
Kontrole typów są bardziej rygorystyczne w usłudze MessagePack
JSProtokół ON Hub będzie wykonywać konwersje typów podczas deserializacji. Jeśli na przykład obiekt przychodzący ma wartość właściwości , która jest liczbą ({ foo: 42 }
), ale właściwość klasy .NET jest typu string
, wartość zostanie przekonwertowana. Jednak pakiet MessagePack nie wykonuje tej konwersji i zgłosi wyjątek, który można zobaczyć w dziennikach po stronie serwera (i w konsoli):
InvalidDataException: Error binding arguments. Make sure that the types of the provided values match the types of the hub method being invoked.
Aby uzyskać więcej informacji na temat tego ograniczenia, zobacz problem z usługą GitHub aspnet/SignalR#2937.