I have a lot of code that depends on HttpContext.Current,
and I noticed that requests that come from SignalR hubs have HttpContext.Current == null
,
so my code breaks, for example:
HttpContext.Current.Request.IsAuthenticated
So I came up with following:
public static class UnifiedHttpContext
{
private static HubCallerContext SignalRContext { get; set; }
private static int SignalRUserId
{
get { return WebSecurity.GetUserId(SignalRContext.User.Identity.Name); }
}
private static bool IsSignalRRequest
{
get { return SignalRContext != null; }
}
public static void SetSignalRContext(HubCallerContext context)
{
SignalRContext = context;
}
public static bool IsAuthenticated
{
get
{
if (!IsSignalRRequest)
{
return System.Web.HttpContext.Current.Request.IsAuthenticated;
}
else
{
return SignalRContext.User.Identity.IsAuthenticated;
}
}
}
public static int UserId
{
get
{
if (!IsSignalRRequest)
{
return WebSecurity.CurrentUserId;
}
else
{
return SignalRUserId;
}
}
}
}
And in master hub (every other hub inherits from it):
public abstract class MainHub : Hub
{
public override Task OnConnected()
{
UnifiedHttpContext.SetSignalRContext(Context);
Groups.Add(Context.ConnectionId, UnifiedHttpContext.UserId.ToString());
return base.OnConnected();
}
}
Is this correct approach, or is this solved somehow already that I'm not aware of?
Is this dangerous since static classes are shared in application, would this set same context for all users? If so can I make it per request?
Just spent a couple of hours on this problem.
It looks like there is no way to get SignalR context outside of hub class in the same manner like you would do this with HttpContext:
or inside Ninject context:
At least the answer to this question states so: Get SignalR User (Hub.Context) outside of hub.
But in this particular case when you need to get current user identity there is a solution which works in both worlds: WebApi/MVC and SignalR.
I used this to get user identity inside my dependency injection code.
Morover, Context property is only available in hub methods (it is null inside hub constructor). But
Thread.CurrentPrincipal.Identity
will give you the user identity even inside hub constructor.SignalR gives you access to
HubCallerContex
instead ofHttpContext
. You can access HubCallerContext object by using keywordcontext
. If you want to accessHttpContext
you can fetch it from the context as follows:Hope this helps.