Make System.Text.Json the default for SignalR and remove Newtonsoft from shared framework (#9476)

This commit is contained in:
BrennanConroy 2019-04-18 13:49:24 -07:00 committed by GitHub
parent 56c064bd53
commit c84e37f30d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 239 additions and 157 deletions

View File

@ -68,7 +68,6 @@
If these are needed as direct dependencies, it is okay to change them to ExternalAspNetCoreAppReference and move up into sections above.
-->
<_TransitiveExternalAspNetCoreAppReference Include="Newtonsoft.Json" Version="$(NewtonsoftJsonPackageVersion)" />
<_TransitiveExternalAspNetCoreAppReference Include="System.Security.Cryptography.Pkcs" Version="$(SystemSecurityCryptographyPkcsPackageVersion)" />
<_TransitiveExternalAspNetCoreAppReference Include="System.Security.Permissions" Version="$(SystemSecurityPermissionsPackageVersion)" />
</ItemGroup>

View File

@ -12,7 +12,6 @@
<AspNetCoreAppReferenceAndPackage Include="Microsoft.AspNetCore.Connections.Abstractions" />
<AspNetCoreAppReferenceAndPackage Include="Microsoft.AspNetCore.Http.Connections.Common" />
<AspNetCoreAppReferenceAndPackage Include="Microsoft.AspNetCore.SignalR.Protocols.Json" />
<AspNetCoreAppReferenceAndPackage Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" />
<AspNetCoreAppReferenceAndPackage Include="Microsoft.AspNetCore.SignalR.Common" />
<AspNetCoreAppReferenceAndPackage Include="Microsoft.AspNetCore.Components.Browser" />
<AspNetCoreAppReferenceAndPackage Include="Microsoft.AspNetCore.Components" />

View File

@ -79,13 +79,11 @@
<_InvalidReferenceToNonSharedFxAssembly Condition="'$(IsAspNetCoreApp)' == 'true'"
Include="@(Reference)"
Exclude="
Newtonsoft.Json;
@(AspNetCoreAppReference);
@(AspNetCoreAppReferenceAndPackage);
@(ExternalAspNetCoreAppReference);
@(_CompilationOnlyReference);
@(Reference->WithMetadataValue('IsSharedSource', 'true'))" />
<!-- TODO: remove Newtonsoft.Json from this list once https://github.com/aspnet/AspNetCore/issues/4260 is resolved -->
<_OriginalReferences Include="@(Reference)" />
<!--
Turn Reference items into a ProjectReference when UseProjectReferences is true.

View File

@ -6,7 +6,7 @@
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<Compile Include="Microsoft.AspNetCore.SignalR.Client.Core.netstandard2.0.cs" />
<Reference Include="Microsoft.AspNetCore.SignalR.Common" />
<Reference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" />
<Reference Include="Microsoft.AspNetCore.SignalR.Protocols.Json" />
<Reference Include="Microsoft.Extensions.DependencyInjection" />
<Reference Include="Microsoft.Extensions.Logging" />
<Reference Include="System.Threading.Channels" />
@ -14,7 +14,7 @@
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.0'">
<Compile Include="Microsoft.AspNetCore.SignalR.Client.Core.netcoreapp3.0.cs" />
<Reference Include="Microsoft.AspNetCore.SignalR.Common" />
<Reference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" />
<Reference Include="Microsoft.AspNetCore.SignalR.Protocols.Json" />
<Reference Include="Microsoft.Extensions.DependencyInjection" />
<Reference Include="Microsoft.Extensions.Logging" />
<Reference Include="System.Threading.Channels" />

View File

@ -25,7 +25,7 @@ namespace Microsoft.AspNetCore.SignalR.Client
Services = new ServiceCollection();
Services.AddSingleton<HubConnection>();
Services.AddLogging();
this.AddNewtonsoftJsonProtocol();
this.AddJsonProtocol();
}
/// <inheritdoc />

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>Client for ASP.NET Core SignalR</Description>
@ -22,7 +22,7 @@
<ItemGroup>
<Reference Include="Microsoft.AspNetCore.SignalR.Common" />
<Reference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" />
<Reference Include="Microsoft.AspNetCore.SignalR.Protocols.Json" />
<Reference Include="Microsoft.Extensions.DependencyInjection" />
<Reference Include="Microsoft.Extensions.Logging" />
<Reference Include="System.Threading.Channels" />

View File

@ -1014,7 +1014,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests
}
}
[Theory]
[Theory(Skip = "Will be fixed by https://github.com/dotnet/corefx/issues/36901")]
[MemberData(nameof(HubProtocolsAndTransportsAndHubPaths))]
public async Task ServerThrowsHubExceptionOnHubMethodArgumentTypeMismatch(string hubProtocolName, HttpTransportType transportType, string hubPath)
{

View File

@ -10,7 +10,6 @@ namespace FunctionalTests
public string String { get; set; }
public int[] IntArray { get; set; }
public byte[] ByteArray { get; set; }
public Guid GUID { get; set; }
public DateTime DateTime { get;set; }
}
}

View File

@ -41,12 +41,6 @@ namespace FunctionalTests
{
options.EnableDetailedErrors = true;
})
.AddNewtonsoftJsonProtocol(options =>
{
// we are running the same tests with JSON and MsgPack protocols and having
// consistent casing makes it cleaner to verify results
options.PayloadSerializerSettings.ContractResolver = new DefaultContractResolver();
})
.AddMessagePackProtocol();
services.AddCors();

View File

@ -125,7 +125,6 @@ namespace FunctionalTests
{
ByteArray = new byte[] { 0x1, 0x2, 0x3 },
DateTime = new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc),
GUID = new Guid("00010203-0405-0607-0706-050403020100"),
IntArray = new int[] { 1, 2, 3 },
String = "hello world",
};

View File

