MVC 5种子用户和角色

我一直在玩新的 MVC 5,我有一些模型,控制器和视图设置使用代码优先迁移。

我的问题是如何为用户和角色提供种子?目前,我在我的“种子”方法的 configuration.cs 中播种了一些参考数据。但是在我看来,用户和角色表直到某些东西第一次碰到 AccountController 才会被创建。

目前我有两个连接字符串,因此我可以将数据从身份验证中分离到不同的数据库中。

如何让用户、角色等表与其他表一起填充?而不是当帐户控制器被击中?

67678 次浏览

Looks like they changes the way authentication works in MVC5, changed my Global.asax.cs to the following did the trick!

using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;


using System.Threading.Tasks;
using MvcAuth.Models;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using System.Threading;
using Microsoft.AspNet.Identity.EntityFramework;


namespace MvcAuth
{
public class MvcApplication : System.Web.HttpApplication
{
async Task<bool> AddRoleAndUser()
{
AuthenticationIdentityManager IdentityManager = new AuthenticationIdentityManager(
new IdentityStore(new ApplicationDbContext()));


var role = new Role("Role1");
IdentityResult result = await IdentityManager.Roles.CreateRoleAsync(role, CancellationToken.None);
if (result.Success == false)
return false;


var user = new ApplicationUser() { UserName = "user1" };
result = await IdentityManager.Users.CreateLocalUserAsync(user, "Password1");
if (result.Success == false)
return false;


result = await IdentityManager.Roles.AddUserToRoleAsync(user.Id, role.Id, CancellationToken.None);
return result.Success;
}


protected async void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
bool x = await AddRoleAndUser();
}
}
}

Here is example of usual Seed approach:

protected override void Seed(SecurityModule.DataContexts.IdentityDb context)
{
if (!context.Roles.Any(r => r.Name == "AppAdmin"))
{
var store = new RoleStore<IdentityRole>(context);
var manager = new RoleManager<IdentityRole>(store);
var role = new IdentityRole { Name = "AppAdmin" };


manager.Create(role);
}


if (!context.Users.Any(u => u.UserName == "founder"))
{
var store = new UserStore<ApplicationUser>(context);
var manager = new UserManager<ApplicationUser>(store);
var user = new ApplicationUser {UserName = "founder"};


manager.Create(user, "ChangeItAsap!");
manager.AddToRole(user.Id, "AppAdmin");
}
}

I used package-manager "update-database". DB and all tables were created and seeded with data.

It's a small addition, but to anyone having the "UserId not found." message when trying to seed: (Tom Regan had this question in the comments, and I was stuck on it myself for a while)

This means that the manager.Create(user, "ChangeItAsap!") was not successful. This might have a different reason, but for me it was because my password was not succeeding its validation.

I had a custom passwordvalidator, which was not being called when seeding the database, so the validation rules i was used to (minlength 4 instead of default 6) did not apply. Make sure your password (and all other fields for that matter) is passing validation.

This is my method base on Valin answer, I have added roles in db and added password for user. This code is placed in Seed() method in Migrations>Configurations.cs.

// role (Const.getRoles() return string[] whit all roles)


var RoleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));
for (int i = 0; i < Const.getRoles().Length; i++)
{
if (RoleManager.RoleExists(Const.getRoles()[i]) == false)
{
RoleManager.Create(new IdentityRole(Const.getRoles()[i]));
}
}


// user


var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
var PasswordHash = new PasswordHasher();
if (!context.Users.Any(u => u.UserName == "admin@admin.net"))
{
var user = new ApplicationUser
{
UserName = "admin@admin.net",
Email = "admin@admin.net",
PasswordHash = PasswordHash.HashPassword("123456")
};


UserManager.Create(user);
UserManager.AddToRole(user.Id, Const.getRoles()[0]);
}
protected override void Seed(ApplicationDbContext context)
{
SeedAsync(context).GetAwaiter().GetResult();
}


private async Task SeedAsync(ApplicationDbContext context)
{
var userManager = new ApplicationUserManager(new UserStore<ApplicationUser, ApplicationRole, int, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>(context));
var roleManager = new ApplicationRoleManager(new RoleStore<ApplicationRole, int, ApplicationUserRole>(context));


if (!roleManager.Roles.Any())
{
await roleManager.CreateAsync(new ApplicationRole { Name = ApplicationRole.AdminRoleName });
await roleManager.CreateAsync(new ApplicationRole { Name = ApplicationRole.AffiliateRoleName });
}


if (!userManager.Users.Any(u => u.UserName == "shimmy"))
{
var user = new ApplicationUser
{
UserName = "shimmy",
Email = "shimmy@gmail.com",
EmailConfirmed = true,
PhoneNumber = "0123456789",
PhoneNumberConfirmed = true
};


await userManager.CreateAsync(user, "****");
await userManager.AddToRoleAsync(user.Id, ApplicationRole.AdminRoleName);
}
}

Here i have an very easy,clean and smooth solution.

 protected override void Seed(UserContext context)
{
//Step 1 Create the user.
var passwordHasher = new PasswordHasher();
var user = new IdentityUser("Administrator");
user.PasswordHash = passwordHasher.HashPassword("Admin12345");
user.SecurityStamp = Guid.NewGuid().ToString();


//Step 2 Create and add the new Role.
var roleToChoose = new IdentityRole("Admin");
context.Roles.Add(roleToChoose);


//Step 3 Create a role for a user
var role = new IdentityUserRole();
role.RoleId = roleToChoose.Id;
role.UserId = user.Id;


//Step 4 Add the role row and add the user to DB)
user.Roles.Add(role);
context.Users.Add(user);
}

write this code in your Migration Configuration.

note: Use ApplicationDbContext in Configuration Class.

    internal sealed class Configuration : DbMigrationsConfiguration<ApplicationDbContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = false;
}


protected override void Seed(ApplicationDbContext context)
{
//  This method will be called after migrating to the latest version.


//  You can use the DbSet<T>.AddOrUpdate() helper extension method
//  to avoid creating duplicate seed data.
context.Roles.AddOrUpdate(p =>
p.Id,
new IdentityRole { Name = "Admins"},
new IdentityRole { Name = "PowerUsers" },
new IdentityRole { Name = "Users" },
new IdentityRole { Name = "Anonymous" }
);




}
}