2015-03-23 1 views
0

У меня есть приложение, использующее SignalR & WebAPI. У меня есть настраиваемый контекст авторизации, основанный на токене, который я предоставляю каждому запросу SignalR с помощью QueryString.SignalR нацеливает определенного пользователя с сервера на пользовательский IUserIdProvider

Я реализую и IUserIdProvider, чтобы извлечь моего пользователя из токена.

И, наконец, я хочу вызвать клиентский метод с сервера, для конкретного пользователя (с идентификатором), я использую HubContext из GlobalHost.ConnectionManager.

Моя проблема заключается в том, что мой Пользователь никогда не найти из моего HubContext, но от самого концентратора ...

Вот моя реализация 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(); 
    } 
} 

Вот мой концентратор imlementation

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

У меня нет решения на данный момент, я не понимаю, что происходит, кто-то уже достиг этого?

+0

Что происходит, когда вы отлаживаете метод GetUserId? Является ли 'Scope' нулевым? – Jonny

+0

Все, что было бы хорошо в моем SignalRUserIdProvider, у меня всегда есть мой токен в QueryString и мой Id_User в области. Он находится в вызове GlobalHost.ConnectionManager, где Пользователь не найден и уведомление не отправлено. – jbuiss0n

ответ

1

Я, наконец, понял вопрос, но я не знаю, как это исправить ...

Действительная проблема проста, сама Hub имеет хороший контекст с клиентами и все, но GlobalHost.ConnectionManager не имеют ничего.

Если я изменить свой хаб на что-то вроде этого:

[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"); 
    } 
} 

Мой клиент получит «Мое послание от самого хаб», но никогда не получить «Мое послание от ConnectionManager».

В заключение, у меня проблема с моим ... Я внедрение зависимости я использую 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>(); 
+0

Почему это 'Notify (уведомление.Message +" из ConnectionManager ")', а не 'Notify (сообщение +" из ConnectionManager ")' – Wasp

+0

Простите, это просто плохая копия/вставка ... – jbuiss0n