ASP.NET Core için içinde SignalR MessagePack Hub Protokolü kullanma

Bu makalede, okuyucunun ASP.NET Core kullanmaya başlama başlığı altında ele alınan konulara aşina olduğu varsayılır SignalR.

MessagePack nedir?

MessagePack hızlı ve kompakt bir ikili serileştirme biçimidir. Performans ve bant genişliği sorun olduğunda kullanışlıdır çünkü ON değerinden JSdaha küçük iletiler oluşturur. Baytlar bir MessagePack ayrıştırıcısı üzerinden geçirilmediği sürece, ağ izlemelerine ve günlüklerine bakılırken ikili iletiler okunamaz. SignalR MessagePack biçimi için yerleşik desteğe sahiptir ve istemci ve sunucunun kullanması için API'ler sağlar.

Sunucuda MessagePack'i yapılandırma

Sunucuda MessagePack Hub Protokolü'ni etkinleştirmek için paketi uygulamanıza yükleyin Microsoft.AspNetCore.SignalR.Protocols.MessagePack . yönteminde Startup.ConfigureServices , sunucuda MessagePack desteğini etkinleştirmek için çağrısına ekleyin AddMessagePackProtocolAddSignalR .

services.AddSignalR()
    .AddMessagePackProtocol();

Dekont

JSON varsayılan olarak etkindir. MessagePack eklemek hem ON hem de JSMessagePack istemcileri için destek sağlar.

MessagePack'in verileri biçimlendirme biçimini özelleştirmek için seçenekleri AddMessagePackProtocol yapılandırmak üzere bir temsilci alır. Bu temsilcide SerializerOptions özelliği MessagePack serileştirme seçeneklerini yapılandırmak için kullanılır. Çözümleyicilerin nasıl çalıştığı hakkında daha fazla bilgi için MessagePack-CSharp sayfasındaki MessagePack kitaplığını ziyaret edin. Öznitelikler, nasıl işlenmeleri gerektiğini tanımlamak için serileştirmek istediğiniz nesnelerde kullanılabilir.

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

Uyarı

CVE-2020-5234'in gözden geçirilmesini ve önerilen düzeltme eklerinin uygulanmasını kesinlikle öneririz. Örneğin, öğesini değiştirirken çağrısı.WithSecurity(MessagePackSecurity.UntrustedData).SerializerOptions

İstemcide MessagePack'i yapılandırma

Dekont

JSON, desteklenen istemciler için varsayılan olarak etkindir. İstemciler yalnızca tek bir protokolü destekleyebilir. MessagePack desteğinin eklenmesi, önceden yapılandırılmış protokollerin yerini alır.

.NET istemcisi

.NET İstemcisi'nde MessagePack'i etkinleştirmek için paketini yükleyin Microsoft.AspNetCore.SignalR.Protocols.MessagePack ve üzerinde çağrısında AddMessagePackProtocol bulunur HubConnectionBuilder.

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

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

Dekont

Bu AddMessagePackProtocol çağrı, sunucu gibi seçenekleri yapılandırmak için bir temsilci alır.

JavaScript istemcisi

JavaScript istemcisi için MessagePack desteği @microsoft/signalr-protocol-msgpack npm paketi tarafından sağlanır. Bir komut kabuğunda aşağıdaki komutu yürüterek paketi yükleyin:

npm install @microsoft/signalr-protocol-msgpack

npm paketini yükledikten sonra, modül bir JavaScript modül yükleyicisi aracılığıyla doğrudan kullanılabilir veya aşağıdaki dosyaya başvurarak tarayıcıya aktarılabilir:

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

Aşağıdaki gerekli javaScript dosyalarına aşağıda gösterilen sırayla başvurulmalıdır:

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

öğesine HubConnectionBuilder eklemek.withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol()), istemciyi bir sunucuya bağlanırken MessagePack protokolunu kullanacak şekilde yapılandırıyor.

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

Şu anda JavaScript istemcisinde MessagePack protokolü için yapılandırma seçeneği yoktur.

Java istemcisi

Java ile MessagePack'i etkinleştirmek için paketi yükleyin com.microsoft.signalr.messagepack . Gradle kullanırken build.gradle dosyasının dependenciesbölümüne aşağıdaki satırı ekleyin:

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

Maven kullanırken, dosyanın öğesinin <dependencies>pom.xml içine aşağıdaki satırları ekleyin:

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

üzerinde HubConnectionBuilderarayınwithHubProtocol(new MessagePackHubProtocol()).

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

MessagePack ile ilgili dikkat edilmesi gerekenler

