本文假設讀者熟悉 開始使用 ASP.NET Core SignalR 中涵蓋的主題。

什麼是 MessagePack?

MessagePack 是快速且精簡的二進位序列化格式。 當效能和頻寬是考慮的時機,因為它會建立比 JS ON 較小的訊息。 除非位元組是透過 MessagePack 剖析器傳遞,否則查看網路追蹤和記錄時,二進位訊息是無法讀取的。 SignalR 具有 MessagePack 格式的內建支援,並提供用戶端和伺服器要使用的 API。

在伺服器上設定 MessagePack

若要在伺服器上啟用 MessagePack Hub 通訊協定,請在 Microsoft.AspNetCore.SignalR.Protocols.MessagePack 應用程式中安裝套件。 在 方法中 Startup.ConfigureServices ,將 新增 AddMessagePackProtocol AddSignalR 呼叫,以在伺服器上啟用 MessagePack 支援。

services.AddSignalR()
    .AddMessagePackProtocol();

JS預設會啟用 ON。 新增 MessagePack 可同時支援 JS ON 和 MessagePack 用戶端。

若要自訂 MessagePack 格式化資料的方式, AddMessagePackProtocol 請接受委派來設定選項。 在該委派中 SerializerOptions ,屬性是用來設定 MessagePack 序列化選項。 如需解析程式運作方式的詳細資訊,請造訪 MessagePack-CSharp 上的 MessagePack程式庫。 屬性可用於您想要序列化的物件,以定義應該如何處理這些屬性。

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

強烈建議您檢閱 CVE-2020-5234 並套用建議的修補程式。 例如,取代 SerializerOptions 時呼叫 .WithSecurity(MessagePackSecurity.UntrustedData)

在用戶端上設定 MessagePack

JS預設會針對支援的用戶端啟用 ON。 用戶端只能支援單一通訊協定。 新增 MessagePack 支援會取代任何先前設定的通訊協定。

.NET 用戶端

若要在 .NET 用戶端中啟用 MessagePack,請安裝 Microsoft.AspNetCore.SignalR.Protocols.MessagePack 套件並在 上 HubConnectionBuilder 呼叫 AddMessagePackProtocol

using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.DependencyInjection;
var hubConnection = new HubConnectionBuilder()
                        .WithUrl("/chathub")
                        .AddMessagePackProtocol()
                        .Build();

AddMessagePackProtocol 呼叫會接受委派來設定選項,就像伺服器一樣。

JavaScript 用戶端

JavaScript 用戶端的 MessagePack 支援是由 @microsoft/signalr-protocol-msgpack npm 套件所提供。 在命令殼層中執行下列命令來安裝套件:

npm install @microsoft/signalr-protocol-msgpack

安裝 npm 套件之後,模組可以直接透過 JavaScript 模組載入器使用,或藉由參考下列檔案匯入瀏覽器:

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

下列必要的 javaScript 檔案必須依照如下所示的順序來參考:

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

新增 .withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol()) 至 會 HubConnectionBuilder 設定用戶端在連線到伺服器時使用 MessagePack 通訊協定。

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

目前,JavaScript 用戶端上沒有 MessagePack 通訊協定的組態選項。

Java 用戶端

若要使用 JAVA 啟用 MessagePack,請安裝 com.microsoft.signalr.messagepack 套件。 使用 Gradle 時,將下列這一行新增至 dependenciesbuild.gradle 檔案的 區段:

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

使用 Maven 時,請在檔案的 pom.xml 元素內 <dependencies> 新增下列幾行:

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

在 上 HubConnectionBuilder 呼叫 withHubProtocol(new MessagePackHubProtocol())

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

MessagePack 考慮

使用 MessagePack Hub 通訊協定時,有幾個問題需要注意。

MessagePack 區分大小寫

MessagePack 通訊協定會區分大小寫。 例如,請考慮下列 C# 類別:

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

從 JavaScript 用戶端傳送時,您必須使用 PascalCased 屬性名稱,因為大小寫必須完全符合 C# 類別。 例如:

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

使用 camelCased 名稱不會正確系結至 C# 類別。 您可以使用 屬性來指定 MessagePack 屬性的不同名稱,以解決此問題 Key 。 如需詳細資訊,請參閱 MessagePack-CSharp檔

