You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

.NET Core中如何从SignalR Hub获取连接ID至服务器端控制器

.NET Core中如何从SignalR Hub获取连接ID至服务器端控制器

嘿,我来帮你搞定这个问题!在.NET Core的SignalR场景里,要把Hub中的连接ID传到服务器端控制器,有几种实用的方案,我给你逐一说明:

方法一:通过客户端中转传递

客户端在和SignalR Hub建立连接后,本身就能直接获取到连接ID,我们可以让客户端主动把这个ID通过API请求传给控制器:

  • 前端(以JavaScript为例):连接成功后拿到connection.connectionId,再用fetch或者axios发起POST请求到控制器接口
  • 后端控制器接收这个参数,示例代码如下:
[HttpPost("submit-connection-id")]
public IActionResult ReceiveConnectionId([FromBody] string connectionId)
{
    // 这里就可以获取到连接ID并进行后续处理了
    return Ok("连接ID已接收");
}

方法二:在Hub中直接调用控制器关联服务

如果控制器的业务逻辑已经封装成了服务,我们可以在Hub中通过依赖注入获取这个服务,然后在连接建立时直接把连接ID传给服务方法,控制器后续就能从服务中获取到这个ID:

public class ForumHub : Hub<IComHub>
{
    private readonly IConnectionService _connectionService;

    // 构造函数注入业务服务
    public ForumHub(IConnectionService connectionService)
    {
        _connectionService = connectionService;
    }

    public override async Task OnConnectedAsync()
    {
        var currentConnectionId = Context.ConnectionId;
        // 调用服务方法传递连接ID
        await _connectionService.StoreConnectionId(currentConnectionId);
        await base.OnConnectedAsync();
    }
}

控制器需要使用连接ID时,直接从IConnectionService中读取即可,这样还能保证逻辑的复用性。

方法三:关联用户ID与连接ID(适用于认证场景)

如果你的应用启用了身份认证,我们可以在Hub中把当前用户的ID和连接ID关联存储起来,控制器再根据当前登录用户的ID去查询对应的连接ID:

public class ForumHub : Hub<IComHub>
{
    // 用字典存储用户ID和连接ID的映射(多服务器场景建议用分布式缓存如Redis)
    public static Dictionary<string, string> UserConnectionMap = new Dictionary<string, string>();

    public override async Task OnConnectedAsync()
    {
        var userId = Context.User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
        if (!string.IsNullOrEmpty(userId))
        {
            lock (UserConnectionMap)
            {
                UserConnectionMap[userId] = Context.ConnectionId;
            }
        }
        await base.OnConnectedAsync();
    }

    public override async Task OnDisconnectedAsync(Exception exception)
    {
        var userId = Context.User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
        if (!string.IsNullOrEmpty(userId) && UserConnectionMap.ContainsKey(userId))
        {
            lock (UserConnectionMap)
            {
                UserConnectionMap.Remove(userId);
            }
        }
        await base.OnDisconnectedAsync(exception);
    }
}

控制器中,只要拿到当前登录用户的ID,就可以从UserConnectionMap中取出对应的连接ID了。

注意事项

  • 用静态字典存储映射关系时,要注意线程安全(比如加锁),多服务器部署的话建议换成Redis等分布式缓存,避免节点间数据不一致
  • 客户端断开连接时,一定要记得移除对应的映射条目,防止内存泄漏

备注:内容来源于stack exchange,提问作者redoc01

火山引擎 最新活动