MessagePack Hub Protokolü kullanılırken dikkat edilmesi gereken birkaç sorun vardır.

MessagePack büyük/küçük harfe duyarlıdır

MessagePack protokolü büyük/küçük harfe duyarlıdır. Örneğin, aşağıdaki C# sınıfını göz önünde bulundurun:

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

JavaScript istemcisinden gönderirken, büyük/küçük harf kullanımının C# sınıfıyla tam olarak eşleşmesi gerektiğinden özellik adlarını kullanmanız PascalCased gerekir. Örnek:

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

Adların kullanılması camelCased C# sınıfına düzgün bağlanmaz. MessagePack özelliği için farklı bir ad belirtmek üzere özniteliğini kullanarak Key bu sorunu geçici olarak aşabilirsiniz. Daha fazla bilgi için MessagePack-CSharp belgelerine bakın.

Seri durumdan çıkarılırken/seri durumdan çıkarılırken DateTime.Kind korunmuyor

MessagePack protokolü değerini kodlamak Kind için bir DateTimeyol sağlamaz. Sonuç olarak, bir tarihi seri durumdan çıkarırken, aksi takdirde DateTime.KindDateTimeKind.Local MessagePack Hub Protokolü saate dokunmaz ve olduğu gibi geçirmezse UTC biçimine dönüştürülür. Değerlerle DateTime çalışıyorsanız, bunları göndermeden önce UTC'ye dönüştürmenizi öneririz. Bunları aldığınızda UTC'den yerel saate dönüştürün.

"Önceden" derleme ortamında MessagePack desteği

.NET istemcisi ve sunucusu tarafından kullanılan MessagePack-CSharp kitaplığı, serileştirmeyi iyileştirmek için kod oluşturmayı kullanır. Sonuç olarak, "zamanından önce" derleme kullanan ortamlarda (Xamarin iOS veya Unity gibi) varsayılan olarak desteklenmez. MessagePack'i bu ortamlarda seri hale getirici/seri durumdan çıkarıcı kodunu "önceden oluşturarak" kullanmak mümkündür. Daha fazla bilgi için MessagePack-CSharp belgelerine bakın. Seri hale getiricileri önceden oluşturduktan sonra, öğesine geçirilen AddMessagePackProtocolyapılandırma temsilcisini kullanarak bunları kaydedebilirsiniz:

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'te tür denetimleri daha katıdır

JSON Hub Protokolü seri durumdan çıkarma sırasında tür dönüştürmeleri gerçekleştirir. Örneğin, gelen nesnenin bir sayı ({ foo: 42 }) olan bir özellik değeri varsa, ancak .NET sınıfındaki özellik türündeyse string, değer dönüştürülür. Ancak, MessagePack bu dönüştürmeyi gerçekleştirmez ve sunucu tarafı günlüklerinde (ve konsolunda) görülebilecek bir özel durum oluşturur:

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

Bu sınırlama hakkında daha fazla bilgi için bkz. GitHub sorunu aspnet/SignalR#2937.

Java'da Karakterler ve Dizeler

Java istemcisinde nesneler tek char karakterli String nesneler olarak serileştirilir. Bu, C# ve JavaScript istemcisinin aksinedir ve bunları nesne olarak short serileştirir. MessagePack belirtiminin kendisi nesneler için char davranış tanımlamaz, bu nedenle bunların nasıl serileştirileceğini belirlemek kitaplık yazarına bağlıdır. Müşterilerimiz arasındaki davranış farkı, uygulamalarımız için kullandığımız kitaplıkların bir sonucudur.

Ek kaynaklar

Bu makalede, okuyucunun ASP.NET Core kullanmaya başlama başlığı altında ele alınan konulara aşina olduğu varsayılır SignalR.

MessagePack nedir?

MessagePack hızlı ve kompakt bir ikili serileştirme biçimidir. On ile karşılaştırıldığında JSdaha küçük iletiler oluşturduğundan performans ve bant genişliği önemli olduğunda kullanışlıdır. Baytlar bir MessagePack ayrıştırıcısı üzerinden geçirilmediği sürece, ağ izlemelerine ve günlüklerine bakılırken ikili iletiler okunamaz. SignalR MessagePack biçimi için yerleşik desteğe sahiptir ve istemci ve sunucunun kullanması için API'ler sağlar.

Sunucuda MessagePack'i yapılandırma

Sunucuda MessagePack Hub Protokolü'ni etkinleştirmek için paketi uygulamanıza yükleyin Microsoft.AspNetCore.SignalR.Protocols.MessagePack . yönteminde Startup.ConfigureServices , sunucuda MessagePack desteğini etkinleştirmek için çağrısına ekleyin AddMessagePackProtocolAddSignalR .

