System.InvalidOperationException:不允许 OnConnectedAsync Hub 方法内的客户端结果

问题描述 投票:0回答:1

使用 SignalR .NET 7 中的新客户端结果功能时,我遇到一个错误:不允许在 OnConnectedAsync Hub 方法中使用客户端结果。

我的用例是我有多个客户端,我使用

OnConnectedAsync 方法缓存每个客户端的连接 ID,以便我可以向特定客户端发送消息并等待他们的响应。

这是我的集线器类,请注意,当我调用客户端方法时抛出异常:

return await Clients.Client(connectionMetadata.ConnectionId).InvokeAsync<bool>("CreateConnection", message, CancellationToken.None);
public class ConnectionCreationHub : Hub
{
    private readonly List<ConnectionMetadata> connectionIdsCache;
    private readonly ITokenValidator2 validator;

    public ConnectionCreationHub(
        ITokenValidator2 validator,
        List<ConnectionMetadata> connectionIdsCache)
    {
        this.validator = validator;
        this.connectionIdsCache = connectionIdsCache;
    }

    public async Task<bool> SendCreateConnectionMessage(
        Guid userId,
        string message)
    {
        var connectionMetadata =
            connectionIdsCache
                .FirstOrDefault(entry => entry.UserId.Equals(userId));

        if (connectionMetadata == null)
        {
            throw new Exception($"Client with userId {userId} not connected");
        }

        //The following line throws an error "System.InvalidOperationException: Client results inside OnConnectedAsync Hub methods are not allowed."
        return await Clients.Client(connectionMetadata.ConnectionId).InvokeAsync<bool>("CreateConnection", message, CancellationToken.None);
    }

    public override async Task OnConnectedAsync()
    {
        //Validate authorization token, and cache connection ID.
        var tokenClaims = await this.AuthorizeOrThrow(validator);

        var userId = tokenClaims.UserId;

        connectionIdsCache.Add(new(userId, Context.ConnectionId));

        await base.OnConnectedAsync();
    }

    public override async Task OnDisconnectedAsync(Exception? exception)
    {
        //Clean cache on client disconnected
        var connectionMetadata =
            connectionIdsCache
                .FirstOrDefault(entry => entry.ConnectionId == Context.ConnectionId);

        if (connectionMetadata != null)
        {
            connectionIdsCache.Remove(connectionMetadata);
        }

        await base.OnDisconnectedAsync(exception);
    }
}
我希望我的客户会收到该消息,但我收到了上述错误。请注意,只有使用 

InvokeAsync 时才会发生这种情况。 *SendAsync 正在按预期工作。

以下是异常详细信息:

System.InvalidOperationException HResult=0x80131509 Message=Client results inside OnConnectedAsync Hub methods are not allowed. Source=Microsoft.AspNetCore.SignalR.Core StackTrace: at Microsoft.AspNetCore.SignalR.Internal.HubCallerClients.NoInvokeSingleClientProxy.InvokeCoreAsync[T](String method, Object[] args, CancellationToken cancellationToken) at Microsoft.AspNetCore.SignalR.ClientProxyExtensions.InvokeAsync[T](ISingleClientProxy clientProxy, String method, Object arg1, CancellationToken cancellationToken) at ConnectionCreationHub.<SendCreateConnectionMessage>d__3.MoveNext() in *\ConnectionCreationHub.cs:line 42
    
.net-7.0 asp.net-core-signalr
1个回答
0
投票
在 SignalR .NET 7 中,有一个限制,不允许在 OnConnectedAsync 方法的上下文中等待客户端结果,因为在 OnConnectedAsync 完成之前连接尚未完全建立。

已知问题使用客户端结果时从 OnConnected 和 OnDisconnected 抛出

优化后的代码如下,大家可以参考一下。

public async Task<bool> SendCreateConnectionMessage( Guid userId, string message) { var connectionMetadata = connectionIdsCache .FirstOrDefault(entry => entry.UserId.Equals(userId)); if (connectionMetadata == null) { throw new Exception($"Client with userId {userId} not connected"); } //We need to ensure that this invocation is not in the lifecycle context. bool result = false; try { result = await Clients.Client(connectionMetadata.ConnectionId) .InvokeAsync<bool>("CreateConnection", message, CancellationToken.None); } catch (Exception ex) { // Handle the exception. throw new Exception($"Error while trying to invoke client method: {ex.Message}", ex); } return result; }
    
© www.soinside.com 2019 - 2024. All rights reserved.