How to Seed Users and Roles with Code First Migration using Identity ASP.NET Core

My way of doing this is to create a class in models namespace.

public class SampleData
{
    public static void Initialize(IServiceProvider serviceProvider)
    {
        var context = serviceProvider.GetService<ApplicationDbContext>();

        string[] roles = new string[] { "Owner", "Administrator", "Manager", "Editor", "Buyer", "Business", "Seller", "Subscriber" };

        foreach (string role in roles)
        {
            var roleStore = new RoleStore<IdentityRole>(context);

            if (!context.Roles.Any(r => r.Name == role))
            {
                roleStore.CreateAsync(new IdentityRole(role));
            }
        }


        var user = new ApplicationUser
        {
            FirstName = "XXXX",
            LastName = "XXXX",
            Email = "[email protected]",
            NormalizedEmail = "[email protected]",
            UserName = "Owner",
            NormalizedUserName = "OWNER",
            PhoneNumber = "+111111111111",
            EmailConfirmed = true,
            PhoneNumberConfirmed = true,
            SecurityStamp = Guid.NewGuid().ToString("D")
        };


        if (!context.Users.Any(u => u.UserName == user.UserName))
        {
            var password = new PasswordHasher<ApplicationUser>();
            var hashed = password.HashPassword(user,"secret");
            user.PasswordHash = hashed;

            var userStore = new UserStore<ApplicationUser>(context);
            var result = userStore.CreateAsync(user);

        }

        AssignRoles(serviceProvider, user.Email, roles);

        context.SaveChangesAsync();
    }

    public static async Task<IdentityResult> AssignRoles(IServiceProvider services, string email, string[] roles)
    {
        UserManager<ApplicationUser> _userManager = services.GetService<UserManager<ApplicationUser>>();
        ApplicationUser user = await _userManager.FindByEmailAsync(email);
        var result = await _userManager.AddToRolesAsync(user, roles);

        return result;
    }

}

To run this code on startup. In Startup.cs at end of configure method just after route configuration add following code as Stafford Williams said before.

SampleData.Initialize(app.ApplicationServices);

As of the time of this writing, there is no plug in place for seeding the database, but you can create a class and add it to your container to do the same thing on app start, here is how I've done it, first create a class:

public class YourDbContextSeedData
{
    private YourDbContext _context;

    public YourDbContextSeedData(YourDbContext context)
    {
        _context = context;
    }

    public async void SeedAdminUser()
    {
        var user = new ApplicationUser
        {
            UserName = "[email protected]",
            NormalizedUserName = "[email protected]",
            Email = "[email protected]",
            NormalizedEmail = "[email protected]",
            EmailConfirmed = true,
            LockoutEnabled = false,
            SecurityStamp = Guid.NewGuid().ToString()
        };

        var roleStore = new RoleStore<IdentityRole>(_context);

        if (!_context.Roles.Any(r => r.Name == "admin"))
        {
            await roleStore.CreateAsync(new IdentityRole { Name = "admin", NormalizedName = "admin" });
        }

        if (!_context.Users.Any(u => u.UserName == user.UserName))
        {
            var password = new PasswordHasher<ApplicationUser>();
            var hashed = password.HashPassword(user, "password");
            user.PasswordHash = hashed;
            var userStore = new UserStore<ApplicationUser>(_context);
            await userStore.CreateAsync(user);
            await userStore.AddToRoleAsync(user, "admin");
        }

        await _context.SaveChangesAsync();
    }

Register the type in ConfigureServices method of your Startup.cs class:

services.AddTransient<YourDbContextSeedData>();

Next pass the YourDbContextSeedData class to the Configure method of your Startup.cs class and use it:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, YourDbContextSeedData seeder)
{
  seeder.SeedAdminUser();
}

You can seed Users and Roles in OnModelCreating() method inside IdentityDbContext.cs file as shown below. Notice that the keys have to be predefined to avoid seeding new users and roles everytime this method is executed.

protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        //Seeding a  'Administrator' role to AspNetRoles table
        modelBuilder.Entity<IdentityRole>().HasData(new IdentityRole {Id = "2c5e174e-3b0e-446f-86af-483d56fd7210", Name = "Administrator", NormalizedName = "ADMINISTRATOR".ToUpper() });


        //a hasher to hash the password before seeding the user to the db
        var hasher = new PasswordHasher<IdentityUser>();


        //Seeding the User to AspNetUsers table
        modelBuilder.Entity<IdentityUser>().HasData(
            new IdentityUser
            {
                Id = "8e445865-a24d-4543-a6c6-9443d048cdb9", // primary key
                UserName = "myuser",
                NormalizedUserName = "MYUSER",
                PasswordHash = hasher.HashPassword(null, "Pa$$w0rd")
            }
        );


        //Seeding the relation between our user and role to AspNetUserRoles table
        modelBuilder.Entity<IdentityUserRole<string>>().HasData(
            new IdentityUserRole<string>
            {
                RoleId = "2c5e174e-3b0e-446f-86af-483d56fd7210", 
                UserId = "8e445865-a24d-4543-a6c6-9443d048cdb9"
            }
        );
        

    }

If you have async issues, try the following code:

    protected override void Seed(ApplicationDbContext context)
    {
        //  This method will be called after migrating to the latest version.

        string[] roles = new string[] { "Admin", "User" };
        foreach (string role in roles)
        {
            if (!context.Roles.Any(r => r.Name == role))
            {
                context.Roles.Add(new IdentityRole(role));
            }
        }

        //create user UserName:Owner Role:Admin
        if (!context.Users.Any(u => u.UserName == "Owner"))
        {
            var userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
            var user = new ApplicationUser
            {
                FirstName = "XXXX",
                LastName = "XXXX",
                Email = "[email protected]",
                UserName = "Owner",
                PhoneNumber = "+111111111111",
                EmailConfirmed = true,
                PhoneNumberConfirmed = true,
                SecurityStamp = Guid.NewGuid().ToString("D"),
                PasswordHash = userManager.PasswordHasher.HashPassword("secret"),
                LockoutEnabled = true,
            };
            userManager.Create(user);
            userManager.AddToRole(user.Id, "Admin");
        }            

        context.SaveChanges();
    }

This is not yet implemented. As a work around, just write your own class that will check the database for the existence of your entities, add them if they don't exist, and call this class from your Startup.cs.