Použití protokolu Centra MessagePack pro SignalR ASP.NET Core

Tento článek předpokládá, že čtenář je obeznámen s tématy popsanými v tématu Začínáme s ASP.NET Core SignalR.

Co je MessagePack?

MessagePack je rychlý a kompaktní binární serializační formát. Je užitečné, když se jedná o výkon a šířku pásma, protože vytváří menší zprávy než JSON. Binární zprávy jsou při pohledu na trasování sítě a protokoly nečitelné, pokud nejsou bajty předány prostřednictvím analyzátoru MessagePack. SignalR má integrovanou podporu pro formát MessagePack a poskytuje rozhraní API pro použití klienta a serveru.

Konfigurace balíčku MessagePack na serveru

Pokud chcete na serveru povolit protokol MessagePack Hub, nainstalujte Microsoft.AspNetCore.SignalR.Protocols.MessagePack balíček do aplikace. Startup.ConfigureServices V metodě přidejte AddMessagePackProtocol do AddSignalR volání povolení podpory MessagePack na serveru.

services.AddSignalR()
    .AddMessagePackProtocol();

Poznámka:

Json je ve výchozím nastavení povolený. Přidání MessagePacku umožňuje podporu pro klienty JSON i MessagePack.

Pokud chcete přizpůsobit, jak MessagePack formátuje data, AddMessagePackProtocol přebírá delegáta pro konfiguraci možností. V daném delegátu se SerializerOptions vlastnost používá ke konfiguraci možností serializace MessagePack. Další informace o tom, jak překladače fungují, naleznete v knihovně MessagePack na MessagePack-CSharp. Atributy lze použít u objektů, které chcete serializovat, a definovat, jak mají být zpracovány.

services.AddSignalR()
    .AddMessagePackProtocol(options =>
    {
        options.SerializerOptions = MessagePackSerializerOptions.Standard
            .WithResolver(new CustomResolver())
            .WithSecurity(MessagePackSecurity.UntrustedData);
    });

Upozorňující

Důrazně doporučujeme zkontrolovat CVE-2020-5234 a použít doporučené opravy. Například volání .WithSecurity(MessagePackSecurity.UntrustedData) při nahrazení .SerializerOptions

Konfigurace balíčku MessagePack v klientovi

Poznámka:

Pro podporované klienty je ve výchozím nastavení povolený JSON. Klienti můžou podporovat pouze jeden protokol. Přidání podpory MessagePacku nahrazuje všechny dříve nakonfigurované protokoly.

Klient .NET

Chcete-li povolit MessagePack v klientovi .NET, nainstalujte Microsoft.AspNetCore.SignalR.Protocols.MessagePack balíček a volání AddMessagePackProtocol .HubConnectionBuilder

using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.DependencyInjection;

var hubConnection = new HubConnectionBuilder()
                        .WithUrl("/chathub")
                        .AddMessagePackProtocol()
                        .Build();

Poznámka:

Toto AddMessagePackProtocol volání přebírá delegáta pro konfiguraci možností stejně jako server.

Javascriptový klient

Podpora MessagePacku pro klienta JavaScriptu je poskytována balíčkem npm @microsoft/signalr-protocol-msgpack npm. Nainstalujte balíček spuštěním následujícího příkazu v příkazovém prostředí:

npm install @microsoft/signalr-protocol-msgpack

Po instalaci balíčku npm je možné modul použít přímo přes zavaděč modulu JavaScript nebo importovat do prohlížeče odkazováním na následující soubor:

node_modules\@microsoft\signalr-protocol-msgpack\dist\browser\signalr-protocol-msgpack.js

Následující požadované soubory javaScriptu musí být odkazovány v uvedeném pořadí:

<script src="~/lib/signalr/signalr.js"></script>
<script src="~/lib/signalr/signalr-protocol-msgpack.js"></script>

Přidání .withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol()) do HubConnectionBuilder konfigurace klienta pro použití protokolu MessagePack při připojování k serveru.

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/chathub")
    .withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
    .build();

V tuto chvíli neexistují žádné možnosti konfigurace protokolu MessagePack v javascriptovém klientovi.

Java klient

Pokud chcete povolit MessagePack s Javou com.microsoft.signalr.messagepack , nainstalujte balíček. Pokud používáte Gradle, přidejte do dependencies oddílu souboru build.gradle následující řádek:

implementation 'com.microsoft.signalr.messagepack:signalr-messagepack:5.0.0'

Při použití Mavenu přidejte do elementu pom.xml souboru následující řádky<dependencies>:

