Не удается обновить столбец SQL Bit с помощью ASP .NET Core

У меня есть веб-приложение ASP .NET Core, и когда я создал проект, проверка подлинности была настроена автоматически с использованием параметра учетных записей отдельных пользователей. Таблицы базы данных для учетных записей / ролей пользователей также были созданы автоматически.

Я создал свой собственный класс ApplicationUser, который наследуется от IdentityUser, и добавил параметры для FirstName, LastName и LockoutReason. (Я также добавил эти поля в таблицу БД). Теперь я пытаюсь добавить функцию, позволяющую кому-либо вручную заблокировать пользователя, и мне кажется, что я не могу обновить поле LockoutEnabled в базе данных. Каждый раз, когда я это делаю, он автоматически сбрасывается на false.

Вот изображение формы:  введите описание изображения здесь

И код GET / POST для него:

//GET Users lock
    public async Task<IActionResult> Lock(string id)
    {
        if (id == null)
        {
            return NotFound();
        }

        var userFromDb = await _db.ApplicationUser.SingleOrDefaultAsync(m => m.Id == id);
        if (userFromDb == null)
        {
            return NotFound();
        }
        else
        {
            return View(userFromDb);
        }
    }

    //POST Users lock
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Lock(string Id, ApplicationUser model)
    {
        var userFromDb = await _db.Users.Where(u => u.Id == Id).FirstOrDefaultAsync();

        userFromDb.LockoutEnd = model.LockoutEnd;
        userFromDb.LockoutEnabled = true;
        userFromDb.AccessFailedCount = model.AccessFailedCount;
        userFromDb.LockoutReason = model.LockoutReason;

        _db.ApplicationUser.Update(userFromDb);
        await _db.SaveChangesAsync();

        return RedirectToAction(nameof(Index));           
    }

ApplicationUser.cs

public class ApplicationUser : IdentityUser
{        
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string LockoutReason { get; set; }
}

Когда я нажимаю кнопку «Заблокировать», поля LockoutEnd и LockoutReason обновляются правильно, но поле LockoutEnabled остается ложным, и учетная запись не блокируется.

Новый метод POST после попытки реализовать решение:

//POST Users lock
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Lock(string Id, ApplicationUser model)
    {
        var userFromDb = await _db.Users.Where(u => u.Id == Id).FirstOrDefaultAsync();

        userFromDb.LockoutEnd = model.LockoutEnd;            
        userFromDb.AccessFailedCount = model.AccessFailedCount;
        userFromDb.LockoutReason = model.LockoutReason;

        _db.ApplicationUser.Update(userFromDb);            
        await _db.SaveChangesAsync();

        var user2 = await _userManager.FindByIdAsync(userFromDb.Id);
        var result = await _userManager.SetLockoutEnabledAsync(user2, true);

        return RedirectToAction(nameof(Index));           
    }

person HDuck    schedule 20.12.2018    source источник
comment
Попробуйте обновить, а затем сохраните ссылку (stackoverflow.com/questions/15799329/)   -  person Ryan Wilson    schedule 20.12.2018
comment
Я просто попробовал это, и у меня это не сработало. Редактировать: Спасибо за помощь.   -  person HDuck    schedule 20.12.2018
comment
Не знаю, почему тогда, может быть, кто-то еще может помочь.   -  person Ryan Wilson    schedule 20.12.2018
comment
вы смотрели запросы, которые приложение отправляет в базу данных? включено ли поле в операторы выбора и обновления?   -  person Chizh    schedule 20.12.2018


Ответы (3)


Вам нужна комбинация двух приличий: LockoutEnabled и LockoutEnd.

LockoutEnabled - это индикатор, показывающий, можно ли заблокировать пользователя, а LockoutEnd - DateTimeOffset. Итак, чтобы заблокировать пользователя, установите для блокировки значение true и поместите значение LockoutEnd в будущее, потому что значение в прошлом означает, что пользователь не заблокирован.

person Hameed    schedule 20.12.2018
comment
Ого, я совершенно не понял, как работают локауты. По какой-то причине я подумал, что LockoutEnabled был индикатором, показывающим, заблокирован ли пользователь в настоящее время, и будет иметь значение 1 до тех пор, пока не пройдет дата LockoutEnd. Я только что вручную обновил значения LockoutEnabled, и теперь моя функция блокировки работает должным образом. Спасибо! - person HDuck; 20.12.2018
comment
Вы также можете создать свой собственный механизм блокировки / отключения, добавив свойство пользователю, например: IsDisabled, затем создайте свой собственный SignInManager, который наследуется от SignInManager, и в нем вы можете переопределить PasswordSignInAsync, чтобы проверить, отключен ли пользователь или нет. - person Hameed; 21.12.2018

вы не можете добиться этого, изменив свойство LockoutEnabled.

Вместо этого вам нужно добавить настраиваемое свойство, например IsEnabled

  • При регистрации действия Изменить пользователя приложения

    var user = new ApplicationUser { UserName = model.Email, Email = model.Email, IsEnabled = true };

  • В PasswordSigninAsync добавьте проверку IsEnabled

'

if (user.IsEnabled)
     return base.PasswordSignInAsync(userName, password, rememberMe, shouldLockout);

return Task.FromResult<SignInStatus>(SignInStatus.LockedOut);
person Derviş Kayımbaşıoğlu    schedule 20.12.2018
comment
Это было предложено в комментарии, для меня это не сработало. Битовое поле (LockoutEnabled) - единственное поле, которое не обновляется. - person HDuck; 20.12.2018
comment
Спасибо за помощь - оказалось, что я просто неправильно понял, как работает блокировка, но в конечном итоге я могу воспользоваться вашим советом и создать свой собственный SignInManager и настраиваемую функцию блокировки. - person HDuck; 21.12.2018
comment
Вы проверили сообщение @Hameed в качестве ответа. Это сработало? - person Derviş Kayımbaşıoğlu; 21.12.2018

UserManager<ApplicationUser> _userManager

_userManager = userManager; //DI'd via CTOR for the class

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

в вашем случае вам может потребоваться захватить пользователя с помощью вызова var user = await _userManager.FindByIdAsync(model.Id)

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

//used from with in method
//model.LockoutEnabled will be either true or false depending on your selection
//from the view.
var result = await _userManager.SetLockoutEnabledAsync(user, model.LockoutEnabled); 

это возвращает IdentityResult, который имеет коллекцию ошибок или свойства bool Succeeded, с которыми можно работать как угодно.

person mvermef    schedule 20.12.2018
comment
Блокирует ли результат установки этого значения пользователя или мне нужно что-то делать с этой переменной? Я попытался просто вызвать await _userManager.SetLockoutEnabledAsync (user, true), и это не сработало. Я также установил пользователя равным await _userManager.FindByIdAsync (userFromDb.Id) - person HDuck; 20.12.2018
comment
Оказывается, мне даже не нужно было обновлять LockoutEnabled, я просто неправильно понял, как работают блокировки учетных записей. Я ценю помощь! - person HDuck; 20.12.2018
comment
у вас есть элементы в Startup.cs, настроенные для Identity? services.Configure<IdentityOptions>(config => {}); - person mvermef; 20.12.2018