解决OWIN Startup类

时间:2017-07-18 07:25:40

标签: c# owin autofac

我有一个多租户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时发生错误。我不知道我在这里做错了什么。目前我的启动Configuration(IAppBuilder app)方法中没有 Autofac DI设置,因为这已经在我的MVC项目中设置。

2 个答案:

答案 0 :(得分:1)

正如MickaëlDerriey所指出的,以下代码是能够解决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创建/处理请求范围的方式。

答案 1 :(得分:0)

我担心此时您需要在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);
}

我希望这有助于你克服这个问题。