2016-06-08 5 views
0

У меня есть приложение mvc/webapi, которое я пытаюсь получить пользовательскую фабричную привязку с ninject. Мне нужно иметь доступ к HttpContext, из моего понимания, мне нужно иметь пользовательскую фабрику, чтобы использовать это.Создание фабрики с ninject для привязки HttpContextBase не получает ожидаемых значений

Так что я

public interface IHttpContextFactory 
{ 
    HttpContextBase Create(); 
} 

public class HttpContextFactory:IHttpContextFactory 
{ 
    private readonly HttpContextWrapper _httpContext; 

    public HttpContextFactory(HttpContextWrapper contextWrapper) 
    { 
     _httpContext = contextWrapper; 
    } 

    public virtual HttpContextBase Create() 
    { 
     return _httpContext; 
    } 
} 

Я пытаюсь использовать завод в службе через

public class ApplicationService:IApplicationService 
{ 
    private readonly ILog _log; 
    private readonly IHttpContextFactory _contextFactory; 

    public ApplicationService(ILog log,IHttpContextFactory contextFactory) 
    { 
     _log = log; 
     _contextFactory = contextFactory; 
     if (_httpContextService == null) 
     { 
      throw new ArgumentNullException("httpContextService"); 
     } 
     if (_log == null) 
     { 
      throw new ArgumentNullException("log"); 
     } 
    } 

    public virtual string GetControllerName() 
    { 
     var factory = _contextFactory.Create(); 
     var controllerName = factory.Request.RequestContext.RouteData.Values["controller"].ToString(); 
     return controllerName; 

    } 
} 

Мой Ninject связывающими выглядит как

public static class NinjectWebCommon 
{ 
    private static readonly Bootstrapper bootstrapper = new Bootstrapper(); 

    /// <summary> 
    /// Starts the application 
    /// </summary> 
    public static void Start() 
    { 
     DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule)); 
     DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule)); 
     bootstrapper.Initialize(CreateKernel); 
    } 

    /// <summary> 
    /// Stops the application. 
    /// </summary> 
    public static void Stop() 
    { 
     bootstrapper.ShutDown(); 
    } 

    /// <summary> 
    /// Creates the kernel that will manage your application. 
    /// </summary> 
    /// <returns>The created kernel.</returns> 
    private static IKernel CreateKernel() 
    { 
     var kernel = new StandardKernel(); 
     //Instruct the Kernel to rebind the HttpConfiguration to the default config instance provided from the GlobalConfiguration 
     kernel.Rebind<HttpConfiguration>().ToMethod(context => GlobalConfiguration.Configuration); 

     try 
     { 
      kernel.Bind<Func<IKernel>>().ToMethod(ctx =>() => new Bootstrapper().Kernel); 
      kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>(); 

      RegisterServices(kernel); 
      return kernel; 
     } 
     catch 
     { 
      kernel.Dispose(); 
      throw; 
     } 
    } 

    /// <summary> 
    /// Load your modules or register your services here! 
    /// </summary> 
    /// <param name="kernel">The kernel.</param> 
    private static void RegisterServices(IKernel kernel) 
    { 
     kernel.Bind<IApplicationService>().To<ApplicationService>(); 
     kernel.Bind<IHttpContextFactory>() 
      .To<HttpContextFactory>().WithConstructorArgument("contextWrapper",ninjectContext=> new HttpContextWrapper(HttpContext.Current)); 

    }   
} 

Однако, если я ставлю точку останова на GetControllerName контроллер недоступен в пределах RouteData.Values.

Почему это так?

+0

Что произойдет, если вы используете HTTPContext.Current напрямую? –

ответ

0

HttpContext не доступен, когда вызывается конструктор контроллера. Это наиболее вероятно, когда вы вызываете делегата конструктора.

Вам нужно будет перестроить свою фабрику, чтобы получить контекст позже в потоке вызова. Это очень похоже на IHttpContextAccessor введенный в asp.net-ядра

public interface IHttpContextAccessor { 
    HttpContextBase HttpContext { get; } 
} 

public class HttpContextProvider : IHttpContextAccessor { 
    private Lazy<HttpContextWrapper> _httpContext; 

    public HttpContextProvider() { 
     _httpContext = 
     new Lazy<HttpContextWrapper>(() => new HttpContextWrapper(HttpContext.Current)); 
    } 

    public virtual HttpContextBase HttpContext { 
     get { 
      return _httpContext.Value; 
     } 
    } 
} 

Вы регистрируете его, как вы это обычно

kernel.Bind<IHttpContextAccessor>().To<HttpContextProvider>(); 

И получить контекст, когда это необходимо.

public class ApplicationService : IApplicationService { 
    private readonly ILog log; 
    private readonly IHttpContextAccessor httpContextProvider; 

    public ApplicationService(ILog log, IHttpContextAccessor httpContextProvider) { 
     this.log = log; 
     this.httpContextProvider = httpContextProvider; 
     if (httpContextProvider == null) { 
      throw new ArgumentNullException("httpContextProvider"); 
     } 
     if (log == null) { 
      throw new ArgumentNullException("log"); 
     } 
    } 

    public virtual string GetControllerName() { 
     var httpContext = httpContextProvider.HttpContext; 
     var controllerName = httpContext.Request.RequestContext.RouteData.Values["controller"].ToString(); 
     return controllerName; 
    } 
}