本文介绍了如何注入UserManager& SignInManager的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图找出如何注入UserManager和SignInManager。我已经在我的应用程序中安装了Ninject,我以下列方式使用它:



请考虑这是一个全新的项目。在Startup.cs里面我有以下内容:

  public partial class Startup 
{
public void Configuration IAppBuilder应用程序)
{
ConfigureAuth(app);

app.UseNinjectMiddleware(CreateKernel);
}

私有静态IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());


返回内核;
}
}

现在,如果我要创建一些Dummy类,尝试根据它的界面来注入它。我已经测试了我想要弄清楚的是我现在如何从Startup.Auth.cs中删除以下内容并注入它。没有可以依赖的接口,我不知道这是如何完成的:

  app.CreatePerOwinContext(ApplicationDbContext.Create); 
app.CreatePerOwinContext< ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext< ApplicationSignInManager>(ApplicationSignInManager.Create);

只是为了澄清一次,我的问题是:如何实例化ApplicationUserManager和ApplicationSignInManager并注入在我的控制器参数。这是我想要注入的控制器:

  public AccountController(ApplicationUserManager userManager,ApplicationSignInManager signInManager)
{
UserManager = userManager;
SignInManager = signInManager;
}

编辑:



这是我试过的:

  private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());

kernel.Bind< IUserStore< ApplicationUser>>()。To< UserStore< ApplicationUser>>()
kernel.Bind< UserManager< ApplicationUser>>()。ToSelf();

返回内核;
}

但是这样我得到空参考错误

解决方案

要准确回答我的问题所在,以下是代码和说明:



步骤1:
创建自定义用户商店

  public class ApplicationUserStore:UserStore< ApplicationUser> 
{
public ApplicationUserStore(ApplicationDbContext context)
:base(context)
{
}
}

步骤2:
更新ApplicationUserManager并将代码从Create方法移动到构造函数

  public class ApplicationUserManager:UserManager< ApplicationUser> 
{
public ApplicationUserManager(IUserStore< ApplicationUser> store,IdentityFactoryOptions< ApplicationUserManager>选项)
:base(store)
{
this.UserValidator = new UserValidator< ApplicationUser> ;(这)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};

//为密码配置验证逻辑
this.PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = true,
RequireDigit = true,
RequireLowercase = true,
RequireUppercase = true,
};

//配置用户锁定默认值
this.UserLockoutEnabledByDefault = true;
this.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
this.MaxFailedAccessAttemptsBeforeLockout = 5;

//注册双因素身份验证提供程序。此应用程序使用电话和电子邮件作为接收验证用户的代码
//您可以编写自己的提供商并将其插入到此处。
this.RegisterTwoFactorProvider(Phone Code,new PhoneNumberTokenProvider< ApplicationUser>
{
MessageFormat =您的安全代码为{0}
});
this.RegisterTwoFactorProvider(电子邮件代码,新的EmailTokenProvider< ApplicationUser>
{
主题=安全代码,
BodyFormat =您的安全代码为{0}
});
this.EmailService = new EmailService();
this.SmsService = new SmsService();
var dataProtectionProvider = options.DataProtectionProvider;
if(dataProtectionProvider!= null)
{
this.UserTokenProvider =
new DataProtectorTokenProvider< ApplicationUser>(dataProtectionProvider.Create(ASP.NET Identity))
}
}
}

步骤3:
修改Startup.Auth类并注​​释掉以下代码

  // app.CreatePerOwinContext(ApplicationDbContext.Create); 
//app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
//app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

步骤4:
更新帐户控制器(或任何其他控制器),并添加以下构造函数

  public AccountController(ApplicationUserManager userManager,ApplicationSignInManager signInManager,IAuthenticationManager authManager)
{
_userManager = userManager ;
_signInManager = signInManager;
_authManager = authManager;
}

步骤5:
更新帐户控制器,使属性只能重新生成所以:

  public ApplicationSignInManager SignInManager 
{
get
{
return _signInManager ;
}
}

public ApplicationUserManager UserManager
{
get
{
return _userManager;
}
}

private IAuthenticationManager AuthenticationManager
{
get
{
return _authManager;
}
}

步骤6:
更新Startup.cs

  public partial class Startup 
{
private IAppBuilder _app;
public void配置(IAppBuilder应用程序)
{
ConfigureAuth(app);
_app = app;
app.UseNinjectMiddleware(CreateKernel);
}

private IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());

kernel.Bind< ApplicationDbContext>()。ToSelf().InRequestScope();
kernel.Bind< IUserStore< ApplicationUser>>()。到< ApplicationUserStore>();
kernel.Bind< ApplicationUserManager>()。ToSelf();
kernel.Bind< ApplicationSignInManager>()。ToSelf();
kernel.Bind< IAuthenticationManager>()。ToMethod(x => HttpContext.Current.GetOwinContext()。Authentication);
kernel.Bind< IDataProtectionProvider>()。ToMethod(x => _app.GetDataProtectionProvider());

返回内核;
}
}

为了进一步扩展这个问题的答案,基于我收到的意见:



这些管理员不应该被注入为类,因为你没有完成DI。应该做的是创建多个接口,根据您的需要进一步分离和分组UserManager的方法。以下是一个示例:

  public interface IUserManagerSegment 
{
任务< IdentityResult> CreateAsync(ApplicationUser用户,字符串密码);
任务< IdentityResult> CreateAsync(ApplicationUser用户);
任务< IdentityResult> ConfirmEmailAsync(string userId,string token);
任务< ApplicationUser> FindByNameAsync(string userName);
任务< bool> IsEmailConfirmedAsync(string userId);
任务< IdentityResult> ResetPasswordAsync(string userId,string token,string newPassword);
任务< IList< string>> GetValidTwoFactorProvidersAsync(string userId);
任务< IdentityResult> AddLoginAsync(string userId,UserLoginInfo login);
void Dispose(bool disposal);
void Dispose();
}

上面的方法列出了我选择的几个随机方法,仅仅是为了说明点。有了这个说法,我们不会根据这样的接口注入方法:

  kernel.Bind< IUserManagerSegment>() 。为了< ApplicationUserManager>(); 

现在我们的AccountController构造函数看起来像这样:

  public AccountController(IUserManagerSegment userManager,ApplicationSignInManager signInManager,IAuthenticationManager authManager)
{
_userManager = userManager;
_signInManager = signInManager;
_authManager = authManager;
}

同样的事情应该对SignInManager和AuthenticationManager完成。



上面的代码已经过测试,正在工作。只需确保您引用了以下DLL:



Ninject.dll

Ninject.Web.Common

Ninject.Web。 Common.OwinHost

Ninject.Web.Mvc


I am trying to figure out how to inject UserManager and SignInManager. I have installed Ninject in my application and I am using it in the following manner:

Please consider this to be a brand new project. Inside Startup.cs I have the following:

public partial class Startup
{
    public void Configuration(IAppBuilder app)
    {
        ConfigureAuth(app);

        app.UseNinjectMiddleware(CreateKernel);
    }

    private static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        kernel.Load(Assembly.GetExecutingAssembly());


        return kernel;
    }
}

now if I were to create some Dummy class and try to inject it based on its interface that works. I have tested it. What I am trying to figure out is how would I now strip out the following out of Startup.Auth.cs and inject it. Having no interfaces I can rely on, I am not sure how this is done:

app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

Just to clarify one more time, my question is: How do I instantiate ApplicationUserManager and ApplicationSignInManager and inject it in my controller parameters. Here is the controller that I am trying to inject this into:

public AccountController(ApplicationUserManager userManager, ApplicationSignInManager signInManager)
{
    UserManager = userManager;
    SignInManager = signInManager;
}

EDIT:

Here is what I tried:

private static IKernel CreateKernel()
{
    var kernel = new StandardKernel();
    kernel.Load(Assembly.GetExecutingAssembly());

    kernel.Bind<IUserStore<ApplicationUser>>().To<UserStore<ApplicationUser>>();
    kernel.Bind<UserManager<ApplicationUser>>().ToSelf();

    return kernel;
}

But with this I get null reference error

解决方案

To give an exact answer to what my question stated, here is the code and instructions:

Step 1: Create custom User Store

public class ApplicationUserStore : UserStore<ApplicationUser>
{
    public ApplicationUserStore(ApplicationDbContext context)
        : base(context)
    {
    }
}

Step 2:Update ApplicationUserManager and move code from Create method into constructor

