OwinMiddleware和依赖注入

7
我正在尝试创建一个OwinMiddleware对象以在管道中注册,以从传入请求中提取一些凭据并将它们应用于我们服务容器中的服务。这将导致需要通过控制器使用的需要验证的服务到达预认证状态,这意味着控制器不再需要提取授权标头和主体,并且我可以删除传递这些值的许多管道。
我们使用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);

根据我所知,基于构造函数是中间件提供额外服务的唯一入口。那么我是否需要不同版本?我需要调用其他特殊功能来通知管道每个请求构建新的中间件实例吗?

这篇博客文章似乎表明这将在aspnet 5中得到解决,而我相信我正在使用aspnet 5。那么问题得到了如何解决?在哪里解决?

... 当我们想要传递一个带有自己依赖项的类并且我们想要开始使用依赖注入时,情况就不那么简单了。由于OwinMiddleware的构造函数需要OwinMiddleware next,我们无法仅注册中间件本身并允许我们的DI容器解析其依赖关系。

据我所见,如果您确实需要向中间件添加其他依赖项,则有两个选择:使用具体实现进行新的配置(不好)或使用项目的依赖项解析器将其传递进去(反模式,也与MVC和Web API之间不同)。如果您发现任何更好的方法,请告诉我,因为我很想知道并更新此部分。这显然已解决ASP.NET 5的问题,但现在对我们没有帮助...

1个回答

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();
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接