<dependency>
    <groupId>com.microsoft.signalr.messagepack</groupId>
    <artifactId>signalr</artifactId>
    <version>5.0.0</version>
</dependency>

Zavolejte withHubProtocol(new MessagePackHubProtocol()) .HubConnectionBuilder

HubConnection messagePackConnection = HubConnectionBuilder.create("YOUR HUB URL HERE")
    .withHubProtocol(new MessagePackHubProtocol())
    .build();

Důležité informace o balíčku MessagePack

Při použití protokolu MessagePack Hub je potřeba mít na paměti několik problémů.

MessagePack rozlišují malá a velká písmena.

V protokolu MessagePack se rozlišují malá a velká písmena. Představte si například následující třídu jazyka C#:

public class ChatMessage
{
    public string Sender { get; }
    public string Message { get; }
}

Při odesílání z klienta JavaScriptu musíte použít PascalCased názvy vlastností, protože velikost písmen musí přesně odpovídat třídě jazyka C#. Příklad:

connection.invoke("SomeMethod", { Sender: "Sally", Message: "Hello!" });

Použití camelCased názvů nebude správně svázané s třídou jazyka C#. Tento problém můžete obejít pomocí atributu Key , který určuje jiný název vlastnosti MessagePack. Další informace najdete v dokumentaci MessagePack-CSharp.

DateTime.Kind se nezachová při serializaci/deserializaci

Protokol MessagePack neposkytuje způsob kódování Kind hodnoty DateTime. V důsledku toho se při deserializaci data protokol Centra MessagePack převede na formát UTC, pokud DateTime.Kind je DateTimeKind.Local jinak nedotkne času a předá ho tak, jak je. Pokud pracujete s DateTime hodnotami, doporučujeme před jejich odesláním převést na UTC. Převeďte je z UTC na místní čas, když je obdržíte.

Podpora MessagePacku v prostředí kompilace s předstihem

Knihovna MessagePack-CSharp používaná klientem a serverem .NET používá generování kódu k optimalizaci serializace. V důsledku toho se ve výchozím nastavení nepodporuje v prostředích, která používají kompilaci s předstihem (například Xamarin iOS nebo Unity). MessagePack je možné v těchto prostředích použít "předgenerováním" serializátoru/deserializátoru. Další informace najdete v dokumentaci MessagePack-CSharp. Jakmile serializátory předem vygenerujete, můžete je zaregistrovat pomocí delegáta konfigurace předaného 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);
    });

Kontroly typů jsou v balíčku MessagePack přísnější.

Protokol CENTRA JSON provede převody typů během deserializace. Pokud například příchozí objekt má hodnotu vlastnosti, která je číslo ({ foo: 42 }), ale vlastnost třídy .NET je typu string, hodnota bude převedena. MessagePack však tento převod neprovádí a vyvolá výjimku, která se dá zobrazit v protokolech na straně serveru (a v konzole):

InvalidDataException: Error binding arguments. Make sure that the types of the provided values match the types of the hub method being invoked.

Další informace o tomto omezení najdete v tématu Problém s GitHubem aspnet/SignalR#2937.

Znaky a řetězce v Javě

V klientovi char Java budou objekty serializovány jako objekty s jedním znakem String . To je na rozdíl od klienta C# a JavaScriptu, který je serializuje jako short objekty. Samotná specifikace MessagePack nedefinuje chování pro char objekty, takže je na autor knihovny, aby určil, jak je serializovat. Rozdíl v chování mezi našimi klienty je výsledkem knihoven, které jsme použili pro naše implementace.

Další materiály

Tento článek předpokládá, že čtenář je obeznámen s tématy popsanými v tématu Začínáme s ASP.NET Core SignalR.

Co je MessagePack?

MessagePack je rychlý a kompaktní binární serializační formát. Je užitečné, když je výkon a šířka pásma problém, protože ve srovnání s JSON vytváří menší zprávy. Binární zprávy jsou při pohledu na trasování sítě a protokoly nečitelné, pokud nejsou bajty předány prostřednictvím analyzátoru MessagePack. SignalR má integrovanou podporu pro formát MessagePack a poskytuje rozhraní API pro použití klienta a serveru.

Konfigurace balíčku MessagePack na serveru

Pokud chcete na serveru povolit protokol MessagePack Hub, nainstalujte Microsoft.AspNetCore.SignalR.Protocols.MessagePack balíček do aplikace. Startup.ConfigureServices V metodě přidejte AddMessagePackProtocol do AddSignalR volání povolení podpory MessagePack na serveru.