Dekont

JSON varsayılan olarak etkindir. MessagePack eklemek hem ON hem de JSMessagePack istemcileri için destek sağlar.

services.AddSignalR()
    .AddMessagePackProtocol();

MessagePack'in verilerinizi nasıl biçimlendireceğini özelleştirmek için seçenekleri AddMessagePackProtocol yapılandırmak üzere bir temsilci alır. Bu temsilcide SerializerOptions özelliği MessagePack serileştirme seçeneklerini yapılandırmak için kullanılabilir. Çözümleyicilerin nasıl çalıştığı hakkında daha fazla bilgi için MessagePack-CSharp sayfasındaki MessagePack kitaplığını ziyaret edin. Öznitelikler, nasıl işlenmeleri gerektiğini tanımlamak için serileştirmek istediğiniz nesnelerde kullanılabilir.

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

Uyarı

CVE-2020-5234'in gözden geçirilmesini ve önerilen düzeltme eklerinin uygulanmasını kesinlikle öneririz. Örneğin, öğesini değiştirirken çağrısı.WithSecurity(MessagePackSecurity.UntrustedData).SerializerOptions

İstemcide MessagePack'i yapılandırma

Dekont

JSON, desteklenen istemciler için varsayılan olarak etkindir. İstemciler yalnızca tek bir protokolü destekleyebilir. MessagePack desteğinin eklenmesi, önceden yapılandırılmış protokollerin yerini alır.

.NET istemcisi

.NET İstemcisi'nde MessagePack'i etkinleştirmek için paketini yükleyin Microsoft.AspNetCore.SignalR.Protocols.MessagePack ve üzerinde çağrısında AddMessagePackProtocol bulunur HubConnectionBuilder.

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

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

Dekont

Bu AddMessagePackProtocol çağrı, sunucu gibi seçenekleri yapılandırmak için bir temsilci alır.

JavaScript istemcisi

JavaScript istemcisi için MessagePack desteği @microsoft/signalr-protocol-msgpack npm paketi tarafından sağlanır. Bir komut kabuğunda aşağıdaki komutu yürüterek paketi yükleyin:

npm install @microsoft/signalr-protocol-msgpack

npm paketini yükledikten sonra, modül bir JavaScript modül yükleyicisi aracılığıyla doğrudan kullanılabilir veya aşağıdaki dosyaya başvurarak tarayıcıya aktarılabilir:

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

Tarayıcıda kitaplığa msgpack5 da başvurulmalıdır. <script> Başvuru oluşturmak için etiket kullanın. Kitaplık node_modules\msgpack5\dist\msgpack5.js konumunda bulunabilir.

Dekont

öğesi kullanılırken <script> sıra önemlidir. öncesinde msgpack5.jsbaşvurulursasignalr-protocol-msgpack.js, MessagePack ile bağlanmaya çalışılırken bir hata oluşur. signalr.js , öncesinde signalr-protocol-msgpack.jsde gereklidir.

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

öğesine HubConnectionBuilder eklemek.withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol()), istemciyi bir sunucuya bağlanırken MessagePack protokolunu kullanacak şekilde yapılandıracaktır.

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

Dekont

Şu anda JavaScript istemcisinde MessagePack protokolü için yapılandırma seçeneği yoktur.

Java istemcisi

Java ile MessagePack'i etkinleştirmek için paketi yükleyin com.microsoft.signalr.messagepack . Gradle kullanırken build.gradle dosyasının dependenciesbölümüne aşağıdaki satırı ekleyin:

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

Maven kullanırken, dosyanın öğesinin <dependencies>pom.xml içine aşağıdaki satırları ekleyin:

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

üzerinde HubConnectionBuilderarayınwithHubProtocol(new MessagePackHubProtocol()).

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

MessagePack ile ilgili dikkat edilmesi gerekenler

MessagePack Hub Protokolü kullanılırken dikkat edilmesi gereken birkaç sorun vardır.

MessagePack büyük/küçük harfe duyarlıdır

MessagePack protokolü büyük/küçük harfe duyarlıdır. Örneğin, aşağıdaki C# sınıfını göz önünde bulundurun:

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

JavaScript istemcisinden gönderirken, büyük/küçük harf kullanımının C# sınıfıyla tam olarak eşleşmesi gerektiğinden özellik adlarını kullanmanız PascalCased gerekir. Örnek:

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

Adların kullanılması camelCased C# sınıfına düzgün bağlanmaz. MessagePack özelliği için farklı bir ad belirtmek üzere özniteliğini kullanarak Key bu sorunu geçici olarak aşabilirsiniz. Daha fazla bilgi için MessagePack-CSharp belgelerine bakın.

Seri durumdan çıkarılırken/seri durumdan çıkarılırken DateTime.Kind korunmuyor

MessagePack protokolü değerini kodlamak Kind için bir DateTimeyol sağlamaz. Sonuç olarak, bir tarihi seri durumdan çıkarırken, aksi takdirde DateTime.KindDateTimeKind.Local MessagePack Hub Protokolü saate dokunmaz ve olduğu gibi geçirmezse UTC biçimine dönüştürülür. Değerlerle DateTime çalışıyorsanız, bunları göndermeden önce UTC'ye dönüştürmenizi öneririz. Bunları aldığınızda UTC'den yerel saate dönüştürün.

DateTime.MinValue, JavaScript'te MessagePack tarafından desteklenmiyor

JavaScript istemcisi tarafından SignalR kullanılan msgpack5 kitaplığı MessagePack'teki türü desteklemeztimestamp96. Bu tür, çok büyük tarih değerlerini (geçmişte çok erken veya gelecekte çok uzak) kodlamak için kullanılır. değeri, bir timestamp96 değerde DateTime.MinValue kodlanması gereken değeridirJanuary 1, 0001. Bu nedenle JavaScript istemcisine gönderme DateTime.MinValue desteklenmez. DateTime.MinValue JavaScript istemcisi tarafından alındığında aşağıdaki hata oluşur:

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

Genellikle bir DateTime.MinValue "eksik" veya null değeri kodlamak için kullanılır. MessagePack'te bu değeri kodlamanız gerekiyorsa, null atanabilir DateTime bir değer (DateTime?) kullanın veya tarihin mevcut olup olmadığını belirten ayrı bool bir değeri kodlayın.

Bu sınırlama hakkında daha fazla bilgi için bkz. GitHub sorunu aspnet/SignalR#2228.

"Önceden" derleme ortamında MessagePack desteği

.NET istemcisi ve sunucusu tarafından kullanılan MessagePack-CSharp kitaplığı, serileştirmeyi iyileştirmek için kod oluşturmayı kullanır. Sonuç olarak, "zamanından önce" derleme kullanan ortamlarda (Xamarin iOS veya Unity gibi) varsayılan olarak desteklenmez. MessagePack'i bu ortamlarda seri hale getirici/seri durumdan çıkarıcı kodunu "önceden oluşturarak" kullanmak mümkündür. Daha fazla bilgi için MessagePack-CSharp belgelerine bakın. Seri hale getiricileri önceden oluşturduktan sonra, öğesine geçirilen AddMessagePackProtocolyapılandırma temsilcisini kullanarak bunları kaydedebilirsiniz:

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'te tür denetimleri daha katıdır

JSON Hub Protokolü seri durumdan çıkarma sırasında tür dönüştürmeleri gerçekleştirir. Örneğin, gelen nesnenin bir sayı ({ foo: 42 }) olan bir özellik değeri varsa, ancak .NET sınıfındaki özellik türündeyse string, değer dönüştürülür. Ancak, MessagePack bu dönüştürmeyi gerçekleştirmez ve sunucu tarafı günlüklerinde (ve konsolunda) görülebilecek bir özel durum oluşturur:

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

Bu sınırlama hakkında daha fazla bilgi için bkz. GitHub sorunu aspnet/SignalR#2937.

Java'da Karakterler ve Dizeler

Java istemcisinde nesneler tek char karakterli String nesneler olarak serileştirilir. Bu, C# ve JavaScript istemcisinin aksinedir ve bunları nesne olarak short serileştirir. MessagePack belirtiminin kendisi nesneler için char davranış tanımlamaz, bu nedenle bunların nasıl serileştirileceğini belirlemek kitaplık yazarına bağlıdır. Müşterilerimiz arasındaki davranış farkı, uygulamalarımız için kullandığımız kitaplıkların bir sonucudur.

Ek kaynaklar

Bu makalede, okuyucunun ASP.NET Core kullanmaya başlama başlığı altında ele alınan konulara aşina olduğu varsayılır SignalR.

MessagePack nedir?

