Support for Others and Caller Client Subsets(#1192)

This commit is contained in:
Mikael Mengistu 2017-12-11 17:30:53 -08:00 committed by GitHub
parent c0b9ae5e55
commit 75e102f97a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 200 additions and 22 deletions

View File

@ -18,7 +18,6 @@ namespace ChatSample.Hubs
public override async Task OnConnectedAsync()
{
await Clients.Client(Context.ConnectionId).InvokeAsync("SetUsersOnline", await GetUsersOnline());
await base.OnConnectedAsync();
}

View File

@ -111,7 +111,7 @@ namespace ChatSample
_hubContext = _serviceProvider.GetRequiredService<IHubContext<THub>>();
}
hub.Clients = _hubContext.Clients;
hub.Clients = new HubCallerClients(_hubContext.Clients, connection.ConnectionId);
hub.Context = new HubCallerContext(connection);
hub.Groups = _hubContext.Groups;

View File

@ -7,17 +7,19 @@ namespace Microsoft.AspNetCore.SignalR
{
public class DynamicHubClients
{
private readonly IHubClients _clients;
private readonly IHubCallerClients _clients;
public DynamicHubClients(IHubClients clients)
public DynamicHubClients(IHubCallerClients clients)
{
_clients = clients;
}
public dynamic All => new DynamicClientProxy(_clients.All);
public dynamic AllExcept(IReadOnlyList<string> excludedIds) => new DynamicClientProxy(_clients.AllExcept(excludedIds));
public dynamic User(string userId) => new DynamicClientProxy(_clients.User(userId));
public dynamic Group(string group) => new DynamicClientProxy(_clients.Group(group));
public dynamic Caller => new DynamicClientProxy(_clients.Caller);
public dynamic Client(string connectionId) => new DynamicClientProxy(_clients.Client(connectionId));
public dynamic Group(string group) => new DynamicClientProxy(_clients.Group(group));
public dynamic Others => new DynamicClientProxy(_clients.Others);
public dynamic User(string userId) => new DynamicClientProxy(_clients.User(userId));
}
}

View File

