ASP.NET MVC 5-身份。如何获取当前的ApplicationUser


237

我的项目中有一个Article实体,其ApplicationUser属性名为Author。如何获取当前已记录的完整对象ApplicationUser?在创建新文章时,我必须将Author属性设置Article为current ApplicationUser

在旧的成员资格机制中,这很简单,但是在新的身份方法中,我不知道该怎么做。

我试图这样做:

  • 为身份扩展添加using语句: 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

Answers:


448

您无需直接向数据库查询当前的ApplicationUser。

这就引入了新的依赖关系,即需要为初学者提供额外的上下文,但是以后用户数据库表会发生变化(过去2年中有3次变化),但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语句,以便非异步UserManager方法可用(它们是UserManager的扩展方法,因此,如果不包括此扩展名,则只会看到FindByIdAsync):

using Microsoft.AspNet.Identity;

如果您根本不在控制器中(例如,您正在使用IOC注入),那么将从以下位置完全检索用户ID:

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.将其添加到Controller的构造函数中:

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

2015年3月更新

注意:Identity框架的最新更新更改了用于身份验证的基础类之一。现在,您可以从当前HttpContent的Owin上下文中访问它。

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在项目中实现自定义。


5
@TBA-谢谢,后来我意识到这是一种扩展方法。需要使用添加Microsoft.AspNet.Identity。再次感谢
Sentinel

2
找不到类型或名称。UserStore。我使用Microsft.AspNet.Indentity添加
Wasfa 2014年

2
@Zapnologica:听起来像是一个新问题(建议您发布)。您可以并行扩展ApplicationUser类(特定AspNetUsers于应用程序)和表,它们将提供任何新字段。再说一遍:不要直接打数据库!:)
Gone Coding

2
@ LifeH2O:FindById返回的ApplicationUser是您的类,并带有的其他属性。请尝试一下。
Gone Coding

1
等待新的解决方法:P
Anup Sharma,2015年

60

我的错误,我不应该在LINQ查询中使用方法。

正确的代码:

using Microsoft.AspNet.Identity;


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

2
我不存在User.Identiy.GetUserId。那是我的自定义方法吗?我只了解User.Identity
Gerrie Pretorius

9
没关系...您需要“使用Microsoft.AspNet.Identity;” 该方法在那里。
2014年

4
仅需注意,User对象仅在Controller中可见。
Miro J.

8
当然,您应该使用UserManager方法而不是直接访问数据库吗?
Gone Coding

3
@Josh Bjelovuk:绝对不要在有API时直接访问数据库。这就引入了新的依赖关系,即需要为初学者提供额外的上下文,但是以后用户数据库表会发生变化(过去2年中有3次变化),但API保持一致。
Gone Coding

33

它在答案的评论中,但没有人将其发布为实际解决方案。

您只需要在顶部添加using语句:

using Microsoft.AspNet.Identity;

2
我带着这个例外来到这里,我用那个解决了using。看到有15,000人访问了我认为这是一个有用的答案的问题:)
rtpHarry

2
@TrueBlueAussie,尽管不是OP问题的直接答案,但我认为提及使用是一个非常有用的补充。
StuartQ 2015年

1
为了清楚起见,这是因为.GetUserId()是一种扩展方法
FSCKur

11

Ellbar的代码有效!您只需要添加使用。

1- using Microsoft.AspNet.Identity;

还有... Ellbar的代码:

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

使用此代码(中的currentUser),您可以处理所连接用户的常规数据,如果需要更多数据,请参阅此链接。


5
它可能“起作用”,但是绝对不建议绕过提供的API并直接访问数据库。如果您确实使用了API,则不需要额外的工作来获取多余的数据,因为它已经存在于ApplicationUser对象中
编码

我同意!但是,求助于这种方式,因为今天我已经拥有一个可以在数据库中运行的系统,并且我需要一个简单的解决方案来解决这个问题!当然,在早期的系统中,我会将对象放在适当的类和标识中。
迭戈·博尔赫斯2015年

6

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

3

对于MVC 5,只需在WebApplication模板支架中的ManageController的EnableTwoFactorAuthentication方法内部,即可在此处完成:

        [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");
        }

正如微软本身所建议的,答案就在那里:

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

它将具有您在ApplicationUser类中定义的所有其他属性。


5
已经覆盖。请检查是否尚未发布相同的答案(或在现有答案中添加评论):)
Gone Coding

3

现在,asp.mvc项目模板创建了一个帐户控制器,该帐户控制器通过以下方式获取用户管理器:

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

以下对我有用:

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

0

我可以通过遵循以下代码段成功获得应用程序用户

var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
            var user = manager.FindById(User.Identity.GetUserId());
            ApplicationUser EmpUser = user;

0

如果有人正在与中的Identity用户合作web forms,我可以这样做:

var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
var user = manager.FindById(User.Identity.GetUserId());
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.