ASP.NET MVC 5 - Идентичность. Как получить текущий ApplicationUser

У меня есть объект Article в моем проекте, у которого есть свойство ApplicationUser с именем Author. Как получить полный объект текущего журнала ApplicationUser. При создании новой статьи мне нужно установить свойство Author в Article на текущий ApplicationUser.

В старом Механизм членства это было просто, но в новом подходе Identity я не знаю, как это сделать.

Я попытался сделать это следующим образом:

  • Добавить инструкцию для расширений Identity: using Microsoft.AspNet.Identity;
  • Затем я пытаюсь получить текущего пользователя: ApplicationUser currentUser = db.Users.FirstOrDefault(x => x.Id == User.Identity.GetUserId());

Но я получаю исключение:

LINQ to Entities не распознает метод 'System.String GetUserId (System.Security.Principal.IIdentity)', и этот метод не может быть переведен в выражение хранилища.   Источник = EntityFramework

Ответ 1

Вам не нужно запрашивать базу данных непосредственно для текущего ApplicationUser.

Это вводит новую зависимость от наличия дополнительного контекста для стартеров, но изменение таблиц базы данных пользователей изменяется (3 раза за последние 2 года), но API является последовательным. Например, таблица users теперь называется AspNetUsers в Identity Framework, а имена нескольких полей первичного ключа продолжают меняться, поэтому код в нескольких ответах больше не будет работать как есть.

Другая проблема заключается в том, что базовый доступ OWIN к базе данных будет использовать отдельный контекст, поэтому изменения от отдельного доступа к SQL могут приводить к недействительным результатам (например, не видя изменений, внесенных в базу данных). Опять же, решение состоит в том, чтобы работать с поставляемым API и не пытаться обходить его.

Правильный способ доступа к текущему пользовательскому объекту в идентификаторе ASP.Net(на данный момент):

var user = UserManager.FindById(User.Identity.GetUserId());

или, если у вас есть асинхронное действие, что-то вроде:

var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());

FindById требует, чтобы у вас был следующий оператор using, чтобы были доступны методы non-async UserManager (они являются методами расширения для UserManager, поэтому, если вы не включили это, вы увидите только FindByIdAsync):

using Microsoft.AspNet.Identity;

Если вы вообще не находитесь в контроллере (например, используете инъекцию IOC), то идентификатор пользователя извлекается полностью из:

System.Web.HttpContext.Current.User.Identity.GetUserId();

Если вы не находитесь в стандартном контроллере учетной записи, вам необходимо добавить к контроллеру следующее (в качестве примера):

1. Добавьте эти два свойства:

    /// <summary>
    /// Application DB context
    /// </summary>
    protected ApplicationDbContext ApplicationDbContext { get; set; }

    /// <summary>
    /// User manager - attached to application DB context
    /// </summary>
    protected UserManager<ApplicationUser> UserManager { get; set; }

2. Добавьте это в конструктор контроллера:

    this.ApplicationDbContext = new ApplicationDbContext();
    this.UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(this.ApplicationDbContext));

Обновить март 2015

Примечание. Последнее обновление для платформы Identity изменяет один из базовых классов, используемых для аутентификации. Теперь вы можете получить доступ к нему из контекста Owin текущего HttpContent.

ApplicationUser user = System.Web.HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>().FindById(System.Web.HttpContext.Current.User.Identity.GetUserId());

Добавление:

При использовании EF и Identity Framework с Azure через удаленное соединение с базой данных (например, локальное тестирование узла в базу данных Azure) вы можете случайно попасть в ужасную ошибку: 19 - физическое соединение не используется ". Поскольку причина скрыта внутри Identity Framework, где вы не можете добавлять повторы (или то, что кажется отсутствующим .Include(x->someTable)), вам необходимо реализовать пользовательский SqlAzureExecutionStrategy в вашем проекте.

Ответ 2

Моя ошибка, я не должен был использовать метод внутри запроса LINQ.

Правильный код:

string currentUserId = User.Identity.GetUserId();
ApplicationUser currentUser = db.Users.FirstOrDefault(x => x.Id == currentUserId);

Ответ 3

В комментариях к ответам, но никто не разместил это как фактическое решение.

Вам просто нужно добавить инструкцию using вверху:

using Microsoft.AspNet.Identity;

Ответ 4

Код Ellbar работает! Вам нужно только добавить использование.

1 - using Microsoft.AspNet.Identity;

И... код Ellbar:

2 - string currentUserId = User.Identity.GetUserId(); ApplicationUser currentUser = db.Users.FirstOrDefault(x => x.Id == currentUserId);

С помощью этого кода (в currentUser) вы работаете с общими данными подключенного пользователя, если вам нужны дополнительные данные... см. эта ссылка

Ответ 5

Как и для ASP.NET Identity 3.0.0, это было реорганизовано в

//returns the userid claim value if present, otherwise returns null
User.GetUserId();

Ответ 6

ApplicationDbContext context = new ApplicationDbContext();
var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
ApplicationUser currentUser = UserManager.FindById(User.Identity.GetUserId());

string ID = currentUser.Id;
string Email = currentUser.Email;
string Username = currentUser.UserName;

Ответ 7

В настоящий момент шаблон проекта asp.mvc создает контроллер учетной записи, который получает этот способ:

HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>()

Для меня работает следующее:

ApplicationUser user = HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>().FindById(User.Identity.GetUserId());

Ответ 8

Для MVC 5 просто загляните внутрь метода EnableTwoFactorAuthentication ManageController в шаблоны шаблонов WebApplication, там делается:

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> EnableTwoFactorAuthentication()
        {
            await UserManager.SetTwoFactorEnabledAsync(User.Identity.GetUserId(), true);
            var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
            if (user != null)
            {
                await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
            }
            return RedirectToAction("Index", "Manage");
        }

Ответ прямо там, как это было предложено самой Microsoft:

var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());

Он будет иметь все дополнительные свойства, определенные вами в классе ApplicationUser.