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.MinValueJanuary 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.MinValueJanuary 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.

Dodatkowe zasoby