注射IOwinContext使用Web API和Ninject [英] Inject IOwinContext with Web API and 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屋!