Merge branch 'release/2.1' into dev

This commit is contained in:
Andrew Stanton-Nurse 2018-05-01 16:15:57 -07:00
commit 1bba0fde87
77 changed files with 2337 additions and 178 deletions

View File

@ -18,6 +18,9 @@ using Microsoft.Extensions.Logging.Abstractions;
namespace Microsoft.AspNetCore.Http.Connections.Client
{
/// <summary>
/// Used to make a connection to an ASP.NET Core ConnectionHandler using an HTTP-based transport.
/// </summary>
public partial class HttpConnection : ConnectionContext, IConnectionInherentKeepAliveFeature
{
// Not configurable on purpose, high enough that if we reach here, it's likely
@ -47,6 +50,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Client
private readonly ILoggerFactory _loggerFactory;
private Func<Task<string>> _accessTokenProvider;
/// <inheritdoc />
public override IDuplexPipe Transport
{
get
@ -61,21 +65,42 @@ namespace Microsoft.AspNetCore.Http.Connections.Client
set => throw new NotSupportedException("The transport pipe isn't settable.");
}
/// <inheritdoc />
public override IFeatureCollection Features { get; } = new FeatureCollection();
/// <inheritdoc />
public override string ConnectionId { get; set; }
/// <inheritdoc />
public override IDictionary<object, object> Items { get; set; } = new ConnectionItems();
/// <inheritdoc />
bool IConnectionInherentKeepAliveFeature.HasInherentKeepAlive => _hasInherentKeepAlive;
/// <summary>
/// Initializes a new instance of the <see cref="HttpConnection"/> class.
/// </summary>
/// <param name="url">The URL to connect to.</param>
public HttpConnection(Uri url)
: this(url, HttpTransports.All)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="HttpConnection"/> class.
/// </summary>
/// <param name="url">The URL to connect to.</param>
/// <param name="transports">A bitmask comprised of one or more <see cref="HttpTransportType"/> that specify what transports the client should use.</param>
public HttpConnection(Uri url, HttpTransportType transports)
: this(url, transports, loggerFactory: null)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="HttpConnection"/> class.
/// </summary>
/// <param name="url">The URL to connect to.</param>
/// <param name="transports">A bitmask comprised of one or more <see cref="HttpTransportType"/> that specify what transports the client should use.</param>
/// <param name="loggerFactory">The logger factory.</param>
public HttpConnection(Uri url, HttpTransportType transports, ILoggerFactory loggerFactory)
: this(CreateHttpOptions(url, transports), loggerFactory)
{
@ -90,6 +115,11 @@ namespace Microsoft.AspNetCore.Http.Connections.Client
return new HttpConnectionOptions { Url = url, Transports = transports };
}
/// <summary>
/// Initializes a new instance of the <see cref="HttpConnection"/> class.
/// </summary>
/// <param name="httpConnectionOptions">The connection options to use.</param>
/// <param name="loggerFactory">The logger factory.</param>
public HttpConnection(HttpConnectionOptions httpConnectionOptions, ILoggerFactory loggerFactory)
{
if (httpConnectionOptions.Url == null)
@ -121,11 +151,30 @@ namespace Microsoft.AspNetCore.Http.Connections.Client
_transportFactory = transportFactory;
}
/// <summary>
/// Starts the connection.
/// </summary>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous start.</returns>
/// <remarks>
/// A connection cannot be restarted after it has stopped. To restart a connection
/// a new instance should be created using the same options.
/// </remarks>
public async Task StartAsync(CancellationToken cancellationToken = default)
{
await StartAsync(TransferFormat.Binary, cancellationToken);
}
/// <summary>
/// Starts the connection using the specified transfer format.
/// </summary>
/// <param name="transferFormat">The transfer format the connection should use.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous start.</returns>
/// <remarks>
/// A connection cannot be restarted after it has stopped. To restart a connection
/// a new instance should be created using the same options.
/// </remarks>
public async Task StartAsync(TransferFormat transferFormat, CancellationToken cancellationToken = default)
{
await StartAsyncCore(transferFormat).ForceAsync();
@ -165,6 +214,14 @@ namespace Microsoft.AspNetCore.Http.Connections.Client
}
}
/// <summary>
/// Disposes the connection.
/// </summary>
/// <returns>A <see cref="Task"/> that represents the asynchronous dispose.</returns>
/// <remarks>
/// A connection cannot be restarted after it has stopped. To restart a connection
/// a new instance should be created using the same options.
/// </remarks>
public async Task DisposeAsync() => await DisposeAsyncCore().ForceAsync();
private async Task DisposeAsyncCore()

View File

@ -11,12 +11,18 @@ using System.Threading.Tasks;
namespace Microsoft.AspNetCore.Http.Connections.Client
{
/// <summary>
/// Options used to configure a <see cref="HttpConnection"/> instance.
/// </summary>
public class HttpConnectionOptions
{
private IDictionary<string, string> _headers;
private X509CertificateCollection _clientCertificates;
private CookieContainer _cookies;
/// <summary>
/// Initializes a new instance of the <see cref="HttpConnectionOptions"/> class.
/// </summary>
public HttpConnectionOptions()
{
_headers = new Dictionary<string, string>();
@ -28,37 +34,78 @@ namespace Microsoft.AspNetCore.Http.Connections.Client
/// <summary>
/// Gets or sets a delegate for wrapping or replacing the <see cref="HttpMessageHandlerFactory"/>
/// that will make HTTP requests the server.
/// that will make HTTP requests.
/// </summary>
public Func<HttpMessageHandler, HttpMessageHandler> HttpMessageHandlerFactory { get; set; }
/// <summary>
/// Gets or sets a collection of headers that will be sent with HTTP requests.
/// </summary>
public IDictionary<string, string> Headers
{
get => _headers;
set => _headers = value ?? throw new ArgumentNullException(nameof(value));
}
/// <summary>
/// Gets or sets a collection of client certificates that will be sent with HTTP requests.
/// </summary>
public X509CertificateCollection ClientCertificates
{
get => _clientCertificates;
set => _clientCertificates = value ?? throw new ArgumentNullException(nameof(value));
}
/// <summary>
/// Gets or sets a collection of cookies that will be sent with HTTP requests.
/// </summary>
public CookieContainer Cookies
{
get => _cookies;
set => _cookies = value ?? throw new ArgumentNullException(nameof(value));
}
/// <summary>
/// Gets or sets the URL used to send HTTP requests.
/// </summary>
public Uri Url { get; set; }
/// <summary>
/// Gets or sets a bitmask comprised of one or more <see cref="HttpTransportType"/> that specify what transports the client should use to send HTTP requests.
/// </summary>
public HttpTransportType Transports { get; set; }
/// <summary>
/// Gets or sets a value indicating whether negotiation is skipped when connecting to the server.
/// </summary>
/// <remarks>
/// Negotiation can only be skipped when using the <see cref="HttpTransportType.WebSockets"/> transport.
/// </remarks>
public bool SkipNegotiation { get; set; }
/// <summary>
/// Gets or sets an access token provider that will be called to return a token for each HTTP request.
/// </summary>
public Func<Task<string>> AccessTokenProvider { get; set; }
/// <summary>
/// Gets or sets a close timeout.
/// </summary>
public TimeSpan CloseTimeout { get; set; } = TimeSpan.FromSeconds(5);
/// <summary>
/// Gets or sets the credentials used when making HTTP requests.
/// </summary>
public ICredentials Credentials { get; set; }
/// <summary>
/// Gets or sets the proxy used when making HTTP requests.
/// </summary>
public IWebProxy Proxy { get; set; }
/// <summary>
/// Gets or sets a value indicating whether default credentials are used when making HTTP requests.
/// </summary>
public bool? UseDefaultCredentials { get; set; }
/// <summary>

View File

@ -5,12 +5,30 @@ using System;
namespace Microsoft.AspNetCore.Http.Connections
{
/// <summary>
/// Specifies transports that the client can use to send HTTP requests.
/// </summary>
/// <remarks>
/// This enumeration has a <see cref="FlagsAttribute"/> attribute that allows a bitwise combination of its member values.
/// </remarks>
[Flags]
public enum HttpTransportType
{
/// <summary>
/// Specifies that no transport is used.
/// </summary>
None = 0,
/// <summary>
/// Specifies that the web sockets transport is used.
/// </summary>
WebSockets = 1,
/// <summary>
/// Specifies that the server sent events transport is used.
/// </summary>
ServerSentEvents = 2,
/// <summary>
/// Specifies that the long polling transport is used.
/// </summary>
LongPolling = 4,
}
}

View File

@ -3,10 +3,14 @@
namespace Microsoft.AspNetCore.Http.Connections
{
/// <summary>
/// Constants related to HTTP transports.
/// </summary>
public static class HttpTransports
{
// Note that this is static readonly instead of const so it is not baked into a DLL when referenced
// Updating package without recompiling will automatically pick up new transports added here
/// <summary>
/// A bitmask comprised of all available <see cref="HttpTransportType"/> values.
/// </summary>
public static readonly HttpTransportType All = HttpTransportType.WebSockets | HttpTransportType.ServerSentEvents | HttpTransportType.LongPolling;
}
}

View File

@ -9,8 +9,17 @@ using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.AspNetCore.Builder
{
/// <summary>
/// Extension methods for <see cref="IApplicationBuilder"/>.
/// </summary>
public static class ConnectionsAppBuilderExtensions
{
/// <summary>
/// Adds support for ASP.NET Core Connection Handlers to the <see cref="IApplicationBuilder"/> request execution pipeline.
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder"/>.</param>
/// <param name="configure">A callback to configure connection routes.</param>
/// <returns>The same instance of the <see cref="IApplicationBuilder"/> for chaining.</returns>
public static IApplicationBuilder UseConnections(this IApplicationBuilder app, Action<ConnectionsRouteBuilder> configure)
{
if (configure == null)

View File

@ -6,8 +6,16 @@ using Microsoft.Extensions.DependencyInjection.Extensions;
namespace Microsoft.Extensions.DependencyInjection
{
/// <summary>
/// Extension methods for <see cref="IServiceCollection"/>.
/// </summary>
public static class ConnectionsDependencyInjectionExtensions
{
/// <summary>
/// Adds required services for ASP.NET Core Connection Handlers to the specified <see cref="IServiceCollection" />.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection" /> to add services to.</param>
/// <returns>The same instance of the <see cref="IServiceCollection"/> for chaining.</returns>
public static IServiceCollection AddConnections(this IServiceCollection services)
{
services.AddRouting();

View File

@ -10,20 +10,39 @@ using Microsoft.AspNetCore.Routing;
namespace Microsoft.AspNetCore.Http.Connections
{
/// <summary>
/// Maps routes to ASP.NET Core Connection Handlers.
/// </summary>
public class ConnectionsRouteBuilder
{
private readonly HttpConnectionDispatcher _dispatcher;
private readonly RouteBuilder _routes;
/// <summary>
/// Initializes a new instance of the <see cref="ConnectionsRouteBuilder"/> class.
/// </summary>
/// <param name="routes">The underlying <see cref="RouteBuilder"/>.</param>
/// <param name="dispatcher">The dispatcher.</param>
public ConnectionsRouteBuilder(RouteBuilder routes, HttpConnectionDispatcher dispatcher)
{
_routes = routes;
_dispatcher = dispatcher;
}
/// <summary>
/// Maps incoming requests with the specified path to the provided connection pipeline.
/// </summary>
/// <param name="path">The request path.</param>
/// <param name="configure">A callback to configure the connection.</param>
public void MapConnections(PathString path, Action<IConnectionBuilder> configure) =>
MapConnections(path, new HttpConnectionDispatcherOptions(), configure);
/// <summary>
/// Maps incoming requests with the specified path to the provided connection pipeline.
/// </summary>
/// <param name="path">The request path.</param>
/// <param name="options">Options used to configure the connection.</param>
/// <param name="configure">A callback to configure the connection.</param>
public void MapConnections(PathString path, HttpConnectionDispatcherOptions options, Action<IConnectionBuilder> configure)
{
var connectionBuilder = new ConnectionBuilder(_routes.ServiceProvider);
@ -33,11 +52,22 @@ namespace Microsoft.AspNetCore.Http.Connections
_routes.MapRoute(path + "/negotiate", c => _dispatcher.ExecuteNegotiateAsync(c, options));
}
/// <summary>
/// Maps incoming requests with the specified path to the provided connection pipeline.
/// </summary>
/// <typeparam name="TConnectionHandler">The <see cref="ConnectionHandler"/> type.</typeparam>
/// <param name="path">The request path.</param>
public void MapConnectionHandler<TConnectionHandler>(PathString path) where TConnectionHandler : ConnectionHandler
{
MapConnectionHandler<TConnectionHandler>(path, configureOptions: null);
}
/// <summary>
/// Maps incoming requests with the specified path to the provided connection pipeline.
/// </summary>
/// <typeparam name="TConnectionHandler">The <see cref="ConnectionHandler"/> type.</typeparam>
/// <param name="path">The request path.</param>
/// <param name="configureOptions">A callback to configure dispatcher options.</param>
public void MapConnectionHandler<TConnectionHandler>(PathString path, Action<HttpConnectionDispatcherOptions> configureOptions) where TConnectionHandler : ConnectionHandler
{
var authorizeAttributes = typeof(TConnectionHandler).GetCustomAttributes<AuthorizeAttribute>(inherit: true);

View File

@ -6,12 +6,18 @@ using Microsoft.AspNetCore.Authorization;
namespace Microsoft.AspNetCore.Http.Connections
{
/// <summary>
/// Options used to configure the HTTP connection dispatcher.
/// </summary>
public class HttpConnectionDispatcherOptions
{
// Selected because this is the default value of PipeWriter.PauseWriterThreshold.
// There maybe the opportunity for performance gains by tuning this default.
private const int DefaultPipeBufferSize = 32768;
/// <summary>
/// Initializes a new instance of the <see cref="HttpConnectionDispatcherOptions"/> class.
/// </summary>
public HttpConnectionDispatcherOptions()
{
AuthorizationData = new List<IAuthorizeData>();
@ -22,16 +28,34 @@ namespace Microsoft.AspNetCore.Http.Connections
ApplicationMaxBufferSize = DefaultPipeBufferSize;
}
/// <summary>
/// Gets a collection of <see cref="IAuthorizeData"/> used during HTTP connection pipeline.
/// </summary>
public IList<IAuthorizeData> AuthorizationData { get; }
/// <summary>
/// Gets or sets a bitmask comprised of one or more <see cref="HttpTransportType"/> that specify what transports the server should use to receive HTTP requests.
/// </summary>
public HttpTransportType Transports { get; set; }
/// <summary>
/// Gets the <see cref="WebSocketOptions"/> used by the web sockets transport.
/// </summary>
public WebSocketOptions WebSockets { get; }
/// <summary>
/// Gets the <see cref="LongPollingOptions"/> used by the long polling transport.
/// </summary>
public LongPollingOptions LongPolling { get; }
/// <summary>
/// Gets or sets the maximum buffer size of the transport writer.
/// </summary>
public long TransportMaxBufferSize { get; set; }
/// <summary>
/// Gets or sets the maximum buffer size of the application writer.
/// </summary>
public long ApplicationMaxBufferSize { get; set; }
}
}

View File

@ -2,8 +2,14 @@ using System;
namespace Microsoft.AspNetCore.Http.Connections
{
/// <summary>
/// Options used to configure the long polling transport.
/// </summary>
public class LongPollingOptions
{
/// <summary>
/// Gets or sets the poll timeout.
/// </summary>
public TimeSpan PollTimeout { get; set; } = TimeSpan.FromSeconds(90);
}
}

View File

@ -20,6 +20,14 @@ using Microsoft.Extensions.Logging.Abstractions;
namespace Microsoft.AspNetCore.SignalR.Client
{
/// <summary>
/// A connection used to invoke hub methods on a SignalR Server.
/// </summary>
/// <remarks>
/// A <see cref="HubConnection"/> should be created using <see cref="HubConnectionBuilder"/>.
/// Before hub methods can be invoked the connection must be started using <see cref="StartAsync"/>.
/// Clean up a connection using <see cref="StopAsync"/> or <see cref="DisposeAsync"/>.
/// </remarks>
public partial class HubConnection
{
public static readonly TimeSpan DefaultServerTimeout = TimeSpan.FromSeconds(30); // Server ping rate is 15 sec, this is 2 times that.
@ -49,12 +57,28 @@ namespace Microsoft.AspNetCore.SignalR.Client
public TimeSpan ServerTimeout { get; set; } = DefaultServerTimeout;
public TimeSpan HandshakeTimeout { get; set; } = DefaultHandshakeTimeout;
/// <summary>
/// Initializes a new instance of the <see cref="HubConnection"/> class.
/// </summary>
/// <param name="connectionFactory">The <see cref="IConnectionFactory" /> used to create a connection each time <see cref="StartAsync" /> is called.</param>
/// <param name="protocol">The <see cref="IHubProtocol" /> used by the connection.</param>
/// <param name="serviceProvider">An <see cref="IServiceProvider"/> containing the services provided to this <see cref="HubConnection"/> instance.</param>
/// <param name="loggerFactory">The logger factory.</param>
/// <remarks>
/// The <see cref="IServiceProvider"/> used to initialize the connection will be disposed when the connection is disposed.
/// </remarks>
public HubConnection(IConnectionFactory connectionFactory, IHubProtocol protocol, IServiceProvider serviceProvider, ILoggerFactory loggerFactory)
: this(connectionFactory, protocol, loggerFactory)
{
_serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
}
/// <summary>
/// Initializes a new instance of the <see cref="HubConnection"/> class.
/// </summary>
/// <param name="connectionFactory">The <see cref="IConnectionFactory" /> used to create a connection each time <see cref="StartAsync" /> is called.</param>
/// <param name="protocol">The <see cref="IHubProtocol" /> used by the connection.</param>
/// <param name="loggerFactory">The logger factory.</param>
public HubConnection(IConnectionFactory connectionFactory, IHubProtocol protocol, ILoggerFactory loggerFactory)
{
_connectionFactory = connectionFactory ?? throw new ArgumentNullException(nameof(connectionFactory));
@ -64,12 +88,22 @@ namespace Microsoft.AspNetCore.SignalR.Client
_logger = _loggerFactory.CreateLogger<HubConnection>();
}
/// <summary>
/// Starts a connection to the server.
/// </summary>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous start.</returns>
public async Task StartAsync(CancellationToken cancellationToken = default)
{
CheckDisposed();
await StartAsyncCore(cancellationToken).ForceAsync();
}
/// <summary>
/// Stops a connection to the server.
/// </summary>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous stop.</returns>
public async Task StopAsync(CancellationToken cancellationToken = default)
{
CheckDisposed();
@ -78,6 +112,10 @@ namespace Microsoft.AspNetCore.SignalR.Client
// Current plan for IAsyncDisposable is that DisposeAsync will NOT take a CancellationToken
// https://github.com/dotnet/csharplang/blob/195efa07806284d7b57550e7447dc8bd39c156bf/proposals/async-streams.md#iasyncdisposable
/// <summary>
/// Disposes the <see cref="HubConnection"/>.
/// </summary>
/// <returns>A <see cref="Task"/> that represents the asynchronous dispose.</returns>
public async Task DisposeAsync()
{
if (!_disposed)
@ -87,6 +125,17 @@ namespace Microsoft.AspNetCore.SignalR.Client
}
// If the registered callback blocks it can cause the client to stop receiving messages. If you need to block, get off the current thread first.
/// <summary>
/// Registers a handler that will be invoked when the hub method with the specified method name is invoked.
/// </summary>
/// <param name="methodName">The name of the hub method to define.</param>
/// <param name="parameterTypes">The parameters types expected by the hub method.</param>
/// <param name="handler">The handler that will be raised when the hub method is invoked.</param>
/// <param name="state">A state object that will be passed to the handler.</param>
/// <returns>A subscription that can be disposed to unsubscribe from the hub method.</returns>
/// <remarks>
/// This is a low level method for registering a handler. Using an <see cref="HubConnectionExtensions"/> <c>On</c> extension method is recommended.
/// </remarks>
public IDisposable On(string methodName, Type[] parameterTypes, Func<object[], object, Task> handler, object state)
{
Log.RegisteringHandler(_logger, methodName);
@ -108,14 +157,51 @@ namespace Microsoft.AspNetCore.SignalR.Client
return new Subscription(invocationHandler, invocationList);
}
/// <summary>
/// Invokes a streaming hub method on the server using the specified method name, return type and arguments.
/// </summary>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="returnType">The return type of the server method.</param>
/// <param name="args">The arguments used to invoke the server method.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the asynchronous invoke.
/// The <see cref="Task{TResult}.Result"/> property returns a <see cref="ChannelReader{T}"/> for the streamed hub method values.
/// </returns>
/// <remarks>
/// This is a low level method for invoking a streaming hub method on the server. Using an <see cref="HubConnectionExtensions"/> <c>StreamAsChannelAsync</c> extension method is recommended.
/// </remarks>
public async Task<ChannelReader<object>> StreamAsChannelCoreAsync(string methodName, Type returnType, object[] args, CancellationToken cancellationToken = default) =>
await StreamAsChannelCoreAsyncCore(methodName, returnType, args, cancellationToken).ForceAsync();
/// <summary>
/// Invokes a hub method on the server using the specified method name, return type and arguments.
/// </summary>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="returnType">The return type of the server method.</param>
/// <param name="args">The arguments used to invoke the server method.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the asynchronous invoke.
/// The <see cref="Task{TResult}.Result"/> property returns an <see cref="object"/> for the hub method return value.
/// </returns>
/// <remarks>
/// This is a low level method for invoking a hub method on the server. Using an <see cref="HubConnectionExtensions"/> <c>InvokeAsync</c> extension method is recommended.
/// </remarks>
public async Task<object> InvokeCoreAsync(string methodName, Type returnType, object[] args, CancellationToken cancellationToken = default) =>
await InvokeCoreAsyncCore(methodName, returnType, args, cancellationToken).ForceAsync();
// REVIEW: We don't generally use cancellation tokens when writing to a pipe because the asynchrony is only the result of backpressure.
// However, this would be the only "invocation" method _without_ a cancellation token... which is odd.
/// <summary>
/// Invokes a hub method on the server using the specified method name and arguments.
/// Does not wait for a response from the receiver.
/// </summary>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="args">The arguments used to invoke the server method.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous invoke.</returns>
/// <remarks>
/// This is a low level method for invoking a hub method on the server. Using an <see cref="HubConnectionExtensions"/> <c>SendAsync</c> extension method is recommended.
/// </remarks>
public async Task SendCoreAsync(string methodName, object[] args, CancellationToken cancellationToken = default) =>
await SendCoreAsyncCore(methodName, args, cancellationToken).ForceAsync();

View File

@ -7,12 +7,19 @@ using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.AspNetCore.SignalR.Client
{
/// <summary>
/// A builder for configuring <see cref="HubConnection"/> instances.
/// </summary>
public class HubConnectionBuilder : IHubConnectionBuilder
{
private bool _hubConnectionBuilt;
/// <inheritdoc />
public IServiceCollection Services { get; }
/// <summary>
/// Initializes a new instance of the <see cref="HubConnectionBuilder"/> class.
/// </summary>
public HubConnectionBuilder()
{
Services = new ServiceCollection();
@ -21,6 +28,7 @@ namespace Microsoft.AspNetCore.SignalR.Client
this.AddJsonProtocol();
}
/// <inheritdoc />
public HubConnection Build()
{
// Build can only be used once
@ -44,6 +52,7 @@ namespace Microsoft.AspNetCore.SignalR.Client
}
// Prevents from being displayed in intellisense
/// <inheritdoc />
[EditorBrowsable(EditorBrowsableState.Never)]
public override int GetHashCode()
{
@ -51,6 +60,7 @@ namespace Microsoft.AspNetCore.SignalR.Client
}
// Prevents from being displayed in intellisense
/// <inheritdoc />
[EditorBrowsable(EditorBrowsableState.Never)]
public override bool Equals(object obj)
{
@ -58,6 +68,7 @@ namespace Microsoft.AspNetCore.SignalR.Client
}
// Prevents from being displayed in intellisense
/// <inheritdoc />
[EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString()
{

View File

@ -7,8 +7,17 @@ using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.SignalR.Client
{
/// <summary>
/// Extension methods for <see cref="IHubConnectionBuilder"/>.
/// </summary>
public static class HubConnectionBuilderExtensions
{
/// <summary>
/// Adds a delegate for configuring the provided <see cref="ILoggingBuilder"/>. This may be called multiple times.
/// </summary>
/// <param name="hubConnectionBuilder">The <see cref="IHubConnectionBuilder" /> to configure.</param>
/// <param name="configureLogging">The delegate that configures the <see cref="ILoggingBuilder"/>.</param>
/// <returns>The same instance of the <see cref="IHubConnectionBuilder"/> for chaining.</returns>
public static IHubConnectionBuilder ConfigureLogging(this IHubConnectionBuilder hubConnectionBuilder, Action<ILoggingBuilder> configureLogging)
{
hubConnectionBuilder.Services.AddLogging(configureLogging);

View File

@ -7,63 +7,206 @@ using System.Threading.Tasks;
namespace Microsoft.AspNetCore.SignalR.Client
{
/// <summary>
/// Extension methods for <see cref="HubConnectionExtensions"/>.
/// </summary>
public partial class HubConnectionExtensions
{
/// <summary>
/// Invokes a hub method on the server using the specified method name.
/// </summary>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task{TResult}"/> that represents the asynchronous invoke.</returns>
public static Task InvokeAsync(this HubConnection hubConnection, string methodName, CancellationToken cancellationToken = default)
{
return hubConnection.InvokeCoreAsync(methodName, Array.Empty<object>(), cancellationToken);
}
/// <summary>
/// Invokes a hub method on the server using the specified method name and argument.
/// </summary>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous invoke.</returns>
public static Task InvokeAsync(this HubConnection hubConnection, string methodName, object arg1, CancellationToken cancellationToken = default)
{
return hubConnection.InvokeCoreAsync(methodName, new[] { arg1 }, cancellationToken);
}
/// <summary>
/// Invokes a hub method on the server using the specified method name and arguments.
/// </summary>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous invoke.</returns>
public static Task InvokeAsync(this HubConnection hubConnection, string methodName, object arg1, object arg2, CancellationToken cancellationToken = default)
{
return hubConnection.InvokeCoreAsync(methodName, new[] { arg1, arg2 }, cancellationToken);
}
/// <summary>
/// Invokes a hub method on the server using the specified method name and arguments.
/// </summary>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous invoke.</returns>
public static Task InvokeAsync(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, CancellationToken cancellationToken = default)
{
return hubConnection.InvokeCoreAsync(methodName, new[] { arg1, arg2, arg3 }, cancellationToken);
}
/// <summary>
/// Invokes a hub method on the server using the specified method name and arguments.
/// </summary>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous invoke.</returns>
public static Task InvokeAsync(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, CancellationToken cancellationToken = default)
{
return hubConnection.InvokeCoreAsync(methodName, new[] { arg1, arg2, arg3, arg4 }, cancellationToken);
}
/// <summary>
/// Invokes a hub method on the server using the specified method name and arguments.
/// </summary>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous invoke.</returns>
public static Task InvokeAsync(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, CancellationToken cancellationToken = default)
{
return hubConnection.InvokeCoreAsync(methodName, new[] { arg1, arg2, arg3, arg4, arg5 }, cancellationToken);
}
/// <summary>
/// Invokes a hub method on the server using the specified method name and arguments.
/// </summary>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
/// <param name="arg6">The sixth argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous invoke.</returns>
public static Task InvokeAsync(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, CancellationToken cancellationToken = default)
{
return hubConnection.InvokeCoreAsync(methodName, new[] { arg1, arg2, arg3, arg4, arg5, arg6 }, cancellationToken);
}
/// <summary>
/// Invokes a hub method on the server using the specified method name and arguments.
/// </summary>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
/// <param name="arg6">The sixth argument.</param>
/// <param name="arg7">The seventh argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous invoke.</returns>
public static Task InvokeAsync(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, CancellationToken cancellationToken = default)
{
return hubConnection.InvokeCoreAsync(methodName, new[] { arg1, arg2, arg3, arg4, arg5, arg6, arg7 }, cancellationToken);
}
/// <summary>
/// Invokes a hub method on the server using the specified method name and arguments.
/// </summary>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
/// <param name="arg6">The sixth argument.</param>
/// <param name="arg7">The seventh argument.</param>
/// <param name="arg8">The eighth argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous invoke.</returns>
public static Task InvokeAsync(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, CancellationToken cancellationToken = default)
{
return hubConnection.InvokeCoreAsync(methodName, new[] { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 }, cancellationToken);
}
/// <summary>
/// Invokes a hub method on the server using the specified method name and arguments.
/// </summary>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
/// <param name="arg6">The sixth argument.</param>
/// <param name="arg7">The seventh argument.</param>
/// <param name="arg8">The eighth argument.</param>
/// <param name="arg9">The ninth argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous invoke.</returns>
public static Task InvokeAsync(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, object arg9, CancellationToken cancellationToken = default)
{
return hubConnection.InvokeCoreAsync(methodName, new[] { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 }, cancellationToken);
}
/// <summary>
/// Invokes a hub method on the server using the specified method name and arguments.
/// </summary>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
/// <param name="arg6">The sixth argument.</param>
/// <param name="arg7">The seventh argument.</param>
/// <param name="arg8">The eighth argument.</param>
/// <param name="arg9">The ninth argument.</param>
/// <param name="arg10">The tenth argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous invoke.</returns>
public static Task InvokeAsync(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, object arg9, object arg10, CancellationToken cancellationToken = default)
{
return hubConnection.InvokeCoreAsync(methodName, new[] { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 }, cancellationToken);
}
/// <summary>
/// Invokes a hub method on the server using the specified method name and arguments.
/// </summary>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="args">The arguments used to invoke the server method.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous invoke.</returns>
public static Task InvokeCoreAsync(this HubConnection hubConnection, string methodName, object[] args, CancellationToken cancellationToken = default)
{
if (hubConnection == null)

View File

@ -7,63 +7,254 @@ using System.Threading.Tasks;
namespace Microsoft.AspNetCore.SignalR.Client
{
/// <summary>
/// Extension methods for <see cref="HubConnectionExtensions"/>.
/// </summary>
public static partial class HubConnectionExtensions
{
/// <summary>
/// Invokes a hub method on the server using the specified method name.
/// </summary>
/// <typeparam name="TResult">The return type of the server method.</typeparam>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the asynchronous invoke.
/// The <see cref="Task{TResult}.Result"/> property returns a <typeparamref name="TResult"/> for the hub method return value.
/// </returns>
public static Task<TResult> InvokeAsync<TResult>(this HubConnection hubConnection, string methodName, CancellationToken cancellationToken = default)
{
return hubConnection.InvokeCoreAsync<TResult>(methodName, Array.Empty<object>(), cancellationToken);
}
/// <summary>
/// Invokes a hub method on the server using the specified method name and argument.
/// </summary>
/// <typeparam name="TResult">The return type of the server method.</typeparam>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the asynchronous invoke.
/// The <see cref="Task{TResult}.Result"/> property returns a <typeparamref name="TResult"/> for the hub method return value.
/// </returns>
public static Task<TResult> InvokeAsync<TResult>(this HubConnection hubConnection, string methodName, object arg1, CancellationToken cancellationToken = default)
{
return hubConnection.InvokeCoreAsync<TResult>(methodName, new[] { arg1 }, cancellationToken);
}
/// <summary>
/// Invokes a hub method on the server using the specified method name and arguments.
/// </summary>
/// <typeparam name="TResult">The return type of the server method.</typeparam>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the asynchronous invoke.
/// The <see cref="Task{TResult}.Result"/> property returns a <typeparamref name="TResult"/> for the hub method return value.
/// </returns>
public static Task<TResult> InvokeAsync<TResult>(this HubConnection hubConnection, string methodName, object arg1, object arg2, CancellationToken cancellationToken = default)
{
return hubConnection.InvokeCoreAsync<TResult>(methodName, new[] { arg1, arg2 }, cancellationToken);
}
/// <summary>
/// Invokes a hub method on the server using the specified method name and arguments.
/// </summary>
/// <typeparam name="TResult">The return type of the server method.</typeparam>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the asynchronous invoke.
/// The <see cref="Task{TResult}.Result"/> property returns a <typeparamref name="TResult"/> for the hub method return value.
/// </returns>
public static Task<TResult> InvokeAsync<TResult>(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, CancellationToken cancellationToken = default)
{
return hubConnection.InvokeCoreAsync<TResult>(methodName, new[] { arg1, arg2, arg3 }, cancellationToken);
}
/// <summary>
/// Invokes a hub method on the server using the specified method name and arguments.
/// </summary>
/// <typeparam name="TResult">The return type of the server method.</typeparam>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the asynchronous invoke.
/// The <see cref="Task{TResult}.Result"/> property returns a <typeparamref name="TResult"/> for the hub method return value.
/// </returns>
public static Task<TResult> InvokeAsync<TResult>(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, CancellationToken cancellationToken = default)
{
return hubConnection.InvokeCoreAsync<TResult>(methodName, new[] { arg1, arg2, arg3, arg4 }, cancellationToken);
}
/// <summary>
/// Invokes a hub method on the server using the specified method name and arguments.
/// </summary>
/// <typeparam name="TResult">The return type of the server method.</typeparam>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the asynchronous invoke.
/// The <see cref="Task{TResult}.Result"/> property returns a <typeparamref name="TResult"/> for the hub method return value.
/// </returns>
public static Task<TResult> InvokeAsync<TResult>(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, CancellationToken cancellationToken = default)
{
return hubConnection.InvokeCoreAsync<TResult>(methodName, new[] { arg1, arg2, arg3, arg4, arg5 }, cancellationToken);
}
/// <summary>
/// Invokes a hub method on the server using the specified method name and arguments.
/// </summary>
/// <typeparam name="TResult">The return type of the server method.</typeparam>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
/// <param name="arg6">The sixth argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the asynchronous invoke.
/// The <see cref="Task{TResult}.Result"/> property returns a <typeparamref name="TResult"/> for the hub method return value.
/// </returns>
public static Task<TResult> InvokeAsync<TResult>(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, CancellationToken cancellationToken = default)
{
return hubConnection.InvokeCoreAsync<TResult>(methodName, new[] { arg1, arg2, arg3, arg4, arg5, arg6 }, cancellationToken);
}
/// <summary>
/// Invokes a hub method on the server using the specified method name and arguments.
/// </summary>
/// <typeparam name="TResult">The return type of the server method.</typeparam>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
/// <param name="arg6">The sixth argument.</param>
/// <param name="arg7">The seventh argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the asynchronous invoke.
/// The <see cref="Task{TResult}.Result"/> property returns a <typeparamref name="TResult"/> for the hub method return value.
/// </returns>
public static Task<TResult> InvokeAsync<TResult>(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, CancellationToken cancellationToken = default)
{
return hubConnection.InvokeCoreAsync<TResult>(methodName, new[] { arg1, arg2, arg3, arg4, arg5, arg6, arg7 }, cancellationToken);
}
/// <summary>
/// Invokes a hub method on the server using the specified method name and arguments.
/// </summary>
/// <typeparam name="TResult">The return type of the server method.</typeparam>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
/// <param name="arg6">The sixth argument.</param>
/// <param name="arg7">The seventh argument.</param>
/// <param name="arg8">The eighth argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the asynchronous invoke.
/// The <see cref="Task{TResult}.Result"/> property returns a <typeparamref name="TResult"/> for the hub method return value.
/// </returns>
public static Task<TResult> InvokeAsync<TResult>(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, CancellationToken cancellationToken = default)
{
return hubConnection.InvokeCoreAsync<TResult>(methodName, new[] { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 }, cancellationToken);
}
/// <summary>
/// Invokes a hub method on the server using the specified method name and arguments.
/// </summary>
/// <typeparam name="TResult">The return type of the server method.</typeparam>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
/// <param name="arg6">The sixth argument.</param>
/// <param name="arg7">The seventh argument.</param>
/// <param name="arg8">The eighth argument.</param>
/// <param name="arg9">The ninth argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the asynchronous invoke.
/// The <see cref="Task{TResult}.Result"/> property returns a <typeparamref name="TResult"/> for the hub method return value.
/// </returns>
public static Task<TResult> InvokeAsync<TResult>(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, object arg9, CancellationToken cancellationToken = default)
{
return hubConnection.InvokeCoreAsync<TResult>(methodName, new[] { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 }, cancellationToken);
}
/// <summary>
/// Invokes a hub method on the server using the specified method name and arguments.
/// </summary>
/// <typeparam name="TResult">The return type of the server method.</typeparam>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
/// <param name="arg6">The sixth argument.</param>
/// <param name="arg7">The seventh argument.</param>
/// <param name="arg8">The eighth argument.</param>
/// <param name="arg9">The ninth argument.</param>
/// <param name="arg10">The tenth argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the asynchronous invoke.
/// The <see cref="Task{TResult}.Result"/> property returns a <typeparamref name="TResult"/> for the hub method return value.
/// </returns>
public static Task<TResult> InvokeAsync<TResult>(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, object arg9, object arg10, CancellationToken cancellationToken = default)
{
return hubConnection.InvokeCoreAsync<TResult>(methodName, new[] { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 }, cancellationToken);
}
/// <summary>
/// Invokes a hub method on the server using the specified method name and arguments.
/// </summary>
/// <typeparam name="TResult">The return type of the server method.</typeparam>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="args">The arguments used to invoke the server method.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the asynchronous invoke.
/// The <see cref="Task{TResult}.Result"/> property returns a <typeparamref name="TResult"/> for the hub method return value.
/// </returns>
public static async Task<TResult> InvokeCoreAsync<TResult>(this HubConnection hubConnection, string methodName, object[] args, CancellationToken cancellationToken = default)
{
if (hubConnection == null)

View File

@ -7,58 +7,204 @@ using System.Threading.Tasks;
namespace Microsoft.AspNetCore.SignalR.Client
{
/// <summary>
/// Extension methods for <see cref="HubConnectionExtensions"/>.
/// </summary>
public static partial class HubConnectionExtensions
{
/// <summary>
/// Invokes a hub method on the server using the specified method name.
/// Does not wait for a response from the receiver.
/// </summary>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task{TResult}"/> that represents the asynchronous invoke.</returns>
public static Task SendAsync(this HubConnection hubConnection, string methodName, CancellationToken cancellationToken = default)
{
return hubConnection.SendCoreAsync(methodName, Array.Empty<object>(), cancellationToken);
}
/// <summary>
/// Invokes a hub method on the server using the specified method name and argument.
/// Does not wait for a response from the receiver.
/// </summary>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task{TResult}"/> that represents the asynchronous invoke.</returns>
public static Task SendAsync(this HubConnection hubConnection, string methodName, object arg1, CancellationToken cancellationToken = default)
{
return hubConnection.SendCoreAsync(methodName, new[] { arg1 }, cancellationToken);
}
/// <summary>
/// Invokes a hub method on the server using the specified method name and arguments.
/// Does not wait for a response from the receiver.
/// </summary>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task{TResult}"/> that represents the asynchronous invoke.</returns>
public static Task SendAsync(this HubConnection hubConnection, string methodName, object arg1, object arg2, CancellationToken cancellationToken = default)
{
return hubConnection.SendCoreAsync(methodName, new[] { arg1, arg2 }, cancellationToken);
}
/// <summary>
/// Invokes a hub method on the server using the specified method name and arguments.
/// Does not wait for a response from the receiver.
/// </summary>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task{TResult}"/> that represents the asynchronous invoke.</returns>
public static Task SendAsync(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, CancellationToken cancellationToken = default)
{
return hubConnection.SendCoreAsync(methodName, new[] { arg1, arg2, arg3 }, cancellationToken);
}
/// <summary>
/// Invokes a hub method on the server using the specified method name and arguments.
/// Does not wait for a response from the receiver.
/// </summary>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task{TResult}"/> that represents the asynchronous invoke.</returns>
public static Task SendAsync(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, CancellationToken cancellationToken = default)
{
return hubConnection.SendCoreAsync(methodName, new[] { arg1, arg2, arg3, arg4 }, cancellationToken);
}
/// <summary>
/// Invokes a hub method on the server using the specified method name and arguments.
/// Does not wait for a response from the receiver.
/// </summary>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task{TResult}"/> that represents the asynchronous invoke.</returns>
public static Task SendAsync(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, CancellationToken cancellationToken = default)
{
return hubConnection.SendCoreAsync(methodName, new[] { arg1, arg2, arg3, arg4, arg5 }, cancellationToken);
}
/// <summary>
/// Invokes a hub method on the server using the specified method name and arguments.
/// Does not wait for a response from the receiver.
/// </summary>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
/// <param name="arg6">The sixth argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task{TResult}"/> that represents the asynchronous invoke.</returns>
public static Task SendAsync(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, CancellationToken cancellationToken = default)
{
return hubConnection.SendCoreAsync(methodName, new[] { arg1, arg2, arg3, arg4, arg5, arg6 }, cancellationToken);
}
/// <summary>
/// Invokes a hub method on the server using the specified method name and arguments.
/// Does not wait for a response from the receiver.
/// </summary>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
/// <param name="arg6">The sixth argument.</param>
/// <param name="arg7">The seventh argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task{TResult}"/> that represents the asynchronous invoke.</returns>
public static Task SendAsync(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, CancellationToken cancellationToken = default)
{
return hubConnection.SendCoreAsync(methodName, new[] { arg1, arg2, arg3, arg4, arg5, arg6, arg7 }, cancellationToken);
}
/// <summary>
/// Invokes a hub method on the server using the specified method name and arguments.
/// Does not wait for a response from the receiver.
/// </summary>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
/// <param name="arg6">The sixth argument.</param>
/// <param name="arg7">The seventh argument.</param>
/// <param name="arg8">The eighth argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task{TResult}"/> that represents the asynchronous invoke.</returns>
public static Task SendAsync(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, CancellationToken cancellationToken = default)
{
return hubConnection.SendCoreAsync(methodName, new[] { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 }, cancellationToken);
}
/// <summary>
/// Invokes a hub method on the server using the specified method name and arguments.
/// Does not wait for a response from the receiver.
/// </summary>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
/// <param name="arg6">The sixth argument.</param>
/// <param name="arg7">The seventh argument.</param>
/// <param name="arg8">The eighth argument.</param>
/// <param name="arg9">The ninth argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task{TResult}"/> that represents the asynchronous invoke.</returns>
public static Task SendAsync(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, object arg9, CancellationToken cancellationToken = default)
{
return hubConnection.SendCoreAsync(methodName, new[] { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 }, cancellationToken);
}
/// <summary>
/// Invokes a hub method on the server using the specified method name and arguments.
/// Does not wait for a response from the receiver.
/// </summary>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
/// <param name="arg6">The sixth argument.</param>
/// <param name="arg7">The seventh argument.</param>
/// <param name="arg8">The eighth argument.</param>
/// <param name="arg9">The ninth argument.</param>
/// <param name="arg10">The tenth argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task{TResult}"/> that represents the asynchronous invoke.</returns>
public static Task SendAsync(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, object arg9, object arg10, CancellationToken cancellationToken = default)
{
return hubConnection.SendCoreAsync(methodName, new[] { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 }, cancellationToken);

View File

@ -8,63 +8,254 @@ using System.Threading.Channels;
namespace Microsoft.AspNetCore.SignalR.Client
{
/// <summary>
/// Extension methods for <see cref="HubConnectionExtensions"/>.
/// </summary>
public static partial class HubConnectionExtensions
{
/// <summary>
/// Invokes a streaming hub method on the server using the specified method name and return type.
/// </summary>
/// <typeparam name="TResult">The return type of the streaming server method.</typeparam>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the asynchronous invoke.
/// The <see cref="Task{TResult}.Result"/> property returns a <see cref="ChannelReader{T}"/> for the streamed hub method values.
/// </returns>
public static Task<ChannelReader<TResult>> StreamAsChannelAsync<TResult>(this HubConnection hubConnection, string methodName, CancellationToken cancellationToken = default)
{
return hubConnection.StreamAsChannelCoreAsync<TResult>(methodName, Array.Empty<object>(), cancellationToken);
}
/// <summary>
/// Invokes a streaming hub method on the server using the specified method name, return type and argument.
/// </summary>
/// <typeparam name="TResult">The return type of the streaming server method.</typeparam>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the asynchronous invoke.
/// The <see cref="Task{TResult}.Result"/> property returns a <see cref="ChannelReader{T}"/> for the streamed hub method values.
/// </returns>
public static Task<ChannelReader<TResult>> StreamAsChannelAsync<TResult>(this HubConnection hubConnection, string methodName, object arg1, CancellationToken cancellationToken = default)
{
return hubConnection.StreamAsChannelCoreAsync<TResult>(methodName, new[] { arg1 }, cancellationToken);
}
/// <summary>
/// Invokes a streaming hub method on the server using the specified method name, return type and arguments.
/// </summary>
/// <typeparam name="TResult">The return type of the streaming server method.</typeparam>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the asynchronous invoke.
/// The <see cref="Task{TResult}.Result"/> property returns a <see cref="ChannelReader{T}"/> for the streamed hub method values.
/// </returns>
public static Task<ChannelReader<TResult>> StreamAsChannelAsync<TResult>(this HubConnection hubConnection, string methodName, object arg1, object arg2, CancellationToken cancellationToken = default)
{
return hubConnection.StreamAsChannelCoreAsync<TResult>(methodName, new[] { arg1, arg2 }, cancellationToken);
}
/// <summary>
/// Invokes a streaming hub method on the server using the specified method name, return type and arguments.
/// </summary>
/// <typeparam name="TResult">The return type of the streaming server method.</typeparam>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the asynchronous invoke.
/// The <see cref="Task{TResult}.Result"/> property returns a <see cref="ChannelReader{T}"/> for the streamed hub method values.
/// </returns>
public static Task<ChannelReader<TResult>> StreamAsChannelAsync<TResult>(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, CancellationToken cancellationToken = default)
{
return hubConnection.StreamAsChannelCoreAsync<TResult>(methodName, new[] { arg1, arg2, arg3 }, cancellationToken);
}
/// <summary>
/// Invokes a streaming hub method on the server using the specified method name, return type and arguments.
/// </summary>
/// <typeparam name="TResult">The return type of the streaming server method.</typeparam>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the asynchronous invoke.
/// The <see cref="Task{TResult}.Result"/> property returns a <see cref="ChannelReader{T}"/> for the streamed hub method values.
/// </returns>
public static Task<ChannelReader<TResult>> StreamAsChannelAsync<TResult>(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, CancellationToken cancellationToken = default)
{
return hubConnection.StreamAsChannelCoreAsync<TResult>(methodName, new[] { arg1, arg2, arg3, arg4 }, cancellationToken);
}
/// <summary>
/// Invokes a streaming hub method on the server using the specified method name, return type and arguments.
/// </summary>
/// <typeparam name="TResult">The return type of the streaming server method.</typeparam>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the asynchronous invoke.
/// The <see cref="Task{TResult}.Result"/> property returns a <see cref="ChannelReader{T}"/> for the streamed hub method values.
/// </returns>
public static Task<ChannelReader<TResult>> StreamAsChannelAsync<TResult>(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, CancellationToken cancellationToken = default)
{
return hubConnection.StreamAsChannelCoreAsync<TResult>(methodName, new[] { arg1, arg2, arg3, arg4, arg5 }, cancellationToken);
}
/// <summary>
/// Invokes a streaming hub method on the server using the specified method name, return type and arguments.
/// </summary>
/// <typeparam name="TResult">The return type of the streaming server method.</typeparam>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
/// <param name="arg6">The sixth argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the asynchronous invoke.
/// The <see cref="Task{TResult}.Result"/> property returns a <see cref="ChannelReader{T}"/> for the streamed hub method values.
/// </returns>
public static Task<ChannelReader<TResult>> StreamAsChannelAsync<TResult>(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, CancellationToken cancellationToken = default)
{
return hubConnection.StreamAsChannelCoreAsync<TResult>(methodName, new[] { arg1, arg2, arg3, arg4, arg5, arg6 }, cancellationToken);
}
/// <summary>
/// Invokes a streaming hub method on the server using the specified method name, return type and arguments.
/// </summary>
/// <typeparam name="TResult">The return type of the streaming server method.</typeparam>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
/// <param name="arg6">The sixth argument.</param>
/// <param name="arg7">The seventh argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the asynchronous invoke.
/// The <see cref="Task{TResult}.Result"/> property returns a <see cref="ChannelReader{T}"/> for the streamed hub method values.
/// </returns>
public static Task<ChannelReader<TResult>> StreamAsChannelAsync<TResult>(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, CancellationToken cancellationToken = default)
{
return hubConnection.StreamAsChannelCoreAsync<TResult>(methodName, new[] { arg1, arg2, arg3, arg4, arg5, arg6, arg7 }, cancellationToken);
}
/// <summary>
/// Invokes a streaming hub method on the server using the specified method name, return type and arguments.
/// </summary>
/// <typeparam name="TResult">The return type of the streaming server method.</typeparam>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
/// <param name="arg6">The sixth argument.</param>
/// <param name="arg7">The seventh argument.</param>
/// <param name="arg8">The eighth argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the asynchronous invoke.
/// The <see cref="Task{TResult}.Result"/> property returns a <see cref="ChannelReader{T}"/> for the streamed hub method values.
/// </returns>
public static Task<ChannelReader<TResult>> StreamAsChannelAsync<TResult>(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, CancellationToken cancellationToken = default)
{
return hubConnection.StreamAsChannelCoreAsync<TResult>(methodName, new[] { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 }, cancellationToken);
}
/// <summary>
/// Invokes a streaming hub method on the server using the specified method name, return type and arguments.
/// </summary>
/// <typeparam name="TResult">The return type of the streaming server method.</typeparam>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
/// <param name="arg6">The sixth argument.</param>
/// <param name="arg7">The seventh argument.</param>
/// <param name="arg8">The eighth argument.</param>
/// <param name="arg9">The ninth argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the asynchronous invoke.
/// The <see cref="Task{TResult}.Result"/> property returns a <see cref="ChannelReader{T}"/> for the streamed hub method values.
/// </returns>
public static Task<ChannelReader<TResult>> StreamAsChannelAsync<TResult>(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, object arg9, CancellationToken cancellationToken = default)
{
return hubConnection.StreamAsChannelCoreAsync<TResult>(methodName, new[] { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 }, cancellationToken);
}
/// <summary>
/// Invokes a streaming hub method on the server using the specified method name, return type and arguments.
/// </summary>
/// <typeparam name="TResult">The return type of the streaming server method.</typeparam>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
/// <param name="arg6">The sixth argument.</param>
/// <param name="arg7">The seventh argument.</param>
/// <param name="arg8">The eighth argument.</param>
/// <param name="arg9">The ninth argument.</param>
/// <param name="arg10">The tenth argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the asynchronous invoke.
/// The <see cref="Task{TResult}.Result"/> property returns a <see cref="ChannelReader{T}"/> for the streamed hub method values.
/// </returns>
public static Task<ChannelReader<TResult>> StreamAsChannelAsync<TResult>(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, object arg9, object arg10, CancellationToken cancellationToken = default)
{
return hubConnection.StreamAsChannelCoreAsync<TResult>(methodName, new[] { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 }, cancellationToken);
}
/// <summary>
/// Invokes a streaming hub method on the server using the specified method name, return type and arguments.
/// </summary>
/// <typeparam name="TResult">The return type of the streaming server method.</typeparam>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the server method to invoke.</param>
/// <param name="args">The arguments used to invoke the server method.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the asynchronous invoke.
/// The <see cref="Task{TResult}.Result"/> property returns a <see cref="ChannelReader{T}"/> for the streamed hub method values.
/// </returns>
public static async Task<ChannelReader<TResult>> StreamAsChannelCoreAsync<TResult>(this HubConnection hubConnection, string methodName, object[] args, CancellationToken cancellationToken = default)
{
if (hubConnection == null)

View File

@ -6,6 +6,9 @@ using System.Threading.Tasks;
namespace Microsoft.AspNetCore.SignalR.Client
{
/// <summary>
/// Extension methods for <see cref="HubConnectionExtensions"/>.
/// </summary>
public static partial class HubConnectionExtensions
{
private static IDisposable On(this HubConnection hubConnetion, string methodName, Type[] parameterTypes, Action<object[]> handler)
@ -18,6 +21,13 @@ namespace Microsoft.AspNetCore.SignalR.Client
}, handler);
}
/// <summary>
/// Registers a handler that will be invoked when the hub method with the specified method name is invoked.
/// </summary>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the hub method to define.</param>
/// <param name="handler">The handler that will be raised when the hub method is invoked.</param>
/// <returns>A subscription that can be disposed to unsubscribe from the hub method.</returns>
public static IDisposable On(this HubConnection hubConnection, string methodName, Action handler)
{
if (hubConnection == null)
@ -28,6 +38,14 @@ namespace Microsoft.AspNetCore.SignalR.Client
return hubConnection.On(methodName, Type.EmptyTypes, args => handler());
}
/// <summary>
/// Registers a handler that will be invoked when the hub method with the specified method name is invoked.
/// </summary>
/// <typeparam name="T1">The first argument type.</typeparam>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the hub method to define.</param>
/// <param name="handler">The handler that will be raised when the hub method is invoked.</param>
/// <returns>A subscription that can be disposed to unsubscribe from the hub method.</returns>
public static IDisposable On<T1>(this HubConnection hubConnection, string methodName, Action<T1> handler)
{
if (hubConnection == null)
@ -40,6 +58,15 @@ namespace Microsoft.AspNetCore.SignalR.Client
args => handler((T1)args[0]));
}
/// <summary>
/// Registers a handler that will be invoked when the hub method with the specified method name is invoked.
/// </summary>
/// <typeparam name="T1">The first argument type.</typeparam>
/// <typeparam name="T2">The second argument type.</typeparam>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the hub method to define.</param>
/// <param name="handler">The handler that will be raised when the hub method is invoked.</param>
/// <returns>A subscription that can be disposed to unsubscribe from the hub method.</returns>
public static IDisposable On<T1, T2>(this HubConnection hubConnection, string methodName, Action<T1, T2> handler)
{
if (hubConnection == null)
@ -52,6 +79,16 @@ namespace Microsoft.AspNetCore.SignalR.Client
args => handler((T1)args[0], (T2)args[1]));
}
/// <summary>
/// Registers a handler that will be invoked when the hub method with the specified method name is invoked.
/// </summary>
/// <typeparam name="T1">The first argument type.</typeparam>
/// <typeparam name="T2">The second argument type.</typeparam>
/// <typeparam name="T3">The third argument type.</typeparam>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the hub method to define.</param>
/// <param name="handler">The handler that will be raised when the hub method is invoked.</param>
/// <returns>A subscription that can be disposed to unsubscribe from the hub method.</returns>
public static IDisposable On<T1, T2, T3>(this HubConnection hubConnection, string methodName, Action<T1, T2, T3> handler)
{
if (hubConnection == null)
@ -64,6 +101,17 @@ namespace Microsoft.AspNetCore.SignalR.Client
args => handler((T1)args[0], (T2)args[1], (T3)args[2]));
}
/// <summary>
/// Registers a handler that will be invoked when the hub method with the specified method name is invoked.
/// </summary>
/// <typeparam name="T1">The first argument type.</typeparam>
/// <typeparam name="T2">The second argument type.</typeparam>
/// <typeparam name="T3">The third argument type.</typeparam>
/// <typeparam name="T4">The fourth argument type.</typeparam>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the hub method to define.</param>
/// <param name="handler">The handler that will be raised when the hub method is invoked.</param>
/// <returns>A subscription that can be disposed to unsubscribe from the hub method.</returns>
public static IDisposable On<T1, T2, T3, T4>(this HubConnection hubConnection, string methodName, Action<T1, T2, T3, T4> handler)
{
if (hubConnection == null)
@ -76,6 +124,18 @@ namespace Microsoft.AspNetCore.SignalR.Client
args => handler((T1)args[0], (T2)args[1], (T3)args[2], (T4)args[3]));
}
/// <summary>
/// Registers a handler that will be invoked when the hub method with the specified method name is invoked.
/// </summary>
/// <typeparam name="T1">The first argument type.</typeparam>
/// <typeparam name="T2">The second argument type.</typeparam>
/// <typeparam name="T3">The third argument type.</typeparam>
/// <typeparam name="T4">The fourth argument type.</typeparam>
/// <typeparam name="T5">The fifth argument type.</typeparam>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the hub method to define.</param>
/// <param name="handler">The handler that will be raised when the hub method is invoked.</param>
/// <returns>A subscription that can be disposed to unsubscribe from the hub method.</returns>
public static IDisposable On<T1, T2, T3, T4, T5>(this HubConnection hubConnection, string methodName, Action<T1, T2, T3, T4, T5> handler)
{
if (hubConnection == null)
@ -88,6 +148,19 @@ namespace Microsoft.AspNetCore.SignalR.Client
args => handler((T1)args[0], (T2)args[1], (T3)args[2], (T4)args[3], (T5)args[4]));
}
/// <summary>
/// Registers a handler that will be invoked when the hub method with the specified method name is invoked.
/// </summary>
/// <typeparam name="T1">The first argument type.</typeparam>
/// <typeparam name="T2">The second argument type.</typeparam>
/// <typeparam name="T3">The third argument type.</typeparam>
/// <typeparam name="T4">The fourth argument type.</typeparam>
/// <typeparam name="T5">The fifth argument type.</typeparam>
/// <typeparam name="T6">The sixth argument type.</typeparam>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the hub method to define.</param>
/// <param name="handler">The handler that will be raised when the hub method is invoked.</param>
/// <returns>A subscription that can be disposed to unsubscribe from the hub method.</returns>
public static IDisposable On<T1, T2, T3, T4, T5, T6>(this HubConnection hubConnection, string methodName, Action<T1, T2, T3, T4, T5, T6> handler)
{
if (hubConnection == null)
@ -100,6 +173,20 @@ namespace Microsoft.AspNetCore.SignalR.Client
args => handler((T1)args[0], (T2)args[1], (T3)args[2], (T4)args[3], (T5)args[4], (T6)args[5]));
}
/// <summary>
/// Registers a handler that will be invoked when the hub method with the specified method name is invoked.
/// </summary>
/// <typeparam name="T1">The first argument type.</typeparam>
/// <typeparam name="T2">The second argument type.</typeparam>
/// <typeparam name="T3">The third argument type.</typeparam>
/// <typeparam name="T4">The fourth argument type.</typeparam>
/// <typeparam name="T5">The fifth argument type.</typeparam>
/// <typeparam name="T6">The sixth argument type.</typeparam>
/// <typeparam name="T7">The seventh argument type.</typeparam>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the hub method to define.</param>
/// <param name="handler">The handler that will be raised when the hub method is invoked.</param>
/// <returns>A subscription that can be disposed to unsubscribe from the hub method.</returns>
public static IDisposable On<T1, T2, T3, T4, T5, T6, T7>(this HubConnection hubConnection, string methodName, Action<T1, T2, T3, T4, T5, T6, T7> handler)
{
if (hubConnection == null)
@ -112,7 +199,21 @@ namespace Microsoft.AspNetCore.SignalR.Client
args => handler((T1)args[0], (T2)args[1], (T3)args[2], (T4)args[3], (T5)args[4], (T6)args[5], (T7)args[6]));
}
/// <summary>
/// Registers a handler that will be invoked when the hub method with the specified method name is invoked.
/// </summary>
/// <typeparam name="T1">The first argument type.</typeparam>
/// <typeparam name="T2">The second argument type.</typeparam>
/// <typeparam name="T3">The third argument type.</typeparam>
/// <typeparam name="T4">The fourth argument type.</typeparam>
/// <typeparam name="T5">The fifth argument type.</typeparam>
/// <typeparam name="T6">The sixth argument type.</typeparam>
/// <typeparam name="T7">The seventh argument type.</typeparam>
/// <typeparam name="T8">The eighth argument type.</typeparam>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the hub method to define.</param>
/// <param name="handler">The handler that will be raised when the hub method is invoked.</param>
/// <returns>A subscription that can be disposed to unsubscribe from the hub method.</returns>
public static IDisposable On<T1, T2, T3, T4, T5, T6, T7, T8>(this HubConnection hubConnection, string methodName, Action<T1, T2, T3, T4, T5, T6, T7, T8> handler)
{
if (hubConnection == null)
@ -125,6 +226,14 @@ namespace Microsoft.AspNetCore.SignalR.Client
args => handler((T1)args[0], (T2)args[1], (T3)args[2], (T4)args[3], (T5)args[4], (T6)args[5], (T7)args[6], (T8)args[7]));
}
/// <summary>
/// Registers a handler that will be invoked when the hub method with the specified method name is invoked.
/// </summary>
/// <param name="hubConnection">The hub connection.</param>
/// <param name="methodName">The name of the hub method to define.</param>
/// <param name="parameterTypes">The parameters types expected by the hub method.</param>
/// <param name="handler">The handler that will be raised when the hub method is invoked.</param>
/// <returns>A subscription that can be disposed to unsubscribe from the hub method.</returns>
public static IDisposable On(this HubConnection hubConnection, string methodName, Type[] parameterTypes, Func<object[], Task> handler)
{
return hubConnection.On(methodName, parameterTypes, (parameters, state) =>

View File

@ -7,12 +7,29 @@ using Microsoft.AspNetCore.Connections;
namespace Microsoft.AspNetCore.SignalR.Client
{
/// <summary>
/// A factory abstraction for creating connections to a SignalR server.
/// </summary>
public interface IConnectionFactory
{
/// <summary>
/// Creates a new connection to a SignalR server using the specified <see cref="TransferFormat"/>.
/// </summary>
/// <param name="transferFormat">The transfer format the connection should use.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the asynchronous connect.
/// The <see cref="Task{TResult}.Result"/> property returns a <see cref="ConnectionContext"/> for the new connection.
/// </returns>
Task<ConnectionContext> ConnectAsync(TransferFormat transferFormat, CancellationToken cancellationToken = default);
// Current plan for IAsyncDisposable is that DisposeAsync will NOT take a CancellationToken
// https://github.com/dotnet/csharplang/blob/195efa07806284d7b57550e7447dc8bd39c156bf/proposals/async-streams.md#iasyncdisposable
/// <summary>
/// Disposes the specified <see cref="ConnectionContext"/>.
/// </summary>
/// <param name="connection">The connection to dispose.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous dispose.</returns>
Task DisposeAsync(ConnectionContext connection);
}
}
}

View File

@ -3,8 +3,17 @@
namespace Microsoft.AspNetCore.SignalR.Client
{
/// <summary>
/// A builder abstraction for configuring <see cref="HubConnection"/> instances.
/// </summary>
public interface IHubConnectionBuilder : ISignalRBuilder
{
/// <summary>
/// Creates a <see cref="HubConnection"/>.
/// </summary>
/// <returns>
/// A <see cref="HubConnection"/> built using the configured options.
/// </returns>
HubConnection Build();
}
}

View File

@ -11,11 +11,19 @@ using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.SignalR.Client
{
/// <summary>
/// A factory for creating <see cref="HttpConnection"/> instances.
/// </summary>
public class HttpConnectionFactory : IConnectionFactory
{
private readonly HttpConnectionOptions _httpConnectionOptions;
private readonly ILoggerFactory _loggerFactory;
/// <summary>
/// Initializes a new instance of the <see cref="HttpConnectionFactory"/> class.
/// </summary>
/// <param name="options">The connection options.</param>
/// <param name="loggerFactory">The logger factory.</param>
public HttpConnectionFactory(IOptions<HttpConnectionOptions> options, ILoggerFactory loggerFactory)
{
if (options == null)
@ -32,6 +40,7 @@ namespace Microsoft.AspNetCore.SignalR.Client
_loggerFactory = loggerFactory;
}
/// <inheritdoc />
public async Task<ConnectionContext> ConnectAsync(TransferFormat transferFormat, CancellationToken cancellationToken = default)
{
var connection = new HttpConnection(_httpConnectionOptions, _loggerFactory);
@ -48,9 +57,10 @@ namespace Microsoft.AspNetCore.SignalR.Client
}
}
/// <inheritdoc />
public Task DisposeAsync(ConnectionContext connection)
{
return ((HttpConnection)connection).DisposeAsync();
}
}
}
}

View File

@ -8,50 +8,109 @@ using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.AspNetCore.SignalR.Client
{
/// <summary>
/// Extension methods for <see cref="IHubConnectionBuilder"/>.
/// </summary>
public static class HubConnectionBuilderHttpExtensions
{
/// <summary>
/// Configures the <see cref="HubConnection" /> to use HTTP-based transports to connect to the specified URL.
/// </summary>
/// <param name="hubConnectionBuilder">The <see cref="IHubConnectionBuilder" /> to configure.</param>
/// <param name="url">The URL the <see cref="HttpConnection"/> will use.</param>
/// <returns>The same instance of the <see cref="IHubConnectionBuilder"/> for chaining.</returns>
public static IHubConnectionBuilder WithUrl(this IHubConnectionBuilder hubConnectionBuilder, string url)
{
hubConnectionBuilder.WithUrlCore(new Uri(url), null, _ => { });
return hubConnectionBuilder;
}
/// <summary>
/// Configures the <see cref="HubConnection" /> to use HTTP-based transports to connect to the specified URL.
/// </summary>
/// <param name="hubConnectionBuilder">The <see cref="IHubConnectionBuilder" /> to configure.</param>
/// <param name="url">The URL the <see cref="HttpConnection"/> will use.</param>
/// <param name="configureHttpConnection">The delegate that configures the <see cref="HttpConnection"/>.</param>
/// <returns>The same instance of the <see cref="IHubConnectionBuilder"/> for chaining.</returns>
public static IHubConnectionBuilder WithUrl(this IHubConnectionBuilder hubConnectionBuilder, string url, Action<HttpConnectionOptions> configureHttpConnection)
{
hubConnectionBuilder.WithUrlCore(new Uri(url), null, configureHttpConnection);
return hubConnectionBuilder;
}
/// <summary>
/// Configures the <see cref="HubConnection" /> to use HTTP-based transports to connect to the specified URL and transports.
/// </summary>
/// <param name="hubConnectionBuilder">The <see cref="IHubConnectionBuilder" /> to configure.</param>
/// <param name="url">The URL the <see cref="HttpConnection"/> will use.</param>
/// <param name="transports">A bitmask comprised of one or more <see cref="HttpTransportType"/> that specify what transports the client should use.</param>
/// <returns>The same instance of the <see cref="IHubConnectionBuilder"/> for chaining.</returns>
public static IHubConnectionBuilder WithUrl(this IHubConnectionBuilder hubConnectionBuilder, string url, HttpTransportType transports)
{
hubConnectionBuilder.WithUrlCore(new Uri(url), transports, _ => { });
return hubConnectionBuilder;
}
/// <summary>
/// Configures the <see cref="HubConnection" /> to use HTTP-based transports to connect to the specified URL and transports.
/// </summary>
/// <param name="hubConnectionBuilder">The <see cref="IHubConnectionBuilder" /> to configure.</param>
/// <param name="url">The URL the <see cref="HttpConnection"/> will use.</param>
/// <param name="transports">A bitmask comprised of one or more <see cref="HttpTransportType"/> that specify what transports the client should use.</param>
/// <param name="configureHttpConnection">The delegate that configures the <see cref="HttpConnection"/>.</param>
/// <returns>The same instance of the <see cref="IHubConnectionBuilder"/> for chaining.</returns>
public static IHubConnectionBuilder WithUrl(this IHubConnectionBuilder hubConnectionBuilder, string url, HttpTransportType transports, Action<HttpConnectionOptions> configureHttpConnection)
{
hubConnectionBuilder.WithUrlCore(new Uri(url), transports, configureHttpConnection);
return hubConnectionBuilder;
}
/// <summary>
/// Configures the <see cref="HubConnection" /> to use HTTP-based transports to connect to the specified URL.
/// </summary>
/// <param name="hubConnectionBuilder">The <see cref="IHubConnectionBuilder" /> to configure.</param>
/// <param name="url">The URL the <see cref="HttpConnection"/> will use.</param>
/// <returns>The same instance of the <see cref="IHubConnectionBuilder"/> for chaining.</returns>
public static IHubConnectionBuilder WithUrl(this IHubConnectionBuilder hubConnectionBuilder, Uri url)
{
hubConnectionBuilder.WithUrlCore(url, null, _ => { });
return hubConnectionBuilder;
}
/// <summary>
/// Configures the <see cref="HubConnection" /> to use HTTP-based transports to connect to the specified URL.
/// </summary>
/// <param name="hubConnectionBuilder">The <see cref="IHubConnectionBuilder" /> to configure.</param>
/// <param name="url">The URL the <see cref="HttpConnection"/> will use.</param>
/// <param name="configureHttpConnection">The delegate that configures the <see cref="HttpConnection"/>.</param>
/// <returns>The same instance of the <see cref="IHubConnectionBuilder"/> for chaining.</returns>
public static IHubConnectionBuilder WithUrl(this IHubConnectionBuilder hubConnectionBuilder, Uri url, Action<HttpConnectionOptions> configureHttpConnection)
{
hubConnectionBuilder.WithUrlCore(url, null, configureHttpConnection);
return hubConnectionBuilder;
}
/// <summary>
/// Configures the <see cref="HubConnection" /> to use HTTP-based transports to connect to the specified URL and transports.
/// </summary>
/// <param name="hubConnectionBuilder">The <see cref="IHubConnectionBuilder" /> to configure.</param>
/// <param name="url">The URL the <see cref="HttpConnection"/> will use.</param>
/// <param name="transports">A bitmask comprised of one or more <see cref="HttpTransportType"/> that specify what transports the client should use.</param>
/// <returns>The same instance of the <see cref="IHubConnectionBuilder"/> for chaining.</returns>
public static IHubConnectionBuilder WithUrl(this IHubConnectionBuilder hubConnectionBuilder, Uri url, HttpTransportType transports)
{
hubConnectionBuilder.WithUrlCore(url, null, _ => { });
return hubConnectionBuilder;
}
/// <summary>
/// Configures the <see cref="HubConnection" /> to use HTTP-based transports to connect to the specified URL and transports.
/// </summary>
/// <param name="hubConnectionBuilder">The <see cref="IHubConnectionBuilder" /> to configure.</param>
/// <param name="url">The URL the <see cref="HttpConnection"/> will use.</param>
/// <param name="transports">A bitmask comprised of one or more <see cref="HttpTransportType"/> that specify what transports the client should use.</param>
/// <param name="configureHttpConnection">The delegate that configures the <see cref="HttpConnection"/>.</param>
/// <returns>The same instance of the <see cref="IHubConnectionBuilder"/> for chaining.</returns>
public static IHubConnectionBuilder WithUrl(this IHubConnectionBuilder hubConnectionBuilder, Uri url, HttpTransportType transports, Action<HttpConnectionOptions> configureHttpConnection)
{
hubConnectionBuilder.WithUrlCore(url, transports, _ => { });
@ -60,6 +119,11 @@ namespace Microsoft.AspNetCore.SignalR.Client
private static IHubConnectionBuilder WithUrlCore(this IHubConnectionBuilder hubConnectionBuilder, Uri url, HttpTransportType? transports, Action<HttpConnectionOptions> configureHttpConnection)
{
if (hubConnectionBuilder == null)
{
throw new ArgumentNullException(nameof(hubConnectionBuilder));
}
hubConnectionBuilder.Services.Configure<HttpConnectionOptions>(o =>
{
o.Url = url;

View File

@ -6,21 +6,45 @@ using System.Runtime.Serialization;
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// The exception thrown from a hub when an error occurs.
/// </summary>
[Serializable]
public class HubException : Exception
{
/// <summary>
/// Initializes a new instance of the <see cref="HubException"/> class.
/// </summary>
public HubException()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="HubException"/> class
/// with a specified error message.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
public HubException(string message) : base(message)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="HubException"/> class
/// with a specified error message and a reference to the inner exception that is the cause of this exception.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception, or <c>null</c> if no inner exception is specified.</param>
public HubException(string message, Exception innerException) : base(message, innerException)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="HubException"/> class.
/// </summary>
/// <param name="info">The <see cref="SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
/// <param name="context">The <see cref="StreamingContext"/> that contains contextual information about the source or destination.</param>
/// <exception cref="ArgumentNullException">The <paramref name="info"/> parameter is <c>null</c>.</exception>
/// <exception cref="SerializationException">The class name is <c>null</c> or <see cref="Exception.HResult"/> is zero (0).</exception>
public HubException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}

View File

@ -9,8 +9,14 @@ using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// A builder abstraction for configuring SignalR object instances.
/// </summary>
public interface ISignalRBuilder
{
/// <summary>
/// Gets the builder service collection.
/// </summary>
IServiceCollection Services { get; }
}
}

View File

@ -6,12 +6,25 @@ using System.Collections.Generic;
namespace Microsoft.AspNetCore.SignalR.Protocol
{
/// <summary>
/// The message sent when closing a connection.
/// </summary>
public class CloseMessage : HubMessage
{
/// <summary>
/// An empty close message with no error.
/// </summary>
public static readonly CloseMessage Empty = new CloseMessage(null);
/// <summary>
/// Gets the optional error message.
/// </summary>
public string Error { get; }
/// <summary>
/// Initializes a new instance of the <see cref="CloseMessage"/> class with an optional error message.
/// </summary>
/// <param name="error">An optional error message.</param>
public CloseMessage(string error)
{
Error = error;

View File

@ -10,6 +10,9 @@ using Newtonsoft.Json;
namespace Microsoft.AspNetCore.SignalR.Protocol
{
/// <summary>
/// A helper class for working with SignalR handshakes.
/// </summary>
public static class HandshakeProtocol
{
private const string ProtocolPropertyName = "protocol";
@ -17,6 +20,9 @@ namespace Microsoft.AspNetCore.SignalR.Protocol
private const string ErrorPropertyName = "error";
private const string TypePropertyName = "type";
/// <summary>
/// The serialized representation of a success handshake.
/// </summary>
public static ReadOnlyMemory<byte> SuccessHandshakeData;
static HandshakeProtocol()
@ -33,6 +39,11 @@ namespace Microsoft.AspNetCore.SignalR.Protocol
}
}
/// <summary>
/// Writes the serialized representation of a <see cref="HandshakeRequestMessage"/> to the specified writer.
/// </summary>
/// <param name="requestMessage">The message to write.</param>
/// <param name="output">The output writer.</param>
public static void WriteRequestMessage(HandshakeRequestMessage requestMessage, IBufferWriter<byte> output)
{
var textWriter = Utf8BufferTextWriter.Get(output);
@ -57,6 +68,11 @@ namespace Microsoft.AspNetCore.SignalR.Protocol
TextMessageFormatter.WriteRecordSeparator(output);
}
/// <summary>
/// Writes the serialized representation of a <see cref="HandshakeResponseMessage"/> to the specified writer.
/// </summary>
/// <param name="responseMessage">The message to write.</param>
/// <param name="output">The output writer.</param>
public static void WriteResponseMessage(HandshakeResponseMessage responseMessage, IBufferWriter<byte> output)
{
var textWriter = Utf8BufferTextWriter.Get(output);
@ -83,6 +99,12 @@ namespace Microsoft.AspNetCore.SignalR.Protocol
TextMessageFormatter.WriteRecordSeparator(output);
}
/// <summary>
/// Creates a new <see cref="HandshakeResponseMessage"/> from the specified serialized representation.
/// </summary>
/// <param name="buffer">The serialized representation of the message.</param>
/// <param name="responseMessage">When this method returns, contains the parsed message.</param>
/// <returns>A value that is <c>true</c> if the <see cref="HandshakeResponseMessage"/> was successfully parsed; otherwise, <c>false</c>.</returns>
public static bool TryParseResponseMessage(ref ReadOnlySequence<byte> buffer, out HandshakeResponseMessage responseMessage)
{
if (!TextMessageParser.TryParseMessage(ref buffer, out var payload))
@ -142,6 +164,12 @@ namespace Microsoft.AspNetCore.SignalR.Protocol
}
}
/// <summary>
/// Creates a new <see cref="HandshakeRequestMessage"/> from the specified serialized representation.
/// </summary>
/// <param name="buffer">The serialized representation of the message.</param>
/// <param name="requestMessage">When this method returns, contains the parsed message.</param>
/// <returns>A value that is <c>true</c> if the <see cref="HandshakeRequestMessage"/> was successfully parsed; otherwise, <c>false</c>.</returns>
public static bool TryParseRequestMessage(ref ReadOnlySequence<byte> buffer, out HandshakeRequestMessage requestMessage)
{
if (!TextMessageParser.TryParseMessage(ref buffer, out var payload))

View File

@ -3,15 +3,30 @@
namespace Microsoft.AspNetCore.SignalR.Protocol
{
/// <summary>
/// A handshake request message.
/// </summary>
public class HandshakeRequestMessage : HubMessage
{
/// <summary>
/// Initializes a new instance of the <see cref="HandshakeRequestMessage"/> class.
/// </summary>
/// <param name="protocol">The requested protocol name.</param>
/// <param name="version">The requested protocol version.</param>
public HandshakeRequestMessage(string protocol, int version)
{
Protocol = protocol;
Version = version;
}
/// <summary>
/// Gets the requested protocol name.
/// </summary>
public string Protocol { get; }
/// <summary>
/// Gets the requested protocol version.
/// </summary>
public int Version { get; }
}
}

View File

@ -3,12 +3,25 @@
namespace Microsoft.AspNetCore.SignalR.Protocol
{
/// <summary>
/// A handshake response message.
/// </summary>
public class HandshakeResponseMessage : HubMessage
{
/// <summary>
/// An empty response message with no error.
/// </summary>
public static readonly HandshakeResponseMessage Empty = new HandshakeResponseMessage(null);
/// <summary>
/// Gets the optional error message.
/// </summary>
public string Error { get; }
/// <summary>
/// Initializes a new instance of the <see cref="HandshakeResponseMessage"/> class.
/// </summary>
/// <param name="error">An optional response error message. A <c>null</c> error message indicates a succesful handshake.</param>
public HandshakeResponseMessage(string error)
{
// Note that a response with an empty string for error in the JSON is considered an errored response

View File

@ -5,12 +5,25 @@ using System.Collections.Generic;
namespace Microsoft.AspNetCore.SignalR.Protocol
{
/// <summary>
/// A base class for hub messages related to a specific invocation.
/// </summary>
public abstract class HubInvocationMessage : HubMessage
{
/// <summary>
/// Gets or sets a name/value collection of headers.
/// </summary>
public IDictionary<string, string> Headers { get; set; }
/// <summary>
/// Gets the invocation ID.
/// </summary>
public string InvocationId { get; }
/// <summary>
/// Initializes a new instance of the <see cref="HubInvocationMessage"/> class.
/// </summary>
/// <param name="invocationId">The invocation ID.</param>
protected HubInvocationMessage(string invocationId)
{
InvocationId = invocationId;

View File

@ -3,6 +3,9 @@
namespace Microsoft.AspNetCore.SignalR.Protocol
{
/// <summary>
/// A base class for hub messages.
/// </summary>
public abstract class HubMessage
{
}

View File

@ -6,12 +6,27 @@ using System.Linq;
namespace Microsoft.AspNetCore.SignalR.Protocol
{
/// <summary>
/// A base class for hub messages representing an invocation.
/// </summary>
public abstract class HubMethodInvocationMessage : HubInvocationMessage
{
/// <summary>
/// Gets the target method name.
/// </summary>
public string Target { get; }
/// <summary>
/// Gets the target method arguments.
/// </summary>
public object[] Arguments { get; }
/// <summary>
/// Initializes a new instance of the <see cref="HubMethodInvocationMessage"/> class.
/// </summary>
/// <param name="invocationId">The invocation ID.</param>
/// <param name="target">The target method name.</param>
/// <param name="arguments">The target method arguments.</param>
protected HubMethodInvocationMessage(string invocationId, string target, object[] arguments)
: base(invocationId)
{
@ -25,18 +40,33 @@ namespace Microsoft.AspNetCore.SignalR.Protocol
}
}
/// <summary>
/// A hub message representing a non-streaming invocation.
/// </summary>
public class InvocationMessage : HubMethodInvocationMessage
{
/// <summary>
/// Initializes a new instance of the <see cref="InvocationMessage"/> class.
/// </summary>
/// <param name="target">The target method name.</param>
/// <param name="arguments">The target method arguments.</param>
public InvocationMessage(string target, object[] arguments)
: this(null, target, arguments)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="InvocationMessage"/> class.
/// </summary>
/// <param name="invocationId">The invocation ID.</param>
/// <param name="target">The target method name.</param>
/// <param name="arguments">The target method arguments.</param>
public InvocationMessage(string invocationId, string target, object[] arguments)
: base(invocationId, target, arguments)
{
}
/// <inheritdoc />
public override string ToString()
{
string args;
@ -52,8 +82,17 @@ namespace Microsoft.AspNetCore.SignalR.Protocol
}
}
/// <summary>
/// A hub message representing a streaming invocation.
/// </summary>
public class StreamInvocationMessage : HubMethodInvocationMessage
{
/// <summary>
/// Initializes a new instance of the <see cref="StreamInvocationMessage"/> class.
/// </summary>
/// <param name="invocationId">The invocation ID.</param>
/// <param name="target">The target method name.</param>
/// <param name="arguments">The target method arguments.</param>
public StreamInvocationMessage(string invocationId, string target, object[] arguments)
: base(invocationId, target, arguments)
{
@ -63,6 +102,7 @@ namespace Microsoft.AspNetCore.SignalR.Protocol
}
}
/// <inheritdoc />
public override string ToString()
{
string args;

View File

@ -3,14 +3,44 @@
namespace Microsoft.AspNetCore.SignalR.Protocol
{
/// <summary>
/// Constants related to the SignalR hub protocol.
/// </summary>
public static class HubProtocolConstants
{
/// <summary>
/// Represents the invocation message type.
/// </summary>
public const int InvocationMessageType = 1;
/// <summary>
/// Represents the stream item message type.
/// </summary>
public const int StreamItemMessageType = 2;
/// <summary>
/// Represents the completion message type.
/// </summary>
public const int CompletionMessageType = 3;
/// <summary>
/// Represents the stream invocation message type.
/// </summary>
public const int StreamInvocationMessageType = 4;
/// <summary>
/// Represents the cancel invocation message type.
/// </summary>
public const int CancelInvocationMessageType = 5;
/// <summary>
/// Represents the ping message type.
/// </summary>
public const int PingMessageType = 6;
/// <summary>
/// Represents the close message type.
/// </summary>
public const int CloseMessageType = 7;
}
}

View File

@ -5,9 +5,17 @@ using Microsoft.AspNetCore.Internal;
namespace Microsoft.AspNetCore.SignalR.Protocol
{
/// <summary>
/// Extension methods for <see cref="IHubProtocol"/>.
/// </summary>
public static class HubProtocolExtensions
{
// Would work as default interface impl
/// <summary>
/// Converts the specified <see cref="HubMessage"/> to its serialized representation.
/// </summary>
/// <param name="hubProtocol">The hub protocol.</param>
/// <param name="message">The message to convert to bytes.</param>
/// <returns>The serialized representation of the specified message.</returns>
public static byte[] GetMessageBytes(this IHubProtocol hubProtocol, HubMessage message)
{
var writer = MemoryBufferWriter.Get();

View File

@ -7,20 +7,54 @@ using Microsoft.AspNetCore.Connections;
namespace Microsoft.AspNetCore.SignalR.Protocol
{
/// <summary>
/// A protocol abstraction for communicating with SignalR hubs.
/// </summary>
public interface IHubProtocol
{
/// <summary>
/// Gets the name of the protocol. The name is used by SignalR to resolve the protocol between the client and server.
/// </summary>
string Name { get; }
/// <summary>
/// Gets the version of the protocol.
/// </summary>
int Version { get; }
/// <summary>
/// Gets the transfer format of the protocol.
/// </summary>
TransferFormat TransferFormat { get; }
/// <summary>
/// Creates a new <see cref="HubMessage"/> from the specified serialized representation, and using the specified binder.
/// </summary>
/// <param name="input">The serialized representation of the message.</param>
/// <param name="binder">The binder used to parse the message.</param>
/// <param name="message">When this method returns <c>true</c>, contains the parsed message.</param>
/// <returns>A value that is <c>true</c> if the <see cref="HubMessage"/> was successfully parsed; otherwise, <c>false</c>.</returns>
bool TryParseMessage(ref ReadOnlySequence<byte> input, IInvocationBinder binder, out HubMessage message);
/// <summary>
/// Writes the specified <see cref="HubMessage"/> to a writer.
/// </summary>
/// <param name="message">The message to write.</param>
/// <param name="output">The output writer.</param>
void WriteMessage(HubMessage message, IBufferWriter<byte> output);
/// <summary>
/// Converts the specified <see cref="HubMessage"/> to its serialized representation.
/// </summary>
/// <param name="message">The message to convert.</param>
/// <returns>The serialized representation of the message.</returns>
ReadOnlyMemory<byte> GetMessageBytes(HubMessage message);
/// <summary>
/// Gets a value indicating whether the protocol supports the specified version.
/// </summary>
/// <param name="version">The version.</param>
/// <returns>A value indicating whether the protocol supports the specified version.</returns>
bool IsVersionSupported(int version);
}
}

View File

@ -10,9 +10,22 @@ namespace Microsoft.AspNetCore.SignalR.Protocol
/// </summary>
public class InvocationBindingFailureMessage : HubInvocationMessage
{
/// <summary>
/// Gets the exception thrown during binding.
/// </summary>
public ExceptionDispatchInfo BindingFailure { get; }
/// <summary>
/// Gets the target method name.
/// </summary>
public string Target { get; }
/// <summary>
/// Initializes a new instance of the <see cref="InvocationBindingFailureMessage"/> class.
/// </summary>
/// <param name="invocationId">The invocation ID.</param>
/// <param name="target">The target method name.</param>
/// <param name="bindingFailure">The exception thrown during binding.</param>
public InvocationBindingFailureMessage(string invocationId, string target, ExceptionDispatchInfo bindingFailure) : base(invocationId)
{
Target = target;

View File

@ -7,6 +7,9 @@ using System.Threading.Tasks;
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// Extension methods for <see cref="IClientProxy"/>.
/// </summary>
public static class ClientProxyExtensions
{
/// <summary>
@ -14,9 +17,9 @@ namespace Microsoft.AspNetCore.SignalR
/// Does not wait for a response from the receiver.
/// </summary>
/// <param name="clientProxy">The <see cref="IClientProxy"/></param>
/// <param name="method">name of the method to invoke</param>
/// <param name="method">The name of the method to invoke.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A task that represents when the data has been sent to the client.</returns>
/// <returns>A <see cref="Task"/> that represents the asynchronous invoke.</returns>
public static Task SendAsync(this IClientProxy clientProxy, string method, CancellationToken cancellationToken = default)
{
return clientProxy.SendCoreAsync(method, Array.Empty<object>(), cancellationToken);
@ -27,10 +30,10 @@ namespace Microsoft.AspNetCore.SignalR
/// Does not wait for a response from the receiver.
/// </summary>
/// <param name="clientProxy">The <see cref="IClientProxy"/></param>
/// <param name="method">name of the method to invoke</param>
/// <param name="arg1">The first argument</param>
/// <param name="method">The name of the method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A task that represents when the data has been sent to the client.</returns>
/// <returns>A <see cref="Task"/> that represents the asynchronous invoke.</returns>
public static Task SendAsync(this IClientProxy clientProxy, string method, object arg1, CancellationToken cancellationToken = default)
{
return clientProxy.SendCoreAsync(method, new[] { arg1 }, cancellationToken);
@ -41,11 +44,11 @@ namespace Microsoft.AspNetCore.SignalR
/// Does not wait for a response from the receiver.
/// </summary>
/// <param name="clientProxy">The <see cref="IClientProxy"/></param>
/// <param name="method">name of the method to invoke</param>
/// <param name="arg1">The first argument</param>
/// <param name="arg2">The second argument</param>
/// <param name="method">The name of the method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A task that represents when the data has been sent to the client.</returns>
/// <returns>A <see cref="Task"/> that represents the asynchronous invoke.</returns>
public static Task SendAsync(this IClientProxy clientProxy, string method, object arg1, object arg2, CancellationToken cancellationToken = default)
{
return clientProxy.SendCoreAsync(method, new[] { arg1, arg2 }, cancellationToken);
@ -56,12 +59,12 @@ namespace Microsoft.AspNetCore.SignalR
/// Does not wait for a response from the receiver.
/// </summary>
/// <param name="clientProxy">The <see cref="IClientProxy"/></param>
/// <param name="method">name of the method to invoke</param>
/// <param name="arg1">The first argument</param>
/// <param name="arg2">The second argument</param>
/// <param name="arg3">The third argument</param>
/// <param name="method">The name of the method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A task that represents when the data has been sent to the client.</returns>
/// <returns>A <see cref="Task"/> that represents the asynchronous invoke.</returns>
public static Task SendAsync(this IClientProxy clientProxy, string method, object arg1, object arg2, object arg3, CancellationToken cancellationToken = default)
{
return clientProxy.SendCoreAsync(method, new[] { arg1, arg2, arg3 }, cancellationToken);
@ -72,13 +75,13 @@ namespace Microsoft.AspNetCore.SignalR
/// Does not wait for a response from the receiver.
/// </summary>
/// <param name="clientProxy">The <see cref="IClientProxy"/></param>
/// <param name="method">name of the method to invoke</param>
/// <param name="arg1">The first argument</param>
/// <param name="arg2">The second argument</param>
/// <param name="arg3">The third argument</param>
/// <param name="arg4">The fourth argument</param>
/// <param name="method">The name of the method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A task that represents when the data has been sent to the client.</returns>
/// <returns>A <see cref="Task"/> that represents the asynchronous invoke.</returns>
public static Task SendAsync(this IClientProxy clientProxy, string method, object arg1, object arg2, object arg3, object arg4, CancellationToken cancellationToken = default)
{
return clientProxy.SendCoreAsync(method, new[] { arg1, arg2, arg3, arg4 }, cancellationToken);
@ -89,14 +92,14 @@ namespace Microsoft.AspNetCore.SignalR
/// Does not wait for a response from the receiver.
/// </summary>
/// <param name="clientProxy">The <see cref="IClientProxy"/></param>
/// <param name="method">name of the method to invoke</param>
/// <param name="arg1">The first argument</param>
/// <param name="arg2">The second argument</param>
/// <param name="arg3">The third argument</param>
/// <param name="arg4">The fourth argument</param>
/// <param name="arg5">The fifth argument</param>
/// <param name="method">The name of the method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A task that represents when the data has been sent to the client.</returns>
/// <returns>A <see cref="Task"/> that represents the asynchronous invoke.</returns>
public static Task SendAsync(this IClientProxy clientProxy, string method, object arg1, object arg2, object arg3, object arg4, object arg5, CancellationToken cancellationToken = default)
{
return clientProxy.SendCoreAsync(method, new[] { arg1, arg2, arg3, arg4, arg5 }, cancellationToken);
@ -107,15 +110,15 @@ namespace Microsoft.AspNetCore.SignalR
/// Does not wait for a response from the receiver.
/// </summary>
/// <param name="clientProxy">The <see cref="IClientProxy"/></param>
/// <param name="method">name of the method to invoke</param>
/// <param name="arg1">The first argument</param>
/// <param name="arg2">The second argument</param>
/// <param name="arg3">The third argument</param>
/// <param name="arg4">The fourth argument</param>
/// <param name="arg5">The fifth argument</param>
/// <param name="arg6">The sixth argument</param>
/// <param name="method">The name of the method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
/// <param name="arg6">The sixth argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A task that represents when the data has been sent to the client.</returns>
/// <returns>A <see cref="Task"/> that represents the asynchronous invoke.</returns>
public static Task SendAsync(this IClientProxy clientProxy, string method, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, CancellationToken cancellationToken = default)
{
return clientProxy.SendCoreAsync(method, new[] { arg1, arg2, arg3, arg4, arg5, arg6 }, cancellationToken);
@ -126,16 +129,16 @@ namespace Microsoft.AspNetCore.SignalR
/// Does not wait for a response from the receiver.
/// </summary>
/// <param name="clientProxy">The <see cref="IClientProxy"/></param>
/// <param name="method">name of the method to invoke</param>
/// <param name="arg1">The first argument</param>
/// <param name="arg2">The second argument</param>
/// <param name="arg3">The third argument</param>
/// <param name="arg4">The fourth argument</param>
/// <param name="arg5">The fifth argument</param>
/// <param name="arg6">The sixth argument</param>
/// <param name="arg7">The seventh argument</param>
/// <param name="method">The name of the method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
/// <param name="arg6">The sixth argument.</param>
/// <param name="arg7">The seventh argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A task that represents when the data has been sent to the client.</returns>
/// <returns>A <see cref="Task"/> that represents the asynchronous invoke.</returns>
public static Task SendAsync(this IClientProxy clientProxy, string method, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, CancellationToken cancellationToken = default)
{
return clientProxy.SendCoreAsync(method, new[] { arg1, arg2, arg3, arg4, arg5, arg6, arg7 }, cancellationToken);
@ -146,17 +149,17 @@ namespace Microsoft.AspNetCore.SignalR
/// Does not wait for a response from the receiver.
/// </summary>
/// <param name="clientProxy">The <see cref="IClientProxy"/></param>
/// <param name="method">name of the method to invoke</param>
/// <param name="arg1">The first argument</param>
/// <param name="arg2">The second argument</param>
/// <param name="arg3">The third argument</param>
/// <param name="arg4">The fourth argument</param>
/// <param name="arg5">The fifth argument</param>
/// <param name="arg6">The sixth argument</param>
/// <param name="arg7">The seventh argument</param>
/// <param name="arg8">The eigth argument</param>
/// <param name="method">The name of the method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
/// <param name="arg6">The sixth argument.</param>
/// <param name="arg7">The seventh argument.</param>
/// <param name="arg8">The eigth argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A task that represents when the data has been sent to the client.</returns>
/// <returns>A <see cref="Task"/> that represents the asynchronous invoke.</returns>
public static Task SendAsync(this IClientProxy clientProxy, string method, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, CancellationToken cancellationToken = default)
{
return clientProxy.SendCoreAsync(method, new[] { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 }, cancellationToken);
@ -167,18 +170,18 @@ namespace Microsoft.AspNetCore.SignalR
/// Does not wait for a response from the receiver.
/// </summary>
/// <param name="clientProxy">The <see cref="IClientProxy"/></param>
/// <param name="method">name of the method to invoke</param>
/// <param name="arg1">The first argument</param>
/// <param name="arg2">The second argument</param>
/// <param name="arg3">The third argument</param>
/// <param name="arg4">The fourth argument</param>
/// <param name="arg5">The fifth argument</param>
/// <param name="arg6">The sixth argument</param>
/// <param name="arg7">The seventh argument</param>
/// <param name="arg8">The eigth argument</param>
/// <param name="arg9">The ninth argument</param>
/// <param name="method">The name of the method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
/// <param name="arg6">The sixth argument.</param>
/// <param name="arg7">The seventh argument.</param>
/// <param name="arg8">The eigth argument.</param>
/// <param name="arg9">The ninth argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A task that represents when the data has been sent to the client.</returns>
/// <returns>A <see cref="Task"/> that represents the asynchronous invoke.</returns>
public static Task SendAsync(this IClientProxy clientProxy, string method, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, object arg9, CancellationToken cancellationToken = default)
{
return clientProxy.SendCoreAsync(method, new[] { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 }, cancellationToken);
@ -189,19 +192,19 @@ namespace Microsoft.AspNetCore.SignalR
/// Does not wait for a response from the receiver.
/// </summary>
/// <param name="clientProxy">The <see cref="IClientProxy"/></param>
/// <param name="method">name of the method to invoke</param>
/// <param name="arg1">The first argument</param>
/// <param name="arg2">The second argument</param>
/// <param name="arg3">The third argument</param>
/// <param name="arg4">The fourth argument</param>
/// <param name="arg5">The fifth argument</param>
/// <param name="arg6">The sixth argument</param>
/// <param name="arg7">The seventh argument</param>
/// <param name="arg8">The eigth argument</param>
/// <param name="arg9">The ninth argument</param>
/// <param name="arg10">The tenth argument</param>
/// <param name="method">The name of the method to invoke.</param>
/// <param name="arg1">The first argument.</param>
/// <param name="arg2">The second argument.</param>
/// <param name="arg3">The third argument.</param>
/// <param name="arg4">The fourth argument.</param>
/// <param name="arg5">The fifth argument.</param>
/// <param name="arg6">The sixth argument.</param>
/// <param name="arg7">The seventh argument.</param>
/// <param name="arg8">The eigth argument.</param>
/// <param name="arg9">The ninth argument.</param>
/// <param name="arg10">The tenth argument.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A task that represents when the data has been sent to the client.</returns>
/// <returns>A <see cref="Task"/> that represents the asynchronous invoke.</returns>
public static Task SendAsync(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, CancellationToken cancellationToken = default)
{
return clientProxy.SendCoreAsync(method, new[] { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 }, cancellationToken);

View File

@ -13,17 +13,25 @@ using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// A default in-memory lifetime manager abstraction for <see cref="Hub"/> instances.
/// </summary>
public class DefaultHubLifetimeManager<THub> : HubLifetimeManager<THub> where THub : Hub
{
private readonly HubConnectionStore _connections = new HubConnectionStore();
private readonly HubGroupList _groups = new HubGroupList();
private readonly ILogger _logger;
/// <summary>
/// Initializes a new instance of the <see cref="DefaultHubLifetimeManager{THub}"/> class.
/// </summary>
/// <param name="logger">The logger.</param>
public DefaultHubLifetimeManager(ILogger<DefaultHubLifetimeManager<THub>> logger)
{
_logger = logger;
}
/// <inheritdoc />
public override Task AddToGroupAsync(string connectionId, string groupName, CancellationToken cancellationToken = default)
{
if (connectionId == null)
@ -47,6 +55,7 @@ namespace Microsoft.AspNetCore.SignalR
return Task.CompletedTask;
}
/// <inheritdoc />
public override Task RemoveFromGroupAsync(string connectionId, string groupName, CancellationToken cancellationToken = default)
{
if (connectionId == null)
@ -70,6 +79,7 @@ namespace Microsoft.AspNetCore.SignalR
return Task.CompletedTask;
}
/// <inheritdoc />
public override Task SendAllAsync(string methodName, object[] args, CancellationToken cancellationToken = default)
{
return SendToAllConnections(methodName, args, null);
@ -146,6 +156,7 @@ namespace Microsoft.AspNetCore.SignalR
}
}
/// <inheritdoc />
public override Task SendConnectionAsync(string connectionId, string methodName, object[] args, CancellationToken cancellationToken = default)
{
if (connectionId == null)
@ -167,6 +178,7 @@ namespace Microsoft.AspNetCore.SignalR
return connection.WriteAsync(message).AsTask();
}
/// <inheritdoc />
public override Task SendGroupAsync(string groupName, string methodName, object[] args, CancellationToken cancellationToken = default)
{
if (groupName == null)
@ -192,6 +204,7 @@ namespace Microsoft.AspNetCore.SignalR
return Task.CompletedTask;
}
/// <inheritdoc />
public override Task SendGroupsAsync(IReadOnlyList<string> groupNames, string methodName, object[] args, CancellationToken cancellationToken = default)
{
// Each task represents the list of tasks for each of the writes within a group
@ -220,6 +233,7 @@ namespace Microsoft.AspNetCore.SignalR
return Task.CompletedTask;
}
/// <inheritdoc />
public override Task SendGroupExceptAsync(string groupName, string methodName, object[] args, IReadOnlyList<string> excludedConnectionIds, CancellationToken cancellationToken = default)
{
if (groupName == null)
@ -254,17 +268,20 @@ namespace Microsoft.AspNetCore.SignalR
return new InvocationMessage(methodName, args);
}
/// <inheritdoc />
public override Task SendUserAsync(string userId, string methodName, object[] args, CancellationToken cancellationToken = default)
{
return SendToAllConnections(methodName, args, connection => string.Equals(connection.UserIdentifier, userId, StringComparison.Ordinal));
}
/// <inheritdoc />
public override Task OnConnectedAsync(HubConnectionContext connection)
{
_connections.Add(connection);
return Task.CompletedTask;
}
/// <inheritdoc />
public override Task OnDisconnectedAsync(HubConnectionContext connection)
{
_connections.Remove(connection);
@ -272,16 +289,19 @@ namespace Microsoft.AspNetCore.SignalR
return Task.CompletedTask;
}
/// <inheritdoc />
public override Task SendAllExceptAsync(string methodName, object[] args, IReadOnlyList<string> excludedConnectionIds, CancellationToken cancellationToken = default)
{
return SendToAllConnections(methodName, args, connection => !excludedConnectionIds.Contains(connection.ConnectionId));
}
/// <inheritdoc />
public override Task SendConnectionsAsync(IReadOnlyList<string> connectionIds, string methodName, object[] args, CancellationToken cancellationToken = default)
{
return SendToAllConnections(methodName, args, connection => connectionIds.Contains(connection.ConnectionId));
}
/// <inheritdoc />
public override Task SendUsersAsync(IReadOnlyList<string> userIds, string methodName, object[] args, CancellationToken cancellationToken = default)
{
return SendToAllConnections(methodName, args, connection => userIds.Contains(connection.UserIdentifier));

View File

@ -5,8 +5,13 @@ using System.Security.Claims;
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// The default provider for getting the user ID from a connection.
/// This provider gets the user ID from the connection's <see cref="HubConnectionContext.User"/> name identifier claim.
/// </summary>
public class DefaultUserIdProvider : IUserIdProvider
{
/// <inheritdoc />
public virtual string GetUserId(HubConnectionContext connection)
{
return connection.User?.FindFirst(ClaimTypes.NameIdentifier)?.Value;

View File

@ -3,10 +3,16 @@
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// A base class for SignalR hubs that use <c>dynamic</c> to represent client invocations.
/// </summary>
public abstract class DynamicHub : Hub
{
private DynamicHubClients _clients;
/// <summary>
/// Gets or sets an object that can be used to invoke methods on the clients connected to this hub.
/// </summary>
public new DynamicHubClients Clients
{
get

View File

@ -6,26 +6,99 @@ using Microsoft.AspNetCore.SignalR.Internal;
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// A class that provides <c>dynamic</c> access to connections, including the one that sent the current invocation.
/// </summary>
public class DynamicHubClients
{
private readonly IHubCallerClients _clients;
/// <summary>
/// Initializes a new instance of the <see cref="DynamicHubClients"/> class.
/// </summary>
/// <param name="clients">A wrapped <see cref="IHubCallerClients"/> that is used to invoke methods.</param>
public DynamicHubClients(IHubCallerClients clients)
{
_clients = clients;
}
/// <summary>
/// Gets an object that can be used to invoke methods on all clients connected to the hub.
/// </summary>
/// <returns>An object that can be used to invoke methods on the specified user.</returns>
public dynamic All => new DynamicClientProxy(_clients.All);
/// <summary>
/// Gets an object that can be used to invoke methods on all clients connected to the hub excluding the specified connections.
/// </summary>
/// <param name="excludedConnectionIds">A collection of connection IDs to exclude.</param>
/// <returns>An object that can be used to invoke methods on the specified user.</returns>
public dynamic AllExcept(IReadOnlyList<string> excludedConnectionIds) => new DynamicClientProxy(_clients.AllExcept(excludedConnectionIds));
/// <summary>
/// Gets an object that can be used to invoke methods on the connection which triggered the current invocation.
/// </summary>
public dynamic Caller => new DynamicClientProxy(_clients.Caller);
/// <summary>
/// Gets an object that can be used to invoke methods on the specified connection.
/// </summary>
/// <param name="connectionId">The connection ID.</param>
/// <returns>An object that can be used to invoke methods.</returns>
public dynamic Client(string connectionId) => new DynamicClientProxy(_clients.Client(connectionId));
/// <summary>
/// Gets an object that can be used to invoke methods on the specified connections.
/// </summary>
/// <param name="connectionIds">The connection IDs.</param>
/// <returns>An object that can be used to invoke methods.</returns>
public dynamic Clients(IReadOnlyList<string> connectionIds) => new DynamicClientProxy(_clients.Clients(connectionIds));
/// <summary>
/// Gets an object that can be used to invoke methods on all connections in the specified group.
/// </summary>
/// <param name="groupName">The group name.</param>
/// <returns>An object that can be used to invoke methods.</returns>
public dynamic Group(string groupName) => new DynamicClientProxy(_clients.Group(groupName));
/// <summary>
/// Gets an object that can be used to invoke methods on all connections in all of the specified groups.
/// </summary>
/// <param name="groupNames">The group names.</param>
/// <returns>An object that can be used to invoke methods on the specified user.</returns>
public dynamic Groups(IReadOnlyList<string> groupNames) => new DynamicClientProxy(_clients.Groups(groupNames));
/// <summary>
/// Gets an object that can be used to invoke methods on all connections in the specified group excluding the specified connections.
/// </summary>
/// <param name="groupName">The group name.</param>
/// <param name="excludedConnectionIds">A collection of connection IDs to exclude.</param>
/// <returns>An object that can be used to invoke methods.</returns>
public dynamic GroupExcept(string groupName, IReadOnlyList<string> excludedConnectionIds) => new DynamicClientProxy(_clients.GroupExcept(groupName, excludedConnectionIds));
/// <summary>
/// Gets an object that can be used to invoke methods on connections in a group other than the caller.
/// </summary>
/// <returns>An object that can be used to invoke methods.</returns>
public dynamic OthersInGroup(string groupName) => new DynamicClientProxy(_clients.OthersInGroup(groupName));
/// <summary>
/// Gets an object that can be used to invoke methods on connections other than the caller.
/// </summary>
public dynamic Others => new DynamicClientProxy(_clients.Others);
/// <summary>
/// Gets an object that can be used to invoke methods on all connections associated with the specified user.
/// </summary>
/// <param name="userId">The user ID.</param>
/// <returns>An object that can be used to invoke methods.</returns>
public dynamic User(string userId) => new DynamicClientProxy(_clients.User(userId));
/// <summary>
/// Gets an object that can be used to invoke methods on all connections associated with all of the specified users.
/// </summary>
/// <param name="users">The user IDs.</param>
/// <returns>An object that can be used to invoke methods.</returns>
public dynamic Users(IReadOnlyList<string> users) => new DynamicClientProxy(_clients.Users(users));
}
}

View File

@ -6,6 +6,9 @@ using System.Threading.Tasks;
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// A base class for a SignalR hub.
/// </summary>
public abstract class Hub : IDisposable
{
private bool _disposed;
@ -13,6 +16,9 @@ namespace Microsoft.AspNetCore.SignalR
private HubCallerContext _context;
private IGroupManager _groups;
/// <summary>
/// Gets or sets an object that can be used to invoke methods on the clients connected to this hub.
/// </summary>
public IHubCallerClients Clients
{
get
@ -27,6 +33,9 @@ namespace Microsoft.AspNetCore.SignalR
}
}
/// <summary>
/// Gets or sets the hub caller context.
/// </summary>
public HubCallerContext Context
{
get
@ -41,6 +50,9 @@ namespace Microsoft.AspNetCore.SignalR
}
}
/// <summary>
/// Gets or sets the group manager.
/// </summary>
public IGroupManager Groups
{
get
@ -55,20 +67,34 @@ namespace Microsoft.AspNetCore.SignalR
}
}
/// <summary>
/// Called when a new connection is established with the hub.
/// </summary>
/// <returns>A <see cref="Task"/> that represents the asynchronous connect.</returns>
public virtual Task OnConnectedAsync()
{
return Task.CompletedTask;
}
/// <summary>
/// Called when a connection with the hub is terminated.
/// </summary>
/// <returns>A <see cref="Task"/> that represents the asynchronous disconnect.</returns>
public virtual Task OnDisconnectedAsync(Exception exception)
{
return Task.CompletedTask;
}
/// <summary>
/// Releases all resources currently used by this <see cref="Hub"/> instance.
/// </summary>
/// <param name="disposing"><c>true</c> if this method is being invoked by the <see cref="Dispose()"/> method,
/// otherwise <c>false</c>.</param>
protected virtual void Dispose(bool disposing)
{
}
/// <inheritdoc />
public void Dispose()
{
if (_disposed)

View File

@ -8,20 +8,44 @@ using Microsoft.AspNetCore.Http.Features;
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// A context abstraction for accessing information about the hub caller connection.
/// </summary>
public abstract class HubCallerContext
{
/// <summary>
/// Gets the connection ID.
/// </summary>
public abstract string ConnectionId { get; }
/// <summary>
/// Gets the user identifier.
/// </summary>
public abstract string UserIdentifier { get; }
/// <summary>
/// Gets the user.
/// </summary>
public abstract ClaimsPrincipal User { get; }
/// <summary>
/// Gets a key/value collection that can be used to share data within the scope of this connection.
/// </summary>
public abstract IDictionary<object, object> Items { get; }
/// <summary>
/// Gets the collection of HTTP features available on the connection.
/// </summary>
public abstract IFeatureCollection Features { get; }
/// <summary>
/// Gets a <see cref="CancellationToken"/> that notifies when the connection is aborted.
/// </summary>
public abstract CancellationToken ConnectionAborted { get; }
/// <summary>
/// Aborts the connection.
/// </summary>
public abstract void Abort();
}
}

View File

@ -34,6 +34,12 @@ namespace Microsoft.AspNetCore.SignalR
private long _lastSendTimestamp = Stopwatch.GetTimestamp();
private ReadOnlyMemory<byte> _cachedPingMessage;
/// <summary>
/// Initializes a new instance of the <see cref="HubConnectionContext"/> class.
/// </summary>
/// <param name="connectionContext">The underlying <see cref="ConnectionContext"/>.</param>
/// <param name="keepAliveInterval">The keep alive interval.</param>
/// <param name="loggerFactory">The logger factory.</param>
public HubConnectionContext(ConnectionContext connectionContext, TimeSpan keepAliveInterval, ILoggerFactory loggerFactory)
{
_connectionContext = connectionContext;
@ -42,21 +48,42 @@ namespace Microsoft.AspNetCore.SignalR
_keepAliveDuration = (int)keepAliveInterval.TotalMilliseconds * (Stopwatch.Frequency / 1000);
}
/// <summary>
/// Gets a <see cref="CancellationToken"/> that notifies when the connection is aborted.
/// </summary>
public virtual CancellationToken ConnectionAborted { get; }
/// <summary>
/// Gets the ID for this connection.
/// </summary>
public virtual string ConnectionId => _connectionContext.ConnectionId;
/// <summary>
/// Gets the user for this connection.
/// </summary>
public virtual ClaimsPrincipal User => Features.Get<IConnectionUserFeature>()?.User;
/// <summary>
/// Gets the collection of features available on this connection.
/// </summary>
public virtual IFeatureCollection Features => _connectionContext.Features;
/// <summary>
/// Gets a key/value collection that can be used to share data within the scope of this connection.
/// </summary>
public virtual IDictionary<object, object> Items => _connectionContext.Items;
// Used by HubConnectionHandler
internal PipeReader Input => _connectionContext.Transport.Input;
/// <summary>
/// Gets or sets the user identifier for this connection.
/// </summary>
public string UserIdentifier { get; set; }
/// <summary>
/// Gets the protocol used by this connection.
/// </summary>
public virtual IHubProtocol Protocol { get; internal set; }
// Currently used only for streaming methods
@ -259,6 +286,9 @@ namespace Microsoft.AspNetCore.SignalR
}
}
/// <summary>
/// Aborts the connection.
/// </summary>
public virtual void Abort()
{
// If we already triggered the token then noop, this isn't thread safe but it's good enough

View File

@ -13,6 +13,9 @@ using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// Handles incoming connections and implements the SignalR Hub Protocol.
/// </summary>
public class HubConnectionHandler<THub> : ConnectionHandler where THub : Hub
{
private readonly HubLifetimeManager<THub> _lifetimeManager;
@ -25,6 +28,17 @@ namespace Microsoft.AspNetCore.SignalR
private readonly HubDispatcher<THub> _dispatcher;
private readonly bool _enableDetailedErrors;
/// <summary>
/// Initializes a new instance of the <see cref="HubConnectionHandler{THub}"/> class.
/// </summary>
/// <param name="lifetimeManager">The hub lifetime manager.</param>
/// <param name="protocolResolver">The protocol resolver used to resolve the protocols between client and server.</param>
/// <param name="globalHubOptions">The global options used to initialize hubs.</param>
/// <param name="hubOptions">Hub specific options used to initialize hubs. These options override the global options.</param>
/// <param name="loggerFactory">The logger factory.</param>
/// <param name="userIdProvider">The user ID provider used to get the user ID from a hub connection.</param>
/// <param name="dispatcher">The hub dispatcher used to dispatch incoming messages to hubs.</param>
/// <remarks>This class is typically created via dependency injection.</remarks>
public HubConnectionHandler(HubLifetimeManager<THub> lifetimeManager,
IHubProtocolResolver protocolResolver,
IOptions<HubOptions> globalHubOptions,
@ -45,6 +59,7 @@ namespace Microsoft.AspNetCore.SignalR
_enableDetailedErrors = _hubOptions.EnableDetailedErrors ?? _globalHubOptions.EnableDetailedErrors ?? false;
}
/// <inheritdoc />
public override async Task OnConnectedAsync(ConnectionContext connection)
{
// We check to see if HubOptions<THub> are set because those take precedence over global hub options.

View File

@ -7,35 +7,133 @@ using System.Threading.Tasks;
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// A lifetime manager abstraction for <see cref="Hub"/> instances.
/// </summary>
public abstract class HubLifetimeManager<THub> where THub : Hub
{
// Called by the framework and not something we'd cancel, so it doesn't take a cancellation token
/// <summary>
/// Called when a connection is started.
/// </summary>
/// <param name="connection">The connection.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous connect.</returns>
public abstract Task OnConnectedAsync(HubConnectionContext connection);
// Called by the framework and not something we'd cancel, so it doesn't take a cancellation token
/// <summary>
/// Called when a connection is finished.
/// </summary>
/// <param name="connection">The connection.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous disconnect.</returns>
public abstract Task OnDisconnectedAsync(HubConnectionContext connection);
/// <summary>
/// Sends an invocation message to all hub connections.
/// </summary>
/// <param name="methodName">The invocation method name.</param>
/// <param name="args">The invocation arguments.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous send.</returns>
public abstract Task SendAllAsync(string methodName, object[] args, CancellationToken cancellationToken = default);
/// <summary>
/// Sends an invocation message to all hub connections excluding the specified connections.
/// </summary>
/// <param name="methodName">The invocation method name.</param>
/// <param name="args">The invocation arguments.</param>
/// <param name="excludedConnectionIds">A collection of connection IDs to exclude.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous send.</returns>
public abstract Task SendAllExceptAsync(string methodName, object[] args, IReadOnlyList<string> excludedConnectionIds, CancellationToken cancellationToken = default);
/// <summary>
/// Sends an invocation message to the specified connection.
/// </summary>
/// <param name="connectionId">The connection ID.</param>
/// <param name="methodName">The invocation method name.</param>
/// <param name="args">The invocation arguments.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous send.</returns>
public abstract Task SendConnectionAsync(string connectionId, string methodName, object[] args, CancellationToken cancellationToken = default);
/// <summary>
/// Sends an invocation message to the specified connections.
/// </summary>
/// <param name="connectionIds">The connection IDs.</param>
/// <param name="methodName">The invocation method name.</param>
/// <param name="args">The invocation arguments.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous send.</returns>
public abstract Task SendConnectionsAsync(IReadOnlyList<string> connectionIds, string methodName, object[] args, CancellationToken cancellationToken = default);
/// <summary>
/// Sends an invocation message to the specified group.
/// </summary>
/// <param name="groupName">The group name.</param>
/// <param name="methodName">The invocation method name.</param>
/// <param name="args">The invocation arguments.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous send.</returns>
public abstract Task SendGroupAsync(string groupName, string methodName, object[] args, CancellationToken cancellationToken = default);
/// <summary>
/// Sends an invocation message to the specified groups.
/// </summary>
/// <param name="groupNames">The group names.</param>
/// <param name="methodName">The invocation method name.</param>
/// <param name="args">The invocation arguments.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous send.</returns>
public abstract Task SendGroupsAsync(IReadOnlyList<string> groupNames, string methodName, object[] args, CancellationToken cancellationToken = default);
/// <summary>
/// Sends an invocation message to the specified group excluding the specified connections.
/// </summary>
/// <param name="groupName">The group name.</param>
/// <param name="methodName">The invocation method name.</param>
/// <param name="args">The invocation arguments.</param>
/// <param name="excludedConnectionIds">A collection of connection IDs to exclude.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous send.</returns>
public abstract Task SendGroupExceptAsync(string groupName, string methodName, object[] args, IReadOnlyList<string> excludedConnectionIds, CancellationToken cancellationToken = default);
/// <summary>
/// Sends an invocation message to the specified user.
/// </summary>
/// <param name="userId">The user ID.</param>
/// <param name="methodName">The invocation method name.</param>
/// <param name="args">The invocation arguments.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous send.</returns>
public abstract Task SendUserAsync(string userId, string methodName, object[] args, CancellationToken cancellationToken = default);
/// <summary>
/// Sends an invocation message to the specified users.
/// </summary>
/// <param name="userIds">The user IDs.</param>
/// <param name="methodName">The invocation method name.</param>
/// <param name="args">The invocation arguments.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous send.</returns>
public abstract Task SendUsersAsync(IReadOnlyList<string> userIds, string methodName, object[] args, CancellationToken cancellationToken = default);
/// <summary>
/// Adds a connection to the specified group.
/// </summary>
/// <param name="connectionId">The connection ID to add to a group.</param>
/// <param name="groupName">The group name.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous add.</returns>
public abstract Task AddToGroupAsync(string connectionId, string groupName, CancellationToken cancellationToken = default);
/// <summary>
/// Removes a connection from the specified group.
/// </summary>
/// <param name="connectionId">The connection ID to remove from a group.</param>
/// <param name="groupName">The group name.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous remove.</returns>
public abstract Task RemoveFromGroupAsync(string connectionId, string groupName, CancellationToken cancellationToken = default);
}
}

View File

@ -5,11 +5,21 @@ using System;
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// Customizes the name of a hub method.
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class HubMethodNameAttribute : Attribute
{
/// <summary>
/// The customized name of the hub method.
/// </summary>
public string Name { get; }
/// <summary>
/// Initializes a new instance of <see cref="HubMethodNameAttribute"/> class.
/// </summary>
/// <param name="name">The customized name of the hub method.</param>
public HubMethodNameAttribute(string name)
{
Name = name;

View File

@ -6,18 +6,35 @@ using System.Collections.Generic;
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// Options used to configure hub instances.
/// </summary>
public class HubOptions
{
// HandshakeTimeout and KeepAliveInterval are set to null here to help identify when
// local hub options have been set. Global default values are set in HubOptionsSetup.
// SupportedProtocols being null is the true default value, and it represents support
// for all available protocols.
/// <summary>
/// Gets or sets the interval used by the server to timeout incoming handshake requests by clients.
/// </summary>
public TimeSpan? HandshakeTimeout { get; set; } = null;
/// <summary>
/// Gets or sets the interval used by the server to send keep alive pings to connected clients.
/// </summary>
public TimeSpan? KeepAliveInterval { get; set; } = null;
/// <summary>
/// Gets or sets a collection of supported hub protocol names.
/// </summary>
public IList<string> SupportedProtocols { get; set; } = null;
/// <summary>
/// Gets or sets a value indicating whether detailed error messages are sent to the client.
/// Detailed error messages include details from exceptions thrown on the server.
/// </summary>
public bool? EnableDetailedErrors { get; set; } = null;
}
}

View File

@ -3,5 +3,9 @@
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// Options used to configure the specified hub type instances. These options override globally set options.
/// </summary>
/// <typeparam name="THub">The hub type to configure.</typeparam>
public class HubOptions<THub> : HubOptions where THub : Hub { }
}

View File

@ -5,10 +5,17 @@ using Microsoft.AspNetCore.SignalR.Internal;
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// A base class for a strongly typed SignalR hub.
/// </summary>
/// <typeparam name="T">The type of client.</typeparam>
public abstract class Hub<T> : Hub where T : class
{
private IHubCallerClients<T> _clients;
/// <summary>
/// Gets or sets a <typeparamref name="T"/> that can be used to invoke methods on the clients connected to this hub.
/// </summary>
public new IHubCallerClients<T> Clients
{
get

View File

@ -6,6 +6,9 @@ using System.Threading.Tasks;
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// A proxy abstraction for invoking hub methods.
/// </summary>
public interface IClientProxy
{
// client proxy method is called SendCoreAsync instead of SendAsync so that arrays of references
@ -19,7 +22,7 @@ namespace Microsoft.AspNetCore.SignalR
/// <param name="method">Name of the method to invoke.</param>
/// <param name="args">A collection of arguments to pass to the client.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A task that represents when the data has been sent to the client.</returns>
/// <returns>A <see cref="Task"/> that represents the asynchronous invoke.</returns>
Task SendCoreAsync(string method, object[] args, CancellationToken cancellationToken = default);
}
}

View File

@ -6,9 +6,27 @@ using System.Threading.Tasks;
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// A manager abstraction for adding and removing connections from groups.
/// </summary>
public interface IGroupManager
{
/// <summary>
/// Adds a connection to the specified group.
/// </summary>
/// <param name="connectionId">The connection ID to add to a group.</param>
/// <param name="groupName">The group name.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous add.</returns>
Task AddToGroupAsync(string connectionId, string groupName, CancellationToken cancellationToken = default);
/// <summary>
/// Removes a connection from the specified group.
/// </summary>
/// <param name="connectionId">The connection ID to remove from a group.</param>
/// <param name="groupName">The group name.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None" />.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous remove.</returns>
Task RemoveFromGroupAsync(string connectionId, string groupName, CancellationToken cancellationToken = default);
}
}

View File

@ -5,9 +5,22 @@ using System;
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// A <see cref="Hub"/> activator abstraction.
/// </summary>
/// <typeparam name="THub">The hub type.</typeparam>
public interface IHubActivator<THub> where THub : Hub
{
/// <summary>
/// Creates a hub.
/// </summary>
/// <returns>The created hub.</returns>
THub Create();
/// <summary>
/// Releases the specified hub.
/// </summary>
/// <param name="hub">The hub to release.</param>
void Release(THub hub);
}
}

View File

@ -3,5 +3,8 @@
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// A clients caller abstraction for a hub.
/// </summary>
public interface IHubCallerClients : IHubCallerClients<IClientProxy> { }
}

View File

@ -3,12 +3,26 @@
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// An abstraction that provides access to client connections, including the one that sent the current invocation.
/// </summary>
/// <typeparam name="T">The client caller type.</typeparam>
public interface IHubCallerClients<T> : IHubClients<T>
{
/// <summary>
/// Gets a caller to the connection which triggered the current invocation.
/// </summary>
T Caller { get; }
/// <summary>
/// Gets a caller to all connections except the one which triggered the current invocation.
/// </summary>
T Others { get; }
/// <summary>
/// Gets a caller to all connections in the specified group, except the one which triggered the current invocation.
/// </summary>
/// <returns>A client caller.</returns>
T OthersInGroup(string groupName);
}
}

View File

@ -5,5 +5,8 @@ using System.Collections.Generic;
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// An abstraction that provides access to client connections.
/// </summary>
public interface IHubClients : IHubClients<IClientProxy> { }
}

View File

@ -5,86 +5,96 @@ using System.Collections.Generic;
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// Extension methods for <see cref="IHubClients{T}"/>.
/// </summary>
public static class IHubClientsExtensions
{
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all clients connected to the hub excluding the specified connection.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="excludedConnectionId1">The first connection to exclude.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T AllExcept<T>(this IHubClients<T> hubClients, string excludedConnectionId1)
{
return hubClients.AllExcept(new [] { excludedConnectionId1 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all clients connected to the hub excluding the specified connections.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="excludedConnectionId1">The first connection to exclude.</param>
/// <param name="excludedConnectionId2">The second connection to exclude.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T AllExcept<T>(this IHubClients<T> hubClients, string excludedConnectionId1, string excludedConnectionId2)
{
return hubClients.AllExcept(new [] { excludedConnectionId1, excludedConnectionId2 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all clients connected to the hub excluding the specified connections.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="excludedConnectionId1">The first connection to exclude.</param>
/// <param name="excludedConnectionId2">The second connection to exclude.</param>
/// <param name="excludedConnectionId3">The third connection to exclude.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T AllExcept<T>(this IHubClients<T> hubClients, string excludedConnectionId1, string excludedConnectionId2, string excludedConnectionId3)
{
return hubClients.AllExcept(new [] { excludedConnectionId1, excludedConnectionId2, excludedConnectionId3 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all clients connected to the hub excluding the specified connections.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="excludedConnectionId1">The first connection to exclude.</param>
/// <param name="excludedConnectionId2">The second connection to exclude.</param>
/// <param name="excludedConnectionId3">The third connection to exclude.</param>
/// <param name="excludedConnectionId4">The fourth connection to exclude.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T AllExcept<T>(this IHubClients<T> hubClients, string excludedConnectionId1, string excludedConnectionId2, string excludedConnectionId3, string excludedConnectionId4)
{
return hubClients.AllExcept(new [] { excludedConnectionId1, excludedConnectionId2, excludedConnectionId3, excludedConnectionId4 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all clients connected to the hub excluding the specified connections.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="excludedConnectionId1">The first connection to exclude.</param>
/// <param name="excludedConnectionId2">The second connection to exclude.</param>
/// <param name="excludedConnectionId3">The third connection to exclude.</param>
/// <param name="excludedConnectionId4">The fourth connection to exclude.</param>
/// <param name="excludedConnectionId5">The fifth connection to exclude.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T AllExcept<T>(this IHubClients<T> hubClients, string excludedConnectionId1, string excludedConnectionId2, string excludedConnectionId3, string excludedConnectionId4, string excludedConnectionId5)
{
return hubClients.AllExcept(new [] { excludedConnectionId1, excludedConnectionId2, excludedConnectionId3, excludedConnectionId4, excludedConnectionId5 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all clients connected to the hub excluding the specified connections.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="excludedConnectionId1">The first connection to exclude.</param>
/// <param name="excludedConnectionId2">The second connection to exclude.</param>
/// <param name="excludedConnectionId3">The third connection to exclude.</param>
/// <param name="excludedConnectionId4">The fourth connection to exclude.</param>
/// <param name="excludedConnectionId5">The fifth connection to exclude.</param>
/// <param name="excludedConnectionId6">The sixth connection to exclude.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T AllExcept<T>(this IHubClients<T> hubClients, string excludedConnectionId1, string excludedConnectionId2, string excludedConnectionId3, string excludedConnectionId4, string excludedConnectionId5, string excludedConnectionId6)
{
return hubClients.AllExcept(new [] { excludedConnectionId1, excludedConnectionId2, excludedConnectionId3, excludedConnectionId4, excludedConnectionId5, excludedConnectionId6 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all clients connected to the hub excluding the specified connections.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="excludedConnectionId1">The first connection to exclude.</param>
/// <param name="excludedConnectionId2">The second connection to exclude.</param>
/// <param name="excludedConnectionId3">The third connection to exclude.</param>
@ -92,15 +102,16 @@ namespace Microsoft.AspNetCore.SignalR
/// <param name="excludedConnectionId5">The fifth connection to exclude.</param>
/// <param name="excludedConnectionId6">The sixth connection to exclude.</param>
/// <param name="excludedConnectionId7">The seventh connection to exclude.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T AllExcept<T>(this IHubClients<T> hubClients, string excludedConnectionId1, string excludedConnectionId2, string excludedConnectionId3, string excludedConnectionId4, string excludedConnectionId5, string excludedConnectionId6, string excludedConnectionId7)
{
return hubClients.AllExcept(new [] { excludedConnectionId1, excludedConnectionId2, excludedConnectionId3, excludedConnectionId4, excludedConnectionId5, excludedConnectionId6, excludedConnectionId7 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all clients connected to the hub excluding the specified connections.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="excludedConnectionId1">The first connection to exclude.</param>
/// <param name="excludedConnectionId2">The second connection to exclude.</param>
/// <param name="excludedConnectionId3">The third connection to exclude.</param>
@ -109,90 +120,97 @@ namespace Microsoft.AspNetCore.SignalR
/// <param name="excludedConnectionId6">The sixth connection to exclude.</param>
/// <param name="excludedConnectionId7">The seventh connection to exclude.</param>
/// <param name="excludedConnectionId8">The eighth connection to exclude.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T AllExcept<T>(this IHubClients<T> hubClients, string excludedConnectionId1, string excludedConnectionId2, string excludedConnectionId3, string excludedConnectionId4, string excludedConnectionId5, string excludedConnectionId6, string excludedConnectionId7, string excludedConnectionId8)
{
return hubClients.AllExcept(new [] { excludedConnectionId1, excludedConnectionId2, excludedConnectionId3, excludedConnectionId4, excludedConnectionId5, excludedConnectionId6, excludedConnectionId7, excludedConnectionId8 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on the specified connections.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="connection1">The first connection to include.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T Clients<T>(this IHubClients<T> hubClients, string connection1)
{
return hubClients.Clients(new [] { connection1 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on the specified connections.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="connection1">The first connection to include.</param>
/// <param name="connection2">The second connection to include.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T Clients<T>(this IHubClients<T> hubClients, string connection1, string connection2)
{
return hubClients.Clients(new [] { connection1, connection2 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on the specified connections.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="connection1">The first connection to include.</param>
/// <param name="connection2">The second connection to include.</param>
/// <param name="connection3">The third connection to include.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T Clients<T>(this IHubClients<T> hubClients, string connection1, string connection2, string connection3)
{
return hubClients.Clients(new [] { connection1, connection2, connection3 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on the specified connections.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="connection1">The first connection to include.</param>
/// <param name="connection2">The second connection to include.</param>
/// <param name="connection3">The third connection to include.</param>
/// <param name="connection4">The fourth connection to include.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T Clients<T>(this IHubClients<T> hubClients, string connection1, string connection2, string connection3, string connection4)
{
return hubClients.Clients(new [] { connection1, connection2, connection3, connection4 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on the specified connections.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="connection1">The first connection to include.</param>
/// <param name="connection2">The second connection to include.</param>
/// <param name="connection3">The third connection to include.</param>
/// <param name="connection4">The fourth connection to include.</param>
/// <param name="connection5">The fifth connection to include.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T Clients<T>(this IHubClients<T> hubClients, string connection1, string connection2, string connection3, string connection4, string connection5)
{
return hubClients.Clients(new [] { connection1, connection2, connection3, connection4, connection5 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on the specified connections.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="connection1">The first connection to include.</param>
/// <param name="connection2">The second connection to include.</param>
/// <param name="connection3">The third connection to include.</param>
/// <param name="connection4">The fourth connection to include.</param>
/// <param name="connection5">The fifth connection to include.</param>
/// <param name="connection6">The sixth connection to include.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T Clients<T>(this IHubClients<T> hubClients, string connection1, string connection2, string connection3, string connection4, string connection5, string connection6)
{
return hubClients.Clients(new [] { connection1, connection2, connection3, connection4, connection5, connection6 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on the specified connections.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="connection1">The first connection to include.</param>
/// <param name="connection2">The second connection to include.</param>
/// <param name="connection3">The third connection to include.</param>
@ -200,15 +218,16 @@ namespace Microsoft.AspNetCore.SignalR
/// <param name="connection5">The fifth connection to include.</param>
/// <param name="connection6">The sixth connection to include.</param>
/// <param name="connection7">The seventh connection to include.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T Clients<T>(this IHubClients<T> hubClients, string connection1, string connection2, string connection3, string connection4, string connection5, string connection6, string connection7)
{
return hubClients.Clients(new [] { connection1, connection2, connection3, connection4, connection5, connection6, connection7 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on the specified connections.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="connection1">The first connection to include.</param>
/// <param name="connection2">The second connection to include.</param>
/// <param name="connection3">The third connection to include.</param>
@ -217,90 +236,97 @@ namespace Microsoft.AspNetCore.SignalR
/// <param name="connection6">The sixth connection to include.</param>
/// <param name="connection7">The seventh connection to include.</param>
/// <param name="connection8">The eighth connection to include.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T Clients<T>(this IHubClients<T> hubClients, string connection1, string connection2, string connection3, string connection4, string connection5, string connection6, string connection7, string connection8)
{
return hubClients.Clients(new [] { connection1, connection2, connection3, connection4, connection5, connection6, connection7, connection8 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all connections in all of the specified groups.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="group1">The first group to include.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T Groups<T>(this IHubClients<T> hubClients, string group1)
{
return hubClients.Groups(new [] { group1 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all connections in all of the specified groups.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="group1">The first group to include.</param>
/// <param name="group2">The second group to include.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T Groups<T>(this IHubClients<T> hubClients, string group1, string group2)
{
return hubClients.Groups(new [] { group1, group2 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all connections in all of the specified groups.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="group1">The first group to include.</param>
/// <param name="group2">The second group to include.</param>
/// <param name="group3">The third group to include.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T Groups<T>(this IHubClients<T> hubClients, string group1, string group2, string group3)
{
return hubClients.Groups(new [] { group1, group2, group3 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all connections in all of the specified groups.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="group1">The first group to include.</param>
/// <param name="group2">The second group to include.</param>
/// <param name="group3">The third group to include.</param>
/// <param name="group4">The fourth group to include.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T Groups<T>(this IHubClients<T> hubClients, string group1, string group2, string group3, string group4)
{
return hubClients.Groups(new [] { group1, group2, group3, group4 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all connections in all of the specified groups.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="group1">The first group to include.</param>
/// <param name="group2">The second group to include.</param>
/// <param name="group3">The third group to include.</param>
/// <param name="group4">The fourth group to include.</param>
/// <param name="group5">The fifth group to include.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T Groups<T>(this IHubClients<T> hubClients, string group1, string group2, string group3, string group4, string group5)
{
return hubClients.Groups(new [] { group1, group2, group3, group4, group5 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all connections in all of the specified groups.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="group1">The first group to include.</param>
/// <param name="group2">The second group to include.</param>
/// <param name="group3">The third group to include.</param>
/// <param name="group4">The fourth group to include.</param>
/// <param name="group5">The fifth group to include.</param>
/// <param name="group6">The sixth group to include.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T Groups<T>(this IHubClients<T> hubClients, string group1, string group2, string group3, string group4, string group5, string group6)
{
return hubClients.Groups(new [] { group1, group2, group3, group4, group5, group6 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all connections in all of the specified groups.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="group1">The first group to include.</param>
/// <param name="group2">The second group to include.</param>
/// <param name="group3">The third group to include.</param>
@ -308,15 +334,16 @@ namespace Microsoft.AspNetCore.SignalR
/// <param name="group5">The fifth group to include.</param>
/// <param name="group6">The sixth group to include.</param>
/// <param name="group7">The seventh group to include.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T Groups<T>(this IHubClients<T> hubClients, string group1, string group2, string group3, string group4, string group5, string group6, string group7)
{
return hubClients.Groups(new [] { group1, group2, group3, group4, group5, group6, group7 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all connections in all of the specified groups.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="group1">The first group to include.</param>
/// <param name="group2">The second group to include.</param>
/// <param name="group3">The third group to include.</param>
@ -325,97 +352,104 @@ namespace Microsoft.AspNetCore.SignalR
/// <param name="group6">The sixth group to include.</param>
/// <param name="group7">The seventh group to include.</param>
/// <param name="group8">The eighth group to include.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T Groups<T>(this IHubClients<T> hubClients, string group1, string group2, string group3, string group4, string group5, string group6, string group7, string group8)
{
return hubClients.Groups(new [] { group1, group2, group3, group4, group5, group6, group7, group8 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all connections in the specified group excluding the specified connections.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="groupName"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="groupName">The group name.</param>
/// <param name="excludedConnectionId1">The first connection to exclude.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T GroupExcept<T>(this IHubClients<T> hubClients, string groupName, string excludedConnectionId1)
{
return hubClients.GroupExcept(groupName, new [] { excludedConnectionId1 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all connections in the specified group excluding the specified connections.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="groupName"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="groupName">The group name.</param>
/// <param name="excludedConnectionId1">The first connection to exclude.</param>
/// <param name="excludedConnectionId2">The second connection to exclude.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T GroupExcept<T>(this IHubClients<T> hubClients, string groupName, string excludedConnectionId1, string excludedConnectionId2)
{
return hubClients.GroupExcept(groupName, new [] { excludedConnectionId1, excludedConnectionId2 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all connections in the specified group excluding the specified connections.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="groupName"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="groupName">The group name.</param>
/// <param name="excludedConnectionId1">The first connection to exclude.</param>
/// <param name="excludedConnectionId2">The second connection to exclude.</param>
/// <param name="excludedConnectionId3">The third connection to exclude.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T GroupExcept<T>(this IHubClients<T> hubClients, string groupName, string excludedConnectionId1, string excludedConnectionId2, string excludedConnectionId3)
{
return hubClients.GroupExcept(groupName, new [] { excludedConnectionId1, excludedConnectionId2, excludedConnectionId3 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all connections in the specified group excluding the specified connections.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="groupName"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="groupName">The group name.</param>
/// <param name="excludedConnectionId1">The first connection to exclude.</param>
/// <param name="excludedConnectionId2">The second connection to exclude.</param>
/// <param name="excludedConnectionId3">The third connection to exclude.</param>
/// <param name="excludedConnectionId4">The fourth connection to exclude.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T GroupExcept<T>(this IHubClients<T> hubClients, string groupName, string excludedConnectionId1, string excludedConnectionId2, string excludedConnectionId3, string excludedConnectionId4)
{
return hubClients.GroupExcept(groupName, new [] { excludedConnectionId1, excludedConnectionId2, excludedConnectionId3, excludedConnectionId4 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all connections in the specified group excluding the specified connections.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="groupName"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="groupName">The group name.</param>
/// <param name="excludedConnectionId1">The first connection to exclude.</param>
/// <param name="excludedConnectionId2">The second connection to exclude.</param>
/// <param name="excludedConnectionId3">The third connection to exclude.</param>
/// <param name="excludedConnectionId4">The fourth connection to exclude.</param>
/// <param name="excludedConnectionId5">The fifth connection to exclude.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T GroupExcept<T>(this IHubClients<T> hubClients, string groupName, string excludedConnectionId1, string excludedConnectionId2, string excludedConnectionId3, string excludedConnectionId4, string excludedConnectionId5)
{
return hubClients.GroupExcept(groupName, new [] { excludedConnectionId1, excludedConnectionId2, excludedConnectionId3, excludedConnectionId4, excludedConnectionId5 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all connections in the specified group excluding the specified connections.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="groupName"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="groupName">The group name.</param>
/// <param name="excludedConnectionId1">The first connection to exclude.</param>
/// <param name="excludedConnectionId2">The second connection to exclude.</param>
/// <param name="excludedConnectionId3">The third connection to exclude.</param>
/// <param name="excludedConnectionId4">The fourth connection to exclude.</param>
/// <param name="excludedConnectionId5">The fifth connection to exclude.</param>
/// <param name="excludedConnectionId6">The sixth connection to exclude.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T GroupExcept<T>(this IHubClients<T> hubClients, string groupName, string excludedConnectionId1, string excludedConnectionId2, string excludedConnectionId3, string excludedConnectionId4, string excludedConnectionId5, string excludedConnectionId6)
{
return hubClients.GroupExcept(groupName, new [] { excludedConnectionId1, excludedConnectionId2, excludedConnectionId3, excludedConnectionId4, excludedConnectionId5, excludedConnectionId6 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all connections in the specified group excluding the specified connections.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="groupName"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="groupName">The group name.</param>
/// <param name="excludedConnectionId1">The first connection to exclude.</param>
/// <param name="excludedConnectionId2">The second connection to exclude.</param>
/// <param name="excludedConnectionId3">The third connection to exclude.</param>
@ -423,16 +457,17 @@ namespace Microsoft.AspNetCore.SignalR
/// <param name="excludedConnectionId5">The fifth connection to exclude.</param>
/// <param name="excludedConnectionId6">The sixth connection to exclude.</param>
/// <param name="excludedConnectionId7">The seventh connection to exclude.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T GroupExcept<T>(this IHubClients<T> hubClients, string groupName, string excludedConnectionId1, string excludedConnectionId2, string excludedConnectionId3, string excludedConnectionId4, string excludedConnectionId5, string excludedConnectionId6, string excludedConnectionId7)
{
return hubClients.GroupExcept(groupName, new [] { excludedConnectionId1, excludedConnectionId2, excludedConnectionId3, excludedConnectionId4, excludedConnectionId5, excludedConnectionId6, excludedConnectionId7 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all connections in the specified group excluding the specified connections.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="groupName"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="groupName">The group name.</param>
/// <param name="excludedConnectionId1">The first connection to exclude.</param>
/// <param name="excludedConnectionId2">The second connection to exclude.</param>
/// <param name="excludedConnectionId3">The third connection to exclude.</param>
@ -441,90 +476,97 @@ namespace Microsoft.AspNetCore.SignalR
/// <param name="excludedConnectionId6">The sixth connection to exclude.</param>
/// <param name="excludedConnectionId7">The seventh connection to exclude.</param>
/// <param name="excludedConnectionId8">The eighth connection to exclude.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T GroupExcept<T>(this IHubClients<T> hubClients, string groupName, string excludedConnectionId1, string excludedConnectionId2, string excludedConnectionId3, string excludedConnectionId4, string excludedConnectionId5, string excludedConnectionId6, string excludedConnectionId7, string excludedConnectionId8)
{
return hubClients.GroupExcept(groupName, new [] { excludedConnectionId1, excludedConnectionId2, excludedConnectionId3, excludedConnectionId4, excludedConnectionId5, excludedConnectionId6, excludedConnectionId7, excludedConnectionId8 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all connections associated with all of the specified users.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="user1">The first user to include.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T Users<T>(this IHubClients<T> hubClients, string user1)
{
return hubClients.Users(new [] { user1 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all connections associated with all of the specified users.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="user1">The first user to include.</param>
/// <param name="user2">The second user to include.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T Users<T>(this IHubClients<T> hubClients, string user1, string user2)
{
return hubClients.Users(new [] { user1, user2 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all connections associated with all of the specified users.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="user1">The first user to include.</param>
/// <param name="user2">The second user to include.</param>
/// <param name="user3">The third user to include.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T Users<T>(this IHubClients<T> hubClients, string user1, string user2, string user3)
{
return hubClients.Users(new [] { user1, user2, user3 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all connections associated with all of the specified users.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="user1">The first user to include.</param>
/// <param name="user2">The second user to include.</param>
/// <param name="user3">The third user to include.</param>
/// <param name="user4">The fourth user to include.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T Users<T>(this IHubClients<T> hubClients, string user1, string user2, string user3, string user4)
{
return hubClients.Users(new [] { user1, user2, user3, user4 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all connections associated with all of the specified users.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="user1">The first user to include.</param>
/// <param name="user2">The second user to include.</param>
/// <param name="user3">The third user to include.</param>
/// <param name="user4">The fourth user to include.</param>
/// <param name="user5">The fifth user to include.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T Users<T>(this IHubClients<T> hubClients, string user1, string user2, string user3, string user4, string user5)
{
return hubClients.Users(new [] { user1, user2, user3, user4, user5 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all connections associated with all of the specified users.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="user1">The first user to include.</param>
/// <param name="user2">The second user to include.</param>
/// <param name="user3">The third user to include.</param>
/// <param name="user4">The fourth user to include.</param>
/// <param name="user5">The fifth user to include.</param>
/// <param name="user6">The sixth user to include.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T Users<T>(this IHubClients<T> hubClients, string user1, string user2, string user3, string user4, string user5, string user6)
{
return hubClients.Users(new [] { user1, user2, user3, user4, user5, user6 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all connections associated with all of the specified users.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="user1">The first user to include.</param>
/// <param name="user2">The second user to include.</param>
/// <param name="user3">The third user to include.</param>
@ -532,15 +574,16 @@ namespace Microsoft.AspNetCore.SignalR
/// <param name="user5">The fifth user to include.</param>
/// <param name="user6">The sixth user to include.</param>
/// <param name="user7">The seventh user to include.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T Users<T>(this IHubClients<T> hubClients, string user1, string user2, string user3, string user4, string user5, string user6, string user7)
{
return hubClients.Users(new [] { user1, user2, user3, user4, user5, user6, user7 });
}
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all connections associated with all of the specified users.
/// </summary>
/// <param name="hubClients"></param>
/// <param name="hubClients">The abstraction that provides access to connections.</param>
/// <param name="user1">The first user to include.</param>
/// <param name="user2">The second user to include.</param>
/// <param name="user3">The third user to include.</param>
@ -549,7 +592,7 @@ namespace Microsoft.AspNetCore.SignalR
/// <param name="user6">The sixth user to include.</param>
/// <param name="user7">The seventh user to include.</param>
/// <param name="user8">The eighth user to include.</param>
/// <returns></returns>
/// <returns>A <typeparamref name="T" /> representing the methods that can be invoked on the clients.</returns>
public static T Users<T>(this IHubClients<T> hubClients, string user1, string user2, string user3, string user4, string user5, string user6, string user7, string user8)
{
return hubClients.Users(new [] { user1, user2, user3, user4, user5, user6, user7, user8 });

View File

@ -5,24 +5,73 @@ using System.Collections.Generic;
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// An abstraction that provides access to client connections.
/// </summary>
/// <typeparam name="T">The client invoker type.</typeparam>
public interface IHubClients<T>
{
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all clients connected to the hub.
/// </summary>
/// <returns>A client caller.</returns>
T All { get; }
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all clients connected to the hub excluding the specified client connections.
/// </summary>
/// <param name="excludedConnectionIds">A collection of connection IDs to exclude.</param>
/// <returns>A client caller.</returns>
T AllExcept(IReadOnlyList<string> excludedConnectionIds);
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on the specified client connection.
/// </summary>
/// <param name="connectionId">The connection ID.</param>
/// <returns>A client caller.</returns>
T Client(string connectionId);
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on the specified client connections.
/// </summary>
/// <param name="connectionIds">The connection IDs.</param>
/// <returns>A client caller.</returns>
T Clients(IReadOnlyList<string> connectionIds);
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all connections in the specified group.
/// </summary>
/// <param name="groupName">The group name.</param>
/// <returns>A client caller.</returns>
T Group(string groupName);
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all connections in all of the specified groups.
/// </summary>
/// <param name="groupNames">The group names.</param>
/// <returns>A client caller.</returns>
T Groups(IReadOnlyList<string> groupNames);
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all connections in the specified group excluding the specified connections.
/// </summary>
/// <param name="groupName">The group name.</param>
/// <param name="excludedConnectionIds">A collection of connection IDs to exclude.</param>
/// <returns>A client caller.</returns>
T GroupExcept(string groupName, IReadOnlyList<string> excludedConnectionIds);
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all connections associated with the specified user.
/// </summary>
/// <param name="userId">The user ID.</param>
/// <returns>A client caller.</returns>
T User(string userId);
/// <summary>
/// Gets a <typeparamref name="T" /> that can be used to invoke methods on all connections associated with all of the specified users.
/// </summary>
/// <param name="userIds">The user IDs.</param>
/// <returns>A client caller.</returns>
T Users(IReadOnlyList<string> userIds);
}
}

View File

@ -3,10 +3,19 @@
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// A context abstraction for a hub.
/// </summary>
public interface IHubContext<THub> where THub : Hub
{
/// <summary>
/// Gets a <see cref="IHubClients"/> that can be used to invoke methods on clients connected to the hub.
/// </summary>
IHubClients Clients { get; }
/// <summary>
/// Gets a <see cref="IGroupManager"/> that can be used to add and remove connections to named groups.
/// </summary>
IGroupManager Groups { get; }
}
}

View File

@ -3,12 +3,21 @@
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// A context abstraction for a hub.
/// </summary>
public interface IHubContext<THub, T>
where THub : Hub<T>
where T : class
{
/// <summary>
/// Gets a <see cref="IHubClients{T}"/> that can be used to invoke methods on clients connected to the hub.
/// </summary>
IHubClients<T> Clients { get; }
/// <summary>
/// Gets a <see cref="IGroupManager"/> that can be used to add and remove connections to named groups.
/// </summary>
IGroupManager Groups { get; }
}
}

View File

@ -6,9 +6,22 @@ using Microsoft.AspNetCore.SignalR.Protocol;
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// A resolver abstraction for working with <see cref="IHubProtocol"/> instances.
/// </summary>
public interface IHubProtocolResolver
{
/// <summary>
/// Gets a collection of all available hub protocols.
/// </summary>
IReadOnlyList<IHubProtocol> AllProtocols { get; }
/// <summary>
/// Gets the hub protocol with the specified name, if it is allowed by the specified list of supported protocols.
/// </summary>
/// <param name="protocolName">The protocol name.</param>
/// <param name="supportedProtocols">A collection of supported protocols.</param>
/// <returns>A matching <see cref="IHubProtocol"/> or <c>null</c> if no matching protocol was found.</returns>
IHubProtocol GetProtocol(string protocolName, IReadOnlyList<string> supportedProtocols);
}
}

View File

@ -3,6 +3,9 @@
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// A builder abstraction for configuring SignalR servers.
/// </summary>
public interface ISignalRServerBuilder : ISignalRBuilder
{
}

View File

@ -3,8 +3,17 @@
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// A provider abstraction for configuring the "User ID" for a connection.
/// </summary>
/// <remarks><see cref="IUserIdProvider"/> is used by <see cref="IHubClients{T}.User(string)"/> to invoke connections associated with a user.</remarks>
public interface IUserIdProvider
{
/// <summary>
/// Gets the user ID for the specified connection.
/// </summary>
/// <param name="connection">The connection get get the user ID for.</param>
/// <returns>The user ID for the specified connection.</returns>
string GetUserId(HubConnectionContext connection);
}
}

View File

@ -10,6 +10,9 @@ using Microsoft.AspNetCore.Http.Features;
namespace Microsoft.AspNetCore.SignalR.Internal
{
/// <summary>
/// A context for accessing information about the hub caller from their connection.
/// </summary>
public class DefaultHubCallerContext : HubCallerContext
{
private readonly HubConnectionContext _connection;
@ -19,18 +22,25 @@ namespace Microsoft.AspNetCore.SignalR.Internal
_connection = connection;
}
/// <inheritdoc />
public override string ConnectionId => _connection.ConnectionId;
/// <inheritdoc />
public override string UserIdentifier => _connection.UserIdentifier;
/// <inheritdoc />
public override ClaimsPrincipal User => _connection.User;
/// <inheritdoc />
public override IDictionary<object, object> Items => _connection.Items;
/// <inheritdoc />
public override IFeatureCollection Features => _connection.Features;
/// <inheritdoc />
public override CancellationToken ConnectionAborted => _connection.ConnectionAborted;
/// <inheritdoc />
public override void Abort() => _connection.Abort();
}
}

View File

@ -8,7 +8,6 @@ using Microsoft.AspNetCore.SignalR.Protocol;
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// This class is designed to support the framework. The API is subject to breaking changes.
/// Represents a serialization cache for a single message.
/// </summary>
public class SerializedHubMessage
@ -18,8 +17,15 @@ namespace Microsoft.AspNetCore.SignalR
private IList<SerializedMessage> _cachedItems;
private readonly object _lock = new object();
/// <summary>
/// Gets the hub message for the serialization cache.
/// </summary>
public HubMessage Message { get; }
/// <summary>
/// Initializes a new instance of the <see cref="SerializedHubMessage"/> class.
/// </summary>
/// <param name="messages">A collection of already serialized messages to cache.</param>
public SerializedHubMessage(IReadOnlyList<SerializedMessage> messages)
{
// A lock isn't needed here because nobody has access to this type until the constructor finishes.
@ -30,11 +36,20 @@ namespace Microsoft.AspNetCore.SignalR
}
}
/// <summary>
/// Initializes a new instance of the <see cref="SerializedHubMessage"/> class.
/// </summary>
/// <param name="message">The hub message for the cache. This will be serialized with an <see cref="IHubProtocol"/> in <see cref="GetSerializedMessage"/> to get the message's serialized representation.</param>
public SerializedHubMessage(HubMessage message)
{
Message = message;
}
/// <summary>
/// Gets the serialized representation of the <see cref="HubMessage"/> using the specified <see cref="IHubProtocol"/>.
/// </summary>
/// <param name="protocol">The protocol used to create the serialized representation.</param>
/// <returns>The serialized representation of the <see cref="HubMessage"/>.</returns>
public ReadOnlyMemory<byte> GetSerializedMessage(IHubProtocol protocol)
{
lock (_lock)

View File

@ -5,11 +5,26 @@ using System;
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// Represents a serialized message.
/// </summary>
public readonly struct SerializedMessage
{
/// <summary>
/// Gets the protocol of the serialized message.
/// </summary>
public string ProtocolName { get; }
/// <summary>
/// Gets the serialized representation of the message.
/// </summary>
public ReadOnlyMemory<byte> Serialized { get; }
/// <summary>
/// Initializes a new instance of the <see cref="SerializedMessage"/> class.
/// </summary>
/// <param name="protocolName">The protocol of the serialized message.</param>
/// <param name="serialized">The serialized representation of the message.</param>
public SerializedMessage(string protocolName, ReadOnlyMemory<byte> serialized)
{
ProtocolName = protocolName;

View File

@ -8,8 +8,17 @@ using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// Extension methods for <see cref="IConnectionBuilder"/>.
/// </summary>
public static class SignalRConnectionBuilderExtensions
{
/// <summary>
/// Configure the connection to host the specified <see cref="Hub"/> type.
/// </summary>
/// <typeparam name="THub">The <see cref="Hub"/> type to host on the connection.</typeparam>
/// <param name="connectionBuilder">The connection to configure.</param>
/// <returns>The same instance of the <see cref="IConnectionBuilder"/> for chaining.</returns>
public static IConnectionBuilder UseHub<THub>(this IConnectionBuilder connectionBuilder) where THub : Hub
{
var marker = connectionBuilder.ApplicationServices.GetService(typeof(SignalRMarkerService));

View File

@ -6,8 +6,17 @@ using Microsoft.AspNetCore.SignalR.Internal;
namespace Microsoft.Extensions.DependencyInjection
{
/// <summary>
/// Extension methods for <see cref="IServiceCollection"/>.
/// </summary>
public static class SignalRDependencyInjectionExtensions
{
/// <summary>
/// Adds the minimum essential SignalR services to the specified <see cref="IServiceCollection" />. Additional services
/// must be added separately using the <see cref="ISignalRServerBuilder"/> returned from this method.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection" /> to add services to.</param>
/// <returns>An <see cref="ISignalRServerBuilder"/> that can be used to further configure the SignalR services.</returns>
public static ISignalRServerBuilder AddSignalRCore(this IServiceCollection services)
{
services.AddSingleton<SignalRMarkerService>();

View File

@ -6,8 +6,14 @@ using Newtonsoft.Json;
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// Options used to configure a <see cref="JsonHubProtocol"/> instance.
/// </summary>
public class JsonHubProtocolOptions
{
/// <summary>
/// Gets or sets the settings used to serialize invocation arguments and return values.
/// </summary>
public JsonSerializerSettings PayloadSerializerSettings { get; set; } = JsonHubProtocol.CreateDefaultSerializerSettings();
}
}

View File

@ -6,6 +6,9 @@ using Microsoft.Extensions.DependencyInjection.Extensions;
namespace Microsoft.Extensions.DependencyInjection
{
/// <summary>
/// Extension methods for <see cref="ISignalRBuilder"/>.
/// </summary>
public static class JsonProtocolDependencyInjectionExtensions
{
/// <summary>

View File

@ -16,6 +16,9 @@ using Newtonsoft.Json.Serialization;
namespace Microsoft.AspNetCore.SignalR.Protocol
{
/// <summary>
/// Implements the SignalR Hub Protocol using JSON.
/// </summary>
public class JsonHubProtocol : IHubProtocol
{
private const string ResultPropertyName = "result";
@ -30,29 +33,43 @@ namespace Microsoft.AspNetCore.SignalR.Protocol
private static readonly string ProtocolName = "json";
private static readonly int ProtocolVersion = 1;
// ONLY to be used for application payloads (args, return values, etc.)
/// <summary>
/// Gets the serializer used to serialize invocation arguments and return values.
/// </summary>
public JsonSerializer PayloadSerializer { get; }
/// <summary>
/// Initializes a new instance of the <see cref="JsonHubProtocol"/> class.
/// </summary>
public JsonHubProtocol() : this(Options.Create(new JsonHubProtocolOptions()))
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JsonHubProtocol"/> class.
/// </summary>
/// <param name="options">The options used to initialize the protocol.</param>
public JsonHubProtocol(IOptions<JsonHubProtocolOptions> options)
{
PayloadSerializer = JsonSerializer.Create(options.Value.PayloadSerializerSettings);
}
/// <inheritdoc />
public string Name => ProtocolName;
/// <inheritdoc />
public int Version => ProtocolVersion;
/// <inheritdoc />
public TransferFormat TransferFormat => TransferFormat.Text;
/// <inheritdoc />
public bool IsVersionSupported(int version)
{
return version == Version;
}
/// <inheritdoc />
public bool TryParseMessage(ref ReadOnlySequence<byte> input, IInvocationBinder binder, out HubMessage message)
{
if (!TextMessageParser.TryParseMessage(ref input, out var payload))
@ -75,12 +92,14 @@ namespace Microsoft.AspNetCore.SignalR.Protocol
return message != null;
}
/// <inheritdoc />
public void WriteMessage(HubMessage message, IBufferWriter<byte> output)
{
WriteMessageCore(message, output);
TextMessageFormatter.WriteRecordSeparator(output);
}
/// <inheritdoc />
public ReadOnlyMemory<byte> GetMessageBytes(HubMessage message)
{
return HubProtocolExtensions.GetMessageBytes(this, message);

View File

@ -8,6 +8,9 @@ using Microsoft.Extensions.DependencyInjection.Extensions;
namespace Microsoft.Extensions.DependencyInjection
{
/// <summary>
/// Extension methods for <see cref="ISignalRBuilder"/>.
/// </summary>
public static class MessagePackProtocolDependencyInjectionExtensions
{
/// <summary>

View File

@ -16,6 +16,9 @@ using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.SignalR.Protocol
{
/// <summary>
/// Implements the SignalR Hub Protocol using MessagePack.
/// </summary>
public class MessagePackHubProtocol : IHubProtocol
{
private const int ErrorResult = 1;
@ -27,16 +30,26 @@ namespace Microsoft.AspNetCore.SignalR.Protocol
private static readonly string ProtocolName = "messagepack";
private static readonly int ProtocolVersion = 1;
/// <inheritdoc />
public string Name => ProtocolName;
/// <inheritdoc />
public int Version => ProtocolVersion;
/// <inheritdoc />
public TransferFormat TransferFormat => TransferFormat.Binary;
/// <summary>
/// Initializes a new instance of the <see cref="MessagePackHubProtocol"/> class.
/// </summary>
public MessagePackHubProtocol()
: this(Options.Create(new MessagePackHubProtocolOptions()))
{ }
/// <summary>
/// Initializes a new instance of the <see cref="MessagePackHubProtocol"/> class.
/// </summary>
/// <param name="options">The options used to initialize the protocol.</param>
public MessagePackHubProtocol(IOptions<MessagePackHubProtocolOptions> options)
{
var msgPackOptions = options.Value;
@ -67,11 +80,13 @@ namespace Microsoft.AspNetCore.SignalR.Protocol
_resolver = SignalRResolver.Instance;
}
/// <inheritdoc />
public bool IsVersionSupported(int version)
{
return version == Version;
}
/// <inheritdoc />
public bool TryParseMessage(ref ReadOnlySequence<byte> input, IInvocationBinder binder, out HubMessage message)
{
if (!BinaryMessageParser.TryParseMessage(ref input, out var payload))
@ -283,6 +298,7 @@ namespace Microsoft.AspNetCore.SignalR.Protocol
return destination;
}
/// <inheritdoc />
public void WriteMessage(HubMessage message, IBufferWriter<byte> output)
{
var writer = MemoryBufferWriter.Get();
@ -302,6 +318,7 @@ namespace Microsoft.AspNetCore.SignalR.Protocol
}
}
/// <inheritdoc />
public ReadOnlyMemory<byte> GetMessageBytes(HubMessage message)
{
var writer = MemoryBufferWriter.Get();

View File

@ -8,13 +8,27 @@ using StackExchange.Redis;
namespace Microsoft.Extensions.DependencyInjection
{
/// <summary>
/// Extension methods for configuring Redis-based scale-out for a SignalR Server in an <see cref="ISignalRServerBuilder" />.
/// </summary>
public static class RedisDependencyInjectionExtensions
{
/// <summary>
/// Adds scale-out to a <see cref="ISignalRServerBuilder"/>, using a shared Redis server.
/// </summary>
/// <param name="builder">The <see cref="ISignalRServerBuilder"/>.</param>
/// <returns>The same instance of the <see cref="ISignalRServerBuilder"/> for chaining.</returns>
public static ISignalRServerBuilder AddRedis(this ISignalRServerBuilder builder)
{
return AddRedis(builder, o => { });
}
/// <summary>
/// Adds scale-out to a <see cref="ISignalRServerBuilder"/>, using a shared Redis server.
/// </summary>
/// <param name="builder">The <see cref="ISignalRServerBuilder"/>.</param>
/// <param name="redisConnectionString">The connection string used to connect to the Redis server.</param>
/// <returns>The same instance of the <see cref="ISignalRServerBuilder"/> for chaining.</returns>
public static ISignalRServerBuilder AddRedis(this ISignalRServerBuilder builder, string redisConnectionString)
{
return AddRedis(builder, o =>
@ -23,6 +37,12 @@ namespace Microsoft.Extensions.DependencyInjection
});
}
/// <summary>
/// Adds scale-out to a <see cref="ISignalRServerBuilder"/>, using a shared Redis server.
/// </summary>
/// <param name="builder">The <see cref="ISignalRServerBuilder"/>.</param>
/// <param name="configure">A callback to configure the Redis options.</param>
/// <returns>The same instance of the <see cref="ISignalRServerBuilder"/> for chaining.</returns>
public static ISignalRServerBuilder AddRedis(this ISignalRServerBuilder builder, Action<RedisOptions> configure)
{
builder.Services.Configure(configure);
@ -30,6 +50,13 @@ namespace Microsoft.Extensions.DependencyInjection
return builder;
}
/// <summary>
/// Adds scale-out to a <see cref="ISignalRServerBuilder"/>, using a shared Redis server.
/// </summary>
/// <param name="builder">The <see cref="ISignalRServerBuilder"/>.</param>
/// <param name="redisConnectionString">The connection string used to connect to the Redis server.</param>
/// <param name="configure">A callback to configure the Redis options.</param>
/// <returns>The same instance of the <see cref="ISignalRServerBuilder"/> for chaining.</returns>
public static ISignalRServerBuilder AddRedis(this ISignalRServerBuilder builder, string redisConnectionString, Action<RedisOptions> configure)
{
return AddRedis(builder, o =>

View File

@ -9,14 +9,23 @@ using StackExchange.Redis;
namespace Microsoft.AspNetCore.SignalR.Redis
{
/// <summary>
/// Options used to configure <see cref="RedisHubLifetimeManager{THub}"/>.
/// </summary>
public class RedisOptions
{
/// <summary>
/// Gets or sets configuration options exposed by <c>StackExchange.Redis</c>.
/// </summary>
public ConfigurationOptions Configuration { get; set; } = new ConfigurationOptions
{
// Enable reconnecting by default
AbortOnConnectFail = false
};
/// <summary>
/// Gets or sets the Redis connection factory.
/// </summary>
public Func<TextWriter, Task<IConnectionMultiplexer>> ConnectionFactory { get; set; }
internal async Task<IConnectionMultiplexer> ConnectAsync(TextWriter log)

View File

@ -7,8 +7,16 @@ using Microsoft.AspNetCore.Http.Connections.Features;
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// Extension methods for accessing <see cref="HttpContext"/> from a hub context.
/// </summary>
public static class GetHttpContextExtensions
{
/// <summary>
/// Gets <see cref="HttpContext"/> from the specified connection, or <c>null</c> if the connection is not associated with an HTTP request.
/// </summary>
/// <param name="connection">The connection.</param>
/// <returns>The <see cref="HttpContext"/> for the connection, or <c>null</c> if the connection is not associated with an HTTP request.</returns>
public static HttpContext GetHttpContext(this HubCallerContext connection)
{
if (connection == null)
@ -18,6 +26,11 @@ namespace Microsoft.AspNetCore.SignalR
return connection.Features.Get<IHttpContextFeature>()?.HttpContext;
}
/// <summary>
/// Gets <see cref="HttpContext"/> from the specified connection, or <c>null</c> if the connection is not associated with an HTTP request.
/// </summary>
/// <param name="connection">The connection.</param>
/// <returns>The <see cref="HttpContext"/> for the connection, or <c>null</c> if the connection is not associated with an HTTP request.</returns>
public static HttpContext GetHttpContext(this HubConnectionContext connection)
{
if (connection == null)

View File

@ -9,20 +9,38 @@ using Microsoft.AspNetCore.Http.Connections;
namespace Microsoft.AspNetCore.SignalR
{
/// <summary>
/// Maps incoming requests to <see cref="Hub"/> types.
/// </summary>
public class HubRouteBuilder
{
private readonly ConnectionsRouteBuilder _routes;
/// <summary>
/// Initializes a new instance of the <see cref="HubRouteBuilder"/> class.
/// </summary>
/// <param name="routes">The routes builder.</param>
public HubRouteBuilder(ConnectionsRouteBuilder routes)
{
_routes = routes;
}
/// <summary>
/// Maps incoming requests with the specified path to the specified <see cref="Hub"/> type.
/// </summary>
/// <typeparam name="THub">The <see cref="Hub"/> type to map requests to.</typeparam>
/// <param name="path">The request path.</param>
public void MapHub<THub>(PathString path) where THub : Hub
{
MapHub<THub>(path, configureOptions: null);
}
/// <summary>
/// Maps incoming requests with the specified path to the specified <see cref="Hub"/> type.
/// </summary>
/// <typeparam name="THub">The <see cref="Hub"/> type to map requests to.</typeparam>
/// <param name="path">The request path.</param>
/// <param name="configureOptions">A callback to configure dispatcher options.</param>
public void MapHub<THub>(PathString path, Action<HttpConnectionDispatcherOptions> configureOptions) where THub : Hub
{
// find auth attributes

View File

@ -6,8 +6,17 @@ using Microsoft.AspNetCore.SignalR;
namespace Microsoft.AspNetCore.Builder
{
/// <summary>
/// Extension methods for <see cref="IApplicationBuilder"/>.
/// </summary>
public static class SignalRAppBuilderExtensions
{
/// <summary>
/// Adds SignalR to the <see cref="IApplicationBuilder"/> request execution pipeline.
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder"/>.</param>
/// <param name="configure">A callback to configure hub routes.</param>
/// <returns>The same instance of the <see cref="IApplicationBuilder"/> for chaining.</returns>
public static IApplicationBuilder UseSignalR(this IApplicationBuilder app, Action<HubRouteBuilder> configure)
{
app.UseConnections(routes =>

View File

@ -8,8 +8,18 @@ using Microsoft.Extensions.Options;
namespace Microsoft.Extensions.DependencyInjection
{
/// <summary>
/// Extension methods for setting up SignalR services in an <see cref="IServiceCollection" />.
/// </summary>
public static class SignalRDependencyInjectionExtensions
{
/// <summary>
/// Adds hub specific options to an <see cref="ISignalRServerBuilder"/>.
/// </summary>
/// <typeparam name="THub">The hub type to configure.</typeparam>
/// <param name="signalrBuilder">The <see cref="ISignalRServerBuilder"/>.</param>
/// <param name="options">A callback to configure the hub options.</param>
/// <returns>The same instance of the <see cref="ISignalRServerBuilder"/> for chaining.</returns>
public static ISignalRServerBuilder AddHubOptions<THub>(this ISignalRServerBuilder signalrBuilder, Action<HubOptions<THub>> options) where THub : Hub
{
signalrBuilder.Services.AddSingleton<IConfigureOptions<HubOptions<THub>>, HubOptionsSetup<THub>>();
@ -17,6 +27,11 @@ namespace Microsoft.Extensions.DependencyInjection
return signalrBuilder;
}
/// <summary>
/// Adds SignalR services to the specified <see cref="IServiceCollection" />.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection" /> to add services to.</param>
/// <returns>An <see cref="ISignalRServerBuilder"/> that can be used to further configure the SignalR services.</returns>
public static ISignalRServerBuilder AddSignalR(this IServiceCollection services)
{
services.AddConnections();
@ -24,6 +39,12 @@ namespace Microsoft.Extensions.DependencyInjection
return services.AddSignalRCore();
}
/// <summary>
/// Adds SignalR services to the specified <see cref="IServiceCollection" />.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection" /> to add services to.</param>
/// <param name="options">An <see cref="Action{MvcOptions}"/> to configure the provided <see cref="HubOptions"/>.</param>
/// <returns>An <see cref="ISignalRServerBuilder"/> that can be used to further configure the SignalR services.</returns>
public static ISignalRServerBuilder AddSignalR(this IServiceCollection services, Action<HubOptions> options)
{
return services.Configure(options)