How to Seed an Admin User in Ef Core 2.1.0

How to seed an Admin user in EF Core 2.1.0?

As user cannot be seeded in a normal way in Identity just like other tables are seeded using .HasData() of .NET Core 2.1.

Microsoft Recommendation: For data that requires calls to external API, such as ASP.NET Core Identity users creation it is recommended to use custom initialization logic.

Seed Roles in .NET Core 2.1 using code given below in ApplicationDbContext Class :

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// Customize the ASP.NET Identity model and override the defaults if needed.
// For example, you can rename the ASP.NET Identity table names and more.
// Add your customizations after calling base.OnModelCreating(builder);

modelBuilder.Entity<IdentityRole>().HasData(new IdentityRole { Name = "Admin", NormalizedName = "Admin".ToUpper() });
}

Seed Users With Roles by Following the steps given below.

Step 1: New class creation

public static class ApplicationDbInitializer
{
public static void SeedUsers(UserManager<IdentityUser> userManager)
{
if (userManager.FindByEmailAsync("abc@xyz.com").Result==null)
{
IdentityUser user = new IdentityUser
{
UserName = "abc@xyz.com",
Email = "abc@xyz.com"
};

IdentityResult result = userManager.CreateAsync(user, "PasswordHere").Result;

if (result.Succeeded)
{
userManager.AddToRoleAsync(user, "Admin").Wait();
}
}
}
}

Step 2: Now Modify ConfigureServices method in Startup.cs class.

Before Modification:

services.AddDefaultIdentity<IdentityUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();

After Modification:

services.AddDefaultIdentity<IdentityUser>().AddRoles<IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>();

Step 3: Modify parameters of Configure Method in Startup.cs class.

Before Modification :

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//..........
}

After modification :

public void Configure(IApplicationBuilder app, IHostingEnvironment env, UserManager<IdentityUser> userManager)
{
//..........
}

Step 4 : Calling method of our Seed (ApplicationDbInitializer) class:

ApplicationDbInitializer.SeedUsers(userManager);

Note: You can also Seed Roles just like users by Injecting the RoleManager along with UserManager.

EF Core Seeding User Role Issue

You need to seed the Roles as well, then link the User to the Role you want.

Check this answer for more information of how you can seed the data.

Adding Admins using Seed data Asp.net core

You can create an extension method for adding user into data base and call method in program.cs file or in configure method in startup class

According to Microsoft documentation better way is use this to using seed data

Program.cs

public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args).Build();

using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var context = services.GetRequiredService<DbContext>();
DbInitializer.Initialize(context);
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred while seeding the database.");
}
}

host.Run();
}

or Configure method way

public static void Initialize(this IApplicationBuilder app)
{
using (var scope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
var dbContext = scope.ServiceProvider.GetServices<DbContext>();
//insert data in database
}
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.Initialize();
}

and this link can be helpful for seeding admin user

Creating Asp.net Identity user in Seed method of Db Initializer

In asp.net-identity-2 usermanager has non async methods to create.

var user = new ApplicationUser { Email = "admin@myemail.com", UserName = "admin@myemail.com" };
manager.Create(user, "Temp_123");

Same for rolemanager if you want to create "admin" role.

var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));
roleManager.Create(new Role("admin"));

make the user admin

manager.AddToRole(user.Id, "admin");

Edit: As trailmax commented, Create() extension method comes in with Microsoft.AspNet.Identity namespace so do not forget using Microsoft.AspNet.Identity

EFcore with IdentityDbContext and hasData seeding creates IdentityRole

As I understand, you are following the following approach:

modelBuilder.Entity<IdentityRole>().HasData(new IdentityRole { Name = "Admin", NormalizedName = "Admin".ToUpper() });

There are two problems with this code.

The first is the usage of modelBuilder.Entity<IdentityRole>(). This makes IdentityRole class to be treated by EF Core as an entity, hence the IdentityRoles table it tries to create. It's because IdentityRole class is different from what your model is using - IdentityRole<Guid>. Change it to modelBuilder.Entity<IdentityRole<Guid>>() (and also the new operator) and the problem will be solved.

The second problem is that HasData requires PK values to be specified, as explained in the Data Seeding section of the EF Core documentation:

The primary key value needs to be specified even if it's usually generated by the database. It will be used to detect data changes between migrations.

So additionally to changing the HasData generic type argument, you need to pre generate Guid to be used as Id for the new role (see Entity Framework Core Auto Generated guid for more details a the similar issue) and use something like this:

modelBuilder.Entity<IdentityRole<Guid>>().HasData(
new IdentityRole<Guid>
{
Id = new Guid("pre generated value"),
Name = "Admin",
NormalizedName = "Admin".ToUpper()
}
);

Asp.net core identity: check if user is admin in cshtml

It's a known issue in the version of 2.1 and has been fixed in 2.2 preview-1 .

In asp.net core 2.1, AddDefaultIdentity is used and the injection becomes to

services.AddDefaultIdentity<IdentityUser>()
.AddRoles<IdentityRole>()

,will not make Roles enabled by default and it always return false for User.IsInRole.

To walk around it , instead of using the new AddDefaultIdentity<TUser>() to configure Identity , simply use the old-style api :

services.AddIdentity<IdentityUser, IdentityRole>()
.AddRoleManager<RoleManager<IdentityRole>>()
.AddDefaultUI()
.AddDefaultTokenProviders()
.AddEntityFrameworkStores<ApplicationDbContext>();

Refer to https://github.com/aspnet/Identity/issues/1813



Related Topics



Leave a reply



Submit