OwinMiddleware和依赖注入

Qui*_*ome 5 c# asp.net-web-api owin

我试图创建一个OwinMiddleware对象以在管道中注册,以从传入的请求中提取一些信用并将其应用于我们的服务容器中的服务。这样的结果是,需要我们在控制器中使用auth的服务将到达预先经过身份验证的状态,这意味着控制器不再需要提取授权标头和主体,并且我可以删除很多将这些值传递给几个对象的管道层。

我们使用DependencyInjection(Microsoft.Extensions.DependencyInjection),更重要的是,此经过身份验证的服务的作用域是有限的,这意味着需要针对每个请求创建和销毁该服务(即,否则它可能会意外使用先前请求的凭据)。它的设置是通过使用ServiceCollection的IDependencyResolver的合理简单实现来实现的。通过我不太了解的.BeginScope()方法进行作用域定义,因为我找不到通过HttpConfiguration.IDependencyResolver实际调用.BeginScope()的源,我有点了解它的意思,但并不完全。不过效果很好。

现在,我从OwinMiddleware继承的对象的问题在于,我似乎无法通过IDependencyResolver使它与相关范围的对象通信。
由于我无法控制OwinMiddleware对象的创建,因此我所能做的就是在构造函数中指定要与之交互的服务。但是,这似乎是无用的,因为它似乎在管道中比在这里晚给我相同的对象实例(我想是因为它是作用域的?)。

即使我将IDependencyResolver放入构造函数中,也仍然无法获得正确的服务实例。我可以验证中间件是否正在执行。

不久前,我看到其他人在谈论能够使用额外的参数覆盖OwinMiddleware的Invoke()函数,从而解决范围问题。如果中间件仅创建一次,这似乎是有道理的,因为任何范围内的构造函数依赖项都会在第二个请求中失效。对我而言,在管道操作期间添加依赖项更为有意义。但是,对于我拥有的Owin lib版本(v3),只有:

public abstract Task Invoke(IOwinContext context);
Run Code Online (Sandbox Code Playgroud)

据我所知,在中间件上定义的唯一入口点是通过构造函数。我需要其他版本吗?我是否需要调用其他特殊方法来通知管道,以便根据请求构造中间件的新实例?

这个博客条目似乎表明它将在aspnet 5中修复,我相信我正在使用。那么如何以及在哪里修复它?

...当您要传递具有自己的依赖关系的类,而我们要开始使用依赖关系注入时,事情就不那么干净了。由于OwinMiddleware的构造函数接下来需要OwinMiddleware,因此我们不能简单地注册中间件本身并允许我们的DI容器解析其依赖项。

据我所知,如果确实需要向中间件添加另一个依赖项,则有两种选择:使用具体的实现(不好)对其进行新建,或者使用项目的Dependency Resolver(反模式,将其传递给MVC之间也有所不同)和Web API)。如果您找到更好的方法,请告诉我,因为我很想知道和更新此部分。对于ASP.NET 5,显然已经解决了该问题,但现在对我们没有帮助...

Mr *_*nce 1

这可能不完全是您想要的,但这是我在不使用自定义 DI 提供程序的情况下找到的唯一解决方案。
您可以在 Owin 环境上下文(有范围)中设置所需的数据。

// SettingsMiddleware.cs
public class SettingsMiddleware : OwinMiddleware
{
    public SettingsMiddleware (OwinMiddleware next)
        : base(next)
    {
    }

    public override async Task Invoke(IOwinContext context)
    {
        try
        {
            string data = context.Request.Headers["my-http-header-key"];
            context.Set("my-context-key", new MyCustomData
            {
                Data = data,
                // ... Anything else you want
            });
        }
        finally
        {
            await Next.Invoke(context);
        }
    }
}


// MyCustomData.cs
public class MyCustomData
{
    public string Data { get; set; }
    // ...
}


// SettingsService.cs
public interface ISettingsService
{
    MyCustomData GetHttpSettings();
}

public class SettingsService : ISettingsService
{
    public MyCustomData GetHttpSettings()
    {
        // Need Microsoft.Owin.Host.SystemWeb package for GetOwinContext.
        var owinContext = HttpContext.Current.GetOwinContext();
        var settings = owinContext.Get<MyCustomData >("my-context-key");
        return settings ?? new MyCustomData();
    }
}
Run Code Online (Sandbox Code Playgroud)