SignalR and HttpContext/Session

2020-06-08 06:04发布

问题:

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.

回答1:

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).



回答2:

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.



回答3:

Apparently you can use Context.GetHttpContext() in 3.0 to 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:

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

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



回答4:

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.



回答5:

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.