Använda MessagePack Hub Protocol i SignalR för ASP.NET Core
Den här artikeln förutsätter att läsaren är bekant med de ämnen som beskrivs i Komma igång med ASP.NET Core SignalR.
Vad är MessagePack?
MessagePack är ett snabbt och kompakt binärt serialiseringsformat. Det är användbart när prestanda och bandbredd är ett problem eftersom det skapar mindre meddelanden än JSON-. Binärmeddelandena kan inte läsas när du tittar på nätverksspårningar och loggar om inte byte skickas via en MessagePack-parser. SignalR har inbyggt stöd för MessagePack-formatet och tillhandahåller API:er som klienten och servern kan använda.
Konfigurera MessagePack på servern
Om du vill aktivera MessagePack Hub-protokollet på servern installerar du Microsoft.AspNetCore.SignalR.Protocols.MessagePack
-paketet i din app. I metoden Startup.ConfigureServices
lägger du till AddMessagePackProtocol
i AddSignalR
-anropet för att aktivera MessagePack-stöd på servern.
services.AddSignalR()
.AddMessagePackProtocol();
Obs
JSON är aktiverat som standard. Genom att lägga till MessagePack får du stöd för både JSON- och MessagePack-klienter.
För att anpassa hur MessagePack formaterar data tar AddMessagePackProtocol
en delegering för att konfigurera alternativ. I den delegaten används egenskapen SerializerOptions
för att konfigurera serialiseringsalternativ för MessagePack. För mer information om hur lösare fungerar, besök MessagePack-biblioteket på MessagePack-CSharp. Attribut kan användas på de objekt som du vill serialisera för att definiera hur de ska hanteras.
services.AddSignalR()
.AddMessagePackProtocol(options =>
{
options.SerializerOptions = MessagePackSerializerOptions.Standard
.WithResolver(new CustomResolver())
.WithSecurity(MessagePackSecurity.UntrustedData);
});
Varning
Vi rekommenderar starkt att du granskar CVE-2020-5234 och tillämpar de rekommenderade korrigeringarna. Du kan till exempel anropa .WithSecurity(MessagePackSecurity.UntrustedData)
när du ersätter SerializerOptions
.
Konfigurera MessagePack på klienten
Obs
JSON är aktiverat som standard för klienter som stöds. Klienter kan bara stödja ett enda protokoll. Om du lägger till MessagePack-stöd ersätts alla tidigare konfigurerade protokoll.
.NET-klient
Om du vill aktivera MessagePack i .NET-klienten installerar du Microsoft.AspNetCore.SignalR.Protocols.MessagePack
-paketet och anropar AddMessagePackProtocol
på HubConnectionBuilder
.
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.DependencyInjection;
var hubConnection = new HubConnectionBuilder()
.WithUrl("/chathub")
.AddMessagePackProtocol()
.Build();
Obs
Det här AddMessagePackProtocol
-anropet tar en delegat för att konfigurera alternativen på samma sätt som servern.
JavaScript-klient
MessagePack-stöd för JavaScript-klienten tillhandahålls av @microsoft/signalr-protocol-msgpack npm-paketet. Installera paketet genom att köra följande kommando i ett kommandogränssnitt:
npm install @microsoft/signalr-protocol-msgpack
När du har installerat npm-paketet kan modulen användas direkt via en JavaScript-modulinläsare eller importeras till webbläsaren genom att referera till följande fil:
node_modules\@microsoft\signalr-protocol-msgpack\dist\browser\signalr-protocol-msgpack.js
Följande nödvändiga javaScript-filer måste refereras i den ordning som visas nedan:
<script src="~/lib/signalr/signalr.js"></script>
<script src="~/lib/signalr/signalr-protocol-msgpack.js"></script>
Genom att lägga till .withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
i HubConnectionBuilder
konfigureras klienten att använda MessagePack-protokollet vid anslutning till en server.
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
.build();
För närvarande finns det inga konfigurationsalternativ för MessagePack-protokollet på JavaScript-klienten.
Java-klient
Om du vill aktivera MessagePack med Java installerar du com.microsoft.signalr.messagepack
-paketet. När du använder Gradle lägger du till följande rad i avsnittet dependencies
i filen build.gradle:
implementation 'com.microsoft.signalr.messagepack:signalr-messagepack:5.0.0'
När du använder Maven lägger du till följande rader i <dependencies>
-elementet i pom.xml
-filen:
<dependency>
<groupId>com.microsoft.signalr.messagepack</groupId>
<artifactId>signalr</artifactId>
<version>5.0.0</version>
</dependency>
Anropa withHubProtocol(new MessagePackHubProtocol())
på HubConnectionBuilder
.
HubConnection messagePackConnection = HubConnectionBuilder.create("YOUR HUB URL HERE")
.withHubProtocol(new MessagePackHubProtocol())
.build();
Överväganden för MessagePack
Det finns några problem att känna till när du använder MessagePack Hub-protokollet.
MessagePack är skiftlägeskänsligt
Protokollet MessagePack är skiftlägeskänsligt. Tänk till exempel på följande C#-klass:
public class ChatMessage
{
public string Sender { get; }
public string Message { get; }
}
När du skickar från JavaScript-klienten måste du använda PascalCased
egenskapsnamn, eftersom höljet måste matcha C#-klassen exakt. Till exempel:
connection.invoke("SomeMethod", { Sender: "Sally", Message: "Hello!" });
Att använda camelCased
-identifierare binder inte korrekt till C#-klassen. Du kan kringgå detta med hjälp av attributet Key
för att ange ett annat namn för egenskapen MessagePack. Mer information finns i MessagePack-CSharp dokumentationen.
DateTime.Kind bevaras inte vid serialisering/deserialisering
MessagePack-protokollet ger inte något sätt att koda Kind
värdet för en DateTime
. När ett datum deserialiseras konverteras därför MessagePack Hub Protocol till UTC-format om DateTime.Kind
är DateTimeKind.Local
annars rör det inte tiden och skickar det som det är. Om du arbetar med DateTime
värden rekommenderar vi att du konverterar till UTC innan du skickar dem. Konvertera dem från UTC till lokal tid när du tar emot dem.
MessagePack-stöd i förhandskompileringens miljö
MessagePack-CSharp--biblioteket som används av .NET-klienten och -servern använder kodgenerering för att optimera serialiseringen. Därför stöds det inte som standard på miljöer som använder kompilering i förväg, till exempel NET Multi-platform App UI (.NET MAUI) eller Unity. Det är möjligt att använda MessagePack i dessa miljöer genom att "förgenerera" serialiseraren/deserialiserarkoden. Mer information finns i MessagePack-CSharp dokumentationen. När du har genererat serialiserarna i förväg kan du registrera dem med hjälp av konfigurationsdelegaten som skickas till 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);
});
Typkontroller är striktare i MessagePack
JSON Hub Protocol utför typkonverteringar under deserialiseringen. Om det inkommande objektet till exempel har ett egenskapsvärde som är ett tal ({ foo: 42 }
) men egenskapen för .NET-klassen är av typen string
konverteras värdet. MessagePack utför dock inte den här konverteringen och utlöser ett undantag som kan visas i loggar på serversidan (och i konsolen):
InvalidDataException: Error binding arguments. Make sure that the types of the provided values match the types of the hub method being invoked.
Mer information om den här begränsningen finns i GitHub-problem aspnet/SignalR#2937.
Tecken och strängar i Java
I Java-klienten kommer char
-objekt att serialiseras som ett-teckens-String
-objekt. Detta står i kontrast till C#- och JavaScript-klienten, som serialiserar dem som short
objekt. Själva MessagePack-specifikationen definierar inte beteendet för char
objekt, så det är upp till biblioteksförfattaren att avgöra hur de ska serialiseras. Skillnaden i beteende mellan våra klienter är ett resultat av de bibliotek som vi använde för våra implementeringar.
Ytterligare resurser
Den här artikeln förutsätter att läsaren är bekant med de ämnen som beskrivs i Komma igång med ASP.NET Core SignalR.
Vad är MessagePack?
MessagePack är ett snabbt och kompakt binärt serialiseringsformat. Det är användbart när prestanda och bandbredd är ett problem eftersom det skapar mindre meddelanden jämfört med JSON-. Binärmeddelandena kan inte läsas när du tittar på nätverksspårningar och loggar om inte byte skickas via en MessagePack-parser. SignalR har inbyggt stöd för MessagePack-formatet och tillhandahåller API:er som klienten och servern kan använda.
Konfigurera MessagePack på servern
Om du vill aktivera MessagePack Hub-protokollet på servern installerar du Microsoft.AspNetCore.SignalR.Protocols.MessagePack
-paketet i din app. I metoden Startup.ConfigureServices
lägger du till AddMessagePackProtocol
i AddSignalR
-anropet för att aktivera MessagePack-stöd på servern.
Obs
JSON är aktiverat som standard. Genom att lägga till MessagePack får du stöd för både JSON- och MessagePack-klienter.
services.AddSignalR()
.AddMessagePackProtocol();
För att anpassa hur MessagePack ska formatera dina data, tar AddMessagePackProtocol
en delegering för att konfigurera alternativ. I den delegeringen kan egenskapen SerializerOptions
användas för att konfigurera serialiseringsalternativ för MessagePack. För mer information om hur lösare fungerar, besök MessagePack-biblioteket på MessagePack-CSharp. Attribut kan användas på de objekt som du vill serialisera för att definiera hur de ska hanteras.
services.AddSignalR()
.AddMessagePackProtocol(options =>
{
options.SerializerOptions = MessagePackSerializerOptions.Standard
.WithResolver(new CustomResolver())
.WithSecurity(MessagePackSecurity.UntrustedData);
});
Varning
Vi rekommenderar starkt att du granskar CVE-2020-5234 och tillämpar de rekommenderade korrigeringarna. Du kan till exempel anropa .WithSecurity(MessagePackSecurity.UntrustedData)
när du ersätter SerializerOptions
.
Konfigurera MessagePack på klienten
Obs
JSON är aktiverat som standard för klienter som stöds. Klienter kan bara stödja ett enda protokoll. Om du lägger till MessagePack-stöd ersätts alla tidigare konfigurerade protokoll.
.NET-klient
Om du vill aktivera MessagePack i .NET-klienten installerar du Microsoft.AspNetCore.SignalR.Protocols.MessagePack
-paketet och anropar AddMessagePackProtocol
på HubConnectionBuilder
.
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.DependencyInjection;
var hubConnection = new HubConnectionBuilder()
.WithUrl("/chathub")
.AddMessagePackProtocol()
.Build();
Obs
Det här AddMessagePackProtocol
-anropet tar en delegat för att konfigurera alternativen på samma sätt som servern.
JavaScript-klient
MessagePack-stöd för JavaScript-klienten tillhandahålls av @microsoft/signalr-protocol-msgpack npm-paketet. Installera paketet genom att köra följande kommando i ett kommandogränssnitt:
npm install @microsoft/signalr-protocol-msgpack
När du har installerat npm-paketet kan modulen användas direkt via en JavaScript-modulinläsare eller importeras till webbläsaren genom att referera till följande fil:
node_modules\@microsoft\signalr-protocol-msgpack\dist\browser\signalr-protocol-msgpack.js
I en webbläsare måste även msgpack5
-biblioteket refereras till. Använd en <script>
tagg för att skapa en referens. Biblioteket finns på node_modules\msgpack5\dist\msgpack5.js.
Obs
När du använder elementet <script>
är ordningen viktig. Om signalr-protocol-msgpack.js
refereras före msgpack5.js
uppstår ett fel när du försöker ansluta till MessagePack.
signalr.js
krävs också innan 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>
Om du lägger till .withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
i HubConnectionBuilder
konfigureras klienten att använda MessagePack-protokollet vid anslutning till en server.
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
.build();
Obs
För närvarande finns det inga konfigurationsalternativ för MessagePack-protokollet på JavaScript-klienten.
Java-klient
Om du vill aktivera MessagePack med Java installerar du com.microsoft.signalr.messagepack
-paketet. När du använder Gradle lägger du till följande rad i avsnittet dependencies
i filen build.gradle:
implementation 'com.microsoft.signalr.messagepack:signalr-messagepack:5.0.0'
När du använder Maven lägger du till följande rader i <dependencies>
-elementet i pom.xml
-filen:
<dependency>
<groupId>com.microsoft.signalr.messagepack</groupId>
<artifactId>signalr</artifactId>
<version>5.0.0</version>
</dependency>
Anropa withHubProtocol(new MessagePackHubProtocol())
på HubConnectionBuilder
.
HubConnection messagePackConnection = HubConnectionBuilder.create("YOUR HUB URL HERE")
.withHubProtocol(new MessagePackHubProtocol())
.build();
Överväganden för MessagePack
Det finns några problem att känna till när du använder MessagePack Hub-protokollet.
MessagePack är skiftlägeskänsligt
Protokollet MessagePack är skiftlägeskänsligt. Tänk till exempel på följande C#-klass:
public class ChatMessage
{
public string Sender { get; }
public string Message { get; }
}
När du skickar från JavaScript-klienten måste du använda PascalCased
egenskapsnamn, eftersom höljet måste matcha C#-klassen exakt. Till exempel:
connection.invoke("SomeMethod", { Sender: "Sally", Message: "Hello!" });
Att använda camelCased
-identifierare binder inte korrekt till C#-klassen. Du kan kringgå detta med hjälp av attributet Key
för att ange ett annat namn för egenskapen MessagePack. Mer information finns i MessagePack-CSharp dokumentationen.
DateTime.Kind bevaras inte vid serialisering/deserialisering
MessagePack-protokollet ger inte något sätt att koda Kind
värdet för en DateTime
. När ett datum deserialiseras konverteras därför MessagePack Hub Protocol till UTC-format om DateTime.Kind
är DateTimeKind.Local
annars rör det inte tiden och skickar det som det är. Om du arbetar med DateTime
värden rekommenderar vi att du konverterar till UTC innan du skickar dem. Konvertera dem från UTC till lokal tid när du tar emot dem.
DateTime.MinValue stöds inte av MessagePack i JavaScript
msgpack5-biblioteket som används av SignalR JavaScript-klienten stöder inte timestamp96
typen i MessagePack. Den här typen används för att koda mycket stora datumvärden (antingen mycket tidigt i det förflutna eller mycket långt i framtiden). Värdet för DateTime.MinValue
är January 1, 0001
, som måste kodas i ett timestamp96
värde. Därför stöds inte sändning av DateTime.MinValue
till en JavaScript-klient. När DateTime.MinValue
tas emot av JavaScript-klienten utlöses följande fel:
Uncaught Error: unable to find ext type 255 at decoder.js:427
Vanligtvis används DateTime.MinValue
för att koda ett värde som "saknas" eller null
. Om du behöver koda det värdet i MessagePack använder du ett nullbart DateTime
värde (DateTime?
) eller kodar ett separat bool
värde som anger om datumet finns.
Mer information om den här begränsningen finns i GitHub-problem aspnet/SignalR#2228.
MessagePack-stöd i förhandskompileringens miljö
MessagePack-CSharp--biblioteket som används av .NET-klienten och -servern använder kodgenerering för att optimera serialiseringen. Därför stöds det inte som standard på miljöer som använder kompilering i förväg, till exempel NET Multi-platform App UI (.NET MAUI) eller Unity. Det är möjligt att använda MessagePack i dessa miljöer genom att "förgenerera" serialiseraren/deserialiserarkoden. Mer information finns i MessagePack-CSharp dokumentationen. När du har genererat serialiserarna i förväg kan du registrera dem med hjälp av konfigurationsdelegaten som skickas till 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);
});
Typkontroller är striktare i MessagePack
JSON Hub Protocol utför typkonverteringar under deserialiseringen. Om det inkommande objektet till exempel har ett egenskapsvärde som är ett tal ({ foo: 42 }
) men egenskapen för .NET-klassen är av typen string
konverteras värdet. MessagePack utför dock inte den här konverteringen och utlöser ett undantag som kan visas i loggar på serversidan (och i konsolen):
InvalidDataException: Error binding arguments. Make sure that the types of the provided values match the types of the hub method being invoked.
Mer information om den här begränsningen finns i GitHub-problem aspnet/SignalR#2937.
Tecken och strängar i Java
I Java-klienten kommer char
-objekt att serialiseras som ett-teckens-String
-objekt. Detta står i kontrast till C#- och JavaScript-klienten, som serialiserar dem som short
objekt. Själva MessagePack-specifikationen definierar inte beteendet för char
objekt, så det är upp till biblioteksförfattaren att avgöra hur de ska serialiseras. Skillnaden i beteende mellan våra klienter är ett resultat av de bibliotek som vi använde för våra implementeringar.
Ytterligare resurser
Den här artikeln förutsätter att läsaren är bekant med de ämnen som beskrivs i Komma igång med ASP.NET Core SignalR.
Vad är MessagePack?
MessagePack är ett snabbt och kompakt binärt serialiseringsformat. Det är användbart när prestanda och bandbredd är ett problem eftersom det skapar mindre meddelanden jämfört med JSON-. Binärmeddelandena kan inte läsas när du tittar på nätverksspårningar och loggar om inte byte skickas via en MessagePack-parser. SignalR har inbyggt stöd för MessagePack-formatet och tillhandahåller API:er som klienten och servern kan använda.
Konfigurera MessagePack på servern
Om du vill aktivera MessagePack Hub-protokollet på servern installerar du Microsoft.AspNetCore.SignalR.Protocols.MessagePack
-paketet i din app. I metoden Startup.ConfigureServices
lägger du till AddMessagePackProtocol
i AddSignalR
-anropet för att aktivera MessagePack-stöd på servern.
Obs
JSON är aktiverat som standard. Genom att lägga till MessagePack får du stöd för både JSON- och MessagePack-klienter.
services.AddSignalR()
.AddMessagePackProtocol();
För att anpassa hur MessagePack ska formatera dina data, tar AddMessagePackProtocol
en delegering för att konfigurera alternativ. I den delegeringen kan egenskapen FormatterResolvers
användas för att konfigurera serialiseringsalternativ för MessagePack. För mer information om hur lösare fungerar, besök MessagePack-biblioteket på MessagePack-CSharp. Attribut kan användas på de objekt som du vill serialisera för att definiera hur de ska hanteras.
services.AddSignalR()
.AddMessagePackProtocol(options =>
{
options.FormatterResolvers = new List<MessagePack.IFormatterResolver>()
{
MessagePack.Resolvers.StandardResolver.Instance
};
});
Varning
Vi rekommenderar starkt att du granskar CVE-2020-5234 och tillämpar de rekommenderade korrigeringarna. Du kan till exempel ange MessagePackSecurity.Active
statisk egenskap till MessagePackSecurity.UntrustedData
. Om du ställer in MessagePackSecurity.Active
måste du installera en 1.9.x-version av MessagePackmanuellt. Om du installerar MessagePack
1.9.x uppgraderas den version SignalR använder.
MessagePack
version 2.x introducerade brytande ändringar och är inte kompatibel med SignalR version 3.1 och tidigare. När MessagePackSecurity.Active
inte är inställt på MessagePackSecurity.UntrustedData
kan en skadlig klient orsaka tjänstblockering. Ange MessagePackSecurity.Active
i Program.Main
, enligt följande kod:
using MessagePack;
public static void Main(string[] args)
{
MessagePackSecurity.Active = MessagePackSecurity.UntrustedData;
CreateHostBuilder(args).Build().Run();
}
Konfigurera MessagePack på klienten
Obs
JSON är aktiverat som standard för klienter som stöds. Klienter kan bara stödja ett enda protokoll. Om du lägger till MessagePack-stöd ersätts alla tidigare konfigurerade protokoll.
.NET-klient
Om du vill aktivera MessagePack i .NET-klienten installerar du Microsoft.AspNetCore.SignalR.Protocols.MessagePack
-paketet och anropar AddMessagePackProtocol
på HubConnectionBuilder
.
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.DependencyInjection;
var hubConnection = new HubConnectionBuilder()
.WithUrl("/chathub")
.AddMessagePackProtocol()
.Build();
Obs
Det här AddMessagePackProtocol
-anropet tar en delegat för att konfigurera alternativen på samma sätt som servern.
JavaScript-klient
MessagePack-stöd för JavaScript-klienten tillhandahålls av @microsoft/signalr-protocol-msgpack npm-paketet. Installera paketet genom att köra följande kommando i ett kommandogränssnitt:
npm install @microsoft/signalr-protocol-msgpack
När du har installerat npm-paketet kan modulen användas direkt via en JavaScript-modulinläsare eller importeras till webbläsaren genom att referera till följande fil:
node_modules\@microsoft\signalr-protocol-msgpack\dist\browser\signalr-protocol-msgpack.js
I en webbläsare måste även msgpack5
-biblioteket refereras till. Använd en <script>
tagg för att skapa en referens. Biblioteket finns på node_modules\msgpack5\dist\msgpack5.js.
Obs
När du använder elementet <script>
är ordningen viktig. Om signalr-protocol-msgpack.js
refereras före msgpack5.js
uppstår ett fel när du försöker ansluta till MessagePack.
signalr.js
krävs också innan 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>
Om du lägger till .withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
i HubConnectionBuilder
konfigureras klienten att använda MessagePack-protokollet vid anslutning till en server.
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
.build();
Obs
För närvarande finns det inga konfigurationsalternativ för MessagePack-protokollet på JavaScript-klienten.
Överväganden för MessagePack
Det finns några problem att känna till när du använder MessagePack Hub-protokollet.
MessagePack är skiftlägeskänsligt
Protokollet MessagePack är skiftlägeskänsligt. Tänk till exempel på följande C#-klass:
public class ChatMessage
{
public string Sender { get; }
public string Message { get; }
}
När du skickar från JavaScript-klienten måste du använda PascalCased
egenskapsnamn, eftersom höljet måste matcha C#-klassen exakt. Till exempel:
connection.invoke("SomeMethod", { Sender: "Sally", Message: "Hello!" });
Att använda camelCased
-identifierare binder inte korrekt till C#-klassen. Du kan kringgå detta med hjälp av attributet Key
för att ange ett annat namn för egenskapen MessagePack. Mer information finns i MessagePack-CSharp dokumentationen.
DateTime.Kind bevaras inte vid serialisering/deserialisering
MessagePack-protokollet ger inte något sätt att koda Kind
värdet för en DateTime
. Därför förutsätter MessagePack Hub-protokollet att det inkommande datumet är i UTC-format när ett datum deserialiseras. Om du arbetar med DateTime
värden i lokal tid rekommenderar vi att du konverterar till UTC innan du skickar dem. Konvertera dem från UTC till lokal tid när du tar emot dem.
Mer information om den här begränsningen finns i GitHub-problem aspnet/SignalR#2632.
DateTime.MinValue stöds inte av MessagePack i JavaScript
msgpack5-biblioteket som används av SignalR JavaScript-klienten stöder inte timestamp96
typen i MessagePack. Den här typen används för att koda mycket stora datumvärden (antingen mycket tidigt i det förflutna eller mycket långt i framtiden). Värdet för DateTime.MinValue
är January 1, 0001
, som måste kodas i ett timestamp96
värde. Därför stöds inte sändning av DateTime.MinValue
till en JavaScript-klient. När DateTime.MinValue
tas emot av JavaScript-klienten utlöses följande fel:
Uncaught Error: unable to find ext type 255 at decoder.js:427
Vanligtvis används DateTime.MinValue
för att koda ett värde som "saknas" eller null
. Om du behöver koda det värdet i MessagePack använder du ett nullbart DateTime
värde (DateTime?
) eller kodar ett separat bool
värde som anger om datumet finns.
Mer information om den här begränsningen finns i GitHub-problem aspnet/SignalR#2228.
MessagePack-stöd i förhandskompileringens miljö
MessagePack-CSharp--biblioteket som används av .NET-klienten och -servern använder kodgenerering för att optimera serialiseringen. Därför stöds det inte som standard på miljöer som använder kompilering i förväg, till exempel NET Multi-platform App UI (.NET MAUI) eller Unity. Det är möjligt att använda MessagePack i dessa miljöer genom att "förgenerera" serialiseraren/deserialiserarkoden. Mer information finns i MessagePack-CSharp dokumentationen. När du har genererat serialiserarna i förväg kan du registrera dem med hjälp av konfigurationsdelegaten som skickas till AddMessagePackProtocol
:
services.AddSignalR()
.AddMessagePackProtocol(options =>
{
options.FormatterResolvers = new List<MessagePack.IFormatterResolver>()
{
MessagePack.Resolvers.GeneratedResolver.Instance,
MessagePack.Resolvers.StandardResolver.Instance
};
});
Typkontroller är striktare i MessagePack
JSON Hub Protocol utför typkonverteringar under deserialiseringen. Om det inkommande objektet till exempel har ett egenskapsvärde som är ett tal ({ foo: 42 }
) men egenskapen för .NET-klassen är av typen string
konverteras värdet. MessagePack utför dock inte den här konverteringen och utlöser ett undantag som kan visas i loggar på serversidan (och i konsolen):
InvalidDataException: Error binding arguments. Make sure that the types of the provided values match the types of the hub method being invoked.
Mer information om den här begränsningen finns i GitHub-problem aspnet/SignalR#2937.
Ytterligare resurser
Den här artikeln förutsätter att läsaren är bekant med de ämnen som beskrivs i Komma igång med ASP.NET Core SignalR.
Vad är MessagePack?
MessagePack är ett snabbt och kompakt binärt serialiseringsformat. Det är användbart när prestanda och bandbredd är ett problem eftersom det skapar mindre meddelanden jämfört med JSON-. Binärmeddelandena kan inte läsas när du tittar på nätverksspårningar och loggar om inte byte skickas via en MessagePack-parser. SignalR har inbyggt stöd för MessagePack-formatet och tillhandahåller API:er som klienten och servern kan använda.
Konfigurera MessagePack på servern
Om du vill aktivera MessagePack Hub-protokollet på servern installerar du Microsoft.AspNetCore.SignalR.Protocols.MessagePack
-paketet i din app. I metoden Startup.ConfigureServices
lägger du till AddMessagePackProtocol
i AddSignalR
-anropet för att aktivera MessagePack-stöd på servern.
Obs
JSON är aktiverat som standard. Genom att lägga till MessagePack får du stöd för både JSON- och MessagePack-klienter.
services.AddSignalR()
.AddMessagePackProtocol();
För att anpassa hur MessagePack ska formatera dina data, tar AddMessagePackProtocol
en delegering för att konfigurera alternativ. I den delegeringen kan egenskapen FormatterResolvers
användas för att konfigurera serialiseringsalternativ för MessagePack. För mer information om hur lösare fungerar, besök MessagePack-biblioteket på MessagePack-CSharp. Attribut kan användas på de objekt som du vill serialisera för att definiera hur de ska hanteras.
services.AddSignalR()
.AddMessagePackProtocol(options =>
{
options.FormatterResolvers = new List<MessagePack.IFormatterResolver>()
{
MessagePack.Resolvers.StandardResolver.Instance
};
});
Varning
Vi rekommenderar starkt att du granskar CVE-2020-5234 och tillämpar de rekommenderade korrigeringarna. Du kan till exempel ange MessagePackSecurity.Active
statisk egenskap till MessagePackSecurity.UntrustedData
. Om du ställer in MessagePackSecurity.Active
måste du installera en 1.9.x-version av MessagePackmanuellt. Om du installerar MessagePack
1.9.x uppgraderas den version SignalR använder. När MessagePackSecurity.Active
inte är inställt på MessagePackSecurity.UntrustedData
, kan en skadlig klient orsaka ett tjänstestopp. Ange MessagePackSecurity.Active
i Program.Main
, enligt följande kod:
using MessagePack;
public static void Main(string[] args)
{
MessagePackSecurity.Active = MessagePackSecurity.UntrustedData;
CreateHostBuilder(args).Build().Run();
}
Konfigurera MessagePack på klienten
Obs
JSON är aktiverat som standard för klienter som stöds. Klienter kan bara stödja ett enda protokoll. Om du lägger till MessagePack-stöd ersätts alla tidigare konfigurerade protokoll.
.NET-klient
Om du vill aktivera MessagePack i .NET-klienten installerar du Microsoft.AspNetCore.SignalR.Protocols.MessagePack
-paketet och anropar AddMessagePackProtocol
på HubConnectionBuilder
.
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.DependencyInjection;
var hubConnection = new HubConnectionBuilder()
.WithUrl("/chathub")
.AddMessagePackProtocol()
.Build();
Obs
Det här AddMessagePackProtocol
-anropet tar en delegat för att konfigurera alternativen på samma sätt som servern.
JavaScript-klient
MessagePack-stöd för JavaScript-klienten tillhandahålls av @aspnet/signalr-protocol-msgpack npm-paketet. Installera paketet genom att köra följande kommando i ett kommandogränssnitt:
npm install @aspnet/signalr-protocol-msgpack
När du har installerat npm-paketet kan modulen användas direkt via en JavaScript-modulinläsare eller importeras till webbläsaren genom att referera till följande fil:
node_modules\@aspnet\signalr-protocol-msgpack\dist\browser\signalr-protocol-msgpack.js
I en webbläsare måste även msgpack5
-biblioteket refereras till. Använd en <script>
tagg för att skapa en referens. Biblioteket finns på node_modules\msgpack5\dist\msgpack5.js.
Obs
När du använder elementet <script>
är ordningen viktig. Om signalr-protocol-msgpack.js
refereras före msgpack5.js
uppstår ett fel när du försöker ansluta till MessagePack.
signalr.js
krävs också innan 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>
Om du lägger till .withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
i HubConnectionBuilder
konfigureras klienten att använda MessagePack-protokollet vid anslutning till en server.
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())
.build();
Obs
För närvarande finns det inga konfigurationsalternativ för MessagePack-protokollet på JavaScript-klienten.
Överväganden för MessagePack
Det finns några problem att känna till när du använder MessagePack Hub-protokollet.
MessagePack är skiftlägeskänsligt
Protokollet MessagePack är skiftlägeskänsligt. Tänk till exempel på följande C#-klass:
public class ChatMessage
{
public string Sender { get; }
public string Message { get; }
}
När du skickar från JavaScript-klienten måste du använda PascalCased
egenskapsnamn, eftersom höljet måste matcha C#-klassen exakt. Till exempel:
connection.invoke("SomeMethod", { Sender: "Sally", Message: "Hello!" });
Att använda camelCased
-identifierare binder inte korrekt till C#-klassen. Du kan kringgå detta med hjälp av attributet Key
för att ange ett annat namn för egenskapen MessagePack. Mer information finns i MessagePack-CSharp dokumentationen.
DateTime.Kind bevaras inte vid serialisering/deserialisering
MessagePack-protokollet ger inte något sätt att koda Kind
värdet för en DateTime
. Därför förutsätter MessagePack Hub-protokollet att det inkommande datumet är i UTC-format när ett datum deserialiseras. Om du arbetar med DateTime
värden i lokal tid rekommenderar vi att du konverterar till UTC innan du skickar dem. Konvertera dem från UTC till lokal tid när du tar emot dem.
Mer information om den här begränsningen finns i GitHub-problem aspnet/SignalR#2632.
DateTime.MinValue stöds inte av MessagePack i JavaScript
msgpack5-biblioteket som används av SignalR JavaScript-klienten stöder inte timestamp96
typen i MessagePack. Den här typen används för att koda mycket stora datumvärden (antingen mycket tidigt i det förflutna eller mycket långt i framtiden). Värdet för DateTime.MinValue
är January 1, 0001
som måste kodas i ett timestamp96
värde. Därför stöds inte sändning av DateTime.MinValue
till en JavaScript-klient. När DateTime.MinValue
tas emot av JavaScript-klienten utlöses följande fel:
Uncaught Error: unable to find ext type 255 at decoder.js:427
Vanligtvis används DateTime.MinValue
för att koda ett värde som "saknas" eller null
. Om du behöver koda det värdet i MessagePack använder du ett nullbart DateTime
värde (DateTime?
) eller kodar ett separat bool
värde som anger om datumet finns.
Mer information om den här begränsningen finns i GitHub-problem aspnet/SignalR#2228.
MessagePack-stöd i förhandskompileringens miljö
MessagePack-CSharp--biblioteket som används av .NET-klienten och -servern använder kodgenerering för att optimera serialiseringen. Därför stöds det inte som standard på miljöer som använder kompilering i förväg, till exempel NET Multi-platform App UI (.NET MAUI) eller Unity. Det är möjligt att använda MessagePack i dessa miljöer genom att "förgenerera" serialiseraren/deserialiserarkoden. Mer information finns i MessagePack-CSharp dokumentationen. När du har genererat serialiserarna i förväg kan du registrera dem med hjälp av konfigurationsdelegaten som skickas till AddMessagePackProtocol
:
services.AddSignalR()
.AddMessagePackProtocol(options =>
{
options.FormatterResolvers = new List<MessagePack.IFormatterResolver>()
{
MessagePack.Resolvers.GeneratedResolver.Instance,
MessagePack.Resolvers.StandardResolver.Instance
};
});
Typkontroller är striktare i MessagePack
JSON Hub Protocol utför typkonverteringar under deserialiseringen. Om det inkommande objektet till exempel har ett egenskapsvärde som är ett tal ({ foo: 42 }
) men egenskapen för .NET-klassen är av typen string
konverteras värdet. MessagePack utför dock inte den här konverteringen och utlöser ett undantag som kan visas i loggar på serversidan (och i konsolen):
InvalidDataException: Error binding arguments. Make sure that the types of the provided values match the types of the hub method being invoked.
Mer information om den här begränsningen finns i GitHub-problem aspnet/SignalR#2937.
Ytterligare resurser
ASP.NET Core