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

C# 从Global.asax.cs调用Identity Framework种子方法时,不会保存新创建的用户,c#,asp.net-mvc,asp.net-identity,C#,Asp.net Mvc,Asp.net Identity,我试图在应用程序启动期间在Identity framework中创建一个“管理员”帐户。我们的大多数应用程序都不是通过代码优先实体框架模型建立的,因此我需要在不扩展IDatabaseInitializer类的情况下完成这项工作。我使用的数据库与这些数据库第一个模型相同 这是一个ASP.NETMVC5应用程序 在Global.asax.cs中,我有以下相关代码 using (var context = new IdentityContext(EnvironmentSettings.Current.

我试图在应用程序启动期间在Identity framework中创建一个“管理员”帐户。我们的大多数应用程序都不是通过代码优先实体框架模型建立的,因此我需要在不扩展IDatabaseInitializer类的情况下完成这项工作。我使用的数据库与这些数据库第一个模型相同

这是一个ASP.NETMVC5应用程序

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 server。用户名是一个电子邮件地址,密码是一个字符串,包括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");
    }
}
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类CreateInitializer:CreateDatabaseIfNotExists
{
受保护的重写异步无效种子(IdentityContext上下文)
{
var user=new
{
EnvironmentSettings.DefaultAdminAccount.UserName,
EnvironmentSettings.DefaultAdminAccount.Password
};
wait context.SeedAdminAccount(user.UserName,user.Password);
种子(上下文);
}
}
好吧,所有这些都解决了,下面是有效的方法:

1) 应用程序启动成功创建了
IdentityContext
的实例

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

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

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

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

这就是我被困的地方:

1) 尽管我的seed方法似乎工作正常,但没有任何行保存到
IdentityUser
表或任何其他Identity framework表中

2) 如果我使用控制器操作中的相同代码,则会成功创建一个用户并将其存储在
IdentityUser
表中


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

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

结果是,我忘记在
SeedAdminAccount()
方法中重载
UserValidator
以使用我的
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));
    }
}
public static void SeedAdminAccount(此IdentityContext IdentityContext、字符串用户名、字符串密码)
{
var userManager=newusermanager(newuserstore(identityContext));
userManager.UserValidator=新的EmailUserValidator(userManager);
var user=userManager.Find(用户名、密码);
如果(user!=null)返回;
SeedUserRoles(identityContext);
user=newidentityuser(){UserName=UserName};
var result=userManager.Create(用户,密码);
if(result.successed)
{
userManager.AddToRole(user.Id,Role.Administrator);
}
其他的
{
var e=新异常(“无法添加默认帐户”);
var enumerator=result.Errors.GetEnumerator();
foreach(result.Errors中的变量错误)
{
e、 Data.Add(enumerator.Current,error);
}
投掷e;
}
}
公共静态void SeedUserRoles(此IdentityContext IdentityContext)
{
var角色管理器=新角色管理器(新角色存储库(identityContext));
foreach(role.Roles中的var角色)
{
var roleExists=rolemager.roleExists(角色);
如果(角色存在)继续;
创建(新的IdentityRole(角色));
}
}

尝试打开SQL事件探查器,并在
identityContext.SaveChanges()期间观察向数据库发送的查询哦,太酷了,我不知道有SQL分析器。我会查一查。尽管我花了好几个小时坐在办公桌前,我还是明白了我的问题所在。我很快就会发布我的答案。我也花了很多时间试图弄清楚为什么没有创建用户:),而不仅仅是检查返回值。在这种情况下,抛出异常可能更合适。谢谢,帮助我解决了我的问题:我尝试添加了一个密码不符合密码要求的用户,因此在没有任何通知的情况下根本没有创建该用户。
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));
    }
}