Poznámka:

Json je ve výchozím nastavení povolený. Přidání MessagePacku umožňuje podporu pro klienty JSON i MessagePack.

services.AddSignalR()
    .AddMessagePackProtocol();

Pokud chcete přizpůsobit, jak bude MessagePack formátovat vaše data, AddMessagePackProtocol vezme delegáta pro konfiguraci možností. V daném delegátu SerializerOptions lze vlastnost použít ke konfiguraci možností serializace MessagePack. Další informace o tom, jak překladače fungují, naleznete v knihovně MessagePack na MessagePack-CSharp. Atributy lze použít u objektů, které chcete serializovat, a definovat, jak mají být zpracovány.

services.AddSignalR()
    .AddMessagePackProtocol(options =>
    {
        options.SerializerOptions = MessagePackSerializerOptions.Standard
            .WithResolver(new CustomResolver())
            .WithSecurity(MessagePackSecurity.UntrustedData);
    });

Upozorňující

Důrazně doporučujeme zkontrolovat CVE-2020-5234 a použít doporučené opravy. Například volání .WithSecurity(MessagePackSecurity.UntrustedData) při nahrazení .SerializerOptions

Konfigurace balíčku MessagePack v klientovi

Poznámka:

Pro podporované klienty je ve výchozím nastavení povolený JSON. Klienti můžou podporovat pouze jeden protokol. Přidání podpory MessagePacku nahradí všechny dříve nakonfigurované protokoly.

Klient .NET

Chcete-li povolit MessagePack v klientovi .NET, nainstalujte Microsoft.AspNetCore.SignalR.Protocols.MessagePack balíček a volání AddMessagePackProtocol .HubConnectionBuilder

using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.DependencyInjection;

var hubConnection = new HubConnectionBuilder()
                        .WithUrl("/chathub")
                        .AddMessagePackProtocol()
                        .Build();

Poznámka:

Toto AddMessagePackProtocol volání přebírá delegáta pro konfiguraci možností stejně jako server.

Javascriptový klient

Podpora MessagePacku pro klienta JavaScriptu je poskytována balíčkem npm @microsoft/signalr-protocol-msgpack npm. Nainstalujte balíček spuštěním následujícího příkazu v příkazovém prostředí:

npm install @microsoft/signalr-protocol-msgpack

Po instalaci balíčku npm je možné modul použít přímo přes zavaděč modulu JavaScript nebo importovat do prohlížeče odkazováním na následující soubor:

node_modules\@microsoft\signalr-protocol-msgpack\dist\browser\signalr-protocol-msgpack.js

V prohlížeči se na knihovnu msgpack5 musí odkazovat také. <script> K vytvoření odkazu použijte značku. Knihovnu najdete na adrese node_modules\msgpack5\dist\msgpack5.js.

Poznámka:

Při použití elementu <script> je pořadí důležité. Pokud signalr-protocol-msgpack.js se odkazuje dříve msgpack5.js, při pokusu o připojení pomocí MessagePacku dojde k chybě. signalr.js je rovněž vyžadována před 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>

Přidání .withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol()) do HubConnectionBuilder konfigurace klienta pro použití protokolu MessagePack při připojování k serveru.

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/chathub")
    .withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
    .build();

Poznámka:

V tuto chvíli neexistují žádné možnosti konfigurace protokolu MessagePack v javascriptovém klientovi.

Java klient

Pokud chcete povolit MessagePack s Javou com.microsoft.signalr.messagepack , nainstalujte balíček. Pokud používáte Gradle, přidejte do dependencies oddílu souboru build.gradle následující řádek:

implementation 'com.microsoft.signalr.messagepack:signalr-messagepack:5.0.0'

Při použití Mavenu přidejte do elementu pom.xml souboru následující řádky<dependencies>:

<dependency>
    <groupId>com.microsoft.signalr.messagepack</groupId>
    <artifactId>signalr</artifactId>
    <version>5.0.0</version>
</dependency>

Zavolejte withHubProtocol(new MessagePackHubProtocol()) .HubConnectionBuilder

HubConnection messagePackConnection = HubConnectionBuilder.create("YOUR HUB URL HERE")
    .withHubProtocol(new MessagePackHubProtocol())
    .build();

Důležité informace o balíčku MessagePack

Při použití protokolu MessagePack Hub je potřeba mít na paměti několik problémů.

MessagePack rozlišují malá a velká písmena.

