- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我试图在应用程序启动期间在身份框架中植入一个“管理员”帐户。我们的大部分应用程序不是通过代码优先 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/
我正在开发 ASP.NET Web 应用程序,对于未处理的异常,我正在使用Global.asax 文件 我在其中编写了将错误日志写为 的逻辑 Sub Application_Error(ByVal s
Tell me about the difference between global.asax and global.asax.cs ? 和 If i click the both file in
在我的本地发布文件夹中,我有 Global.asax 和 Global.asax.cs,其中 Global.asax 未更新(日期为一个月前)和 Global.asax .cs 已更新。 我检查了 G
我在 2 台开发计算机上安装了一个 ASP.NET MVC 应用程序。该应用程序在两台计算机上运行良好(使用本地 IIS)。直到最近,我经常从一台或另一台计算机在生产服务器上发布而没有问题。从3周前开
我正在尝试将代码添加到我没有源代码的第 3 方 ASP.NET Web 应用程序的 application_start 事件。我通过从供应商的 Global 类继承来做到这一点。这是代码(注意“new
在我们使用 WebAPI 构建“简单”API 的冒险过程中,我们遇到了与任何项目一样的问题,但是我无法找到可以解释以下行为的任何此类资源:细节 : 带有 Update 2 的 Visual Studi
我有一个仅适用于 Firefox 的登录页面。它不适用于任何其他浏览器。 当我检查事件日志时,我看到“响应在当前上下文中不可用”。它告诉我错误在 global.asax 文件中,在 response.
我构建了一个包含 Global.asax 文件的 WCF 应用程序。我添加了 AspNetCompatibilityRequirements(RequirementsMode = AspNetComp
有一个Global.asax asp.net 应用程序根目录中的文件。 扩展命名背后的原因是什么? 我可以创建其他文件来使用这个扩展吗?出于什么目的? 最佳答案 Global.asax分机 stand
是否可以在 global.asax 中捕获回收事件? 我知道 Application_End 会被触发,但有没有办法知道它是由应用程序池的回收触发的? 谢谢,Lieven Cardoen 又名 Joh
我想创建一个全局选项,当 REST 调用包含 &format=json 以将响应输出为 JSON 字符串时。 如果我在我的方法中输入以下字符串,它会起作用: WebOperationContext.C
我计划使用 System.Data 包的全局导入。在我添加之后 在 global.asax 的标记中 在我的一个类中,我删除了代码顶部的“使用 System.Data”。 我构建了 global.a
我在asp.net和C#中有Web应用程序 我试图处理异常,如果它们在此应用程序内的任何地方发生。 例如,假设行为应为if和发生这种异常 //generate your fictional excep
我无法调试 global.asax 文件! 我在 Application_Start() 方法中有一些代码,但是当我在该方法中设置断点时,它会被忽略! 这正常吗? 最佳答案 中断 Applicatio
我试图从数据库中检查用户是否属于某人的好友列表并相应地重定向他。 我在 Global Asax 调用的路由处理程序中执行此操作。 我只想知道如何在路由处理程序类(或全局 asax)中获取用户名(从登录
我添加了一个 global.asax 文件,后来我决定不需要它,所以我将它从项目中排除,但现在我在尝试运行我的项目时遇到解析器错误。 下面是 View 上显示的错误: Line 1: 发生了什么以
我想在我的 global.asax 中使用带有 response.redirecttoroute 的自定义路由,但它不起作用。我的 RouteConfig 中有以下内容: routes.MapRout
全局 asax 文件有什么用?我希望声明将在整个应用程序页面中使用的特定于用户的对象字典。我在哪里声明这个字典? 谢谢。 最佳答案 Global.asax 包含一个代表整个应用程序的类。如果您的词典是
我正在开发一个 HttpModule 并使用 Global.asax。我开发了一个派生自 HttpApplication 的类,但我的类的 Application_Start 方法从不执行(我在 Ap
是否可以将 Global.asax 文件嵌入到程序集中?当前,它表示为 Web 根目录中的一个文件。但我想将它作为资源存储在程序集中。 最佳答案 我不确定。您是否尝试过将 Build Action 设
我是一名优秀的程序员,十分优秀!