diff --git a/samples/ChatSample/Views/Home/Index.cshtml b/samples/ChatSample/Views/Home/Index.cshtml index 5e45c8fcf6..d16f51d417 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.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 a6b770d6cc..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 @@ -18,7 +19,17 @@ 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 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) @@ -26,6 +37,16 @@ namespace Microsoft.AspNetCore.SignalR.Client 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) { hubConnectionBuilder.AddSetting(HubConnectionBuilderDefaults.LoggerFactoryKey, diff --git a/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/JsonHubProtocol.cs b/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/JsonHubProtocol.cs index 4bf45cd274..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 { @@ -28,6 +29,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(JsonSerializer.Create(CreateDefaultSerializerSettings())) + { } + /// /// Creates an instance of the using the specified /// to serialize application payloads (arguments, results, etc.). The serialization of the outer protocol can @@ -249,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.Common/Internal/Protocol/MessagePackHubProtocol.cs b/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/MessagePackHubProtocol.cs index 22e90fe437..c75c681222 100644 --- a/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/MessagePackHubProtocol.cs +++ b/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/MessagePackHubProtocol.cs @@ -20,18 +20,19 @@ 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() + : this(CreateDefaultSerializationContext()) + { } + + 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 +157,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 +292,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..f652ea6755 100644 --- a/src/Microsoft.AspNetCore.SignalR.Core/HubOptions.cs +++ b/src/Microsoft.AspNetCore.SignalR.Core/HubOptions.cs @@ -1,12 +1,15 @@ // 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 { 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/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 dbf86e7d66..a9a02a0f72 100644 --- a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs @@ -245,7 +245,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public static IEnumerable HubProtocols => new IHubProtocol[] { - new JsonHubProtocol(new JsonSerializer()), + new JsonHubProtocol(), new MessagePackHubProtocol(), }; 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 c9a8928b4a..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 { @@ -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(), 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(), 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() + .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.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 19ef3b4c4c..18c2464bd3 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(); 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..673c3bd1bf 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; @@ -1005,7 +1008,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests { o.JsonSerializerSettings = new JsonSerializerSettings { - ContractResolver = new CamelCasePropertyNamesContractResolver() + ContractResolver = new DefaultContractResolver() }; }); }); @@ -1020,10 +1023,37 @@ 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" + // 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); @@ -1033,6 +1063,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 +1497,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 +1540,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..b0596994cd 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests/Internal/DefaultHubProtocolResolverTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests/Internal/DefaultHubProtocolResolverTests.cs @@ -41,7 +41,7 @@ namespace Microsoft.AspNetCore.SignalR.Common.Protocol.Tests public static IEnumerable HubProtocols => new[] { - new object[] { new JsonHubProtocol(new JsonSerializer()) }, + new object[] { new JsonHubProtocol() }, new object[] { new MessagePackHubProtocol() }, }; } 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..516a38cab4 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(); _protocolReaderWriter = new HubProtocolReaderWriter(protocol, new PassThroughEncoder()); _cts = new CancellationTokenSource();