From aa12922efa46a0c53eabe3b3e9e335459926c3f4 Mon Sep 17 00:00:00 2001 From: Andrew Stanton-Nurse Date: Wed, 27 Feb 2019 10:17:24 -0800 Subject: [PATCH 1/4] Add section on SignalR MessagePack "known issues" There are some known issues/quirks in the MessagePack Hub Protocol for SignalR. We should call them out in our docs instead of making users search GitHub for these answers :) --- aspnetcore/signalr/messagepackhubprotocol.md | 58 ++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/aspnetcore/signalr/messagepackhubprotocol.md b/aspnetcore/signalr/messagepackhubprotocol.md index 48c60fcdfc20..1b7c77d86b8b 100644 --- a/aspnetcore/signalr/messagepackhubprotocol.md +++ b/aspnetcore/signalr/messagepackhubprotocol.md @@ -94,6 +94,64 @@ const connection = new signalR.HubConnectionBuilder() > [!NOTE] > At this time, there are no configuration options for the MessagePack protocol on the JavaScript client. +## MessagePack Quirks + +There are a few unique issues to be aware of when using the MessagePack Hub Protocol. + +### MessagePack is case-sensitive + +The MessagePack protocol is case-sensitive. For example, consider the following C# class: + +```csharp +public class ChatMessage +{ + public string Sender { get; } + public string Message { get; } +} +``` + +When sending from the JavaScript client, you must use `PascalCased` property names, since the casing must match the C# class exactly. For example: + +```javascript +connection.invoke("SomeMethod", { Sender: "Sally", Message: "Hello!" }); +``` + +Using `camelCased` names will not properly bind to the C# class. You can work around this by using the `Key` attribute to specify a different name for the MessagePack property. See [the MessagePack-CSharp documentation](https://github.com/neuecc/MessagePack-CSharp#object-serialization) for more information. + +### DateTime.MinValue is not supported by MessagePack in JavaScript + +The [msgpack5](https://github.com/mcollina/msgpack5) library used by the SignalR JavaScript client does not support the `timestamp96` type in MessagePack. This type is used to encode very large date values (either very early in the past or very far in the future). The value of `DateTime.MinValue` is `January 1, 0001` which must be encoded in a `timestamp96` value. Because of this, sending `DateTime.MinValue` to a JavaScript client is not supported. Usually, `DateTime.MinValue` is used to encode a "missing" or `null` value. If you need to encode that value in MessagePack, use a nullable `DateTime` value (`DateTime?`) or encode a separate `bool` value indicating if the date is present. + +See [aspnet/SignalR#2228](https://github.com/aspnet/SignalR/issues/2228) for more information on this limitation. + +### MessagePack support in "ahead-of-time" compilation environment + +The [MessagePack-CSharp](https://github.com/neuecc/MessagePack-CSharp) library used by the .NET Client and Server uses code generation to optimize serialization. As a result, it is not supported by default on environmment that use "ahead-of-time" compilation (such as Xamarin iOS or Unity). It is possible to use MessagePack in these environments by "pre-generating" the serializer/deserializer code. For more information see [the MessagePack-CSharp documentation](https://github.com/neuecc/MessagePack-CSharp#pre-code-generationunityxamarin-supports). Once you have pre-generated the serializers, you can register them using the configuration delegate passed to `AddMessagePackProtocol`: + +```csharp +services.AddSignalR() + .AddMessagePackProtocol(options => + { + options.FormatterResolvers = new List() + { + MessagePack.Resolvers.GeneratedResolver.Instance, + MessagePack.Resolvers.StandardResolver.Instance + }; + }); +``` + +### Type checks are more strict in MessagePack + +The JSON Hub Protocol will perform type conversions during deserialization. For example, if the incoming object has an property value that is a number (`{ foo: 42 }`) but the property on the .NET class is of type `string`, the value will be converted. However, MessagePack does not perform this conversion, and will throw an `InvalidDataException` instead. + +See [aspnet/SignalR#2937](https://github.com/aspnet/SignalR/issues/2937) for more information on this limitation. + +### DateTime.Kind is not preserved when serializing/deserializing + +The MessagePack protocol does not provide a way to encode the `Kind` value of a `DateTime`. As a result, when deserializing a date, the MessagePack Hub Protocol assumes the incoming date is in UTC format. If you are working with `DateTime` values in local time, we recommend converting to UTC before sending them, and convert them from UTC to local time when you receive them. + +See [aspnet/SignalR#2632](https://github.com/aspnet/SignalR/issues/2632) for more information on this limitation. + ## Related resources * [Get Started](xref:tutorials/signalr) From cf415693ecaa597b3aee15ec017a793f8b20e232 Mon Sep 17 00:00:00 2001 From: Scott Addie <10702007+scottaddie@users.noreply.github.com> Date: Wed, 27 Feb 2019 11:45:39 -0800 Subject: [PATCH 2/4] Applying auto-applyable suggestions Co-Authored-By: anurse --- aspnetcore/signalr/messagepackhubprotocol.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/aspnetcore/signalr/messagepackhubprotocol.md b/aspnetcore/signalr/messagepackhubprotocol.md index 1b7c77d86b8b..92356fbf241a 100644 --- a/aspnetcore/signalr/messagepackhubprotocol.md +++ b/aspnetcore/signalr/messagepackhubprotocol.md @@ -116,17 +116,17 @@ When sending from the JavaScript client, you must use `PascalCased` property nam connection.invoke("SomeMethod", { Sender: "Sally", Message: "Hello!" }); ``` -Using `camelCased` names will not properly bind to the C# class. You can work around this by using the `Key` attribute to specify a different name for the MessagePack property. See [the MessagePack-CSharp documentation](https://github.com/neuecc/MessagePack-CSharp#object-serialization) for more information. +Using `camelCased` names won't properly bind to the C# class. You can work around this by using the `Key` attribute to specify a different name for the MessagePack property. For more information, see [the MessagePack-CSharp documentation](https://github.com/neuecc/MessagePack-CSharp#object-serialization). ### DateTime.MinValue is not supported by MessagePack in JavaScript -The [msgpack5](https://github.com/mcollina/msgpack5) library used by the SignalR JavaScript client does not support the `timestamp96` type in MessagePack. This type is used to encode very large date values (either very early in the past or very far in the future). The value of `DateTime.MinValue` is `January 1, 0001` which must be encoded in a `timestamp96` value. Because of this, sending `DateTime.MinValue` to a JavaScript client is not supported. Usually, `DateTime.MinValue` is used to encode a "missing" or `null` value. If you need to encode that value in MessagePack, use a nullable `DateTime` value (`DateTime?`) or encode a separate `bool` value indicating if the date is present. +The [msgpack5](https://github.com/mcollina/msgpack5) library used by the SignalR JavaScript client doesn't support the `timestamp96` type in MessagePack. This type is used to encode very large date values (either very early in the past or very far in the future). The value of `DateTime.MinValue` is `January 1, 0001` which must be encoded in a `timestamp96` value. Because of this, sending `DateTime.MinValue` to a JavaScript client isn't supported. Usually, `DateTime.MinValue` is used to encode a "missing" or `null` value. If you need to encode that value in MessagePack, use a nullable `DateTime` value (`DateTime?`) or encode a separate `bool` value indicating if the date is present. -See [aspnet/SignalR#2228](https://github.com/aspnet/SignalR/issues/2228) for more information on this limitation. +For more information on this limitation, see [aspnet/SignalR#2228](https://github.com/aspnet/SignalR/issues/2228). ### MessagePack support in "ahead-of-time" compilation environment -The [MessagePack-CSharp](https://github.com/neuecc/MessagePack-CSharp) library used by the .NET Client and Server uses code generation to optimize serialization. As a result, it is not supported by default on environmment that use "ahead-of-time" compilation (such as Xamarin iOS or Unity). It is possible to use MessagePack in these environments by "pre-generating" the serializer/deserializer code. For more information see [the MessagePack-CSharp documentation](https://github.com/neuecc/MessagePack-CSharp#pre-code-generationunityxamarin-supports). Once you have pre-generated the serializers, you can register them using the configuration delegate passed to `AddMessagePackProtocol`: +The [MessagePack-CSharp](https://github.com/neuecc/MessagePack-CSharp) library used by the .NET client and server uses code generation to optimize serialization. As a result, it isn't supported by default on environments that use "ahead-of-time" compilation (such as Xamarin iOS or Unity). It's possible to use MessagePack in these environments by "pre-generating" the serializer/deserializer code. For more information, see [the MessagePack-CSharp documentation](https://github.com/neuecc/MessagePack-CSharp#pre-code-generationunityxamarin-supports). Once you have pre-generated the serializers, you can register them using the configuration delegate passed to `AddMessagePackProtocol`: ```csharp services.AddSignalR() @@ -142,15 +142,15 @@ services.AddSignalR() ### Type checks are more strict in MessagePack -The JSON Hub Protocol will perform type conversions during deserialization. For example, if the incoming object has an property value that is a number (`{ foo: 42 }`) but the property on the .NET class is of type `string`, the value will be converted. However, MessagePack does not perform this conversion, and will throw an `InvalidDataException` instead. +The JSON Hub Protocol will perform type conversions during deserialization. For example, if the incoming object has a property value that is a number (`{ foo: 42 }`) but the property on the .NET class is of type `string`, the value will be converted. However, MessagePack doesn't perform this conversion and will throw an `InvalidDataException` instead. -See [aspnet/SignalR#2937](https://github.com/aspnet/SignalR/issues/2937) for more information on this limitation. +For more information on this limitation, see [aspnet/SignalR#2937](https://github.com/aspnet/SignalR/issues/2937). ### DateTime.Kind is not preserved when serializing/deserializing -The MessagePack protocol does not provide a way to encode the `Kind` value of a `DateTime`. As a result, when deserializing a date, the MessagePack Hub Protocol assumes the incoming date is in UTC format. If you are working with `DateTime` values in local time, we recommend converting to UTC before sending them, and convert them from UTC to local time when you receive them. +The MessagePack protocol doesn't provide a way to encode the `Kind` value of a `DateTime`. As a result, when deserializing a date, the MessagePack Hub Protocol assumes the incoming date is in UTC format. If you're working with `DateTime` values in local time, we recommend converting to UTC before sending them. Convert them from UTC to local time when you receive them. -See [aspnet/SignalR#2632](https://github.com/aspnet/SignalR/issues/2632) for more information on this limitation. +For more information on this limitation, see [aspnet/SignalR#2632](https://github.com/aspnet/SignalR/issues/2632). ## Related resources From 4ed30a75fd7ee1502cd8806d3ed863ab75c92b3e Mon Sep 17 00:00:00 2001 From: Andrew Stanton-Nurse Date: Wed, 27 Feb 2019 11:51:31 -0800 Subject: [PATCH 3/4] pr feedback --- aspnetcore/signalr/messagepackhubprotocol.md | 32 +++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/aspnetcore/signalr/messagepackhubprotocol.md b/aspnetcore/signalr/messagepackhubprotocol.md index 92356fbf241a..d5ea305e5419 100644 --- a/aspnetcore/signalr/messagepackhubprotocol.md +++ b/aspnetcore/signalr/messagepackhubprotocol.md @@ -5,7 +5,7 @@ description: Add MessagePack Hub Protocol to ASP.NET Core SignalR. monikerRange: '>= aspnetcore-2.1' ms.author: bradyg ms.custom: mvc -ms.date: 06/04/2018 +ms.date: 02/27/2019 uid: signalr/messagepackhubprotocol --- @@ -94,7 +94,7 @@ const connection = new signalR.HubConnectionBuilder() > [!NOTE] > At this time, there are no configuration options for the MessagePack protocol on the JavaScript client. -## MessagePack Quirks +## MessagePack quirks There are a few unique issues to be aware of when using the MessagePack Hub Protocol. @@ -118,11 +118,23 @@ connection.invoke("SomeMethod", { Sender: "Sally", Message: "Hello!" }); Using `camelCased` names won't properly bind to the C# class. You can work around this by using the `Key` attribute to specify a different name for the MessagePack property. For more information, see [the MessagePack-CSharp documentation](https://github.com/neuecc/MessagePack-CSharp#object-serialization). +### DateTime.Kind is not preserved when serializing/deserializing + +The MessagePack protocol doesn't provide a way to encode the `Kind` value of a `DateTime`. As a result, when deserializing a date, the MessagePack Hub Protocol assumes the incoming date is in UTC format. If you're working with `DateTime` values in local time, we recommend converting to UTC before sending them. Convert them from UTC to local time when you receive them. + +For more information on this limitation, see GitHub issue [aspnet/SignalR#2632](https://github.com/aspnet/SignalR/issues/2632). + ### DateTime.MinValue is not supported by MessagePack in JavaScript -The [msgpack5](https://github.com/mcollina/msgpack5) library used by the SignalR JavaScript client doesn't support the `timestamp96` type in MessagePack. This type is used to encode very large date values (either very early in the past or very far in the future). The value of `DateTime.MinValue` is `January 1, 0001` which must be encoded in a `timestamp96` value. Because of this, sending `DateTime.MinValue` to a JavaScript client isn't supported. Usually, `DateTime.MinValue` is used to encode a "missing" or `null` value. If you need to encode that value in MessagePack, use a nullable `DateTime` value (`DateTime?`) or encode a separate `bool` value indicating if the date is present. +The [msgpack5](https://github.com/mcollina/msgpack5) library used by the SignalR JavaScript client doesn't support the `timestamp96` type in MessagePack. This type is used to encode very large date values (either very early in the past or very far in the future). The value of `DateTime.MinValue` is `January 1, 0001` which must be encoded in a `timestamp96` value. Because of this, sending `DateTime.MinValue` to a JavaScript client isn't supported. When `DateTime.MinValue` is received by the JavaScript client, the following error is thrown: + +``` +Uncaught Error: unable to find ext type 255 at decoder.js:427 +``` -For more information on this limitation, see [aspnet/SignalR#2228](https://github.com/aspnet/SignalR/issues/2228). +Usually, `DateTime.MinValue` is used to encode a "missing" or `null` value. If you need to encode that value in MessagePack, use a nullable `DateTime` value (`DateTime?`) or encode a separate `bool` value indicating if the date is present. + +For more information on this limitation, see GitHub issue [aspnet/SignalR#2228](https://github.com/aspnet/SignalR/issues/2228). ### MessagePack support in "ahead-of-time" compilation environment @@ -142,15 +154,13 @@ services.AddSignalR() ### Type checks are more strict in MessagePack -The JSON Hub Protocol will perform type conversions during deserialization. For example, if the incoming object has a property value that is a number (`{ foo: 42 }`) but the property on the .NET class is of type `string`, the value will be converted. However, MessagePack doesn't perform this conversion and will throw an `InvalidDataException` instead. - -For more information on this limitation, see [aspnet/SignalR#2937](https://github.com/aspnet/SignalR/issues/2937). - -### DateTime.Kind is not preserved when serializing/deserializing +The JSON Hub Protocol will perform type conversions during deserialization. For example, if the incoming object has a property value that is a number (`{ foo: 42 }`) but the property on the .NET class is of type `string`, the value will be converted. However, MessagePack doesn't perform this conversion and will throw an exception that can be seen in server-side logs (and in the console): -The MessagePack protocol doesn't provide a way to encode the `Kind` value of a `DateTime`. As a result, when deserializing a date, the MessagePack Hub Protocol assumes the incoming date is in UTC format. If you're working with `DateTime` values in local time, we recommend converting to UTC before sending them. Convert them from UTC to local time when you receive them. +``` +InvalidDataException: Error binding arguments. Make sure that the types of the provided values match the types of the hub method being invoked. +``` -For more information on this limitation, see [aspnet/SignalR#2632](https://github.com/aspnet/SignalR/issues/2632). +For more information on this limitation, see GitHub issue [aspnet/SignalR#2937](https://github.com/aspnet/SignalR/issues/2937). ## Related resources From 6013e138a5b7b0c4869436a494dde9aa6e8211fa Mon Sep 17 00:00:00 2001 From: Tom Dykstra Date: Wed, 27 Feb 2019 14:54:10 -0800 Subject: [PATCH 4/4] Update aspnetcore/signalr/messagepackhubprotocol.md Co-Authored-By: anurse --- aspnetcore/signalr/messagepackhubprotocol.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/signalr/messagepackhubprotocol.md b/aspnetcore/signalr/messagepackhubprotocol.md index d5ea305e5419..d69ffd646067 100644 --- a/aspnetcore/signalr/messagepackhubprotocol.md +++ b/aspnetcore/signalr/messagepackhubprotocol.md @@ -96,7 +96,7 @@ const connection = new signalR.HubConnectionBuilder() ## MessagePack quirks -There are a few unique issues to be aware of when using the MessagePack Hub Protocol. +There are a few issues to be aware of when using the MessagePack Hub Protocol. ### MessagePack is case-sensitive