From ba25dee1417b882a1c0993118a4fe6cfaa98c3fc Mon Sep 17 00:00:00 2001 From: Pawel Kadluczka Date: Tue, 19 Sep 2017 17:32:00 -0700 Subject: [PATCH 1/4] Enabling customizing serialization settings in MessagePack protocol --- .../HubConnectionBuilderExtensions.cs | 3 +- .../Protocol/MessagePackHubProtocol.cs | 21 ++++--- .../HubOptions.cs | 3 + .../Internal/DefaultHubProtocolResolver.cs | 2 +- .../HubConnectionTests.cs | 2 +- .../HubConnectionProtocolTests.cs | 9 ++- .../Protocol/MessagePackHubProtocolTests.cs | 3 +- .../HubEndpointTests.cs | 56 ++++++++++++++++++- .../DefaultHubProtocolResolverTests.cs | 2 +- ...gnalRDependencyInjectionExtensionsTests.cs | 15 +++++ .../TestClient.cs | 4 +- 11 files changed, 101 insertions(+), 19 deletions(-) diff --git a/src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnectionBuilderExtensions.cs b/src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnectionBuilderExtensions.cs index a6b770d6cc..fdfe9aef73 100644 --- a/src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnectionBuilderExtensions.cs +++ b/src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnectionBuilderExtensions.cs @@ -23,7 +23,8 @@ namespace Microsoft.AspNetCore.SignalR.Client public static IHubConnectionBuilder WithMessagePackProtocol(this IHubConnectionBuilder hubConnectionBuilder) { - return hubConnectionBuilder.WithHubProtocol(new MessagePackHubProtocol()); + return hubConnectionBuilder.WithHubProtocol( + new MessagePackHubProtocol(MessagePackHubProtocol.CreateDefaultSerializationContext())); } public static IHubConnectionBuilder WithLoggerFactory(this IHubConnectionBuilder hubConnectionBuilder, ILoggerFactory loggerFactory) diff --git a/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/MessagePackHubProtocol.cs b/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/MessagePackHubProtocol.cs index 22e90fe437..77ad478fc1 100644 --- a/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/MessagePackHubProtocol.cs +++ b/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/MessagePackHubProtocol.cs @@ -20,18 +20,15 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Protocol private const int VoidResult = 2; private const int NonVoidResult = 3; - private static readonly SerializationContext _serializationContext; + private readonly SerializationContext _serializationContext; public string Name => "messagepack"; public ProtocolType Type => ProtocolType.Binary; - static MessagePackHubProtocol() + public MessagePackHubProtocol(SerializationContext serializationContext) { - // serializes objects (here: arguments and results) as maps so that property names are preserved - _serializationContext = new SerializationContext { SerializationMethod = SerializationMethod.Map }; - // allows for serializing objects that cannot be deserialized due to the lack of the default ctor etc. - _serializationContext.CompatibilityOptions.AllowAsymmetricSerializer = true; + _serializationContext = serializationContext; } public bool TryParseMessages(ReadOnlyBuffer input, IInvocationBinder binder, out IList messages) @@ -156,7 +153,7 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Protocol } } - private static void WriteInvocationMessage(InvocationMessage invocationMessage, Packer packer, Stream output) + private void WriteInvocationMessage(InvocationMessage invocationMessage, Packer packer, Stream output) { packer.PackArrayHeader(5); packer.Pack(InvocationMessageType); @@ -291,5 +288,15 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Protocol throw new FormatException($"Deserializing object of the `{type.Name}` type for '{field}' failed.", msgPackException); } + + public static SerializationContext CreateDefaultSerializationContext() + { + // serializes objects (here: arguments and results) as maps so that property names are preserved + var serializationContext = new SerializationContext { SerializationMethod = SerializationMethod.Map }; + // allows for serializing objects that cannot be deserialized due to the lack of the default ctor etc. + serializationContext.CompatibilityOptions.AllowAsymmetricSerializer = true; + + return serializationContext; + } } } diff --git a/src/Microsoft.AspNetCore.SignalR.Core/HubOptions.cs b/src/Microsoft.AspNetCore.SignalR.Core/HubOptions.cs index b1d6f40cdd..b1eebb66fd 100644 --- a/src/Microsoft.AspNetCore.SignalR.Core/HubOptions.cs +++ b/src/Microsoft.AspNetCore.SignalR.Core/HubOptions.cs @@ -1,6 +1,8 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using Microsoft.AspNetCore.SignalR.Internal.Protocol; +using MsgPack.Serialization; using Newtonsoft.Json; namespace Microsoft.AspNetCore.SignalR @@ -8,5 +10,6 @@ namespace Microsoft.AspNetCore.SignalR public class HubOptions { public JsonSerializerSettings JsonSerializerSettings { get; set; } = new JsonSerializerSettings(); + public SerializationContext MessagePackSerializationContext { get; set; } = MessagePackHubProtocol.CreateDefaultSerializationContext(); } } diff --git a/src/Microsoft.AspNetCore.SignalR.Core/Internal/DefaultHubProtocolResolver.cs b/src/Microsoft.AspNetCore.SignalR.Core/Internal/DefaultHubProtocolResolver.cs index bb0d44bf97..fe2a59f7bd 100644 --- a/src/Microsoft.AspNetCore.SignalR.Core/Internal/DefaultHubProtocolResolver.cs +++ b/src/Microsoft.AspNetCore.SignalR.Core/Internal/DefaultHubProtocolResolver.cs @@ -24,7 +24,7 @@ namespace Microsoft.AspNetCore.SignalR.Internal case "json": return new JsonHubProtocol(JsonSerializer.Create(_options.Value.JsonSerializerSettings)); case "messagepack": - return new MessagePackHubProtocol(); + return new MessagePackHubProtocol(_options.Value.MessagePackSerializationContext); default: throw new NotSupportedException($"The protocol '{protocolName ?? "(null)"}' is not supported."); } diff --git a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs index e92ee22a3f..39f7ab26ac 100644 --- a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs @@ -246,7 +246,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests new IHubProtocol[] { new JsonHubProtocol(new JsonSerializer()), - new MessagePackHubProtocol(), + new MessagePackHubProtocol(MessagePackHubProtocol.CreateDefaultSerializationContext()), }; public static IEnumerable TransportTypes() diff --git a/test/Microsoft.AspNetCore.SignalR.Client.Tests/HubConnectionProtocolTests.cs b/test/Microsoft.AspNetCore.SignalR.Client.Tests/HubConnectionProtocolTests.cs index c9a8928b4a..d88054e2b9 100644 --- a/test/Microsoft.AspNetCore.SignalR.Client.Tests/HubConnectionProtocolTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Client.Tests/HubConnectionProtocolTests.cs @@ -331,7 +331,8 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests { var connection = new TestConnection(TransferMode.Text); - var hubConnection = new HubConnection(connection, new MessagePackHubProtocol(), new LoggerFactory()); + var hubConnection = new HubConnection(connection, + new MessagePackHubProtocol(MessagePackHubProtocol.CreateDefaultSerializationContext()), new LoggerFactory()); try { await hubConnection.StartAsync().OrTimeout(); @@ -361,7 +362,8 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests public async Task MessagesDecodedWhenUsingBinaryProtocolOverTextTransport() { var connection = new TestConnection(TransferMode.Text); - var hubConnection = new HubConnection(connection, new MessagePackHubProtocol(), new LoggerFactory()); + var hubConnection = new HubConnection(connection, + new MessagePackHubProtocol(MessagePackHubProtocol.CreateDefaultSerializationContext()), new LoggerFactory()); var invocationTcs = new TaskCompletionSource(); try @@ -371,7 +373,8 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests using (var ms = new MemoryStream()) { - new MessagePackHubProtocol().WriteMessage(new InvocationMessage("1", true, "MyMethod", 42), ms); + new MessagePackHubProtocol(MessagePackHubProtocol.CreateDefaultSerializationContext()) + .WriteMessage(new InvocationMessage("1", true, "MyMethod", 42), ms); var invokeMessage = Convert.ToBase64String(ms.ToArray()); var payloadSize = invokeMessage.Length.ToString(CultureInfo.InvariantCulture); diff --git a/test/Microsoft.AspNetCore.SignalR.Common.Tests/Internal/Protocol/MessagePackHubProtocolTests.cs b/test/Microsoft.AspNetCore.SignalR.Common.Tests/Internal/Protocol/MessagePackHubProtocolTests.cs index 19ef3b4c4c..32c45ae11d 100644 --- a/test/Microsoft.AspNetCore.SignalR.Common.Tests/Internal/Protocol/MessagePackHubProtocolTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Common.Tests/Internal/Protocol/MessagePackHubProtocolTests.cs @@ -12,7 +12,8 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Protocol { public class MessagePackHubProtocolTests { - private static readonly MessagePackHubProtocol _hubProtocol = new MessagePackHubProtocol(); + private static readonly MessagePackHubProtocol _hubProtocol + = new MessagePackHubProtocol(MessagePackHubProtocol.CreateDefaultSerializationContext()); public static IEnumerable TestMessages => new[] { diff --git a/test/Microsoft.AspNetCore.SignalR.Tests/HubEndpointTests.cs b/test/Microsoft.AspNetCore.SignalR.Tests/HubEndpointTests.cs index 9b44396d1b..104c32739c 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests/HubEndpointTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests/HubEndpointTests.cs @@ -13,8 +13,11 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.SignalR.Internal.Protocol; using Microsoft.AspNetCore.SignalR.Tests.Common; using Microsoft.AspNetCore.Sockets; +using Microsoft.AspNetCore.Sockets.Features; using Microsoft.Extensions.DependencyInjection; using Moq; +using MsgPack; +using MsgPack.Serialization; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using Xunit; @@ -1020,7 +1023,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests await client.SendInvocationAsync(nameof(MethodHub.BroadcastItem)).OrTimeout(); - var message = await client.ReadAsync().OrTimeout() as InvocationMessage; + var message = (InvocationMessage)await client.ReadAsync().OrTimeout(); var customItem = message.Arguments[0].ToString(); // Originally "Message" and "paramName" @@ -1033,6 +1036,46 @@ namespace Microsoft.AspNetCore.SignalR.Tests } } + [Fact] + public async Task HubOptionsCanUseCustomMessagePackSettings() + { + var serializationContext = MessagePackHubProtocol.CreateDefaultSerializationContext(); + serializationContext.SerializationMethod = SerializationMethod.Array; + + var serviceProvider = CreateServiceProvider(services => + { + services.AddSignalR(options => + { + options.MessagePackSerializationContext = serializationContext; + }); + }); + + var endPoint = serviceProvider.GetService>(); + + using (var client = new TestClient(synchronousCallbacks: false, protocol: new MessagePackHubProtocol(serializationContext))) + { + var transportFeature = new Mock(); + transportFeature.SetupGet(f => f.TransportCapabilities).Returns(TransferMode.Binary); + client.Connection.Features.Set(transportFeature.Object); + var endPointLifetime = endPoint.OnConnectedAsync(client.Connection); + + await client.Connected.OrTimeout(); + + await client.SendInvocationAsync(nameof(MethodHub.BroadcastItem)).OrTimeout(); + + var message = await client.ReadAsync().OrTimeout() as InvocationMessage; + + var msgPackObject = Assert.IsType(message.Arguments[0]); + // Custom serialization - object was serialized as an array and not a map + Assert.True(msgPackObject.IsArray); + Assert.Equal(new[] { "test", "param" }, ((MessagePackObject[])msgPackObject.ToObject()).Select(o => o.AsString())); + + client.Dispose(); + + await endPointLifetime.OrTimeout(); + } + } + [Fact] public async Task CanGetHttpContextFromHubConnectionContext() { @@ -1427,6 +1470,15 @@ namespace Microsoft.AspNetCore.SignalR.Tests } } + public class Result + { + public string Message { get; set; } +#pragma warning disable IDE1006 // Naming Styles + // testing casing + public string paramName { get; set; } +#pragma warning restore IDE1006 // Naming Styles + } + private class MethodHub : TestHub { public Task GroupRemoveMethod(string groupName) @@ -1461,7 +1513,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests public Task BroadcastItem() { - return Clients.All.InvokeAsync("Broadcast", new { Message = "test", paramName = "test" }); + return Clients.All.InvokeAsync("Broadcast", new Result { Message = "test", paramName = "param" }); } public Task TaskValueMethod() diff --git a/test/Microsoft.AspNetCore.SignalR.Tests/Internal/DefaultHubProtocolResolverTests.cs b/test/Microsoft.AspNetCore.SignalR.Tests/Internal/DefaultHubProtocolResolverTests.cs index 39c77de93e..0b3b604182 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests/Internal/DefaultHubProtocolResolverTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests/Internal/DefaultHubProtocolResolverTests.cs @@ -42,7 +42,7 @@ namespace Microsoft.AspNetCore.SignalR.Common.Protocol.Tests new[] { new object[] { new JsonHubProtocol(new JsonSerializer()) }, - new object[] { new MessagePackHubProtocol() }, + new object[] { new MessagePackHubProtocol(MessagePackHubProtocol.CreateDefaultSerializationContext()) }, }; } } diff --git a/test/Microsoft.AspNetCore.SignalR.Tests/SignalRDependencyInjectionExtensionsTests.cs b/test/Microsoft.AspNetCore.SignalR.Tests/SignalRDependencyInjectionExtensionsTests.cs index a4f834f97d..3652afb2de 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests/SignalRDependencyInjectionExtensionsTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests/SignalRDependencyInjectionExtensionsTests.cs @@ -3,6 +3,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; +using MsgPack.Serialization; using Xunit; namespace Microsoft.AspNetCore.SignalR.Tests @@ -19,5 +20,19 @@ namespace Microsoft.AspNetCore.SignalR.Tests var hubOptions = serviceProvider.GetService>(); Assert.NotNull(hubOptions.Value.JsonSerializerSettings); } + + [Fact] + public void MessagePackSerializationContextInOptionsIsSetAndHasDefaultSettings() + { + var services = new ServiceCollection(); + services.AddOptions(); + services.AddSignalR(); + var serviceProvider = services.BuildServiceProvider(); + var hubOptions = serviceProvider.GetService>(); + var serializationContext = hubOptions.Value.MessagePackSerializationContext; + Assert.NotNull(serializationContext); + Assert.Equal(SerializationMethod.Map, serializationContext.SerializationMethod); + Assert.True(serializationContext.CompatibilityOptions.AllowAsymmetricSerializer); + } } } diff --git a/test/Microsoft.AspNetCore.SignalR.Tests/TestClient.cs b/test/Microsoft.AspNetCore.SignalR.Tests/TestClient.cs index e589fefff1..94725fdebe 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests/TestClient.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests/TestClient.cs @@ -28,7 +28,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests public Channel Application { get; } public Task Connected => ((TaskCompletionSource)Connection.Metadata["ConnectedTask"]).Task; - public TestClient(bool synchronousCallbacks = false) + public TestClient(bool synchronousCallbacks = false, IHubProtocol protocol = null) { var options = new ChannelOptimizations { AllowSynchronousContinuations = synchronousCallbacks }; var transportToApplication = Channel.CreateUnbounded(options); @@ -41,7 +41,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests Connection.User = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, Interlocked.Increment(ref _id).ToString()) })); Connection.Metadata["ConnectedTask"] = new TaskCompletionSource(); - var protocol = new JsonHubProtocol(new JsonSerializer()); + protocol = protocol ?? new JsonHubProtocol(new JsonSerializer()); _protocolReaderWriter = new HubProtocolReaderWriter(protocol, new PassThroughEncoder()); _cts = new CancellationTokenSource(); From 126901a08f3ab47a107c2e02068ae5a3466aa56b Mon Sep 17 00:00:00 2001 From: Pawel Kadluczka Date: Wed, 20 Sep 2017 16:24:21 -0700 Subject: [PATCH 2/4] Adding default ctors for HubProtocols --- .../HubConnectionBuilder.cs | 2 +- .../HubConnectionBuilderExtensions.cs | 4 +-- .../Internal/Protocol/JsonHubProtocol.cs | 9 ++++++ .../Protocol/MessagePackHubProtocol.cs | 4 +++ .../HubConnectionTests.cs | 4 +-- .../HubConnectionExtensionsTests.cs | 4 +-- .../HubConnectionProtocolTests.cs | 30 +++++++++---------- .../HubConnectionTests.cs | 4 +-- .../Internal/Protocol/JsonHubProtocolTests.cs | 4 +-- .../Protocol/MessagePackHubProtocolTests.cs | 2 +- .../DefaultHubProtocolResolverTests.cs | 4 +-- .../TestClient.cs | 2 +- 12 files changed, 43 insertions(+), 30 deletions(-) diff --git a/src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnectionBuilder.cs b/src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnectionBuilder.cs index 2dca887414..81fb12c56b 100644 --- a/src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnectionBuilder.cs +++ b/src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnectionBuilder.cs @@ -46,7 +46,7 @@ namespace Microsoft.AspNetCore.SignalR.Client var loggerFactory = ((IHubConnectionBuilder)this).GetLoggerFactory(); var hubProtocol = ((IHubConnectionBuilder)this).GetHubProtocol(); - return new HubConnection(connection, hubProtocol ?? new JsonHubProtocol(new JsonSerializer()), loggerFactory); + return new HubConnection(connection, hubProtocol ?? new JsonHubProtocol(), loggerFactory); } [EditorBrowsable(EditorBrowsableState.Never)] diff --git a/src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnectionBuilderExtensions.cs b/src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnectionBuilderExtensions.cs index fdfe9aef73..d060f8dda6 100644 --- a/src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnectionBuilderExtensions.cs +++ b/src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnectionBuilderExtensions.cs @@ -18,13 +18,13 @@ namespace Microsoft.AspNetCore.SignalR.Client public static IHubConnectionBuilder WithJsonProtocol(this IHubConnectionBuilder hubConnectionBuilder) { - return hubConnectionBuilder.WithHubProtocol(new JsonHubProtocol(new JsonSerializer())); + return hubConnectionBuilder.WithHubProtocol(new JsonHubProtocol()); } public static IHubConnectionBuilder WithMessagePackProtocol(this IHubConnectionBuilder hubConnectionBuilder) { return hubConnectionBuilder.WithHubProtocol( - new MessagePackHubProtocol(MessagePackHubProtocol.CreateDefaultSerializationContext())); + new MessagePackHubProtocol()); } public static IHubConnectionBuilder WithLoggerFactory(this IHubConnectionBuilder hubConnectionBuilder, ILoggerFactory loggerFactory) diff --git a/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/JsonHubProtocol.cs b/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/JsonHubProtocol.cs index 4bf45cd274..a4fc7cbe88 100644 --- a/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/JsonHubProtocol.cs +++ b/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/JsonHubProtocol.cs @@ -28,6 +28,15 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Protocol // ONLY to be used for application payloads (args, return values, etc.) private JsonSerializer _payloadSerializer; + /// + /// Creates an instance of the using the default + /// to serialize application payloads (arguments, results, etc.). The serialization of the outer protocol can + /// NOT be changed using this serializer. + /// + public JsonHubProtocol() + : this(new JsonSerializer()) + { } + /// /// Creates an instance of the using the specified /// to serialize application payloads (arguments, results, etc.). The serialization of the outer protocol can diff --git a/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/MessagePackHubProtocol.cs b/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/MessagePackHubProtocol.cs index 77ad478fc1..c75c681222 100644 --- a/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/MessagePackHubProtocol.cs +++ b/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/MessagePackHubProtocol.cs @@ -26,6 +26,10 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Protocol public ProtocolType Type => ProtocolType.Binary; + public MessagePackHubProtocol() + : this(CreateDefaultSerializationContext()) + { } + public MessagePackHubProtocol(SerializationContext serializationContext) { _serializationContext = serializationContext; diff --git a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs index 39f7ab26ac..b56fecd10e 100644 --- a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs @@ -245,8 +245,8 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public static IEnumerable HubProtocols => new IHubProtocol[] { - new JsonHubProtocol(new JsonSerializer()), - new MessagePackHubProtocol(MessagePackHubProtocol.CreateDefaultSerializationContext()), + new JsonHubProtocol(), + new MessagePackHubProtocol(), }; public static IEnumerable TransportTypes() diff --git a/test/Microsoft.AspNetCore.SignalR.Client.Tests/HubConnectionExtensionsTests.cs b/test/Microsoft.AspNetCore.SignalR.Client.Tests/HubConnectionExtensionsTests.cs index 4c2f15fc2d..34e0a4b9ae 100644 --- a/test/Microsoft.AspNetCore.SignalR.Client.Tests/HubConnectionExtensionsTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Client.Tests/HubConnectionExtensionsTests.cs @@ -97,7 +97,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests private async Task InvokeOn(Action> onAction, object[] args) { var connection = new TestConnection(); - var hubConnection = new HubConnection(connection, new JsonHubProtocol(new JsonSerializer()), new LoggerFactory()); + var hubConnection = new HubConnection(connection, new JsonHubProtocol(), new LoggerFactory()); var handlerTcs = new TaskCompletionSource(); try { @@ -169,7 +169,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests public async Task ConnectionClosedOnCallbackArgumentTypeMismatch() { var connection = new TestConnection(); - var hubConnection = new HubConnection(connection, new JsonHubProtocol(new JsonSerializer()), new LoggerFactory()); + var hubConnection = new HubConnection(connection, new JsonHubProtocol(), new LoggerFactory()); var closeTcs = new TaskCompletionSource(); hubConnection.Closed += e => { diff --git a/test/Microsoft.AspNetCore.SignalR.Client.Tests/HubConnectionProtocolTests.cs b/test/Microsoft.AspNetCore.SignalR.Client.Tests/HubConnectionProtocolTests.cs index d88054e2b9..d51e309668 100644 --- a/test/Microsoft.AspNetCore.SignalR.Client.Tests/HubConnectionProtocolTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Client.Tests/HubConnectionProtocolTests.cs @@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests public async Task SendAsyncSendsANonBlockingInvocationMessage() { var connection = new TestConnection(); - var hubConnection = new HubConnection(connection, new JsonHubProtocol(new JsonSerializer()), new LoggerFactory()); + var hubConnection = new HubConnection(connection, new JsonHubProtocol(), new LoggerFactory()); try { await hubConnection.StartAsync(); @@ -50,7 +50,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests public async Task ClientSendsNegotationMessageWhenStartingConnection() { var connection = new TestConnection(); - var hubConnection = new HubConnection(connection, new JsonHubProtocol(new JsonSerializer()), new LoggerFactory()); + var hubConnection = new HubConnection(connection, new JsonHubProtocol(), new LoggerFactory()); try { await hubConnection.StartAsync(); @@ -69,7 +69,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests public async Task InvokeSendsAnInvocationMessage() { var connection = new TestConnection(); - var hubConnection = new HubConnection(connection, new JsonHubProtocol(new JsonSerializer()), new LoggerFactory()); + var hubConnection = new HubConnection(connection, new JsonHubProtocol(), new LoggerFactory()); try { await hubConnection.StartAsync(); @@ -93,7 +93,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests public async Task StreamSendsAnInvocationMessage() { var connection = new TestConnection(); - var hubConnection = new HubConnection(connection, new JsonHubProtocol(new JsonSerializer()), new LoggerFactory()); + var hubConnection = new HubConnection(connection, new JsonHubProtocol(), new LoggerFactory()); try { await hubConnection.StartAsync(); @@ -121,7 +121,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests public async Task InvokeCompletedWhenCompletionMessageReceived() { var connection = new TestConnection(); - var hubConnection = new HubConnection(connection, new JsonHubProtocol(new JsonSerializer()), new LoggerFactory()); + var hubConnection = new HubConnection(connection, new JsonHubProtocol(), new LoggerFactory()); try { await hubConnection.StartAsync(); @@ -165,7 +165,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests public async Task InvokeYieldsResultWhenCompletionMessageReceived() { var connection = new TestConnection(); - var hubConnection = new HubConnection(connection, new JsonHubProtocol(new JsonSerializer()), new LoggerFactory()); + var hubConnection = new HubConnection(connection, new JsonHubProtocol(), new LoggerFactory()); try { await hubConnection.StartAsync(); @@ -187,7 +187,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests public async Task StreamFailsIfCompletionMessageHasPayload() { var connection = new TestConnection(); - var hubConnection = new HubConnection(connection, new JsonHubProtocol(new JsonSerializer()), new LoggerFactory()); + var hubConnection = new HubConnection(connection, new JsonHubProtocol(), new LoggerFactory()); try { await hubConnection.StartAsync(); @@ -210,7 +210,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests public async Task InvokeFailsWithExceptionWhenCompletionWithErrorReceived() { var connection = new TestConnection(); - var hubConnection = new HubConnection(connection, new JsonHubProtocol(new JsonSerializer()), new LoggerFactory()); + var hubConnection = new HubConnection(connection, new JsonHubProtocol(), new LoggerFactory()); try { await hubConnection.StartAsync(); @@ -233,7 +233,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests public async Task StreamFailsWithExceptionWhenCompletionWithErrorReceived() { var connection = new TestConnection(); - var hubConnection = new HubConnection(connection, new JsonHubProtocol(new JsonSerializer()), new LoggerFactory()); + var hubConnection = new HubConnection(connection, new JsonHubProtocol(), new LoggerFactory()); try { await hubConnection.StartAsync(); @@ -256,7 +256,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests public async Task InvokeFailsWithErrorWhenStreamingItemReceived() { var connection = new TestConnection(); - var hubConnection = new HubConnection(connection, new JsonHubProtocol(new JsonSerializer()), new LoggerFactory()); + var hubConnection = new HubConnection(connection, new JsonHubProtocol(), new LoggerFactory()); try { await hubConnection.StartAsync(); @@ -279,7 +279,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests public async Task StreamYieldsItemsAsTheyArrive() { var connection = new TestConnection(); - var hubConnection = new HubConnection(connection, new JsonHubProtocol(new JsonSerializer()), new LoggerFactory()); + var hubConnection = new HubConnection(connection, new JsonHubProtocol(), new LoggerFactory()); try { await hubConnection.StartAsync(); @@ -306,7 +306,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests public async Task HandlerRegisteredWithOnIsFiredWhenInvocationReceived() { var connection = new TestConnection(); - var hubConnection = new HubConnection(connection, new JsonHubProtocol(new JsonSerializer()), new LoggerFactory()); + var hubConnection = new HubConnection(connection, new JsonHubProtocol(), new LoggerFactory()); var handlerCalled = new TaskCompletionSource(); try { @@ -332,7 +332,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests var connection = new TestConnection(TransferMode.Text); var hubConnection = new HubConnection(connection, - new MessagePackHubProtocol(MessagePackHubProtocol.CreateDefaultSerializationContext()), new LoggerFactory()); + new MessagePackHubProtocol(), new LoggerFactory()); try { await hubConnection.StartAsync().OrTimeout(); @@ -363,7 +363,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests { var connection = new TestConnection(TransferMode.Text); var hubConnection = new HubConnection(connection, - new MessagePackHubProtocol(MessagePackHubProtocol.CreateDefaultSerializationContext()), new LoggerFactory()); + new MessagePackHubProtocol(), new LoggerFactory()); var invocationTcs = new TaskCompletionSource(); try @@ -373,7 +373,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests using (var ms = new MemoryStream()) { - new MessagePackHubProtocol(MessagePackHubProtocol.CreateDefaultSerializationContext()) + new MessagePackHubProtocol() .WriteMessage(new InvocationMessage("1", true, "MyMethod", 42), ms); var invokeMessage = Convert.ToBase64String(ms.ToArray()); diff --git a/test/Microsoft.AspNetCore.SignalR.Client.Tests/HubConnectionTests.cs b/test/Microsoft.AspNetCore.SignalR.Client.Tests/HubConnectionTests.cs index f21ffe604d..3a25409ee3 100644 --- a/test/Microsoft.AspNetCore.SignalR.Client.Tests/HubConnectionTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Client.Tests/HubConnectionTests.cs @@ -100,7 +100,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests public async Task CannotCallInvokeOnClosedHubConnection() { var connection = new TestConnection(); - var hubConnection = new HubConnection(connection, new JsonHubProtocol(new JsonSerializer()), new LoggerFactory()); + var hubConnection = new HubConnection(connection, new JsonHubProtocol(), new LoggerFactory()); await hubConnection.StartAsync(); await hubConnection.DisposeAsync(); @@ -114,7 +114,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests public async Task PendingInvocationsAreCancelledWhenConnectionClosesCleanly() { var connection = new TestConnection(); - var hubConnection = new HubConnection(connection, new JsonHubProtocol(new JsonSerializer()), new LoggerFactory()); + var hubConnection = new HubConnection(connection, new JsonHubProtocol(), new LoggerFactory()); await hubConnection.StartAsync(); var invokeTask = hubConnection.InvokeAsync("testMethod"); diff --git a/test/Microsoft.AspNetCore.SignalR.Common.Tests/Internal/Protocol/JsonHubProtocolTests.cs b/test/Microsoft.AspNetCore.SignalR.Common.Tests/Internal/Protocol/JsonHubProtocolTests.cs index cc652e1d42..c7d3e3cd20 100644 --- a/test/Microsoft.AspNetCore.SignalR.Common.Tests/Internal/Protocol/JsonHubProtocolTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Common.Tests/Internal/Protocol/JsonHubProtocolTests.cs @@ -119,7 +119,7 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Protocol input = Frame(input); var binder = new TestBinder(); - var protocol = new JsonHubProtocol(new JsonSerializer()); + var protocol = new JsonHubProtocol(); var ex = Assert.Throws(() => protocol.TryParseMessages(Encoding.UTF8.GetBytes(input), binder, out var messages)); Assert.Equal(expectedMessage, ex.Message); } @@ -133,7 +133,7 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Protocol input = Frame(input); var binder = new TestBinder(paramTypes: new[] { typeof(int), typeof(string) }, returnType: typeof(bool)); - var protocol = new JsonHubProtocol(new JsonSerializer()); + var protocol = new JsonHubProtocol(); var ex = Assert.Throws(() => protocol.TryParseMessages(Encoding.UTF8.GetBytes(input), binder, out var messages)); Assert.Equal(expectedMessage, ex.Message); } diff --git a/test/Microsoft.AspNetCore.SignalR.Common.Tests/Internal/Protocol/MessagePackHubProtocolTests.cs b/test/Microsoft.AspNetCore.SignalR.Common.Tests/Internal/Protocol/MessagePackHubProtocolTests.cs index 32c45ae11d..18c2464bd3 100644 --- a/test/Microsoft.AspNetCore.SignalR.Common.Tests/Internal/Protocol/MessagePackHubProtocolTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Common.Tests/Internal/Protocol/MessagePackHubProtocolTests.cs @@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Protocol public class MessagePackHubProtocolTests { private static readonly MessagePackHubProtocol _hubProtocol - = new MessagePackHubProtocol(MessagePackHubProtocol.CreateDefaultSerializationContext()); + = new MessagePackHubProtocol(); public static IEnumerable TestMessages => new[] { diff --git a/test/Microsoft.AspNetCore.SignalR.Tests/Internal/DefaultHubProtocolResolverTests.cs b/test/Microsoft.AspNetCore.SignalR.Tests/Internal/DefaultHubProtocolResolverTests.cs index 0b3b604182..b0596994cd 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests/Internal/DefaultHubProtocolResolverTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests/Internal/DefaultHubProtocolResolverTests.cs @@ -41,8 +41,8 @@ namespace Microsoft.AspNetCore.SignalR.Common.Protocol.Tests public static IEnumerable HubProtocols => new[] { - new object[] { new JsonHubProtocol(new JsonSerializer()) }, - new object[] { new MessagePackHubProtocol(MessagePackHubProtocol.CreateDefaultSerializationContext()) }, + new object[] { new JsonHubProtocol() }, + new object[] { new MessagePackHubProtocol() }, }; } } diff --git a/test/Microsoft.AspNetCore.SignalR.Tests/TestClient.cs b/test/Microsoft.AspNetCore.SignalR.Tests/TestClient.cs index 94725fdebe..516a38cab4 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests/TestClient.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests/TestClient.cs @@ -41,7 +41,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests Connection.User = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, Interlocked.Increment(ref _id).ToString()) })); Connection.Metadata["ConnectedTask"] = new TaskCompletionSource(); - protocol = protocol ?? new JsonHubProtocol(new JsonSerializer()); + protocol = protocol ?? new JsonHubProtocol(); _protocolReaderWriter = new HubProtocolReaderWriter(protocol, new PassThroughEncoder()); _cts = new CancellationTokenSource(); From 6ed3f6d1aafa988cc88569f6fbf03d537e4ff670 Mon Sep 17 00:00:00 2001 From: Pawel Kadluczka Date: Wed, 20 Sep 2017 16:46:02 -0700 Subject: [PATCH 3/4] Enabling hub connection with customized hub protocols --- .../HubConnectionBuilderExtensions.cs | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnectionBuilderExtensions.cs b/src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnectionBuilderExtensions.cs index d060f8dda6..e678c97349 100644 --- a/src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnectionBuilderExtensions.cs +++ b/src/Microsoft.AspNetCore.SignalR.Client.Core/HubConnectionBuilderExtensions.cs @@ -4,6 +4,7 @@ using System; using Microsoft.AspNetCore.SignalR.Internal.Protocol; using Microsoft.Extensions.Logging; +using MsgPack.Serialization; using Newtonsoft.Json; namespace Microsoft.AspNetCore.SignalR.Client @@ -21,10 +22,29 @@ namespace Microsoft.AspNetCore.SignalR.Client return hubConnectionBuilder.WithHubProtocol(new JsonHubProtocol()); } + public static IHubConnectionBuilder WithJsonProtocol(this IHubConnectionBuilder hubConnectionBuilder, JsonSerializerSettings serializerSettings) + { + return hubConnectionBuilder.WithHubProtocol(new JsonHubProtocol(JsonSerializer.Create(serializerSettings))); + } + + public static IHubConnectionBuilder WithJsonProtocol(this IHubConnectionBuilder hubConnectionBuilder, JsonSerializer jsonSerializer) + { + return hubConnectionBuilder.WithHubProtocol(new JsonHubProtocol(jsonSerializer)); + } + public static IHubConnectionBuilder WithMessagePackProtocol(this IHubConnectionBuilder hubConnectionBuilder) { - return hubConnectionBuilder.WithHubProtocol( - new MessagePackHubProtocol()); + return hubConnectionBuilder.WithHubProtocol(new MessagePackHubProtocol()); + } + + public static IHubConnectionBuilder WithMessagePackProtocol(this IHubConnectionBuilder hubConnectionBuilder, SerializationContext serializationContext) + { + if (serializationContext == null) + { + throw new ArgumentNullException(nameof(serializationContext)); + } + + return hubConnectionBuilder.WithHubProtocol(new MessagePackHubProtocol(serializationContext)); } public static IHubConnectionBuilder WithLoggerFactory(this IHubConnectionBuilder hubConnectionBuilder, ILoggerFactory loggerFactory) From 4db78685dce1558073959644b9e35c0bc03b3a9f Mon Sep 17 00:00:00 2001 From: Pawel Kadluczka Date: Thu, 21 Sep 2017 15:21:17 -0700 Subject: [PATCH 4/4] camelCasing objects serialized by JsonHubProtocol Fixes: #859 --- samples/ChatSample/Views/Home/Index.cshtml | 12 +++---- .../Internal/Protocol/JsonHubProtocol.cs | 8 ++++- .../HubOptions.cs | 2 +- .../HubEndpointTests.cs | 31 +++++++++++++++++-- 4 files changed, 43 insertions(+), 10 deletions(-) diff --git a/samples/ChatSample/Views/Home/Index.cshtml b/samples/ChatSample/Views/Home/Index.cshtml index 0207c365e6..6089f6a0af 100644 --- a/samples/ChatSample/Views/Home/Index.cshtml +++ b/samples/ChatSample/Views/Home/Index.cshtml @@ -35,15 +35,15 @@ connection.on('SetUsersOnline', usersOnline => { connection.on('UsersJoined', users => { users.forEach(user => { - appendLine('User ' + user.Name + ' joined the chat'); + appendLine('User ' + user.name + ' joined the chat'); addUserOnline(user); }); }); connection.on('UsersLeft', users => { users.forEach(user => { - appendLine('User ' + user.Name + ' left the chat'); - document.getElementById(user.ConnectionId).outerHTML = ''; + appendLine('User ' + user.name + ' left the chat'); + document.getElementById(user.connectionId).outerHTML = ''; }); }); @@ -78,12 +78,12 @@ function appendLine(line, color) { }; function addUserOnline(user) { - if (document.getElementById(user.ConnectionId)) { + if (document.getElementById(user.connectionId)) { return; } var userLi = document.createElement('li'); - userLi.innerText = `${user.Name} (${user.ConnectionId})`; - userLi.id = user.ConnectionId; + userLi.innerText = `${user.name} (${user.connectionId})`; + userLi.id = user.connectionId; document.getElementById('users').appendChild(userLi); } diff --git a/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/JsonHubProtocol.cs b/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/JsonHubProtocol.cs index a4fc7cbe88..fb5aea9f8f 100644 --- a/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/JsonHubProtocol.cs +++ b/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/JsonHubProtocol.cs @@ -7,6 +7,7 @@ using System.IO; using Microsoft.AspNetCore.SignalR.Internal.Formatters; using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using Newtonsoft.Json.Serialization; namespace Microsoft.AspNetCore.SignalR.Internal.Protocol { @@ -34,7 +35,7 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Protocol /// NOT be changed using this serializer. /// public JsonHubProtocol() - : this(new JsonSerializer()) + : this(JsonSerializer.Create(CreateDefaultSerializerSettings())) { } /// @@ -258,5 +259,10 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Protocol return new CompletionMessage(invocationId, error, result: payload, hasResult: true); } } + + public static JsonSerializerSettings CreateDefaultSerializerSettings() + { + return new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }; + } } } diff --git a/src/Microsoft.AspNetCore.SignalR.Core/HubOptions.cs b/src/Microsoft.AspNetCore.SignalR.Core/HubOptions.cs index b1eebb66fd..f652ea6755 100644 --- a/src/Microsoft.AspNetCore.SignalR.Core/HubOptions.cs +++ b/src/Microsoft.AspNetCore.SignalR.Core/HubOptions.cs @@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.SignalR { public class HubOptions { - public JsonSerializerSettings JsonSerializerSettings { get; set; } = new JsonSerializerSettings(); + public JsonSerializerSettings JsonSerializerSettings { get; set; } = JsonHubProtocol.CreateDefaultSerializerSettings(); public SerializationContext MessagePackSerializationContext { get; set; } = MessagePackHubProtocol.CreateDefaultSerializationContext(); } } diff --git a/test/Microsoft.AspNetCore.SignalR.Tests/HubEndpointTests.cs b/test/Microsoft.AspNetCore.SignalR.Tests/HubEndpointTests.cs index 104c32739c..673c3bd1bf 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests/HubEndpointTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests/HubEndpointTests.cs @@ -1008,7 +1008,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests { o.JsonSerializerSettings = new JsonSerializerSettings { - ContractResolver = new CamelCasePropertyNamesContractResolver() + ContractResolver = new DefaultContractResolver() }; }); }); @@ -1026,7 +1026,34 @@ namespace Microsoft.AspNetCore.SignalR.Tests var message = (InvocationMessage)await client.ReadAsync().OrTimeout(); var customItem = message.Arguments[0].ToString(); - // Originally "Message" and "paramName" + // by default properties serialized by JsonHubProtocol are using camelCasing + Assert.Contains("Message", customItem); + Assert.Contains("paramName", customItem); + + client.Dispose(); + + await endPointLifetime.OrTimeout(); + } + } + + [Fact] + public async Task JsonHubProtocolUsesCamelCasingByDefault() + { + var serviceProvider = CreateServiceProvider(); + var endPoint = serviceProvider.GetService>(); + + using (var client = new TestClient()) + { + var endPointLifetime = endPoint.OnConnectedAsync(client.Connection); + + await client.Connected.OrTimeout(); + + await client.SendInvocationAsync(nameof(MethodHub.BroadcastItem)).OrTimeout(); + + var message = (InvocationMessage)await client.ReadAsync().OrTimeout(); + + var customItem = message.Arguments[0].ToString(); + // originally Message, paramName Assert.Contains("message", customItem); Assert.Contains("paramName", customItem);