SignalR-使用(IUserIdProvider) * NEW 2.0.0 * 向特定用户发送消息

在 Asp 的最新版本中。NetSignalR 添加了一种使用接口“ IUserIdProvider”向特定用户发送消息的新方法。

public interface IUserIdProvider
{
string GetUserId(IRequest request);
}


public class MyHub : Hub
{
public void Send(string userId, string message)
{
Clients.User(userId).send(message);
}
}

我的问题是: 我如何知道我要向谁发送我的信息?对这种新方法的解释非常肤浅。而且 SignalR2.0.0的语句草案带有这个 bug,并且不能编译。有人实现过这个特性吗?

更多资讯: http://www.asp.net/signalr/overview/signalr-20/hubs-api/mapping-users-to-connections#IUserIdProvider

Hugs.

131630 次浏览

看看 信号 R 测试的特性。

Test "SendToUser" takes automatically the user identity passed by using a regular owin authentication library.

这个场景是,您有一个从多个设备/浏览器连接的用户,您希望将一条消息推送到他所有的活动连接。

Here's a start.. Open to suggestions/improvements.

服务器

public class ChatHub : Hub
{
public void SendChatMessage(string who, string message)
{
string name = Context.User.Identity.Name;
Clients.Group(name).addChatMessage(name, message);
Clients.Group("2@2.com").addChatMessage(name, message);
}


public override Task OnConnected()
{
string name = Context.User.Identity.Name;
Groups.Add(Context.ConnectionId, name);


return base.OnConnected();
}
}

JavaScript

(请注意,在上面的服务器代码中,addChatMessagesendChatMessage也是方法)

    $(function () {
// Declare a proxy to reference the hub.
var chat = $.connection.chatHub;
// Create a function that the hub can call to broadcast messages.
chat.client.addChatMessage = function (who, message) {
// Html encode display name and message.
var encodedName = $('<div />').text(who).html();
var encodedMsg = $('<div />').text(message).html();
// Add the message to the page.
$('#chat').append('<li><strong>' + encodedName
+ '</strong>:&nbsp;&nbsp;' + encodedMsg + '</li>');
};


// Start the connection.
$.connection.hub.start().done(function () {
$('#sendmessage').click(function () {
// Call the Send method on the hub.
chat.server.sendChatMessage($('#displayname').val(), $('#message').val());
// Clear text box and reset focus for next comment.
$('#message').val('').focus();
});
});
});

测试 enter image description here

SignalR provides ConnectionId for each connection. To find which connection belongs to whom (the user), we need to create a mapping between the connection and the user. This depends on how you identify a user in your application.

在 SignalR 2.0中,这是通过使用内置的 IPrincipal.Identity.Name完成的,IPrincipal.Identity.Name是在 ASP.NET 身份验证期间设置的登录用户标识符。

但是,您可能需要使用不同的标识符而不是使用 Identity 与用户映射连接。姓名。为此,可以将此新提供程序与自定义实现一起使用,以便将用户与连接映射。

使用 IUserIdProvider 将 SignalR 用户映射到连接的示例

假设我们的应用程序使用 userId来标识每个用户。现在,我们需要向特定的用户发送消息。我们有 userIdmessage,但 SignalR 还必须知道 userId 和连接之间的映射。

要做到这一点,首先我们需要创建一个实现 IUserIdProvider的新类:

public class CustomUserIdProvider : IUserIdProvider
{
public string GetUserId(IRequest request)
{
// your logic to fetch a user identifier goes here.


// for example:


var userId = MyCustomUserClass.FindUserId(request.User.Identity.Name);
return userId.ToString();
}
}

第二步是告诉 SignalR 使用我们的 CustomUserIdProvider代替缺省实现。这可以在 Startup.cs 中完成,同时初始化 hub 配置:

public class Startup
{
public void Configuration(IAppBuilder app)
{
var idProvider = new CustomUserIdProvider();


GlobalHost.DependencyResolver.Register(typeof(IUserIdProvider), () => idProvider);


// Any connection or hub wire up and configuration should go here
app.MapSignalR();
}
}

现在,您可以使用文档中提到的 userId向特定用户发送消息,如:

public class MyHub : Hub
{
public void Send(string userId, string message)
{
Clients.User(userId).send(message);
}
}

希望这个能帮上忙。

以下是如何使用 SignarR 来针对特定用户(不使用任何提供程序) :

 private static ConcurrentDictionary<string, string> clients = new ConcurrentDictionary<string, string>();


public string Login(string username)
{
clients.TryAdd(Context.ConnectionId, username);
return username;
}


// The variable 'contextIdClient' is equal to Context.ConnectionId of the user,
// once logged in. You have to store that 'id' inside a dictionaty for example.
Clients.Client(contextIdClient).send("Hello!");

旧线索,但是在一个样本中发现了这个:

services.AddSignalR()
.AddAzureSignalR(options =>
{
options.ClaimsProvider = context => new[]
{
new Claim(ClaimTypes.NameIdentifier, context.Request.Query["username"])
};
});

对于任何人试图在 asp.net 核心这样做。你可以使用声明。

public class CustomEmailProvider : IUserIdProvider
{
public virtual string GetUserId(HubConnectionContext connection)
{
return connection.User?.FindFirst(ClaimTypes.Email)?.Value;
}
}

可以使用任何标识符,但它必须是唯一的。例如,如果您使用名称标识符,这意味着如果有多个用户与收件人具有相同的名称,消息也将传递给他们。我之所以选择电子邮件,是因为它对每个用户都是独一无二的。

然后在启动类中注册服务。

services.AddSingleton<IUserIdProvider, CustomEmailProvider>();

接下来,在用户注册期间添加索赔。

var result = await _userManager.CreateAsync(user, Model.Password);
if (result.Succeeded)
{
await _userManager.AddClaimAsync(user, new Claim(ClaimTypes.Email, Model.Email));
}

向特定用户发送消息。

public class ChatHub : Hub
{
public async Task SendMessage(string receiver, string message)
{
await Clients.User(receiver).SendAsync("ReceiveMessage", message);
}
}

注意: 不会通知消息发送方已发送消息。如果您希望在发件人端得到通知。将 SendMessage方法更改为。

public async Task SendMessage(string sender, string receiver, string message)
{
await Clients.Users(sender, receiver).SendAsync("ReceiveMessage", message);
}

只有在需要更改默认标识符时,才需要执行这些步骤。否则,直接跳到最后一步,您可以通过向 SendMessage传递 userID 或 ConnectionID 来简单地发送消息。为了更多