注射IOwinContext使用Web API和Ninject [英] Inject IOwinContext with Web API and Ninject

查看:381
本文介绍了注射IOwinContext使用Web API和Ninject的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Using Web API 2 and OWIN hosting with Ninject.

我想目前IOwinContext注入到特定服务(这样我就可以在申请到获得主要做一些数据过滤)。

I would like to inject the current IOwinContext into certain services (so I can get at the Request to get the principal to do some data filtering).

使用虚拟主机我想,在旧时代,根本就用HttpContext.Current但不是与OWIN托管(真是谢天谢地)的选项。

With Web Hosting I would, in the old days, simply have used HttpContext.Current but that is not an option with OWIN hosting (and good riddance).

<一个href=\"http://stackoverflow.com/questions/21703268/resolving-iowincontext-in-mvc5-application-using-autofac\">This SO质疑介绍如何使用Autofac做到这一点。从本质上讲,创建一个依赖的范围,然后,对每个请求,调用Autofac的Registerinstance到目前IOwinContext注册成依赖范围,像这样:

This SO question explains how to do it with Autofac. Essentially, you create a Dependency Scope and then, on each request, calls Autofac's Registerinstance to register the current IOwinContext into that dependency scope like so:

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方法:这里的关键是,这种结合是只有这个特定的依赖范围内有效。

That is very elegant. With Ninject and the Ninject.Web.WebApi.OwinHosting I already get a named scope for each request so that plumbing is taken care of. However, I haven't been able to find any way in ninject to mirror AutoFac's RegisterInstance method: The key here is that this binding is only valid within this particular dependency scope.

我读到了关于我发现周围的适用范围,但一切的各种方案依赖于能够申报常量或ToMethod。我所希望做的,是在说:没关系,我现在有一个ninject依赖范围,如果任何人要求的IOwinContext的这个的范围,给他们这种情况下,我已经拥有。

I have read up on the various options around Scope but everything I have found relies on being able to declare constants or ToMethod. What I am looking to do here is to say, "okay, I now have a ninject dependency scope and if anyone asks for an IOwinContext from this scope, give them this instance that I already have.

我不明白,我可以从我的控制器中获取当前上下文,并通过它,但宁可违背了什么,我试图做的目的;我希望我的DbContext了解用户,因此它可以过滤数据谁。而且,当然,一旦我能得到我IOwinContext实际上不会传递到的DbContext,而我会用一个ToMethod或类似的提取ClaimsPrincipal但就是出于这个问题的范围。

I do understand that I can get the current context from within my controller and pass it on, but that rather defeats the purpose of what I am trying to do; I want my DbContext to understand who the user is so it can filter the data. And, of course, once I can get the IOwinContext I won't actually pass that to the DbContext, rather I will use a ToMethod or similar to extract the ClaimsPrincipal but that is out of scope of this question.

推荐答案

免责声明:这是一个黑客。它的工作原理,但感觉很污秽。使用后果自负。

DISCLAIMER: This is a hack. It works, but it feels very unclean. Use at your peril.

在本质上,你可以创建一个OwinContextHolder级,将其绑定InRequestScope并使用DelegatingHandler来填充它的每个请求。事情是这样的:

In essence, you can create an OwinContextHolder class, bind it InRequestScope and use a DelegatingHandler to populate it on each request. Something like this:

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添加到您的启动类:

Finally add the DelegatingHandler to your Startup class:

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

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

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

您现在可以注入OwinContextHolder到您的类。

You can now inject OwinContextHolder into your classes.

请注意,如果你有从您的主机一个单独的程序你的API,你可能有InRequestScope默默不工作的问题(如,你每次请求一个没有错误的时间得到不同的对象)。如果你这样做,请参见 https://groups.google.com/forum/#​​!专题/ ninject / Wmy83BhhFz8

Note that if you have your API in a separate assembly from your host, you may have problems with InRequestScope silently not working (as in, you get a different object every time you request one and no errors). If you do, see https://groups.google.com/forum/#!topic/ninject/Wmy83BhhFz8.

这篇关于注射IOwinContext使用Web API和Ninject的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