【问题标题】:signalR - send message to specific usersignalR - 向特定用户发送消息
【发布时间】:2020-08-07 14:37:10
【问题描述】:

我正在学习位于hereSignalR Microsoft 教程。

一切正常,但是,我想尝试更改 ChatHub#SendMessage 中的代码以向特定用户发送消息。

所以我修改了这样的代码:

public class ChatHub : Hub
{
    public async Task SendMessage(string user, string message)
    {
        //await Clients.All.SendAsync("ReceiveMessage", user, message);

        await Clients.User(user).SendAsync("ReceiveMessage", message);
    }
}

但是,用户永远不会收到消息。仅当您使用 Clients.All.SendAsync(即上面注释掉的行)时才会发送消息。

我还做了更多的研究,从this answer 发现,也许我需要实现一个自定义用户提供程序。所以我实现了一个:

public class CustomUserIdProvider : IUserIdProvider
{
    public string GetUserId(HubConnectionContext connection)
    {
        return "user1";
    }
}

然后在Startup.cs,我注册了这个provider:

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();
    services.AddSingleton<IUserIdProvider, CustomUserIdProvider>();
    services.AddSignalR();
}

然后我尝试在发送消息时使用Context.UserIdentifier,如下所示:

public async Task SendMessage(string user, string message)
{
    //await Clients.All.SendAsync("ReceiveMessage", user, message);

    await Clients.User(Context.UserIdentifier).SendAsync("ReceiveMessage", message);
}

但它似乎仍然没有发送消息。

我做错了什么?

【问题讨论】:

  • @Andy- 感谢您的链接,我确实查看了那个链接。但是,不幸的是,它不适用于 dotnet core。
  • 啊,真可惜……我讨厌这样。但其中一些可能会转移。我将添加一个关于如何根据组处理用户的答案。也许它在未来可能会有用。

标签: asp.net-core signalr


【解决方案1】:

我这样做的方式是,当用户登录时,我将他们添加到 SignalR 组,该组是用户的 ID 或名称。这样一来,对于该一个用户来说,它就是一个独特的组。然后我将消息发送到该组。只有该用户会收到该消息,因为他们是该组中的唯一用户。

客户端代码:

// Optional: authenticate with a server, get a token... or send username/password in following request

_hub = new HubConnectionBuilder()
    .WithUrl(_envSettings.CreatePlayerServiceHubPath(), x =>
    {
        x.Headers.Add("x-lcc-version", AppEnvironment.Application.Version);
        x.Headers.Add("x-lcc-username", username);
        x.Headers.Add("x-lcc-authorization", token);
    })
    .AddNewtonsoftJsonProtocol()
    .Build();

_hub.Closed += OnSignalRDisconnectedFromServerAsync;
SetupRPCs();
await _hub.StartAsync().ConfigureAwait(false);

服务器端代码:

public override async Task OnConnectedAsync()
{
    var userName = Context.GetHttpContext().Request.Headers["x-lcc-username"];
    var token = Context.GetHttpContext().Request.Headers["x-lcc-authorization"];
    
    // Optional: validate authorization
    
    await Groups.AddToGroupAsync(Context.ConnectionId, userName);
    
    // Then when you want to send a message to the user:
    await Clients.Group(userName).SendAsync("hello", "world");
}

很好的是,当用户断开连接时,Group 会自动消失。您不必维护您正在创建的那些组。

我知道这可能不是 100% 您正在寻找的,但它是关于如何处理与其他场景类似的情况的一个想法。

【讨论】:

  • 非常感谢您提供的信息,我可能最终会在某个时候使用这个想法。
【解决方案2】:

我发现了问题。我在Clients.User(user).SendAsync 调用中省略了用户参数。

所以应该是这样的:

public async Task SendMessage(string user, string message)
{
    //await Clients.All.SendAsync("ReceiveMessage", user, message);

    await Clients.User(user).SendAsync("ReceiveMessage", user, message); // <-- add user parameter
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-30
    • 2016-09-19
    • 2017-12-28
    • 2015-04-27
    • 1970-01-01
    相关资源
    最近更新 更多