Gunakan MessagePack Hub Protocol di SignalR untuk ASP.NET Core

Artikel ini mengasumsikan pembaca terbiasa dengan topik yang dibahas dalam Memulai ASP.NET Core SignalR.

Apa itu MessagePack?

MessagePack adalah format serialisasi biner yang cepat dan ringkas. Ini berguna ketika performa dan bandwidth menjadi perhatian karena menciptakan pesan yang lebih kecil daripada JSAKTIF. Pesan biner tidak dapat dibaca saat melihat jejak jaringan dan log kecuali byte diteruskan melalui parser MessagePack. SignalR memiliki dukungan bawaan untuk format MessagePack dan menyediakan API untuk digunakan klien dan server.

Mengonfigurasi MessagePack di server

Untuk mengaktifkan Protokol Hub MessagePack di server, instal Microsoft.AspNetCore.SignalR.Protocols.MessagePack paket di aplikasi Anda. Dalam metode , Startup.ConfigureServices tambahkan AddMessagePackProtocol ke AddSignalR panggilan untuk mengaktifkan dukungan MessagePack di server.

services.AddSignalR()
    .AddMessagePackProtocol();

Catatan

JSAKTIF diaktifkan secara default. Menambahkan MessagePack memungkinkan dukungan untuk JSklien ON dan MessagePack.

Untuk menyesuaikan bagaimana MessagePack memformat data, AddMessagePackProtocol ambil delegasi untuk mengonfigurasi opsi. Dalam delegasi tersebut SerializerOptions , properti digunakan untuk mengonfigurasi opsi serialisasi MessagePack. Untuk informasi selengkapnya tentang cara kerja pemecah masalah, kunjungi pustaka MessagePack di MessagePack-CSharp. Atribut dapat digunakan pada objek yang ingin Anda serialkan untuk menentukan bagaimana atribut tersebut harus ditangani.

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

Peringatan

Kami sangat menyarankan untuk meninjau CVE-2020-5234 dan menerapkan patch yang direkomendasikan. Misalnya, memanggil .WithSecurity(MessagePackSecurity.UntrustedData) saat mengganti SerializerOptions.

Mengonfigurasi MessagePack pada klien

Catatan

JSAKTIF diaktifkan secara default untuk klien yang didukung. Klien hanya dapat mendukung satu protokol. Menambahkan dukungan MessagePack menggantikan protokol yang dikonfigurasi sebelumnya.

Klien .NET

Untuk mengaktifkan MessagePack di Klien .NET, instal Microsoft.AspNetCore.SignalR.Protocols.MessagePack paket dan panggil AddMessagePackProtocol di HubConnectionBuilder.

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

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

Catatan

Panggilan ini AddMessagePackProtocol mengambil delegasi untuk mengonfigurasi opsi seperti server.

Klien JavaScript

Dukungan MessagePack untuk klien JavaScript disediakan oleh paket npm @microsoft/signalr-protocol-msgpack . Instal paket dengan menjalankan perintah berikut dalam shell perintah:

npm install @microsoft/signalr-protocol-msgpack

Setelah menginstal paket npm, modul dapat digunakan langsung melalui pemuat modul JavaScript atau diimpor ke browser dengan mereferensikan file berikut:

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

File javaScript yang diperlukan berikut harus direferensikan dalam urutan yang ditunjukkan di bawah ini:

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

.withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol()) Menambahkan ke HubConnectionBuilder konfigurasi klien untuk menggunakan protokol MessagePack saat menyambungkan ke server.

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

Saat ini, tidak ada opsi konfigurasi untuk protokol MessagePack pada klien JavaScript.

Klien Java

Untuk mengaktifkan MessagePack dengan Java, instal com.microsoft.signalr.messagepack paket. Saat menggunakan Gradle, tambahkan baris berikut ke bagian dependenciesfile build.gradle :

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

Saat menggunakan Maven, tambahkan baris berikut di <dependencies> dalam elemen pom.xml file:

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

Panggil withHubProtocol(new MessagePackHubProtocol()) di HubConnectionBuilder.

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

Pertimbangan MessagePack

Ada beberapa masalah yang perlu diperhatikan saat menggunakan Protokol Hub MessagePack.

MessagePack peka huruf besar/kecil

Protokol MessagePack peka huruf besar/kecil. Misalnya, pertimbangkan kelas C# berikut:

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

Saat mengirim dari klien JavaScript, Anda harus menggunakan PascalCased nama properti, karena casing harus sama persis dengan kelas C#. Contohnya:

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

Menggunakan camelCased nama tidak akan terikat dengan benar ke kelas C#. Anda dapat mengatasinya dengan menggunakan Key atribut untuk menentukan nama yang berbeda untuk properti MessagePack. Untuk informasi selengkapnya, lihat dokumentasi MessagePack-CSharp.

DateTime.Kind tidak dipertahankan saat serialisasi/deserialisasi

Protokol MessagePack tidak menyediakan cara untuk mengodekan KindDateTimenilai . Akibatnya, ketika mendeserialisasi tanggal, Protokol MessagePack Hub akan mengonversi ke format UTC jika DateTime.Kind sebaliknya DateTimeKind.Local tidak akan menyentuh waktu dan meneruskannya apa adanya. Jika Anda bekerja dengan DateTime nilai, sebaiknya konversi ke UTC sebelum mengirimkannya. Konversikan dari UTC ke waktu lokal saat Anda menerimanya.

Dukungan MessagePack di lingkungan kompilasi "sebelumnya"

Pustaka MessagePack-CSharp yang digunakan oleh klien .NET dan server menggunakan pembuatan kode untuk mengoptimalkan serialisasi. Akibatnya, ini tidak didukung secara default pada lingkungan yang menggunakan kompilasi "ahead-of-time" (seperti Xamarin iOS atau Unity). Dimungkinkan untuk menggunakan MessagePack di lingkungan ini dengan "pra-pembuatan" kode serializer/deserializer. Untuk informasi selengkapnya, lihat dokumentasi MessagePack-CSharp. Setelah membuat serializer sebelumnya, Anda dapat mendaftarkannya menggunakan delegasi konfigurasi yang diteruskan ke 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);
    });

Pemeriksaan jenis lebih ketat di MessagePack

JSProtokol ON Hub akan melakukan konversi jenis selama deserialisasi. Misalnya, jika objek masuk memiliki nilai properti yang merupakan angka ({ foo: 42 }) tetapi properti pada kelas .NET berjenis string, nilai akan dikonversi. Namun, MessagePack tidak melakukan konversi ini dan akan melemparkan pengecualian yang dapat dilihat di log sisi server (dan di konsol):

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

Untuk informasi selengkapnya tentang batasan ini, lihat Masalah GitHub aspnet/SignalR#2937.

Karakter dan String di Java

Di klien java, char objek akan diserialisasikan sebagai objek satu karakter String . Ini berbeda dengan klien C# dan JavaScript, yang menserialisasikannya sebagai short objek. Spesifikasi MessagePack itu sendiri tidak menentukan perilaku untuk char objek, jadi terserah penulis pustaka untuk menentukan cara menserialisasikannya. Perbedaan perilaku antara klien kami adalah hasil dari pustaka yang kami gunakan untuk implementasi kami.

Sumber Daya Tambahan:

Artikel ini mengasumsikan pembaca terbiasa dengan topik yang dibahas dalam Memulai ASP.NET Core SignalR.

Apa itu MessagePack?

MessagePack adalah format serialisasi biner yang cepat dan ringkas. Ini berguna ketika performa dan bandwidth menjadi perhatian karena menciptakan pesan yang lebih kecil dibandingkan JSdengan AKTIF. Pesan biner tidak dapat dibaca saat melihat jejak jaringan dan log kecuali byte diteruskan melalui parser MessagePack. SignalR memiliki dukungan bawaan untuk format MessagePack dan menyediakan API untuk digunakan klien dan server.

Mengonfigurasi MessagePack di server

Untuk mengaktifkan Protokol Hub MessagePack di server, instal Microsoft.AspNetCore.SignalR.Protocols.MessagePack paket di aplikasi Anda. Dalam metode , Startup.ConfigureServices tambahkan AddMessagePackProtocol ke AddSignalR panggilan untuk mengaktifkan dukungan MessagePack di server.

Catatan

JSAKTIF diaktifkan secara default. Menambahkan MessagePack memungkinkan dukungan untuk JSklien ON dan MessagePack.

services.AddSignalR()
    .AddMessagePackProtocol();

Untuk menyesuaikan bagaimana MessagePack akan memformat data Anda, AddMessagePackProtocol ambil delegasi untuk mengonfigurasi opsi. Dalam delegasi tersebut SerializerOptions , properti dapat digunakan untuk mengonfigurasi opsi serialisasi MessagePack. Untuk informasi selengkapnya tentang cara kerja pemecah masalah, kunjungi pustaka MessagePack di MessagePack-CSharp. Atribut dapat digunakan pada objek yang ingin Anda serialkan untuk menentukan bagaimana atribut tersebut harus ditangani.

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

Peringatan

Kami sangat menyarankan untuk meninjau CVE-2020-5234 dan menerapkan patch yang direkomendasikan. Misalnya, memanggil .WithSecurity(MessagePackSecurity.UntrustedData) saat mengganti SerializerOptions.

Mengonfigurasi MessagePack pada klien

Catatan

JSAKTIF diaktifkan secara default untuk klien yang didukung. Klien hanya dapat mendukung satu protokol. Menambahkan dukungan MessagePack akan menggantikan protokol yang dikonfigurasi sebelumnya.

Klien .NET

Untuk mengaktifkan MessagePack di Klien .NET, instal Microsoft.AspNetCore.SignalR.Protocols.MessagePack paket dan panggil AddMessagePackProtocol di HubConnectionBuilder.

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

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

Catatan

Panggilan ini AddMessagePackProtocol mengambil delegasi untuk mengonfigurasi opsi seperti server.

Klien JavaScript

Dukungan MessagePack untuk klien JavaScript disediakan oleh paket npm @microsoft/signalr-protocol-msgpack . Instal paket dengan menjalankan perintah berikut dalam shell perintah:

npm install @microsoft/signalr-protocol-msgpack

Setelah menginstal paket npm, modul dapat digunakan langsung melalui pemuat modul JavaScript atau diimpor ke browser dengan mereferensikan file berikut:

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

Di browser, msgpack5 pustaka juga harus dirujuk. <script> Gunakan tag untuk membuat referensi. Pustaka dapat ditemukan di node_modules\msgpack5\dist\msgpack5.js.

Catatan

Saat menggunakan <script> elemen , urutannya penting. Jika signalr-protocol-msgpack.js dirujuk sebelum msgpack5.js, kesalahan terjadi saat mencoba terhubung dengan MessagePack. signalr.js juga diperlukan sebelum 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()) Menambahkan ke HubConnectionBuilder akan mengonfigurasi klien untuk menggunakan protokol MessagePack saat menyambungkan ke server.

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

Catatan

Saat ini, tidak ada opsi konfigurasi untuk protokol MessagePack pada klien JavaScript.

Klien Java

Untuk mengaktifkan MessagePack dengan Java, instal com.microsoft.signalr.messagepack paket. Saat menggunakan Gradle, tambahkan baris berikut ke bagian dependenciesfile build.gradle :

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

Saat menggunakan Maven, tambahkan baris berikut di <dependencies> dalam elemen pom.xml file:

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

Panggil withHubProtocol(new MessagePackHubProtocol()) di HubConnectionBuilder.

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

Pertimbangan MessagePack

Ada beberapa masalah yang perlu diperhatikan saat menggunakan Protokol Hub MessagePack.

MessagePack peka huruf besar/kecil

Protokol MessagePack peka huruf besar/kecil. Misalnya, pertimbangkan kelas C# berikut:

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

Saat mengirim dari klien JavaScript, Anda harus menggunakan PascalCased nama properti, karena casing harus sama persis dengan kelas C#. Contohnya:

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

Menggunakan camelCased nama tidak akan terikat dengan benar ke kelas C#. Anda dapat mengatasinya dengan menggunakan Key atribut untuk menentukan nama yang berbeda untuk properti MessagePack. Untuk informasi selengkapnya, lihat dokumentasi MessagePack-CSharp.

