【问题标题】:How to inject User Manager to Account Controller with default Identity Model in Identity 2 using Ninject如何使用 Ninject 在 Identity 2 中使用默认身份模型将用户管理器注入帐户控制器
【发布时间】:2024-01-21 04:09:02
【问题描述】:

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

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

对于使用 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 是在 App_Start 下的 IdentityConfig.cs 中定义的。

附带说明:我正在使用 Ninject 的约定扩展:

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

谢谢。

【问题讨论】:

  • 这个question and answer 可能会有所帮助
  • 实际上并没有什么问题,我刚刚注入了与 Identity 相关的 DbContext,一切似乎都运行良好。因为现在 Identity 有更多选择,我有点迷路了,一直在寻找错误的地方,但我仍然希望看到该主题的专家为 Ninject 和 Identity 模型的使用写一个小教程。
  • @Bogac 你有想过这个吗?我遇到了同样的问题。我什至在这里为它提供了赏金*.com/questions/36239743/…
  • @Bagzli 已经很久了,坦率地说我不记得了,需要检查我使用它的项目才能给出答案。

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


【解决方案1】:

我在使用 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. 如您所见,我们有一个方法可以注入我们想要的所有服务,在这种情况下,我们必须注入 ApplicationUserManagerIUserStoreDbContext强>。所以对于 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 上所有键的类型,但是 使用默认值(字符串作为键)应该是一样的。

  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 before 获得 ApplicationUserManager现在 我们从 Ninject 内核获得它。请注意,我们为 DataProtectionProvider 创建了一个内部静态属性并从 appBuilder 设置它,我们将在 IdentityConfig/ApplicationUserManager 中使用此属性。(请参阅以后再说)

  4. 现在我们必须更改 ApplicationUserManager,我们将代码从 Create 方法中删除为 constructor,只需要一个与 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. 最后我们可以像这样在 Accountcontroller 的 构造函数 中使用 ApplicationUserManager

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

【讨论】:

  • 接受了你的答案,但没有测试(我现在在不同的平台上)。如果有人拒绝,我会改变它。
  • 不幸的是 var kernl = context.Get();不工作
【解决方案2】:

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

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

【讨论】:

    最近更新 更多