Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Configure Unity DI for ASP.NET Identity

I'm using Unity successfully for all regular constructor injection such as repositories etc., but I can't get it working with the ASP.NET Identity classes. The setup is this:

public class AccountController : ApiController
{
    private UserManager<ApplicationUser> _userManager { get; set; }

    public AccountController(UserManager<ApplicationUser> userManager)
    {
        if (userManager == null) { throw new ArgumentNullException("userManager"); }
        _userManager = userManager;
    }

    // ...
}

with these configs for Unity:

unity.RegisterType<AccountController>();
unity.RegisterType<UserManager<ApplicationUser>>(new HierarchicalLifetimeManager());
unity.RegisterType<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>(new HierarchicalLifetimeManager());

That's the same as other posts here for Autofac, Ninject e.g., but it doesn't work in my case. The error message is:

An error occurred when trying to create a controller of type 'AccountController'. Make sure that the controller has a parameterless public constructor. Manual creation works of course:

public AccountController()
    : this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>("Mongo")))
{
}

What's wrong?

UPDATE

As suggested by @emodendroket, shortening the code to this does the trick. No need for the Unity.Mvc package.

unity.RegisterType<IUserStore<IdentityUser>, 
  MyCustomUserStore>(new HierarchicalLifetimeManager());

and

public AccountController(UserManager<IdentityUser> _userManager,
  IAccountRepository _account)
{
    // ...
like image 535
Benjamin E. Avatar asked Feb 21 '14 07:02

Benjamin E.


Video Answer


2 Answers

You also need to resolve the UserManager. The following is an example how you could do it with the UserManager and the RoleManager. In this sample I use the regular Unity 3 package instead of one of the derivates or bootstrappers (had some problems with them in the past).

AccountController

private readonly UserManager<ApplicationUser> _userManager;

private readonly RoleManager<IdentityRole> _roleManager;

public AccountController(IUserStore<ApplicationUser> userStore, IRoleStore<IdentityRole> roleStore)
{
  _userManager = new UserManager<ApplicationUser>(userStore);
  _roleManager = new RoleManager<IdentityRole>(roleStore);
}

Unity Bootstrapper

var accountInjectionConstructor = new InjectionConstructor(new IdentitySampleDbModelContext(configurationStore));
container.RegisterType<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>(accountInjectionConstructor);
container.RegisterType<IRoleStore<IdentityRole>, RoleStore<IdentityRole>>(accountInjectionConstructor);
like image 67
Horizon_Net Avatar answered Oct 26 '22 02:10

Horizon_Net


As this blog post from enterpriseframework.com says:

First, add the Unity Bootstrapper for ASP.NET MVC Nuget package.

  1. In your Visual Studio "Solution Explorer" > right click on your Web project's "References" node > click "Manage NuGet Packages".

  2. From the left menu, choose Online > All

  3. In the upper right search box > Search Online (Ctrl + E) > type "Unity bootstrapper for ASP.NET MVC".
  4. Select "Unity Bootstrapper for ASP.NET MVC" and choose Install.
  5. Click Close after install completes

Then Modify your-Web-project/App_Start/UnityConfig.cs file and update the using statements as follows:

    using System;
    using System.Data.Entity;
    using Microsoft.AspNet.Identity;
    using Microsoft.AspNet.Identity.EntityFramework;
    using Microsoft.Practices.Unity;
    using Microsoft.Practices.Unity.Configuration;
    using MicrosoftIdentity.Controllers;
    using MicrosoftIdentity.Models;

Finally, in the same file, update RegisterTypes method as below:

        public static void RegisterTypes(IUnityContainer container)
        {
            // NOTE: To load from web.config uncomment the line below. Make sure to add a Microsoft.Practices.Unity.Configuration to the using statements.
            // container.LoadConfiguration();

            // TODO: Register your types here
            container.RegisterType<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>();
            container.RegisterType<UserManager<ApplicationUser>>();
            container.RegisterType<DbContext, ApplicationDbContext>();
            container.RegisterType<ApplicationUserManager>();
            container.RegisterType<AccountController>(new InjectionConstructor());
        }

HTH

like image 34
Kamran Avatar answered Oct 26 '22 02:10

Kamran