Как внедрить User Manager в Account Controller с моделью идентификации по умолчанию в Identity 2 с помощью Ninject

Я использую Ninject в проекте MVC 5 с Identity 2.

Для остальной части контекста данных и контроллеров, использующих это, у меня нет проблем с внедрением зависимостей.

Для контроллера учетной записи, использующего модель Identity 2, я получаю null UserManager при попытке войти в систему:

public class AccountController : Controller
{
    private ApplicationUserManager _userManager;

    public AccountController()
    {
    }

    public AccountController(ApplicationUserManager userManager)
    {
        UserManager = userManager;
    }

    public ApplicationUserManager UserManager {
        get
        {
            return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
        }
        private set
        {
            _userManager = value;
        }
    }

Каков правильный способ внедрения необходимых зависимостей? Я не создавал собственный UserManager, это стандартная модель, ApplicationUserManager определен в IdentityConfig.cs в разделе App_Start.

В качестве примечания: я использую расширение соглашений Ninject:

private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind(
           x => x.FromThisAssembly()
               .SelectAllClasses()
               .BindAllInterfaces()
           );

Спасибо.


comment
Этот вопрос и ответ может помочь   -  person    schedule 23.08.2014
comment
На самом деле нет ничего плохого, я только что ввел DbContext, связанный с Identity, и все работает нормально. Поскольку теперь у Identity больше вариантов, я немного растерялся и искал не те места, но я все же хотел бы, чтобы эксперт по этому вопросу написал небольшой учебник по использованию моделей Ninject и Identity.   -  person Bogac    schedule 24.08.2014
comment
@ Богач, ты когда-нибудь это понимал? Я застрял с той же проблемой. Я даже предложил награду за это здесь "> stackoverflow.com/questions/36239743/   -  person Bagzli    schedule 29.03.2016
comment
@Bagzli это было давно, и, честно говоря, я не помню, нужно проверить проект, для которого я использовал это, чтобы дать ответ.   -  person Bogac    schedule 29.03.2016


Ответы (2)


У меня была такая же проблема с Ninject4.0, MVC5.2.3, Identity2.0 и Owin3.0.1, здесь вы должны сделать, чтобы все работало правильно.

  1. Прежде всего, вы должны получить Ninject.Web.Common.OwinHost от NuGet, потому что, если вы работаете с Owin, вы хотите использовать NinjectMiddleware.

        public partial class StartUp
        { 
             private IKernel kernel = null;
             public void Configuration(IAppBuilder app)
             {
                kernel = CreateKernel();
                app.UseNinjectMiddleware(() => kernel);
                ConfigureAuth(app);
             }
    
             public IKernel CreateKernel()
             {
                var kernel = new StandardKernel();
                try
                {
    
                   // TODO: Put any other injection which are required.
                   RegisterServices(kernel);
                   return kernel;
                }
                catch
                {
                  kernel.Dispose();
                  throw;
                }
             }
          }
    
  2. Как видите, у нас есть метод для внедрения всех нужных нам служб, в этом случае мы должны внедрить ApplicationUserManager, IUserStore и DbContext. Итак, для RegisterServices в классе Startup мы имеем:

         private static void RegisterServices(IKernel kernel) 
         {
    
            kernel.Bind<DbContext>().To<ApplicationDbContext>();
            kernel.Bind<IUserStore<User, long>>().To<UserStore<User, Role, long, UserLogin, UserRole, UserClaim>>();
    
            kernel.Bind<ApplicationUserManager>().ToSelf();
    
        }
    

    Примечание. Я использую long insted of string как тип всех ключей в Identity, но использование default (string as key) должно быть таким же.

  3. В файле StartUp.Auth.cs, который содержит часть класса StartUp, мы должны изменить метод ConfigureAuth на этот:

         internal static IDataProtectionProvider DataProtectionProvider
         { get; private set; }
    
         public void ConfigureAuth(IAppBuilder app)
         {
         DataProtectionProvider = app.GetDataProtectionProvider();
        //app.CreatePerOwinContext<ApplicationUserManager(ApplicationUserManager.Create)
    
         app.CreatePerOwinContext<ApplicationUserManager>(
         (option, context) => {
                var kernl = context.Get<IKernel>();
    
              return kernel.Get<ApplicationUserManager>();
    
            });
    
             //rest of the code 
       }
    

    Примечание: мы получаем ApplicationUserManager из owin ранее, но сейчас мы получаем его из Ninject kernelОбратите внимание, что мы создаем внутреннее статическое свойство для DataProtectionProvider и устанавливаем его из appBuilder. Мы собираемся использовать это свойство в IdentityConfig/ApplicationUserManager (см. позже).

  4. Теперь мы должны изменить ApplicationUserManager, мы удаляем код из метода Create в конструктор только с одной зависимостью от IUserStore, здесь это окончательный вид:

           public class ApplicationUserManager : UserManager<User,long>
           {
            public ApplicationUserManager(IUserStore<User,long> store)
               :base(store)
              {
    
    
              this.UserValidator = new UserValidator<User, long>(this)
                {
                   AllowOnlyAlphanumericUserNames = false,
                   RequireUniqueEmail = true
                 };
             // Configure validation logic for passwords
             this.PasswordValidator = new PasswordValidator
                 {
                    RequiredLength = 6,
                    RequireNonLetterOrDigit = true,
                    RequireDigit = true,
                    RequireLowercase = true,
                    RequireUppercase = true,
                 };
    
              var dataProtectionProvider = Startup.DataProtectionProvider;
    
             // this is unchanged
             if (dataProtectionProvider != null)
             {
                IDataProtector dataProtector = 
                      dataProtectionProvider.Create("ASP.NET Identity");
    
                this.UserTokenProvider = 
                  new DataProtectorTokenProvider<User,long>(dataProtector);
             }
          }
       }
    
  5. наконец, мы можем использовать ApplicationUserManager в конструкторе нашего Accountcontroller следующим образом:

     public class AccountController : ApiController
     {
         private ApplicationUserManager UserManager ;
         public AccountController(ApplicationUserManager userManager){
    
                UserManager = userManager;
         }
        // all apis come here
    
      }
    
person Mona Moravej    schedule 21.04.2017
comment
Принял ваш ответ, но не проверял его (сейчас я на другой платформе). Если кто-то откажется, поменяю. - person Bogac; 08.05.2017
comment
к сожалению, var kernl = context.Get‹IKernel›(); не работает - person Oktay Myumyunov; 30.06.2020

Можете ли вы попробовать удалить упомянутые строки в вашем вопросе из своего кода и заменить его следующим:

public AccountController()
            : this(new UserManager<ApplicationUser>(new Microsoft.AspNet.Identity.EntityFramework.UserStore<ApplicationUser>(new ApplicationDbContext())))
        {
        }

        public AccountController(UserManager<ApplicationUser> userManager)
        {
            UserManager = userManager;
        }
        public UserManager<ApplicationUser> UserManager { get; private set; }
person DJ'    schedule 04.01.2015