Подтвердить что ты не робот

Сопоставление соединений SignalR с пользователями

Рассмотрим веб-приложение, подобное facebook, которое может отправлять пользователям в реальном времени уведомления.

Каков наилучший способ использования asp.net SignalR, чтобы отслеживать, какие идентификаторы подключений принадлежат тому пользователю, даже если пользователь отключается или повторно подключается позже

4b9b3361

Ответ 1

Обратите внимание на следующее сообщение в блоге:

Отображение соединений ASP.NET SignalR с реальными пользователями приложений

Вкратце, вы добавляете идентификаторы подключения к пользователю по методу OnConnected и удаляете это соединение по методу OnDisconnected. Имейте в виду, что пользователь приложения может иметь несколько соединений. Таким образом, между вашим пользователем и идентификаторами подключения должно быть отношение один-много. Вышеупомянутая ссылка объясняет это подробно с образцом.

Ответ 2

Я сделал это для внутреннего приложения. То, как я это делал, заключается в том, что когда пользователь подключается, у меня есть сервер, который просит пользователя зарегистрироваться. Таким образом, я знаю, что подключен не только пользователь и их идентификатор соединения signalR, но также могут сообщить мне любую другую информацию (например, имя пользователя или что-то еще).

Когда они снова подключатся, я прошу их сделать это снова.

SignalR будет поддерживать один и тот же идентификатор соединения на клиент, даже если они снова подключится, что приятно. Повторное соединение не совпадает с исходным соединением. Новые подключения указывают на новый клиент, но переподключение происходит на одном клиенте.

В моем приложении я поддерживал отдельный словарь потокобезопасности, который я отслеживал, какой пользователь и какой connectionID что делает. Таким образом, я могу сказать "о, отправить сообщение пользователю ABC" и посмотреть их идентификатор соединения. Затем действуйте на объект клиентов-концентратора в signalR для этого идентификатора соединения. Если вы сделаете это так, вы можете даже иметь одного и того же "пользователя" в mutliple соединениях. Представьте, что пользователь "abc" открыт в двух вкладках браузера. Если вы строго придерживаетесь connectionID, они будут технически двумя разными пользователями. Но, поддерживая некоторые локальные пользователи группировки коллекций и соединений, вы можете теперь иметь несколько подключений для одного и того же пользователя.

Я должен упомянуть, что если вы сделаете это так, вы должны убедиться, что ваш сайт обрабатывает то, что происходит, когда он перезагружается и теряет всю информацию о подключении. Для меня, когда кто-то снова подключается, я прошу их снова переименовать себя. Таким образом, я могу перестроить свой локальный словарь, когда сервер приходит в интернет, не беспокоясь. У этого есть больше накладных расходов, потому что теперь вы просите всех своих клиентов отправлять вам информацию, но в зависимости от вашего случая пользователя это может быть пошатнуто или сгруппировано или иным образом распространено, чтобы помочь вам справиться с нагрузкой.

В общем, однако вы получаете локальную информацию (будь то, спрашивая у пользователя, чтобы ее предоставить), или через информацию о сеансе http-контекста, вам нужно отслеживать ее самостоятельно.

Ответ 3

Ну, я использовал другой подход, я расширил класс ApplicationUser следующим образом:

    // You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more.
public class ApplicationUser : IdentityUser
{
    //public int ApplicationUserId { get; set; }
    //public string Name { get; set; }
    //public string Address { get; set; }
    //public string City { get; set; }
    //public string State { get; set; }
    //public string Zip { get; set; }
    [Required]
    public string Email { get; set; }
    [Required]
    public override string UserName { get; set; }
    [NotMapped]
    public string ConnectionId { get; set; }
    [NotMapped]
    public string ChattingUserConnectionId { get; set; }
    //public string HomeTown { get; set; }
    //public DateTime? BirthDate { get; set; }
}

И в моем хабе я делаю что-то вроде этого:

public class ChatHub : Hub
{
    #region Data Members
    private static ApplicationDbContext applicationDbContext = new ApplicationDbContext();
    private static UserManager<ApplicationUser> userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(applicationDbContext));
    private static List<ApplicationUser> connectedUsers = new List<ApplicationUser>();

И когда пользователь подключается к чату, я получаю его объект ApplicationUser своим именем пользователя и добавляю его в список connectedUsers. Когда он отключается, я удаляю его.

Я столкнулся с некоторыми случайными исключениями с состояниями EF и такими, которые заставляли меня создавать ApplicationDbContext и UserManager каждый раз, когда к нему обращаются, вместо того, чтобы устанавливать его в статическом объекте:

 private ApplicationUser GetCurrentUser()
    {
        ApplicationDbContext applicationDbContext = new ApplicationDbContext();
        UserManager<ApplicationUser> userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(applicationDbContext));
        var userName = Context.User.Identity.GetUserName();
        var user = userManager.FindByName<ApplicationUser>(userName);

        return user;
    }

Edit:

В коде концентратора возникают некоторые проблемы с загрузкой дочерних объектов пользователя. Этот код, который также используется в шаблоне asp.net, будет работать лучше, ApplicationDBContext не нужен:

    private ApplicationUserManager _userManager
    {
        get
        {
            return HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
        }
    }


    var user = _userManager.FindByName<ApplicationUser, string>(userName);

Ответ 4

Там очень хорошая статья об учебном разделе ASP.NET SignalR. Я включил вводный параграф ниже.

Отображение пользователей SignalR для подключений

Каждый клиент, подключающийся к концентратору, передает уникальный идентификатор соединения. Ты можешь получить это значение в свойстве Context.ConnectionId концентратора контекст. Если вашему приложению необходимо сопоставить пользователя с идентификатором соединения и сохраняйте это отображение, вы можете использовать одно из следующих значений:

  • Поставщик идентификатора пользователя (SignalR 2)
  • Хранилище в памяти, такое как словарь
  • Группа SignalR для каждого пользователя

Постоянное внешнее хранилище, такое как таблица базы данных или таблица Azure хранилище. Каждая из этих реализаций показана в этом разделе. Ты используешь методы OnConnected, OnDisconnected и OnReconnected концентратора класс для отслеживания состояния подключения пользователя.


Поставщик UserID

Если вы используете стандартный поставщик членства в ASP.NET(IPrincipal.Identity.Name), вы можете просто сделать следующее для доступа к клиенту на основе учетной записи пользователя. Если у вас есть собственная пользовательская система, вы можете создать своего собственного провайдера.

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