序列化/還原序列化時,不會保留 DateTime.Kind

MessagePack 通訊協定不提供編碼 KindDateTime 的方法。 如此一來,還原序列化日期時,如果 DateTime.KindDateTimeKind.Local 不是,則 MessagePack Hub 通訊協定會轉換成 UTC 格式,否則不會觸碰時間並依原樣傳遞。 如果您使用 DateTime 值,建議您在傳送值之前先轉換成 UTC。 當您收到 UTC 時,將它們從 UTC 轉換為當地時間。

「預先」編譯環境中的 MessagePack 支援

.NET 用戶端和伺服器所使用的 MessagePack-CSharp 程式庫會使用程式碼產生來優化序列化。 因此,預設不支援使用「預先」編譯的環境 (,例如 Xamarin iOS 或 Unity) 。 您可以透過「預先產生」序列化程式/還原序列化程式程式碼,在這些環境中使用 MessagePack。 如需詳細資訊,請參閱 MessagePack-CSharp檔。 預先產生序列化程式之後,您可以使用傳遞至 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);

MessagePack 中的類型檢查更嚴格

ON 中 JS 樞通訊協定會在還原序列化期間執行類型轉換。 例如,如果傳入物件具有數值 () { foo: 42 } 但 .NET 類別上的 屬性屬於 類型 string ,則會轉換值。 不過,MessagePack 不會執行此轉換,而且會擲回可在伺服器端記錄 (和主控台) 中看到的例外狀況:

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

如需此限制的詳細資訊,請參閱 GitHub 問題 aspnet/ SignalR #2937

JAVA 中的字元和字串