V protokolu MessagePack se rozlišují malá a velká písmena. Představte si například následující třídu jazyka C#:

public class ChatMessage
{
    public string Sender { get; }
    public string Message { get; }
}

Při odesílání z klienta JavaScriptu musíte použít PascalCased názvy vlastností, protože velikost písmen musí přesně odpovídat třídě jazyka C#. Příklad:

connection.invoke("SomeMethod", { Sender: "Sally", Message: "Hello!" });

Použití camelCased názvů nebude správně svázané s třídou jazyka C#. Tento problém můžete obejít pomocí atributu Key , který určuje jiný název vlastnosti MessagePack. Další informace najdete v dokumentaci MessagePack-CSharp.

DateTime.Kind se nezachová při serializaci/deserializaci

Protokol MessagePack neposkytuje způsob kódování Kind hodnoty DateTime. V důsledku toho se při deserializaci data protokol Centra MessagePack převede na formát UTC, pokud DateTime.Kind je DateTimeKind.Local jinak nedotkne času a předá ho tak, jak je. Pokud pracujete s DateTime hodnotami, doporučujeme před jejich odesláním převést na UTC. Převeďte je z UTC na místní čas, když je obdržíte.

MessagePack v JavaScriptu nepodporuje DateTime.MinValue

Knihovna msgpack5 používaná klientem SignalR JavaScriptu nepodporuje timestamp96 typ v MessagePacku. Tento typ se používá ke kódování velmi velkých hodnot kalendářních dat (buď velmi brzy v minulosti, nebo velmi daleko v budoucnu). Hodnota DateTime.MinValue je January 1, 0001, která musí být kódována v hodnotě timestamp96 . Z tohoto důvodu se odesílání DateTime.MinValue do javascriptového klienta nepodporuje. Při DateTime.MinValue přijetí javascriptovým klientem se vyvolá následující chyba:

Uncaught Error: unable to find ext type 255 at decoder.js:427

DateTime.MinValue Obvykle se používá ke kódování "chybějící" nebo null hodnoty. Pokud potřebujete tuto hodnotu zakódovat v balíčku MessagePack, použijte hodnotu nullable DateTime (DateTime?) nebo zakódujte samostatnou bool hodnotu označující, jestli je datum k dispozici.

Další informace o tomto omezení najdete v tématu Problém s GitHubem aspnet/SignalR#2228.

Podpora MessagePacku v prostředí kompilace s předstihem

Knihovna MessagePack-CSharp používaná klientem a serverem .NET používá generování kódu k optimalizaci serializace. V důsledku toho se ve výchozím nastavení nepodporuje v prostředích, která používají kompilaci s předstihem (například Xamarin iOS nebo Unity). MessagePack je možné v těchto prostředích použít "předgenerováním" serializátoru/deserializátoru. Další informace najdete v dokumentaci MessagePack-CSharp. Jakmile serializátory předem vygenerujete, můžete je zaregistrovat pomocí delegáta konfigurace předaného 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);
    });

Kontroly typů jsou v balíčku MessagePack přísnější.

Protokol CENTRA JSON provede převody typů během deserializace. Pokud například příchozí objekt má hodnotu vlastnosti, která je číslo ({ foo: 42 }), ale vlastnost třídy .NET je typu string, hodnota bude převedena. MessagePack však tento převod neprovádí a vyvolá výjimku, která se dá zobrazit v protokolech na straně serveru (a v konzole):

InvalidDataException: Error binding arguments. Make sure that the types of the provided values match the types of the hub method being invoked.

Další informace o tomto omezení najdete v tématu Problém s GitHubem aspnet/SignalR#2937.

Znaky a řetězce v Javě

V klientovi char Java budou objekty serializovány jako objekty s jedním znakem String . To je na rozdíl od klienta C# a JavaScriptu, který je serializuje jako short objekty. Samotná specifikace MessagePack nedefinuje chování pro char objekty, takže je na autor knihovny, aby určil, jak je serializovat. Rozdíl v chování mezi našimi klienty je výsledkem knihoven, které jsme použili pro naše implementace.

Další materiály

Tento článek předpokládá, že čtenář je obeznámen s tématy popsanými v tématu Začínáme s ASP.NET Core SignalR.

Co je MessagePack?

MessagePack je rychlý a kompaktní binární serializační formát. Je užitečné, když je výkon a šířka pásma problém, protože ve srovnání s JSON vytváří menší zprávy. Binární zprávy jsou při pohledu na trasování sítě a protokoly nečitelné, pokud nejsou bajty předány prostřednictvím analyzátoru MessagePack. SignalR má integrovanou podporu pro formát MessagePack a poskytuje rozhraní API pro použití klienta a serveru.

