繁体   English   中英

SignalR 将用户 ID 从 controller 映射到连接 ID

[英]SignalR mapping User Id to Connection Id from controller

我正在使用 Angular 构建一个 ASP.NET Core 应用程序,我正在尝试使用 SignalR 实现基本的一对一聊天功能。

因为我想允许一对一聊天并在某个时候使聊天消息持久化,所以我希望能够将 map 用户 ID 转换为 SignalR 连接 ID,并根据用户的 ID 直接向用户发送消息。

现在,我看到的所有示例都使用 Hub 中的代码,这是有道理的,因为 Hub 会跟踪客户端及其连接 ID。 但是我的其他逻辑在我的 Controller 中开始和结束,当然,我不能直接从 controller 调用集线器。

由于默认情况下 SignalR 应该依赖于 Identity,因此到目前为止我已经尝试过:

[Route("send")]
    [HttpPost]
    public async Task<IActionResult> SendRequest([FromBody] Chat.Models.Message message)
    {
        var userId = Guid.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)); // I'd like to register this (current) userId with SignalR connection Id somehow
        
        var sender = new ChatSender { Id= userId, Name = user.FullName };

        await _hubContext.Clients.All.SendAsync("ReceiveMessage", sender, message.MessageText); // can't extend this, nor access hub directly

        //var recipient = _hubContext.Clients.User(message.To); // message.To is a Guid of a recepient
        //await recipient.SendAsync("ReceiveMessage", sender, message.MessageText);
        return Ok();
    }

上面的代码作为广播工作,但如果我用下面的两条注释掉的行替换_hubContext.Clients.All.SendAsync ,它什么都不做。

有什么建议么?

SignalR 将用户 ID 映射到连接 ID

map 用户id/name 和connection id,需要使用Hub 的OnConnectedAsync方法获取userid/username 和connection id,然后将它们插入到数据库中。 代码如下:

[Authorize]
public class ChatHub : Hub
{
    private readonly ApplicationDbContext _context;
    public ChatHub(ApplicationDbContext context)
    {
        _context = context;
    }
    public override async Task OnConnectedAsync()
    {
        //get the connection id
        var connectionid = Context.ConnectionId;
        //get the username or userid
        var username = Context.User.Identity.Name;
        var userId = Guid.Parse(Context.User.FindFirstValue(ClaimTypes.NameIdentifier));

        //insert or updatde them into database.
        var CId = _context.UserIdToCId.Find(userId);
        CId.ConnectionId = connectionid;
        _context.Update(CId);
        await _context.SaveChangesAsync();
        await base.OnConnectedAsync();
    }

map User Id 到 SignalR Connection Id 并根据他们的 Id 直接向用户发送消息。

您可以将您的接收者 ID 或名称从您的客户端传递给SendRequest方法,根据接收者 ID 或名称从数据库中找到 signalr 连接 ID。 找到接收者的连接 ID 后,然后使用以下代码发送消息:

await _hubContext.Clients.Client("{receiver connection id}").SendAsync("ReceiveMessage", message);

更多代码可以参考:

 public class HomeController : Controller
    {
        private readonly IHubContext<ChatHub> _hubContext;
        private readonly ApplicationDbContext _context;
        public HomeController( IHubContext<ChatHub> hubContext, ApplicationDbContext context)
        {               
            _hubContext = hubContext;
            _context = context;
        }
         ...
        /// <summary>
        /// 
        /// </summary>
        /// <param name="receiver">receiver id or name</param>
        /// <param name="message">message </param>
        /// <returns></returns>
        [Route("send")]
        [HttpPost]
        public async Task<IActionResult> SendRequest([FromBody] string receiver, Message message)
        {
            //1. according to the receiver id or name to find the signalr connection id
                //To map the user id /name with the connection id, you need to use the Hub's OnConnectedAsync method to get the userid/username and the connection id.
                //then insert them into database
            //2. After find the receiver's connection id, then use the following code to send message.
            await _hubContext.Clients.Client("{receiver connection id}").SendAsync("ReceiveMessage", message);
             
            return Ok();
        } 

注意当接收方断开连接时,记得从数据库中删除接收方的连接ID,避免发送错误。

另外可以参考How can I make one to one chat system in Asp.Net.Core Mvc Signalr? 了解更多。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM