2015-11-22 4 views
1

Я установил Ninject для работы с SignalR (размещенным на IIS), как описано в ответе на этот вопрос: SignalR 2 Dependency Injection with Ninject.Инъекция HttpContextBase с Ninject 3 и SignalR 2.0

Это работает в большинстве случаев, за исключением случаев, когда клиент отключается от концентратора. HttpContext.Current переменная null и, таким образом, Ninject не может вводить значение и выдает исключение.

Я прочитал эту проблему и выяснил, что большинство людей рекомендует, чтобы текущий HttpContext был получен из IRequest.GetHttpContext() (доступный из контекста концентраторов). К сожалению, это не помогает при попытке вставить значение (я мог бы передать контекст из концентратора, но это может привести к поражению цели инъекции зависимостей).

пример кода (некоторые части удалены для краткости):

public class TestHub : Hub 
{ 
    public TestHub(ITestService testService) 
    { 
     TestService = testService; 
    } 

    // When the disconnection request is issued, a ArgumentNullException 
    // for the HttpContext construction is thrown 
    public override Task OnDisconnected(bool stopCalled) 
    { 
     TestService.DoSomething(); 
    } 
} 

public class TestService : ITestService 
{ 
    public TestService(HttpContextBase httpContext) 
    { 
     HttpContext = httpContext; 
    } 

    public void DoSomething() 
    { 
     // Service uses some data from the httpContext 
     TestLogger.Log(HttpContext.User.Identity.Name); 
    } 
} 

Есть ли способ, чтобы ввести HttpContextBase в сферу услуг, которые в свою очередь, закачиваемой в SignalR концентраторы без доступа HttpContext.Current?

+0

как вы получить доступ к контексту концентраторы? – BatteryBackupUnit

+0

Я получаю доступ к контексту хабов через свойство 'Context' (типа' HubCallerContext'), находящееся в базовом классе 'Hub'. Затем это свойство предоставляет доступ к контексту http через «Context.Request.GetHttpContext()». – betelgewse

ответ

1

В случае HttpContext на самом деле доступны во время строительства, вы можете использовать следующие привязки:

kernel.Bind<HttpContextBase>() 
     .ToMethod(ctx => Context.Request.GetHttpContext()) 
     .WhenAnyAncestorMatches(ctx => typeof(Hub).IsAssignableFrom(ctx.Plan.Type)); 

The When условие проверяет ли HttpContextBase впрыскивается в Hub (или производный класс), или в какой-либо зависимости от Hub.

В случае, если HttpContextBase вводится только при монтаже Hub s, вы также можете просто отказаться от состояния When.

+1

Небольшое недоразумение: «Контекст» является свойством «быть установленным классом» TestHub, а не статическим свойством. Другими словами, это не так много, как вопрос Ninject, а скорее сигнал SignalR. Спасибо за все усилия. – betelgewse

+0

oh ok. Да, я бы сказал, что это больше связано с проблемой SignalR, чтобы получить доступ к контексту до создания «Hub». Я думаю, что контекст должен быть доступен до создания «Hub», но вопрос в том, как получить к нему доступ.Должен ли я оставить ответ - поскольку он показывает, по крайней мере, как сделать привязку для чего-то, введенного в «концентратор» или зависимости, который может быть использован для решения, как только вы узнаете, как получить доступ к контексту, или это будет неактуально? В этом случае я удалю ответ. – BatteryBackupUnit

+0

По-моему, оставьте его, он показывает вторую половину решения - после того, как будет найден контекст концентратора. – betelgewse

0

Я сейчас работал над проблемой, и, таким образом, это не решение проблемы, а нечистый способ ее смягчить.

Поскольку отсутствующие HttpContext происходит только на клиентских разъединителях, я первым из всех моих инъецируемых услуг был отмечен как Lazy<T>, поэтому они не сразу разрешаются, но только при их доступе. После применения этого изменения исключения выбрасываются только при срабатывании кода в событии SignalR OnDisconnected хаба. Поэтому мне пришлось изменить код, который выполняется в методе OnDisconnected для использования (или передачи в качестве параметра) контекста, полученного непосредственно из концентратора. В моем случае не так много кода выполняется там, но это может стать проблемой, если в будущем потребуется больше.

Патч применяется к коду образца от моего вопроса:

public class TestHub : Hub 
{ 
    public TestHub(Lazy<ITestService> testService) 
    { 
     TestService = testService; 
    } 

    public override Task OnDisconnected(bool stopCalled) 
    { 
     DoSomethingThatInvolvesHttpContext(Context.Request.GetHttpContext()); 
    } 
} 
Смежные вопросы