aho*_*mes 5 c# asp.net-mvc asp.net-identity
我正在尝试在应用程序启动期间在Identity框架中播种"admin"帐户.我们的大部分应用程序都没有通过代码优先的Entity框架模型进行设置,因此我需要在不扩展其中一个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();
}
Run Code Online (Sandbox Code Playgroud)
连接字符串是Azure SQL服务器.用户名是电子邮件地址,密码是一串字符,包括一声巨响.
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");
}
}
Run Code Online (Sandbox Code Playgroud)
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();
}
}
Run Code Online (Sandbox Code Playgroud)
最后,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);
}
}
Run Code Online (Sandbox Code Playgroud)
好的,所有这一切都在这里,这是有效的:
1)应用程序启动成功创建了一个实例IdentityContext.
2)Identity框架使用修改的表名创建正确的表.
3)SeedAdminAccount()使用正确的参数调用.
4)userManager.FindAsync()找不到用户(因为它不存在).
5)SeedAdminAccount()继续其身体中的每个陈述并成功返回.
这是我被困的地方:
1)虽然看起来我的种子方法工作正常,但没有行保存到IdentityUser表或任何其他Identity框架表.
2)如果我使用控制器操作中的相同代码,则会IdentityUser成功创建用户并将其存储在表中.
我在这里错过了什么?我是否在应用程序启动期间使用了错误的上下文?是否有某种我无法看到的异常?
完全失去了,我决定检查的回报值userManager.CreateAsync().我注意到Errors字段是非空的,错误是"指定的名称包含无效字符".
事实证明,我忘了重载在方法中UserValidator使用我的EmailUserValidator类SeedAdminAccount().
我也改变了我存储角色的方式.这就是我的种子方法现在的样子.
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));
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4928 次 |
| 最近记录: |