DateTime.Kind tidak dipertahankan saat serialisasi/deserialisasi

Protokol MessagePack tidak menyediakan cara untuk mengodekan KindDateTimenilai . Akibatnya, ketika mendeserialisasi tanggal, Protokol MessagePack Hub akan mengonversi ke format UTC jika DateTime.Kind sebaliknya DateTimeKind.Local tidak akan menyentuh waktu dan meneruskannya apa adanya. Jika Anda bekerja dengan DateTime nilai, sebaiknya konversi ke UTC sebelum mengirimkannya. Konversikan dari UTC ke waktu lokal saat Anda menerimanya.

DateTime.MinValue tidak didukung oleh MessagePack di JavaScript

Pustaka msgpack5 yang digunakan oleh SignalR klien JavaScript tidak mendukung timestamp96 jenis di MessagePack. Jenis ini digunakan untuk mengodekan nilai tanggal yang sangat besar (baik sangat awal di masa lalu atau sangat jauh di masa depan). Nilai DateTime.MinValue adalah January 1, 0001, yang harus dikodekan dalam nilai timestamp96 . Karena itu, pengiriman DateTime.MinValue ke klien JavaScript tidak didukung. Ketika DateTime.MinValue diterima oleh klien JavaScript, kesalahan berikut dilemparkan:

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

Biasanya, DateTime.MinValue digunakan untuk mengodekan "hilang" atau null nilai. Jika Anda perlu mengodekan nilai tersebut di MessagePack, gunakan nilai nullable DateTime (DateTime?) atau enkode nilai terpisah bool yang menunjukkan apakah tanggal ada.

Untuk informasi selengkapnya tentang batasan ini, lihat Masalah GitHub aspnet/SignalR#2228.

Dukungan MessagePack di lingkungan kompilasi "sebelumnya"

Pustaka MessagePack-CSharp yang digunakan oleh klien .NET dan server menggunakan pembuatan kode untuk mengoptimalkan serialisasi. Akibatnya, ini tidak didukung secara default pada lingkungan yang menggunakan kompilasi "ahead-of-time" (seperti Xamarin iOS atau Unity). Dimungkinkan untuk menggunakan MessagePack di lingkungan ini dengan "pra-pembuatan" kode serializer/deserializer. Untuk informasi selengkapnya, lihat dokumentasi MessagePack-CSharp. Setelah membuat serializer sebelumnya, Anda dapat mendaftarkannya menggunakan delegasi konfigurasi yang diteruskan ke 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);
    });

Pemeriksaan jenis lebih ketat di MessagePack

JSProtokol ON Hub akan melakukan konversi jenis selama deserialisasi. Misalnya, jika objek masuk memiliki nilai properti yang merupakan angka ({ foo: 42 }) tetapi properti pada kelas .NET berjenis string, nilai akan dikonversi. Namun, MessagePack tidak melakukan konversi ini dan akan melemparkan pengecualian yang dapat dilihat di log sisi server (dan di konsol):

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

Untuk informasi selengkapnya tentang batasan ini, lihat Masalah GitHub aspnet/SignalR#2937.

Karakter dan String di Java

Di klien java, char objek akan diserialisasikan sebagai objek satu karakter String . Ini berbeda dengan klien C# dan JavaScript, yang menserialisasikannya sebagai short objek. Spesifikasi MessagePack itu sendiri tidak menentukan perilaku untuk char objek, jadi terserah penulis pustaka untuk menentukan cara menserialisasikannya. Perbedaan perilaku antara klien kami adalah hasil dari pustaka yang kami gunakan untuk implementasi kami.

Sumber Daya Tambahan:

Artikel ini mengasumsikan pembaca terbiasa dengan topik yang dibahas dalam Memulai ASP.NET Core SignalR.

Apa itu MessagePack?

