【问题标题】:Inject IOwinContext with Web API and Ninject使用 Web API 和 Ninject 注入 IOwinContext
【发布时间】:2014-06-23 11:02:39
【问题描述】:

通过 Ninject 使用 Web API 2 和 OWIN 托管。

我想将当前的 IOwinContext 注入到某些服务中(这样我就可以在请求中获取委托人进行一些数据过滤)。

使用 Web 托管,在过去,我会简单地使用 HttpContext.Current,但这不是 OWIN 托管的选项(并且很好摆脱)。

This SO question 解释了如何使用 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 依赖范围,如果有人从 this 范围请求 IOwinContext,请给他们这个我已经拥有的实例。

注意

我确实知道我可以从控制器中获取当前上下文并将其传递,但​​这反而违背了我试图做的事情的目的;我希望我的 DbContext 了解用户是谁,以便它可以过滤数据。当然,一旦我能够获得 IOwinContext,我实际上不会将其传递给 DbContext,而是使用 ToMethod 或类似方法来提取 ClaimsPrincipal,但这超出了本问题的范围。

【问题讨论】:

    标签: asp.net-web-api ninject owin


    【解决方案1】:

    免责声明:这是一个 hack。它有效,但感觉很不干净。使用后果自负。

    本质上,您可以创建一个 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

    【讨论】:

    • 是时候切换注入框架了。 Autofac 没有这些技巧就可以做到这一点。
    猜你喜欢
    • 1970-01-01
    • 2018-10-19
    • 1970-01-01
    • 2018-08-23
    • 1970-01-01
    • 1970-01-01
    • 2014-01-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多