使用Ninject的Web API 2和OWIN托管。
我想将当前的IOwinContext注入某些服务(因此我可以获取请求让主体进行一些数据过滤)。
使用虚拟主机我会在过去使用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依赖范围,如果有人从这个范围请求IOwinContext,给他们这个我已经拥有的实例。” p>
我确实理解我可以从我的控制器中获取当前上下文并将其传递,但这反而违背了我想要做的目的;我希望我的DbContext能够理解用户是谁,以便过滤数据。当然,一旦我可以获得IOwinContext,我实际上不会将其传递给DbContext,而是使用ToMethod或类似方法来提取ClaimsPrincipal,但这超出了这个问题的范围。
答案 0 :(得分:3)
免责声明:这是一个黑客攻击。它有效,但感觉非常不洁净。使用危险。
实际上,您可以创建一个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。