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

Ell*_*bar 229 c# identity asp.net-mvc-5 asp.net-identity

我的项目中有一个Article实体,其中包含ApplicationUser名为的属性Author.如何获取当前记录的完整对象ApplicationUser?在创建新文章时,我必须将Author属性设置Article为当前属性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

Gon*_*ing 436

您不需要直接查询数据库以获取当前的ApplicationUser.

这引入了为初学者提供额外上下文的新依赖关系,但是前进的用户数据库表发生了变化(过去2年中有3次),但API是一致的.例如,users现在AspNetUsers在Identity Framework中调用该表,并且几个主键字段的名称不断变化,因此几个答案中的代码将不再按原样运行.

另一个问题是对数据库的底层OWIN访问将使用单独的上下文,因此来自单独的SQL访问的更改可能会产生无效结果(例如,看不到对数据库所做的更改).同样,解决方案是使用提供的API,而不是尝试解决它.

在ASP.Net标识中访问当前用户对象的正确方法(截至此日期)为:

var user = UserManager.FindById(User.Identity.GetUserId());
Run Code Online (Sandbox Code Playgroud)

或者,如果您有异步操作,请执行以下操作:

var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
Run Code Online (Sandbox Code Playgroud)

FindById要求您具有以下using语句,以便非异步UserManager方法可用(它们是UserManager的扩展方法,因此如果您不包含此方法,您将只看到FindByIdAsync):

using Microsoft.AspNet.Identity;
Run Code Online (Sandbox Code Playgroud)

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

System.Web.HttpContext.Current.User.Identity.GetUserId();
Run Code Online (Sandbox Code Playgroud)

如果您不在标准帐户控制器中,则需要将以下内容(作为示例)添加到控制器:

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; }
Run Code Online (Sandbox Code Playgroud)

2.在Controller的构造函数中添加:

    this.ApplicationDbContext = new ApplicationDbContext();
    this.UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(this.ApplicationDbContext));
Run Code Online (Sandbox Code Playgroud)

2015年3月更新

注意:Identity Framework的最新更新会更改用于身份验证的基础类之一.您现在可以从当前HttpContent的Owin Context访问它.

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

附录:

当通过远程数据库连接(例如,对Azure数据库的本地主机测试)使用EF和Identity Framework与Azure时,您可以随机点击可怕的"错误:19 - 物理连接不可用".由于原因被隐藏在Identity Framework中,您无法在其中添加重试(或似乎缺少重试.Include(x->someTable)),您需要SqlAzureExecutionStrategy在项目中实现自定义.

  • @TBA - 谢谢,我后来意识到这是一种扩展方法.需要使用添加Microsoft.AspNet.Identity.再次感谢 (5认同)
  • 无法找到类型或namesapce UserStore.我使用Microsft.AspNet.Indentity添加 (2认同)
  • @Zapnologica:这听起来像一个新问题(建议你发布).您可以并行扩展`ApplicationUser`类(特定于应用程序)和`AspNetUsers`表,它们将提供任何新字段.再说一遍:不要直接点击数据库!:) (2认同)
  • @ LifeH2O:FindById返回的ApplicationUser是*your*class,带有*your*额外属性.请试一试. (2认同)
  • 等待您的新解决方法:P (2认同)

Ell*_*bar 59

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

正确的代码:

using Microsoft.AspNet.Identity;


string currentUserId = User.Identity.GetUserId();
ApplicationUser currentUser = db.Users.FirstOrDefault(x => x.Id == currentUserId);
Run Code Online (Sandbox Code Playgroud)

  • 没关系......你需要"使用Microsoft.AspNet.Identity;" 那个方法就在那里. (9认同)
  • 当然你应该使用`UserManager`方法而不是直接命中数据库? (8认同)
  • 只是注意,User对象仅在控制器中可见. (3认同)
  • @Josh Bjelovuk:当API可用时,永远不要直接访问数据库.这引入了为初学者提供额外上下文的新依赖关系,但是前进的用户数据库表发生了变化(过去2年中有3次),但API是一致的. (3认同)
  • User.Identiy.GetUserId对我来说不存在.是我的自定义方法?我只能达到User.Identity (2认同)

rtp*_*rry 32

它在答案的评论中,但没有人发布这个作为实际的解决方案.

你只需要在顶部添加一个using语句:

using Microsoft.AspNet.Identity;
Run Code Online (Sandbox Code Playgroud)

  • 我带着那个例外来到这里,我用`using`解决了它。看到 15,000 人访问了这个问题,我认为这是一个有用的答案:) (2认同)
  • @TrueBlueAussie,尽管不是OP问题的直接答案,我觉得提到使用是一个非常有用的补充. (2认同)
  • 为了清楚起见,这是因为 `.GetUserId()` 是一个扩展方法 (2认同)

小智 11

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

1 - using Microsoft.AspNet.Identity;

并且...... Ellbar的代码:

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

使用此代码(in currentUser),您可以处理已连接用户的常规数据,如果您需要额外数据...请参阅此链接

  • 它可能"工作",但肯定不是*建议*绕过提供的API并直接命中数据库如果您确实使用了API,则不需要额外的工作来获取额外的数据*,因为它已经存在于` ApplicationUser`对象* (5认同)

Set*_* IK 6

从ASP.NET Identity 3.0.0开始,这已被重构

//returns the userid claim value if present, otherwise returns null
User.GetUserId();
Run Code Online (Sandbox Code Playgroud)


Maj*_*aey 5

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;
Run Code Online (Sandbox Code Playgroud)