首页 文章

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

提问于
浏览
82

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

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

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

我的问题是:我如何知道我向谁发送信息?这种新方法的解释非常肤浅 . SignalR 2.0.0的声明草案带有这个bug并且没有编译 . 有没有人实现过这个功能?

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

拥抱 .

4 回答

  • 2

    SignalR为每个连接提供ConnectionId . 要查找哪个连接属于谁(用户),我们需要在连接和用户之间创建映射 . 这取决于您在应用程序中识别用户的方式 .

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

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

    使用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中完成此操作:

    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);
       }
    }
    

    希望这可以帮助 .

  • 122

    这是一个开始..接受建议/改进 .

    服务器

    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

  • 0

    请查看SignalR Tests以获取该功能 .

    测试“SendToUser”自动使用常规owin身份验证库传递的用户身份 .

    方案是您有一个用户从多个设备/浏览器连接,并且您希望将消息推送到他的所有活动连接 .

  • 29

    这是使用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!");
    

相关问题