No access to the Session information through SignalR Hub. Is my design is wrong?
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
.
How to pass data to Signalr hub class
You can't use session in Signalr hub class, see this link
No access to the Session information through SignalR Hub. Is my design is wrong?
There are some solutions to your problem. You can use Standard ASP.NET security to store your global information.
You can store the data you want using this code
FormsAuthentication.SetAuthCookie("string contain your data", false);
and you can retrieve your data using this code
string GlobalData = Context.User.Identity.Name;
SignalR doesn't use Session on server
SignalR connections (including the connection underlying all Hub operations for a client) do not support Session state. You could enable it if you wanted to but we'd strongly recommend against it as session state access serializes requests for a given client, meaning you won't really get the benefit from SignalR duplex messaging anymore, as one request will block the other e.g. in the long polling transport, the receiving connection will block any attempt to send.
Safe way to send session based data to SignalR Hub
I just posted a gist on how to use readonly sessions with SignalR. https://gist.github.com/4692934
Provide user information from signalr request in business logic layer using autofac
Session is not supported by SignalR by default and you should avoid using it. See No access to the Session information through SignalR Hub. Is my design is wrong?. But you still can use cookie or querystring to get the desired value.
In both case you need to have access to the HubCallerContext
of the underlying hub, the one that is accessible through the Context
property of the Hub
.
In a ideal word you should just have to had the dependency to the SignalAuthorizationProvider
ie :
public class SignalrAuthorizationProvider {
public SignalrAuthorizationProvider(HubCallerContext context){
this._context = context;
}
private readonly HubCallerContext _context;
public long? GetUserId() {
return this._context.Request.QueryString["UserId"]
}
}
But due to SignalR design it is not possible. Context
property is assigned after construction of the Hub and AFAIK there is no way to change it.
Source code here : HubDispatcher.cs
One possible solution would be to inject a mutable dependency inside the Hub
and alter the object in the OnConnected
, OnReconnected
methods.
public class SignalrAuthorizationProvider : IAuthorizationProvider
{
private Boolean _isInitialized;
private String _userId;
public String UserId
{
get
{
if (!_isInitialized)
{
throw new Exception("SignalR hack not initialized");
}
return this._userId;
}
}
public void OnConnected(HubCallerContext context)
{
this.Initialize(context);
}
public void OnReconnected(HubCallerContext context)
{
this.Initialize(context);
}
private void Initialize(HubCallerContext context) {
this._userId = context.QueryString["UserId"];
this._isInitialized = true;
}
}
and the Hub
public abstract class CustomHub : Hub
{
public CustomHub(IAuthorizationProvider authorizationProvider)
{
this._authorizationProvider = authorizationProvider;
}
private readonly IAuthorizationProvider _authorizationProvider;
public override Task OnConnected()
{
this._authorizationProvider.OnConnected(this.Context);
return base.OnConnected();
}
public override Task OnReconnected()
{
this._authorizationProvider.OnReconnected(this.Context);
return base.OnReconnected();
}
}
Having a mutable dependency is not the best design but I can't see any other way to have access to IRequest
or HubCallerContext
.
Instead of having an abstract Hub
class which is not a perfect solution. You can change the RegisterHubs
autofac method to use AOP with Castle.Core
and let the interceptor calls the methods for you.
Related Topics
Access Visual Studio 2017's Private Registry Hive
There Is No Viewdata Item of Type 'Ienumerable<Selectlistitem>' That Has the Key Country
Convert String Value to Operator in C#
Using Sse in C# Is It Possible
How to Use Extension Methods and Linq in .Net 2.0 or 3.0
Is There a Quick Way to Get the Control That's Under the Mouse
Webclient Does Not Support Concurrent I/O Operations
What Thread Runs the Code After the 'Await' Keyword
Linq to Objects - Return Pairs of Numbers from List of Numbers
Multicast Delegate of Type Func (With Return Value)
Directoryinfo.Enumeratefiles(...) Causes Unauthorizedaccessexception (And Other Exceptions)
How to Implement Inotifypropertychanged in C# 6.0
C#: Cast to Generic Interface with Base Type
Dynamically Cross-Join Multiple Different-Size Collections Together in Linq (C#)
How to Apply Indenting Serialization Only to Some Properties
Open File in Exclusive Mode in C#
How to Use Xpath Function in a Xpathexpression Instance Programatically