MessagePack adalah format serialisasi biner yang cepat dan ringkas. Ini berguna ketika performa dan bandwidth menjadi perhatian karena menciptakan pesan yang lebih kecil dibandingkan JSdengan AKTIF. Pesan biner tidak dapat dibaca saat melihat jejak jaringan dan log kecuali byte diteruskan melalui parser MessagePack. SignalR memiliki dukungan bawaan untuk format MessagePack, dan menyediakan API untuk digunakan klien dan server.

Mengonfigurasi MessagePack di server

Untuk mengaktifkan Protokol Hub MessagePack di server, instal Microsoft.AspNetCore.SignalR.Protocols.MessagePack paket di aplikasi Anda. Dalam metode , Startup.ConfigureServices tambahkan AddMessagePackProtocol ke AddSignalR panggilan untuk mengaktifkan dukungan MessagePack di server.

Catatan

JSAKTIF diaktifkan secara default. Menambahkan MessagePack memungkinkan dukungan untuk JSklien ON dan MessagePack.

services.AddSignalR()
    .AddMessagePackProtocol();

Untuk menyesuaikan bagaimana MessagePack akan memformat data Anda, AddMessagePackProtocol ambil delegasi untuk mengonfigurasi opsi. Dalam delegasi tersebut FormatterResolvers , properti dapat digunakan untuk mengonfigurasi opsi serialisasi MessagePack. Untuk informasi selengkapnya tentang cara kerja pemecah masalah, kunjungi pustaka MessagePack di MessagePack-CSharp. Atribut dapat digunakan pada objek yang ingin Anda serialkan untuk menentukan bagaimana atribut tersebut harus ditangani.

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

Peringatan

Kami sangat menyarankan untuk meninjau CVE-2020-5234 dan menerapkan patch yang direkomendasikan. Misalnya, atur MessagePackSecurity.Active properti statis ke MessagePackSecurity.UntrustedData. MessagePackSecurity.Active Mengatur persyaratan menginstal MessagePack versi 1.9.x secara manual. MessagePack Menginstal 1.9.x meningkatkan versi SignalR yang digunakan. MessagePack versi 2.x memperkenalkan perubahan melanggar dan tidak kompatibel dengan SignalR versi 3.1 dan yang lebih lama. Ketika MessagePackSecurity.Active tidak diatur ke MessagePackSecurity.UntrustedData, klien berbahaya dapat menyebabkan penolakan layanan. Atur MessagePackSecurity.Active di Program.Main, seperti yang ditunjukkan dalam kode berikut:

using MessagePack;

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

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

Mengonfigurasi MessagePack pada klien

Catatan

JSAKTIF diaktifkan secara default untuk klien yang didukung. Klien hanya dapat mendukung satu protokol. Menambahkan dukungan MessagePack akan menggantikan protokol yang dikonfigurasi sebelumnya.

Klien .NET

Untuk mengaktifkan MessagePack di Klien .NET, instal Microsoft.AspNetCore.SignalR.Protocols.MessagePack paket dan panggil AddMessagePackProtocol di HubConnectionBuilder.

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

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

Catatan

Panggilan ini AddMessagePackProtocol mengambil delegasi untuk mengonfigurasi opsi seperti server.

Klien JavaScript

Dukungan MessagePack untuk klien JavaScript disediakan oleh paket npm @microsoft/signalr-protocol-msgpack . Instal paket dengan menjalankan perintah berikut dalam shell perintah:

npm install @microsoft/signalr-protocol-msgpack

Setelah menginstal paket npm, modul dapat digunakan langsung melalui pemuat modul JavaScript atau diimpor ke browser dengan mereferensikan file berikut:

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

Di browser, msgpack5 pustaka juga harus dirujuk. <script> Gunakan tag untuk membuat referensi. Pustaka dapat ditemukan di node_modules\msgpack5\dist\msgpack5.js.

Catatan

Saat menggunakan <script> elemen , urutannya penting. Jika signalr-protocol-msgpack.js dirujuk sebelum msgpack5.js, kesalahan terjadi saat mencoba terhubung dengan MessagePack. signalr.js juga diperlukan sebelum 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()) Menambahkan ke HubConnectionBuilder akan mengonfigurasi klien untuk menggunakan protokol MessagePack saat menyambungkan ke server.

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

Catatan

