Получение информации о пользователе на уровне класса в ASP.NET Identity

В ASP.NET Identity 2 or 3 можно ли получить информацию о пользователе на уровне класса? Сценарий следующий: в приложении всего две роли, а именно AdminRole и RegRole. Пользователь в AdminRole может действовать как пользователь в UserRole, выбрав имя пользователя из раскрывающегося списка, доступного только пользователю AdminRole. Что мне нужно сделать, так это то, что если администратор выбирает пользователя из раскрывающегося списка с домашней страницы, мне нужно назначить имя выбранного пользователя переменной уровня класса (то есть контроллера), чтобы имя пользователя можно было использовать на всех методы действия этого Контроллера (класса). Я пробовал следующее, но он выдает исключение NullException в if (User.Identity.Name == "Admin") строке приведенного ниже кода:

NullReferenceException: ссылка на объект не установлена ​​на экземпляр объекта.

Домашний контроллер [где администратор выбирает имя пользователя из раскрывающегося списка]

public class HomeController : Controller
{
    ...
    [HttpPost]
    public IActionResult ChooseUser(string selectedUser)
    {
        HttpContext.Session.SetString(SessionKeySelUser, selectedUser);

        return View();
    }
}

Другой контроллер [где я хочу использовать выбранное имя пользователя сверху во всех методах действий следующего контроллера]

public class TestController : Controller
{
   private MyProjContext _context;
   private string _userName;

  public TestController (MyProjContext context)
  {
    _context = context;

    if (User.Identity.Name == "Admin")
        _userName = HttpContext.Session.GetString("selectedUser"); //This session variable was assigned the user name value when the admin had selected the user name from the dropdown on the home page
   }
}

//use the class level variable _userName in all action methods like the one below
public IActionResult TestAction()
{
    _context.Orders.Where(ord => ord.Seller == _userName);

    return View();
}

....

person nam    schedule 03.07.2017    source источник


Ответы (1)


Если вы используете Identity 3, вы должны получить экземпляр UserManager, чтобы получить текущего вошедшего в систему пользователя.

Вы можете получить экземпляр UserManager, используя iOC, а затем использовать GetUserAsync метод UserManager, чтобы получить текущую объектную модель пользователя.

protected readonly UserManager<AppUser> UserManager;
private Task<AppUser> GetCurrentUserAsync() => UserManager.GetUserAsync(HttpContext.User);

public TestController(UserManager<AppUser> userManager)
{
     UserManager = userManager;
}

Ваше состояние можно изменить так:

var curUser = await GetCurrentUserAsync();
if (curUser.Name == "Admin")
        _userName = HttpContext.Session.GetString("selectedUser"); //This session variable was assigned the user name value when the admin had selected the user name from the dropdown on the home page

Поскольку вы пытаетесь получить к нему доступ из конструктора, вы можете добавить Result впереди, чтобы сделать его синхронным. Как вы сообщили в комментариях, HttpContext контроллера имеет значение null, когда класс создается. Тем не менее, вы можете получить к нему доступ из IHttpContextAccessor.

public TestController(UserManager<AppUser> userManager, IHttpContextAccessor httpContextAccessor)
{
    UserManager = userManager;
    var curUser = UserManager.GetUserAsync(httpContextAccessor.HttpContext.User).Result;
    if (curUser.Name == "Admin")
        _userName = HttpContext.Session.GetString("selectedUser"); 
}

Если вы используете Identity, я считаю, что IHttpContextAccessor вводится в конвейер. Если он возвращает null, вы должны добавить его как синглтон в свой Startup класс.

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
person João Pereira    schedule 03.07.2017
comment
Я полагаю, что под Task<AppUser> вы имели в виду Task<ApplicationUser>. Как бы то ни было, в строке GetCurrentUserAsync.Name == "Admin" я получаю сообщение об ошибке: Task ‹ApplicationUser› `не содержит определения для Name. - person nam; 03.07.2017
comment
Ты прав. Я только что обновил ответ. Я использую специального пользователя, поэтому я назвал класс AppUser. По умолчанию используется ApplicationUser. - person João Pereira; 03.07.2017
comment
Черт. Измените его с свойства на метод и посмотрите, работает ли он. Просто добавьте () к определению GetCurrentUserAsync и вызовите. Я сейчас использую мобильный телефон и не могу его протестировать ... - person João Pereira; 03.07.2017
comment
Хорошо, только что заметил, что вы пытаетесь получить к нему доступ из конструктора. Я обновил ответ, чтобы он соответствовал вашим потребностям. - person João Pereira; 03.07.2017
comment
Теперь я получаю NULLException в строке var curUser = UserManager.GetUserAsync(HttpContext.User).Result;. Кажется, что доступ к пользователю невозможен внутри Controller's Constructor, как объясняется в этом сообщении. - person nam; 04.07.2017
comment
Вы снова правы ... :) Но вы можете получить доступ к HttpContext из IHttpContextAccessor, инициированного запросом. Проверьте обновленный ответ. - person João Pereira; 04.07.2017