在 java 用戶端中, char 物件會序列化為一個字元 String 的物件。 這與 C# 和 JavaScript 用戶端相反,它會將它們序列化為 short 物件。 MessagePack 規格本身不會定義物件的行為 char ,因此,程式庫作者必須決定如何序列化它們。 用戶端之間的行為差異是我們用於實作的程式庫的結果。

  • SignalRASP.NET Core .NET 用戶端
  • SignalRASP.NET Core JavaScript 用戶端
  • 本文假設讀者熟悉開始使用 ASP.NET Core SignalR中涵蓋的主題。

    什麼是 MessagePack?

    MessagePack 是快速且精簡的二進位序列化格式。 效能和頻寬是考慮的時機,因為它會建立比 ON 較小的訊息JS。 除非位元組是透過 MessagePack 剖析器傳遞,否則查看網路追蹤和記錄時,二進位訊息是無法讀取的。 SignalR 具有 MessagePack 格式的內建支援,並提供用戶端和伺服器要使用的 API。

    在伺服器上設定 MessagePack

    若要在伺服器上啟用 MessagePack Hub 通訊協定,請在 Microsoft.AspNetCore.SignalR.Protocols.MessagePack 應用程式中安裝套件。 在 方法中 Startup.ConfigureServices ,將 新增 AddMessagePackProtocolAddSignalR 呼叫,以在伺服器上啟用 MessagePack 支援。

    JS預設會啟用 ON。 新增 MessagePack 可同時支援 JS ON 和 MessagePack 用戶端。

    services.AddSignalR()
        .AddMessagePackProtocol();
    

    若要自訂 MessagePack 如何格式化您的資料, AddMessagePackProtocol 請接受委派來設定選項。 在該委派中 SerializerOptions ,屬性可用來設定 MessagePack 序列化選項。 如需解析程式運作方式的詳細資訊,請造訪 MessagePack-CSharp 上的 MessagePack程式庫。 屬性可用於您想要序列化的物件,以定義應該如何處理這些屬性。

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

    強烈建議您檢閱 CVE-2020-5234 並套用建議的修補程式。 例如,取代 SerializerOptions 時呼叫 .WithSecurity(MessagePackSecurity.UntrustedData)

    在用戶端上設定 MessagePack

    JS預設會針對支援的用戶端啟用 ON。 用戶端只能支援單一通訊協定。 新增 MessagePack 支援將會取代任何先前設定的通訊協定。

    .NET 用戶端

    若要在 .NET 用戶端中啟用 MessagePack,請安裝 Microsoft.AspNetCore.SignalR.Protocols.MessagePack 套件並在 上 HubConnectionBuilder 呼叫 AddMessagePackProtocol

    using Microsoft.AspNetCore.SignalR.Client;
    using Microsoft.Extensions.DependencyInjection;
    var hubConnection = new HubConnectionBuilder()
                            .WithUrl("/chathub")
                            .AddMessagePackProtocol()
                            .Build();
    

    AddMessagePackProtocol 呼叫會接受委派來設定選項,就像伺服器一樣。

    JavaScript 用戶端

    JavaScript 用戶端的 MessagePack 支援是由 @microsoft/signalr-protocol-msgpack npm 套件所提供。 在命令殼層中執行下列命令來安裝套件:

    npm install @microsoft/signalr-protocol-msgpack
    

    安裝 npm 套件之後,模組可以直接透過 JavaScript 模組載入器使用,或藉由參考下列檔案匯入瀏覽器:

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

    在瀏覽器中,也必須參考連結 msgpack5 庫。 <script>使用 標記來建立參考。 您可以在 node_modules\msgpack5\dist\msgpack5.js找到程式庫。

    使用 <script> 元素時,順序很重要。 如果在 signalr-protocol-msgpack.js 之前 msgpack5.js 參考 ,則嘗試使用 MessagePack 連線時發生錯誤。 signalr.js 也需要在 之前 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>
    

    新增 .withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())HubConnectionBuilder 會將用戶端設定為在連接到伺服器時使用 MessagePack 通訊協定。

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

    目前,JavaScript 用戶端上沒有 MessagePack 通訊協定的組態選項。

    Java 用戶端

    若要使用 JAVA 啟用 MessagePack,請安裝 com.microsoft.signalr.messagepack 套件。 使用 Gradle 時,將下列這一行新增至 dependenciesbuild.gradle 檔案的 區段:

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

    使用 Maven 時,請在檔案的 pom.xml 元素內 <dependencies> 新增下列幾行:

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

    在 上 HubConnectionBuilder 呼叫 withHubProtocol(new MessagePackHubProtocol())

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

    MessagePack 考慮

    使用 MessagePack Hub 通訊協定時,有幾個問題需要注意。

    MessagePack 區分大小寫

    MessagePack 通訊協定會區分大小寫。 例如,請考慮下列 C# 類別:

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

    從 JavaScript 用戶端傳送時,您必須使用 PascalCased 屬性名稱,因為大小寫必須完全符合 C# 類別。 例如:

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

    使用 camelCased 名稱不會正確系結至 C# 類別。 您可以使用 屬性來指定 MessagePack 屬性的不同名稱,以解決此問題 Key 。 如需詳細資訊,請參閱 MessagePack-CSharp檔

    序列化/還原序列化時,不會保留 DateTime.Kind

    MessagePack 通訊協定不提供編碼 KindDateTime 的方法。 如此一來,還原序列化日期時,如果 DateTime.KindDateTimeKind.Local 不是,則 MessagePack Hub 通訊協定會轉換成 UTC 格式,否則不會觸碰時間並依原樣傳遞。 如果您使用 DateTime 值,建議您在傳送值之前先轉換成 UTC。 當您收到 UTC 時,將它們從 UTC 轉換為當地時間。

    JavaScript 中的 MessagePack 不支援 DateTime.MinValue

    JavaScript 用戶端所使用的 SignalRmsgpack5程式庫不支援 timestamp96 MessagePack 中的類型。 此類型用來編碼非常大型的日期值, (過去或未來非常遠) 。 的值是 January 1, 0001 ,這個值 DateTime.MinValue 必須編碼在 值中 timestamp96 。 因此,不支援傳送 DateTime.MinValue 至 JavaScript 用戶端。 當 JavaScript 用戶端收到時 DateTime.MinValue ,會擲回下列錯誤:

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

    通常, DateTime.MinValue 用來編碼「遺漏」或 null 值。 如果您需要在 MessagePack 中編碼該值,請使用可為 DateTime Null 的值 (DateTime?) 或編碼個別 bool 的值,指出日期是否存在。

    如需此限制的詳細資訊,請參閱 GitHub 問題 aspnet/ SignalR #2228

    「預先」編譯環境中的 MessagePack 支援

    .NET 用戶端和伺服器所使用的 MessagePack-CSharp 程式庫會使用程式碼產生來優化序列化。 因此,預設不支援使用「預先」編譯的環境 (,例如 Xamarin iOS 或 Unity) 。 您可以透過「預先產生」序列化程式/還原序列化程式程式碼,在這些環境中使用 MessagePack。 如需詳細資訊,請參閱 MessagePack-CSharp檔。 預先產生序列化程式之後,您可以使用傳遞至 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);
    

    MessagePack 中的類型檢查更嚴格

    ON 中 JS 樞通訊協定會在還原序列化期間執行類型轉換。 例如,如果傳入物件具有數值 () { foo: 42 } 但 .NET 類別上的 屬性屬於 類型 string ,則會轉換值。 不過,MessagePack 不會執行此轉換,而且會擲回可在伺服器端記錄 (和主控台) 中看到的例外狀況:

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

    如需此限制的詳細資訊,請參閱 GitHub 問題 aspnet/ SignalR #2937

    JAVA 中的字元和字串

    在 java 用戶端中, char 物件會序列化為一個字元 String 的物件。 這與 C# 和 JavaScript 用戶端相反,它會將它們序列化為 short 物件。 MessagePack 規格本身不會定義物件的行為 char ,因此,程式庫作者必須決定如何序列化它們。 用戶端之間的行為差異是我們用於實作的程式庫的結果。

  • SignalRASP.NET Core .NET 用戶端
  • SignalRASP.NET Core JavaScript 用戶端
  • 本文假設讀者熟悉開始使用 ASP.NET Core SignalR中涵蓋的主題。

    什麼是 MessagePack?

    MessagePack 是快速且精簡的二進位序列化格式。 效能和頻寬是考慮的時機,因為它會建立比 ON 較小的訊息JS。 除非位元組是透過 MessagePack 剖析器傳遞,否則查看網路追蹤和記錄時,二進位訊息是無法讀取的。 SignalR 具有 MessagePack 格式的內建支援,並提供用戶端和伺服器要使用的 API。

    在伺服器上設定 MessagePack

    若要在伺服器上啟用 MessagePack Hub 通訊協定,請在 Microsoft.AspNetCore.SignalR.Protocols.MessagePack 應用程式中安裝套件。 在 方法中 Startup.ConfigureServices ,將 新增 AddMessagePackProtocolAddSignalR 呼叫,以在伺服器上啟用 MessagePack 支援。

    JS預設會啟用 ON。 新增 MessagePack 可同時支援 JS ON 和 MessagePack 用戶端。

    services.AddSignalR()
        .AddMessagePackProtocol();
    

    若要自訂 MessagePack 如何格式化您的資料, AddMessagePackProtocol 請接受委派來設定選項。 在該委派中 FormatterResolvers ,屬性可用來設定 MessagePack 序列化選項。 如需解析程式運作方式的詳細資訊,請造訪 MessagePack-CSharp 上的 MessagePack程式庫。 屬性可用於您想要序列化的物件,以定義應該如何處理這些屬性。

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

    強烈建議您檢閱 CVE-2020-5234 並套用建議的修補程式。 例如,將 MessagePackSecurity.Active 靜態屬性設定為 MessagePackSecurity.UntrustedDataMessagePackSecurity.Active設定 需要手動安裝1.9.x 版的 MessagePack。 安裝 MessagePack 1.9.x 會升級版本所使用的版本 SignalR 。 MessagePack 2.x 版引進了重大變更,且與 SignalR 3.1 版和更早版本不相容。 當 未設定為 MessagePackSecurity.UntrustedDataMessagePackSecurity.Active ,惡意用戶端可能會導致拒絕服務。 在 中 Program.Main 設定 MessagePackSecurity.Active ,如下列程式碼所示:

    using MessagePack;
    public static void Main(string[] args)
      MessagePackSecurity.Active = MessagePackSecurity.UntrustedData;
      CreateHostBuilder(args).Build().Run();
    

    在用戶端上設定 MessagePack

    JS預設會針對支援的用戶端啟用 ON。 用戶端只能支援單一通訊協定。 新增 MessagePack 支援將會取代任何先前設定的通訊協定。

    .NET 用戶端

    若要在 .NET 用戶端中啟用 MessagePack,請在 Microsoft.AspNetCore.SignalR.Protocols.MessagePack 上安裝 HubConnectionBuilder 套件並呼叫 AddMessagePackProtocol

    using Microsoft.AspNetCore.SignalR.Client;
    using Microsoft.Extensions.DependencyInjection;
    var hubConnection = new HubConnectionBuilder()
                            .WithUrl("/chathub")
                            .AddMessagePackProtocol()
                            .Build();
    

    AddMessagePackProtocol 呼叫會接受委派來設定選項,就像伺服器一樣。

    JavaScript 用戶端

    JavaScript 用戶端的 MessagePack 支援是由 @microsoft/signalr-protocol-msgpack npm 套件所提供。 在命令殼層中執行下列命令來安裝套件:

    npm install @microsoft/signalr-protocol-msgpack
    

    安裝 npm 套件之後,模組可以直接透過 JavaScript 模組載入器使用,或藉由參考下列檔案匯入瀏覽器:

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

    在瀏覽器中,也必須參考連結 msgpack5 庫。 <script>使用 標記來建立參考。 程式庫位於 node_modules\msgpack5\dist\msgpack5.js

    使用 <script> 元素時,順序很重要。 如果在 signalr-protocol-msgpack.js 之前 msgpack5.js 參考 ,則嘗試使用 MessagePack 連線時發生錯誤。 signalr.js 也需要在 之前 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>
    

    新增 .withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())HubConnectionBuilder 會將用戶端設定為在連線到伺服器時使用 MessagePack 通訊協定。

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

    目前,JavaScript 用戶端上沒有 MessagePack 通訊協定的組態選項。

    MessagePack 考慮

    使用 MessagePack 中樞通訊協定時,有一些需要注意的問題。

    MessagePack 區分大小寫

    MessagePack 通訊協定會區分大小寫。 例如,請考慮下列 C# 類別:

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

    從 JavaScript 用戶端傳送時,您必須使用 PascalCased 屬性名稱,因為大小寫必須完全符合 C# 類別。 例如:

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

    使用 camelCased 名稱不會正確系結至 C# 類別。 您可以使用 屬性來指定 MessagePack 屬性的不同名稱來解決此問題 Key 。 如需詳細資訊,請參閱 MessagePack-CSharp檔

    序列化/還原序列化時,不會保留 DateTime.Kind

    MessagePack 通訊協定不提供編碼 KindDateTime 的方法。 因此,還原序列化日期時,MessagePack Hub 通訊協定會假設傳入日期採用 UTC 格式。 如果您在當地時間使用 DateTime 值,建議您在傳送值之前先轉換成 UTC。 當您收到 UTC 時,將它們從 UTC 轉換為當地時間。

    如需這項限制的詳細資訊,請參閱 GitHub 問題 aspnet/ SignalR #2632

    JavaScript 中的 MessagePack 不支援 DateTime.MinValue

    JavaScript 用戶端所使用的 SignalRmsgpack5程式庫不支援 timestamp96 MessagePack 中的類型。 此類型用來編碼非常大型的日期值, (過去或未來非常遠的日期值) 。 的值 DateTime.MinValueJanuary 1, 0001 ,其必須在 值中 timestamp96 編碼。 因此,不支援傳送 DateTime.MinValue 至 JavaScript 用戶端。 當 JavaScript 用戶端收到 時 DateTime.MinValue ,會擲回下列錯誤:

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

    通常, DateTime.MinValue 是用來編碼「遺漏」或 null 值。 如果您需要在 MessagePack 中編碼該值,請使用可為 DateTime Null 的值 () DateTime? 或編碼個別 bool 的值,指出日期是否存在。

    如需這項限制的詳細資訊,請參閱 GitHub 問題 aspnet/ SignalR #2228

    「預先」編譯環境中的 MessagePack 支援

    .NET 用戶端和伺服器所使用的 MessagePack-CSharp 程式庫會使用程式碼產生來優化序列化。 因此,使用「預先」編譯 (的環境預設不支援它,例如 Xamarin iOS 或 Unity) 。 您可以藉由「預先產生」序列化程式/還原序列化程式程式程式碼,在這些環境中使用 MessagePack。 如需詳細資訊,請參閱 MessagePack-CSharp檔。 預先產生序列化程式之後,您可以使用傳遞至 AddMessagePackProtocol 的組態委派來註冊序列化程式:

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

    MessagePack 中的類型檢查更嚴格

    ON 中 JS 樞通訊協定會在還原序列化期間執行類型轉換。 例如,如果傳入物件有一個屬性值,其為數字 ({ foo: 42 }) 但 .NET 類別上的 屬性的類型 string 為 ,則會轉換該值。 不過,MessagePack 不會執行此轉換,而且會擲回可在伺服器端記錄 (和主控台) 中看到的例外狀況:

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

    如需這項限制的詳細資訊,請參閱 GitHub 問題 aspnet/ SignalR #2937

  • SignalRASP.NET Core .NET 用戶端
  • ASP.NET Core SignalR JavaScript 用戶端
  • 本文假設讀者熟悉開始使用 ASP.NET Core SignalR中涵蓋的主題。

    什麼是 MessagePack?

    MessagePack 是快速且精簡的二進位序列化格式。 相較于 ON,當效能和頻寬是一個考慮時,它很有用。因為它會建立較小的訊息JS。 除非位元組透過 MessagePack 剖析器傳遞,否則查看網路追蹤和記錄時,二進位訊息是無法讀取的。 SignalR 具有 MessagePack 格式的內建支援,並提供用戶端和伺服器要使用的 API。

    在伺服器上設定 MessagePack

    若要在伺服器上啟用 MessagePack 中樞通訊協定,請在 Microsoft.AspNetCore.SignalR.Protocols.MessagePack 您的應用程式中安裝套件。 在 方法中 Startup.ConfigureServices ,將 新增 AddMessagePackProtocolAddSignalR 呼叫,以在伺服器上啟用 MessagePack 支援。

    JS預設會啟用 ON。 新增 MessagePack 可同時支援 JS ON 和 MessagePack 用戶端。

    services.AddSignalR()
        .AddMessagePackProtocol();
    

    若要自訂 MessagePack 將資料格式化的方式, AddMessagePackProtocol 請採用委派來設定選項。 在該委派中 FormatterResolvers ,屬性可用來設定 MessagePack 序列化選項。 如需解析程式運作方式的詳細資訊,請造訪 MessagePack-CSharp 上的 MessagePack程式庫。 屬性可用於您想要序列化的物件,以定義應該如何處理它們。

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

    強烈建議您檢閱 CVE-2020-5234 並套用建議的修補程式。 例如,將 MessagePackSecurity.Active 靜態屬性設定為 MessagePackSecurity.UntrustedDataMessagePackSecurity.Active設定 需要手動安裝1.9.x 版的 MessagePack。 安裝 MessagePack 1.9.x 升級版本所使用的版本 SignalR 。 當 未設定為 MessagePackSecurity.UntrustedDataMessagePackSecurity.Active ,惡意用戶端可能會導致拒絕服務。 在 中 Program.Main 設定 MessagePackSecurity.Active ,如下列程式碼所示:

    using MessagePack;
    public static void Main(string[] args)
      MessagePackSecurity.Active = MessagePackSecurity.UntrustedData;
      CreateHostBuilder(args).Build().Run();
    

    在用戶端上設定 MessagePack

    JS預設會針對支援的用戶端啟用 ON。 用戶端只能支援單一通訊協定。 新增 MessagePack 支援將會取代任何先前設定的通訊協定。

    .NET 用戶端

    若要在 .NET 用戶端中啟用 MessagePack,請在 Microsoft.AspNetCore.SignalR.Protocols.MessagePack 上安裝 HubConnectionBuilder 套件並呼叫 AddMessagePackProtocol

    using Microsoft.AspNetCore.SignalR.Client;
    using Microsoft.Extensions.DependencyInjection;
    var hubConnection = new HubConnectionBuilder()
                            .WithUrl("/chathub")
                            .AddMessagePackProtocol()
                            .Build();
    

    AddMessagePackProtocol 呼叫會接受委派來設定選項,就像伺服器一樣。

    JavaScript 用戶端

    JavaScript 用戶端的 MessagePack 支援是由 @aspnet/signalr-protocol-msgpack npm 套件所提供。 在命令殼層中執行下列命令來安裝套件:

    npm install @aspnet/signalr-protocol-msgpack
    

    安裝 npm 套件之後,模組可以直接透過 JavaScript 模組載入器使用,或藉由參考下列檔案匯入瀏覽器:

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

    在瀏覽器中,也必須參考連結 msgpack5 庫。 <script>使用 標記來建立參考。 程式庫位於 node_modules\msgpack5\dist\msgpack5.js

    使用 <script> 元素時,順序很重要。 如果在 signalr-protocol-msgpack.js 之前 msgpack5.js 參考 ,則嘗試使用 MessagePack 連線時發生錯誤。 signalr.js 也需要在 之前 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>
    

    新增 .withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol())HubConnectionBuilder 會將用戶端設定為在連接到伺服器時使用 MessagePack 通訊協定。

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

    目前,JavaScript 用戶端上沒有 MessagePack 通訊協定的組態選項。

    MessagePack 考慮

    使用 MessagePack Hub 通訊協定時,有幾個問題需要注意。

    MessagePack 區分大小寫

    MessagePack 通訊協定會區分大小寫。 例如,請考慮下列 C# 類別:

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

    從 JavaScript 用戶端傳送時,您必須使用 PascalCased 屬性名稱,因為大小寫必須完全符合 C# 類別。 例如:

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

    使用 camelCased 名稱不會正確系結至 C# 類別。 您可以使用 屬性來指定 MessagePack 屬性的不同名稱,以解決此問題 Key 。 如需詳細資訊,請參閱 MessagePack-CSharp檔

    序列化/還原序列化時,不會保留 DateTime.Kind

    MessagePack 通訊協定不提供編碼 KindDateTime 的方法。 因此,還原序列化日期時,MessagePack Hub 通訊協定會假設傳入日期是 UTC 格式。 如果您要在當地時間使用 DateTime 值,建議您先轉換成 UTC,再傳送這些值。 當您收到 UTC 時,將它們從 UTC 轉換為當地時間。

    如需此限制的詳細資訊,請參閱 GitHub 問題 aspnet/ SignalR #2632

    JavaScript 中的 MessagePack 不支援 DateTime.MinValue

    JavaScript 用戶端所使用的 SignalRmsgpack5程式庫不支援 timestamp96 MessagePack 中的類型。 此類型用來編碼非常大型的日期值, (過去或未來非常遠) 。 的值必須在 January 1, 0001DateTime.MinValuetimestamp96 編碼。 因此,不支援傳送 DateTime.MinValue 至 JavaScript 用戶端。 當 JavaScript 用戶端收到時 DateTime.MinValue ,會擲回下列錯誤:

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

    通常, DateTime.MinValue 用來編碼「遺漏」或 null 值。 如果您需要在 MessagePack 中編碼該值,請使用可為 DateTime Null 的值 (DateTime?) 或編碼個別 bool 的值,指出日期是否存在。

    如需此限制的詳細資訊,請參閱 GitHub 問題 aspnet/ SignalR #2228

    「預先」編譯環境中的 MessagePack 支援

    .NET 用戶端和伺服器所使用的 MessagePack-CSharp 程式庫會使用程式碼產生來優化序列化。 因此,預設不支援使用「預先」編譯的環境 (,例如 Xamarin iOS 或 Unity) 。 您可以透過「預先產生」序列化程式/還原序列化程式程式碼,在這些環境中使用 MessagePack。 如需詳細資訊,請參閱 MessagePack-CSharp檔。 預先產生序列化程式之後,您可以使用傳遞至 AddMessagePackProtocol 的組態委派來註冊它們:

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

    MessagePack 中的類型檢查更嚴格

    ON 中 JS 樞通訊協定會在還原序列化期間執行類型轉換。 例如,如果傳入物件具有數值 () { foo: 42 } 但 .NET 類別上的 屬性屬於 類型 string ,則會轉換值。 不過,MessagePack 不會執行此轉換,而且會擲回可在伺服器端記錄 (和主控台) 中看到的例外狀況:

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

    如需此限制的詳細資訊,請參閱 GitHub 問題 aspnet/ SignalR #2937

  • SignalRASP.NET Core .NET 用戶端
  • SignalRASP.NET Core JavaScript 用戶端
  •