@ -457,12 +457,11 @@ describe("hubConnection", () => {
const complexObject = {
ByteArray: protocol.name === "json"
? "aGVsbG8="
? new Array(0x68, 0x65, 0x6c, 0x6c, 0x6f)
: new Uint8Array([0x68, 0x65, 0x6c, 0x6c, 0x6f]),
DateTime: protocol.name === "json"
? "2002-04-01T10:20:15Z"
: new Date(Date.UTC(2002, 3, 1, 10, 20, 15)), // Apr 1, 2002, 10:20:15am UTC
GUID: "00010203-0405-0607-0706-050403020100",
IntArray: [0x01, 0x02, 0x03, 0xff],
String: "Hello, World!",
};
@ -500,12 +499,11 @@ describe("hubConnection", () => {
const complexObject = {
ByteArray: protocol.name === "json"
? "AQID"
? new Array(0x1, 0x2, 0x3)
: new Uint8Array([0x1, 0x2, 0x3]),
DateTime: protocol.name === "json"
? "2000-01-01T00:00:00Z"
: new Date(Date.UTC(2000, 0, 1)),
GUID: "00010203-0405-0607-0706-050403020100",
IntArray: [0x01, 0x02, 0x03],
String: "hello world",
};

View File

@ -1,11 +1,22 @@
// 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.
namespace Microsoft.AspNetCore.SignalR
{
public partial class JsonHubProtocolOptions
{
public JsonHubProtocolOptions() { }
public bool AllowTrailingCommas { get { throw null; } set { } }
public bool IgnoreNullValues { get { throw null; } set { } }
public bool WriteIndented { get { throw null; } set { } }
}
}
namespace Microsoft.AspNetCore.SignalR.Protocol
{
public sealed partial class JsonHubProtocol : Microsoft.AspNetCore.SignalR.Protocol.IHubProtocol
{
public JsonHubProtocol() { }
public JsonHubProtocol(Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.SignalR.JsonHubProtocolOptions> options) { }
public int MinorVersion { get { throw null; } }
public string Name { get { throw null; } }
public Microsoft.AspNetCore.Connections.TransferFormat TransferFormat { get { throw null; } }
@ -21,5 +32,6 @@ namespace Microsoft.Extensions.DependencyInjection
public static partial class JsonProtocolDependencyInjectionExtensions
{
public static TBuilder AddJsonProtocol<TBuilder>(this TBuilder builder) where TBuilder : Microsoft.AspNetCore.SignalR.ISignalRBuilder { throw null; }
public static TBuilder AddJsonProtocol<TBuilder>(this TBuilder builder, System.Action<Microsoft.AspNetCore.SignalR.JsonHubProtocolOptions> configure) where TBuilder : Microsoft.AspNetCore.SignalR.ISignalRBuilder { throw null; }
}
}

View File

@ -1,11 +1,22 @@
// 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.
namespace Microsoft.AspNetCore.SignalR
{
public partial class JsonHubProtocolOptions
{
public JsonHubProtocolOptions() { }
public bool AllowTrailingCommas { get { throw null; } set { } }
public bool IgnoreNullValues { get { throw null; } set { } }
public bool WriteIndented { get { throw null; } set { } }
}
}
namespace Microsoft.AspNetCore.SignalR.Protocol
{
public sealed partial class JsonHubProtocol : Microsoft.AspNetCore.SignalR.Protocol.IHubProtocol
{
public JsonHubProtocol() { }
public JsonHubProtocol(Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.SignalR.JsonHubProtocolOptions> options) { }
public int MinorVersion { get { throw null; } }
public string Name { get { throw null; } }
public Microsoft.AspNetCore.Connections.TransferFormat TransferFormat { get { throw null; } }
@ -21,5 +32,6 @@ namespace Microsoft.Extensions.DependencyInjection
public static partial class JsonProtocolDependencyInjectionExtensions
{
public static TBuilder AddJsonProtocol<TBuilder>(this TBuilder builder) where TBuilder : Microsoft.AspNetCore.SignalR.ISignalRBuilder { throw null; }
public static TBuilder AddJsonProtocol<TBuilder>(this TBuilder builder, System.Action<Microsoft.AspNetCore.SignalR.JsonHubProtocolOptions> configure) where TBuilder : Microsoft.AspNetCore.SignalR.ISignalRBuilder { throw null; }
}
}

View File

@ -0,0 +1,25 @@
// 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 System.Text.Json.Serialization;
using Microsoft.AspNetCore.SignalR.Protocol;
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// Options used to configure a <see cref="JsonHubProtocolOptions"/> instance.
/// </summary>
public class JsonHubProtocolOptions
{
internal readonly JsonSerializerOptions _serializerOptions;
public JsonHubProtocolOptions()
{
_serializerOptions = JsonHubProtocol.CreateDefaultSerializerSettings();
}
public bool IgnoreNullValues { get => _serializerOptions.IgnoreNullValues; set => _serializerOptions.IgnoreNullValues = value; }
public bool WriteIndented { get => _serializerOptions.WriteIndented; set => _serializerOptions.WriteIndented = value; }
public bool AllowTrailingCommas { get => _serializerOptions.AllowTrailingCommas; set => _serializerOptions.AllowTrailingCommas = value; }
}
}

View File

@ -1,6 +1,7 @@
// 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 System;
using Microsoft.AspNetCore.SignalR;
using Microsoft.AspNetCore.SignalR.Protocol;
using Microsoft.Extensions.DependencyInjection.Extensions;
@ -21,8 +22,21 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="builder">The <see cref="ISignalRBuilder"/> representing the SignalR server to add JSON protocol support to.</param>
/// <returns>The value of <paramref name="builder"/></returns>
public static TBuilder AddJsonProtocol<TBuilder>(this TBuilder builder) where TBuilder : ISignalRBuilder
=> AddJsonProtocol(builder, _ => { });
/// <summary>
/// Enables the JSON protocol for SignalR and allows options for the JSON protocol to be configured.
/// </summary>
/// <remarks>
/// Any options configured here will be applied, even if the JSON protocol has already been registered with the server.
/// </remarks>
/// <param name="builder">The <see cref="ISignalRBuilder"/> representing the SignalR server to add JSON protocol support to.</param>
/// <param name="configure">A delegate that can be used to configure the <see cref="JsonHubProtocolOptions"/></param>
/// <returns>The value of <paramref name="builder"/></returns>
public static TBuilder AddJsonProtocol<TBuilder>(this TBuilder builder, Action<JsonHubProtocolOptions> configure) where TBuilder : ISignalRBuilder
{
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IHubProtocol, JsonHubProtocol>());
builder.Services.Configure(configure);
return builder;
}
}

View File

@ -21,7 +21,7 @@
<Reference Include="Microsoft.AspNetCore.SignalR.Common" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'" >
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<Reference Include="Microsoft.Bcl.Json.Sources" />
<Reference Include="System.Buffers" />
<Reference Include="System.Runtime.CompilerServices.Unsafe" />

View File

@ -10,6 +10,7 @@ using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.Internal;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.SignalR.Protocol
{
@ -42,13 +43,27 @@ namespace Microsoft.AspNetCore.SignalR.Protocol
private static readonly int ProtocolVersion = 1;
private static readonly int ProtocolMinorVersion = 0;
/// <summary>
/// Gets the serializer used to serialize invocation arguments and return values.
/// </summary>
private readonly JsonSerializerOptions _payloadSerializerOptions;
/// <summary>
/// Initializes a new instance of the <see cref="JsonHubProtocol"/> class.
/// </summary>
public JsonHubProtocol()
public JsonHubProtocol() : this(Options.Create(new JsonHubProtocolOptions()))
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JsonHubProtocol"/> class.
/// </summary>
/// <param name="options">The options used to initialize the protocol.</param>
public JsonHubProtocol(IOptions<JsonHubProtocolOptions> options)
{
_payloadSerializerOptions = options.Value._serializerOptions;
}
/// <inheritdoc />
public string Name => ProtocolName;
@ -188,13 +203,10 @@ namespace Microsoft.AspNetCore.SignalR.Protocol
{
// If we have an invocation id already we can parse the end result
var returnType = binder.GetReturnType(invocationId);
if (reader.TokenType != JsonTokenType.Null)
{
using var token = JsonDocument.ParseValue(ref reader);
result = BindType(token.RootElement, returnType);
}
}
}
else if (reader.TextEquals(ItemPropertyNameBytes))
{
reader.CheckRead();
@ -216,12 +228,9 @@ namespace Microsoft.AspNetCore.SignalR.Protocol
try
{
var itemType = binder.GetStreamItemType(id);
if (reader.TokenType != JsonTokenType.Null)
{
using var token = JsonDocument.ParseValue(ref reader);
item = BindType(token.RootElement, itemType);
}
}
catch (Exception ex)
{
return new StreamBindingFailureMessage(id, ExceptionDispatchInfo.Capture(ex));
@ -571,7 +580,7 @@ namespace Microsoft.AspNetCore.SignalR.Protocol
private JsonDocument GetParsedObject(object obj, Type type)
{
var bytes = JsonSerializer.ToBytes(obj, type);
var bytes = JsonSerializer.ToBytes(obj, type, _payloadSerializerOptions);
var token = JsonDocument.Parse(bytes);
return token;
}
@ -695,11 +704,7 @@ namespace Microsoft.AspNetCore.SignalR.Protocol
return jsonObject.GetDateTimeOffset();
}
if (jsonObject.Type == JsonValueType.Null)
{
return null;
}
return JsonSerializer.Parse(jsonObject.GetRawText(), type);
return JsonSerializer.Parse(jsonObject.GetRawText(), type, _payloadSerializerOptions);
}
private object[] BindTypes(JsonElement jsonArray, IReadOnlyList<Type> paramTypes)
@ -756,5 +761,18 @@ namespace Microsoft.AspNetCore.SignalR.Protocol
return message;
}
internal static JsonSerializerOptions CreateDefaultSerializerSettings()
{
var options = new JsonSerializerOptions();
options.WriteIndented = false;
options.ReadCommentHandling = JsonCommentHandling.Disallow;
options.AllowTrailingCommas = false;
options.IgnoreNullValues = false;
options.IgnoreReadOnlyProperties = false;
// TODO: camelCase
return options;
}
}
}

View File

@ -3,8 +3,6 @@
<PropertyGroup>
<Description>Implements the SignalR Hub Protocol using Newtonsoft.Json.</Description>
<TargetFramework>netstandard2.0</TargetFramework>
<!-- TODO: remove this from the shared framework once we have a JSON protocol implementation which doesn't use Newtonsoft.Json. -->
<IsAspNetCoreApp>true</IsAspNetCoreApp>
<RootNamespace>Microsoft.AspNetCore.SignalR</RootNamespace>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<IsShippingPackage>true</IsShippingPackage>

View File

