4

I am writing a user manager for a system administrator where you can perform various functions on the user object. My current dilemma is I want to be able to write something like

await UserManager.RemoveFromRoleAsync(userID, any);

and have that person removed from all previous roles.

Right now I've written this code, but it "feels" dirty and could be better. I also am getting a generic "object not set to instance of an object" error when testing it.

Controller code (userID and level are passed in from calling page):

var userID = "68790581-d2ae-4bc3-8db3-e4c8f4b0bb9f";
        string level = "FullAdmin";

//POST: /Account/MakeAdmin
        [HttpPost]
        [Authorize(Roles = "SuperAdmin")]
        public async Task<ActionResult> MakeAdmin(string userID, string level)
        {

        if(userID == null || level == null)
        {
            return View("Error");
        }

        if (level == "FullAdmin")
        {
            try
            {
                await UserManager.RemoveFromRoleAsync(userID, "Admin1");
            }

            catch { }

            try
            {
                await UserManager.RemoveFromRoleAsync(userID, "ReadOnly");
            }

            catch { }

            //Add to the desired role
            try
            {
                await UserManager.AddToRoleAsync(userID, "SuperAdmin");
            }
            catch (Exception ex)
            {
                ViewBag.Exception = ex;
            }



            return Content("Admin permissions activated");
        }

        if(level == "ReadOnlyAdmin")
        {
            try
            {
                await UserManager.RemoveFromRoleAsync(userID, "SuperAdmin");
            }

            catch { }

            try
            {
                await UserManager.RemoveFromRoleAsync(userID, "Admin1");
            }

            catch { }

    //Add to the desired role
            try
            {
                await UserManager.AddToRoleAsync(userID, "ReadOnly");
            }
            catch (Exception ex)
            {
                ViewBag.Exception = ex;
            }


            return Content("Read only admin permissions activated");
        }

        return View();
    }

This code fails - here's my stack trace:

 Test Name: PostMakeAdmin
Test FullName:  Testing.AccountTests.PostMakeAdmin
Test Source:    h:\app\Controllers\UnitTest1.cs : line 880
Test Outcome:   Failed
Test Duration:  0:00:00.5725984

Result Message: 
Test method Testing.AccountTests.PostMakeAdmin threw exception: 
System.NullReferenceException: Object reference not set to an instance of an object.
Result StackTrace:  
at System.Web.HttpContextBaseExtensions.GetOwinEnvironment(HttpContextBase context)
   at System.Web.HttpContextBaseExtensions.GetOwinContext(HttpContextBase context)
   at app.Controllers.AccountController.get_UserManager() in h:\app\Controllers\AccountController.cs:line 42
   at app.Controllers.AccountController.<MakeAdmin>d__c.MoveNext() in h:\app\Controllers\AccountController.cs:line 305
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at app.AccountTests.<PostMakeAdmin>d__d.MoveNext() in h:\app\Controllers\UnitTest1.cs:line 888
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()

Thanks to anyone who can help!

UPDATE The initial iteration problem is solved. I'm getting an error about "Object reference not set to instance of an object" in relation to my UserManager.

Here's the code establishing UserManager:

 public AccountController()
    {
    }

    public AccountController(ApplicationUserManager userManager, ApplicationSignInManager signInManager )
    {
        UserManager = userManager;
        SignInManager = signInManager;
    }

    public ApplicationUserManager UserManager
    {
        get
        {
            return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
        }
        private set
        {
            _userManager = value;
        }
    }
Dreamcasting
  • 454
  • 2
  • 5
  • 21
  • You have a syntax error at `await UserManager.RemoveFromRoleAsync(userID, ReadOnly");`. Open your quote before ReadOnly. Will make it more readable. – kspearrin May 26 '15 at 20:52

2 Answers2

19

You can get all of the roles a user is part of, iterate them and remove.

   var user = await UserManager.FindByIdAsync(userId);
   await UserManager.RemoveFromRolesAsync(userId, UserManager.GetRoles(userId).ToArray());
   await UserManager.AddToRoleAsync(userId, "NewRole");
   await UserManager.UpdateAsync(user);
Jacob Roberts
  • 1,725
  • 3
  • 16
  • 24
  • Beautiful code - definitely integrated it, but the problem persists. I still get the exception error for UserManager. – Dreamcasting May 26 '15 at 21:47
  • 1
    Getting error while unit testing? You need to mock up some dependencies. http://stackoverflow.com/questions/21194324/mocking-new-microsoft-entity-framework-identity-usermanager-and-rolemanager – Jacob Roberts May 26 '15 at 21:50
  • 2
    You code is okay, the issue is with your unit tests. There are dependencies that normally get injected when the app is ran but when running it from a unit test, it will fail because those dependencies aren't available. You have to mock up those dependencies, check the link I pasted in my comment before this. – Jacob Roberts May 26 '15 at 21:56
  • Understood. I'll mock up the details I need. Thank you so much for your help! – Dreamcasting May 26 '15 at 22:00
2

For Asp.Net Core 2.2.0 use this instead of the accepted answer

(GetRoles no longer exists, use GetRolesAsync instead)

await _userManager.RemoveFromRolesAsync(userObj, await _userManager.GetRolesAsync(userObj));
await _userManager.AddToRoleAsync(userObj, roleName);
Community
  • 1
  • 1
Tim Gerhard
  • 3,477
  • 2
  • 19
  • 40