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
Entity Framework Thread Safety
Treeview Remove Checkbox by Some Nodes
Map Category Parent Id Self Referencing Table Structure to Ef Core Entity
Windows Forms Designer and Wpf Designer for .Net Core
How to Embed an Application Manifest into an Application Using VS2008
Configurationmanager Doesn't Save Settings
In Mvvmcross How to Do Custom Bind Properties
Setting Unique Constraint with Fluent API
How to Merge a List of Lists with Same Type of Items to a Single List of Items
Cryptographicexception Was Unhandled: System Cannot Find the Specified File
Variables Within App.Config/Web.Config
I Need a Fast Runtime Expression Parser
Observablecollection and Threading
Why Does Stylecop Recommend Prefixing Method or Property Calls with "This"