@ -9,6 +9,7 @@ using System.Linq;
using System.Text;
using Microsoft.AspNetCore.Internal;
using Microsoft.AspNetCore.SignalR.Protocol;
using Microsoft.Extensions.Options;
using Xunit;
namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Protocol
@ -17,6 +18,17 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Protocol
{
protected override IHubProtocol JsonHubProtocol => new JsonHubProtocol();
protected override IHubProtocol GetProtocolWithOptions(bool useCamelCase, bool ignoreNullValues)
{
var protocolOptions = new JsonHubProtocolOptions()
{
IgnoreNullValues = ignoreNullValues,
//TODO: camelCase
};
return new JsonHubProtocol(Options.Create(protocolOptions));
}
[Theory]
[InlineData("", "Error reading JSON.")]
[InlineData("42", "Unexpected JSON Token Type 'Number'. Expected a JSON Object.")]
@ -42,7 +54,8 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Protocol
var writer = MemoryBufferWriter.Get();
try
{
JsonHubProtocol.WriteMessage(testData.Message, writer);
var protocol = GetProtocolWithOptions(testData.UseCamelCase, testData.IgnoreNullValues);
protocol.WriteMessage(testData.Message, writer);
var json = Encoding.UTF8.GetString(writer.ToArray());
Assert.Equal(expectedOutput, json);
@ -63,7 +76,8 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Protocol
var binder = new TestBinder(testData.Message);
var data = new ReadOnlySequence<byte>(Encoding.UTF8.GetBytes(input));
JsonHubProtocol.TryParseMessage(ref data, binder, out var message);
var protocol = GetProtocolWithOptions(testData.UseCamelCase, testData.IgnoreNullValues);
protocol.TryParseMessage(ref data, binder, out var message);
Assert.Equal(testData.Message, message, TestHubMessageEqualityComparer.Instance);
}
@ -83,11 +97,11 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Protocol
public static IDictionary<string, JsonProtocolTestData> CustomProtocolTestData => new[]
{
new JsonProtocolTestData("InvocationMessage_HasFloatArgument", new InvocationMessage(null, "Target", new object[] { 1, "Foo", 2.0f }), "{\"type\":1,\"target\":\"Target\",\"arguments\":[1,\"Foo\",2]}"),
new JsonProtocolTestData("StreamItemMessage_HasFloatItem", new StreamItemMessage("123", 2.0f), "{\"type\":2,\"invocationId\":\"123\",\"item\":2}"),
new JsonProtocolTestData("CompletionMessage_HasFloatResult", CompletionMessage.WithResult("123", 2.0f), "{\"type\":3,\"invocationId\":\"123\",\"result\":2}"),
new JsonProtocolTestData("StreamInvocationMessage_HasFloatArgument", new StreamInvocationMessage("123", "Target", new object[] { 1, "Foo", 2.0f }), "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[1,\"Foo\",2]}"),
new JsonProtocolTestData("InvocationMessage_StringIsoDateArgument", new InvocationMessage("Method", new object[] { "2016-05-10T13:51:20+12:34" }), "{\"type\":1,\"target\":\"Method\",\"arguments\":[\"2016-05-10T13:51:20\\u002b12:34\"]}"),
new JsonProtocolTestData("InvocationMessage_HasFloatArgument", new InvocationMessage(null, "Target", new object[] { 1, "Foo", 2.0f }), true, true, "{\"type\":1,\"target\":\"Target\",\"arguments\":[1,\"Foo\",2]}"),
new JsonProtocolTestData("StreamItemMessage_HasFloatItem", new StreamItemMessage("123", 2.0f), true, true, "{\"type\":2,\"invocationId\":\"123\",\"item\":2}"),
new JsonProtocolTestData("CompletionMessage_HasFloatResult", CompletionMessage.WithResult("123", 2.0f), true, true, "{\"type\":3,\"invocationId\":\"123\",\"result\":2}"),
new JsonProtocolTestData("StreamInvocationMessage_HasFloatArgument", new StreamInvocationMessage("123", "Target", new object[] { 1, "Foo", 2.0f }), true, true, "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[1,\"Foo\",2]}"),
new JsonProtocolTestData("InvocationMessage_StringIsoDateArgument", new InvocationMessage("Method", new object[] { "2016-05-10T13:51:20+12:34" }), true, true, "{\"type\":1,\"target\":\"Method\",\"arguments\":[\"2016-05-10T13:51:20\\u002b12:34\"]}"),
}.ToDictionary(t => t.Name);
public static IEnumerable<object[]> CustomProtocolTestDataNames => CustomProtocolTestData.Keys.Select(name => new object[] { name });

View File

@ -19,6 +19,8 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Protocol
{
protected abstract IHubProtocol JsonHubProtocol { get; }
protected abstract IHubProtocol GetProtocolWithOptions(bool useCamelCase, bool ignoreNullValues);
public static readonly IDictionary<string, string> TestHeaders = new Dictionary<string, string>
{
{ "Foo", "Bar" },
@ -31,18 +33,18 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Protocol
public static IDictionary<string, JsonProtocolTestData> ProtocolTestData => new[]
{
new JsonProtocolTestData("InvocationMessage_HasInvocationId", new InvocationMessage("123", "Target", new object[] { 1, "Foo" }), "{\"type\":1,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[1,\"Foo\"]}"),
new JsonProtocolTestData("InvocationMessage_HasBoolArgument", new InvocationMessage(null, "Target", new object[] { true }), "{\"type\":1,\"target\":\"Target\",\"arguments\":[true]}"),
new JsonProtocolTestData("InvocationMessage_HasNullArgument", new InvocationMessage(null, "Target", new object[] { null }), "{\"type\":1,\"target\":\"Target\",\"arguments\":[null]}"),
new JsonProtocolTestData("InvocationMessage_HasStreamArgument", new InvocationMessage(null, "Target", Array.Empty<object>(), new string[] { "__test_id__" }), "{\"type\":1,\"target\":\"Target\",\"arguments\":[],\"streamIds\":[\"__test_id__\"]}"),
new JsonProtocolTestData("InvocationMessage_HasStreamAndNormalArgument", new InvocationMessage(null, "Target", new object[] { 42 }, new string[] { "__test_id__" }), "{\"type\":1,\"target\":\"Target\",\"arguments\":[42],\"streamIds\":[\"__test_id__\"]}"),
new JsonProtocolTestData("InvocationMessage_HasMultipleStreams", new InvocationMessage(null, "Target", Array.Empty<object>(), new string[] { "__test_id__", "__test_id2__" }), "{\"type\":1,\"target\":\"Target\",\"arguments\":[],\"streamIds\":[\"__test_id__\",\"__test_id2__\"]}"),
new JsonProtocolTestData("InvocationMessage_DateTimeOffsetArgument", new InvocationMessage("Method", new object[] { DateTimeOffset.Parse("2016-05-10T13:51:20+12:34") }), "{\"type\":1,\"target\":\"Method\",\"arguments\":[\"2016-05-10T13:51:20+12:34\"]}"),
new JsonProtocolTestData("InvocationMessage_HasInvocationId", new InvocationMessage("123", "Target", new object[] { 1, "Foo" }), true, true, "{\"type\":1,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[1,\"Foo\"]}"),
new JsonProtocolTestData("InvocationMessage_HasBoolArgument", new InvocationMessage(null, "Target", new object[] { true }), true, true, "{\"type\":1,\"target\":\"Target\",\"arguments\":[true]}"),
new JsonProtocolTestData("InvocationMessage_HasNullArgument", new InvocationMessage(null, "Target", new object[] { null }), true, true, "{\"type\":1,\"target\":\"Target\",\"arguments\":[null]}"),
new JsonProtocolTestData("InvocationMessage_HasStreamArgument", new InvocationMessage(null, "Target", Array.Empty<object>(), new string[] { "__test_id__" }), true, true, "{\"type\":1,\"target\":\"Target\",\"arguments\":[],\"streamIds\":[\"__test_id__\"]}"),
new JsonProtocolTestData("InvocationMessage_HasStreamAndNormalArgument", new InvocationMessage(null, "Target", new object[] { 42 }, new string[] { "__test_id__" }), true, true, "{\"type\":1,\"target\":\"Target\",\"arguments\":[42],\"streamIds\":[\"__test_id__\"]}"),
new JsonProtocolTestData("InvocationMessage_HasMultipleStreams", new InvocationMessage(null, "Target", Array.Empty<object>(), new string[] { "__test_id__", "__test_id2__" }), true, true, "{\"type\":1,\"target\":\"Target\",\"arguments\":[],\"streamIds\":[\"__test_id__\",\"__test_id2__\"]}"),
new JsonProtocolTestData("InvocationMessage_DateTimeOffsetArgument", new InvocationMessage("Method", new object[] { DateTimeOffset.Parse("2016-05-10T13:51:20+12:34") }), true, true, "{\"type\":1,\"target\":\"Method\",\"arguments\":[\"2016-05-10T13:51:20+12:34\"]}"),
new JsonProtocolTestData("StreamItemMessage_HasIntegerItem", new StreamItemMessage("123", 1), "{\"type\":2,\"invocationId\":\"123\",\"item\":1}"),
new JsonProtocolTestData("StreamItemMessage_HasStringItem", new StreamItemMessage("123", "Foo"), "{\"type\":2,\"invocationId\":\"123\",\"item\":\"Foo\"}"),
new JsonProtocolTestData("StreamItemMessage_HasBoolItem", new StreamItemMessage("123", true), "{\"type\":2,\"invocationId\":\"123\",\"item\":true}"),
new JsonProtocolTestData("StreamItemMessage_HasNullItem", new StreamItemMessage("123", null), "{\"type\":2,\"invocationId\":\"123\",\"item\":null}"),
new JsonProtocolTestData("StreamItemMessage_HasIntegerItem", new StreamItemMessage("123", 1), true, true, "{\"type\":2,\"invocationId\":\"123\",\"item\":1}"),
new JsonProtocolTestData("StreamItemMessage_HasStringItem", new StreamItemMessage("123", "Foo"), true, true, "{\"type\":2,\"invocationId\":\"123\",\"item\":\"Foo\"}"),
new JsonProtocolTestData("StreamItemMessage_HasBoolItem", new StreamItemMessage("123", true), true, true, "{\"type\":2,\"invocationId\":\"123\",\"item\":true}"),
new JsonProtocolTestData("StreamItemMessage_HasNullItem", new StreamItemMessage("123", null), true, true, "{\"type\":2,\"invocationId\":\"123\",\"item\":null}"),
// Dictionary not supported yet
//new JsonProtocolTestData("StreamItemMessage_HasHeaders", AddHeaders(TestHeaders, new StreamItemMessage("123", new CustomObject())), "{\"type\":2," + SerializedHeaders + ",\"invocationId\":\"123\",\"item\":{\"StringProp\":\"SignalR!\",\"DoubleProp\":6.2831853071,\"IntProp\":42,\"DateTimeProp\":\"2017-04-11T00:00:00Z\",\"NullProp\":null,\"ByteArrProp\":[1,2,3]}}"),
@ -50,25 +52,26 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Protocol
//new JsonProtocolTestData("StreamInvocationMessage_HasHeaders", AddHeaders(TestHeaders, new StreamInvocationMessage("123", "Target", new object[] { new CustomObject() })), "{\"type\":4," + SerializedHeaders + ",\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[{\"StringProp\":\"SignalR!\",\"DoubleProp\":6.2831853071,\"IntProp\":42,\"DateTimeProp\":\"2017-04-11T00:00:00Z\",\"NullProp\":null,\"ByteArrProp\":[1,2,3]}]}"),
//new JsonProtocolTestData("CancelInvocationMessage_HasHeaders", AddHeaders(TestHeaders, new CancelInvocationMessage("123")), "{\"type\":5," + SerializedHeaders + ",\"invocationId\":\"123\"}"),
new JsonProtocolTestData("CompletionMessage_HasIntegerResult", CompletionMessage.WithResult("123", 1), "{\"type\":3,\"invocationId\":\"123\",\"result\":1}"),
new JsonProtocolTestData("CompletionMessage_HasStringResult", CompletionMessage.WithResult("123", "Foo"), "{\"type\":3,\"invocationId\":\"123\",\"result\":\"Foo\"}"),
new JsonProtocolTestData("CompletionMessage_HasBoolResult", CompletionMessage.WithResult("123", true), "{\"type\":3,\"invocationId\":\"123\",\"result\":true}"),
new JsonProtocolTestData("CompletionMessage_HasNullResult", CompletionMessage.WithResult("123", null), "{\"type\":3,\"invocationId\":\"123\",\"result\":null}"),
new JsonProtocolTestData("CompletionMessage_HasError", CompletionMessage.WithError("123", "Whoops!"), "{\"type\":3,\"invocationId\":\"123\",\"error\":\"Whoops!\"}"),
new JsonProtocolTestData("CompletionMessage_HasErrorAndHeaders", AddHeaders(TestHeaders, CompletionMessage.WithError("123", "Whoops!")), "{\"type\":3," + SerializedHeaders + ",\"invocationId\":\"123\",\"error\":\"Whoops!\"}"),
new JsonProtocolTestData("CompletionMessage_HasIntegerResult", CompletionMessage.WithResult("123", 1), true, true, "{\"type\":3,\"invocationId\":\"123\",\"result\":1}"),
new JsonProtocolTestData("CompletionMessage_HasStringResult", CompletionMessage.WithResult("123", "Foo"), true, true, "{\"type\":3,\"invocationId\":\"123\",\"result\":\"Foo\"}"),
new JsonProtocolTestData("CompletionMessage_HasBoolResult", CompletionMessage.WithResult("123", true), true, true, "{\"type\":3,\"invocationId\":\"123\",\"result\":true}"),
new JsonProtocolTestData("CompletionMessage_HasNullResult", CompletionMessage.WithResult("123", null), true, true, "{\"type\":3,\"invocationId\":\"123\",\"result\":null}"),
new JsonProtocolTestData("CompletionMessage_HasError", CompletionMessage.WithError("123", "Whoops!"), true, true, "{\"type\":3,\"invocationId\":\"123\",\"error\":\"Whoops!\"}"),
new JsonProtocolTestData("CompletionMessage_HasErrorAndHeaders", AddHeaders(TestHeaders, CompletionMessage.WithError("123", "Whoops!")), true, true, "{\"type\":3," + SerializedHeaders + ",\"invocationId\":\"123\",\"error\":\"Whoops!\"}"),
new JsonProtocolTestData("StreamInvocationMessage_HasInvocationId", new StreamInvocationMessage("123", "Target", new object[] { 1, "Foo" }), "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[1,\"Foo\"]}"),
new JsonProtocolTestData("StreamInvocationMessage_HasBoolArgument", new StreamInvocationMessage("123", "Target", new object[] { true }), "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[true]}"),
new JsonProtocolTestData("StreamInvocationMessage_HasNullArgument", new StreamInvocationMessage("123", "Target", new object[] { null }), "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[null]}"),
new JsonProtocolTestData("StreamInvocationMessage_HasStreamArgument", new StreamInvocationMessage("123", "Target", Array.Empty<object>(), new string[] { "__test_id__" }), "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[],\"streamIds\":[\"__test_id__\"]}"),
new JsonProtocolTestData("StreamInvocationMessage_HasInvocationId", new StreamInvocationMessage("123", "Target", new object[] { 1, "Foo" }), true, true, "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[1,\"Foo\"]}"),
new JsonProtocolTestData("StreamInvocationMessage_HasBoolArgument", new StreamInvocationMessage("123", "Target", new object[] { true }), true, true, "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[true]}"),
new JsonProtocolTestData("StreamInvocationMessage_HasNullArgument", new StreamInvocationMessage("123", "Target", new object[] { null }), true, true, "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[null]}"),
new JsonProtocolTestData("StreamInvocationMessage_HasStreamArgument", new StreamInvocationMessage("123", "Target", Array.Empty<object>(), new string[] { "__test_id__" }), true, true, "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[],\"streamIds\":[\"__test_id__\"]}"),
new JsonProtocolTestData("CancelInvocationMessage_HasInvocationId", new CancelInvocationMessage("123"), "{\"type\":5,\"invocationId\":\"123\"}"),
new JsonProtocolTestData("CancelInvocationMessage_HasInvocationId", new CancelInvocationMessage("123"), true, true, "{\"type\":5,\"invocationId\":\"123\"}"),
new JsonProtocolTestData("PingMessage", PingMessage.Instance, "{\"type\":6}"),
new JsonProtocolTestData("PingMessage", PingMessage.Instance, true, true, "{\"type\":6}"),
new JsonProtocolTestData("CloseMessage", CloseMessage.Empty, "{\"type\":7}"),
new JsonProtocolTestData("CloseMessage_HasError", new CloseMessage("Error!"), "{\"type\":7,\"error\":\"Error!\"}"),
new JsonProtocolTestData("CloseMessage_HasErrorEmptyString", new CloseMessage(""), "{\"type\":7,\"error\":\"\"}"),
new JsonProtocolTestData("CloseMessage", CloseMessage.Empty, false, true, "{\"type\":7}"),
new JsonProtocolTestData("CloseMessage_HasError", new CloseMessage("Error!"), false, true, "{\"type\":7,\"error\":\"Error!\"}"),
new JsonProtocolTestData("CloseMessage_HasErrorEmptyString", new CloseMessage(""), false, true, "{\"type\":7,\"error\":\"\"}"),
new JsonProtocolTestData("CloseMessage_HasErrorWithCamelCase", new CloseMessage("Error!"), true, true, "{\"type\":7,\"error\":\"Error!\"}"),
}.ToDictionary(t => t.Name);
@ -76,13 +79,12 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Protocol
public static IDictionary<string, JsonProtocolTestData> OutOfOrderJsonTestData => new[]
{
new JsonProtocolTestData("InvocationMessage_StringIsoDateArgumentFirst", new InvocationMessage("Method", new object[] { "2016-05-10T13:51:20+12:34" }), "{ \"arguments\": [\"2016-05-10T13:51:20+12:34\"], \"type\":1, \"target\": \"Method\" }"),
//new JsonProtocolTestData("InvocationMessage_StringIsoDateArgumentFirst", new InvocationMessage("Method", new object[] { "2016-05-10T13:51:20+12:34" }), false, "{ \"arguments\": [\"2016-05-10T13:51:20+12:34\"], \"type\":1, \"target\": \"Method\" }"),
//new JsonProtocolTestData("InvocationMessage_DateTimeOffsetArgumentFirst", new InvocationMessage("Method", new object[] { DateTimeOffset.Parse("2016-05-10T13:51:20+12:34") }), false, "{ \"arguments\": [\"2016-05-10T13:51:20+12:34\"], \"type\":1, \"target\": \"Method\" }"),
new JsonProtocolTestData("InvocationMessage_IntegerArrayArgumentFirst", new InvocationMessage("Method", new object[] { 1, 2 }), "{ \"arguments\": [1,2], \"type\":1, \"target\": \"Method\" }"),
new JsonProtocolTestData("StreamInvocationMessage_IntegerArrayArgumentFirst", new StreamInvocationMessage("3", "Method", new object[] { 1, 2 }), "{ \"type\":4, \"arguments\": [1,2], \"target\": \"Method\", \"invocationId\": \"3\" }"),
new JsonProtocolTestData("CompletionMessage_ResultFirst", new CompletionMessage("15", null, 10, hasResult: true), "{ \"type\":3, \"result\": 10, \"invocationId\": \"15\" }"),
new JsonProtocolTestData("StreamItemMessage_ItemFirst", new StreamItemMessage("1a", "foo"), "{ \"item\": \"foo\", \"invocationId\": \"1a\", \"type\":2 }")
new JsonProtocolTestData("InvocationMessage_StringIsoDateArgumentFirst", new InvocationMessage("Method", new object[] { "2016-05-10T13:51:20+12:34" }), false, true, "{ \"arguments\": [\"2016-05-10T13:51:20+12:34\"], \"type\":1, \"target\": \"Method\" }"),
new JsonProtocolTestData("InvocationMessage_DateTimeOffsetArgumentFirst", new InvocationMessage("Method", new object[] { DateTimeOffset.Parse("2016-05-10T13:51:20+12:34") }), false, true, "{ \"arguments\": [\"2016-05-10T13:51:20+12:34\"], \"type\":1, \"target\": \"Method\" }"),
new JsonProtocolTestData("InvocationMessage_IntegerArrayArgumentFirst", new InvocationMessage("Method", new object[] { 1, 2 }), false, true, "{ \"arguments\": [1,2], \"type\":1, \"target\": \"Method\" }"),
new JsonProtocolTestData("StreamInvocationMessage_IntegerArrayArgumentFirst", new StreamInvocationMessage("3", "Method", new object[] { 1, 2 }), false, true, "{ \"type\":4, \"arguments\": [1,2], \"target\": \"Method\", \"invocationId\": \"3\" }"),
new JsonProtocolTestData("CompletionMessage_ResultFirst", new CompletionMessage("15", null, 10, hasResult: true), false, true, "{ \"type\":3, \"result\": 10, \"invocationId\": \"15\" }"),
new JsonProtocolTestData("StreamItemMessage_ItemFirst", new StreamItemMessage("1a", "foo"), false, true, "{ \"item\": \"foo\", \"invocationId\": \"1a\", \"type\":2 }")
}.ToDictionary(t => t.Name);
@ -99,7 +101,8 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Protocol
var writer = MemoryBufferWriter.Get();
try
{
JsonHubProtocol.WriteMessage(testData.Message, writer);
var protocol = GetProtocolWithOptions(testData.UseCamelCase, testData.IgnoreNullValues);
protocol.WriteMessage(testData.Message, writer);
var json = Encoding.UTF8.GetString(writer.ToArray());
Assert.Equal(expectedOutput, json);
@ -120,7 +123,8 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Protocol
var binder = new TestBinder(testData.Message);
var data = new ReadOnlySequence<byte>(Encoding.UTF8.GetBytes(input));
JsonHubProtocol.TryParseMessage(ref data, binder, out var message);
var protocol = GetProtocolWithOptions(testData.UseCamelCase, testData.IgnoreNullValues);
protocol.TryParseMessage(ref data, binder, out var message);
Assert.Equal(testData.Message, message, TestHubMessageEqualityComparer.Instance);
}
@ -179,7 +183,8 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Protocol
var binder = new TestBinder(testData.Message);
var data = new ReadOnlySequence<byte>(Encoding.UTF8.GetBytes(input));
JsonHubProtocol.TryParseMessage(ref data, binder, out var message);
var protocol = GetProtocolWithOptions(testData.UseCamelCase, testData.IgnoreNullValues);
protocol.TryParseMessage(ref data, binder, out var message);
Assert.Equal(testData.Message, message, TestHubMessageEqualityComparer.Instance);
}
@ -205,7 +210,8 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Protocol
[InlineData("{\"type\":4,\"invocationId\":\"42\",\"target\":\"foo\",\"arguments\":[ \"abc\", \"xyz\"]}", "Error binding arguments. Make sure that the types of the provided values match the types of the hub method being invoked.")]
[InlineData("{\"type\":1,\"invocationId\":\"42\",\"target\":\"foo\",\"arguments\":[1,\"\",{\"1\":1,\"2\":2}]}", "Invocation provides 3 argument(s) but target expects 2.")]
[InlineData("{\"type\":1,\"arguments\":[1,\"\",{\"1\":1,\"2\":2}]},\"invocationId\":\"42\",\"target\":\"foo\"", "Invocation provides 3 argument(s) but target expects 2.")]
[InlineData("{\"type\":1,\"invocationId\":\"42\",\"target\":\"foo\",\"arguments\":[1,[1]]}", "Error binding arguments. Make sure that the types of the provided values match the types of the hub method being invoked.")]
// Both of these should be fixed by https://github.com/dotnet/corefx/issues/36901
// [InlineData("{\"type\":1,\"invocationId\":\"42\",\"target\":\"foo\",\"arguments\":[1,[1]]}", "Error binding arguments. Make sure that the types of the provided values match the types of the hub method being invoked.")]
// [InlineData("{\"type\":1,\"invocationId\":\"42\",\"target\":\"foo\",\"arguments\":[1,[]]}", "Error binding arguments. Make sure that the types of the provided values match the types of the hub method being invoked.")]
public void ArgumentBindingErrors(string input, string expectedMessage)
{
@ -277,12 +283,16 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Protocol
public string Name { get; }
public HubMessage Message { get; }
public string Json { get; }
public bool UseCamelCase { get; }
public bool IgnoreNullValues { get; }
public JsonProtocolTestData(string name, HubMessage message, string json)
public JsonProtocolTestData(string name, HubMessage message, bool useCamelCase, bool ignoreNullValues, string json)
{
Name = name;
Message = message;
Json = json;
UseCamelCase = useCamelCase;
IgnoreNullValues = ignoreNullValues;
}
public override string ToString() => Name;

View File

@ -22,6 +22,20 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Protocol
{
protected override IHubProtocol JsonHubProtocol => new NewtonsoftJsonHubProtocol();
protected override IHubProtocol GetProtocolWithOptions(bool useCamelCase, bool ignoreNullValues)
{
var protocolOptions = new NewtonsoftJsonHubProtocolOptions
{
PayloadSerializerSettings = new JsonSerializerSettings()
{
NullValueHandling = ignoreNullValues ? NullValueHandling.Ignore : NullValueHandling.Include,
ContractResolver = useCamelCase ? new CamelCasePropertyNamesContractResolver() : new DefaultContractResolver()
}
};
return new NewtonsoftJsonHubProtocol(Options.Create(protocolOptions));
}
[Theory]
[InlineData("", "Unexpected end when reading JSON.")]
[InlineData("42", "Unexpected JSON Token Type 'Integer'. Expected a JSON Object.")]
@ -44,16 +58,7 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Protocol
var expectedOutput = Frame(testData.Json);
var protocolOptions = new NewtonsoftJsonHubProtocolOptions
{
PayloadSerializerSettings = new JsonSerializerSettings()
{
NullValueHandling = testData.NullValueHandling,
ContractResolver = testData.CamelCase ? new CamelCasePropertyNamesContractResolver() : new DefaultContractResolver()
}
};
var protocol = new NewtonsoftJsonHubProtocol(Options.Create(protocolOptions));
var protocol = GetProtocolWithOptions(testData.UseCamelCase, testData.IgnoreNullValues);
var writer = MemoryBufferWriter.Get();
try
@ -69,49 +74,36 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Protocol
}
}
public static IDictionary<string, NewtonsoftJsonProtocolTestData> CustomProtocolTestData => new[]
public static IDictionary<string, JsonProtocolTestData> CustomProtocolTestData => new[]
{
new NewtonsoftJsonProtocolTestData("InvocationMessage_HasFloatArgument", new InvocationMessage(null, "Target", new object[] { 1, "Foo", 2.0f }), true, NullValueHandling.Ignore, "{\"type\":1,\"target\":\"Target\",\"arguments\":[1,\"Foo\",2.0]}"),
new NewtonsoftJsonProtocolTestData("StreamItemMessage_HasFloatItem", new StreamItemMessage("123", 2.0f), true, NullValueHandling.Ignore, "{\"type\":2,\"invocationId\":\"123\",\"item\":2.0}"),
new NewtonsoftJsonProtocolTestData("CompletionMessage_HasFloatResult", CompletionMessage.WithResult("123", 2.0f), true, NullValueHandling.Ignore, "{\"type\":3,\"invocationId\":\"123\",\"result\":2.0}"),
new NewtonsoftJsonProtocolTestData("StreamInvocationMessage_HasFloatArgument", new StreamInvocationMessage("123", "Target", new object[] { 1, "Foo", 2.0f }), true, NullValueHandling.Ignore, "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[1,\"Foo\",2.0]}"),
new NewtonsoftJsonProtocolTestData("InvocationMessage_StringIsoDateArgument", new InvocationMessage("Method", new object[] { "2016-05-10T13:51:20+12:34" }), false, NullValueHandling.Ignore, "{\"type\":1,\"target\":\"Method\",\"arguments\":[\"2016-05-10T13:51:20+12:34\"]}"),
new NewtonsoftJsonProtocolTestData("InvocationMessage_HasCustomArgumentWithNoCamelCase", new InvocationMessage(null, "Target", new object[] { new CustomObject() }), false, NullValueHandling.Ignore, "{\"type\":1,\"target\":\"Target\",\"arguments\":[{\"StringProp\":\"SignalR!\",\"DoubleProp\":6.2831853071,\"IntProp\":42,\"DateTimeProp\":\"2017-04-11T00:00:00Z\",\"ByteArrProp\":\"AQID\"}]}"),
new NewtonsoftJsonProtocolTestData("InvocationMessage_HasCustomArgumentWithNullValueIgnore", new InvocationMessage(null, "Target", new object[] { new CustomObject() }), true, NullValueHandling.Ignore, "{\"type\":1,\"target\":\"Target\",\"arguments\":[{\"stringProp\":\"SignalR!\",\"doubleProp\":6.2831853071,\"intProp\":42,\"dateTimeProp\":\"2017-04-11T00:00:00Z\",\"byteArrProp\":\"AQID\"}]}"),
new NewtonsoftJsonProtocolTestData("InvocationMessage_HasCustomArgumentWithNullValueIgnoreAndNoCamelCase", new InvocationMessage(null, "Target", new object[] { new CustomObject() }), false, NullValueHandling.Include, "{\"type\":1,\"target\":\"Target\",\"arguments\":[{\"StringProp\":\"SignalR!\",\"DoubleProp\":6.2831853071,\"IntProp\":42,\"DateTimeProp\":\"2017-04-11T00:00:00Z\",\"NullProp\":null,\"ByteArrProp\":\"AQID\"}]}"),
new NewtonsoftJsonProtocolTestData("InvocationMessage_HasCustomArgumentWithNullValueInclude", new InvocationMessage(null, "Target", new object[] { new CustomObject() }), true, NullValueHandling.Include, "{\"type\":1,\"target\":\"Target\",\"arguments\":[{\"stringProp\":\"SignalR!\",\"doubleProp\":6.2831853071,\"intProp\":42,\"dateTimeProp\":\"2017-04-11T00:00:00Z\",\"nullProp\":null,\"byteArrProp\":\"AQID\"}]}"),
new NewtonsoftJsonProtocolTestData("StreamItemMessage_HasCustomItemWithNoCamelCase", new StreamItemMessage("123", new CustomObject()), false, NullValueHandling.Ignore, "{\"type\":2,\"invocationId\":\"123\",\"item\":{\"StringProp\":\"SignalR!\",\"DoubleProp\":6.2831853071,\"IntProp\":42,\"DateTimeProp\":\"2017-04-11T00:00:00Z\",\"ByteArrProp\":\"AQID\"}}"),
new NewtonsoftJsonProtocolTestData("StreamItemMessage_HasCustomItemWithNullValueIgnore", new StreamItemMessage("123", new CustomObject()), true, NullValueHandling.Ignore, "{\"type\":2,\"invocationId\":\"123\",\"item\":{\"stringProp\":\"SignalR!\",\"doubleProp\":6.2831853071,\"intProp\":42,\"dateTimeProp\":\"2017-04-11T00:00:00Z\",\"byteArrProp\":\"AQID\"}}"),
new NewtonsoftJsonProtocolTestData("StreamItemMessage_HasCustomItemWithNullValueIgnoreAndNoCamelCase", new StreamItemMessage("123", new CustomObject()), false, NullValueHandling.Include, "{\"type\":2,\"invocationId\":\"123\",\"item\":{\"StringProp\":\"SignalR!\",\"DoubleProp\":6.2831853071,\"IntProp\":42,\"DateTimeProp\":\"2017-04-11T00:00:00Z\",\"NullProp\":null,\"ByteArrProp\":\"AQID\"}}"),
new NewtonsoftJsonProtocolTestData("StreamItemMessage_HasCustomItemWithNullValueInclude", new StreamItemMessage("123", new CustomObject()), true, NullValueHandling.Include, "{\"type\":2,\"invocationId\":\"123\",\"item\":{\"stringProp\":\"SignalR!\",\"doubleProp\":6.2831853071,\"intProp\":42,\"dateTimeProp\":\"2017-04-11T00:00:00Z\",\"nullProp\":null,\"byteArrProp\":\"AQID\"}}"),
new NewtonsoftJsonProtocolTestData("StreamItemMessage_HasHeaders", AddHeaders(TestHeaders, new StreamItemMessage("123", new CustomObject())), true, NullValueHandling.Include, "{\"type\":2," + SerializedHeaders + ",\"invocationId\":\"123\",\"item\":{\"stringProp\":\"SignalR!\",\"doubleProp\":6.2831853071,\"intProp\":42,\"dateTimeProp\":\"2017-04-11T00:00:00Z\",\"nullProp\":null,\"byteArrProp\":\"AQID\"}}"),
new NewtonsoftJsonProtocolTestData("CompletionMessage_HasCustomResultWithNoCamelCase", CompletionMessage.WithResult("123", new CustomObject()), false, NullValueHandling.Ignore, "{\"type\":3,\"invocationId\":\"123\",\"result\":{\"StringProp\":\"SignalR!\",\"DoubleProp\":6.2831853071,\"IntProp\":42,\"DateTimeProp\":\"2017-04-11T00:00:00Z\",\"ByteArrProp\":\"AQID\"}}"),
new NewtonsoftJsonProtocolTestData("CompletionMessage_HasCustomResultWithNullValueIgnore", CompletionMessage.WithResult("123", new CustomObject()), true, NullValueHandling.Ignore, "{\"type\":3,\"invocationId\":\"123\",\"result\":{\"stringProp\":\"SignalR!\",\"doubleProp\":6.2831853071,\"intProp\":42,\"dateTimeProp\":\"2017-04-11T00:00:00Z\",\"byteArrProp\":\"AQID\"}}"),
new NewtonsoftJsonProtocolTestData("CompletionMessage_HasCustomResultWithNullValueIncludeAndNoCamelCase", CompletionMessage.WithResult("123", new CustomObject()), false, NullValueHandling.Include, "{\"type\":3,\"invocationId\":\"123\",\"result\":{\"StringProp\":\"SignalR!\",\"DoubleProp\":6.2831853071,\"IntProp\":42,\"DateTimeProp\":\"2017-04-11T00:00:00Z\",\"NullProp\":null,\"ByteArrProp\":\"AQID\"}}"),
new NewtonsoftJsonProtocolTestData("CompletionMessage_HasCustomResultWithNullValueInclude", CompletionMessage.WithResult("123", new CustomObject()), true, NullValueHandling.Include, "{\"type\":3,\"invocationId\":\"123\",\"result\":{\"stringProp\":\"SignalR!\",\"doubleProp\":6.2831853071,\"intProp\":42,\"dateTimeProp\":\"2017-04-11T00:00:00Z\",\"nullProp\":null,\"byteArrProp\":\"AQID\"}}"),
new NewtonsoftJsonProtocolTestData("CompletionMessage_HasTestHeadersAndCustomItemResult", AddHeaders(TestHeaders, CompletionMessage.WithResult("123", new CustomObject())), true, NullValueHandling.Include, "{\"type\":3," + SerializedHeaders + ",\"invocationId\":\"123\",\"result\":{\"stringProp\":\"SignalR!\",\"doubleProp\":6.2831853071,\"intProp\":42,\"dateTimeProp\":\"2017-04-11T00:00:00Z\",\"nullProp\":null,\"byteArrProp\":\"AQID\"}}"),
new NewtonsoftJsonProtocolTestData("CompletionMessage_HasErrorAndCamelCase", CompletionMessage.Empty("123"), true, NullValueHandling.Ignore, "{\"type\":3,\"invocationId\":\"123\"}"),
new NewtonsoftJsonProtocolTestData("CompletionMessage_HasErrorAndHeadersAndCamelCase", AddHeaders(TestHeaders, CompletionMessage.Empty("123")), true, NullValueHandling.Ignore, "{\"type\":3," + SerializedHeaders + ",\"invocationId\":\"123\"}"),
new NewtonsoftJsonProtocolTestData("StreamInvocationMessage_HasCustomArgumentWithNoCamelCase", new StreamInvocationMessage("123", "Target", new object[] { new CustomObject() }), false, NullValueHandling.Ignore, "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[{\"StringProp\":\"SignalR!\",\"DoubleProp\":6.2831853071,\"IntProp\":42,\"DateTimeProp\":\"2017-04-11T00:00:00Z\",\"ByteArrProp\":\"AQID\"}]}"),
new NewtonsoftJsonProtocolTestData("StreamInvocationMessage_HasCustomArgumentWithNullValueIgnore", new StreamInvocationMessage("123", "Target", new object[] { new CustomObject() }), true, NullValueHandling.Ignore, "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[{\"stringProp\":\"SignalR!\",\"doubleProp\":6.2831853071,\"intProp\":42,\"dateTimeProp\":\"2017-04-11T00:00:00Z\",\"byteArrProp\":\"AQID\"}]}"),
new NewtonsoftJsonProtocolTestData("StreamInvocationMessage_HasCustomArgumentWithNullValueIgnoreAndNoCamelCase", new StreamInvocationMessage("123", "Target", new object[] { new CustomObject() }), false, NullValueHandling.Include, "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[{\"StringProp\":\"SignalR!\",\"DoubleProp\":6.2831853071,\"IntProp\":42,\"DateTimeProp\":\"2017-04-11T00:00:00Z\",\"NullProp\":null,\"ByteArrProp\":\"AQID\"}]}"),
new NewtonsoftJsonProtocolTestData("StreamInvocationMessage_HasCustomArgumentWithNullValueInclude", new StreamInvocationMessage("123", "Target", new object[] { new CustomObject() }), true, NullValueHandling.Include, "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[{\"stringProp\":\"SignalR!\",\"doubleProp\":6.2831853071,\"intProp\":42,\"dateTimeProp\":\"2017-04-11T00:00:00Z\",\"nullProp\":null,\"byteArrProp\":\"AQID\"}]}"),
new NewtonsoftJsonProtocolTestData("StreamInvocationMessage_HasHeaders", AddHeaders(TestHeaders, new StreamInvocationMessage("123", "Target", new object[] { new CustomObject() })), true, NullValueHandling.Include, "{\"type\":4," + SerializedHeaders + ",\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[{\"stringProp\":\"SignalR!\",\"doubleProp\":6.2831853071,\"intProp\":42,\"dateTimeProp\":\"2017-04-11T00:00:00Z\",\"nullProp\":null,\"byteArrProp\":\"AQID\"}]}"),
new NewtonsoftJsonProtocolTestData("CloseMessage_HasErrorWithCamelCase", new CloseMessage("Error!"), true, NullValueHandling.Ignore, "{\"type\":7,\"error\":\"Error!\"}"),
new JsonProtocolTestData("InvocationMessage_HasFloatArgument", new InvocationMessage(null, "Target", new object[] { 1, "Foo", 2.0f }), true, true, "{\"type\":1,\"target\":\"Target\",\"arguments\":[1,\"Foo\",2.0]}"),
new JsonProtocolTestData("StreamItemMessage_HasFloatItem", new StreamItemMessage("123", 2.0f), true, true, "{\"type\":2,\"invocationId\":\"123\",\"item\":2.0}"),
new JsonProtocolTestData("CompletionMessage_HasFloatResult", CompletionMessage.WithResult("123", 2.0f), true, true, "{\"type\":3,\"invocationId\":\"123\",\"result\":2.0}"),
new JsonProtocolTestData("StreamInvocationMessage_HasFloatArgument", new StreamInvocationMessage("123", "Target", new object[] { 1, "Foo", 2.0f }), true, true, "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[1,\"Foo\",2.0]}"),
new JsonProtocolTestData("InvocationMessage_StringIsoDateArgument", new InvocationMessage("Method", new object[] { "2016-05-10T13:51:20+12:34" }), false, true, "{\"type\":1,\"target\":\"Method\",\"arguments\":[\"2016-05-10T13:51:20+12:34\"]}"),
new JsonProtocolTestData("InvocationMessage_HasCustomArgumentWithNoCamelCase", new InvocationMessage(null, "Target", new object[] { new CustomObject() }), false, true, "{\"type\":1,\"target\":\"Target\",\"arguments\":[{\"StringProp\":\"SignalR!\",\"DoubleProp\":6.2831853071,\"IntProp\":42,\"DateTimeProp\":\"2017-04-11T00:00:00Z\",\"ByteArrProp\":\"AQID\"}]}"),
new JsonProtocolTestData("InvocationMessage_HasCustomArgumentWithNullValueIgnore", new InvocationMessage(null, "Target", new object[] { new CustomObject() }), true, true, "{\"type\":1,\"target\":\"Target\",\"arguments\":[{\"stringProp\":\"SignalR!\",\"doubleProp\":6.2831853071,\"intProp\":42,\"dateTimeProp\":\"2017-04-11T00:00:00Z\",\"byteArrProp\":\"AQID\"}]}"),
new JsonProtocolTestData("InvocationMessage_HasCustomArgumentWithNullValueIgnoreAndNoCamelCase", new InvocationMessage(null, "Target", new object[] { new CustomObject() }), false, false, "{\"type\":1,\"target\":\"Target\",\"arguments\":[{\"StringProp\":\"SignalR!\",\"DoubleProp\":6.2831853071,\"IntProp\":42,\"DateTimeProp\":\"2017-04-11T00:00:00Z\",\"NullProp\":null,\"ByteArrProp\":\"AQID\"}]}"),
new JsonProtocolTestData("InvocationMessage_HasCustomArgumentWithNullValueInclude", new InvocationMessage(null, "Target", new object[] { new CustomObject() }), true, false, "{\"type\":1,\"target\":\"Target\",\"arguments\":[{\"stringProp\":\"SignalR!\",\"doubleProp\":6.2831853071,\"intProp\":42,\"dateTimeProp\":\"2017-04-11T00:00:00Z\",\"nullProp\":null,\"byteArrProp\":\"AQID\"}]}"),
new JsonProtocolTestData("StreamItemMessage_HasCustomItemWithNoCamelCase", new StreamItemMessage("123", new CustomObject()), false, true, "{\"type\":2,\"invocationId\":\"123\",\"item\":{\"StringProp\":\"SignalR!\",\"DoubleProp\":6.2831853071,\"IntProp\":42,\"DateTimeProp\":\"2017-04-11T00:00:00Z\",\"ByteArrProp\":\"AQID\"}}"),
new JsonProtocolTestData("StreamItemMessage_HasCustomItemWithNullValueIgnore", new StreamItemMessage("123", new CustomObject()), true, true, "{\"type\":2,\"invocationId\":\"123\",\"item\":{\"stringProp\":\"SignalR!\",\"doubleProp\":6.2831853071,\"intProp\":42,\"dateTimeProp\":\"2017-04-11T00:00:00Z\",\"byteArrProp\":\"AQID\"}}"),
new JsonProtocolTestData("StreamItemMessage_HasCustomItemWithNullValueIgnoreAndNoCamelCase", new StreamItemMessage("123", new CustomObject()), false, false, "{\"type\":2,\"invocationId\":\"123\",\"item\":{\"StringProp\":\"SignalR!\",\"DoubleProp\":6.2831853071,\"IntProp\":42,\"DateTimeProp\":\"2017-04-11T00:00:00Z\",\"NullProp\":null,\"ByteArrProp\":\"AQID\"}}"),
new JsonProtocolTestData("StreamItemMessage_HasCustomItemWithNullValueInclude", new StreamItemMessage("123", new CustomObject()), true, false, "{\"type\":2,\"invocationId\":\"123\",\"item\":{\"stringProp\":\"SignalR!\",\"doubleProp\":6.2831853071,\"intProp\":42,\"dateTimeProp\":\"2017-04-11T00:00:00Z\",\"nullProp\":null,\"byteArrProp\":\"AQID\"}}"),
new JsonProtocolTestData("StreamItemMessage_HasHeaders", AddHeaders(TestHeaders, new StreamItemMessage("123", new CustomObject())), true, false, "{\"type\":2," + SerializedHeaders + ",\"invocationId\":\"123\",\"item\":{\"stringProp\":\"SignalR!\",\"doubleProp\":6.2831853071,\"intProp\":42,\"dateTimeProp\":\"2017-04-11T00:00:00Z\",\"nullProp\":null,\"byteArrProp\":\"AQID\"}}"),
new JsonProtocolTestData("CompletionMessage_HasCustomResultWithNoCamelCase", CompletionMessage.WithResult("123", new CustomObject()), false, true, "{\"type\":3,\"invocationId\":\"123\",\"result\":{\"StringProp\":\"SignalR!\",\"DoubleProp\":6.2831853071,\"IntProp\":42,\"DateTimeProp\":\"2017-04-11T00:00:00Z\",\"ByteArrProp\":\"AQID\"}}"),
new JsonProtocolTestData("CompletionMessage_HasCustomResultWithNullValueIgnore", CompletionMessage.WithResult("123", new CustomObject()), true, true, "{\"type\":3,\"invocationId\":\"123\",\"result\":{\"stringProp\":\"SignalR!\",\"doubleProp\":6.2831853071,\"intProp\":42,\"dateTimeProp\":\"2017-04-11T00:00:00Z\",\"byteArrProp\":\"AQID\"}}"),
new JsonProtocolTestData("CompletionMessage_HasCustomResultWithNullValueIncludeAndNoCamelCase", CompletionMessage.WithResult("123", new CustomObject()), false, false, "{\"type\":3,\"invocationId\":\"123\",\"result\":{\"StringProp\":\"SignalR!\",\"DoubleProp\":6.2831853071,\"IntProp\":42,\"DateTimeProp\":\"2017-04-11T00:00:00Z\",\"NullProp\":null,\"ByteArrProp\":\"AQID\"}}"),
new JsonProtocolTestData("CompletionMessage_HasCustomResultWithNullValueInclude", CompletionMessage.WithResult("123", new CustomObject()), true, false, "{\"type\":3,\"invocationId\":\"123\",\"result\":{\"stringProp\":\"SignalR!\",\"doubleProp\":6.2831853071,\"intProp\":42,\"dateTimeProp\":\"2017-04-11T00:00:00Z\",\"nullProp\":null,\"byteArrProp\":\"AQID\"}}"),
new JsonProtocolTestData("CompletionMessage_HasTestHeadersAndCustomItemResult", AddHeaders(TestHeaders, CompletionMessage.WithResult("123", new CustomObject())), true, false, "{\"type\":3," + SerializedHeaders + ",\"invocationId\":\"123\",\"result\":{\"stringProp\":\"SignalR!\",\"doubleProp\":6.2831853071,\"intProp\":42,\"dateTimeProp\":\"2017-04-11T00:00:00Z\",\"nullProp\":null,\"byteArrProp\":\"AQID\"}}"),
new JsonProtocolTestData("CompletionMessage_HasErrorAndCamelCase", CompletionMessage.Empty("123"), true, true, "{\"type\":3,\"invocationId\":\"123\"}"),
new JsonProtocolTestData("CompletionMessage_HasErrorAndHeadersAndCamelCase", AddHeaders(TestHeaders, CompletionMessage.Empty("123")), true, true, "{\"type\":3," + SerializedHeaders + ",\"invocationId\":\"123\"}"),
new JsonProtocolTestData("StreamInvocationMessage_HasCustomArgumentWithNoCamelCase", new StreamInvocationMessage("123", "Target", new object[] { new CustomObject() }), false, true, "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[{\"StringProp\":\"SignalR!\",\"DoubleProp\":6.2831853071,\"IntProp\":42,\"DateTimeProp\":\"2017-04-11T00:00:00Z\",\"ByteArrProp\":\"AQID\"}]}"),
new JsonProtocolTestData("StreamInvocationMessage_HasCustomArgumentWithNullValueIgnore", new StreamInvocationMessage("123", "Target", new object[] { new CustomObject() }), true, true, "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[{\"stringProp\":\"SignalR!\",\"doubleProp\":6.2831853071,\"intProp\":42,\"dateTimeProp\":\"2017-04-11T00:00:00Z\",\"byteArrProp\":\"AQID\"}]}"),
new JsonProtocolTestData("StreamInvocationMessage_HasCustomArgumentWithNullValueIgnoreAndNoCamelCase", new StreamInvocationMessage("123", "Target", new object[] { new CustomObject() }), false, false, "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[{\"StringProp\":\"SignalR!\",\"DoubleProp\":6.2831853071,\"IntProp\":42,\"DateTimeProp\":\"2017-04-11T00:00:00Z\",\"NullProp\":null,\"ByteArrProp\":\"AQID\"}]}"),
new JsonProtocolTestData("StreamInvocationMessage_HasCustomArgumentWithNullValueInclude", new StreamInvocationMessage("123", "Target", new object[] { new CustomObject() }), true, false, "{\"type\":4,\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[{\"stringProp\":\"SignalR!\",\"doubleProp\":6.2831853071,\"intProp\":42,\"dateTimeProp\":\"2017-04-11T00:00:00Z\",\"nullProp\":null,\"byteArrProp\":\"AQID\"}]}"),
new JsonProtocolTestData("StreamInvocationMessage_HasHeaders", AddHeaders(TestHeaders, new StreamInvocationMessage("123", "Target", new object[] { new CustomObject() })), true, false, "{\"type\":4," + SerializedHeaders + ",\"invocationId\":\"123\",\"target\":\"Target\",\"arguments\":[{\"stringProp\":\"SignalR!\",\"doubleProp\":6.2831853071,\"intProp\":42,\"dateTimeProp\":\"2017-04-11T00:00:00Z\",\"nullProp\":null,\"byteArrProp\":\"AQID\"}]}"),
}.ToDictionary(t => t.Name);
public static IEnumerable<object[]> CustomProtocolTestDataNames => CustomProtocolTestData.Keys.Select(name => new object[] { name });
public class NewtonsoftJsonProtocolTestData : JsonProtocolTestData
{
public NewtonsoftJsonProtocolTestData(string name, HubMessage message, bool camelCase, NullValueHandling nullValueHandling, string json) : base(name, message, json)
{
CamelCase = camelCase;
NullValueHandling = nullValueHandling;
}
public bool CamelCase { get; }
public NullValueHandling NullValueHandling { get; }
}
}
}

