2015-12-17 36 views
14

我創建了一個新的乾淨的asp.net 5項目(rc1-final)。使用身份認證我只是用下面的代碼的ApplicationDbContext.cs:如何爲使用身份驗證的代碼優先遷移種子用戶和角色ASP.NET MVC 6

public class ApplicationDbContext : IdentityDbContext<ApplicationUser> 
{ 
    protected override void OnModelCreating(ModelBuilder builder) 
    { 
     // On event model creating 
     base.OnModelCreating(builder); 
    } 
} 

請注意ApplicationDbContext使用IdentityDbContext而不是的DbContext。

有任何IdentityConfig.cs。我需要把經典的保護覆蓋無效種子創建角色和用戶,如果它不存在?

回答

2

這是not yet implemented。作爲解決方法,只需編寫自己的類,它將檢查數據庫中是否存在實體,如果它們不存在則添加它們,然後從Startup.cs中調用此類。

33

我這樣做的方法是在模型命名空間中創建一個類。

public class SampleData 
{ 
    public static void Initialize(IServiceProvider serviceProvider) 
    { 
     var context = serviceProvider.GetService<ApplicationDbContext>(); 

     string[] roles = new string[] { "Owner", "Administrator", "Manager", "Editor", "Buyer", "Business", "Seller", "Subscriber" }; 

     foreach (string role in roles) 
     { 
      var roleStore = new RoleStore<IdentityRole>(context); 

      if (!context.Roles.Any(r => r.Name == role)) 
      { 
       roleStore.CreateAsync(new IdentityRole(role)); 
      } 
     } 


     var user = new ApplicationUser 
     { 
      FirstName = "XXXX", 
      LastName = "XXXX", 
      Email = "[email protected]", 
      NormalizedEmail = "[email protected]", 
      UserName = "Owner", 
      NormalizedUserName = "OWNER", 
      PhoneNumber = "+111111111111", 
      EmailConfirmed = true, 
      PhoneNumberConfirmed = true, 
      SecurityStamp = Guid.NewGuid().ToString("D") 
     }; 


     if (!context.Users.Any(u => u.UserName == user.UserName)) 
     { 
      var password = new PasswordHasher<ApplicationUser>(); 
      var hashed = password.HashPassword(user,"secret"); 
      user.PasswordHash = hashed; 

      var userStore = new UserStore<ApplicationUser>(context); 
      var result = userStore.CreateAsync(user); 

     } 

     AssignRoles(serviceProvider, user.Email, roles); 

     context.SaveChangesAsync(); 
    } 

    public static async Task<IdentityResult> AssignRoles(IServiceProvider services, string email, string[] roles) 
    { 
     UserManager<ApplicationUser> _userManager = services.GetService<UserManager<ApplicationUser>>(); 
     ApplicationUser user = await _userManager.FindByEmailAsync(email); 
     var result = await _userManager.AddToRolesAsync(user, roles); 

     return result; 
    } 

} 

在啓動時運行此代碼。在配置方法結束後的Startup.cs中,在路由配置之後添加以下代碼,如Stafford Williams之前所述。

SampleData.Initialize(app.ApplicationServices); 
+0

是的!就是這個方法。用於幫助人們瞭解種子數據的真棒代碼。謝謝 – Sauron

+1

我正在尋找一種讓用戶擁有固定ID的方法。當您移交某個ApplicationUser實例進行創建時,UserManager將分配一個新的ID。您的方法允許我將Id設置爲某個固定值 - 因此感謝您的努力:) – intertag

+0

System.InvalidOperationException:'當分配給命令的連接處於未決的本地事務中時,ExecuteReader需要命令執行事務。該命令的Transaction屬性尚未初始化。' – tnktnk

0

以下行在AspNetRoles表中創建條目,但不會填充NormalizedName列。

替代與此列如下,以填充:

RoleManager<IdentityRole> roleManager = serviceProvider.GetService<RoleManager<IdentityRole>>(); 
roleManager.CreateAsync(new IdentityRole(role)); 
13

