2015-03-18 3 views
3

Я использую идентификатор ASP.NET (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(); 
     } 
    } 

Спасибо за любую помощь.

+0

Да, я борюсь с одним и тем же, а не из-за внешней петли. Я отследил его до метода 'RemoveClaimsAsync' в UserStore и код: ' '' foreach (TUserClaim локальный в перечисляемом) { this._userClaims.Remove (local); } '' ' У кого-нибудь есть идея? –

+0

Да, я закончил в том же месте ... –

ответ

2

Я нашел решение в конце концов, однако, он не является нигде в любом случае. Если кто-нибудь придумает лучшее решение, я все равно буду рад его видеть.

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; 
} 
+0

Кажется немного экстремальным для доступа к базе данных напрямую, но я согласен - нормальный RemoveClaim, похоже, имеет проблему (см. Мой комментарий к вопросу). Спасибо за решение, поскольку я действительно застрял на этом. –

0

Я перепутан с отличным пакетом ElCamino.AspNet.Identity.AzureTable который обеспечивает Azure реализацию на основе хранения Таблицы для замены стандартного Microsoft.AspNet.Identity.EntityFramework Entity Framework на базу хранения идентичности.

С установленным пакетом ElCamino.AspNet.Identity.AzureTable нормальный userManager.RemoveClaimAsync работает должным образом. Из этого и взгляда на то, где ошибка возникает в стандартном пакете, я подозреваю, что это ошибка в Microsoft.AspNet.Identity.EntityFramework.

+0

[Ответ] (http://stackoverflow.com/questions/28785300/removeclaimasync-identity-2-2) на другой аналогичный вопрос подтверждает, что в ASP.Net есть ошибка. @Lucho говорит, что исправлено в версии 2.1.1, но это пока недоступно в Nuget, но доступно в [nightly build] (https://www.myget.org/gallery/aspnetwebstacknightly) –

2

Это хорошо сработало для меня. Надеюсь это поможет!

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

Context.SaveChanges(); 
Смежные вопросы