View File

@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests
{
return new HubConnectionContext(connection, TimeSpan.FromSeconds(15), NullLoggerFactory.Instance)
{
Protocol = protocol ?? new NewtonsoftJsonHubProtocol(),
Protocol = protocol ?? new JsonHubProtocol(),
UserIdentifier = userIdentifier,
};
}

View File

@ -7,7 +7,7 @@
<Compile Include="Microsoft.AspNetCore.SignalR.Core.netcoreapp3.0.cs" />
<Reference Include="Microsoft.AspNetCore.Authorization" />
<Reference Include="Microsoft.AspNetCore.SignalR.Common" />
<Reference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" />
<Reference Include="Microsoft.AspNetCore.SignalR.Protocols.Json" />
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
<Reference Include="Microsoft.Extensions.Logging.Abstractions" />
<Reference Include="System.Threading.Channels" />

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>Real-time communication framework for ASP.NET Core.</Description>
@ -17,7 +17,7 @@
<ItemGroup>
<Reference Include="Microsoft.AspNetCore.Authorization" />
<Reference Include="Microsoft.AspNetCore.SignalR.Common" />
<Reference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" />
<Reference Include="Microsoft.AspNetCore.SignalR.Protocols.Json" />
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
<Reference Include="Microsoft.Extensions.Logging.Abstractions" />
<Reference Include="System.Threading.Channels" />