Konfigurace balíčku MessagePack na serveru

Pokud chcete na serveru povolit protokol MessagePack Hub, nainstalujte Microsoft.AspNetCore.SignalR.Protocols.MessagePack balíček do aplikace. Startup.ConfigureServices V metodě přidejte AddMessagePackProtocol do AddSignalR volání povolení podpory MessagePack na serveru.

Poznámka:

Json je ve výchozím nastavení povolený. Přidání MessagePacku umožňuje podporu pro klienty JSON i MessagePack.

services.AddSignalR()
    .AddMessagePackProtocol();

Pokud chcete přizpůsobit, jak bude MessagePack formátovat vaše data, AddMessagePackProtocol vezme delegáta pro konfiguraci možností. V daném delegátu FormatterResolvers lze vlastnost použít ke konfiguraci možností serializace MessagePack. Další informace o tom, jak překladače fungují, naleznete v knihovně MessagePack na MessagePack-CSharp. Atributy lze použít u objektů, které chcete serializovat, a definovat, jak mají být zpracovány.

services.AddSignalR()
    .AddMessagePackProtocol(options =>
    {
        options.FormatterResolvers = new List<MessagePack.IFormatterResolver>()
        {
            MessagePack.Resolvers.StandardResolver.Instance
        };
    });

Upozorňující

Důrazně doporučujeme zkontrolovat CVE-2020-5234 a použít doporučené opravy. Můžete například nastavit statickou MessagePackSecurity.Active vlastnost na MessagePackSecurity.UntrustedDatahodnotu . MessagePackSecurity.Active Nastavení vyžaduje ruční instalaci verze MessagePack 1.9.x. Instalace MessagePack verze 1.9.x upgraduje SignalR verzi. MessagePack verze 2.x zavedla zásadní změny a není kompatibilní s verzemi SignalR 3.1 a staršími. Pokud MessagePackSecurity.Active není nastavená hodnota MessagePackSecurity.UntrustedData, může škodlivý klient způsobit odepření služby. Nastavit MessagePackSecurity.Active v Program.Main, jak je znázorněno v následujícím kódu:

using MessagePack;

public static void Main(string[] args)
{
  MessagePackSecurity.Active = MessagePackSecurity.UntrustedData;

  CreateHostBuilder(args).Build().Run();
}

Konfigurace balíčku MessagePack v klientovi

Poznámka:

Pro podporované klienty je ve výchozím nastavení povolený JSON. Klienti můžou podporovat pouze jeden protokol. Přidání podpory MessagePacku nahradí všechny dříve nakonfigurované protokoly.

Klient .NET

Chcete-li povolit MessagePack v klientovi .NET, nainstalujte Microsoft.AspNetCore.SignalR.Protocols.MessagePack balíček a volání AddMessagePackProtocol .HubConnectionBuilder

using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.DependencyInjection;

var hubConnection = new HubConnectionBuilder()
                        .WithUrl("/chathub")
                        .AddMessagePackProtocol()
                        .Build();

Poznámka:

Toto AddMessagePackProtocol volání přebírá delegáta pro konfiguraci možností stejně jako server.

Javascriptový klient

Podpora MessagePacku pro klienta JavaScriptu je poskytována balíčkem npm @microsoft/signalr-protocol-msgpack npm. Nainstalujte balíček spuštěním následujícího příkazu v příkazovém prostředí:

npm install @microsoft/signalr-protocol-msgpack

Po instalaci balíčku npm je možné modul použít přímo přes zavaděč modulu JavaScript nebo importovat do prohlížeče odkazováním na následující soubor:

node_modules\@microsoft\signalr-protocol-msgpack\dist\browser\signalr-protocol-msgpack.js

V prohlížeči se na knihovnu msgpack5 musí odkazovat také. <script> K vytvoření odkazu použijte značku. Knihovnu najdete na adrese node_modules\msgpack5\dist\msgpack5.js.

Poznámka:

Při použití elementu <script> je pořadí důležité. Pokud signalr-protocol-msgpack.js se odkazuje dříve msgpack5.js, při pokusu o připojení pomocí MessagePacku dojde k chybě. signalr.js je rovněž vyžadována před 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>

Přidání .withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol()) do HubConnectionBuilder konfigurace klienta pro použití protokolu MessagePack při připojování k serveru.

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/chathub")
    .withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
    .build();

