diff --git a/samples/ChatSample/Hubs/Chat.cs b/samples/ChatSample/Hubs/Chat.cs index ab59700c01..74a0317924 100644 --- a/samples/ChatSample/Hubs/Chat.cs +++ b/samples/ChatSample/Hubs/Chat.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.SignalR; namespace ChatSample.Hubs { @@ -23,12 +24,12 @@ namespace ChatSample.Hubs public override Task OnUsersJoined(UserDetails[] users) { - return Clients.Client(Context.ConnectionId).InvokeAsync("UsersJoined", new[] { users }); + return Clients.Client(Context.ConnectionId).InvokeAsync("UsersJoined", users); } public override Task OnUsersLeft(UserDetails[] users) { - return Clients.Client(Context.ConnectionId).InvokeAsync("UsersLeft", new[] { users }); + return Clients.Client(Context.ConnectionId).InvokeAsync("UsersLeft", users); } public async Task Send(string message) diff --git a/src/Microsoft.AspNetCore.SignalR.Core/IClientProxy.cs b/src/Microsoft.AspNetCore.SignalR.Core/IClientProxy.cs index 3749eba811..666d46a035 100644 --- a/src/Microsoft.AspNetCore.SignalR.Core/IClientProxy.cs +++ b/src/Microsoft.AspNetCore.SignalR.Core/IClientProxy.cs @@ -13,6 +13,6 @@ namespace Microsoft.AspNetCore.SignalR /// name of the method to invoke /// argumetns to pass to the client /// A task that represents when the data has been sent to the client. - Task InvokeAsync(string method, params object[] args); + Task InvokeAsync(string method, object[] args); } } diff --git a/src/Microsoft.AspNetCore.SignalR.Core/IClientProxyExtensions.cs b/src/Microsoft.AspNetCore.SignalR.Core/IClientProxyExtensions.cs new file mode 100644 index 0000000000..d4a6a3abd0 --- /dev/null +++ b/src/Microsoft.AspNetCore.SignalR.Core/IClientProxyExtensions.cs @@ -0,0 +1,175 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; + +namespace Microsoft.AspNetCore.SignalR +{ + public static class IClientProxyExtensions + { + /// + /// Invokes a method on the connection(s) represented by the instance. + /// + /// The + /// name of the method to invoke + /// The first argument + /// A task that represents when the data has been sent to the client. + public static Task InvokeAsync(this IClientProxy clientProxy, string method, object arg1) + { + return clientProxy.InvokeAsync(method, new object[] { arg1 }); + } + + /// + /// Invokes a method on the connection(s) represented by the instance. + /// + /// The + /// name of the method to invoke + /// The first argument + /// The second argument + /// A task that represents when the data has been sent to the client. + public static Task InvokeAsync(this IClientProxy clientProxy, string method, object arg1, object arg2) + { + return clientProxy.InvokeAsync(method, new object[] { arg1, arg2 }); + } + + /// + /// Invokes a method on the connection(s) represented by the instance. + /// + /// The + /// name of the method to invoke + /// The first argument + /// The second argument + /// The third argument + /// A task that represents when the data has been sent to the client. + public static Task InvokeAsync(this IClientProxy clientProxy, string method, object arg1, object arg2, object arg3) + { + return clientProxy.InvokeAsync(method, new object[] { arg1, arg2, arg3 }); + } + + /// + /// Invokes a method on the connection(s) represented by the instance. + /// + /// The + /// name of the method to invoke + /// The first argument + /// The second argument + /// The third argument + /// The fourth argument + /// A task that represents when the data has been sent to the client. + public static Task InvokeAsync(this IClientProxy clientProxy, string method, object arg1, object arg2, object arg3, object arg4) + { + return clientProxy.InvokeAsync(method, new object[] { arg1, arg2, arg3, arg4 }); + } + + /// + /// Invokes a method on the connection(s) represented by the instance. + /// + /// The + /// name of the method to invoke + /// The first argument + /// The second argument + /// The third argument + /// The fourth argument + /// The fifth argument + /// A task that represents when the data has been sent to the client. + public static Task InvokeAsync(this IClientProxy clientProxy, string method, object arg1, object arg2, object arg3, object arg4, object arg5) + { + return clientProxy.InvokeAsync(method, new object[] { arg1, arg2, arg3, arg4, arg5 }); + } + + /// + /// Invokes a method on the connection(s) represented by the instance. + /// + /// The + /// name of the method to invoke + /// The first argument + /// The second argument + /// The third argument + /// The fourth argument + /// The fifth argument + /// The sixth argument + /// A task that represents when the data has been sent to the client. + public static Task InvokeAsync(this IClientProxy clientProxy, string method, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6) + { + return clientProxy.InvokeAsync(method, new object[] { arg1, arg2, arg3, arg4, arg5, arg6 }); + } + + /// + /// Invokes a method on the connection(s) represented by the instance. + /// + /// The + /// name of the method to invoke + /// The first argument + /// The second argument + /// The third argument + /// The fourth argument + /// The fifth argument + /// The sixth argument + /// The seventh argument + /// A task that represents when the data has been sent to the client. + public static Task InvokeAsync(this IClientProxy clientProxy, string method, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7) + { + return clientProxy.InvokeAsync(method, new object[] { arg1, arg2, arg3, arg4, arg5, arg6, arg7 }); + } + + /// + /// Invokes a method on the connection(s) represented by the instance. + /// + /// The + /// name of the method to invoke + /// The first argument + /// The second argument + /// The third argument + /// The fourth argument + /// The fifth argument + /// The sixth argument + /// The seventh argument + /// The eigth argument + /// A task that represents when the data has been sent to the client. + public static Task InvokeAsync(this IClientProxy clientProxy, string method, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8) + { + return clientProxy.InvokeAsync(method, new object[] { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 }); + } + + /// + /// Invokes a method on the connection(s) represented by the instance. + /// + /// The + /// name of the method to invoke + /// The first argument + /// The second argument + /// The third argument + /// The fourth argument + /// The fifth argument + /// The sixth argument + /// The seventh argument + /// The eigth argument + /// The ninth argument + /// A task that represents when the data has been sent to the client. + public static Task InvokeAsync(this IClientProxy clientProxy, string method, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, object arg9) + { + return clientProxy.InvokeAsync(method, new object[] { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 }); + } + + /// + /// Invokes a method on the connection(s) represented by the instance. + /// + /// The + /// name of the method to invoke + /// The first argument + /// The second argument + /// The third argument + /// The fourth argument + /// The fifth argument + /// The sixth argument + /// The seventh argument + /// The eigth argument + /// The ninth argument + /// The tenth argument + /// A task that represents when the data has been sent to the client. + public static Task InvokeAsync(this IClientProxy clientProxy, string method, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, object arg9, object arg10) + { + return clientProxy.InvokeAsync(method, new object[] { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 }); + } + } +} diff --git a/test/Microsoft.AspNetCore.SignalR.Tests/HubEndpointTests.cs b/test/Microsoft.AspNetCore.SignalR.Tests/HubEndpointTests.cs index 8159f38de2..d9123e448c 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests/HubEndpointTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests/HubEndpointTests.cs @@ -21,6 +21,7 @@ using Moq; using MsgPack; using MsgPack.Serialization; using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; using Xunit; @@ -697,6 +698,42 @@ namespace Microsoft.AspNetCore.SignalR.Tests } } + [Fact] + public async Task SendArraySendsArrayToAllClients() + { + var serviceProvider = CreateServiceProvider(); + + var endPoint = serviceProvider.GetService>(); + + using (var firstClient = new TestClient()) + using (var secondClient = new TestClient()) + { + Task firstEndPointTask = endPoint.OnConnectedAsync(firstClient.Connection); + Task secondEndPointTask = endPoint.OnConnectedAsync(secondClient.Connection); + + await Task.WhenAll(firstClient.Connected, secondClient.Connected).OrTimeout(); + + await firstClient.SendInvocationAsync(nameof(MethodHub.SendArray)).OrTimeout(); + + foreach (var result in await Task.WhenAll( + firstClient.ReadAsync(), + secondClient.ReadAsync()).OrTimeout()) + { + var invocation = Assert.IsType(result); + Assert.Equal("Array", invocation.Target); + Assert.Single(invocation.Arguments); + var values = ((JArray)invocation.Arguments[0]).Select(t => t.Value()).ToArray(); + Assert.Equal(new int[] { 1, 2, 3 }, values); + } + + // kill the connections + firstClient.Dispose(); + secondClient.Dispose(); + + await Task.WhenAll(firstEndPointTask, secondEndPointTask).OrTimeout(); + } + } + [Theory] [MemberData(nameof(HubTypes))] public async Task SendToAllExcept(Type hubType) @@ -1570,6 +1607,11 @@ namespace Microsoft.AspNetCore.SignalR.Tests return Clients.All.InvokeAsync("Broadcast", new Result { Message = "test", paramName = "param" }); } + public Task SendArray() + { + return Clients.All.InvokeAsync("Array", new int[] { 1, 2, 3 }); + } + public Task TaskValueMethod() { return Task.FromResult(42);