← Back to articles

ASP.Net 5 Identity Framework 3.0 manually adding users

Bulk-importing users through Identity Framework 3 kept failing with disposed-object and modified-collection errors. The culprit: async void. Change to async Task and await properly — code included.

Tedd

Identity Framework 3 is in release candidate along with ASP.Net 5.

The problem

I set up a web project in ASP.Net 5 and created a controller for user import. It’s just some simple code that attempts to add multiple users. Adding a single user works great, but if I attempt to perform multiple operations in one go I run into problems.

  • Adding multiple users gives me “Collection was modified; enumeration operation may not execute” on second user.

  • Attempting to update the password for more multiple users gives me “Cannot access a disposed object” on second user.

The problem turned out to be me calling my commands in “async void” methods. (public async void MyMethod(…) { … }). Changing it to “public async Task” instead and awaiting it to finish seems to solve the problem.

But in case someone needs it, here is the solution I used for manually adding users.

My solution

By digging into the source code of Identity Framework I figured out how to fill the user objects myself.

Here is a simple method to get you going. Note that it required your DbContext to inherit from IdentityDbContext.

private static PasswordHasher<ApplicationUser> _passwordHasher = new PasswordHasher<ApplicationUser>();

private static void AddUser(DbContext dbContext, ApplicationUser user, string userPassword) 
{
 // If you need to generate user id this is how
 // But no need - it is done automatically when you create user object
 //user.Id = Guid.NewGuid().ToString();

 // Normally done by UserManager.CreateAsync
 user.PasswordHash = _passwordHasher.HashPassword(user, userPassword);
 user.SecurityStamp = Guid.NewGuid().ToString();
 user.LockoutEnabled = true;

 if (!string.IsNullOrWhiteSpace(user.Email)) 
 user.NormalizedEmail = user.Email.Normalize().ToUpperInvariant();

 if (!string.IsNullOrWhiteSpace(user.UserName))
 user.NormalizedUserName = user.UserName.Normalize().ToUpperInvariant();
 // End of stuff done by UserManager.CreateAsync

 // You may want to use AddRange to optimize inserts dbContext.Add(user);
 // And only call SaveChanges() once you've added all users, so if you add many users you want to comment this out and all it yourself at the end dbContext.SaveChanges();
} 

Written by Tedd · Oslo, Norway

Updated 5 Jan 2017

Follow the journal via RSS