In my website, I want to let login the admin with an account in order to modify the database. Also, I might add some roles and accounts in the future.
So, I am trying to implement identity.
I made a project in Visual Studio 2019 (not sure if that is important) and choose ASP.NET Core 2.2 (I installed Core 2.2 on my own) with MVC, Authentication with individual user accounts and I let clicked the box which said: "configure for HTTPS".
Once made the project, I open it, make a random account, got an error and then migrate the database to fix it.
Then, I add in appsetting.json
:
"UserSettings": {
"UserName": "MyAdminUser",
"UserEmail": "MyAdminUser@gmail.com",
"UserPassword": "A_123456a"
}
Create a new class inside the folder Data
:
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace WebApplication1.Data {
public static class Seed {
public static async Task CreateRoles(IServiceProvider serviceProvider, IConfiguration Configuration) {
// Add customs roles
var RoleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
// Note: I used IdentityUser instead of make my ApplicationUser as other people do because the default idendity is fine for me, I don't need additional fields nor I want to make this more difficult.
var UserManager = serviceProvider.GetRequiredService<UserManager<IdentityUser>>();
string[] roleNames = { "Admin" };
IdentityResult roleResult;
foreach (var roleName in roleNames) {
// Create roles and seeding them to the database
var roleExist = await RoleManager.RoleExistsAsync(roleName);
if (!roleExist) {
roleResult = await RoleManager.CreateAsync(new IdentityRole(roleName));
}
}
// Create a super user
var poweruser = new IdentityUser {
UserName = Configuration.GetSection("AppSettings")["UserSettings:UserName"],
Email = Configuration.GetSection("AppSettings")["UserSettings:UserEmail"]
};
string userPassword = Configuration.GetSection("AppSettings")["UserSettings:UserPassword"];
var user = await UserManager.FindByEmailAsync(Configuration.GetSection("AppSettings")["UserSettings:UserEmail"]);
if (user == null) {
var createPowerUser = await UserManager.CreateAsync(poweruser, userPassword);
if (createPowerUser.Succeeded) {
// Assign the new user the "Admin" role
await UserManager.AddToRoleAsync(poweruser, "Admin");
}
}
}
}
}
And finally replace the Main
method of Program
class to:
public static void Main(string[] args) {
var host = CreateWebHostBuilder(args).Build();
using (var scope = host.Services.CreateScope()) {
var services = scope.ServiceProvider;
var serviceProvider = services.GetRequiredService<IServiceProvider>();
var configuration = services.GetRequiredService<IConfiguration>();
Seed.CreateRoles(serviceProvider, configuration).Wait();
}
host.Run();
}
But when I run it, the error HTTP Error 500.30 - ANCM In-Process Start Failure
is raised on the webpage and the debug console said the following exceptions:
'System.InvalidOperationException' in Microsoft.Extensions.DependencyInjection.Abstractions.dll
'System.AggregateException' in System.Private.CoreLib.dll
I don't know how to fix that.
Also, I have found all these questions (with their answers) 1, 2, 3, 4, 5, 6 and these Non-SO 7 and 8. But my main problem with them is that each one use a different way to implement an Identity (some of them obsolete to 2.2) and I don't know which one is better, even some raise error on my project or I don't understand at all, so I tried to do this (I read that execute this code in Program
is better than Startup
in perfomance).
By the way, I also tried to remove my code from Programm
and instead add in the Configure
method from Startup
the parameter IServiceProvider serviceProvider
and:
// I used _ = because VS said me something about async
_ = Seed.CreateRoles(serviceProvider, Configuration);