renelopez renelopez - 2 months ago 91
ASP.NET (C#) Question

How to plug my Autofac container into ASP. NET Identity 2.1

I have been looking into the new features of the new version of ASP.NET Identity 2.1 and one of its enhancements is the new IoC features integrated into the OWIN Middleware.
One of the sentences that I looked in the examples is this one:

app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);


This sentence receives a function delegate which returns a new instance of a manager implementation provided on the examples:

public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options,
IOwinContext context)
{
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));


I personally dont like this implementation because I am not able to use a container to inject any dependency that I want for these managers.

Also there is an "IdentityFactoryOptions" and a "IOwinContext" that are "magically" injected to the function which Im not able to pull out into my IoC container.

Do anyone have a better workaround on this implementation?

Answer

I'm starting from an out-of-the-box MVC5 installation and using AutoFac as an IoC container. It sounds like I am trying to acheive a similar goal as you, so let me explain what I've done. As a disclaimer, I am fairly new to using IoC and to Identity.

I believe the IOwinContext is unnecessary in a role as an IoC if you are using your own - I switched over to registering my ApplicationUserManager with AutoFac. To achieve this I had to:

Remove CreatePerOwinContext lines from Startup.Auth since I'll register ApplicationDbContext and ApplicationUserManager in AutoFac.

//app.CreatePerOwinContext(ApplicationDbContext.Create);
//app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);

Modify the ApplicationUserManager constructor arguments and included everything from the Create function.

public ApplicationUserManager(IUserStore<ApplicationUser> store, IdentityFactoryOptions<ApplicationUserManager> options)
        : base(store)
{
    //all the code from the 'Create' function here, using `this` for `manager`
}

Set the AccountController to have a single constructor taking an ApplicationUserManager as an argument and scrapped the UserManager property that grabs the ApplicationUserManager from the OwinContext.

private ApplicationUserManager _userManager; //every thing that needs the old UserManager property references this now
public AccountController(ApplicationUserManager userManager) 
{
    _userManager = userManager;
}

Register everything with AutoFac, including an instance of IdentityFactoryOptions.

var x = new ApplicationDbContext();
builder.Register<ApplicationDbContext>(c => x);
builder.Register<UserStore<ApplicationUser>>(c => new UserStore<ApplicationUser>(x)).AsImplementedInterfaces();
builder.Register<IdentityFactoryOptions<ApplicationUserManager>>(c => new IdentityFactoryOptions<ApplicationUserManager>()
{
    DataProtectionProvider = new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider("ApplicationName")
});
builder.RegisterType<ApplicationUserManager>();

That's the rough summary. I may have missed a couple of other tweaks I had to do along the way.

Comments