【问题标题】:Accessing UserManager outside AccountController在 AccountController 之外访问 UserManager
【发布时间】:2015-05-31 07:16:16
【问题描述】:

我正在尝试从不同的控制器(不是accountcontroller)设置aspnetuser 表中列的值。我一直在尝试访问UserManager,但我不知道该怎么做。

到目前为止,我已经在要使用的控制器中尝试了以下操作:

    ApplicationUser u = UserManager.FindById(User.Identity.GetUserId());
    u.IsRegComplete = true;
    UserManager.Update(u);

这不会编译(我认为是因为UserManager 还没有被实例化控制器)

我还尝试在AccountController 中创建一个公共方法来接受我想要将值更改为的值并在那里执行,但我不知道如何调用它。

public void setIsRegComplete(Boolean setValue)
{
    ApplicationUser u = UserManager.FindById(User.Identity.GetUserId());
    u.IsRegComplete = setValue;
    UserManager.Update(u);

    return;
}

您如何在帐户控制器之外访问和编辑用户数据?

更新:

我尝试像这样在另一个控制器中实例化 UserManager:

    var userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(db));
    ApplicationUser u = userManager.FindById(User.Identity.GetUserId());

我的项目完成了(有点兴奋),但是当我运行代码时,我收到以下错误:

Additional information: The entity type ApplicationUser is not part of the model for the current context.

更新 2:

我已将函数移至 IdentityModel(不要问我在这里抓着稻草),如下所示:

   public class ApplicationUser : IdentityUser
    {
        public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
        {
            // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
            var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
            // Add custom user claims here
            return userIdentity;
        }
        public Boolean IsRegComplete { get; set; }

        public void SetIsRegComplete(string userId, Boolean valueToSet)
        {

            var userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>());
            ApplicationUser u = new ApplicationUser();
            u = userManager.FindById(userId);

            u.IsRegComplete = valueToSet;
            return;
        }
    }

但是我仍然得到以下信息:

The entity type ApplicationUser is not part of the model for the current context.

IdentitiesModels.cs中还有如下类:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("DefaultConnection", throwIfV1Schema: false)
    {
    }

    public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }
}

我在这里做错了什么?感觉就像我完全在吠叫错误的树。我要做的就是从不同控制器(即不是 AccountsController)的操作中更新 aspnetuser 表中的列。

【问题讨论】:

  • 从错误消息看来,您传递给商店的“db”与包含您的身份表的 DbContext 不同。
  • 你的public class ApplicationDbContext : IdentityDbContext&lt;ApplicationUser&gt;{} 上下文类中有public class ApplicationDbContext : IdentityDbContext&lt;ApplicationUser&gt;{} 吗?
  • 查看上面的更新帖子 - 谢谢
  • var userManager = new UserManager&lt;ApplicationUser&gt;(new UserStore&lt;ApplicationUser&gt;(ApplicationDbContext.Create()));
  • 是的,这很奏效。谢谢!

标签: asp.net-mvc asp.net-mvc-5 asp.net-identity-2 actioncontroller


【解决方案1】:

如果您需要在控制器之外访问 UserManager,您可以使用以下方法:

var userStore = new UserStore<ApplicationUser>(new ApplicationDbContext());
var applicationManager = new ApplicationUserManager(userStore);

