Resolve Autofac dependencies in OWIN Startup class

时光毁灭记忆、已成空白 提交于 2019-12-12 03:58:24

问题


I have a multi-tenant MVC5 webapp, which is using Autofac v3.5.2 and Autofac.Mvc5 v3.3.4.

My Autofac DI wiring takes place in a class within my MVC project. For authentication, we are using OWIN OpenId middleware to integrate with Azure B2C. In the OWIN Startup class I need a dependency to set tenantId/clientId using information from the current request. I try to grab the dependency via :

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

However, this always throws an ObjectDisposedException

Instances cannot be resolved and nested lifetimes cannot be created from this LifetimeScope as it has already been disposed.

We have an ISiteContext in our application that has a request-lifetime. It gets populated with configuration values specific to the current request. I am trying to fetch these values like this:

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

The error happens when trying to use the DependencyResolver in SetSettingsForRequest. I have no clue as to what I am doing wrong here. Currently I have no Autofac DI setup in my Startup Configuration(IAppBuilder app) method, since this is already setup in my MVC project.


回答1:


As Mickaël Derriey pointed out, the following code is a solution to being able to resolve request-scoped dependencies in 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.
    }
}

and then use in any later code to resolve a dependency:

// 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;

Using this solution, I did not have any issues anymore resolving request-scoped dependencies, since Autofac seems to accord to the OWIN way of creating/disposing of a request scope.




回答2:


I'm afraid that at this point you need to set up DI in the OWIN pipeline. It's not a difficult operation.

You'll have to:

  • follow the steps listed in the official documentation on OWIN integration with ASP.NET MVC
  • move your existing registration code (that is most probably in Global.asax.cs in Startup.cs as the documentation linked above shows

Doing this means Autofac will create the per-request lifetime scope lower in the stack, at the OWIN level. This will allow you to get hold of the HTTP request lifetime scope from the OWIN context:

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

I hope this helps you get over that issue.



来源:https://stackoverflow.com/questions/45160188/resolve-autofac-dependencies-in-owin-startup-class

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!