27

I understand why SignalR doesn't give you access to the HttpContext. However, this is quite problematic for us. Let me explain:

Our application is a Multi-Tenant application where the user chooses the environment while logging in. This basically registers the ConnectionStringName in the HttpSession. In our SignalR Hub, we need to access the database on Disconnect. But this is not possible because we have no HttpContext at this point and cannot determine the environment to write to.

Can anyone provide us with a suggestion how to solve this problem? We're a bit stuck on this one.

EDIT: Bonus point if your solution works in a Load-Balanced environment.

Community
  • 1
  • 1
Lodewijk
  • 2,380
  • 4
  • 25
  • 40

5 Answers5

28

This is an old question, but I'm leaving my answer just in case it is helpful to anyone out there.

Since your hub extends Microsoft.AspNet.SignalR.Hub it has access to the Context property of type HubCallerContext

This property exposes a lot of information from the caller:

  • ConnectionId
  • Headers
  • QueryString
  • Request
  • Cookies
  • User

In my solution I use the username stored in Context.User.Identity.Name as a key in my key/value store (Redis in my case) to keep track of all the connections a user has.

You can override OnConnnect and OnDisconnect to maintain the list of connections associated to the user. You can also store anything else you want along with the connections ids (your user connection strings, in your case).

Raciel R.
  • 2,136
  • 20
  • 27
  • 5
    Unfortunately caching based on user name does not work if the user has multiple sessions open... – Dave Sep 17 '13 at 02:39
  • I had similar problem here: http://stackoverflow.com/questions/27729113/null-exception-on-httpcontext-current-request-cookies-when-firing-signalr-method. This thread saved me from pulling my hair out. I have fixed my problem but i don't truly understand the problem. If any one could head over and give me a solid answer that would be great! I hate moving on without fully understanding it. – Tez Wingfield Jan 01 '15 at 20:06
  • 1
    @dave I still don't see the problem with having mutliple signalR connections sessions but maintaining state using as suggested. – eaglei22 May 30 '17 at 17:41
14

If you're using ASP.NET Core SignalR 3.0 (not ASP.NET SignalR 2.1) then you can use Context.GetHttpContext() into get the HttpContext.

FYI, Signalr 3.0 no longer has the Context.Request object. The Request context can be reached by accessing the IHttpContextFeature in Context.Features[]. I used the following:

IHttpContextFeature  hcf           = (IHttpContextFeature)this.Context.Features[typeof(IHttpContextFeature)];
HttpContext          hc            = hcf.HttpContext;
string               myCookieValue = hc.Request.Cookies["Value"];

This could probably use some null checks or could be cleaner, but hopefully this saves someone some time.

Dai
  • 141,631
  • 28
  • 261
  • 374
R. Hargrove
  • 141
  • 1
  • 2
12

Hi had a similar problem as I needed to identify non-authenticated visitors to my application to personalise their requests to the SignalR hub.

I have solved it by accessing "HttpContext.Current.Request.AnonymousId". The AnonymousId maps to a temporary record in a self-implemented Session-entity in a SQL database - essentially emulating a database-backed session.

Here some relevant documentation in case you wish to customize the AnonymousId, or initialise the database-entry: http://msdn.microsoft.com/en-us/library/system.web.httprequest.anonymousid.aspx

Moreover, you should be able to access the Context in OnDisconnected() like this: Context.Request.GetHttpContext().

I hope this helps.

JDR
  • 1,094
  • 1
  • 11
  • 31
0

You can use something like a Dictionary to keep track of the ConnectionId of the user when they connect. Also using SQL Server to store the Session State may also help : http://support.microsoft.com/kb/317604

SignalR does give you access to User.Identity.Name which you can use to track when the disoconnect() is fired.

Steve
  • 2,988
  • 2
  • 30
  • 47
  • Sadly, the User info is not available: "..as well as the HubContext's User and Cookies will not be populated." (https://github.com/SignalR/SignalR/wiki/Hubs) – Lodewijk Sep 18 '12 at 08:46
  • Also, we're in a load-balanced environment, so the disconnect could end up on the other server where the dictionary is not populated. – Lodewijk Sep 18 '12 at 08:48
  • I have looked at some previous code and Context.User.Identity.Name does show the current logged in user. If the environment is load balanced, you should maybe look at redis for SignalR. https://github.com/SignalR/SignalR/wiki/SignalR-with-Redis-Running-on-a-Windows-Azure-Virtual-Machine – Steve Sep 18 '12 at 09:00
  • I meant that the User info will not be populated on Disconnect. I'm relying on the docs for this. Haven't actually spiked it. – Lodewijk Sep 19 '12 at 09:30
0

The fact that you need your solution to be working on a load balanced environment enforces the fact that you need to store your connection string in something different from Session. A key-value store (how do you implement it does not matter) where the key is the ConnectionId (the only info available on disconnect) and the value is the connection string. You can keep on using Session in any other place if you want, but I think you should move the whole application to write and read from there, at least for that info.

Wasp
  • 3,395
  • 19
  • 37
  • Session state is no problem in a load balanced environment, and hasn't been for at least a decade. – Tor Haugen Apr 16 '13 at 12:09
  • Read better the question before down voting, HttpContext is not available with SignalR (or at least was not at that time), and with that Session – Wasp Apr 16 '13 at 12:39
  • 1
    Actually HttpContext and HttpContext.Current are both available and it is only Session that is null. – Dave Sep 17 '13 at 02:54
  • 1
    That's true right now, I'm pretty sure the whole HttpContext was not available at the time of the question (one year ago, SignalR 0.5), but it's a good point to add to make the discussion actual, thanks :) – Wasp Sep 17 '13 at 06:24