public class ApplicationUserManager : UserManager<ApplicationUser>
{
    public ApplicationUserManager(IUserStore<ApplicationUser> store, IdentityFactoryOptions<ApplicationUserManager> options)
        : base(store)
    {
        this.UserValidator = new UserValidator<ApplicationUser>(this)
        {
            AllowOnlyAlphanumericUserNames = false,
            RequireUniqueEmail = true
        };

        // Configure validation logic for passwords
        this.PasswordValidator = new PasswordValidator
        {
            RequiredLength = 6,
            RequireNonLetterOrDigit = true,
            RequireDigit = true,
            RequireLowercase = true,
            RequireUppercase = true,
        };

        // Configure user lockout defaults
        this.UserLockoutEnabledByDefault = true;
        this.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
        this.MaxFailedAccessAttemptsBeforeLockout = 5;

        // Register two-factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user
        // You can write your own provider and plug it in here.
        this.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider<ApplicationUser>
        {
            MessageFormat = "Your security code is {0}"
        });
        this.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider<ApplicationUser>
        {
            Subject = "Security Code",
            BodyFormat = "Your security code is {0}"
        });
        this.EmailService = new EmailService();
        this.SmsService = new SmsService();
        var dataProtectionProvider = options.DataProtectionProvider;
        if (dataProtectionProvider != null)
        {
            this.UserTokenProvider =
                new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
        }
    }
}

Step 3:Modify the Startup.Auth class and comment out the following code

//app.CreatePerOwinContext(ApplicationDbContext.Create);
//app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
//app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

Step 4:Update Account Controller (or any other controller in question) and add the following constructor

public AccountController(ApplicationUserManager userManager, ApplicationSignInManager signInManager, IAuthenticationManager authManager)
{
    _userManager = userManager;
    _signInManager = signInManager;
    _authManager = authManager;
}

Step 5:Update Account Controller and make properties only retrivable as so:

public ApplicationSignInManager SignInManager
{
    get
    {
        return _signInManager;
    }
}

public ApplicationUserManager UserManager
{
    get
    {
        return _userManager;
    }
}

private IAuthenticationManager AuthenticationManager
{
    get
    {
        return _authManager;
    }
}

Step 6:Update Startup.cs

public partial class Startup
{
    private IAppBuilder _app;
    public void Configuration(IAppBuilder app)
    {
        ConfigureAuth(app);
        _app = app;
        app.UseNinjectMiddleware(CreateKernel);
    }

    private IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        kernel.Load(Assembly.GetExecutingAssembly());

        kernel.Bind<ApplicationDbContext>().ToSelf().InRequestScope();
        kernel.Bind<IUserStore<ApplicationUser>>().To<ApplicationUserStore>();
        kernel.Bind<ApplicationUserManager>().ToSelf();
        kernel.Bind<ApplicationSignInManager>().ToSelf();
        kernel.Bind<IAuthenticationManager>().ToMethod(x => HttpContext.Current.GetOwinContext().Authentication);
        kernel.Bind<IDataProtectionProvider>().ToMethod(x => _app.GetDataProtectionProvider());

        return kernel;
    }
}

To further expand the answer to this question, based on the comments I have received:

These managers should not be injected as classes as then you are not accomplishing DI. What should be done instead is create multiple interfaces that further separate and group methods of UserManager according to your needs. Here is an example:

public interface IUserManagerSegment
{
    Task<IdentityResult> CreateAsync(ApplicationUser user, string password);
    Task<IdentityResult> CreateAsync(ApplicationUser user);
    Task<IdentityResult> ConfirmEmailAsync(string userId, string token);
    Task<ApplicationUser> FindByNameAsync(string userName);
    Task<bool> IsEmailConfirmedAsync(string userId);
    Task<IdentityResult> ResetPasswordAsync(string userId, string token, string newPassword);
    Task<IList<string>> GetValidTwoFactorProvidersAsync(string userId);
    Task<IdentityResult> AddLoginAsync(string userId, UserLoginInfo login);
    void Dispose(bool disposing);
    void Dispose();
}

The above method has a list of few random methods I chose just to illustrate the point. With this said, we would not inject the method based on the interface such as this:

kernel.Bind<IUserManagerSegment>().To<ApplicationUserManager>();

And now our AccountController constructor would look like this:

public AccountController(IUserManagerSegment userManager, ApplicationSignInManager signInManager, IAuthenticationManager authManager)  
{
    _userManager = userManager;
    _signInManager = signInManager;
    _authManager = authManager;
}

Same thing should be done to SignInManager and AuthenticationManager.

The code above has been tested and is working. Just ensure you have referenced the following DLLs:

Ninject.dll
Ninject.Web.Common
Ninject.Web.Common.OwinHost
Ninject.Web.Mvc

这篇关于如何注入UserManager&amp; SignInManager的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-28 04:40