Search code examples
c#asp.netasp.net-mvcasp.net-identity

Removing a user from a role in ASP.NET MVC 5


I'm currently building a RESTful Web API so that a user can be removed from a role within the application.

This is the UsersController (API):

public class UsersController : ApiController
{
    private ApplicationDbContext _identity;
    private readonly UserManager<ApplicationUser> _userManager;

    public UsersController()
    {
        _identity = new ApplicationDbContext();
        var store = new UserStore<ApplicationUser>(_identity);
        _userManager = new UserManager<ApplicationUser>(store);
    }              

    // --- REMOVE USER FROM ROLE HERE ---
    [HttpDelete]
    [Route("api/users/{userId}/roles/{roleName}")]
    public async void RemoveFromRole(string userId, string roleName)
    {
        var userInDb = _identity.Users.SingleOrDefault(u => u.Id == userId);

        if (userInDb == null)
            throw new HttpResponseException(HttpStatusCode.NotFound);

        var roleInDb = _identity.Roles.SingleOrDefault(r => r.Name == roleName);

        if (roleInDb == null)
            throw new HttpResponseException(HttpStatusCode.NotFound);

        await _userManager.RemoveFromRoleAsync(userInDb.Id, roleInDb.Id);
    }

I am calling the RemoveFromRole method using this AJAX request inside the view:

$("#roles").on("click", ".js-delete", function() {
    var button = $(this);
    bootbox.confirm("Are you sure you want to remove the user from this role?",
        function(result) {
            if (result) {
                $.ajax({
                    url: "/api/users/" +
                        button.attr("data-user-id") +
                        "/roles/" +
                        button.attr("data-role-name"),
                    method: "DELETE",
                    success: function() {
                        location.reload();
                        toastr.success("Role removed");
                    },
                    error: function() {
                        toastr.error("Unable to remove user from role");
                    }
                });
            }
        });
});

However when running this, the RemoveFromRoleAsyncdoes not succeed (result.Succeeded = false) and so the user is not removed from the role.

I am new to using ASP Identity, and I think I may be using the UserManager/UserStore incorrectly.


Solution

  • User manager has a method Task<IList<string>> GetRolesAsync(TKey userId) that

    Returns the roles for the user

    Use that to get the assigned roles of the user. Confirm the role to be removed exists for that user and then remove it using the user manager.

    [HttpDelete]
    [Route("api/users/{userId}/roles/{roleName}")]
    public async Task<IHttpActionResult> RemoveFromRole(string userId, string roleName) {
        var userInDb = _identity.Users.FirstOrDefault(user => user.Id == userId);
        if (userInDb == null)
            return NotFound();
    
        //get user's assigned roles
        IList<string> userRoles = await _userManager.GetRolesAsync(userId);
    
        //check for role to be removed
        var roleToRemove = userRoles.FirstOrDefault(role => role.Equals(roleName, StringComparison.InvariantCultureIgnoreCase));
        if (roleToRemove == null)
            return NotFound();
    
        var result = await _userManager.RemoveFromRoleAsync(userId, roleToRemove);
        if(result.Succeeded)
            return Ok();
    
        return BadRequest();
    }
    

    Note the action was also refactored to follow advised syntax from documentation