2017-07-18 71 views
0

我有一个多租户MVC5 webapp,它使用Autofac v3.5.2和Autofac.Mvc5 v3.3.4。解决OWIN启动类中的Autofac依赖关系

我的Autofac DI接线发生在我的MVC项目中的一个类中。对于身份验证,我们使用OWIN OpenId middleware与Azure B2C进行集成。在OWIN启动类中,我需要依赖项来使用来自当前请求的信息来设置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时发生此错误。我不知道我在这里做错了什么。目前我没有Autofac我的启动Configuration(IAppBuilder app)方法中的DI设置,因为这已经在我的MVC项目中设置。

+0

你能分享更多的代码吗?你是如何获得'tenantId'的? –

+0

@CyrilDurand我添加了一个代码示例,显示我试图解析依赖关系以获取每个请求的客户端的位置 –

回答

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

我希望这可以帮助你克服这个问题。

+0

将尝试您的建议并在此处记录结果。谢谢! –

0

作为的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创建/处理请求范围的方式。