31

I am trying to set the value of a column in aspnetuser table from a different controller (not accountcontroller). I have been trying to access UserManager but I can't figure our how to do it.

So far I have tried the following in the controller I want to use it in:

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

This would not compile (I think because UserManager has not been instantiated the controller)

I also tried to create a public method in the AccountController to accept the value I want to change the value to and do it there but I can't figure out how to call it.

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

    return;
}

How do you access and edit user data outside of the Account Controller?

UPDATE:

I tried to instantiate the UserManager in the other controller like so:

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

I the project complied (got a little excited) but when I ran the code I get the following error:

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

UPDATE 2:

I have moved the function to the IdentityModel (don't ask I am clutching at straws here) like so:

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

However I am still getting the following:

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

There is also the following class in IdentitiesModels.cs:

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

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

What am I doing wrong here? It feels like I am completely barking up the wrong tree. All I am trying to do is update a column in aspnetuser table from the action of a different controller (i.e not the AccountsController).

unicorn2
  • 844
  • 13
  • 30
Spionred
  • 797
  • 2
  • 10
  • 27
  • It seems from the error message like the "db" you're passing to the store, is not the same DbContext that contains your Identity tables. – Iravanchi Mar 27 '15 at 07:50
  • do you have `public class ApplicationDbContext : IdentityDbContext{}` in your `db` context class? – Mike Debela Mar 27 '15 at 07:51
  • 5
    `var userManager = new UserManager(new UserStore(ApplicationDbContext.Create()));` – Mike Debela Mar 27 '15 at 08:08
  • Yup, That worked a treat. Thank you! – Spionred Mar 27 '15 at 08:24
  • I don't have enough rep yet to comment, so I am making a new an answer post. Just to add to @Iravanchi answer the extension method for GetOwinContext() has been moved to Microsoft.AspNet.Identity.Owin; http://stackoverflow.com/questions/23532964/microsoft-owin-iowincontext-does-not-contain-a-definition-for-getusermanager – salli Jan 13 '17 at 22:38

5 Answers5

35

If you're using the default project template, the UserManager gets created the following way:

In the Startup.Auth.cs file, there's a line like this:

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

that makes OWIN pipeline instantiate an instance of ApplicationUserManager each time a request arrives at the server. You can get that instance from OWIN pipeline using the following code inside a controller:

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

If you look carefully at your AccountController class, you'll see the following pieces of code that makes access to the ApplicationUserManager possible:

    private ApplicationUserManager _userManager;

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

Please note, that in case you need to instantiate the ApplicationUserManager class, you need to use the ApplicationUserManager.Create static method so that you have the appropriate settings and configuration applied to it.

Iravanchi
  • 5,139
  • 9
  • 40
  • 56
  • Thanks for the contribution. The suggestion in the comment above worked. I kept the code in the IdentityModels.cs file as I will need to access it in multiple places. – Spionred Mar 27 '15 at 08:26
  • 2
    I suggest that you retrieve the `UserManager` from OWIN context instead of creating a new instance, as it is created in each request anyway, and creating a new one is redundant overhead. – Iravanchi Mar 27 '15 at 08:40
5

If you have to get UserManager's instance in another Controller just add its parameter in Controller's constructor like this

public class MyController : Controller
{
    private readonly UserManager<ApplicationUser> _userManager;

    public MyController(UserManager<ApplicationUser> userManager)
    {
        _userManager = userManager;;
    }
}

But I have to get UserManager in a class that is not controller !

Any help would be appreciated.

UPDATE

I am considering you are using asp.net core

Abubakar Ikram
  • 433
  • 9
  • 23
  • But how to you pass it to your controller in the first place? I have no references to my controller in my entire project, so I don't know how to pass it a reference to the userManager? Where is it actually instantiated? – rollsch Dec 20 '16 at 05:34
  • No no. UserManager will be injected to your application controllers from your startup.cs class. Make an ASP.NET Identity project in ASP.NET Core and see the startup.cs class. The following code is injecting UserManager Instance to your controllers services.AddIdentity() .AddEntityFrameworkStores() .AddDefaultTokenProviders(); – Abubakar Ikram Dec 28 '16 at 10:27
  • So I see, lots of magic going on. Hard to follow when all the code that does this stuff is hidden away. – rollsch Dec 28 '16 at 14:05
  • If I try this, I get an error that the controller has no default constructor. – Jonathan Wood Feb 22 '17 at 00:22
  • @JonathanWood try to make another constructor with empty parameters then chek – Abubakar Ikram Feb 27 '17 at 06:54
  • 1
    @ДвυΒдкдя: Yes, of course. But then I don't have a `UserManager` instance. – Jonathan Wood Feb 27 '17 at 16:42
  • @JonathanWood create a new asp.net core application with user authentication and see AccountController – Abubakar Ikram Mar 08 '17 at 07:17
0

I ran into this same problem and modified my code to pass a reference to the UserManager class from the Controller to the Model:

//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;
}
Mitch Stewart
  • 1,253
  • 10
  • 12
0

FOR MVC 5

The steps to access usermanger or createUser outside Account controller is easy. Follow the below steps

  1. Create a controller, consider SuperAdminController
  2. Decorate the SuperAdminController same as the AccountController as below,

    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. Create User in Action method

    [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);
    }
    
Ganesh Todkar
  • 507
  • 5
  • 12
0

If you need access to the UserManager outside of a controller you can use the following:

var userStore = new UserStore<ApplicationUser>(new ApplicationDbContext());
var applicationManager = new ApplicationUserManager(userStore);
rolznz
  • 779
  • 9
  • 16