Личность ASP.NET класса UserManager 2.0 вместе с UnitOfWork и сервис-локатор анти-паттерн


Мне было интересно, будет ли это хороший подход к тож 2.0 UserManager рядом с UnitOfWork шаблон? Я использую UserManager только на вход и регистрация, так как он дает свободу не заботясь о хэширования паролей (также предоставляет возможности электронной почты пользователя и т. д.) и пользователь-роль управления. Хотя для остальной части проекта я использую UOW для поддержания пользователей и ролей (например, для редактирования информации (не пароль).

Это мои Login и Registerметоды:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult >Login(UserLoginViewModel model, string returnUrl)
{
    if (!this.ModelState.IsValid)
    {
        return this.View();
    }

    var user = (await this.unitOfWork.UserRepository.Find(u =>
        u.UserName == model.Login || u.UstId == model.Login)).FirstOrDefault();
    if (user == null)
    {
        this.ModelState.AddModelError("Login", Properties.Error.UserDoesntExist);
        return this.View();
    }
    var userManager = this.HttpContext.GetOwinContext().GetUserManager<LeaveUserManager>();
    var authManager = this.HttpContext.GetOwinContext().Authentication;

    if (!await userManager.CheckPasswordAsync(user, model.Password))
    {
        this.ModelState.AddModelError("Password", Properties.Error.WrongPassword);
        return this.View();
    }

    var ident = userManager.CreateIdentity(user, DefaultAuthenticationTypes.ApplicationCookie);
    authManager.SignIn(new AuthenticationProperties { IsPersistent = false }, ident);

    this.TempData["SuccessMessage"] = "Logged in";
    if (!string.IsNullOrEmpty(returnUrl) && this.Url.IsLocalUrl(returnUrl))
    {
        return this.Redirect(returnUrl);
    }
    return this.RedirectToAction("Index");
}

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Register(UserRegisterViewModel model)
{
    if (!this.ModelState.IsValid)
    {
        return this.View();
    }
    var userManager = this.HttpContext.GetOwinContext().GetUserManager<LeaveUserManager>();

    var user = new User(model);
    var result = userManager.Create(user, model.Password);
    if (!result.Succeeded)
    {
        result.Errors.ForEach(e => this.ModelState.AddModelError(string.Empty, e));
        return this.View();
    }

    var userRole = this.unitOfWork.UserRoleRepository.Find(ur => ur.Name == "User").Result.FirstOrDefault();
    if (userRole == null)
    {
        userRole = new UserRole("User");

        this.unitOfWork.UserRoleRepository.Add(userRole);
        this.unitOfWork.Complete();
    }
    userManager.AddToRole(user.Id, "User");

    this.TempData["SuccessMessage"] = "Registered";
    return this.RedirectToAction("Index");
}

И назначение пользователей на роль также использует UserManager:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Assign(AssignRoleViewModel model)
{
    if (!this.ModelState.IsValid)
    {
        return this.View(model);
    }
    var userManager = this.HttpContext.GetOwinContext().GetUserManager<LeaveUserManager>();

    userManager.RemoveFromRoles(model.Id, userManager.GetRoles(model.Id).ToArray());
    if (model.SelectedRoles.Any())
    {
        userManager.AddToRoles(model.Id, model.SelectedRoles.ToArray());
    }
    return this.RedirectToAction("Details", new { id = model.Id });
}

Хотя изменить способ использует uow:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit(User model)
{
    if (this.ModelState.IsValid)
    {
        var user = await this.unitOfWork.UserRepository.Get(model.Id);
        user.EditUser(model);
        await this.unitOfWork.Complete();
        return this.RedirectToAction("Index");
    }
    var userList = this.unitOfWork.UserRepository.GetAll().Result;
    this.ViewBag.SuperiorId = new SelectList(userList, "Id", "FirstName", model.SuperiorId);
    return this.View(model);
}

И мой UserManager:

public class LeaveUserManager : UserManager<User>
{
    public LeaveUserManager(IUserStore<User> store) : base(store)
    {
    }

    public static LeaveUserManager Create(
        IdentityFactoryOptions<LeaveUserManager> options, IOwinContext context)
    {
        var manager = new LeaveUserManager(
            new UserStore<User>(context.Get<VacationsContext>()))
        {
            EmailService = new LeaveEmailService()
        };
        return manager;
    }
}

Это ОК, чтобы оставить ее как есть, или я должен создать свою собственную класса UserManager, который будет использовать uow и хранилищ?
Я использую ASP.NET MVC5 с помощью ef6.


2018-03-20 изменить:
Я удалил .Result из всех асинхронных методов и заменяется await.
У меня зависимость вводят все managers, dbcontext и uow используя Ninject библиотека.

    private static void RegisterService(IKernel kernel)
    {
        kernel.Bind<VacationsContext>().ToSelf().InSingletonScope();
        kernel.Bind<RoleManager<UserRole>>().ToSelf().InRequestScope();
        kernel.Bind<LeaveUserManager>().ToMethod(c => LeaveUserManager.Create(kernel.Get<VacationsContext>())).InRequestScope();
        kernel.Bind<IAuthenticationManager>().ToMethod(c => HttpContext.Current.GetOwinContext().Authentication).InRequestScope();
        kernel.Bind<IUserStore<User>>().To<UserStore<User>>().InRequestScope().WithConstructorArgument("context", kernel.Get<VacationsContext>());
        kernel.Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
    }

Впрыск работает в контроллерах:

public HomeController(LeaveUserManager userManager, IAuthenticationManager authManager, IUnitOfWork unitOfWork)
{
    this.leaveUserManager = userManager;
    this.authenticationManager = authManager;
    this.unitOfWork = unitOfWork;
}

И если никто не говорит, что это какое-то нарушение - тогда я оставлю LeaveUserManager как это - через собственную сторону для доступа к базе данных слоя (пропуск мой пользовательский Ву).



Комментарии
1 ответ

Во-первых, избежать .Result в async-методов

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit(User model) {
//...

var userList = this.unitOfWork.UserRepository.GetAll().Result;

//...
}

как эти звонки могут приводить к взаимоблокировкам. Сделать функцию async на всем пути

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit(User model) {
if (this.ModelState.IsValid) {
var user = await this.unitOfWork.UserRepository.Get(model.Id);
user.EditUser(model);
await this.unitOfWork.Complete();
return this.RedirectToAction("Index");
}
var userList = await this.unitOfWork.UserRepository.GetAll();
this.ViewBag.SuperiorId = new SelectList(userList, "Id", "FirstName", model.SuperiorId);
return this.View(model);
}

Далее выясняется, что Ди и Служба поиска будут смешаны.

var userManager = this.HttpContext.GetOwinContext().GetUserManager<LeaveUserManager>();
var authManager = this.HttpContext.GetOwinContext().Authentication;

можно рассматривать как локатор анти-шаблон в действии называется.

Предполагая, что unitOfWork вводится в контроллер, то диспетчер пользователей и аутентификации должны быть явно вводят также.


Это ОК, чтобы оставить ее как есть, или я должен создать свою собственную класса UserManager, который будет использовать uow и хранилищ?

Основы сущности уже построен после ВУ/шаблон репозитория и основы идентичности на нем.

UserManager и расширение идентичности структуры-это скорее относится к выполнению/деталь, что вы можете инкапсулировать за свои собственные абстракции в любой структуре/шаблон, который вы хотите.

Вместо того чтобы сосредоточиться на том, что картины рассмотрим только создание сервиса для выполнения требуемой функциональности и вводишь ее в свой зависимые классы.

2
ответ дан 19 марта 2018 в 05:03 Источник Поделиться