简体   繁体   中英

ASP.NET EF6 Identity 2 Update User Claims Error Updating For User

I have a web application in which I am using ASP.NET Identity 2 Claims for the access control list for Users of the site. I have all the claims available correctly in the ApplicationUser model, which has a Claims list.

I am trying to clear the claims for a user and then give them a whole set of new ones. I have a Claim Group object which contains a list of Claim Items

[HttpPost, ValidateAntiForgeryToken]
    public async Task<ActionResult> Claims_UpdateByClaimGroup([Bind(Include = "Id,SelectedClaimGroupId")] UserClaimsViewModel viewModel)
    {
        User user = await _repository.GetAsync<User>(viewModel.Id);
        ApplicationUser appUser = await UserManager.FindByIdAsync(user.AppUser.Id);
        var claimGroup = await _repository.GetAsync<ClaimGroup>(Convert.ToInt32(viewModel.SelectedClaimGroupId));

        appUser.Claims.Clear();// Clear all the claims first

        // Then add the new claims.
        foreach (ClaimGroupItems claimGroupItem in claimGroup.Items)
        {
            //UserManager.AddClaim(user.AppUser.Id, new Claim(claimGroupItem.MenuItemId.ToString(), claimGroupItem.ClaimValue));
            appUser.Claims.Add(new IdentityUserClaim()
            {
                ClaimType = claimGroupItem.MenuItemId.ToString(),
                ClaimValue = claimGroupItem.ClaimValue,
                UserId = user.AppUser.Id,
            });
        }

        try
        {
            _repository.Save<User>(appUser.User);
            //await UserManager.UpdateAsync(appUser);
        }
        catch (DbEntityValidationException dbEx)
        {
            foreach (var validationErrors in dbEx.EntityValidationErrors)
            {
                foreach (var validationError in validationErrors.ValidationErrors)
                {
                    Trace.TraceInformation("Class: {0}, Property: {1}, Error: {2}",
                        validationErrors.Entry.Entity.GetType().FullName,
                        validationError.PropertyName,
                        validationError.ErrorMessage);
                }
            }

            throw;  // You can also choose to handle the exception here...
        }

        return RedirectToAction("Claims", new { id = viewModel.Id, Updated = true });
    }

You can see here a few things:

  1. I am trying to remove, add and Save the claims on the ApplicationUser.Claims object without using the UserManager methods. (ApplicationUser contains a reference to User).
  2. I have a try catch block because it is throwing some validation errors. The error message that comes out on the trace is:

Class: System.Data.Entity.DynamicProxies.IdentityUserClaim_FCA22938ED9E4AAF12F5F2E4717CA49CC6F53B512CF2A371AA0C95D210D35870, Property: UserId, Error: The UserId field is required.

  1. If I try and use the UserManager methods I get the same error.

    UserManager.AddClaim(user.AppUser.Id, new Claim(claimGroupItem.MenuItemId.ToString(), claimGroupItem.ClaimValue));

and

await UserManager.UpdateAsync(appUser);

The error is caused by this being called: appUser.Claims.Clear();

How can I correctly update the claims for the user?

I got it working. For some reason appUser.Claims.Clear() wasn't working and was causing the userId is null error. So I've manually removed the old claims in a loop, and it all works now.

[HttpPost, ValidateAntiForgeryToken]
public async Task<ActionResult> Claims_UpdateByClaimGroup([Bind(Include = "Id,SelectedClaimGroupId")] UserClaimsViewModel viewModel)
{
    var claimGroup = await _repository.GetAsync<ClaimGroup>(Convert.ToInt32(viewModel.SelectedClaimGroupId));
    User user = await _repository.GetAsync<User>(viewModel.Id);
    ApplicationUser appUser = await UserManager.FindByIdAsync(user.AppUser.Id);

    // Remove all the old claims
    var listToRemove = appUser.Claims.ToArray();
    foreach (var item in listToRemove)
    {
        await UserManager.RemoveClaimAsync(item.UserId, new Claim(item.ClaimType, item.ClaimValue));
    }

    try
    {
        // Then add the new claims.
        foreach (ClaimGroupItems claimGroupItem in claimGroup.Items)
        {
            //UserManager.AddClaim(appUser.Id, new Claim(claimGroupItem.MenuItemId.ToString(), claimGroupItem.ClaimValue));
            appUser.Claims.Add(new IdentityUserClaim()
            {
                UserId = appUser.Id,
                ClaimType = claimGroupItem.MenuItemId.ToString(),
                ClaimValue = claimGroupItem.ClaimValue,
            });
        }
        await UserManager.UpdateAsync(appUser);
    }
    catch (DbEntityValidationException dbEx)
    {
        foreach (var validationErrors in dbEx.EntityValidationErrors)
        {
            foreach (var validationError in validationErrors.ValidationErrors)
            {
                Trace.TraceInformation("Class: {0}, Property: {1}, Error: {2}",
                    validationErrors.Entry.Entity.GetType().FullName,
                    validationError.PropertyName,
                    validationError.ErrorMessage);
            }
        }

        throw;  // You can also choose to handle the exception here...
    }

    return RedirectToAction("Claims", new { id = viewModel.Id, Updated = true });
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM