如何使用Ninject将用户管理器注入到身份2中的默认身份模型的帐户控制器

时间:2014-08-23 11:46:46

标签: asp.net-mvc asp.net-mvc-5 ninject.web.mvc asp.net-identity-2 asp.net-mvc-controller

我在带有Identity 2的MVC 5项目中使用Ninject。

对于使用它的其余数据上下文和控制器,我没有依赖注入的问题。

对于使用Identity 2模型的Account控制器,当我尝试登录时,我将获得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是在App_Start下的IdentityConfig.cs中定义的。

作为旁注:我正在使用Ninject的约定扩展:

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

感谢。

2 个答案:

答案 0 :(得分:2)

我在使用Ninject4.0,MVC5.2.3,Identity2.0和Owin3.0.1时遇到了同样的问题,在这里你应该做好正确的工作。

  1. 首先你应该从NuGet获得 Ninject.Web.Common.OwinHost ,因为如果你使用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 即可。因此,对于 Startup 类中的 RegisterServices ,我们有:

         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上所有键的类型,但是 使用defualt(字符串作为键)应该是相同的。

  3. 在包含部分 StartUp 类的 StartUp.Auth.cs 文件中,我们应将 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 
       }
    

    注意:我们从 owin 之前获取 ApplicationUserManager ,但现在我们从 Ninject内核获取 。请注意我们为 DataProtectionProvider 创建内部静态属性并从appBuilder设置它,我们将在 IdentityConfig / ApplicationUserManager 中使用此属性。 (稍后见)

  4. 现在我们必须更改 ApplicationUserManager ,我们将创建方法中的代码移除到构造函数,只需一个依赖 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 ,如下所示:

     public class AccountController : ApiController
     {
         private ApplicationUserManager UserManager ;
         public AccountController(ApplicationUserManager userManager){
    
                UserManager = userManager;
         }
        // all apis come here
    
      }
    

答案 1 :(得分:0)

您可以尝试从代码中删除问题中提及的行,并将其替换为以下内容:

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