@ -9,11 +9,11 @@ namespace Microsoft.AspNetCore.SignalR
public class Hub : IDisposable
{
private bool _disposed;
private IHubClients _clients;
private IHubCallerClients _clients;
private HubCallerContext _context;
private IGroupManager _groups;
public IHubClients Clients
public IHubCallerClients Clients
{
get
{

View File

@ -0,0 +1,47 @@
// 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.Collections.Generic;
namespace Microsoft.AspNetCore.SignalR
{
public class HubCallerClients : IHubCallerClients
{
private string _connectionId;
private IHubClients _hubClients;
private string[] _currentConnectionId;
public HubCallerClients(IHubClients hubClients, string connectionId)
{
_connectionId = connectionId;
_hubClients = hubClients;
_currentConnectionId = new string[] { _connectionId };
}
public IClientProxy Caller => _hubClients.Client(_connectionId);
public IClientProxy Others => _hubClients.AllExcept(_currentConnectionId);
public IClientProxy All => _hubClients.All;
public IClientProxy AllExcept(IReadOnlyList<string> excludedIds)
{
return _hubClients.AllExcept(excludedIds);
}
public IClientProxy Client(string connectionId)
{
return _hubClients.Client(connectionId);
}
public IClientProxy Group(string groupName)
{
return _hubClients.Group(groupName);
}
public IClientProxy User(string userId)
{
return _hubClients.User(userId);
}
}
}

View File

@ -368,7 +368,7 @@ namespace Microsoft.AspNetCore.SignalR
private void InitializeHub(THub hub, HubConnectionContext connection)
{
hub.Clients = _hubContext.Clients;
hub.Clients = new HubCallerClients(_hubContext.Clients, connection.ConnectionId);
hub.Context = new HubCallerContext(connection);
hub.Groups = _hubContext.Groups;
}

View File

@ -5,9 +5,9 @@ namespace Microsoft.AspNetCore.SignalR
{
public class Hub<T> : Hub where T : class
{
private IHubClients<T> _clients;
private IHubCallerClients<T> _clients;
public new IHubClients<T> Clients
public new IHubCallerClients<T> Clients
{
get
{

View File

@ -0,0 +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.
namespace Microsoft.AspNetCore.SignalR
{
public interface IHubCallerClients : IHubCallerClients<IClientProxy> { }
}

View File

@ -0,0 +1,12 @@
// 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 interface IHubCallerClients<T> : IHubClients<T>
{
T Caller { get; }
T Others { get; }
}
}

View File

@ -1,9 +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 System.Collections.Generic;
using System.Text;
namespace Microsoft.AspNetCore.SignalR
{
@ -20,3 +18,4 @@ namespace Microsoft.AspNetCore.SignalR
T User(string userId);
}
}

View File

@ -5,32 +5,36 @@ using System.Collections.Generic;
namespace Microsoft.AspNetCore.SignalR
{
internal class TypedHubClients<T> : IHubClients<T>
internal class TypedHubClients<T> : IHubCallerClients<T>
{
private IHubClients hubClients;
private IHubCallerClients _hubClients;
public TypedHubClients(IHubClients dynamicContext)
public TypedHubClients(IHubCallerClients dynamicContext)
{
hubClients = dynamicContext;
_hubClients = dynamicContext;
}
public T All => TypedClientBuilder<T>.Build(hubClients.All);
public T All => TypedClientBuilder<T>.Build(_hubClients.All);
public T AllExcept(IReadOnlyList<string> excludedIds) => TypedClientBuilder<T>.Build(hubClients.AllExcept(excludedIds));
public T Caller => TypedClientBuilder<T>.Build(_hubClients.Caller);
public T Others => TypedClientBuilder<T>.Build(_hubClients.Others);
public T AllExcept(IReadOnlyList<string> excludedIds) => TypedClientBuilder<T>.Build(_hubClients.AllExcept(excludedIds));
public T Client(string connectionId)
{
return TypedClientBuilder<T>.Build(hubClients.Client(connectionId));
return TypedClientBuilder<T>.Build(_hubClients.Client(connectionId));
}
public T Group(string groupName)
{
return TypedClientBuilder<T>.Build(hubClients.Group(groupName));
return TypedClientBuilder<T>.Build(_hubClients.Group(groupName));
}
public T User(string userId)
{
return TypedClientBuilder<T>.Build(hubClients.User(userId));
return TypedClientBuilder<T>.Build(_hubClients.User(userId));
}
}
}

View File

@ -826,6 +826,84 @@ namespace Microsoft.AspNetCore.SignalR.Tests
}
}
[Theory]
[MemberData(nameof(HubTypes))]
public async Task SendToOthers(Type hubType)
{
var serviceProvider = CreateServiceProvider();
dynamic endPoint = serviceProvider.GetService(GetEndPointType(hubType));
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("SendToOthers", "To others").OrTimeout();
var secondClientResult = await secondClient.ReadAsync().OrTimeout();
var invocation = Assert.IsType<InvocationMessage>(secondClientResult);
Assert.Equal("Send", invocation.Target);
Assert.Equal("To others", invocation.Arguments[0]);
var firstClientResult = await firstClient.ReadAsync().OrTimeout();
var completion = Assert.IsType<CompletionMessage>(firstClientResult);
await secondClient.SendInvocationAsync("BroadcastMethod", "To everyone").OrTimeout();
firstClientResult = await firstClient.ReadAsync().OrTimeout();
invocation = Assert.IsType<InvocationMessage>(firstClientResult);
Assert.Equal("Broadcast", invocation.Target);
Assert.Equal("To everyone", invocation.Arguments[0]);
// kill the connections
firstClient.Dispose();
secondClient.Dispose();
await Task.WhenAll(firstEndPointTask, secondEndPointTask).OrTimeout();
}
}
[Theory]
[MemberData(nameof(HubTypes))]
public async Task SendToCaller(Type hubType)
{
var serviceProvider = CreateServiceProvider();
dynamic endPoint = serviceProvider.GetService(GetEndPointType(hubType));
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("SendToCaller", "To caller").OrTimeout();
var firstClientResult = await firstClient.ReadAsync().OrTimeout();
var invocation = Assert.IsType<InvocationMessage>(firstClientResult);
Assert.Equal("Send", invocation.Target);
Assert.Equal("To caller", invocation.Arguments[0]);
await firstClient.SendInvocationAsync("BroadcastMethod", "To everyone").OrTimeout();
var secondClientResult = await secondClient.ReadAsync().OrTimeout();
invocation = Assert.IsType<InvocationMessage>(secondClientResult);
Assert.Equal("Broadcast", invocation.Target);
Assert.Equal("To everyone", invocation.Arguments[0]);
// kill the connections
firstClient.Dispose();
await firstEndPointTask.OrTimeout();
}
}
[Theory]
[MemberData(nameof(HubTypes))]
public async Task SendToAllExcept(Type hubType)
@ -1557,6 +1635,16 @@ namespace Microsoft.AspNetCore.SignalR.Tests
{
return Clients.AllExcept(excludedIds).Send(message);
}
public Task SendToOthers(string message)
{
return Clients.Others.Send(message);
}
public Task SendToCaller(string message)
{
return Clients.Caller.Send(message);
}
}
public interface Test
@ -1735,6 +1823,16 @@ namespace Microsoft.AspNetCore.SignalR.Tests
{
return Clients.AllExcept(excludedIds).Send(message);
}
public Task SendToOthers(string message)
{
return Clients.Others.Send(message);
}
public Task SendToCaller(string message)
{
return Clients.Caller.Send(message);
}
}
public class StreamingHub : TestHub
@ -1930,6 +2028,16 @@ namespace Microsoft.AspNetCore.SignalR.Tests
{
return Context.Connection.GetHttpContext() != null;
}
public Task SendToOthers(string message)
{
return Clients.Others.InvokeAsync("Send", message);
}
public Task SendToCaller(string message)
{
return Clients.Caller.InvokeAsync("Send", message);
}
}
private class InheritedHub : BaseHub