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);
Running your code shows an exception on the following line:
var RoleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
Based on the exception it appears you are missing the configuration in the startup.cs
file to enable Identity. I can't see your startup.cs
but I suspect you are missing the whole services.AddIdentity(...)
calls.
I suggest you take some time to read up on how to configure Identity in ASP.NET Core. The Microsoft Docs are always a good place to start.
Also, the second question you mentioned in your question has good steps. You specifically need to look at Step 2 and Step 3.
The issue is that you're attempting to retrieve scoped services from IServiceProvider
without creating a scope. Interestingly, you created a scope around your call to Seed.CreateRoles
, but then you pass in IServiceProvider
, which is not scoped.
What you should be doing is either passing in IServiceProvider
and creating the scope inside your Seed.CreateRoles
method, or leave the scope creation where it is now and instead pass in your scoped services, ie RoleManager
and UserManager
.
Edit
You need to do one of the following:
Inject IServiceProvider
and then create your scope inside the seed method:
var host = CreateWebHostBuilder(args).Build(); Seed.CreateRoles(host.Services); host.Run();
Then:
public static async Task CreateRoles(IServiceProvider services) { var configuration = services.GetRequiredService<IConfiguration>(); using (var scope = services.CreateScope()) { var roleManager = scope.ServiceProvider.GetRequiredService<RoleManager<IdentityRole>>(); var userManager = scope.ServiceProvider.GetRequiredService<UserManager<IdentityUser>>(); // seed data } }
Inject your scoped services:
var host = CreateWebHostBuilder(args).Build(); var configuration = host.Services.GetRequiredService<IConfiguration>(); using (var scope = host.Services.CreateScope()) { var roleManager = scope.ServiceProvider.GetRequiredService<RoleManager<IdentityRole>>(); var userManager = scope.ServiceProvider.GetRequiredService<UserManager<IdentityUser>>(); Seed.CreateRoles(configuration, roleManager, userManager); } host.Run();
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.