Dynamic Hub Change Part 2 (#644)

This commit is contained in:
Mikael Mengistu 2017-07-14 15:54:31 -07:00 committed by GitHub
parent 0ebd33a25c
commit 8ba29b578d
13 changed files with 276 additions and 59 deletions

View File

@ -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}");
}
}
}

View File

@ -47,7 +47,8 @@ namespace SocketsSample
app.UseSignalR(routes => app.UseSignalR(routes =>
{ {
routes.MapHub<Chat>("hubs"); routes.MapHub<DynamicChat>("dynamic");
routes.MapHub<Chat>("default");
routes.MapHub<Streaming>("streaming"); routes.MapHub<Streaming>("streaming");
}); });

View File

@ -78,6 +78,8 @@ function getText(id) {
} }
let transportType = signalR.TransportType[getParameterByName('transport')] || signalR.TransportType.WebSockets; 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]; document.getElementById('head1').innerHTML = signalR.TransportType[transportType];
@ -89,7 +91,8 @@ var connection;
click('connect', event => { click('connect', event => {
connectButton.disabled = true; connectButton.disabled = true;
disconnectButton.disabled = false; 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 = new signalR.HubConnection(http);
connection.on('Send', msg => { connection.on('Send', msg => {
addLine('message-list', msg); addLine('message-list', msg);

View File

@ -1,4 +1,4 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
@ -18,6 +18,12 @@
<li><a href="hubs.html?transport=ServerSentEvents">Server Sent Events</a></li> <li><a href="hubs.html?transport=ServerSentEvents">Server Sent Events</a></li>
<li><a href="hubs.html?transport=WebSockets">Web Sockets</a></li> <li><a href="hubs.html?transport=WebSockets">Web Sockets</a></li>
</ul> </ul>
<h1>ASP.NET Core SignalR (Dynamic Hubs)</h1>
<ul>
<li><a href="hubs.html?transport=LongPolling&hubType=dynamic">Long polling</a></li>
<li><a href="hubs.html?transport=ServerSentEvents&hubType=dynamic">Server Sent Events</a></li>
<li><a href="hubs.html?transport=WebSockets&hubType=dynamic">Web Sockets</a></li>
</ul>
<h1>ASP.NET Core SignalR (Streaming)</h1> <h1>ASP.NET Core SignalR (Streaming)</h1>
<ul> <ul>
<li><a href="streaming.html?transport=LongPolling">Long polling</a></li> <li><a href="streaming.html?transport=LongPolling">Long polling</a></li>

View File

@ -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;
}
}
}

View File

@ -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; }
}
}
}

View File

@ -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));
}
}

View File

