Как ввести UserManager и SignInManager

Я пытаюсь выяснить, как ввести UserManager и SignInManager. Я установил Ninject в своем приложении, и я использую его следующим образом:

прошу считать это совершенно новый проект. Внутри Стартапа.cs у меня есть следующее:

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

теперь, если я должен был создать некоторый фиктивный класс и попытаться ввести его на основе его интерфейса, который работает. Я проверил его. То, что я пытаюсь выяснить, как бы я теперь вычеркнул следующее из автозагрузки.Автор.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;
}

EDIT:

вот что я пробовал:

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

но с этим я получаю пустой ссылкой ошибка

2 ответов


предпосылки

запустите новое приложение MVC5 с помощью шаблона MVC. Это позволит установить все необходимые зависимости, а также развернуть Startup.Auth.cs файл, который содержит код начальной загрузки для Microsoft.AspNet.Identity (он также включает все ссылки для Microsoft.сеть САШ.Идентичность.)

установите следующие пакеты и обновите их до последней версии.

Install-Package Ninject
Install-Package Ninject.MVC5

конфигурация

удалить конструктор по умолчанию AccountController так только параметризованный конструктор остается. Он должен иметь подпись follownig.

public AccountController(ApplicationUserManager userManager, ApplicationSignInManager signInManager)

это обеспечит что вы получите ошибку если впрыска терпит неудачу которая чего мы хотим.

Конфигурация NInject

развертывание пакета NInject NuGet создаст файл с именем NinjectWebCommon.cs где происходит регистрация плиты котла NInject. Это имеет метод со следующей подписью, которую вы можете расширить с помощью регистрации.

private static void RegisterServices(IKernel kernel)

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

private static void RegisterServices(IKernel kernel) {
    kernel.Bind<IUserStore<ApplicationUser>>().To<UserStore<ApplicationUser>>();
    kernel.Bind<UserManager<ApplicationUser>>().ToSelf();

    kernel.Bind<HttpContextBase>().ToMethod(ctx => new HttpContextWrapper(HttpContext.Current)).InTransientScope();

    kernel.Bind<ApplicationSignInManager>().ToMethod((context)=>
    {
        var cbase = new HttpContextWrapper(HttpContext.Current);
        return cbase.GetOwinContext().Get<ApplicationSignInManager>();
    });

    kernel.Bind<ApplicationUserManager>().ToSelf();
}

вот и все. Теперь вы должны иметь возможность перейти к логину или зарегистрировать ссылки и инъекции будет происходить.

Альтернативный Вариант

я предпочитаю Прокси-подход, который предоставляет ограниченную функциональность для ApplicationSignInManager и ApplicationUserManager экземпляров. Затем я ввожу этот прокси-сервер в необходимые контроллеры. Это помогает абстрагировать некоторую идентификационную информацию от контроллеров, что облегчает ее изменение в будущем. Это не новая концепция, и независимо от того, делаете вы это или нет, зависит от размера и сложности вашего проекта, а также от того, как вы хотите обрабатывать зависимости. Таким образом, преимущества (общие на самом деле для любого прокси):

  • вы можете абстрагировать некоторые зависимости от вашего кода
  • можно упростить некоторые из вызовов в api
  • вы можете выставить только ту функциональность, которую вы хотите использовать, включая настраиваемые части
  • управление изменениями должно быть проще, если интерфейсы когда-либо изменятся, теперь вы меняете вызовы в своем прокси-сервере вместо всего вызывающего кода на контроллерах.

пример кода:

public interface IAuthManager
{
    Task<SignInStatus> PasswordSignInAsync(string userName, string password, bool rememberMe);
}

public class AuthManager : IAuthManager
{
    private ApplicationUserManager _userManager;
    ApplicationSignInManager _signInManager;

    public AuthManager(ApplicationUserManager userManager, ApplicationSignInManager signInManager)
    {
        this._userManager = userManager;
        this._signInManager = signInManager;
    }

    public Task<SignInStatus> PasswordSignInAsync(string userName, string password, bool rememberMe)
    {
        return _signInManager.PasswordSignInAsync(userName, password, rememberMe, true);
    }
}

добавьте следующую строку в регистрацию зависимостей NInject.

kernel.Bind<IAuthManager>().To<AuthManager>();

изменить AccountController конструктор, чтобы взять экземпляр IAuthManager. Наконец, измените свои методы, чтобы ссылаться на этот прокси-сервер вместо ASP.NET классы идентификаторов напрямую.

отказ от ответственности-я не проводил сложный вызов, просто очень простой, чтобы проиллюстрировать мою точку зрения. Это также полностью необязательно, и независимо от того, делаете вы это или нет, должно зависеть от объема и размера вашего проекта и от того, как вы планируете использовать ASP.NET Identity framework


чтобы дать точный ответ на мой вопрос, вот код и инструкции:

Шаг 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> 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"));
        }
    }
}

Шаг 3: Изменение параметров запуска.Auth class и прокомментируйте следующий код

//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: Обновить контроллер учетной записи и сделать свойства только retrivable как так:

public ApplicationSignInManager SignInManager
{
    get
    {
        return _signInManager;
    }
}

public ApplicationUserManager UserManager
{
    get
    {
        return _userManager;
    }
}

private IAuthenticationManager AuthenticationManager
{
    get
    {
        return _authManager;
    }
}

Шаг 6: Обновление Запуска.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;
    }
}

для дальнейшего расширения ответа на этот вопрос, основываясь на полученных комментариях:

эти менеджеры не должны вводиться как классы, поскольку тогда вы не выполняете DI. Вместо этого следует создать несколько интерфейсов, которые далее разделяют и группируют методы UserManager в соответствии с вашими потребностями. Вот пример:

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

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

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

и теперь наш конструктор AccountController будет выглядеть так:

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

то же самое следует сделать для SignInManager и AuthenticationManager.

код выше был протестирован и работает. Просто убедитесь, что вы ссылались на следующие библиотеки DLL:

Ninject.dll файлы
Ninject.Сеть.Common
Ninject.Сеть.Общий.OwinHost
Ninject.Сеть.В MVC