diff --git a/aspnetcore/signalr/client-features.md b/aspnetcore/signalr/client-features.md index 6fbcbca909d9..2044c118aa3b 100644 --- a/aspnetcore/signalr/client-features.md +++ b/aspnetcore/signalr/client-features.md @@ -41,6 +41,7 @@ The table below shows the features and support for the clients that offer real-t | Long Polling Transport |2.1.0|1.0.0|1.0.0|3.0.0| | JSON Hub Protocol |2.1.0|1.0.0|1.0.0|1.0.0| | MessagePack Hub Protocol |2.1.0|1.0.0|1.0.0|5.0.0| +| Client Results |7.0.0|7.0.0|7.0.0|❌| Support for enabling additional client features is tracked in [our issue tracker](https://github.com/dotnet/AspNetCore/issues). diff --git a/aspnetcore/signalr/hubs.md b/aspnetcore/signalr/hubs.md index acc61ad515f7..a17126941587 100644 --- a/aspnetcore/signalr/hubs.md +++ b/aspnetcore/signalr/hubs.md @@ -577,11 +577,14 @@ The class includes a | Calls a method on all connections in the specified group, except the specified connections | | | Calls a method on multiple groups of connections | | | Calls a method on a group of connections, excluding the client that invoked the hub method | +| `Single` | Calls a method on a specific connected client | | | Calls a method on all connections associated with a specific user | | | Calls a method on all connections associated with the specified users | Each property or method in the preceding tables returns an object with a `SendAsync` method. The `SendAsync` method receives the name of the client method to call and any parameters. +The object returned by the `Single` method also contains an `InvokeAsync` method, which can be used to wait for a [result from the client](xref:signalr/hubs#client-results). + ## Send messages to clients To make calls to specific clients, use the properties of the `Clients` object. In the following example, there are three hub methods: @@ -609,6 +612,88 @@ Using `Hub` enables compile-time checking of the client methods. Th > [!NOTE] > The `Async` suffix isn't stripped from method names. Unless a client method is defined with `.on('MyMethodAsync')`, don't use `MyMethodAsync` as the name. +## Client results + +In addition to making calls to clients, the server can request a result from a client. This requires the server to use `ISingleClientProxy.InvokeAsync` and the client to return a result from its `.On` handler. + +There are two ways to use the API on the server, the first is to call `Single(...)` on the `Clients` property in a Hub method: + +```csharp +public class ChatHub : Hub +{ + public async Task WaitForMessage(string connectionId) + { + var message = await Clients.Single(connectionId).InvokeAsync( + "GetMessage"); + return message; + } +} +``` + +> [!NOTE] +> Using `InvokeAsync` from a Hub method requires setting the [`MaximumParallelInvocationsPerClient`](xref:signalr/configuration#configure-server-options) option to a value greater than 1. +> +> This will be addressed in a future release. For more information, see [Support returning values from client invocations](https://github.com/dotnet/aspnetcore/issues/5280). + +The second way is to call `Single(...)` on an instance of [`IHubContext`](xref:signalr/hubcontext): + +```csharp +async Task SomeMethod(IHubContext context) +{ + string result = await context.Clients.Single(connectionID).InvokeAsync( + "GetMessage"); +} +``` + +Strongly-typed hubs can also return values from interface methods: + +```csharp +public interface IClient +{ + Task GetMessage(); +} + +public class ChatHub : Hub +{ + public async Task WaitForMessage(string connectionId) + { + string message = await Clients.Single(connectionId).GetMessage(); + return message; + } +} +``` + +Clients return results in their `.On(...)` handlers, as shown below: + +#### .NET client + +```csharp +hubConnection.On("GetMessage", async () => +{ + Console.WriteLine("Enter message:"); + var message = await Console.In.ReadLineAsync(); + return message; +}); +``` + +#### Typescript client + +```typescript +hubConnection.on("GetMessage", async () => { + let promise = new Promise((resolve, reject) => { + setTimeout(() => { + resolve("message"); + }, 100); + }); + return promise; +}); +``` + +> [!NOTE] +> Client results don't work with the Azure SignalR Service. +> +> This will be addressed in a future release. For more information, see [Support returning values from client invocations](https://github.com/dotnet/aspnetcore/issues/5280). + ## Change the name of a hub method By default, a server hub method name is the name of the .NET method. To change this default behavior for a specific method, use the [HubMethodName](xref:Microsoft.AspNetCore.SignalR.HubMethodNameAttribute) attribute. The client should use this name instead of the .NET method name when invoking the method: