No access to the Session information through SignalR Hub. Is my design is wrong?
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?
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
.
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.
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.
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;
}
}