SignalR 使用自定义 IUserIdProvider 从服务器定位特定用户
SignalR target a specific user from server with custom IUserIdProvider
我有一个使用 SignalR 和 WebAPI 的应用程序。我有一个基于令牌的自定义授权上下文,我使用 QueryString 在每个 SignalR 请求上提供该令牌。
我已经实施 IUserIdProvider
,以便从令牌中检索我的用户。
最后,我想从服务器调用客户端方法,对于特定用户(带有 is ID),我正在使用来自 GlobalHost.ConnectionManager
.
的 HubContext
我的问题是我的用户永远无法从我的 HubContext 中找到,但它来自 Hub 本身...
这是我的 IUserIdProvider 实现
public class SignalRUserIdProvider : IUserIdProvider
{
public string GetUserId(IRequest request)
{
var token = request.QueryString["token"];
var scope = GetUnprotectedScope(token);
if (scope == null)
return null;
return scope.Id_User.ToString();
}
}
这是我的 Hub 实现
[HubName("notifier")]
public class NotifierHub : Hub
{
public void Notify(string message)
{
Clients.User("1").Notify(message); //When call from a client, this works very well, only the User with the Id = 1 receive the notification
}
}
最后,我使用它从我的服务器调用客户端方法:
GlobalHost
.ConnectionManager
.GetHubContext<NotifierHub>()
.Clients
.User("1")
.Notify(notification.Message);
// This does nothing...
我现在无法解决,我不明白会发生什么,有人已经实现了吗?
我终于解决了这个问题,但我不知道如何解决...
实际问题很简单,Hub
本身与客户和一切都有很好的背景,但GlobalHost.ConnectionManager
什么都没有。
如果我将 Hub 更改为如下所示:
[HubName("notifier")]
public class NotifierHub : Hub
{
public void Notify(string message)
{
Clients.User("1").Notify(message + " from Hub itself");
GlobalHost
.ConnectionManager
.GetHubContext<NotifierHub>()
.Clients
.User("1")
.Notify(message + " from ConnectionManager");
}
}
我的客户收到 "My message from Hub itself",但从未收到 "My message from ConnectionManager"。
总之,我的 DependencyInjection 有问题...我正在使用 Structuremap 和这个 DependencyResover :
public class StructureMapSignalRDependencyResolver : DefaultDependencyResolver
{
private IContainer _container;
public StructureMapSignalRDependencyResolver(IContainer container)
{
_container = container;
}
public override object GetService(Type serviceType)
{
if (serviceType == null)
return null;
var service = _container.TryGetInstance(serviceType) ?? base.GetService(serviceType);
if (service != null) return service;
return (!serviceType.IsAbstract && !serviceType.IsInterface && serviceType.IsClass)
? _container.GetInstance(serviceType)
: _container.TryGetInstance(serviceType);
}
public override IEnumerable<object> GetServices(Type serviceType)
{
var objects = _container.GetAllInstances(serviceType).Cast<object>();
return objects.Concat(base.GetServices(serviceType));
}
}
我的启动文件:
public void Configuration(IAppBuilder app)
{
app.Map("/signalr", RegisterSignalR);
}
public static void RegisterSignalR(IAppBuilder map)
{
var resolver = new StructureMapSignalRDependencyResolver(IoC.Initialize());
var config = new HubConfiguration { Resolver = resolver };
map.UseCors(CorsOptions.AllowAll);
map.RunSignalR(config);
}
最后是我的注册表...
For<Microsoft.AspNet.SignalR.IDependencyResolver>().Add<StructureMapSignalRDependencyResolver>();
For<INotifier>().Use<SignalRNotifier>();
我有一个使用 SignalR 和 WebAPI 的应用程序。我有一个基于令牌的自定义授权上下文,我使用 QueryString 在每个 SignalR 请求上提供该令牌。
我已经实施 IUserIdProvider
,以便从令牌中检索我的用户。
最后,我想从服务器调用客户端方法,对于特定用户(带有 is ID),我正在使用来自 GlobalHost.ConnectionManager
.
我的问题是我的用户永远无法从我的 HubContext 中找到,但它来自 Hub 本身...
这是我的 IUserIdProvider 实现
public class SignalRUserIdProvider : IUserIdProvider
{
public string GetUserId(IRequest request)
{
var token = request.QueryString["token"];
var scope = GetUnprotectedScope(token);
if (scope == null)
return null;
return scope.Id_User.ToString();
}
}
这是我的 Hub 实现
[HubName("notifier")]
public class NotifierHub : Hub
{
public void Notify(string message)
{
Clients.User("1").Notify(message); //When call from a client, this works very well, only the User with the Id = 1 receive the notification
}
}
最后,我使用它从我的服务器调用客户端方法:
GlobalHost
.ConnectionManager
.GetHubContext<NotifierHub>()
.Clients
.User("1")
.Notify(notification.Message);
// This does nothing...
我现在无法解决,我不明白会发生什么,有人已经实现了吗?
我终于解决了这个问题,但我不知道如何解决...
实际问题很简单,Hub
本身与客户和一切都有很好的背景,但GlobalHost.ConnectionManager
什么都没有。
如果我将 Hub 更改为如下所示:
[HubName("notifier")]
public class NotifierHub : Hub
{
public void Notify(string message)
{
Clients.User("1").Notify(message + " from Hub itself");
GlobalHost
.ConnectionManager
.GetHubContext<NotifierHub>()
.Clients
.User("1")
.Notify(message + " from ConnectionManager");
}
}
我的客户收到 "My message from Hub itself",但从未收到 "My message from ConnectionManager"。
总之,我的 DependencyInjection 有问题...我正在使用 Structuremap 和这个 DependencyResover :
public class StructureMapSignalRDependencyResolver : DefaultDependencyResolver
{
private IContainer _container;
public StructureMapSignalRDependencyResolver(IContainer container)
{
_container = container;
}
public override object GetService(Type serviceType)
{
if (serviceType == null)
return null;
var service = _container.TryGetInstance(serviceType) ?? base.GetService(serviceType);
if (service != null) return service;
return (!serviceType.IsAbstract && !serviceType.IsInterface && serviceType.IsClass)
? _container.GetInstance(serviceType)
: _container.TryGetInstance(serviceType);
}
public override IEnumerable<object> GetServices(Type serviceType)
{
var objects = _container.GetAllInstances(serviceType).Cast<object>();
return objects.Concat(base.GetServices(serviceType));
}
}
我的启动文件:
public void Configuration(IAppBuilder app)
{
app.Map("/signalr", RegisterSignalR);
}
public static void RegisterSignalR(IAppBuilder map)
{
var resolver = new StructureMapSignalRDependencyResolver(IoC.Initialize());
var config = new HubConfiguration { Resolver = resolver };
map.UseCors(CorsOptions.AllowAll);
map.RunSignalR(config);
}
最后是我的注册表...
For<Microsoft.AspNet.SignalR.IDependencyResolver>().Add<StructureMapSignalRDependencyResolver>();
For<INotifier>().Use<SignalRNotifier>();