在編寫這本書的時候,有一個地方播種數據庫中沒有插頭,但你可以創建一個類,並將其添加您的容器上做應用程序啓動同樣的事情,這裏是如何我已經做到了,首先要創建一個類:

public class YourDbContextSeedData 
{ 
    private YourDbContext _context; 

    public YourDbContextSeedData(YourDbContext context) 
    { 
     _context = context; 
    } 

    public async void SeedAdminUser() 
    { 
     var user = new ApplicationUser 
     { 
      UserName = "[email protected]", 
      NormalizedUserName = "[email protected]", 
      Email = "[email protected]", 
      NormalizedEmail = "[email protected]", 
      EmailConfirmed = true, 
      LockoutEnabled = false, 
      SecurityStamp = Guid.NewGuid().ToString() 
     }; 

     var roleStore = new RoleStore<IdentityRole>(_context); 

     if (!_context.Roles.Any(r => r.Name == "admin")) 
     { 
      await roleStore.CreateAsync(new IdentityRole { Name = "admin", NormalizedName = "admin" }); 
     } 

     if (!_context.Users.Any(u => u.UserName == user.UserName)) 
     { 
      var password = new PasswordHasher<ApplicationUser>(); 
      var hashed = password.HashPassword(user, "password"); 
      user.PasswordHash = hashed; 
      var userStore = new UserStore<ApplicationUser>(_context); 
      await userStore.CreateAsync(user); 
      await userStore.AddToRoleAsync(user, "admin"); 
     } 

     await _context.SaveChangesAsync(); 
    } 

Startup.csConfigureServices方法註冊類型:

services.AddTransient<YourDbContextSeedData>(); 

下一頁通過YourDbContextSeedData類的Startup.cs類的Configure方法,並使用它:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, YourDbContextSeedData seeder) 
{ 
    seeder.SeedAdminUser(); 
} 
+0

在嘗試在我的核心2應用程序中種下一個管理員級別帳戶多少浪費時間後當我調用AddToRoleAsync方法時,所有其他方法都失敗了,所以你的帖子的修改版本最終爲我做了。非常感謝! – Nathan

1

添加下面的類模型的命名空間。它適用於添加多個用戶和角色,並且還會將角色添加到現有用戶(例如,圖表登錄)。這樣稱呼它app.SeedUsersAndRoles();從startup.cs

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Threading.Tasks; 
using Microsoft.AspNet.Builder; 
using Microsoft.Extensions.DependencyInjection; 
using Microsoft.AspNet.Identity.EntityFramework; 
using Microsoft.AspNet.Identity; 

namespace MyApplication.Models 
{ 
    public static class DataSeeder 
    { 
     public static async void SeedUsersAndRoles(this IApplicationBuilder app) 
     { 
      var context = app.ApplicationServices.GetService<ApplicationDbContext>(); 
      UserWithRoles[] usersWithRoles = { 
       new UserWithRoles("Admin", new string[] { "Administrator" , "Distributor" },"somepassword"),//user and optional roles and password you want to seed 
       new UserWithRoles("PlainUser"), 
       new UserWithRoles("Jojo",new string[]{"Distributor" }) //seed roles to existing users (e.g. facebook login). 
      }; 

      foreach (var userWithRoles in usersWithRoles) 
      { 
       foreach (string role in userWithRoles.Roles) 
        if (!context.Roles.Any(r => r.Name == role)) 
        { 
         var roleStore = new RoleStore<IdentityRole>(context); 
         await roleStore.CreateAsync(new IdentityRole(role)); 
        } 
       var ExistingUser = context.Users.FirstOrDefault(p => p.NormalizedUserName == userWithRoles.User.NormalizedUserName); 
       if (ExistingUser == null) //the following syntax: !context.Users.FirstOrDefault(p => p.NormalizedUserName == userWithRoles.User.NormalizedUserName)) 
              //provokes execption:(ExecuteReader requires an open and available Connection.) 
        await new UserStore<ApplicationUser>(context).CreateAsync(userWithRoles.User); 
       await app.AssignRoles(userWithRoles); //assign also to existing users. 
      } 

      context.SaveChangesAsync(); 
     } 

