Support for Others and Caller Client Subsets(#1192)
This commit is contained in:
parent
c0b9ae5e55
commit
75e102f97a
|
|
@ -18,7 +18,6 @@ namespace ChatSample.Hubs
|
|||
public override async Task OnConnectedAsync()
|
||||
{
|
||||
await Clients.Client(Context.ConnectionId).InvokeAsync("SetUsersOnline", await GetUsersOnline());
|
||||
|
||||
await base.OnConnectedAsync();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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> { }
|
||||
}
|
||||
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue