通过 Ninject 使用 Web API 2 和 OWIN 托管。
我想将当前的 IOwinContext 注入(inject)到某些服务中(这样我就可以获取请求以让主体进行一些数据过滤)。
在过去,对于虚拟主机,我只会使用 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 方法:这里的关键是这个绑定(bind)仅在这个特定的依赖范围内有效。
我已经阅读了有关 Scope 的各种选项,但我发现的所有内容都依赖于能够声明常量或 ToMethod。我在这里想做的是说,“好吧,我现在有一个 ninject 依赖范围,如果有人从 this 范围请求 IOwinContext,请给他们我已经拥有的这个实例。
注意
我确实明白我可以从 Controller 中获取当前上下文并将其传递,但这违背了我想要做的事情的目的;我希望我的 DbContext 了解用户是谁,以便它可以过滤数据。当然,一旦我可以获得 IOwinContext,我实际上不会将其传递给 DbContext,而是使用 ToMethod 或类似的方法来提取 ClaimsPrincipal,但这超出了这个问题的范围。
最佳答案
免责声明:这是一个黑客行为。它可以工作,但感觉很不干净。使用后果自负。
本质上,您可以创建一个 OwinContextHolder 类,将其绑定(bind)到 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();
}
}
您的委托(delegate)处理程序:
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 注入(inject)到您的类中。
请注意,如果您的 API 位于与主机不同的程序集中,则可能会遇到 InRequestScope 无法正常工作的问题(例如,每次请求一个对象时都会得到一个不同的对象,并且没有错误)。如果您这样做,请参阅https://groups.google.com/forum/#!topic/ninject/Wmy83BhhFz8 .
关于asp.net-web-api - 使用 Web API 和 Ninject 注入(inject) IOwinContext,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23501363/