From 8ba29b578da537af40d3e4942da6580963d7812c Mon Sep 17 00:00:00 2001 From: Mikael Mengistu Date: Fri, 14 Jul 2017 15:54:31 -0700 Subject: [PATCH] Dynamic Hub Change Part 2 (#644) --- samples/SocketsSample/Hubs/DynamicChat.cs | 51 ++++++++ samples/SocketsSample/Startup.cs | 3 +- samples/SocketsSample/wwwroot/hubs.html | 5 +- samples/SocketsSample/wwwroot/index.html | 8 +- .../DynamicClientProxy.cs | 23 ++++ .../DynamicHub.cs | 16 +++ .../DynamicHubClients.cs | 20 ++++ .../HubConnectionTests.cs | 60 +++++----- .../Hubs.cs | 29 +++++ ...Core.SignalR.Client.FunctionalTests.csproj | 4 + .../Startup.cs | 3 +- .../HubEndpointTests.cs | 109 +++++++++++++----- .../Microsoft.AspNetCore.SignalR.Tests.csproj | 4 + 13 files changed, 276 insertions(+), 59 deletions(-) create mode 100644 samples/SocketsSample/Hubs/DynamicChat.cs create mode 100644 src/Microsoft.AspNetCore.SignalR/DynamicClientProxy.cs create mode 100644 src/Microsoft.AspNetCore.SignalR/DynamicHub.cs create mode 100644 src/Microsoft.AspNetCore.SignalR/DynamicHubClients.cs diff --git a/samples/SocketsSample/Hubs/DynamicChat.cs b/samples/SocketsSample/Hubs/DynamicChat.cs new file mode 100644 index 0000000000..5966a7267d --- /dev/null +++ b/samples/SocketsSample/Hubs/DynamicChat.cs @@ -0,0 +1,51 @@ +// 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 System.Threading.Tasks; +using Microsoft.AspNetCore.SignalR; + +namespace SocketsSample.Hubs +{ + public class DynamicChat : DynamicHub + { + public override async Task OnConnectedAsync() + { + await Clients.All.Send($"{Context.ConnectionId} joined"); + } + + public override async Task OnDisconnectedAsync(Exception ex) + { + await Clients.All.Send($"{Context.ConnectionId} left"); + } + + public Task Send(string message) + { + return Clients.All.Send($"{Context.ConnectionId}: {message}"); + } + + public Task SendToGroup(string groupName, string message) + { + return Clients.Group(groupName).Send($"{Context.ConnectionId}@{groupName}: {message}"); + } + + public async Task JoinGroup(string groupName) + { + await Groups.AddAsync(Context.ConnectionId, groupName); + + await Clients.Group(groupName).Send($"{Context.ConnectionId} joined {groupName}"); + } + + public async Task LeaveGroup(string groupName) + { + await Groups.RemoveAsync(Context.ConnectionId, groupName); + + await Clients.Group(groupName).Send($"{Context.ConnectionId} left {groupName}"); + } + + public Task Echo(string message) + { + return Clients.Client(Context.ConnectionId).Send($"{Context.ConnectionId}: {message}"); + } + } +} diff --git a/samples/SocketsSample/Startup.cs b/samples/SocketsSample/Startup.cs index 0f05209bf8..4b3b90715a 100644 --- a/samples/SocketsSample/Startup.cs +++ b/samples/SocketsSample/Startup.cs @@ -47,7 +47,8 @@ namespace SocketsSample app.UseSignalR(routes => { - routes.MapHub("hubs"); + routes.MapHub("dynamic"); + routes.MapHub("default"); routes.MapHub("streaming"); }); diff --git a/samples/SocketsSample/wwwroot/hubs.html b/samples/SocketsSample/wwwroot/hubs.html index c7fcc7e4e8..0b084f160d 100644 --- a/samples/SocketsSample/wwwroot/hubs.html +++ b/samples/SocketsSample/wwwroot/hubs.html @@ -78,6 +78,8 @@ function getText(id) { } let transportType = signalR.TransportType[getParameterByName('transport')] || signalR.TransportType.WebSockets; +let hubRoute = getParameterByName('hubType') || "default"; +console.log('Hub Route:' + hubRoute); document.getElementById('head1').innerHTML = signalR.TransportType[transportType]; @@ -89,7 +91,8 @@ var connection; click('connect', event => { connectButton.disabled = true; disconnectButton.disabled = false; - let http = new signalR.HttpConnection(`http://${document.location.host}/hubs`, { transport: transportType }); + console.log(`http://${document.location.host}/${hubRoute}`); + let http = new signalR.HttpConnection(`http://${document.location.host}/${hubRoute}`, { transport: transportType }); connection = new signalR.HubConnection(http); connection.on('Send', msg => { addLine('message-list', msg); diff --git a/samples/SocketsSample/wwwroot/index.html b/samples/SocketsSample/wwwroot/index.html index 5f0e8c06b2..9c45d8c636 100644 --- a/samples/SocketsSample/wwwroot/index.html +++ b/samples/SocketsSample/wwwroot/index.html @@ -1,4 +1,4 @@ - + @@ -18,6 +18,12 @@
  • Server Sent Events
  • Web Sockets
  • +

    ASP.NET Core SignalR (Dynamic Hubs)

    +

    ASP.NET Core SignalR (Streaming)

    • Long polling
    • diff --git a/src/Microsoft.AspNetCore.SignalR/DynamicClientProxy.cs b/src/Microsoft.AspNetCore.SignalR/DynamicClientProxy.cs new file mode 100644 index 0000000000..a99e04d772 --- /dev/null +++ b/src/Microsoft.AspNetCore.SignalR/DynamicClientProxy.cs @@ -0,0 +1,23 @@ +// 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.Dynamic; + +namespace Microsoft.AspNetCore.SignalR +{ + public class DynamicClientProxy : DynamicObject + { + private readonly IClientProxy _clientProxy; + + public DynamicClientProxy(IClientProxy clientProxy) + { + _clientProxy = clientProxy; + } + + public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) + { + result = _clientProxy.InvokeAsync(binder.Name, args); + return true; + } + } +} diff --git a/src/Microsoft.AspNetCore.SignalR/DynamicHub.cs b/src/Microsoft.AspNetCore.SignalR/DynamicHub.cs new file mode 100644 index 0000000000..9a05cba7cd --- /dev/null +++ b/src/Microsoft.AspNetCore.SignalR/DynamicHub.cs @@ -0,0 +1,16 @@ +// 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 class DynamicHub : Hub + { + private DynamicHubClients _clients; + + public new DynamicHubClients Clients + { + get { return _clients ?? new DynamicHubClients(base.Clients); } + set { _clients = value; } + } + } +} diff --git a/src/Microsoft.AspNetCore.SignalR/DynamicHubClients.cs b/src/Microsoft.AspNetCore.SignalR/DynamicHubClients.cs new file mode 100644 index 0000000000..3f75f1d90e --- /dev/null +++ b/src/Microsoft.AspNetCore.SignalR/DynamicHubClients.cs @@ -0,0 +1,20 @@ +// 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 class DynamicHubClients + { + private readonly IHubClients _clients; + + public DynamicHubClients(IHubClients clients) + { + _clients = clients; + } + + public dynamic All => new DynamicClientProxy(_clients.All); + public dynamic User(string userId) => new DynamicClientProxy(_clients.User(userId)); + public dynamic Group(string group) => new DynamicClientProxy(_clients.Group(group)); + public dynamic Client(string connectionId) => new DynamicClientProxy(_clients.Client(connectionId)); + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs index 9f0f461107..a31f5b42aa 100644 --- a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/HubConnectionTests.cs @@ -39,18 +39,19 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests } [Theory] - [MemberData(nameof(HubProtocolsXTransports))] - public async Task CheckFixedMessage(IHubProtocol protocol, TransportType transport) + [MemberData(nameof(HubProtocolsXTransportsXHubPaths))] + public async Task CheckFixedMessage(IHubProtocol protocol, TransportType transportType, string path) { using (StartLog(out var loggerFactory)) { - var httpConnection = new HttpConnection(new Uri(_serverFixture.BaseUrl + "/hubs"), transport, loggerFactory); + + var httpConnection = new HttpConnection(new Uri(_serverFixture.BaseUrl + path), transportType, loggerFactory); var connection = new HubConnection(httpConnection, protocol, loggerFactory); try { await connection.StartAsync().OrTimeout(); - var result = await connection.InvokeAsync(nameof(TestHub.HelloWorld)).OrTimeout(); + var result = await connection.InvokeAsync("HelloWorld").OrTimeout(); Assert.Equal("Hello World!", result); } @@ -67,20 +68,19 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests } [Theory] - [MemberData(nameof(HubProtocolsXTransports))] - public async Task CanSendAndReceiveMessage(IHubProtocol protocol, TransportType transport) + [MemberData(nameof(HubProtocolsXTransportsXHubPaths))] + public async Task CanSendAndReceiveMessage(IHubProtocol protocol, TransportType transportType, string path) { using (StartLog(out var loggerFactory)) { const string originalMessage = "SignalR"; - - var httpConnection = new HttpConnection(new Uri(_serverFixture.BaseUrl + "/hubs"), transport, loggerFactory); + var httpConnection = new HttpConnection(new Uri(_serverFixture.BaseUrl + path), transportType, loggerFactory); var connection = new HubConnection(httpConnection, protocol, loggerFactory); try { await connection.StartAsync().OrTimeout(); - var result = await connection.InvokeAsync(nameof(TestHub.Echo), originalMessage).OrTimeout(); + var result = await connection.InvokeAsync("Echo", originalMessage).OrTimeout(); Assert.Equal(originalMessage, result); } @@ -97,20 +97,20 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests } [Theory] - [MemberData(nameof(HubProtocolsXTransports))] - public async Task MethodsAreCaseInsensitive(IHubProtocol protocol, TransportType transport) + [MemberData(nameof(HubProtocolsXTransportsXHubPaths))] + public async Task MethodsAreCaseInsensitive(IHubProtocol protocol, TransportType transportType, string path) { using (StartLog(out var loggerFactory)) { const string originalMessage = "SignalR"; - - var httpConnection = new HttpConnection(new Uri(_serverFixture.BaseUrl + "/hubs"), transport, loggerFactory); + var uriString = "http://test/" + path; + var httpConnection = new HttpConnection(new Uri(_serverFixture.BaseUrl + path), transportType, loggerFactory); var connection = new HubConnection(httpConnection, protocol, loggerFactory); try { await connection.StartAsync().OrTimeout(); - var result = await connection.InvokeAsync(nameof(TestHub.Echo).ToLowerInvariant(), originalMessage).OrTimeout(); + var result = await connection.InvokeAsync("echo", originalMessage).OrTimeout(); Assert.Equal(originalMessage, result); } @@ -127,14 +127,14 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests } [Theory] - [MemberData(nameof(HubProtocolsXTransports))] - public async Task CanInvokeClientMethodFromServer(IHubProtocol protocol, TransportType transport) + [MemberData(nameof(HubProtocolsXTransportsXHubPaths))] + public async Task CanInvokeClientMethodFromServer(IHubProtocol protocol, TransportType transportType, string path) { using (StartLog(out var loggerFactory)) { const string originalMessage = "SignalR"; - var httpConnection = new HttpConnection(new Uri(_serverFixture.BaseUrl + "/hubs"), transport, loggerFactory); + var httpConnection = new HttpConnection(new Uri(_serverFixture.BaseUrl + path), transportType, loggerFactory); var connection = new HubConnection(httpConnection, protocol, loggerFactory); try { @@ -143,7 +143,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests var tcs = new TaskCompletionSource(); connection.On("Echo", tcs.SetResult); - await connection.InvokeAsync(nameof(TestHub.CallEcho), originalMessage).OrTimeout(); + await connection.InvokeAsync("CallEcho", originalMessage).OrTimeout(); Assert.Equal(originalMessage, await tcs.Task.OrTimeout()); } @@ -160,12 +160,12 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests } [Theory] - [MemberData(nameof(HubProtocolsXTransports))] - public async Task CanStreamClientMethodFromServer(IHubProtocol protocol, TransportType transport) + [MemberData(nameof(HubProtocolsXTransportsXHubPaths))] + public async Task CanStreamClientMethodFromServer(IHubProtocol protocol, TransportType transportType, string path) { using (StartLog(out var loggerFactory)) { - var httpConnection = new HttpConnection(new Uri(_serverFixture.BaseUrl + "/hubs"), transport, loggerFactory); + var httpConnection = new HttpConnection(new Uri(_serverFixture.BaseUrl + path), transportType, loggerFactory); var connection = new HubConnection(httpConnection, protocol, loggerFactory); try { @@ -173,7 +173,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests var tcs = new TaskCompletionSource(); - var results = await connection.Stream(nameof(TestHub.Stream)).ReadAllAsync().OrTimeout(); + var results = await connection.Stream("Stream").ReadAllAsync().OrTimeout(); Assert.Equal(new[] { "a", "b", "c" }, results.ToArray()); } @@ -190,12 +190,12 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests } [Theory] - [MemberData(nameof(HubProtocolsXTransports))] - public async Task ServerClosesConnectionIfHubMethodCannotBeResolved(IHubProtocol hubProtocol, TransportType transport) + [MemberData(nameof(HubProtocolsXTransportsXHubPaths))] + public async Task ServerClosesConnectionIfHubMethodCannotBeResolved(IHubProtocol hubProtocol, TransportType transportType, string hubPath) { using (StartLog(out var loggerFactory)) { - var httpConnection = new HttpConnection(new Uri(_serverFixture.BaseUrl + "/hubs"), transport, loggerFactory); + var httpConnection = new HttpConnection(new Uri(_serverFixture.BaseUrl + hubPath), transportType, loggerFactory); var connection = new HubConnection(httpConnection, hubProtocol, loggerFactory); try { @@ -218,17 +218,22 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests } } - public static IEnumerable HubProtocolsXTransports() + public static IEnumerable HubProtocolsXTransportsXHubPaths() { foreach (var protocol in HubProtocols) { foreach (var transport in TransportTypes()) { - yield return new object[] { protocol, transport }; + foreach (var hubPath in HubPaths) + { + yield return new object[] { protocol, transport, hubPath }; + } } } } + public static string[] HubPaths = new[] { "/default", "/dynamic" }; + public static IEnumerable HubProtocols => new IHubProtocol[] { @@ -236,6 +241,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests new MessagePackHubProtocol(), }; + public static IEnumerable TransportTypes() { if (WebsocketsSupported()) diff --git a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/Hubs.cs b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/Hubs.cs index 058e3ee2d9..33daaa4202 100644 --- a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/Hubs.cs +++ b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/Hubs.cs @@ -4,6 +4,7 @@ using System; using System.Reactive.Linq; using System.Threading.Tasks; +using Microsoft.CSharp; namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { @@ -29,4 +30,32 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests return new[] { "a", "b", "c" }.ToObservable(); } } + + public class DynamicTestHub : DynamicHub + { + public string HelloWorld() + { + return "Hello World!"; + } + + public string Echo(string message) + { + return message; + } + + public async Task CallEcho(string message) + { + await Clients.Client(Context.ConnectionId).Echo(message); + } + + public IObservable Stream() + { + return new[] { "a", "b", "c" }.ToObservable(); + } + + public Task SendMessage(string message) + { + return Clients.All.Send(message); + } + } } diff --git a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/Microsoft.AspNetCore.SignalR.Client.FunctionalTests.csproj b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/Microsoft.AspNetCore.SignalR.Client.FunctionalTests.csproj index e54ec702d1..d14f25bf48 100644 --- a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/Microsoft.AspNetCore.SignalR.Client.FunctionalTests.csproj +++ b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/Microsoft.AspNetCore.SignalR.Client.FunctionalTests.csproj @@ -9,6 +9,10 @@ win7-x64 + + + + diff --git a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/Startup.cs b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/Startup.cs index 7874144d8d..b29410f3ba 100644 --- a/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/Startup.cs +++ b/test/Microsoft.AspNetCore.SignalR.Client.FunctionalTests/Startup.cs @@ -17,7 +17,8 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests { app.UseSignalR(routes => { - routes.MapHub("hubs"); + routes.MapHub("default"); + routes.MapHub("dynamic"); }); } } diff --git a/test/Microsoft.AspNetCore.SignalR.Tests/HubEndpointTests.cs b/test/Microsoft.AspNetCore.SignalR.Tests/HubEndpointTests.cs index db442410cd..61ecf3a363 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests/HubEndpointTests.cs +++ b/test/Microsoft.AspNetCore.SignalR.Tests/HubEndpointTests.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using System.Security.Claims; using System.Threading; using System.Threading.Tasks; @@ -9,6 +10,7 @@ using System.Threading.Tasks.Channels; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.SignalR.Internal.Protocol; using Microsoft.AspNetCore.SignalR.Tests.Common; +using Microsoft.CSharp; using Microsoft.Extensions.DependencyInjection; using Moq; using Xunit; @@ -142,16 +144,17 @@ namespace Microsoft.AspNetCore.SignalR.Tests } } - [Fact] - public async Task HubMethodsAreCaseInsensitive() + [Theory] + [MemberData(nameof(HubTypes))] + public async Task HubMethodsAreCaseInsensitive(Type hubType) { var serviceProvider = CreateServiceProvider(); - var endPoint = serviceProvider.GetService>(); + dynamic endPoint = serviceProvider.GetService(GetEndPointType(hubType)); using (var client = new TestClient()) { - var endPointTask = endPoint.OnConnectedAsync(client.Connection); + Task endPointTask = endPoint.OnConnectedAsync(client.Connection); var result = (await client.InvokeAsync("echo", "hello").OrTimeout()).Result; @@ -437,22 +440,23 @@ namespace Microsoft.AspNetCore.SignalR.Tests } } - [Fact] - public async Task BroadcastHubMethod_SendsToAllClients() + [Theory] + [MemberData(nameof(HubTypes))] + public async Task BroadcastHubMethodSendsToAllClients(Type hubType) { var serviceProvider = CreateServiceProvider(); - var endPoint = serviceProvider.GetService>(); + dynamic endPoint = serviceProvider.GetService(GetEndPointType(hubType)); using (var firstClient = new TestClient()) using (var secondClient = new TestClient()) { - var firstEndPointTask = endPoint.OnConnectedAsync(firstClient.Connection); - var secondEndPointTask = endPoint.OnConnectedAsync(secondClient.Connection); + 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.BroadcastMethod), "test").OrTimeout(); + await firstClient.SendInvocationAsync("BroadcastMethod", "test").OrTimeout(); foreach (var result in await Task.WhenAll( firstClient.Read(), @@ -472,22 +476,23 @@ namespace Microsoft.AspNetCore.SignalR.Tests } } - [Fact] - public async Task HubsCanAddAndSendToGroup() + [Theory] + [MemberData(nameof(HubTypes))] + public async Task HubsCanAddAndSendToGroup(Type hubType) { var serviceProvider = CreateServiceProvider(); - var endPoint = serviceProvider.GetService>(); + dynamic endPoint = serviceProvider.GetService(GetEndPointType(hubType)); using (var firstClient = new TestClient()) using (var secondClient = new TestClient()) { - var firstEndPointTask = endPoint.OnConnectedAsync(firstClient.Connection); - var secondEndPointTask = endPoint.OnConnectedAsync(secondClient.Connection); + Task firstEndPointTask = endPoint.OnConnectedAsync(firstClient.Connection); + Task secondEndPointTask = endPoint.OnConnectedAsync(secondClient.Connection); await Task.WhenAll(firstClient.Connected, secondClient.Connected).OrTimeout(); - var result = (await firstClient.InvokeAsync(nameof(MethodHub.GroupSendMethod), "testGroup", "test").OrTimeout()).Result; + var result = (await firstClient.InvokeAsync("GroupSendMethod", "testGroup", "test").OrTimeout()).Result; // check that 'firstConnection' hasn't received the group send Assert.Null(firstClient.TryRead()); @@ -534,22 +539,23 @@ namespace Microsoft.AspNetCore.SignalR.Tests } } - [Fact] - public async Task HubsCanSendToUser() + [Theory] + [MemberData(nameof(HubTypes))] + public async Task HubsCanSendToUser(Type hubType) { var serviceProvider = CreateServiceProvider(); - var endPoint = serviceProvider.GetService>(); + dynamic endPoint = serviceProvider.GetService(GetEndPointType(hubType)); using (var firstClient = new TestClient()) using (var secondClient = new TestClient()) { - var firstEndPointTask = endPoint.OnConnectedAsync(firstClient.Connection); - var secondEndPointTask = endPoint.OnConnectedAsync(secondClient.Connection); + 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.ClientSendMethod), secondClient.Connection.User.Identity.Name, "test").OrTimeout(); + await firstClient.SendInvocationAsync("ClientSendMethod", secondClient.Connection.User.Identity.Name, "test").OrTimeout(); // check that 'secondConnection' has received the group send var hubMessage = await secondClient.Read().OrTimeout(); @@ -566,22 +572,23 @@ namespace Microsoft.AspNetCore.SignalR.Tests } } - [Fact] - public async Task HubsCanSendToConnection() + [Theory] + [MemberData(nameof(HubTypes))] + public async Task HubsCanSendToConnection(Type hubType) { var serviceProvider = CreateServiceProvider(); - var endPoint = serviceProvider.GetService>(); + dynamic endPoint = serviceProvider.GetService(GetEndPointType(hubType)); using (var firstClient = new TestClient()) using (var secondClient = new TestClient()) { - var firstEndPointTask = endPoint.OnConnectedAsync(firstClient.Connection); - var secondEndPointTask = endPoint.OnConnectedAsync(secondClient.Connection); + 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.ConnectionSendMethod), secondClient.Connection.ConnectionId, "test").OrTimeout(); + await firstClient.SendInvocationAsync("ConnectionSendMethod", secondClient.Connection.ConnectionId, "test").OrTimeout(); // check that 'secondConnection' has received the group send var hubMessage = await secondClient.Read().OrTimeout(); @@ -721,6 +728,12 @@ namespace Microsoft.AspNetCore.SignalR.Tests } } + public static IEnumerable HubTypes() + { + yield return new Type[] { typeof(DynamicTestHub) }; + yield return new Type[] { typeof(MethodHub) }; + } + private static Type GetEndPointType(Type hubType) { var endPointType = typeof(HubEndPoint<>); @@ -744,6 +757,46 @@ namespace Microsoft.AspNetCore.SignalR.Tests return services.BuildServiceProvider(); } + private class DynamicTestHub : DynamicHub + { + public override Task OnConnectedAsync() + { + var tcs = (TaskCompletionSource)Context.Connection.Metadata["ConnectedTask"]; + tcs?.TrySetResult(true); + return base.OnConnectedAsync(); + } + + public string Echo(string data) + { + return data; + } + + public Task ClientSendMethod(string userId, string message) + { + return Clients.User(userId).Send(message); + } + + public Task ConnectionSendMethod(string connectionId, string message) + { + return Clients.Client(connectionId).Send(message); + } + + public Task GroupAddMethod(string groupName) + { + return Groups.AddAsync(Context.ConnectionId, groupName); + } + + public Task GroupSendMethod(string groupName, string message) + { + return Clients.Group(groupName).Send(message); + } + + public Task BroadcastMethod(string message) + { + return Clients.All.Broadcast(message); + } + } + public class StreamingHub : TestHub { public IObservable CounterObservable(int count) diff --git a/test/Microsoft.AspNetCore.SignalR.Tests/Microsoft.AspNetCore.SignalR.Tests.csproj b/test/Microsoft.AspNetCore.SignalR.Tests/Microsoft.AspNetCore.SignalR.Tests.csproj index 147599b53e..21923cfe38 100644 --- a/test/Microsoft.AspNetCore.SignalR.Tests/Microsoft.AspNetCore.SignalR.Tests.csproj +++ b/test/Microsoft.AspNetCore.SignalR.Tests/Microsoft.AspNetCore.SignalR.Tests.csproj @@ -14,6 +14,10 @@ win7-x64 + + + +