用Web API和Ninject注入IOwinContext

使用Web API 2和OWIN与Ninject进行托管。

我想将当前的IOwinContext注入到某些服务中(这样我就可以获得请求,让主体执行一些数据过滤)。

随着虚拟主机,我会,在过去,只是简单地使用HttpContext.Current,但这不是OWIN托管(和好消息)的选项。

这个SO问题解释了如何用Autofac做到这一点。 本质上,你创建一个依赖范围,然后在每个请求中调用Autofac的Registerinstance来将当前的IOwinContext注册到该依赖范围中,如下所示:

app.Use(async (ctx, next) =>
{
    // this creates a per-request, disposable scope
    using (var scope = container.BeginLifetimeScope(b =>
    {
        // this makes owin context resolvable in the scope
        b.RegisterInstance(ctx).As<IOwinContext>();
    }))
    {
        // this makes scope available for downstream frameworks
        ctx.Set<ILifetimeScope>("idsrv:AutofacScope", scope);
        await next();
    }
}); 

这非常优雅。 有了Ninject和Ninject.Web.WebApi.OwinHosting,我已经为每个请求获得了一个命名范围,因此管理工作已经完成。 但是,我还没有找到任何方法在ninject中镜像AutoFac的RegisterInstance方法:这里的关键是这个绑定仅在这个特定的依赖范围内有效。

我已经阅读了Scope的各种选项,但是我发现的所有东西都依赖于能够声明常量或ToMethod。 我在这里要做的是说,“好吧,我现在有一个ninject依赖范围,如果有人从这个范围请求IOwinContext,给他们这个我已经拥有的实例。

注意

我明白我可以从我的控制器中获取当前上下文并传递它,但这相当于打破了我尝试做的目的; 我希望我的DbContext能够理解用户是谁,因此可以过滤数据。 而且,当然,一旦我可以获得IOwinContext,我实际上不会将它传递给DbContext,而是使用ToMethod或类似方法来提取ClaimsPrincipal,但超出了此问题的范围。


免责声明:这是一个黑客。 它有效,但感觉非常不洁。 在你的危险中使用。

本质上,您可以创建一个OwinContextHolder类,将其绑定到InRequestScope中,并使用DelegatingHandler将其填充到每个请求上。 像这样的东西:

public class OwinContextHolder
{
    public IOwinContext OwinContext { get; set; }
}

public class OwinContextHolderModule : NinjectModule
{
    public override void Load()
    {
        // Instead of a NinjectModule you can of course just register the service
        this.Kernel.Bind<OwinContextHolder>().ToSelf().InRequestScope();
    }
}

您的委托处理程序:

public class SetOwinContextHandler : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var holder = request.GetDependencyScope().GetService(typeof(OwinContextHolder)) as OwinContextHolder;
        if (holder != null)
        {
            holder.OwinContext = request.GetOwinContext();
        }
        return base.SendAsync(request, cancellationToken);
    }
}

最后将DelegatingHandler添加到Startup类中:

public void Configuration(IAppBuilder app)
{
    var webApiConfiguration = new HttpConfiguration();
    webApiConfiguration.Routes.MapHttpRoute(...);

    webApiConfiguration.MessageHandlers.Add(new SetOwinContextHandler());

    app.UseNinjectMiddleware(CreateKernel);
    app.UseNinjectWebApi(webApiConfiguration);
}

你现在可以将OwinContextHolder注入到你的类中。

请注意,如果您将API用于与主机分开的组件中,那么InRequestScope可能会遇到问题,并且无法正常工作(例如,每次请求一个错误时都会得到一个不同的对象)。 如果是这样,请参阅https://groups.google.com/forum/#!topic/ninject/Wmy83BhhFz8。

链接地址: http://www.djcxy.com/p/20189.html

上一篇: Inject IOwinContext with Web API and Ninject

下一篇: Deep Learning Neural Networks for Time Series Prediction