繁体   English   中英

删除用户的声明

[英]Remove claims from user

我正在使用ASP.NET Identity(v2)和Entity Framework。 我正在构建一个包含多个复选框的页面,每个复选框代表一个声明。 在按钮单击(我的示例中的SavePrivileges函数)我想根据我的复选框的状态调整给定用户的声明,即删除未检查的声明,并添加检查的声明。

添加声明工作正常。 但是,我似乎无法删除用户的声明。 在调用manager.RemoveClaim我得到一个InvalidOperationException,说集合已经改变。 即使我不修改user.Claims集合,我实际上也得到了这个异常。

这是我的简化示例场景:

    protected void SavePrivileges(string userId)
    {
        const string claim1Type = "...";
        const string claim2Type = "...";
        const string claim1Value = "...";
        const string claim2Value = "...";

        var store = new UserStore<IdentityUser>();
        var manager = new UserManager<IdentityUser>(store);
        var user = manager.FindById(userId);

        // Lists to keep track of changes
        var removed = new List<Claim>();
        var added = new List<Claim>();

        bool claim1Checked = CheckBox1.Checked;
        bool claim2Checked = CheckBox2.Checked;

        bool claim1Possesed = user.Claims.FirstOrDefault(claim => claim.ClaimValue == claim1Value &&
                                                                  claim.ClaimType  == claim1Type) != null;
        bool claim2Possesed = user.Claims.FirstOrDefault(claim => claim.ClaimValue == claim2Value &&
                                                                  claim.ClaimType  == claim2Type) != null;

        if (claim1Checked && !claim1Possesed)
        {
            added.Add(new Claim(claim1Type, claim1Value));
        }
        else if (!claim1Checked && claim1Possesed)
        {
            removed.Add(new Claim(claim1Type, claim1Value));
        }
        // + The same for claim2...

        // Remove extra claims
        foreach (Claim claim in removed)
        {
            manager.RemoveClaim(user.Id, claim);
        }
        // Add new claims
        foreach (Claim claim in added)
        {
            IdentityUserClaim identityUserClaim = new IdentityUserClaim { ClaimType = claim.Type, ClaimValue = claim.Value };
            user.Claims.Add(identityUserClaim);
        }

        // Save the result
        var result = manager.Update(user);
        if (result.Succeeded)
        {
            store.Context.SaveChanges();
        }
    }

谢谢你的帮助。

我最终找到了一个解决方案,然而,它在任何方面都不是优雅的。 如果有人想出更好的解决方案,我仍然会很高兴看到它。

foreach (Claim claim in removed) {
    var claimCollection = store.Context.Entry(user).Collection(u => u.Claims).CurrentValue;
    var storedClaim = claimCollection.FirstOrDefault(c => c.ClaimType == claim.Type && c.ClaimValue == claim.Value && c.UserId == user.Id);
    if (storedClaim != null)
        store.Context.Entry(storedClaim).State = EntityState.Deleted;
}

这对我很有用。 希望这可以帮助!

user.Claims.ToList().ForEach(claim => Context.Entry(claim).State = 
                             System.Data.Entity.EntityState.Deleted);

Context.SaveChanges();

我已经交换到优秀的包ElCamino.AspNet.Identity.AzureTable ,它提供了基于Azure Table存储的实现,以替换标准的Microsoft.AspNet.Identity.EntityFramework Entity Framework存储Identity。

安装ElCamino.AspNet.Identity.AzureTable包后,正常的userManager.RemoveClaimAsync按预期工作。 从这里,看看标准包中发生错误的位置,我怀疑它是Microsoft.AspNet.Identity.EntityFramework中的一个错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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