Использование протокола MessagePack Hub для SignalR ASP.NET Core
В этой статье предполагается, что читатель знаком с темами, описанными в статье "Начало работы с ASP.NET Core SignalR".
Что такое MessagePack?
MessagePack — это быстрый и компактный формат двоичной сериализации. Это полезно, если производительность и пропускная способность являются проблемой, так как она создает небольшие сообщения, чем JSON. Двоичные сообщения недоступны при просмотре сетевых трассировок и журналов, если только байты не передаются через средство синтаксического анализа MessagePack. SignalR имеет встроенную поддержку формата MessagePack и предоставляет API-интерфейсы для использования клиента и сервера.
Настройка MessagePack на сервере
Чтобы включить протокол MessagePack Hub на сервере, установите Microsoft.AspNetCore.SignalR.Protocols.MessagePack
пакет в приложении. В методе Startup.ConfigureServices
добавьте AddMessagePackProtocol
вызов AddSignalR
, чтобы включить поддержку MessagePack на сервере.
services.AddSignalR()
.AddMessagePackProtocol();
Примечание.
JSON включен по умолчанию. Добавление MessagePack обеспечивает поддержку клиентов JSON и MessagePack.
Чтобы настроить способ форматирования данных MessagePack, AddMessagePackProtocol
принимает делегат для настройки параметров. В этом делегате SerializerOptions
свойство используется для настройки параметров сериализации MessagePack. Дополнительные сведения о работе сопоставителей см. в библиотеке MessagePack-CSharp. Атрибуты можно использовать для объектов, которые необходимо сериализовать, чтобы определить способ их обработки.
services.AddSignalR()
.AddMessagePackProtocol(options =>
{
options.SerializerOptions = MessagePackSerializerOptions.Standard
.WithResolver(new CustomResolver())
.WithSecurity(MessagePackSecurity.UntrustedData);
});
Предупреждение
Настоятельно рекомендуется просматривать CVE-2020-5234 и применять рекомендуемые исправления. Например, вызов .WithSecurity(MessagePackSecurity.UntrustedData)
при замене SerializerOptions
.
Настройка MessagePack на клиенте
Примечание.
JSON включен по умолчанию для поддерживаемых клиентов. Клиенты могут поддерживать только один протокол. Добавление поддержки MessagePack заменяет все ранее настроенные протоколы.
Клиент .NET
Чтобы включить MessagePack в клиенте .NET, установите Microsoft.AspNetCore.SignalR.Protocols.MessagePack
пакет и вызов AddMessagePackProtocol
HubConnectionBuilder
.
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.DependencyInjection;
var hubConnection = new HubConnectionBuilder()
.WithUrl("/chathub")
.AddMessagePackProtocol()
.Build();
Примечание.
Этот AddMessagePackProtocol
вызов принимает делегат для настройки параметров так же, как сервер.
Клиент на JavaScript
Поддержка MessagePack для клиента JavaScript предоставляется пакетом npm @microsoft/signalr-protocol-msgpack . Установите пакет, выполнив следующую команду в командной оболочке:
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();
В настоящее время нет параметров конфигурации для протокола MessagePack на клиенте JavaScript.
Клиент на Java
Чтобы включить MessagePack с Java, установите com.microsoft.signalr.messagepack
пакет. При использовании Gradle добавьте следующую строку в dependencies
раздел файла build.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#. Это можно обойти с помощью атрибута Key
, чтобы указать другое имя свойства MessagePack. Дополнительные сведения см . в документации по MessagePack-CSharp.
DateTime.Kind не сохраняется при сериализации или десериализации
Протокол MessagePack не предоставляет способ кодирования Kind
значения DateTime
объекта. В результате при десериализации даты протокол MessagePack Hub преобразуется в формат UTC, если DateTime.Kind
DateTimeKind.Local
в противном случае он не будет касаться времени и передавать его как есть. Если вы работаете со значениями DateTime
, рекомендуется преобразовать их в формате UTC перед отправкой. Преобразуйте их из UTC в местное время при получении.
Поддержка MessagePack в среде компиляции "перед временем"
Библиотека MessagePack-CSharp, используемая клиентом и сервером .NET, использует создание кода для оптимизации сериализации. В результате она не поддерживается по умолчанию в средах, использующих компиляцию "заранее" (например, 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
Протокол JSON Hub будет выполнять преобразования типов во время десериализации. Например, если входящий объект имеет значение свойства, которое является числом ({ 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 issue aspnet/SignalR#2937.
Chars and Strings in Java
В клиенте char
Java объекты будут сериализованы как однозначные String
объекты. Это отличается от клиента C# и JavaScript, который сериализует их в виде short
объектов. Сама спецификация MessagePack не определяет поведение для char
объектов, поэтому автор библиотеки может определить, как сериализовать их. Разница в поведении между нашими клиентами является результатом библиотек, которые мы использовали для наших реализаций.
Дополнительные ресурсы
В этой статье предполагается, что читатель знаком с темами, описанными в статье "Начало работы с ASP.NET Core SignalR".
Что такое MessagePack?
MessagePack — это быстрый и компактный формат двоичной сериализации. Это полезно, если производительность и пропускная способность являются проблемой, так как она создает небольшие сообщения по сравнению с JSON. Двоичные сообщения недоступны при просмотре сетевых трассировок и журналов, если только байты не передаются через средство синтаксического анализа MessagePack. SignalR имеет встроенную поддержку формата MessagePack и предоставляет API-интерфейсы для использования клиента и сервера.
Настройка MessagePack на сервере
Чтобы включить протокол MessagePack Hub на сервере, установите Microsoft.AspNetCore.SignalR.Protocols.MessagePack
пакет в приложении. В методе Startup.ConfigureServices
добавьте AddMessagePackProtocol
вызов AddSignalR
, чтобы включить поддержку MessagePack на сервере.
Примечание.
JSON включен по умолчанию. Добавление MessagePack обеспечивает поддержку клиентов JSON и MessagePack.
services.AddSignalR()
.AddMessagePackProtocol();
Чтобы настроить форматирование данных в MessagePack, AddMessagePackProtocol
необходимо принять делегат для настройки параметров. В этом делегате SerializerOptions
свойство можно использовать для настройки параметров сериализации MessagePack. Дополнительные сведения о работе сопоставителей см. в библиотеке MessagePack-CSharp. Атрибуты можно использовать для объектов, которые необходимо сериализовать, чтобы определить способ их обработки.
services.AddSignalR()
.AddMessagePackProtocol(options =>
{
options.SerializerOptions = MessagePackSerializerOptions.Standard
.WithResolver(new CustomResolver())
.WithSecurity(MessagePackSecurity.UntrustedData);
});
Предупреждение
Настоятельно рекомендуется просматривать CVE-2020-5234 и применять рекомендуемые исправления. Например, вызов .WithSecurity(MessagePackSecurity.UntrustedData)
при замене SerializerOptions
.
Настройка MessagePack на клиенте
Примечание.
JSON включен по умолчанию для поддерживаемых клиентов. Клиенты могут поддерживать только один протокол. Добавление поддержки MessagePack заменит все ранее настроенные протоколы.
Клиент .NET
Чтобы включить MessagePack в клиенте .NET, установите Microsoft.AspNetCore.SignalR.Protocols.MessagePack
пакет и вызов AddMessagePackProtocol
HubConnectionBuilder
.
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.DependencyInjection;
var hubConnection = new HubConnectionBuilder()
.WithUrl("/chathub")
.AddMessagePackProtocol()
.Build();
Примечание.
Этот AddMessagePackProtocol
вызов принимает делегат для настройки параметров так же, как сервер.
Клиент на JavaScript
Поддержка MessagePack для клиента JavaScript предоставляется пакетом npm @microsoft/signalr-protocol-msgpack . Установите пакет, выполнив следующую команду в командной оболочке:
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();
Примечание.
В настоящее время нет параметров конфигурации для протокола MessagePack на клиенте JavaScript.
Клиент на Java
Чтобы включить MessagePack с Java, установите com.microsoft.signalr.messagepack
пакет. При использовании Gradle добавьте следующую строку в dependencies
раздел файла build.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#. Это можно обойти с помощью атрибута Key
, чтобы указать другое имя свойства MessagePack. Дополнительные сведения см . в документации по MessagePack-CSharp.
DateTime.Kind не сохраняется при сериализации или десериализации
Протокол MessagePack не предоставляет способ кодирования Kind
значения DateTime
объекта. В результате при десериализации даты протокол MessagePack Hub преобразуется в формат UTC, если DateTime.Kind
DateTimeKind.Local
в противном случае он не будет касаться времени и передавать его как есть. Если вы работаете со значениями DateTime
, рекомендуется преобразовать их в формате UTC перед отправкой. Преобразуйте их из UTC в местное время при получении.
DateTime.MinValue не поддерживается MessagePack в JavaScript
Библиотека msgpack5, используемая клиентом SignalR JavaScript, не поддерживает timestamp96
тип в MessagePack. Этот тип используется для кодирования очень больших значений дат (либо в начале прошлого или очень далеко в будущем). Значение DateTime.MinValue
имеет значение January 1, 0001
, которое должно быть закодировано в значении timestamp96
. Из-за этого отправка DateTime.MinValue
клиенту JavaScript не поддерживается. При DateTime.MinValue
получении клиентом JavaScript возникает следующая ошибка:
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 в среде компиляции "перед временем"
Библиотека MessagePack-CSharp, используемая клиентом и сервером .NET, использует создание кода для оптимизации сериализации. В результате она не поддерживается по умолчанию в средах, использующих компиляцию "заранее" (например, 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
Протокол JSON Hub будет выполнять преобразования типов во время десериализации. Например, если входящий объект имеет значение свойства, которое является числом ({ 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 issue aspnet/SignalR#2937.
Chars and Strings in Java
В клиенте char
Java объекты будут сериализованы как однозначные String
объекты. Это отличается от клиента C# и JavaScript, который сериализует их в виде short
объектов. Сама спецификация MessagePack не определяет поведение для char
объектов, поэтому автор библиотеки может определить, как сериализовать их. Разница в поведении между нашими клиентами является результатом библиотек, которые мы использовали для наших реализаций.
Дополнительные ресурсы
В этой статье предполагается, что читатель знаком с темами, описанными в статье "Начало работы с ASP.NET Core SignalR".
Что такое MessagePack?
MessagePack — это быстрый и компактный формат двоичной сериализации. Это полезно, если производительность и пропускная способность являются проблемой, так как она создает небольшие сообщения по сравнению с JSON. Двоичные сообщения недоступны при просмотре сетевых трассировок и журналов, если только байты не передаются через средство синтаксического анализа MessagePack. SignalR имеет встроенную поддержку формата MessagePack и предоставляет API-интерфейсы для использования клиента и сервера.
Настройка MessagePack на сервере
Чтобы включить протокол MessagePack Hub на сервере, установите Microsoft.AspNetCore.SignalR.Protocols.MessagePack
пакет в приложении. В методе Startup.ConfigureServices
добавьте AddMessagePackProtocol
вызов AddSignalR
, чтобы включить поддержку MessagePack на сервере.
Примечание.
JSON включен по умолчанию. Добавление MessagePack обеспечивает поддержку клиентов JSON и MessagePack.
services.AddSignalR()
.AddMessagePackProtocol();
Чтобы настроить форматирование данных в MessagePack, AddMessagePackProtocol
необходимо принять делегат для настройки параметров. В этом делегате FormatterResolvers
свойство можно использовать для настройки параметров сериализации MessagePack. Дополнительные сведения о работе сопоставителей см. в библиотеке MessagePack-CSharp. Атрибуты можно использовать для объектов, которые необходимо сериализовать, чтобы определить способ их обработки.
services.AddSignalR()
.AddMessagePackProtocol(options =>
{
options.FormatterResolvers = new List<MessagePack.IFormatterResolver>()
{
MessagePack.Resolvers.StandardResolver.Instance
};
});
Предупреждение
Настоятельно рекомендуется просматривать CVE-2020-5234 и применять рекомендуемые исправления. Например, присвойте статическому свойству MessagePackSecurity.Active
MessagePackSecurity.UntrustedData
значение . MessagePackSecurity.Active
Установка необходимой вручную установки пакета MessagePack версии 1.9.x. При установке MessagePack
версии 1.9.x используется версия SignalR . MessagePack
версия 2.x представила критические изменения и несовместима с SignalR версиями 3.1 и более ранними версиями. Если MessagePackSecurity.Active
не задано MessagePackSecurity.UntrustedData
значение, вредоносный клиент может вызвать отказ в обслуживании. Задайте значение MessagePackSecurity.Active
, Program.Main
как показано в следующем коде:
using MessagePack;
public static void Main(string[] args)
{
MessagePackSecurity.Active = MessagePackSecurity.UntrustedData;
CreateHostBuilder(args).Build().Run();
}
Настройка MessagePack на клиенте
Примечание.
JSON включен по умолчанию для поддерживаемых клиентов. Клиенты могут поддерживать только один протокол. Добавление поддержки MessagePack заменит все ранее настроенные протоколы.
Клиент .NET
Чтобы включить MessagePack в клиенте .NET, установите Microsoft.AspNetCore.SignalR.Protocols.MessagePack
пакет и вызов AddMessagePackProtocol
HubConnectionBuilder
.
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.DependencyInjection;
var hubConnection = new HubConnectionBuilder()
.WithUrl("/chathub")
.AddMessagePackProtocol()
.Build();
Примечание.
Этот AddMessagePackProtocol
вызов принимает делегат для настройки параметров так же, как сервер.
Клиент на JavaScript
Поддержка MessagePack для клиента JavaScript предоставляется пакетом npm @microsoft/signalr-protocol-msgpack . Установите пакет, выполнив следующую команду в командной оболочке:
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();
Примечание.
В настоящее время нет параметров конфигурации для протокола MessagePack на клиенте JavaScript.
Рекомендации по 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#. Это можно обойти с помощью атрибута Key
, чтобы указать другое имя свойства MessagePack. Дополнительные сведения см . в документации по MessagePack-CSharp.
DateTime.Kind не сохраняется при сериализации или десериализации
Протокол MessagePack не предоставляет способ кодирования Kind
значения DateTime
объекта. В результате при десериализации даты протокол MessagePack Hub предполагает, что входящие даты в формате UTC. Если вы работаете со значениями DateTime
в локальном времени, рекомендуется преобразовать их в формате UTC перед отправкой. Преобразуйте их из UTC в местное время при получении.
Дополнительные сведения об этом ограничении см. в статье GitHub о проблеме aspnet/SignalR#2632.
DateTime.MinValue не поддерживается MessagePack в JavaScript
Библиотека msgpack5, используемая клиентом SignalR JavaScript, не поддерживает timestamp96
тип в MessagePack. Этот тип используется для кодирования очень больших значений дат (либо в начале прошлого или очень далеко в будущем). Значение DateTime.MinValue
имеет значение January 1, 0001
, которое должно быть закодировано в значении timestamp96
. Из-за этого отправка DateTime.MinValue
клиенту JavaScript не поддерживается. При DateTime.MinValue
получении клиентом JavaScript возникает следующая ошибка:
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 в среде компиляции "перед временем"
Библиотека MessagePack-CSharp, используемая клиентом и сервером .NET, использует создание кода для оптимизации сериализации. В результате она не поддерживается по умолчанию в средах, использующих компиляцию "заранее" (например, 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
Протокол JSON Hub будет выполнять преобразования типов во время десериализации. Например, если входящий объект имеет значение свойства, которое является числом ({ 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 issue aspnet/SignalR#2937.
Дополнительные ресурсы
В этой статье предполагается, что читатель знаком с темами, описанными в статье "Начало работы с ASP.NET Core SignalR".
Что такое MessagePack?
MessagePack — это быстрый и компактный формат двоичной сериализации. Это полезно, если производительность и пропускная способность являются проблемой, так как она создает небольшие сообщения по сравнению с JSON. Двоичные сообщения недоступны при просмотре сетевых трассировок и журналов, если только байты не передаются через средство синтаксического анализа MessagePack. SignalR имеет встроенную поддержку формата MessagePack и предоставляет API-интерфейсы для использования клиента и сервера.
Настройка MessagePack на сервере
Чтобы включить протокол MessagePack Hub на сервере, установите Microsoft.AspNetCore.SignalR.Protocols.MessagePack
пакет в приложении. В методе Startup.ConfigureServices
добавьте AddMessagePackProtocol
вызов AddSignalR
, чтобы включить поддержку MessagePack на сервере.
Примечание.
JSON включен по умолчанию. Добавление MessagePack обеспечивает поддержку клиентов JSON и MessagePack.
services.AddSignalR()
.AddMessagePackProtocol();
Чтобы настроить форматирование данных в MessagePack, AddMessagePackProtocol
необходимо принять делегат для настройки параметров. В этом делегате FormatterResolvers
свойство можно использовать для настройки параметров сериализации MessagePack. Дополнительные сведения о работе сопоставителей см. в библиотеке MessagePack-CSharp. Атрибуты можно использовать для объектов, которые необходимо сериализовать, чтобы определить способ их обработки.
services.AddSignalR()
.AddMessagePackProtocol(options =>
{
options.FormatterResolvers = new List<MessagePack.IFormatterResolver>()
{
MessagePack.Resolvers.StandardResolver.Instance
};
});
Предупреждение
Настоятельно рекомендуется просматривать CVE-2020-5234 и применять рекомендуемые исправления. Например, присвойте статическому свойству MessagePackSecurity.Active
MessagePackSecurity.UntrustedData
значение . MessagePackSecurity.Active
Установка необходимой вручную установки пакета MessagePack версии 1.9.x. При установке MessagePack
версии 1.9.x используется версия SignalR . Если MessagePackSecurity.Active
не задано значение MessagePackSecurity.UntrustedData
, вредоносный клиент может вызвать отказ в обслуживании. Задайте значение MessagePackSecurity.Active
, Program.Main
как показано в следующем коде:
using MessagePack;
public static void Main(string[] args)
{
MessagePackSecurity.Active = MessagePackSecurity.UntrustedData;
CreateHostBuilder(args).Build().Run();
}
Настройка MessagePack на клиенте
Примечание.
JSON включен по умолчанию для поддерживаемых клиентов. Клиенты могут поддерживать только один протокол. Добавление поддержки MessagePack заменит все ранее настроенные протоколы.
Клиент .NET
Чтобы включить MessagePack в клиенте .NET, установите Microsoft.AspNetCore.SignalR.Protocols.MessagePack
пакет и вызов AddMessagePackProtocol
HubConnectionBuilder
.
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.DependencyInjection;
var hubConnection = new HubConnectionBuilder()
.WithUrl("/chathub")
.AddMessagePackProtocol()
.Build();
Примечание.
Этот AddMessagePackProtocol
вызов принимает делегат для настройки параметров так же, как сервер.
Клиент на JavaScript
Поддержка MessagePack для клиента JavaScript предоставляется пакетом npm @aspnet/signalr-protocol-msgpack . Установите пакет, выполнив следующую команду в командной оболочке:
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();
Примечание.
В настоящее время нет параметров конфигурации для протокола MessagePack на клиенте JavaScript.
Рекомендации по 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#. Это можно обойти с помощью атрибута Key
, чтобы указать другое имя свойства MessagePack. Дополнительные сведения см . в документации по MessagePack-CSharp.
DateTime.Kind не сохраняется при сериализации или десериализации
Протокол MessagePack не предоставляет способ кодирования Kind
значения DateTime
объекта. В результате при десериализации даты протокол MessagePack Hub предполагает, что входящие даты в формате UTC. Если вы работаете со значениями DateTime
в локальном времени, рекомендуется преобразовать их в формате UTC перед отправкой. Преобразуйте их из UTC в местное время при получении.
Дополнительные сведения об этом ограничении см. в статье GitHub о проблеме aspnet/SignalR#2632.
DateTime.MinValue не поддерживается MessagePack в JavaScript
Библиотека msgpack5, используемая клиентом SignalR JavaScript, не поддерживает timestamp96
тип в MessagePack. Этот тип используется для кодирования очень больших значений дат (либо в начале прошлого или очень далеко в будущем). Значение DateTime.MinValue
, January 1, 0001
которое должно быть закодировано в значении timestamp96
. Из-за этого отправка DateTime.MinValue
клиенту JavaScript не поддерживается. При DateTime.MinValue
получении клиентом JavaScript возникает следующая ошибка:
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 в среде компиляции "перед временем"
Библиотека MessagePack-CSharp, используемая клиентом и сервером .NET, использует создание кода для оптимизации сериализации. В результате она не поддерживается по умолчанию в средах, использующих компиляцию "заранее" (например, 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
Протокол JSON Hub будет выполнять преобразования типов во время десериализации. Например, если входящий объект имеет значение свойства, которое является числом ({ 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 issue aspnet/SignalR#2937.
Дополнительные ресурсы
ASP.NET Core