gpt4 book ai didi

c# - 从 Global.asax.cs 调用时,Identity Framework 种子方法不会保存新创建的用户

转载 作者:太空狗 更新时间:2023-10-29 22:37:29 25 4
gpt4 key购买 nike

我试图在应用程序启动期间在身份框架中植入一个“管理员”帐户。我们的大部分应用程序不是通过代码优先 Entity Framework 模型设置的,因此我需要在不扩展 IDatabaseInitializer 类之一的情况下执行此操作。我使用与这些数据库优先模型相同的数据库。

这是一个 ASP.NET MVC 5 应用程序。

Global.asax.cs中,我有以下相关代码。

using (var context = new IdentityContext(EnvironmentSettings.Current.DatabaseConnections.CreateDbConnection("Extranet").ConnectionString))
{
context.SeedAdminAccount(EnvironmentSettings.DefaultAdminAccount.UserName, EnvironmentSettings.DefaultAdminAccount.Password).Wait();
}

连接字符串是一个 Azure SQL 服务器。用户名是一个电子邮件地址,密码是一串字符,包括一个bang。

IdentityContext 类如下所示。

public class IdentityContext : IdentityDbContext<IdentityUser>
{
public IdentityContext(string connectionString) : base(connectionString)
{
Debug.WriteLine(connectionString);
Initialize();
}

void Initialize()
{
Database.Log = s => System.Diagnostics.Debug.WriteLine(s);
Database.SetInitializer<IdentityContext>(new CreateInitializer());
}

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);

modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

modelBuilder.Entity<IdentityUser>().ToTable("IdentityUser", "dbo");
modelBuilder.Entity<IdentityRole>().ToTable("IdentityRole", "dbo");
modelBuilder.Entity<IdentityUserClaim>().ToTable("IdentityUserClaim", "dbo");
modelBuilder.Entity<IdentityUserLogin>().ToTable("IdentityUserLogin", "dbo");
modelBuilder.Entity<IdentityUserRole>().ToTable("IdentityUserRole", "dbo");
}
}

context.SeedAdminAccount()IdentityContext 的扩展。看起来像这样。

public static class IdentityContextExtensions
{
public static async Task SeedAdminAccount(this IdentityContext identityContext, string username, string password)
{
var userManager = new UserManager<IdentityUser>(new UserStore<IdentityUser>(identityContext));

//var user = await userManager.FindAsync(EnvironmentSettings.DefaultAdminAccount.UserName, EnvironmentSettings.DefaultAdminAccount.Password);
var user = await userManager.FindAsync(username, password);

if (user != null) return;

user = new IdentityUser() { UserName = username };

var role = new IdentityUserRole { Role = new IdentityRole(Role.Admin) };
user.Roles.Add(role);

await userManager.CreateAsync(user, password);

identityContext.SaveChanges();
}
}

最后,CreateInitializer 看起来像这样(虽然它没有被调用)。

public class CreateInitializer : CreateDatabaseIfNotExists<IdentityContext>
{
protected override async void Seed(IdentityContext context)
{
var user = new
{
EnvironmentSettings.DefaultAdminAccount.UserName,
EnvironmentSettings.DefaultAdminAccount.Password
};

await context.SeedAdminAccount(user.UserName, user.Password);

base.Seed(context);
}
}

好吧,所有这些都解决了,下面是有效的方法:

1) 应用启动成功创建IdentityContext实例。

2) Identity framework 使用修改后的表名创建正确的表。

3) 使用正确的参数调用 SeedAdminAccount()

4) userManager.FindAsync() 没有找到用户(因为它不存在)。

5) SeedAdminAccount() 继续其主体中的每个语句并成功返回。

这是我卡住的地方:

1) 虽然看起来我的种子方法工作正常,但没有行保存到 IdentityUser 表或任何其他身份框架表中。

2) 如果我使用来自 Controller 操作的相同代码,则会成功创建用户并将其存储在 IdentityUser 表中。

我在这里错过了什么?我在应用程序启动期间使用了错误的上下文吗?是否发生了某种我看不到的异常?

最佳答案

由于完全不知所措,我决定检查 userManager.CreateAsync() 的返回值。我注意到错误字段是非空的,错误是“指定的名称包含无效字符”。

原来,我忘记重载 UserValidator 以在 SeedAdminAccount() 方法中使用我的 EmailUserValidator 类。

我还更改了存储角色的方式。这就是我的种子方法现在的样子。

public static void SeedAdminAccount(this IdentityContext identityContext, string username, string password)
{
var userManager = new UserManager<IdentityUser>(new UserStore<IdentityUser>(identityContext));
userManager.UserValidator = new EmailUserValidator<IdentityUser>(userManager);

var user = userManager.Find(username, password);

if (user != null) return;

SeedUserRoles(identityContext);

user = new IdentityUser() { UserName = username };

var result = userManager.Create(user, password);

if (result.Succeeded)
{
userManager.AddToRole(user.Id, Role.Administrator);
}
else
{
var e = new Exception("Could not add default account.");

var enumerator = result.Errors.GetEnumerator();
foreach(var error in result.Errors)
{
e.Data.Add(enumerator.Current, error);
}

throw e;
}
}

public static void SeedUserRoles(this IdentityContext identityContext)
{
var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(identityContext));

foreach(var role in Role.Roles)
{
var roleExists = roleManager.RoleExists(role);

if (roleExists) continue;

roleManager.Create(new IdentityRole(role));
}
}

关于c# - 从 Global.asax.cs 调用时,Identity Framework 种子方法不会保存新创建的用户,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21639280/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com