Настройка Unity DI для идентификации ASP.NET

Я использую Unity успешно для всех регулярных инъекций конструктора, таких как репозитории и т.д., но я не могу заставить его работать с классами ASP.NET Identity. Настройка такова:

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

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

    // ...
}

с этими конфигами для Unity:

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

То же, что и другие сообщения здесь для Autofac, Ninject, например, но это не работает в моем случае. Сообщение об ошибке:

Произошла ошибка при попытке создать контроллер типа AccountController. Удостоверьтесь, что контроллер имеет безкоммертный публичный конструктор. Конечно, ручные работы:

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

Что не так?

UPDATE

Как было предложено @emodendroket, сокращение кода до этого делает трюк. Нет необходимости в пакете Unity.Mvc.

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

и

public AccountController(UserManager<IdentityUser> _userManager,
  IAccountRepository _account)
{
    // ...

Ответы

Ответ 1

Вам также нужно решить UserManager. Ниже приведен пример того, как вы могли бы сделать это с помощью UserManager и RoleManager. В этом примере я использую обычный пакет Unity 3 вместо одного из дериватов или загрузчиков (с некоторыми проблемами с ними в прошлом).

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

Ответ 2

Как говорится в сообщении в блоге от enterpriseframework.com:

Сначала добавьте Unity Bootstrapper для пакета ASP.NET MVC Nuget.

  • В вашей Visual Studio "Обозреватель решений" > щелкните правой кнопкой мыши на своем веб-проекте "Ссылки" node > нажмите "Управление пакетами NuGet".

  • В меню слева выберите "Интернет" > "Все"

  • В верхнем правом окне поискa > Поиск в Интернете (Ctrl + E) > введите "Unity bootstrapper для ASP.NET MVC".
  • Выберите "Unity Bootstrapper для ASP.NET MVC" и выберите "Установить".
  • Нажмите "Закрыть" после завершения установки.

Затем измените файл your-Web-project/App_Start/UnityConfig.cs и обновите операторы using следующим образом:

    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;

Наконец, в том же файле обновите метод RegisterTypes, как показано ниже:

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

НТН

Ответ 3

Install-Package Unity.AspNet.WebApi

Вам нужно зарегистрировать Unity в свойстве HttpConfiguration.DependencyResolver. Это позволяет WebApi знать, что для использования контроллеров необходимо использовать Unity, а не рефлексию.

Самый простой способ сделать это - с указанным выше пакетом nuget.

Ответ 4

Замените это свойство в AccountController

public ApplicationUserManager UserManager
{
    get
    { 
        _userManager = new ApplicationUserManager(
                          new UserStore<ApplicationUser>(new ApplicationDbContext()));
        return _userManager ??
               Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
    }
    private set
    {
        _userManager = value;
    }
}