【问题标题】:ASP.NET MVC 5 - Identity. How to get current ApplicationUserASP.NET MVC 5 - 身份。如何获取当前的ApplicationUser
【发布时间】:2014-01-22 10:21:40
【问题描述】:

我的项目中有一个 Article 实体,它具有名为 AuthorApplicationUser 属性。如何获取当前记录的ApplicationUser 的完整对象?在创建新文章时,我必须将Article 中的Author 属性设置为当前的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)”方法,并且该方法无法转换为存储表达式。 来源=实体框架

【问题讨论】:

    标签: c# asp.net-mvc-5 identity asp.net-identity


    【解决方案1】:

    您应该不需要直接在数据库中查询当前的 ApplicationUser。

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

    另一个问题是对数据库的底层 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 月更新

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

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

    附录:

    在 Azure 中使用 EF 和 Identity Framework 时,通过远程数据库连接(例如,本地主机测试到 Azure 数据库),您可能会随机遇到可怕的“错误:19 - 物理连接不可用”。由于原因隐藏在 Identity Framework 中,您无法在其中添加重试(或似乎缺少 .Include(x-&gt;someTable)),因此您需要在项目中实现自定义 SqlAzureExecutionStrategy

    【讨论】:

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

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

    正确代码:

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

    【讨论】:

    • User.Identiy.GetUserId 对我来说不存在。那是我自定义的方法吗?我只起身 User.Identity
    • 没关系...您需要“使用 Microsoft.AspNet.Identity;”让那个方法在那里。
    • 请注意,用户对象仅在控制器中可见。
    • 您当然应该使用UserManager 方法而不是直接访问数据库吗?
    • @Josh Bjelovuk:当 API 可用时,切勿直接访问数据库。这为初学者引入了一个新的依赖关系,即为初学者提供额外的上下文,但未来用户数据库表会发生变化(过去 2 年中发生了 3 次),但 API 是一致的。
    【解决方案3】:

    它在答案的 cmets 中,但没有人将此作为实际解决方案发布。

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

    using Microsoft.AspNet.Identity;
    

    【讨论】:

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

    Ellbar 的代码有效!您只需添加 using。

    1 - using Microsoft.AspNet.Identity;

    还有……Ellbar的代码:

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

    使用此代码(在currentUser 中),您可以处理连接用户的一般数据,如果您需要额外数据...请参阅this link

    【讨论】:

    • 它可能“工作”,但肯定不建议绕过提供的 API 并直接访问数据库 如果您确实使用了该 API,则不需要额外的工作来获取额外的数据因为它已经在 ApplicationUser 对象中
    • 我同意!但是,之所以采用这种方式,是因为我今天已经有一个系统,在数据库中运行,我需要一个简单的解决方案来解决这个问题!当然,在早期的系统中,我会将对象放在适当的类和身份中。
    【解决方案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】:

        对于 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 类中定义的所有附加属性。

        【讨论】:

        • 已经涵盖。请检查是否尚未发布相同的答案(或对现有答案添加评论):)
        【解决方案8】:

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

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

        以下对我有用:

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

        【讨论】:

          【解决方案9】:

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

          var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
          var user = manager.FindById(User.Identity.GetUserId());
          

          【讨论】:

            【解决方案10】:

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

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

            【讨论】:

              猜你喜欢
              • 2015-03-07
              • 1970-01-01
              • 1970-01-01
              • 2018-10-30
              • 1970-01-01
              • 2014-04-30
              • 1970-01-01
              • 2013-09-06
              相关资源
              最近更新 更多