MessagePack hızlı ve kompakt bir ikili serileştirme biçimidir. On ile karşılaştırıldığında JSdaha küçük iletiler oluşturduğundan performans ve bant genişliği önemli olduğunda kullanışlıdır. Baytlar bir MessagePack ayrıştırıcısı üzerinden geçirilmediği sürece, ağ izlemelerine ve günlüklerine bakılırken ikili iletiler okunamaz. SignalR , MessagePack biçimi için yerleşik desteğe sahiptir ve istemci ve sunucunun kullanması için API'ler sağlar.

Sunucuda MessagePack'i yapılandırma

Sunucuda MessagePack Hub Protokolü'ni etkinleştirmek için paketi uygulamanıza yükleyin Microsoft.AspNetCore.SignalR.Protocols.MessagePack . yönteminde Startup.ConfigureServices , sunucuda MessagePack desteğini etkinleştirmek için çağrısına ekleyin AddMessagePackProtocolAddSignalR .

Dekont

JSON varsayılan olarak etkindir. MessagePack eklemek hem ON hem de JSMessagePack istemcileri için destek sağlar.

services.AddSignalR()
    .AddMessagePackProtocol();

MessagePack'in verilerinizi nasıl biçimlendireceğini özelleştirmek için seçenekleri AddMessagePackProtocol yapılandırmak üzere bir temsilci alır. Bu temsilcide FormatterResolvers özelliği MessagePack serileştirme seçeneklerini yapılandırmak için kullanılabilir. Çözümleyicilerin nasıl çalıştığı hakkında daha fazla bilgi için MessagePack-CSharp sayfasındaki MessagePack kitaplığını ziyaret edin. Öznitelikler, nasıl işlenmeleri gerektiğini tanımlamak için serileştirmek istediğiniz nesnelerde kullanılabilir.

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

Uyarı

CVE-2020-5234'in gözden geçirilmesini ve önerilen düzeltme eklerinin uygulanmasını kesinlikle öneririz. Örneğin, statik özelliği olarak MessagePackSecurity.UntrustedDataayarlayınMessagePackSecurity.Active. ayarının MessagePackSecurity.Active ayarlanması için MessagePack'in 1.9.x sürümünün el ile yüklenmesi gerekir. 1.9.x'i yüklemek MessagePack , sürümün kullandığı sürümü SignalR yükselter. MessagePack sürüm 2.x, hataya neden olan değişiklikler yaptı ve 3.1 ve önceki sürümlerle SignalR uyumlu değil. MessagePackSecurity.Active olarak ayarlı MessagePackSecurity.UntrustedDataolmadığında, kötü amaçlı bir istemci hizmet reddine neden olabilir. Program.Mainiçinde, aşağıdaki kodda gösterildiği gibi ayarlayınMessagePackSecurity.Active:

using MessagePack;

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

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

İstemcide MessagePack'i yapılandırma

Dekont

JSON, desteklenen istemciler için varsayılan olarak etkindir. İstemciler yalnızca tek bir protokolü destekleyebilir. MessagePack desteğinin eklenmesi, önceden yapılandırılmış protokollerin yerini alır.

.NET istemcisi

.NET İstemcisi'nde MessagePack'i etkinleştirmek için paketini yükleyin Microsoft.AspNetCore.SignalR.Protocols.MessagePack ve üzerinde çağrısında AddMessagePackProtocol bulunur HubConnectionBuilder.

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

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

Dekont

Bu AddMessagePackProtocol çağrı, sunucu gibi seçenekleri yapılandırmak için bir temsilci alır.

JavaScript istemcisi

JavaScript istemcisi için MessagePack desteği @microsoft/signalr-protocol-msgpack npm paketi tarafından sağlanır. Bir komut kabuğunda aşağıdaki komutu yürüterek paketi yükleyin:

npm install @microsoft/signalr-protocol-msgpack

npm paketini yükledikten sonra, modül bir JavaScript modül yükleyicisi aracılığıyla doğrudan kullanılabilir veya aşağıdaki dosyaya başvurarak tarayıcıya aktarılabilir:

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

Tarayıcıda kitaplığa msgpack5 da başvurulmalıdır. <script> Başvuru oluşturmak için etiket kullanın. Kitaplık node_modules\msgpack5\dist\msgpack5.js konumunda bulunabilir.

Dekont

öğesi kullanılırken <script> sıra önemlidir. öncesinde msgpack5.jsbaşvurulursasignalr-protocol-msgpack.js, MessagePack ile bağlanmaya çalışılırken bir hata oluşur. signalr.js , öncesinde signalr-protocol-msgpack.jsde gereklidir.

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

öğesine HubConnectionBuilder eklemek.withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol()), istemciyi bir sunucuya bağlanırken MessagePack protokolunu kullanacak şekilde yapılandıracaktır.

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

