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

Нет доступа к информации о сеансе через концентратор SignalR. Является ли мой дизайн неправильным?

Я только что обнаружил, что вы не можете получить доступ к текущему сеансу в концентраторе SignalR.

Упрощен мой сценарий: я пытался написать чат.

Имя текущего пользователя хранилось в сеансе.

Я использовал SignalR для обновления (группы подключений) о каждом новом сообщении.

Теперь я вижу, что я не могу получить доступ к имени текущего пользователя через концентратор.

Я предполагаю, что могут быть некоторые обходные пути, но разве реализация моего проекта была неправильной?

Должен ли я использовать SignalR для этой цели? Или я не должен использовать Session таким образом?

4b9b3361

Ответ 1

Вы не должны использовать Session with SignalR (см. SignalR не использует сеанс на сервере). Вы идентифицируете логические соединения по их идентификатору соединения, который вы можете сопоставить с именами пользователей.

Основная проблема заключается в том, что доступ к SessionState сериализуется в ASP.NET для обеспечения согласованности состояния, поэтому каждый запрос на концентратор блокирует другие запросы. Раньше ограниченный доступ только для чтения (я предполагаю (но не могу подтвердить, так как суть исчезла), установив EnableSessionstate только для чтения, который предотвращает описанную проблему блокировки), но поддержка для этого была удалена. Также см. различные другие места, где команда SignalR сделала аналогичные заявления. И наконец: в официальной документации о HTTPContext.Current.Session.

Ответ 2

Вы можете отправлять значения с клиентского сервера на сервер через Query String.

До метода $.connection.hub.start() вы можете добавить что-то вроде этого:

Клиентский код JS:

// Replace "some value" with the session value or anything you want
$.connection.hub.qs = { "Name": "some value" };

$.connection.hub.start()...bla bla bla

На стороне сервера на концентраторе вы можете использовать его любым способом:

string ClientValue= Context.QueryString["Name"].ToString();

Я не тестировал сеансы, но, конечно же, на стороне клиента вы могли быть такими же потрясающими, как можете.

Ответ 3

Я был в ситуации, когда я не мог использовать User/Identity, потому что сеанс еще не прошел проверку подлинности, поэтому я просто использовал фактическое значение cookie сеанса.

 [HubName("headerHub")]
 public class HeaderHub : Hub
 {
    static HeaderHub()
    {
        EventManager.CartUpdated += Update;
        EventManager.LoggedOut += Update;
        EventManager.LoggedIn += Update;
    }

    public override Task OnConnected()
    {
        var group = Context.Request.Cookies["ASP.NET_SessionId"].Value;
        Groups.Add(Context.ConnectionId, group);
        return base.OnConnected();
    }

    private static void Update(object sender, SessionEventArgs e)
    {
        var hubContext = GlobalHost.ConnectionManager.GetHubContext<HeaderHub>();
        hubContext.Clients.Group(e.SessionId).onUpdateHeader();
    }
}

Я уверен, что кто-то найдет что-то не так с этим решением, и если так, не стесняйтесь комментировать, потому что мне нужен лучший способ выполнить привязку сеанса к набору клиентов для уведомления.

Ответ 4

Один из лучших способов - использовать Cookie вместо сеанса. потому что, как упоминалось выше, вы не можете использовать сеанс. поэтому при входе пользователя в систему укажите свой уникальный идентификатор (например, имя пользователя) в cookie. затем работайте с файлом cookie, где бы вы ни хотели сеанса доступа. таких ниже...

  public class CustomUserIdProvider : IUserIdProvider
    {
        public string GetUserId(IRequest request)
        {
           return request.Cookies["ODPUserID"].Value;
        }
    }