25

I want to add newly registered user to a generic "User" role in my application. I am using ASP.NET Identity. My code below returns a cryptic error - Exception Details: System.Configuration.Provider.ProviderException: The role '' was not found.

Do I need to instantiate something in my account controller (role manager etc)? Here my code in the AccountController Register POST action.

    // POST: /Account/Register
    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Register(RegisterViewModel model)
    {
        if (ModelState.IsValid)
        {
            var user = new ApplicationUser() { UserName = model.UserName };
            var result = await UserManager.CreateAsync(user, model.Password);
            var person = new Person() { 
                UserName = user.UserName, 
                UserId = user.Id, 
                LastName = model.LastName, 
                FirstName = model.FirstName, 
                Email = model.Email, 
                PhoneCell = model.PhoneCell };
                Roles.AddUserToRole(model.UserName, "User");
            if (result.Succeeded)
            {
                await SignInAsync(user, isPersistent: false);
                db.People.Add(person);
                db.SaveChanges();
                return RedirectToAction("Index", "Home");
            }
            else
            {
                AddErrors(result);
            }
        }

        // If we got this far, something failed, redisplay form
        return View(model);
    }
SKale
  • 471
  • 1
  • 6
  • 15
  • By the way, the role of "User" does exist in my ASPNetRoles table. I took the adduserinrole line of code from a previous version of the application that used SimpleMembership, and it had worked then. Roles.AddUserToRole(model.UserName, "User"); – SKale Dec 30 '13 at 14:27

2 Answers2

52

You need to use UserManager to add role to the user. See below:

    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Register(RegisterViewModel model)
    {
        using (var context = new ApplicationDbContext())
        {
            if (ModelState.IsValid)
            {
                var user = new ApplicationUser() { UserName = model.UserName };
                var result = await UserManager.CreateAsync(user, model.Password);

                var roleStore = new RoleStore<IdentityRole>(context);
                var roleManager = new RoleManager<IdentityRole>(roleStore);

                var userStore = new UserStore<ApplicationUser>(context);
                var userManager = new UserManager<ApplicationUser>(userStore);
                userManager.AddToRole(user.Id, "User");

                if (result.Succeeded)
                {
                    await SignInAsync(user, isPersistent: false);
                    return RedirectToAction("Index", "Home");
                }
                else
                {
                    AddErrors(result);
                }
            }
            // If we got this far, something failed, redisplay form
            return View(model);                
        }
    }
Lin
  • 15,078
  • 4
  • 47
  • 49
  • 1
    I don't understand why this question and answer is not that popular, this answer gives the exact solution for using the default template. Thanks a lot! – CularBytes Jan 20 '15 at 21:58
  • 13
    one note, add the line `userManger.AddToRole` within the result.Secceeded. If password is not in correct format (uppercase, digits or symbols missing) it will dispose the `user.Id` and thus unable to add a role to a userId that is null – CularBytes Jan 21 '15 at 19:45
  • Oh, this worked for me too, and I was able to use it in the ManageUserRoles that had "add user to role" also. I was ready to quit MVC for good, still might, but for now the rainbow is out and birds are chirping. I'm starting to believe there is some sort of method to this madness. Thank you. – JustJohn Oct 29 '15 at 07:08
  • 1
    Shouldn't this code be in the if(result.Succeeded) section? As it stands a failure to register will still try to add the role to a non registered user. Also the final return View(Model) should be outside the using(var context...) as if this fails there will be a hang. – SimonN Mar 12 '16 at 09:01
  • 1
    Is it necessary to instantiate roleManager? Because in the example it is not used anywhere directly. – Przemek Marcinkiewicz Apr 20 '16 at 07:25
  • @Lin How do we achieve the same if the role is selected from a `dropdown of Roles`? In other words how the selected role from the dropdown is passed to above `Register Post method`? – nam Aug 15 '16 at 19:27
  • @nam, sorry this reply is late, I just saw it. Instead of using hardcoded role name in the sample called `User`, you could create a role name property in the `RegisterViewModel` class. Then when the user role is selected from the dropdown list, pass the selected value (role name) to the role name property. – Lin Aug 22 '16 at 02:09
  • But every time a user registers, this code will run and will create a role named "User" multiple time, or it just skips if role already exists and just adds the user to that role? – Unbreakable Aug 15 '17 at 13:20
21

If you're using the built in authentication manager and Account Controller then this will do it:

UserManager.AddToRole(user.Id, "<Role>");
Willy David Jr
  • 8,604
  • 6
  • 46
  • 57
ASPCoder1450
  • 1,651
  • 4
  • 23
  • 47