Saat ini, tidak ada opsi konfigurasi untuk protokol MessagePack pada klien JavaScript.

Pertimbangan MessagePack

Ada beberapa masalah yang perlu diperhatikan saat menggunakan Protokol Hub MessagePack.

MessagePack peka huruf besar/kecil

Protokol MessagePack peka huruf besar/kecil. Misalnya, pertimbangkan kelas C# berikut:

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

Saat mengirim dari klien JavaScript, Anda harus menggunakan PascalCased nama properti, karena casing harus sama persis dengan kelas C#. Contohnya:

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

Menggunakan camelCased nama tidak akan terikat dengan benar ke kelas C#. Anda dapat mengatasinya dengan menggunakan Key atribut untuk menentukan nama yang berbeda untuk properti MessagePack. Untuk informasi selengkapnya, lihat dokumentasi MessagePack-CSharp.

DateTime.Kind tidak dipertahankan saat serialisasi/deserialisasi

Protokol MessagePack tidak menyediakan cara untuk mengodekan KindDateTimenilai . Akibatnya, saat mendeserialisasi tanggal, Protokol Hub MessagePack mengasumsikan tanggal masuk dalam format UTC. Jika Anda bekerja dengan DateTime nilai di waktu lokal, sebaiknya konversi ke UTC sebelum mengirimkannya. Konversikan dari UTC ke waktu lokal saat Anda menerimanya.

Untuk informasi selengkapnya tentang batasan ini, lihat Masalah GitHub aspnet/SignalR#2632.

DateTime.MinValue tidak didukung oleh MessagePack di JavaScript

Pustaka msgpack5 yang digunakan oleh SignalR klien JavaScript tidak mendukung timestamp96 jenis di MessagePack. Jenis ini digunakan untuk mengodekan nilai tanggal yang sangat besar (baik sangat awal di masa lalu atau sangat jauh di masa depan). Nilai DateTime.MinValue adalah January 1, 0001, yang harus dikodekan dalam nilai timestamp96 . Karena itu, pengiriman DateTime.MinValue ke klien JavaScript tidak didukung. Ketika DateTime.MinValue diterima oleh klien JavaScript, kesalahan berikut dilemparkan:

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

Biasanya, DateTime.MinValue digunakan untuk mengodekan "hilang" atau null nilai. Jika Anda perlu mengodekan nilai tersebut di MessagePack, gunakan nilai nullable DateTime (DateTime?) atau enkode nilai terpisah bool yang menunjukkan apakah tanggal ada.

Untuk informasi selengkapnya tentang batasan ini, lihat Masalah GitHub aspnet/SignalR#2228.

Dukungan MessagePack di lingkungan kompilasi "sebelumnya"

Pustaka MessagePack-CSharp yang digunakan oleh klien .NET dan server menggunakan pembuatan kode untuk mengoptimalkan serialisasi. Akibatnya, ini tidak didukung secara default pada lingkungan yang menggunakan kompilasi "ahead-of-time" (seperti Xamarin iOS atau Unity). Dimungkinkan untuk menggunakan MessagePack di lingkungan ini dengan "pra-pembuatan" kode serializer/deserializer. Untuk informasi selengkapnya, lihat dokumentasi MessagePack-CSharp. Setelah membuat serializer sebelumnya, Anda dapat mendaftarkannya menggunakan delegasi konfigurasi yang diteruskan ke AddMessagePackProtocol:

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

Pemeriksaan jenis lebih ketat di MessagePack

JSProtokol ON Hub akan melakukan konversi jenis selama deserialisasi. Misalnya, jika objek masuk memiliki nilai properti yang merupakan angka ({ foo: 42 }) tetapi properti pada kelas .NET berjenis string, nilai akan dikonversi. Namun, MessagePack tidak melakukan konversi ini dan akan melemparkan pengecualian yang dapat dilihat di log sisi server (dan di konsol):

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

Untuk informasi selengkapnya tentang batasan ini, lihat Masalah GitHub aspnet/SignalR#2937.

Sumber Daya Tambahan:

Artikel ini mengasumsikan pembaca terbiasa dengan topik yang dibahas dalam Memulai ASP.NET Core SignalR.

Apa itu MessagePack?

MessagePack adalah format serialisasi biner yang cepat dan ringkas. Ini berguna ketika performa dan bandwidth menjadi perhatian karena menciptakan pesan yang lebih kecil dibandingkan JSdengan AKTIF. Pesan biner tidak dapat dibaca saat melihat jejak jaringan dan log kecuali byte diteruskan melalui parser MessagePack. SignalR memiliki dukungan bawaan untuk format MessagePack, dan menyediakan API untuk digunakan klien dan server.

Mengonfigurasi MessagePack di server

Untuk mengaktifkan Protokol Hub MessagePack di server, instal Microsoft.AspNetCore.SignalR.Protocols.MessagePack paket di aplikasi Anda. Dalam metode , Startup.ConfigureServices tambahkan AddMessagePackProtocol ke AddSignalR panggilan untuk mengaktifkan dukungan MessagePack di server.

Catatan

JSAKTIF diaktifkan secara default. Menambahkan MessagePack memungkinkan dukungan untuk JSklien ON dan MessagePack.

services.AddSignalR()
    .AddMessagePackProtocol();

Untuk menyesuaikan bagaimana MessagePack akan memformat data Anda, AddMessagePackProtocol ambil delegasi untuk mengonfigurasi opsi. Dalam delegasi tersebut FormatterResolvers , properti dapat digunakan untuk mengonfigurasi opsi serialisasi MessagePack. Untuk informasi selengkapnya tentang cara kerja pemecah masalah, kunjungi pustaka MessagePack di MessagePack-CSharp. Atribut dapat digunakan pada objek yang ingin Anda serialkan untuk menentukan bagaimana atribut tersebut harus ditangani.

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

Peringatan

Kami sangat menyarankan untuk meninjau CVE-2020-5234 dan menerapkan patch yang direkomendasikan. Misalnya, atur MessagePackSecurity.Active properti statis ke MessagePackSecurity.UntrustedData. MessagePackSecurity.Active Mengatur persyaratan menginstal MessagePack versi 1.9.x secara manual. MessagePack Menginstal 1.9.x meningkatkan versi SignalR yang digunakan. Ketika MessagePackSecurity.Active tidak diatur ke MessagePackSecurity.UntrustedData, klien berbahaya dapat menyebabkan penolakan layanan. Atur MessagePackSecurity.Active di Program.Main, seperti yang ditunjukkan dalam kode berikut:

using MessagePack;

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

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

Mengonfigurasi MessagePack pada klien

Catatan

JSAKTIF diaktifkan secara default untuk klien yang didukung. Klien hanya dapat mendukung satu protokol. Menambahkan dukungan MessagePack akan menggantikan protokol yang dikonfigurasi sebelumnya.

Klien .NET

Untuk mengaktifkan MessagePack di Klien .NET, instal Microsoft.AspNetCore.SignalR.Protocols.MessagePack paket dan panggil AddMessagePackProtocol di HubConnectionBuilder.

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

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

Catatan

Panggilan ini AddMessagePackProtocol mengambil delegasi untuk mengonfigurasi opsi seperti server.

Klien JavaScript

Dukungan MessagePack untuk klien JavaScript disediakan oleh paket npm @aspnet/signalr-protocol-msgpack . Instal paket dengan menjalankan perintah berikut dalam shell perintah:

npm install @aspnet/signalr-protocol-msgpack

Setelah menginstal paket npm, modul dapat digunakan langsung melalui pemuat modul JavaScript atau diimpor ke browser dengan mereferensikan file berikut:

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

Di browser, msgpack5 pustaka juga harus dirujuk. <script> Gunakan tag untuk membuat referensi. Pustaka dapat ditemukan di node_modules\msgpack5\dist\msgpack5.js.

Catatan

Saat menggunakan <script> elemen , urutannya penting. Jika signalr-protocol-msgpack.js dirujuk sebelum msgpack5.js, kesalahan terjadi saat mencoba terhubung dengan MessagePack. signalr.js juga diperlukan sebelum 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()) Menambahkan ke HubConnectionBuilder akan mengonfigurasi klien untuk menggunakan protokol MessagePack saat menyambungkan ke server.

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

