0

I want to seed the default DB with an admin user before I start the project on .NET Core Default MVC application. The code is as below:

public void SeedDb(ApplicationDbContext Context, IServiceProvider ServiceProvider, IConfiguration Configuration)
    {

        if (Context.Users.Count() > 0) return;

        var UserManager = ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();

        var ApplicationUser = new ApplicationUser()
        {
            Email = Configuration["Email"],
            NormalizedEmail = Configuration["Email"],
            LockoutEnabled = false,
            NormalizedUserName = Configuration["Email"],
            SecurityStamp = "579355dd - a64c - 498d - a0b5 - 9e55754c9109",
            EmailConfirmed = true,
            ConcurrencyStamp = null,
            Id = "977ec1a5-1ae7-4658-952a-6b5dccd75a85",
            PasswordHash ="",
            PhoneNumber = "333333333333",
            LockoutEnd = null,
            AccessFailedCount = 1,
            PhoneNumberConfirmed = true,
            TwoFactorEnabled = false,
            UserName = Configuration["Email"]
        };

        var Password =  HashPassword(ApplicationUser, Configuration["Password"]);

        if (VerifyHashedPassword(ApplicationUser, Password, Configuration["Password"]) == PasswordVerificationResult.Success)
        {
            ApplicationUser.PasswordHash = Password;
        }

        Context.Users.Add(ApplicationUser);
        Context.SaveChanges();

        var RoleManager = ServiceProvider.GetRequiredService<RoleManager<IdentityRole>>();
        string[] Roles = { "Admin", "Manager", "User" };

        foreach (string RoleName in Roles) {
            RoleManager.CreateAsync(new IdentityRole(RoleName));
        }

         var Admin = Context.Users.SingleOrDefault(m => m.Email == Configuration["Email"]);
         var Role =  Context.Roles.SingleOrDefault(m => m.Name == Configuration["Role"]);
         IdentityUserRole<string> UserRole = new IdentityUserRole<string>() { UserId = Admin.Id, RoleId = Role.Id };

         Context.UserRoles.Add(UserRole);
         Context.SaveChanges();
    }

Everything runs perfect except I can't seed the UserRole DB with Data. From DBContext I add IdentityUserRole entity and save the changes to DB. Although nothing passed under the DB. Any suggestion?

2 Answers2

1

Create a class named StartupDbInitializer:

using System;
using System.Collections.Generic;
using System.Linq;
using Core.Entities;
using Microsoft.AspNetCore.Identity;

namespace Core.Startups
{
    public class StartupDbInitializer
    {
        private const string AdminEmail = "admin@admin.com";
        private const string AdminPassword = "StrongPasswordAdmin123!";

        private static readonly List<IdentityRole> Roles = new List<IdentityRole>()  
        {
            new IdentityRole {Name = "Admin", NormalizedName = "ADMIN", ConcurrencyStamp = Guid.NewGuid().ToString()}
        };

        public static void SeedData(ApplicationDbContext dbContext, UserManager<User> userManager)
        {
            dbContext.Database.EnsureCreated();
            AddRoles(dbContext);
            AddUser(dbContext, userManager);
            AddUserRoles(dbContext, userManager);
        }

        private static void AddRoles(ApplicationDbContext dbContext)
        {
            if (!dbContext.Roles.Any())
            {
                foreach (var role in Roles)
                {
                    dbContext.Roles.Add(role);
                    dbContext.SaveChanges();
                } 
            }
        }

        private static async void AddUser(ApplicationDbContext dbContext, UserManager<User> userManager)
        {
            if (!dbContext.Users.Any())
            {
                var user = new User { 
                    UserName = AdminEmail, 
                    Email = AdminEmail, 
                    IsEnabled = true, 
                    EmailConfirmed = true,
                };
                await userManager.CreateAsync(user, AdminPassword);
            }
        }

        private static void AddUserRoles(ApplicationDbContext dbContext, UserManager<User> userManager)
        {
            if (!dbContext.UserRoles.Any())
            {
                var userRole = new IdentityUserRole<string>
                {
                    UserId = dbContext.Users.Single(r => r.Email == AdminEmail).Id,
                    RoleId = dbContext.Roles.Single(r => r.Name == "Admin").Id
                };
                dbContext.UserRoles.Add(userRole);
                dbContext.SaveChanges();
            }
        }
    }
}

Then call it in your Startup's Configure method:

public void Configure(
    IApplicationBuilder app, 
    IHostingEnvironment env, 
    ApplicationDbContext dbContext,
    UserManager<User> userManager,
)
{
   // rest of code...
    StartupDbInitializer.SeedData(dbContext, userManager);
}

Above, I inject my DbContext and UserManager<T>.

Ozgur
  • 3,738
  • 17
  • 34
0

Try this line... it must work.

ApplicationUser user = await _usermanager.FindByEmailAsync("your.email@mymail.com");
if (!await _usermanager.IsInRoleAsync(user, "Admin"))
{
    await _usermanager.AddToRoleAsync(user, "Admin");
}

When you tried it and it works, change it to your config parameters if you prefer them. It's not that hard to get it to work, you have everything you need in UserManager and RoleManager classes.

I still say you have to check if the role exist in table before you insert it, I got all my roles populated every time I run the application before I added the check.

if ((await _roleManager.FindByNameAsync("Admin")) == null)
{
    await _roleManager.CreateAsync(new IdentityRole { Name = "Admin" });
}
chrillelundmark
  • 305
  • 1
  • 2
  • 18