Poznámka:

V tuto chvíli neexistují žádné možnosti konfigurace protokolu MessagePack v javascriptovém klientovi.

Důležité informace o balíčku MessagePack

Při použití protokolu MessagePack Hub je potřeba mít na paměti několik problémů.

MessagePack rozlišují malá a velká písmena.

V protokolu MessagePack se rozlišují malá a velká písmena. Představte si například následující třídu jazyka C#:

public class ChatMessage
{
    public string Sender { get; }
    public string Message { get; }
}

Při odesílání z klienta JavaScriptu musíte použít PascalCased názvy vlastností, protože velikost písmen musí přesně odpovídat třídě jazyka C#. Příklad:

connection.invoke("SomeMethod", { Sender: "Sally", Message: "Hello!" });

Použití camelCased názvů nebude správně svázané s třídou jazyka C#. Tento problém můžete obejít pomocí atributu Key , který určuje jiný název vlastnosti MessagePack. Další informace najdete v dokumentaci MessagePack-CSharp.

DateTime.Kind se nezachová při serializaci/deserializaci

Protokol MessagePack neposkytuje způsob kódování Kind hodnoty DateTime. V důsledku toho při deserializaci data protokol centra MessagePack předpokládá, že příchozí datum je ve formátu UTC. Pokud pracujete s DateTime hodnotami v místním čase, doporučujeme před jejich odesláním převést na UTC. Převeďte je z UTC na místní čas, když je obdržíte.

Další informace o tomto omezení najdete v tématu Problém s GitHubem aspnet/SignalR#2632.

MessagePack v JavaScriptu nepodporuje DateTime.MinValue

Knihovna msgpack5 používaná klientem SignalR JavaScriptu nepodporuje timestamp96 typ v MessagePacku. Tento typ se používá ke kódování velmi velkých hodnot kalendářních dat (buď velmi brzy v minulosti, nebo velmi daleko v budoucnu). Hodnota DateTime.MinValue je January 1, 0001, která musí být kódována v hodnotě timestamp96 . Z tohoto důvodu se odesílání DateTime.MinValue do javascriptového klienta nepodporuje. Při DateTime.MinValue přijetí javascriptovým klientem se vyvolá následující chyba:

Uncaught Error: unable to find ext type 255 at decoder.js:427

DateTime.MinValue Obvykle se používá ke kódování "chybějící" nebo null hodnoty. Pokud potřebujete tuto hodnotu zakódovat v balíčku MessagePack, použijte hodnotu nullable DateTime (DateTime?) nebo zakódujte samostatnou bool hodnotu označující, jestli je datum k dispozici.

Další informace o tomto omezení najdete v tématu Problém s GitHubem aspnet/SignalR#2228.

Podpora MessagePacku v prostředí kompilace s předstihem

Knihovna MessagePack-CSharp používaná klientem a serverem .NET používá generování kódu k optimalizaci serializace. V důsledku toho se ve výchozím nastavení nepodporuje v prostředích, která používají kompilaci s předstihem (například Xamarin iOS nebo Unity). MessagePack je možné v těchto prostředích použít "předgenerováním" serializátoru/deserializátoru. Další informace najdete v dokumentaci MessagePack-CSharp. Jakmile serializátory předem vygenerujete, můžete je zaregistrovat pomocí delegáta konfigurace předaného do AddMessagePackProtocol:

services.AddSignalR()
    .AddMessagePackProtocol(options =>
    {
        options.FormatterResolvers = new List<MessagePack.IFormatterResolver>()
        {
            MessagePack.Resolvers.GeneratedResolver.Instance,
            MessagePack.Resolvers.StandardResolver.Instance
        };
    });

Kontroly typů jsou v balíčku MessagePack přísnější.

Protokol CENTRA JSON provede převody typů během deserializace. Pokud například příchozí objekt má hodnotu vlastnosti, která je číslo ({ foo: 42 }), ale vlastnost třídy .NET je typu string, hodnota bude převedena. MessagePack však tento převod neprovádí a vyvolá výjimku, která se dá zobrazit v protokolech na straně serveru (a v konzole):

InvalidDataException: Error binding arguments. Make sure that the types of the provided values match the types of the hub method being invoked.

Další informace o tomto omezení najdete v tématu Problém s GitHubem aspnet/SignalR#2937.

Další materiály

Tento článek předpokládá, že čtenář je obeznámen s tématy popsanými v tématu Začínáme s ASP.NET Core SignalR.

Co je MessagePack?

