在我的网站上,我想使用一个帐户登录管理员,以便修改数据库。另外,我将来可能会添加一些角色和帐户。
因此,我正在尝试实现身份。
我在Visual Studio 2019中创建了一个项目(不确定是否重要),然后选择具有MVC的ASP.NET Core 2.2(我自己安装了Core 2.2),具有单个用户帐户的身份验证,然后单击了说:“配置HTTPS”。
一旦创建了项目,我就打开它,创建一个随机帐户,遇到错误,然后迁移数据库进行修复。
然后,我添加appsetting.json
:
"UserSettings": {
"UserName": "MyAdminUser",
"UserEmail": "MyAdminUser@gmail.com",
"UserPassword": "A_123456a"
}
在文件夹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");
}
}
}
}
}
最后将Main
类的Program
方法替换为:
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();
}
但是,当我运行它时,网页上出现错误HTTP Error 500.30 - ANCM In-Process Start Failure
,并且调试控制台显示以下异常:
'System.InvalidOperationException' in Microsoft.Extensions.DependencyInjection.Abstractions.dll
'System.AggregateException' in System.Private.CoreLib.dll
我不知道该如何解决。
我也找到了所有这些问题(及其答案)1,2,3,4,5,{{3} }以及这些非SO 6和7。但是我的主要问题是每个人都使用不同的方式来实现身份(其中一些人过时了2.2),我不知道哪个更好,甚至有些人在我的项目中提出错误,或者我不明白根本没有,所以我尝试这样做(我读到在性能方面,在Program
中执行此代码要好于Startup
)。
顺便说一句,我还尝试从Programm
删除我的代码,而是从Configure
的{{1}}方法中添加参数Startup
和:
IServiceProvider serviceProvider
答案 0 :(得分:0)
运行代码将在以下行显示异常:
var RoleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
基于例外情况,您似乎缺少startup.cs
文件中用于启用身份的配置。我看不到您的startup.cs
,但我怀疑您错过了整个services.AddIdentity(...)
的电话。
我建议您花一些时间来阅读如何在ASP.NET Core中配置身份。 Microsoft Docs总是一个很好的起点。
此外,您在问题中提到的second question有很好的步骤。您特别需要查看步骤2和步骤3。
答案 1 :(得分:0)
问题是您试图从IServiceProvider
检索范围服务而不创建范围。有趣的是,您围绕对Seed.CreateRoles
的调用创建了一个作用域,但随后传入了IServiceProvider
,但没有作用域。
您应该做的是要么传入IServiceProvider
并在您的Seed.CreateRoles
方法内创建范围 ,要么将范围创建保留在当前位置,而直接传递您的范围服务,即RoleManager
和UserManager
。
修改
您需要执行以下一项操作:
注入IServiceProvider
,然后在种子方法内创建作用域:
var host = CreateWebHostBuilder(args).Build();
Seed.CreateRoles(host.Services);
host.Run();
然后:
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
}
}
注入您的作用域服务:
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();