2

I have the following model and claims:

var bm = new UserProfileUpdateModel
{
  LastName = "new",
  FirstName = "name",
};

List<Claim> claims = new List<Claim>
{
    new Claim("family_name", bm.LastName),
    new Claim("given_name", bm.FirstName),
};

In the .NET Core 3.1 application, I am going to remove all the matched claims using _userManager.RemoveClaimsAsync() first and then add the new corresponding claim in claims using _userManager.AddClaimAsync().

Problem:

When I trying to loop the items in claims and do the remove/add, it works.

foreach(var c in claims)
{
    // principal is a ClaimsPrincipal
    var list = principal.Claims.Where(currC => currC.Type == c.Type).ToList();
    var removeResult = await _userManager.RemoveClaimsAsync(user, list);
    if(removeResult.Succeeded)
    {
        var addResult = await _userManager.AddClaimAsync(user, c);
    }
}

However, when I switched to use ForEach(),

claims.ForEach(async c =>
{
    // principal is a ClaimsPrincipal
    var list = principal.Claims.Where(currC => currC.Type == c.Type).ToList();
    var removeResult = await _userManager.RemoveClaimsAsync(user, list);
    if(removeResult.Succeeded)
    {
        var addResult = await _userManager.AddClaimAsync(user, c);
    }
});

The application will throw an exception telling me A second operation started on this context before a previous operation completed.

exception in visual studio

So the question is, what happened when I call foreach() and ForEach()? And why only ForEach() will cause the exception?

Bemn
  • 1,291
  • 1
  • 7
  • 22
  • 2
    General advice: don't use `ForEach`. I'm not sure why it was ever included in the first place, but there's almost never a good reason to use it. – DavidG Jul 27 '20 at 09:18
  • 2
    You're creating an `async` lambda. The `ForEach` is just creating the lambdas - not waiting for each to finish before running the next iteration. – Damien_The_Unbeliever Jul 27 '20 at 09:18
  • @DavidG Agreed, should have been left out of .NET Core. It's unfortunate Microsoft keeps adding backwards compatibility to 20 years old code – Camilo Terevinto Jul 27 '20 at 09:19
  • Pretty much a dupe of: https://stackoverflow.com/questions/18667633/how-can-i-use-async-with-foreach – Charleh Jul 27 '20 at 09:21
  • Thank you @Damien_The_Unbeliever I see what you mean. So basically `ForEach()` is a trap when doing async call haha. – Bemn Jul 27 '20 at 09:42

0 Answers0