MessagePack je rychlý a kompaktní binární serializační formát. Je užitečné, když je výkon a šířka pásma problém, protože ve srovnání s JSON vytváří menší zprávy. Binární zprávy jsou při pohledu na trasování sítě a protokoly nečitelné, pokud nejsou bajty předány prostřednictvím analyzátoru MessagePack. SignalR má integrovanou podporu pro formát MessagePack a poskytuje rozhraní API pro použití klienta a serveru.

Konfigurace balíčku MessagePack na serveru

Pokud chcete na serveru povolit protokol MessagePack Hub, nainstalujte Microsoft.AspNetCore.SignalR.Protocols.MessagePack balíček do aplikace. Startup.ConfigureServices V metodě přidejte AddMessagePackProtocol do AddSignalR volání povolení podpory MessagePack na serveru.

Poznámka:

Json je ve výchozím nastavení povolený. Přidání MessagePacku umožňuje podporu pro klienty JSON i MessagePack.

services.AddSignalR()
    .AddMessagePackProtocol();

Pokud chcete přizpůsobit, jak bude MessagePack formátovat vaše data, AddMessagePackProtocol vezme delegáta pro konfiguraci možností. V daném delegátu FormatterResolvers lze vlastnost použít ke konfiguraci možností serializace MessagePack. Další informace o tom, jak překladače fungují, naleznete v knihovně MessagePack na MessagePack-CSharp. Atributy lze použít u objektů, které chcete serializovat, a definovat, jak mají být zpracovány.

services.AddSignalR()
    .AddMessagePackProtocol(options =>
    {
        options.FormatterResolvers = new List<MessagePack.IFormatterResolver>()
        {
            MessagePack.Resolvers.StandardResolver.Instance
        };
    });

Upozorňující

Důrazně doporučujeme zkontrolovat CVE-2020-5234 a použít doporučené opravy. Můžete například nastavit statickou MessagePackSecurity.Active vlastnost na MessagePackSecurity.UntrustedDatahodnotu . MessagePackSecurity.Active Nastavení vyžaduje ruční instalaci verze MessagePack 1.9.x. Instalace MessagePack verze 1.9.x upgraduje SignalR verzi. Pokud MessagePackSecurity.Active není nastavená hodnota MessagePackSecurity.UntrustedData, může škodlivý klient způsobit odepření služby. Nastavit MessagePackSecurity.Active v Program.Main, jak je znázorněno v následujícím kódu:

using MessagePack;

public static void Main(string[] args)
{
  MessagePackSecurity.Active = MessagePackSecurity.UntrustedData;

  CreateHostBuilder(args).Build().Run();
}

Konfigurace balíčku MessagePack v klientovi

Poznámka:

Pro podporované klienty je ve výchozím nastavení povolený JSON. Klienti můžou podporovat pouze jeden protokol. Přidání podpory MessagePacku nahradí všechny dříve nakonfigurované protokoly.

Klient .NET

Chcete-li povolit MessagePack v klientovi .NET, nainstalujte Microsoft.AspNetCore.SignalR.Protocols.MessagePack balíček a volání AddMessagePackProtocol .HubConnectionBuilder

using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.DependencyInjection;

var hubConnection = new HubConnectionBuilder()
                        .WithUrl("/chathub")
                        .AddMessagePackProtocol()
                        .Build();

Poznámka:

Toto AddMessagePackProtocol volání přebírá delegáta pro konfiguraci možností stejně jako server.

Javascriptový klient

Podpora MessagePacku pro klienta JavaScriptu je poskytována balíčkem npm @aspnet/signalr-protocol-msgpack npm. Nainstalujte balíček spuštěním následujícího příkazu v příkazovém prostředí:

npm install @aspnet/signalr-protocol-msgpack

Po instalaci balíčku npm je možné modul použít přímo přes zavaděč modulu JavaScript nebo importovat do prohlížeče odkazováním na následující soubor:

node_modules\@aspnet\signalr-protocol-msgpack\dist\browser\signalr-protocol-msgpack.js

V prohlížeči se na knihovnu msgpack5 musí odkazovat také. <script> K vytvoření odkazu použijte značku. Knihovnu najdete na adrese node_modules\msgpack5\dist\msgpack5.js.

Poznámka:

Při použití elementu <script> je pořadí důležité. Pokud signalr-protocol-msgpack.js se odkazuje dříve msgpack5.js, při pokusu o připojení pomocí MessagePacku dojde k chybě. signalr.js je rovněž vyžadována před 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>

Přidání .withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol()) do HubConnectionBuilder konfigurace klienta pro použití protokolu MessagePack při připojování k serveru.

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/chathub")
    .withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
    .build();

Poznámka:

V tuto chvíli neexistují žádné možnosti konfigurace protokolu MessagePack v javascriptovém klientovi.

Důležité informace o balíčku MessagePack

Při použití protokolu MessagePack Hub je potřeba mít na paměti několik problémů.

MessagePack rozlišují malá a velká písmena.

V protokolu MessagePack se rozlišují malá a velká písmena. Představte si například následující třídu jazyka C#:

public class ChatMessage
{
    public string Sender { get; }
    public string Message { get; }
}

Při odesílání z klienta JavaScriptu musíte použít PascalCased názvy vlastností, protože velikost písmen musí přesně odpovídat třídě jazyka C#. Příklad:

connection.invoke("SomeMethod", { Sender: "Sally", Message: "Hello!" });

Použití camelCased názvů nebude správně svázané s třídou jazyka C#. Tento problém můžete obejít pomocí atributu Key , který určuje jiný název vlastnosti MessagePack. Další informace najdete v dokumentaci MessagePack-CSharp.

DateTime.Kind se nezachová při serializaci/deserializaci

Protokol MessagePack neposkytuje způsob kódování Kind hodnoty DateTime. V důsledku toho při deserializaci data protokol centra MessagePack předpokládá, že příchozí datum je ve formátu UTC. Pokud pracujete s DateTime hodnotami v místním čase, doporučujeme před jejich odesláním převést na UTC. Převeďte je z UTC na místní čas, když je obdržíte.

Další informace o tomto omezení najdete v tématu Problém s GitHubem aspnet/SignalR#2632.

MessagePack v JavaScriptu nepodporuje DateTime.MinValue

Knihovna msgpack5 používaná klientem SignalR JavaScriptu nepodporuje timestamp96 typ v MessagePacku. Tento typ se používá ke kódování velmi velkých hodnot kalendářních dat (buď velmi brzy v minulosti, nebo velmi daleko v budoucnu). Hodnota, January 1, 0001 která DateTime.MinValue musí být zakódována v hodnotětimestamp96. Z tohoto důvodu se odesílání DateTime.MinValue do javascriptového klienta nepodporuje. Při DateTime.MinValue přijetí javascriptovým klientem se vyvolá následující chyba:

Uncaught Error: unable to find ext type 255 at decoder.js:427

DateTime.MinValue Obvykle se používá ke kódování "chybějící" nebo null hodnoty. Pokud potřebujete tuto hodnotu zakódovat v balíčku MessagePack, použijte hodnotu nullable DateTime (DateTime?) nebo zakódujte samostatnou bool hodnotu označující, jestli je datum k dispozici.

Další informace o tomto omezení najdete v tématu Problém s GitHubem aspnet/SignalR#2228.

Podpora MessagePacku v prostředí kompilace s předstihem

Knihovna MessagePack-CSharp používaná klientem a serverem .NET používá generování kódu k optimalizaci serializace. V důsledku toho se ve výchozím nastavení nepodporuje v prostředích, která používají kompilaci s předstihem (například Xamarin iOS nebo Unity). MessagePack je možné v těchto prostředích použít "předgenerováním" serializátoru/deserializátoru. Další informace najdete v dokumentaci MessagePack-CSharp. Jakmile serializátory předem vygenerujete, můžete je zaregistrovat pomocí delegáta konfigurace předaného do AddMessagePackProtocol:

services.AddSignalR()
    .AddMessagePackProtocol(options =>
    {
        options.FormatterResolvers = new List<MessagePack.IFormatterResolver>()
        {
            MessagePack.Resolvers.GeneratedResolver.Instance,
            MessagePack.Resolvers.StandardResolver.Instance
        };
    });

Kontroly typů jsou v balíčku MessagePack přísnější.

Protokol CENTRA JSON provede převody typů během deserializace. Pokud například příchozí objekt má hodnotu vlastnosti, která je číslo ({ foo: 42 }), ale vlastnost třídy .NET je typu string, hodnota bude převedena. MessagePack však tento převod neprovádí a vyvolá výjimku, která se dá zobrazit v protokolech na straně serveru (a v konzole):

InvalidDataException: Error binding arguments. Make sure that the types of the provided values match the types of the hub method being invoked.

Další informace o tomto omezení najdete v tématu Problém s GitHubem aspnet/SignalR#2937.

Další materiály