Dekont

Şu anda JavaScript istemcisinde MessagePack protokolü için yapılandırma seçeneği yoktur.

MessagePack ile ilgili dikkat edilmesi gerekenler

MessagePack Hub Protokolü kullanılırken dikkat edilmesi gereken birkaç sorun vardır.

MessagePack büyük/küçük harfe duyarlıdır

MessagePack protokolü büyük/küçük harfe duyarlıdır. Örneğin, aşağıdaki C# sınıfını göz önünde bulundurun:

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

JavaScript istemcisinden gönderirken, büyük/küçük harf kullanımının C# sınıfıyla tam olarak eşleşmesi gerektiğinden özellik adlarını kullanmanız PascalCased gerekir. Örnek:

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

Adların kullanılması camelCased C# sınıfına düzgün bağlanmaz. MessagePack özelliği için farklı bir ad belirtmek üzere özniteliğini kullanarak Key bu sorunu geçici olarak aşabilirsiniz. Daha fazla bilgi için MessagePack-CSharp belgelerine bakın.

Seri durumdan çıkarılırken/seri durumdan çıkarılırken DateTime.Kind korunmuyor

MessagePack protokolü değerini kodlamak Kind için bir DateTimeyol sağlamaz. Sonuç olarak, bir tarihi seri durumdan çıkarırken MessagePack Hub Protokolü gelen tarihin UTC biçiminde olduğunu varsayar. Yerel saat değerleriyle DateTime çalışıyorsanız, bunları göndermeden önce UTC'ye dönüştürmenizi öneririz. Bunları aldığınızda UTC'den yerel saate dönüştürün.

Bu sınırlama hakkında daha fazla bilgi için bkz. GitHub sorunu aspnet/SignalR#2632.

DateTime.MinValue, JavaScript'te MessagePack tarafından desteklenmiyor

JavaScript istemcisi tarafından SignalR kullanılan msgpack5 kitaplığı MessagePack'teki türü desteklemeztimestamp96. Bu tür, çok büyük tarih değerlerini (geçmişte çok erken veya gelecekte çok uzak) kodlamak için kullanılır. değeri, bir timestamp96 değerde DateTime.MinValue kodlanması gereken değeridirJanuary 1, 0001. Bu nedenle JavaScript istemcisine gönderme DateTime.MinValue desteklenmez. DateTime.MinValue JavaScript istemcisi tarafından alındığında aşağıdaki hata oluşur:

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

Genellikle bir DateTime.MinValue "eksik" veya null değeri kodlamak için kullanılır. MessagePack'te bu değeri kodlamanız gerekiyorsa, null atanabilir DateTime bir değer (DateTime?) kullanın veya tarihin mevcut olup olmadığını belirten ayrı bool bir değeri kodlayın.

Bu sınırlama hakkında daha fazla bilgi için bkz. GitHub sorunu aspnet/SignalR#2228.

"Önceden" derleme ortamında MessagePack desteği

.NET istemcisi ve sunucusu tarafından kullanılan MessagePack-CSharp kitaplığı, serileştirmeyi iyileştirmek için kod oluşturmayı kullanır. Sonuç olarak, "zamanından önce" derleme kullanan ortamlarda (Xamarin iOS veya Unity gibi) varsayılan olarak desteklenmez. MessagePack'i bu ortamlarda seri hale getirici/seri durumdan çıkarıcı kodunu "önceden oluşturarak" kullanmak mümkündür. Daha fazla bilgi için MessagePack-CSharp belgelerine bakın. Seri hale getiricileri önceden oluşturduktan sonra, öğesine geçirilen AddMessagePackProtocolyapılandırma temsilcisini kullanarak bunları kaydedebilirsiniz:

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

MessagePack'te tür denetimleri daha katıdır

JSON Hub Protokolü seri durumdan çıkarma sırasında tür dönüştürmeleri gerçekleştirir. Örneğin, gelen nesnenin bir sayı ({ foo: 42 }) olan bir özellik değeri varsa, ancak .NET sınıfındaki özellik türündeyse string, değer dönüştürülür. Ancak, MessagePack bu dönüştürmeyi gerçekleştirmez ve sunucu tarafı günlüklerinde (ve konsolunda) görülebilecek bir özel durum oluşturur:

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

Bu sınırlama hakkında daha fazla bilgi için bkz. GitHub sorunu aspnet/SignalR#2937.

Ek kaynaklar

Bu makalede, okuyucunun ASP.NET Core kullanmaya başlama başlığı altında ele alınan konulara aşina olduğu varsayılır SignalR.