@ -39,18 +39,19 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests
} }
[Theory] [Theory]
[MemberData(nameof(HubProtocolsXTransports))] [MemberData(nameof(HubProtocolsXTransportsXHubPaths))]
public async Task CheckFixedMessage(IHubProtocol protocol, TransportType transport) public async Task CheckFixedMessage(IHubProtocol protocol, TransportType transportType, string path)
{ {
using (StartLog(out var loggerFactory)) 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); var connection = new HubConnection(httpConnection, protocol, loggerFactory);
try try
{ {
await connection.StartAsync().OrTimeout(); await connection.StartAsync().OrTimeout();
var result = await connection.InvokeAsync<string>(nameof(TestHub.HelloWorld)).OrTimeout(); var result = await connection.InvokeAsync<string>("HelloWorld").OrTimeout();
Assert.Equal("Hello World!", result); Assert.Equal("Hello World!", result);
} }
@ -67,20 +68,19 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests
} }
[Theory] [Theory]
[MemberData(nameof(HubProtocolsXTransports))] [MemberData(nameof(HubProtocolsXTransportsXHubPaths))]
public async Task CanSendAndReceiveMessage(IHubProtocol protocol, TransportType transport) public async Task CanSendAndReceiveMessage(IHubProtocol protocol, TransportType transportType, string path)
{ {
using (StartLog(out var loggerFactory)) using (StartLog(out var loggerFactory))
{ {
const string originalMessage = "SignalR"; const string originalMessage = "SignalR";
var httpConnection = new HttpConnection(new Uri(_serverFixture.BaseUrl + path), transportType, loggerFactory);
var httpConnection = new HttpConnection(new Uri(_serverFixture.BaseUrl + "/hubs"), transport, loggerFactory);
var connection = new HubConnection(httpConnection, protocol, loggerFactory); var connection = new HubConnection(httpConnection, protocol, loggerFactory);
try try
{ {
await connection.StartAsync().OrTimeout(); await connection.StartAsync().OrTimeout();
var result = await connection.InvokeAsync<string>(nameof(TestHub.Echo), originalMessage).OrTimeout(); var result = await connection.InvokeAsync<string>("Echo", originalMessage).OrTimeout();
Assert.Equal(originalMessage, result); Assert.Equal(originalMessage, result);
} }
@ -97,20 +97,20 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests
} }
[Theory] [Theory]
[MemberData(nameof(HubProtocolsXTransports))] [MemberData(nameof(HubProtocolsXTransportsXHubPaths))]
public async Task MethodsAreCaseInsensitive(IHubProtocol protocol, TransportType transport) public async Task MethodsAreCaseInsensitive(IHubProtocol protocol, TransportType transportType, string path)
{ {
using (StartLog(out var loggerFactory)) using (StartLog(out var loggerFactory))
{ {
const string originalMessage = "SignalR"; const string originalMessage = "SignalR";
var uriString = "http://test/" + path;
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); var connection = new HubConnection(httpConnection, protocol, loggerFactory);
try try
{ {
await connection.StartAsync().OrTimeout(); await connection.StartAsync().OrTimeout();
var result = await connection.InvokeAsync<string>(nameof(TestHub.Echo).ToLowerInvariant(), originalMessage).OrTimeout(); var result = await connection.InvokeAsync<string>("echo", originalMessage).OrTimeout();
Assert.Equal(originalMessage, result); Assert.Equal(originalMessage, result);
} }
@ -127,14 +127,14 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests
} }
[Theory] [Theory]
[MemberData(nameof(HubProtocolsXTransports))] [MemberData(nameof(HubProtocolsXTransportsXHubPaths))]
public async Task CanInvokeClientMethodFromServer(IHubProtocol protocol, TransportType transport) public async Task CanInvokeClientMethodFromServer(IHubProtocol protocol, TransportType transportType, string path)
{ {
using (StartLog(out var loggerFactory)) using (StartLog(out var loggerFactory))
{ {
const string originalMessage = "SignalR"; 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); var connection = new HubConnection(httpConnection, protocol, loggerFactory);
try try
{ {
@ -143,7 +143,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests
var tcs = new TaskCompletionSource<string>(); var tcs = new TaskCompletionSource<string>();
connection.On<string>("Echo", tcs.SetResult); connection.On<string>("Echo", tcs.SetResult);
await connection.InvokeAsync(nameof(TestHub.CallEcho), originalMessage).OrTimeout(); await connection.InvokeAsync("CallEcho", originalMessage).OrTimeout();
Assert.Equal(originalMessage, await tcs.Task.OrTimeout()); Assert.Equal(originalMessage, await tcs.Task.OrTimeout());
} }
@ -160,12 +160,12 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests
} }
[Theory] [Theory]
[MemberData(nameof(HubProtocolsXTransports))] [MemberData(nameof(HubProtocolsXTransportsXHubPaths))]
public async Task CanStreamClientMethodFromServer(IHubProtocol protocol, TransportType transport) public async Task CanStreamClientMethodFromServer(IHubProtocol protocol, TransportType transportType, string path)
{ {
using (StartLog(out var loggerFactory)) 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); var connection = new HubConnection(httpConnection, protocol, loggerFactory);
try try
{ {
@ -173,7 +173,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests
var tcs = new TaskCompletionSource<string>(); var tcs = new TaskCompletionSource<string>();
var results = await connection.Stream<string>(nameof(TestHub.Stream)).ReadAllAsync().OrTimeout(); var results = await connection.Stream<string>("Stream").ReadAllAsync().OrTimeout();
Assert.Equal(new[] { "a", "b", "c" }, results.ToArray()); Assert.Equal(new[] { "a", "b", "c" }, results.ToArray());
} }
@ -190,12 +190,12 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests
} }
[Theory] [Theory]
[MemberData(nameof(HubProtocolsXTransports))] [MemberData(nameof(HubProtocolsXTransportsXHubPaths))]
public async Task ServerClosesConnectionIfHubMethodCannotBeResolved(IHubProtocol hubProtocol, TransportType transport) public async Task ServerClosesConnectionIfHubMethodCannotBeResolved(IHubProtocol hubProtocol, TransportType transportType, string hubPath)
{ {
using (StartLog(out var loggerFactory)) 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); var connection = new HubConnection(httpConnection, hubProtocol, loggerFactory);
try try
{ {
@ -218,17 +218,22 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests
} }
} }
public static IEnumerable<object []> HubProtocolsXTransports() public static IEnumerable<object[]> HubProtocolsXTransportsXHubPaths()
{ {
foreach (var protocol in HubProtocols) foreach (var protocol in HubProtocols)
{ {
foreach (var transport in TransportTypes()) 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<IHubProtocol> HubProtocols => public static IEnumerable<IHubProtocol> HubProtocols =>
new IHubProtocol[] new IHubProtocol[]
{ {
@ -236,6 +241,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests
new MessagePackHubProtocol(), new MessagePackHubProtocol(),
}; };
public static IEnumerable<TransportType> TransportTypes() public static IEnumerable<TransportType> TransportTypes()
{ {
if (WebsocketsSupported()) if (WebsocketsSupported())

View File

@ -4,6 +4,7 @@
using System; using System;
using System.Reactive.Linq; using System.Reactive.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.CSharp;
namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests
{ {
@ -29,4 +30,32 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests
return new[] { "a", "b", "c" }.ToObservable(); 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<string> Stream()
{
return new[] { "a", "b", "c" }.ToObservable();
}
public Task SendMessage(string message)
{
return Clients.All.Send(message);
}
}
} }

View File

@ -9,6 +9,10 @@
<RuntimeIdentifier Condition="'$(TargetFramework)' != 'netcoreapp2.0'">win7-x64</RuntimeIdentifier> <RuntimeIdentifier Condition="'$(TargetFramework)' != 'netcoreapp2.0'">win7-x64</RuntimeIdentifier>
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net461'">
<PackageReference Include="Microsoft.CSharp" Version="$(CoreFxVersion)" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="..\Common\ServerFixture.cs" Link="ServerFixture.cs" /> <Compile Include="..\Common\ServerFixture.cs" Link="ServerFixture.cs" />
<Compile Include="..\Common\TaskExtensions.cs" Link="TaskExtensions.cs" /> <Compile Include="..\Common\TaskExtensions.cs" Link="TaskExtensions.cs" />

View File

@ -17,7 +17,8 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests
{ {
app.UseSignalR(routes => app.UseSignalR(routes =>
{ {
routes.MapHub<TestHub>("hubs"); routes.MapHub<TestHub>("default");
routes.MapHub<DynamicTestHub>("dynamic");
}); });
} }
} }

View File

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Collections.Generic;
using System.Security.Claims; using System.Security.Claims;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -9,6 +10,7 @@ using System.Threading.Tasks.Channels;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.SignalR.Internal.Protocol; using Microsoft.AspNetCore.SignalR.Internal.Protocol;
using Microsoft.AspNetCore.SignalR.Tests.Common; using Microsoft.AspNetCore.SignalR.Tests.Common;
using Microsoft.CSharp;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Moq; using Moq;
using Xunit; using Xunit;
@ -142,16 +144,17 @@ namespace Microsoft.AspNetCore.SignalR.Tests
} }
} }
[Fact] [Theory]
public async Task HubMethodsAreCaseInsensitive() [MemberData(nameof(HubTypes))]
public async Task HubMethodsAreCaseInsensitive(Type hubType)
{ {
var serviceProvider = CreateServiceProvider(); var serviceProvider = CreateServiceProvider();
var endPoint = serviceProvider.GetService<HubEndPoint<MethodHub>>(); dynamic endPoint = serviceProvider.GetService(GetEndPointType(hubType));
using (var client = new TestClient()) 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; var result = (await client.InvokeAsync("echo", "hello").OrTimeout()).Result;
@ -437,22 +440,23 @@ namespace Microsoft.AspNetCore.SignalR.Tests
} }
} }
[Fact] [Theory]
public async Task BroadcastHubMethod_SendsToAllClients() [MemberData(nameof(HubTypes))]
public async Task BroadcastHubMethodSendsToAllClients(Type hubType)
{ {
var serviceProvider = CreateServiceProvider(); var serviceProvider = CreateServiceProvider();
var endPoint = serviceProvider.GetService<HubEndPoint<MethodHub>>(); dynamic endPoint = serviceProvider.GetService(GetEndPointType(hubType));
using (var firstClient = new TestClient()) using (var firstClient = new TestClient())
using (var secondClient = new TestClient()) using (var secondClient = new TestClient())
{ {
var firstEndPointTask = endPoint.OnConnectedAsync(firstClient.Connection); Task firstEndPointTask = endPoint.OnConnectedAsync(firstClient.Connection);
var secondEndPointTask = endPoint.OnConnectedAsync(secondClient.Connection); Task secondEndPointTask = endPoint.OnConnectedAsync(secondClient.Connection);
await Task.WhenAll(firstClient.Connected, secondClient.Connected).OrTimeout(); 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( foreach (var result in await Task.WhenAll(
firstClient.Read(), firstClient.Read(),
@ -472,22 +476,23 @@ namespace Microsoft.AspNetCore.SignalR.Tests
} }
} }
[Fact] [Theory]
public async Task HubsCanAddAndSendToGroup() [MemberData(nameof(HubTypes))]
public async Task HubsCanAddAndSendToGroup(Type hubType)
{ {
var serviceProvider = CreateServiceProvider(); var serviceProvider = CreateServiceProvider();
var endPoint = serviceProvider.GetService<HubEndPoint<MethodHub>>(); dynamic endPoint = serviceProvider.GetService(GetEndPointType(hubType));
using (var firstClient = new TestClient()) using (var firstClient = new TestClient())
using (var secondClient = new TestClient()) using (var secondClient = new TestClient())
{ {
var firstEndPointTask = endPoint.OnConnectedAsync(firstClient.Connection); Task firstEndPointTask = endPoint.OnConnectedAsync(firstClient.Connection);
var secondEndPointTask = endPoint.OnConnectedAsync(secondClient.Connection); Task secondEndPointTask = endPoint.OnConnectedAsync(secondClient.Connection);
await Task.WhenAll(firstClient.Connected, secondClient.Connected).OrTimeout(); 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 // check that 'firstConnection' hasn't received the group send
Assert.Null(firstClient.TryRead()); Assert.Null(firstClient.TryRead());
@ -534,22 +539,23 @@ namespace Microsoft.AspNetCore.SignalR.Tests
} }
} }
[Fact] [Theory]
public async Task HubsCanSendToUser() [MemberData(nameof(HubTypes))]
public async Task HubsCanSendToUser(Type hubType)
{ {
var serviceProvider = CreateServiceProvider(); var serviceProvider = CreateServiceProvider();
var endPoint = serviceProvider.GetService<HubEndPoint<MethodHub>>(); dynamic endPoint = serviceProvider.GetService(GetEndPointType(hubType));
using (var firstClient = new TestClient()) using (var firstClient = new TestClient())
using (var secondClient = new TestClient()) using (var secondClient = new TestClient())
{ {
var firstEndPointTask = endPoint.OnConnectedAsync(firstClient.Connection); Task firstEndPointTask = endPoint.OnConnectedAsync(firstClient.Connection);
var secondEndPointTask = endPoint.OnConnectedAsync(secondClient.Connection); Task secondEndPointTask = endPoint.OnConnectedAsync(secondClient.Connection);
await Task.WhenAll(firstClient.Connected, secondClient.Connected).OrTimeout(); 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 // check that 'secondConnection' has received the group send
var hubMessage = await secondClient.Read().OrTimeout(); var hubMessage = await secondClient.Read().OrTimeout();
@ -566,22 +572,23 @@ namespace Microsoft.AspNetCore.SignalR.Tests
} }
} }
[Fact] [Theory]
public async Task HubsCanSendToConnection() [MemberData(nameof(HubTypes))]
public async Task HubsCanSendToConnection(Type hubType)
{ {
var serviceProvider = CreateServiceProvider(); var serviceProvider = CreateServiceProvider();
var endPoint = serviceProvider.GetService<HubEndPoint<MethodHub>>(); dynamic endPoint = serviceProvider.GetService(GetEndPointType(hubType));
using (var firstClient = new TestClient()) using (var firstClient = new TestClient())
using (var secondClient = new TestClient()) using (var secondClient = new TestClient())
{ {
var firstEndPointTask = endPoint.OnConnectedAsync(firstClient.Connection); Task firstEndPointTask = endPoint.OnConnectedAsync(firstClient.Connection);
var secondEndPointTask = endPoint.OnConnectedAsync(secondClient.Connection); Task secondEndPointTask = endPoint.OnConnectedAsync(secondClient.Connection);
await Task.WhenAll(firstClient.Connected, secondClient.Connected).OrTimeout(); 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 // check that 'secondConnection' has received the group send
var hubMessage = await secondClient.Read().OrTimeout(); var hubMessage = await secondClient.Read().OrTimeout();
@ -721,6 +728,12 @@ namespace Microsoft.AspNetCore.SignalR.Tests
} }
} }
public static IEnumerable<Type[]> HubTypes()
{
yield return new Type[] { typeof(DynamicTestHub) };
yield return new Type[] { typeof(MethodHub) };
}
private static Type GetEndPointType(Type hubType) private static Type GetEndPointType(Type hubType)
{ {
var endPointType = typeof(HubEndPoint<>); var endPointType = typeof(HubEndPoint<>);
@ -744,6 +757,46 @@ namespace Microsoft.AspNetCore.SignalR.Tests
return services.BuildServiceProvider(); return services.BuildServiceProvider();
} }
private class DynamicTestHub : DynamicHub
{
public override Task OnConnectedAsync()
{
var tcs = (TaskCompletionSource<bool>)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 class StreamingHub : TestHub
{ {
public IObservable<string> CounterObservable(int count) public IObservable<string> CounterObservable(int count)

View File

@ -14,6 +14,10 @@
<RuntimeIdentifier Condition="'$(TargetFramework)' != 'netcoreapp2.0'">win7-x64</RuntimeIdentifier> <RuntimeIdentifier Condition="'$(TargetFramework)' != 'netcoreapp2.0'">win7-x64</RuntimeIdentifier>
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net461'">
<PackageReference Include="Microsoft.CSharp" Version="$(CoreFxVersion)" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="..\Common\ServerFixture.cs" Link="ServerFixture.cs" /> <Compile Include="..\Common\ServerFixture.cs" Link="ServerFixture.cs" />
<Compile Include="..\Common\TaskExtensions.cs" Link="TaskExtensions.cs" /> <Compile Include="..\Common\TaskExtensions.cs" Link="TaskExtensions.cs" />