UserTokenProvider/DataProtectorTokenProvider代码优先迁移种子方法期间出现 NullReferenceException
UserTokenProvider/DataProtectorTokenProvider NullReferenceException during Code First Migrations Seed method
架构更新正常,但种子方法没有 运行 因为 NullReferenceException。其他一切似乎都很好,包括能够在站点 运行ning 时发出用于密码重置的令牌等。它只是在 Seed 方法 运行s 时执行此操作。我想我只是在添加 DataProtectorTokenProvider 东西之后才开始得到这个。有什么想法吗?
编辑:当然,这个 NullReferenceException 根本不应该发生,所以 What is a NullReferenceException, and how do I fix it? 在这里无关紧要。
编辑:或许不是。我在这里错过了一些真正基本的东西吗?这行代码:
UserTokenProvider = new DataProtectorTokenProvider<AppUser> (dataProtectionProvider.Create("ASP.NET Identity")) { TokenLifespan = TimeSpan.FromDays(90d) };
DataProtectorTokenProvider 实例化能否在 Seed 方法期间产生除 null 以外的任何结果,因为 site/app 未 running/hasn 未启动,而这正是 OWIN 的工作方式?谢谢。
这是 PMC 的输出:
运行种子方法。
System.NullReferenceException: 对象引用未设置为对象的实例。
在 Identity.AppUserManager..ctor(IUserStore`1 store) 在 Identity\AppUserManager.cs:line 25
在 Migrations.Configuration.Seed(EFDbContext 上下文)在 Migrations\Configuration.cs:第 49 行
在 System.Data.Entity.Migrations.DbMigrationsConfiguration`1.OnSeed(DbContext 上下文)
在 System.Data.Entity.Migrations.DbMigrator.SeedDatabase()
在 System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.SeedDatabase()
在 System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable`1 pendingMigrations,字符串 targetMigrationId,字符串 lastMigrationId)
在 System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.Upgrade(IEnumerable`1 pendingMigrations,字符串 targetMigrationId,字符串 lastMigrationId)
在System.Data.Entity.Migrations.DbMigrator.UpdateInternal(字符串目标迁移)
在 System.Data.Entity.Migrations.DbMigrator.<>c__DisplayClassc.b__b()
在 System.Data.Entity.Migrations.DbMigrator.EnsureDatabaseExists(操作 mustSucceedToKeepDatabase)
在 System.Data.Entity.Migrations.Infrastructure.MigratorBase.EnsureDatabaseExists(操作 mustSucceedToKeepDatabase)
在 System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration)
在System.Data.Entity.Migrations.Infrastructure.MigratorBase.Update(字符串目标迁移)
在 System.Data.Entity.Migrations.Design.ToolingFacade.UpdateRunner.Run()
在System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
在System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
在 System.Data.Entity.Migrations.Design.ToolingFacade.Run(BaseRunner 运行ner)
at System.Data.Entity.Migrations.Design.ToolingFacade.Update(字符串 targetMigration,布尔力)
在 System.Data.Entity.Migrations.UpdateDatabaseCommand.<>c__DisplayClass2.<.ctor>b__0()
at System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(操作命令)
对象引用未设置为对象的实例。
配置代码如下:
internal sealed class Configuration: DbMigrationsConfiguration<Website.Domain.Concrete.EFDbContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
ContextKey = "Website.Domain.Concrete.EFDbContext";
}
protected override void Seed(Concrete.EFDbContext context)
{
// This line is where we hit the exception
AppUserManager userManager = new AppUserManager(new UserStore<AppUser>(context));
AppRoleManager roleManager = new AppRoleManager(new RoleStore<AppRole>(context));
...
这是 AppUserManager 代码:
public class AppUserManager : UserManager<AppUser>
{
public AppUserManager(IUserStore<AppUser> store)
: base(store)
{
IDataProtectionProvider dataProtectionProvider = IdentityConfig.DataProtectionProvider;
// This is causing the NullReferenceException
UserTokenProvider = new DataProtectorTokenProvider<AppUser>(dataProtectionProvider.Create("ASP.NET Identity")) { TokenLifespan = TimeSpan.FromDays(90d) };
}
public static AppUserManager Create(IdentityFactoryOptions<AppUserManager> options, IOwinContext context)
{
EFDbContext db = context.Get<EFDbContext>();
AppUserManager manager = new AppUserManager(new UserStore<AppUser>(db));
manager.PasswordValidator = new PasswordValidator
{
RequiredLength = 8,
RequireNonLetterOrDigit = false,
RequireDigit = false,
RequireLowercase = false,
RequireUppercase = false
};
manager.UserValidator = new UserValidator<AppUser>(manager)
{
AllowOnlyAlphanumericUserNames = true,
RequireUniqueEmail = true
};
return manager;
}
}
这是 IdentityConfig 文件。我有这个而不是启动文件,我告诉 Owin 在 web.config
的 appsettings 中使用这个键在启动时 运行 它
<add key="owin:AppStartup" value="Website.Domain.App_Start.IdentityConfig" />:
namespace Website.Domain.App_Start
{
public class IdentityConfig
{
public static IDataProtectionProvider DataProtectionProvider { get; set; }
public void Configuration(IAppBuilder app)
{
DataProtectionProvider = app.GetDataProtectionProvider();
app.CreatePerOwinContext<EFDbContext>(EFDbContext.Create);
app.CreatePerOwinContext<AppUserManager>(AppUserManager.Create);
app.CreatePerOwinContext<AppRoleManager>(AppRoleManager.Create);
app.CreatePerOwinContext<AppSignInManager>(AppSignInManager.Create);
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/account/login")
});
}
}
}
失败是因为
IDataProtectionProvider dataProtectionProvider = IdentityConfig.DataProtectionProvider;
将 return 为空,除非该应用实际上是 运行。因此,这在迁移期间失败了。
修复方法如下:
if (dataProtectionProvider != null)
{
UserTokenProvider = new DataProtectorTokenProvider<AppUser>(dataProtectionProvider.Create("ASP.NET Identity")) { TokenLifespan = TimeSpan.FromDays(90d) };
}
架构更新正常,但种子方法没有 运行 因为 NullReferenceException。其他一切似乎都很好,包括能够在站点 运行ning 时发出用于密码重置的令牌等。它只是在 Seed 方法 运行s 时执行此操作。我想我只是在添加 DataProtectorTokenProvider 东西之后才开始得到这个。有什么想法吗?
编辑:当然,这个 NullReferenceException 根本不应该发生,所以 What is a NullReferenceException, and how do I fix it? 在这里无关紧要。
编辑:或许不是。我在这里错过了一些真正基本的东西吗?这行代码:
UserTokenProvider = new DataProtectorTokenProvider<AppUser> (dataProtectionProvider.Create("ASP.NET Identity")) { TokenLifespan = TimeSpan.FromDays(90d) };
DataProtectorTokenProvider 实例化能否在 Seed 方法期间产生除 null 以外的任何结果,因为 site/app 未 running/hasn 未启动,而这正是 OWIN 的工作方式?谢谢。
这是 PMC 的输出:
运行种子方法。
System.NullReferenceException: 对象引用未设置为对象的实例。
在 Identity.AppUserManager..ctor(IUserStore`1 store) 在 Identity\AppUserManager.cs:line 25
在 Migrations.Configuration.Seed(EFDbContext 上下文)在 Migrations\Configuration.cs:第 49 行
在 System.Data.Entity.Migrations.DbMigrationsConfiguration`1.OnSeed(DbContext 上下文)
在 System.Data.Entity.Migrations.DbMigrator.SeedDatabase()
在 System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.SeedDatabase()
在 System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable`1 pendingMigrations,字符串 targetMigrationId,字符串 lastMigrationId)
在 System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.Upgrade(IEnumerable`1 pendingMigrations,字符串 targetMigrationId,字符串 lastMigrationId)
在System.Data.Entity.Migrations.DbMigrator.UpdateInternal(字符串目标迁移)
在 System.Data.Entity.Migrations.DbMigrator.<>c__DisplayClassc.b__b()
在 System.Data.Entity.Migrations.DbMigrator.EnsureDatabaseExists(操作 mustSucceedToKeepDatabase)
在 System.Data.Entity.Migrations.Infrastructure.MigratorBase.EnsureDatabaseExists(操作 mustSucceedToKeepDatabase)
在 System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration)
在System.Data.Entity.Migrations.Infrastructure.MigratorBase.Update(字符串目标迁移)
在 System.Data.Entity.Migrations.Design.ToolingFacade.UpdateRunner.Run()
在System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
在System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
在 System.Data.Entity.Migrations.Design.ToolingFacade.Run(BaseRunner 运行ner)
at System.Data.Entity.Migrations.Design.ToolingFacade.Update(字符串 targetMigration,布尔力)
在 System.Data.Entity.Migrations.UpdateDatabaseCommand.<>c__DisplayClass2.<.ctor>b__0()
at System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(操作命令)
对象引用未设置为对象的实例。
配置代码如下:
internal sealed class Configuration: DbMigrationsConfiguration<Website.Domain.Concrete.EFDbContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
ContextKey = "Website.Domain.Concrete.EFDbContext";
}
protected override void Seed(Concrete.EFDbContext context)
{
// This line is where we hit the exception
AppUserManager userManager = new AppUserManager(new UserStore<AppUser>(context));
AppRoleManager roleManager = new AppRoleManager(new RoleStore<AppRole>(context));
...
这是 AppUserManager 代码:
public class AppUserManager : UserManager<AppUser>
{
public AppUserManager(IUserStore<AppUser> store)
: base(store)
{
IDataProtectionProvider dataProtectionProvider = IdentityConfig.DataProtectionProvider;
// This is causing the NullReferenceException
UserTokenProvider = new DataProtectorTokenProvider<AppUser>(dataProtectionProvider.Create("ASP.NET Identity")) { TokenLifespan = TimeSpan.FromDays(90d) };
}
public static AppUserManager Create(IdentityFactoryOptions<AppUserManager> options, IOwinContext context)
{
EFDbContext db = context.Get<EFDbContext>();
AppUserManager manager = new AppUserManager(new UserStore<AppUser>(db));
manager.PasswordValidator = new PasswordValidator
{
RequiredLength = 8,
RequireNonLetterOrDigit = false,
RequireDigit = false,
RequireLowercase = false,
RequireUppercase = false
};
manager.UserValidator = new UserValidator<AppUser>(manager)
{
AllowOnlyAlphanumericUserNames = true,
RequireUniqueEmail = true
};
return manager;
}
}
这是 IdentityConfig 文件。我有这个而不是启动文件,我告诉 Owin 在 web.config
的 appsettings 中使用这个键在启动时 运行 它<add key="owin:AppStartup" value="Website.Domain.App_Start.IdentityConfig" />:
namespace Website.Domain.App_Start
{
public class IdentityConfig
{
public static IDataProtectionProvider DataProtectionProvider { get; set; }
public void Configuration(IAppBuilder app)
{
DataProtectionProvider = app.GetDataProtectionProvider();
app.CreatePerOwinContext<EFDbContext>(EFDbContext.Create);
app.CreatePerOwinContext<AppUserManager>(AppUserManager.Create);
app.CreatePerOwinContext<AppRoleManager>(AppRoleManager.Create);
app.CreatePerOwinContext<AppSignInManager>(AppSignInManager.Create);
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/account/login")
});
}
}
}
失败是因为
IDataProtectionProvider dataProtectionProvider = IdentityConfig.DataProtectionProvider;
将 return 为空,除非该应用实际上是 运行。因此,这在迁移期间失败了。
修复方法如下:
if (dataProtectionProvider != null)
{
UserTokenProvider = new DataProtectorTokenProvider<AppUser>(dataProtectionProvider.Create("ASP.NET Identity")) { TokenLifespan = TimeSpan.FromDays(90d) };
}