【讨论】:

    【解决方案2】:

    适用于 MVC 5

    在 Account 控制器之外访问 usermanger 或 createUser 的步骤很简单。请按照以下步骤操作

    1. 创建一个控制器,考虑 SuperAdminController
    2. 将 SuperAdminController 装饰成与 AccountController 相同,如下所示,

      private readonly IAdminOrganizationService _organizationService;
      private readonly ICommonService _commonService;
      private ApplicationSignInManager _signInManager;
      private ApplicationUserManager _userManager;
      
      public SuperAdminController()
      {
      }
      
      public SuperAdminController(ApplicationUserManager userManager, ApplicationSignInManager signInManager)
      {
          UserManager = userManager;
          SignInManager = signInManager;
      }
      
      public SuperAdminController(IAdminOrganizationService organizationService, ICommonService commonService)
      {
          if (organizationService == null)
              throw new ArgumentNullException("organizationService");
      
      
          if (commonService == null)
              throw new ArgumentNullException("commonService");
      
          _organizationService = organizationService;
          _commonService = commonService;
      }
      
      
      public ApplicationSignInManager SignInManager
      {
          get
          {
              return _signInManager ?? HttpContext.GetOwinContext().Get<ApplicationSignInManager>();
          }
          private set
          {
              _signInManager = value;
          }
      }
      
      
      public ApplicationUserManager UserManager
      {
          get
          {
              return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
          }
          private set
          {
              _userManager = value;
          }
      }
      
    3. 在操作中创建用户方法

      [HttpPost]
      public async Task<ActionResult> AddNewOrganizationAdminUser(UserViewModel userViewModel)
      {
          if (!ModelState.IsValid)
          {
              return View(userViewModel);
          }
      
          var user = new ApplicationUser { UserName = userViewModel.Email, Email = userViewModel.Email };
          var result = await UserManager.CreateAsync(user, userViewModel.Password);
          if (result.Succeeded)
          {
              var model = Mapper.Map<UserViewModel, tblUser>(userViewModel);
      
              var success = _organizationService.AddNewOrganizationAdminUser(model);
      
              return RedirectToAction("OrganizationAdminUsers", "SuperAdmin");
      
          }
          AddErrors(result);
          return View(userViewModel);
      }
      

    【讨论】:

      【解决方案3】:

      如果您必须在另一个 Controller 中获取 UserManager 的实例,只需将其参数添加到 Controller 的构造函数中,如下所示

      public class MyController : Controller
      {
          private readonly UserManager<ApplicationUser> _userManager;
      
          public MyController(UserManager<ApplicationUser> userManager)
          {
              _userManager = userManager;;
          }
      }
      

      但我必须在一个不是控制器的类中获取 UserManager!

      任何帮助将不胜感激。

      更新

      我正在考虑你正在使用 asp.net core

      【讨论】:

      • 但是你首先如何将它传递给你的控制器呢?我的整个项目中没有对我的控制器的引用,所以我不知道如何将它的引用传递给 userManager?它实际实例化在哪里?
      • 没有没有。 UserManager 将从您的 startup.cs 类注入到您的应用程序控制器中。在 ASP.NET Core 中创建一个 ASP.NET Identity 项目并查看 startup.cs 类。以下代码将 UserManager 实例注入您的控制器 services.AddIdentity() .AddEntityFrameworkStores() .AddDefaultTokenProviders();
      • 所以我明白了,很多魔法正在发生。当执行此操作的所有代码都被隐藏起来时,很难理解。
      • 如果我尝试这个,我得到一个控制器没有默认构造函数的错误。
      • @ДвυΒдкдя:是的,当然。但是我没有UserManager&lt;ApplicationUser&gt; 实例。
      【解决方案4】:

      我遇到了同样的问题并修改了我的代码以将 UserManager 类的引用从控制器传递给模型:

      //snippet from Controller
      public async Task<JsonResult> UpdateUser(ApplicationUser applicationUser)
      {
          return Json(await UserIdentityDataAccess.UpdateUser(UserManager, applicationUser));
      }
      
      //snippet from Data Model
      public static async Task<IdentityResult> UpdateUser(ApplicationUserManager userManager, ApplicationUser applicationUser)
      {
          applicationUser.UserName = applicationUser.Email;
          var result = await userManager.UpdateAsync(applicationUser);
      
          return result;
      }
      

      【讨论】:

        【解决方案5】:

        如果您使用默认项目模板,UserManager 将按以下方式创建:

        在 Startup.Auth.cs 文件中,有这样一行:

        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
        

        这使得 OWIN 管道在每次请求到达服务器时都会实例化一个 ApplicationUserManager 的实例。您可以使用控制器内的以下代码从 OWIN 管道获取该实例:

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

        如果您仔细查看您的 AccountController 类,您会看到以下代码片段可以访问 ApplicationUserManager

            private ApplicationUserManager _userManager;
        
            public ApplicationUserManager UserManager
            {
                get
                {
                    return _userManager ?? Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
                }
                private set
                {
                    _userManager = value;
                }
            }
        

        请注意,如果您需要实例化ApplicationUserManager 类,则需要使用ApplicationUserManager.Create 静态方法,以便对其应用适当的设置和配置。

        【讨论】:

        • 感谢您的贡献。上面评论中的建议奏效了。我将代码保存在 IdentityModels.cs 文件中,因为我需要在多个地方访问它。
        • 我建议您从 OWIN 上下文中检索 UserManager 而不是创建一个新实例,因为它是在每个请求中创建的,并且创建一个新实例是多余的开销。
        猜你喜欢
        • 1970-01-01
        • 2018-02-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-01
        • 2012-08-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多