     public static async Task<IdentityResult> AssignRoles(this IApplicationBuilder app, UserWithRoles uWR) 
     { 
      UserManager<ApplicationUser> _userManager = app.ApplicationServices.GetService<UserManager<ApplicationUser>>(); 
      ApplicationUser user = await _userManager.FindByNameAsync(uWR.User.NormalizedUserName); 
      var result = await _userManager.AddToRolesAsync(user, uWR.Roles); 
      return result; 
     } 
    } 
    public class UserWithRoles 
    { 
     private ApplicationUser user; 
     public ApplicationUser User { get { return user; } } 
     public string[] Roles { get; set; } 
     public UserWithRoles(string name, string[] roles = null, string password = "secret") 
     { 
      if (roles != null) 
       Roles = roles; 
      else 
       Roles = new string[] { }; 
      user = new ApplicationUser 
      { 
       Email = name + "@gmail.com", NormalizedEmail = name.ToUpper() + "@GMAIL.COM", 
       UserName = name, NormalizedUserName = name.ToUpper(), 
       PhoneNumber = "+1312341234", 
       EmailConfirmed = true, 
       PhoneNumberConfirmed = true, 
       SecurityStamp = Guid.NewGuid().ToString("D"), 
      }; 
      user.PasswordHash = new PasswordHasher<ApplicationUser>().HashPassword(user, password); 
     } 
    } 
} 
0

所以這是基於穆罕默德阿卜杜拉答案的解決方案。包括一些代碼改進,提高了代碼的可讀性,並使其與.net core 2一起工作。

public class Seed 
    { 
     public static async Task Initialize(IServiceProvider serviceProvider, IConfiguration configuration) 
     { 
      var usrName = configuration.GetSection("Admin").GetSection("UserName").Value; 
      var email = configuration.GetSection("Admin").GetSection("Email").Value; 
      var pass = configuration.GetSection("Admin").GetSection("Pass").Value; 
      var roles = new string[4] { OWNER, ADMIN, SENIOR, USER }; 

      if(await CreateUser(serviceProvider, email, usrName, pass, roles)) 
      { 
       await AddToRoles(serviceProvider, email, roles); 
      } 
     } 

     private static async Task<bool> CreateUser(IServiceProvider serviceProvider, string email, string usrName, string pass, string[] roles) 
     { 
      var res = false; 

      using (var scope = serviceProvider.CreateScope()) 
      { 
       var context = scope.ServiceProvider.GetService<BaseContext>(); 

       if (!context.ApplicationUsers.Any(u => u.NormalizedUserName == usrName.ToUpper())) 
       { 
        var roleStore = scope.ServiceProvider.GetService<RoleManager<IdentityRole>>(); 

        foreach (string role in roles) 
        { 
         if (!context.Roles.Any(r => r.Name == role)) 
         { 
          await roleStore.CreateAsync(new IdentityRole(role)).ConfigureAwait(false); 
         } 
        } 

        var user = new ApplicationUser 
        { 
         UserName = usrName, 
         Email = email, 
         EmailConfirmed = true, 
         NormalizedEmail = email.ToUpper(), 
         NormalizedUserName = usrName.ToUpper(), 
         PhoneNumber = null, 
         PhoneNumberConfirmed = true, 
         SecurityStamp = Guid.NewGuid().ToString() 
        }; 

        var password = new PasswordHasher<ApplicationUser>(); 
        user.PasswordHash = password.HashPassword(user, pass); ; 

        var userStore = new UserStore<ApplicationUser>(context); 
        res = (await userStore.CreateAsync(user).ConfigureAwait(false)).Succeeded; 
       } 

       return res; 
      } 
     } 

     private static async Task AddToRoles(IServiceProvider serviceProvider, string email, string[] roles) 
     { 
      using (var scope = serviceProvider.CreateScope()) 
      { 
       var userManager = scope.ServiceProvider.GetService<UserManager<ApplicationUser>>(); 
       var usr = await userManager.FindByEmailAsync(email).ConfigureAwait(false); 
       await userManager.AddToRolesAsync(usr, roles).ConfigureAwait(false); 
      }   
     } 
    } 
相關問題