我有向特定用户发送通知的要求。我正在使用dotnet core 3.1。通知的ASPNETCORE signalR。 我能够将邮件发送给所有客户端,但绝对不能针对特定用户发送邮件。
编辑1
我的集线器看起来像:
public class NotificationHub : Hub
{
public override async Task OnConnectedAsync()
{
await Groups.AddToGroupAsync(Context.ConnectionId, Context.User.Identity.Name);
await base.OnConnectedAsync();
}
public override async Task OnDisconnectedAsync(Exception ex)
{
await Groups.RemoveFromGroupAsync(Context.ConnectionId, Context.User.Identity.Name);
await base.OnDisconnectedAsync(ex);
}
}
我正在从Controller调用SendAsync方法为:
private IHubContext<NotificationHub> _hub;
public NotificationController(IHubContext<NotificationHub> hub)
{
_hub = hub;
}
[HttpGet]
public IActionResult Get()
{
//_hub.Clients.All.SendAsync("SendMessage",
_hub.Clients.All.SendAsync("SendMessage",
new
{
val1 = getRandomString(),
val2 = getRandomString(),
val3 = getRandomString(),
val4 = getRandomString()
});
return Ok(new { Message = "Request Completed" });
}
答案 0 :(得分:1)
您可以通过user id
向特定用户发送消息在此示例中,我们将尝试获取当前用户信息,并使用用户ID将一些数据发送回该用户:
在中心:
public async Task GetInfo()
{
var user = await _userManager.GetUserAsync(Context.User);
await Clients.User(user.Id).SendCoreAsync("msg", new object[] { user.Id, user.Email });
}
在客户端中:
connection.on('msg', function (...data) {
console.log('data:', data); // ["27010e2f-a47f-4c4e-93af-b55fd95f48a5", "foo@bar.com"]
});
connection.start().then(function () {
connection.invoke('getinfo');
});
注意:请确保您已经在UseEndpoints
方法内映射了中心:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapHub<YourHubName>("/yourhubname");
});
答案 1 :(得分:1)
如果您知道用户connectionId或将连接的用户添加到组中,则可以将通知发送到指定的人。
在中心,假设您知道connectionId:
await this.Clients.Client("connectionId").SendAsync("MethodName", "The message");
您还可以将指定的用户添加到组中,然后将消息发送到该组:
await this.Groups.AddToGroupAsync("connectionId", "groupName");
await this.Clients.Group("groupName").SendAsync("MethodName", "The message");
您可以在此Microsoft Documentation中了解更多信息。
更新:
要回答更新的问题,必须向中心提供授权属性,以便具有身份名称和其他参数
[Authorize]
public class NotificationHub : Hub
{
public override async Task OnConnectedAsync()
{
await Groups.AddToGroupAsync(Context.ConnectionId, Context.User.Identity.Name);
await base.OnConnectedAsync();
}
public override async Task OnDisconnectedAsync(Exception ex)
{
await Groups.RemoveFromGroupAsync(Context.ConnectionId, Context.User.Identity.Name);
await base.OnDisconnectedAsync(ex);
}
}
然后在Angular客户端上,您必须提供令牌以连接到集线器,例如:
private configureSignalR(token: string) {
this.hubMessageConnection = new signalR.HubConnectionBuilder()
.configureLogging(signalR.LogLevel.Error).withUrl(this.signalRUrl + "/notifications",
{
accessTokenFactory: () => token
})
.withAutomaticReconnect()
.build();
}
您可以了解有关Authentication and authorization in the microsoft documentation的更多信息。
答案 2 :(得分:0)
我认为是ASP.NET Core SignalR中的错误(我也在使用ASP.NET Core 3.1 ),
_hubContext.Clients.User(userId).SendAsync(...)
似乎不起作用。请注意,默认情况下,userId
是基于声明的身份验证存储为ClaimTypes.NameIdentifier
的内容( From doc:默认情况下,SignalR使用与连接关联的ClaimsPrincipal中的ClaimTypes.NameIdentifier作为用户标识符。)
所以我不得不创建自己的连接管理器,并且运行良好,一旦获得所有用户的连接,就可以循环并编写类似的内容
_hubContext.Clients.Client(connectionId).SendAsync(...)
以下是有关如何管理用户连接的提示:
public class YourHub : Hub
...
public override Task OnConnectedAsync()
{
//Get userId
_connectionHubManager.AddConnection(userId, Context.ConnectionId);
return base.OnConnectedAsync();
}
public override Task OnDisconnectedAsync(Exception exception)
{
_connectionHubManager.RemoveConnection(Context.ConnectionId);
return base.OnDisconnectedAsync(exception);
}
获得userId
取决于您的努力。
如果将userId
注册为ClaimTypes.Name
,则只需获取它:
Context.User.Identity.Name;
如果将userId
注册为ClaimTypes.NameIdentifier
,则需要执行以下操作:
(Context.User.Identity as ClaimsIdentity)?.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier)?.Value;
不要忘记将[Authorize]
添加到您的集线器类中,以填充这些字段并检查Doc以获得SignalR身份验证。