MessagePack nedir?

MessagePack hızlı ve kompakt bir ikili serileştirme biçimidir. On ile karşılaştırıldığında JSdaha küçük iletiler oluşturduğundan performans ve bant genişliği önemli olduğunda kullanışlıdır. Baytlar bir MessagePack ayrıştırıcısı üzerinden geçirilmediği sürece, ağ izlemelerine ve günlüklerine bakılırken ikili iletiler okunamaz. SignalR , MessagePack biçimi için yerleşik desteğe sahiptir ve istemci ve sunucunun kullanması için API'ler sağlar.

Sunucuda MessagePack'i yapılandırma

Sunucuda MessagePack Hub Protokolü'ni etkinleştirmek için paketi uygulamanıza yükleyin Microsoft.AspNetCore.SignalR.Protocols.MessagePack . yönteminde Startup.ConfigureServices , sunucuda MessagePack desteğini etkinleştirmek için çağrısına ekleyin AddMessagePackProtocolAddSignalR .

Dekont

JSON varsayılan olarak etkindir. MessagePack eklemek hem ON hem de JSMessagePack istemcileri için destek sağlar.

services.AddSignalR()
    .AddMessagePackProtocol();

MessagePack'in verilerinizi nasıl biçimlendireceğini özelleştirmek için seçenekleri AddMessagePackProtocol yapılandırmak üzere bir temsilci alır. Bu temsilcide FormatterResolvers özelliği MessagePack serileştirme seçeneklerini yapılandırmak için kullanılabilir. Çözümleyicilerin nasıl çalıştığı hakkında daha fazla bilgi için MessagePack-CSharp sayfasındaki MessagePack kitaplığını ziyaret edin. Öznitelikler, nasıl işlenmeleri gerektiğini tanımlamak için serileştirmek istediğiniz nesnelerde kullanılabilir.

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

Uyarı

CVE-2020-5234'in gözden geçirilmesini ve önerilen düzeltme eklerinin uygulanmasını kesinlikle öneririz. Örneğin, statik özelliği olarak MessagePackSecurity.UntrustedDataayarlayınMessagePackSecurity.Active. ayarının MessagePackSecurity.Active ayarlanması için MessagePack'in 1.9.x sürümünün el ile yüklenmesi gerekir. 1.9.x'i yüklemek MessagePack , sürümün kullandığı sürümü SignalR yükselter. olarak ayarlanmadığında MessagePackSecurity.ActiveMessagePackSecurity.UntrustedDatakötü amaçlı bir istemci hizmet reddine neden olabilir. Program.Mainiçinde, aşağıdaki kodda gösterildiği gibi ayarlayınMessagePackSecurity.Active:

using MessagePack;

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

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

İstemcide MessagePack'i yapılandırma

Dekont

JSON, desteklenen istemciler için varsayılan olarak etkindir. İstemciler yalnızca tek bir protokolü destekleyebilir. MessagePack desteğinin eklenmesi, önceden yapılandırılmış protokollerin yerini alır.

.NET istemcisi

.NET İstemcisi'nde MessagePack'i etkinleştirmek için paketini yükleyin Microsoft.AspNetCore.SignalR.Protocols.MessagePack ve üzerinde çağrısında AddMessagePackProtocol bulunur HubConnectionBuilder.

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

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

Dekont

Bu AddMessagePackProtocol çağrı, sunucu gibi seçenekleri yapılandırmak için bir temsilci alır.

JavaScript istemcisi

JavaScript istemcisi için MessagePack desteği @aspnet/signalr-protocol-msgpack npm paketi tarafından sağlanır. Bir komut kabuğunda aşağıdaki komutu yürüterek paketi yükleyin:

npm install @aspnet/signalr-protocol-msgpack

npm paketini yükledikten sonra, modül bir JavaScript modül yükleyicisi aracılığıyla doğrudan kullanılabilir veya aşağıdaki dosyaya başvurarak tarayıcıya aktarılabilir:

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

Tarayıcıda kitaplığa msgpack5 da başvurulmalıdır. <script> Başvuru oluşturmak için etiket kullanın. Kitaplık node_modules\msgpack5\dist\msgpack5.js konumunda bulunabilir.

Dekont

öğesi kullanılırken <script> sıra önemlidir. öncesinde msgpack5.jsbaşvurulursasignalr-protocol-msgpack.js, MessagePack ile bağlanmaya çalışılırken bir hata oluşur. signalr.js , öncesinde signalr-protocol-msgpack.jsde gereklidir.

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

öğesine HubConnectionBuilder eklemek.withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol()), istemciyi bir sunucuya bağlanırken MessagePack protokolunu kullanacak şekilde yapılandıracaktır.

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

Dekont

Şu anda JavaScript istemcisinde MessagePack protokolü için yapılandırma seçeneği yoktur.

MessagePack ile ilgili dikkat edilmesi gerekenler

MessagePack Hub Protokolü kullanılırken dikkat edilmesi gereken birkaç sorun vardır.

MessagePack büyük/küçük harfe duyarlıdır

MessagePack protokolü büyük/küçük harfe duyarlıdır. Örneğin, aşağıdaki C# sınıfını göz önünde bulundurun:

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

JavaScript istemcisinden gönderirken, büyük/küçük harf kullanımının C# sınıfıyla tam olarak eşleşmesi gerektiğinden özellik adlarını kullanmanız PascalCased gerekir. Örnek:

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

Adların kullanılması camelCased C# sınıfına düzgün bağlanmaz. MessagePack özelliği için farklı bir ad belirtmek üzere özniteliğini kullanarak Key bu sorunu geçici olarak aşabilirsiniz. Daha fazla bilgi için MessagePack-CSharp belgelerine bakın.

Seri durumdan çıkarılırken/seri durumdan çıkarılırken DateTime.Kind korunmuyor

MessagePack protokolü değerini kodlamak Kind için bir DateTimeyol sağlamaz. Sonuç olarak, bir tarihi seri durumdan çıkarırken MessagePack Hub Protokolü gelen tarihin UTC biçiminde olduğunu varsayar. Yerel saat değerleriyle DateTime çalışıyorsanız, bunları göndermeden önce UTC'ye dönüştürmenizi öneririz. Bunları aldığınızda UTC'den yerel saate dönüştürün.

Bu sınırlama hakkında daha fazla bilgi için bkz. GitHub sorunu aspnet/SignalR#2632.

DateTime.MinValue, JavaScript'te MessagePack tarafından desteklenmiyor

JavaScript istemcisi tarafından SignalR kullanılan msgpack5 kitaplığı MessagePack'teki türü desteklemeztimestamp96. Bu tür, çok büyük tarih değerlerini (geçmişte çok erken veya gelecekte çok uzak) kodlamak için kullanılır. değeri, bir timestamp96 değerde DateTime.MinValue kodlanması gereken değerdirJanuary 1, 0001. Bu nedenle JavaScript istemcisine gönderme DateTime.MinValue desteklenmez. DateTime.MinValue JavaScript istemcisi tarafından alındığında aşağıdaki hata oluşur:

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

Genellikle bir DateTime.MinValue "eksik" veya null değeri kodlamak için kullanılır. MessagePack'te bu değeri kodlamanız gerekiyorsa, null atanabilir DateTime bir değer (DateTime?) kullanın veya tarihin mevcut olup olmadığını belirten ayrı bool bir değeri kodlayın.

Bu sınırlama hakkında daha fazla bilgi için bkz. GitHub sorunu aspnet/SignalR#2228.

"Önceden" derleme ortamında MessagePack desteği

.NET istemcisi ve sunucusu tarafından kullanılan MessagePack-CSharp kitaplığı, serileştirmeyi iyileştirmek için kod oluşturmayı kullanır. Sonuç olarak, "zamanından önce" derleme kullanan ortamlarda (Xamarin iOS veya Unity gibi) varsayılan olarak desteklenmez. MessagePack'i bu ortamlarda seri hale getirici/seri durumdan çıkarıcı kodunu "önceden oluşturarak" kullanmak mümkündür. Daha fazla bilgi için MessagePack-CSharp belgelerine bakın. Seri hale getiricileri önceden oluşturduktan sonra, öğesine geçirilen AddMessagePackProtocolyapılandırma temsilcisini kullanarak bunları kaydedebilirsiniz:

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

MessagePack'te tür denetimleri daha katıdır

JSON Hub Protokolü seri durumdan çıkarma sırasında tür dönüştürmeleri gerçekleştirir. Örneğin, gelen nesnenin bir sayı ({ foo: 42 }) olan bir özellik değeri varsa, ancak .NET sınıfındaki özellik türündeyse string, değer dönüştürülür. Ancak, MessagePack bu dönüştürmeyi gerçekleştirmez ve sunucu tarafı günlüklerinde (ve konsolunda) görülebilecek bir özel durum oluşturur:

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

Bu sınırlama hakkında daha fazla bilgi için bkz. GitHub sorunu aspnet/SignalR#2937.

Ek kaynaklar