23

I've just discovered you can't access the current session within the SignalR Hub.

Simplified my scenario: I've tried to write a chat.

The name of the current user was kept within the Session.

I've used SignalR to update (a group of connections) about every new message.

Now I see that I can't access the name of the current user through the hub.

I guess there might be some workarounds, but is that implement my design was wrong?

Should I've not used SignalR for that purpose? Or should I not use Session in this way?

Letterman
  • 4,076
  • 5
  • 29
  • 41

4 Answers4

29

You shouldn't use Session with SignalR (see SignalR doesn't use Session on server). You identify logical connections by their connection id which you can map to user names.

The underlying problem is that access to SessionState is serialized in ASP.NET to ensure state consistency, so each request to the hub would block other requests. In the past, limited read-only access (I assume (but can't confirm since the gist is gone) by setting EnableSessionstate to read-only, which prevents the locking problem I described) was possible, but support for this was dropped. Also see various other places where the SignalR team made similar statements. Lastly: there's a statement in the official documentation about HTTPContext.Current.Session.

Community
  • 1
  • 1
Lars Höppner
  • 18,252
  • 2
  • 45
  • 73
  • But I already have some information within the session, from normal requests. Should I not use session *at all* ? – Letterman Dec 11 '13 at 16:58
  • 1
    No, you shouldn't use it at all with SignalR. You'll need to find another way of sharing the necessary data - either cache it server-side with your user data, pass it into your hub methods or [set state on your hub](http://www.asp.net/signalr/overview/signalr-20/hubs-api/hubs-api-guide-server), depending on the nature of the data. – Lars Höppner Dec 11 '13 at 18:10
  • Thanks!.. Not disrespecting your knowledge, but can you please give some reference to that? I just want to be sure – Letterman Dec 11 '13 at 19:33
  • 2
    @Letterman I added more detail to my answer, as well as a few links – Lars Höppner Dec 11 '13 at 21:57
  • @LarsHöppner So am I right to assume the 'correct' way to handle this is keeping connectionID's in session? – Alexander Derck Jan 24 '17 at 08:24
14

You could send values from client to server hub via Query String.

Before the $.connection.hub.start() method you could add something like this:

Client JS Code:

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

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

On the server side on the Hub you could use this in any method:

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

I did not test with sessions, but of course on client side you could be as awesome as you can.

Tasos K.
  • 7,979
  • 7
  • 39
  • 63
Luis Villarroel
  • 141
  • 1
  • 3
2

I was in a situation where I couldn't use the User/Identity because the session hadn't been authenticated yet so I just used the actual session cookie value.

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

I am sure someone will find something wrong with this solution and if so feel free to comment because I would like a better way to accomplish tying a session to a set of clients to notify.

Merritt
  • 2,333
  • 21
  • 23
  • I m new to SignalR, I m also in situation where I need to identify SignalR clients based on some custom id where I thought of using ASP.Net session id. I m also interested in knowing if there is any flaw in these design. Will try out this now :) – Shaggy Nov 23 '16 at 11:29
  • I tried to do this but I found that the session ID kept on changing for every request. The session ID isn't persisted until the session is accessed (IE data is stored for the user) [This answer explains why](https://stackoverflow.com/a/2874174/894792). – Luke Dec 28 '17 at 11:35
1

One the best approach is to use Cookie instead of session. because as mentioned above , You can not use session . so When user login to your system, put its unique identifier(such as username) in cookie . then work with cookie where ever you want access session . such below...

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