【问题标题】:Resolve Autofac dependencies in OWIN Startup class解决 OWIN 启动类中的 Autofac 依赖项
【发布时间】:2017-07-18 07:25:40
【问题描述】:

我有一个多租户 MVC5 webapp,它使用 Autofac v3.5.2 和 Autofac.Mvc5 v3.3.4。

我的 Autofac DI 连接发生在我的 MVC 项目中的一个类中。对于身份验证,我们使用OWIN OpenId middleware 与 Azure B2C 集成。在 OWIN Startup 类中,我需要一个依赖项来使用当前请求中的信息设置tenantId/clientId。 我尝试通过以下方式获取依赖项:

DependencyResolver.Current.GetService<...>(); 

但是,这总是会抛出 ObjectDisposedException

无法解析实例,并且无法从此 LifetimeScope 创建嵌套生命周期,因为它已被释放。

我们的应用程序中有一个具有请求生命周期的 ISiteContext。它填充了特定于当前请求的配置值。我正在尝试像这样获取这些值:

private OpenIdConnectAuthenticationOptions CreateOptionsFromPolicy(string policy)
{
    var options = new OpenIdConnectAuthenticationOptions
        {
            Notifications = new OpenIdConnectAuthenticationNotifications
            {
                ...
                RedirectToIdentityProvider = SetSettingsForRequest
            }
        }
}

private Task SetSettingsForRequest(RedirectToIdentityProviderNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context)
{
    var siteContext = DependencyResolver.Current.GetService<ISiteContext>();
    context.ProtocolMessage.ClientId = siteContext.ClientId;
    return Task.FromResult(0);
}

尝试在 SetSettingsForRequest 中使用 DependencyResolver 时发生错误。我不知道我在这里做错了什么。目前我的 Startup Configuration(IAppBuilder app) 方法中没有 Autofac DI 设置,因为这已经在我的 MVC 项目中设置。

【问题讨论】:

  • 你能分享更多代码吗?您是如何尝试获得tenantId 的?
  • @CyrilDurand 我添加了一个代码示例,显示我试图解决依赖关系以获取每个请求的 clientId

标签: c# owin autofac


【解决方案1】:

正如 Mickaël Derriey 所指出的,以下代码是能够在 OWIN 中解决请求范围依赖关系的解决方案:

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        var builder = new ContainerBuilder();
        // Register dependencies, then...
        var container = builder.Build();

        // Register the Autofac middleware FIRST. This also adds
        // Autofac-injected middleware registered with the container.
        app.UseAutofacMiddleware(container);

        // ...then register your other middleware not registered
        // with Autofac.
    }
}

然后在任何以后的代码中使用来解决依赖关系:

// getting the OWIN context from the OWIN context parameter
var owinContext = context.OwinContext;
var lifetimeScope = owinContext.GetAutofacLifetimeScope(); 
var siteContext = lifetimeScope.GetService<ISiteContext>();
context.ProtocolMessage.ClientId = siteContext.ClientId;

使用这个解决方案,我不再有任何问题解决请求范围的依赖关系,因为 Autofac 似乎符合 OWIN 创建/处理请求范围的方式。

【讨论】:

    【解决方案2】:

    恐怕此时您需要在 OWIN 管道中设置 DI。操作难度不大。

    你必须:

    这样做意味着 Autofac 将在堆栈中较低的 OWIN 级别创建每个请求的生命周期范围。这将允许您从 OWIN 上下文中获取 HTTP 请求生命周期范围:

    private Task SetSettingsForRequest(RedirectToIdentityProviderNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context)
    {
        // getting the OWIN context from the OIDC notification context
        var owinContext = context.OwinContext;
    
        // that's an extension method provided by the Autofac OWIN integration
        // see https://github.com/autofac/Autofac.Owin/blob/1e6eab35b59bc3838bbd2f6c7653d41647649b01/src/Autofac.Integration.Owin/OwinContextExtensions.cs#L19
        var lifetimeScope = owinContext.GetAutofacLifetimeScope(); 
    
        var siteContext = lifetimeScope.GetService<ISiteContext>();
        context.ProtocolMessage.ClientId = siteContext.ClientId;
        return Task.FromResult(0);
    }
    

    我希望这可以帮助您解决这个问题。

    【讨论】:

    • 将尝试您的建议并在此处记录结果。谢谢!
    猜你喜欢
    • 2015-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-29
    • 1970-01-01
    相关资源
    最近更新 更多