View File

@ -32,7 +32,7 @@ namespace Microsoft.Extensions.DependencyInjection
services.AddAuthorization();
var builder = new SignalRServerBuilder(services);
builder.AddNewtonsoftJsonProtocol();
builder.AddJsonProtocol();
return builder;
}
}

View File

@ -23,7 +23,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests
return Clients.User(userId).SendAsync("Send", message);
}
public Task SendToMultipleUsers(List<string> userIds, string message)
public Task SendToMultipleUsers(IReadOnlyList<string> userIds, string message)
{
return Clients.Users(userIds).SendAsync("Send", message);
}
@ -33,7 +33,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests
return Clients.Client(connectionId).SendAsync("Send", message);
}
public Task SendToMultipleClients(string message, List<string> connectionIds)
public Task SendToMultipleClients(string message, IReadOnlyList<string> connectionIds)
{
return Clients.Clients(connectionIds).SendAsync("Send", message);
}
@ -48,12 +48,12 @@ namespace Microsoft.AspNetCore.SignalR.Tests
return Clients.Group(groupName).SendAsync("Send", message);
}
public Task GroupExceptSendMethod(string groupName, string message, List<string> excludedConnectionIds)
public Task GroupExceptSendMethod(string groupName, string message, IReadOnlyList<string> excludedConnectionIds)
{
return Clients.GroupExcept(groupName, excludedConnectionIds).SendAsync("Send", message);
}
public Task SendToMultipleGroups(string message, List<string> groupNames)
public Task SendToMultipleGroups(string message, IReadOnlyList<string> groupNames)
{
return Clients.Groups(groupNames).SendAsync("Send", message);
}
@ -142,7 +142,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests
{
}
public Task SendToAllExcept(string message, List<string> excludedConnectionIds)
public Task SendToAllExcept(string message, IReadOnlyList<string> excludedConnectionIds)
{
return Clients.AllExcept(excludedConnectionIds).SendAsync("Send", message);
}
@ -313,7 +313,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests
return Clients.Client(connectionId).Send(message);
}
public Task SendToMultipleClients(string message, List<string> connectionIds)
public Task SendToMultipleClients(string message, IReadOnlyList<string> connectionIds)
{
return Clients.Clients(connectionIds).Send(message);
}
@ -328,7 +328,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests
return Clients.Group(groupName).Send(message);
}
public Task GroupExceptSendMethod(string groupName, string message, List<string> excludedConnectionIds)
public Task GroupExceptSendMethod(string groupName, string message, IReadOnlyList<string> excludedConnectionIds)
{
return Clients.GroupExcept(groupName, excludedConnectionIds).Send(message);
}
@ -338,7 +338,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests
return Clients.OthersInGroup(groupName).Send(message);
}
public Task SendToMultipleGroups(string message, List<string> groupNames)
public Task SendToMultipleGroups(string message, IReadOnlyList<string> groupNames)
{
return Clients.Groups(groupNames).Send(message);
}
@ -348,7 +348,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests
return Clients.All.Broadcast(message);
}
public Task SendToAllExcept(string message, List<string> excludedConnectionIds)
public Task SendToAllExcept(string message, IReadOnlyList<string> excludedConnectionIds)
{
return Clients.AllExcept(excludedConnectionIds).Send(message);
}
@ -393,7 +393,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests
return Clients.Client(connectionId).Send(message);
}
public Task SendToMultipleClients(string message, List<string> connectionIds)
public Task SendToMultipleClients(string message, IReadOnlyList<string> connectionIds)
{
return Clients.Clients(connectionIds).Send(message);
}
@ -414,12 +414,12 @@ namespace Microsoft.AspNetCore.SignalR.Tests
return Clients.Group(groupName).Send(message);
}
public Task GroupExceptSendMethod(string groupName, string message, List<string> excludedConnectionIds)
public Task GroupExceptSendMethod(string groupName, string message, IReadOnlyList<string> excludedConnectionIds)
{
return Clients.GroupExcept(groupName, excludedConnectionIds).Send(message);
}
public Task SendToMultipleGroups(string message, List<string> groupNames)
public Task SendToMultipleGroups(string message, IReadOnlyList<string> groupNames)
{
return Clients.Groups(groupNames).Send(message);
}
@ -434,7 +434,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests
return Clients.All.Broadcast(message);
}
public Task SendToAllExcept(string message, List<string> excludedConnectionIds)
public Task SendToAllExcept(string message, IReadOnlyList<string> excludedConnectionIds)
{
return Clients.AllExcept(excludedConnectionIds).Send(message);
}

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>Tests for users to verify their own implementations of SignalR types</Description>
@ -19,6 +19,7 @@
<ItemGroup>
<Reference Include="Microsoft.AspNetCore.SignalR.Common" />
<Reference Include="Microsoft.AspNetCore.SignalR.Core" />
<Reference Include="Microsoft.AspNetCore.SignalR.Protocols.Json" />
<Reference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" />
<Reference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" />
<Reference Include="xunit.assert" />

View File

@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<Compile Include="$(SignalRSharedSourceRoot)JsonUtils.cs" Link="Internal\JsonUtils.cs" />
<Compile Include="$(SignalRSharedSourceRoot)SystemTextJsonExtensions.cs" Link="Internal\SystemTextJsonExtensions.cs" />
<Compile Include="$(SignalRSharedSourceRoot)MemoryBufferWriter.cs" Link="Internal\MemoryBufferWriter.cs" />
</ItemGroup>