Asp.net core 信号器-向特定用户发送消息

Asp.net core 信号器-向特定用户发送消息,asp.net-core,signalr,Asp.net Core,Signalr,我正在学习SignalRMicrosoft教程 一切正常,但是,我想尝试更改ChatHub#SendMessage中的代码,以便向特定用户发送消息 所以我修改代码如下: public class ChatHub : Hub { public async Task SendMessage(string user, string message) { //await Clients.All.SendAsync("ReceiveMessage", u

我正在学习
SignalR
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);
    }
}
public async Task SendMessage(string user, string message)
{
    //await Clients.All.SendAsync("ReceiveMessage", user, message);

    await Clients.User(Context.UserIdentifier).SendAsync("ReceiveMessage", message);
}
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
}
但是,用户从未收到消息。只有在使用
Clients.All.SendAsync
时才会发送消息(这是上面注释掉的行)

我还做了更多的研究,发现也许我需要实现一个定制的用户提供者。所以我实施了一个:

public class CustomUserIdProvider : IUserIdProvider
{
    public string GetUserId(HubConnectionContext connection)
    {
        return "user1";
    }
}
然后在
Startup.cs
中,我注册了此提供商:

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();
    services.AddSingleton<IUserIdProvider, CustomUserIdProvider>();
    services.AddSignalR();
}
但它似乎仍然没有发出信息


我做错了什么?

我这样做的方式是,当用户登录时,我将他们添加到信号器组,该组是用户的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");
}
服务器端代码:

// 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");
}
有趣的是,当用户断开连接时,
组自动消失。您不必维护正在创建的组


我知道这可能不是你想要的100%,但这是一个如何处理其他场景中类似情况的想法。

我这样做的方式是当用户登录时,我将他们添加到信号器组中,该组是用户的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");
}
服务器端代码:

// 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");
}
有趣的是,当用户断开连接时,
组自动消失。您不必维护正在创建的组


我知道这可能不是你想要的100%,但这是一个如何处理其他场景中类似情况的想法。

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

所以它应该是这样的:

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);
    }
}
public async Task SendMessage(string user, string message)
{
    //await Clients.All.SendAsync("ReceiveMessage", user, message);

    await Clients.User(Context.UserIdentifier).SendAsync("ReceiveMessage", message);
}
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
}
公共异步任务发送消息(字符串用户,字符串消息)
{
//等待Clients.All.SendAsync(“ReceiveMessage”,user,message);

wait Clients.User(User).SendAsync(“ReceiveMessage”,User,message);//我发现了问题。我在
Clients.User(User).SendAsync调用中省略了用户参数

所以它应该是这样的:

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);
    }
}
public async Task SendMessage(string user, string message)
{
    //await Clients.All.SendAsync("ReceiveMessage", user, message);

    await Clients.User(Context.UserIdentifier).SendAsync("ReceiveMessage", message);
}
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
}
公共异步任务发送消息(字符串用户,字符串消息)
{
//等待Clients.All.SendAsync(“ReceiveMessage”,user,message);

等待Clients.User(User).SendAsync(“ReceiveMessage”,User,message);//你看过了吗?@Andy-谢谢你的链接,我确实看过了。但是,不幸的是,这不是dotnet core的。啊,糟糕……我讨厌这样。但其中一些可能会转移。我会补充一个关于我如何处理基于组的用户的答案。也许以后会有用。你看过了吗?@Andy-谢谢你的链接,我看过了看看这个。然而,不幸的是,它不是为dotnet core设计的。啊,糟糕。我讨厌它。但其中一些可能会转移。我将添加一个关于我如何处理基于组的用户的答案。也许这在以后可能会有用。非常感谢你提供的信息,我可能会在某个时候使用这个想法。非常感谢你提供的信息,我可能最终会使用这个想法有一点。