asp.net-web-api - 使用 Web API 和 Ninject 注入(inject) IOwinContext

标签 asp.net-web-api ninject owin

通过 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/

相关文章:

asp.net - 如何从 HttpActionExecutedContext 获取当前的 HttpContext

c# - Web API - 复杂类型枚举的表单编码输入允许无效值

c# - 依赖于实现相同接口(interface)的两个对象的简单注入(inject)器

c# - 带有 Ninject 的 WPF 应用程序

c# - Ninject 和静态类 - 如何?

c# - 使用 Caliburn Micro & Ninject 设置依赖注入(inject)

signalr - 手动启动 Owin

c# - ASP.NET 身份电子邮件验证 token 始终无效

azure - 使用 Oauth2/OpenID 连接构建 Web-API

asp.net-mvc - 多个模型和 Breeze 上下文的元数据问题