Catatan

Saat ini, tidak ada opsi konfigurasi untuk protokol MessagePack pada klien JavaScript.

Pertimbangan MessagePack

Ada beberapa masalah yang perlu diperhatikan saat menggunakan Protokol Hub MessagePack.

MessagePack peka huruf besar/kecil

Protokol MessagePack peka huruf besar/kecil. Misalnya, pertimbangkan kelas C# berikut:

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

Saat mengirim dari klien JavaScript, Anda harus menggunakan PascalCased nama properti, karena casing harus sama persis dengan kelas C#. Contohnya:

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

Menggunakan camelCased nama tidak akan terikat dengan benar ke kelas C#. Anda dapat mengatasinya dengan menggunakan Key atribut untuk menentukan nama yang berbeda untuk properti MessagePack. Untuk informasi selengkapnya, lihat dokumentasi MessagePack-CSharp.

DateTime.Kind tidak dipertahankan saat serialisasi/deserialisasi

Protokol MessagePack tidak menyediakan cara untuk mengodekan KindDateTimenilai . Akibatnya, saat mendeserialisasi tanggal, Protokol Hub MessagePack mengasumsikan tanggal masuk dalam format UTC. Jika Anda bekerja dengan DateTime nilai di waktu lokal, sebaiknya konversi ke UTC sebelum mengirimkannya. Konversikan dari UTC ke waktu lokal saat Anda menerimanya.

Untuk informasi selengkapnya tentang batasan ini, lihat Masalah GitHub aspnet/SignalR#2632.

DateTime.MinValue tidak didukung oleh MessagePack di JavaScript

Pustaka msgpack5 yang digunakan oleh SignalR klien JavaScript tidak mendukung timestamp96 jenis di MessagePack. Jenis ini digunakan untuk mengodekan nilai tanggal yang sangat besar (baik sangat awal di masa lalu atau sangat jauh di masa depan). Nilai DateTime.MinValue yang January 1, 0001 harus dikodekan dalam nilai timestamp96 . Karena itu, pengiriman DateTime.MinValue ke klien JavaScript tidak didukung. Ketika DateTime.MinValue diterima oleh klien JavaScript, kesalahan berikut dilemparkan:

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

Biasanya, DateTime.MinValue digunakan untuk mengodekan "hilang" atau null nilai. Jika Anda perlu mengodekan nilai tersebut di MessagePack, gunakan nilai nullable DateTime (DateTime?) atau enkode nilai terpisah bool yang menunjukkan apakah tanggal ada.

Untuk informasi selengkapnya tentang batasan ini, lihat Masalah GitHub aspnet/SignalR#2228.

Dukungan MessagePack di lingkungan kompilasi "sebelumnya"

Pustaka MessagePack-CSharp yang digunakan oleh klien .NET dan server menggunakan pembuatan kode untuk mengoptimalkan serialisasi. Akibatnya, ini tidak didukung secara default pada lingkungan yang menggunakan kompilasi "ahead-of-time" (seperti Xamarin iOS atau Unity). Dimungkinkan untuk menggunakan MessagePack di lingkungan ini dengan "pra-pembuatan" kode serializer/deserializer. Untuk informasi selengkapnya, lihat dokumentasi MessagePack-CSharp. Setelah membuat serializer sebelumnya, Anda dapat mendaftarkannya menggunakan delegasi konfigurasi yang diteruskan ke AddMessagePackProtocol:

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

Pemeriksaan jenis lebih ketat di MessagePack

JSProtokol ON Hub akan melakukan konversi jenis selama deserialisasi. Misalnya, jika objek masuk memiliki nilai properti yang merupakan angka ({ foo: 42 }) tetapi properti pada kelas .NET berjenis string, nilai akan dikonversi. Namun, MessagePack tidak melakukan konversi ini dan akan melemparkan pengecualian yang dapat dilihat di log sisi server (dan di konsol):

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

Untuk informasi selengkapnya tentang batasan ini, lihat Masalah GitHub aspnet/SignalR#2937.

Sumber Daya Tambahan: