I was initializing my website Users and Roles data in IdentityConfig.cs file and when I added a new model than mapping it to the database using code-first add-migration and update-database command, I get an empty database:
public class ApplicationDbInitializer : DropCreateDatabaseIfModelChanges<ApplicationDbContext>
{
protected override void Seed(ApplicationDbContext context)
{
InitializeIdentityForEF(context);
base.Seed(context);
}
// Create User=aadmin2018#mail.com with Admin2018#mail.com in the Admin role
public static void InitializeIdentityForEF(ApplicationDbContext db)
{
var userManager = HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();
var roleManager = HttpContext.Current.GetOwinContext().Get<ApplicationRoleManager>();
const string name = "admin2018#mail.com";
const string password = "Admin2018#mail.com";
const string roleName = "Admin";
// Create role Admin if it does not exist
var role = roleManager.FindByName(roleName);
if (role == null)
{
role = new IdentityRole(roleName);
var roleresult = roleManager.Create(role);
}
var user = userManager.FindByName(name);
if (user == null)
{
user = new ApplicationUser
{
UserName = name,
Email = name,
FirstName = "Admin",
LastName = "Admin",
DateOfBirth = new DateTime(2015, 1, 1),
Address = new Address
{
AddressLine1 = "1 Admin Street",
Town = "Town",
County = "County",
Postcode = "PostCode"
}
};
var result = userManager.Create(user, password);
result = userManager.SetLockoutEnabled(user.Id, false);
}
// Add user admin to Role Admin if not already added
var rolesForUser = userManager.GetRoles(user.Id);
if (!rolesForUser.Contains(role.Name))
{
var result = userManager.AddToRole(user.Id, role.Name);
}
// Create users role
const string userRoleName = "Users";
role = roleManager.FindByName(userRoleName);
if (role == null)
{
role = new IdentityRole(userRoleName);
var roleresult = roleManager.Create(role);
}
}
}
What should I change to the code so those data return to the database?
Related
I'm trying to create the IdentityRole in a request, but I can't apply it to the database. Here's the code:
if (registerUser.Admin)
{
var role = await _roleManager.FindByIdAsync("Administrador");
if(role != null)
{
var userRole = new IdentityUserRole<string>
{
UserId = user.Id,
RoleId = role.Id
};
}
}
else
{
var role = await _roleManager.FindByIdAsync("25F3226654FD457E99C35B9A62B9CE3C");
if (role != null)
{
var userRole = new IdentityUserRole<string>
{
UserId = user.Id,
RoleId = role.Id
};
}
}
OBS: It's worth mentioning, when I look for these Roles I can't find them by name, but by id with you.
I will attach how I create this Role:
builder.Entity<IdentityRole>().HasData(new IdentityRole { Id="6596B380EC604E9A8708924CCCD717EC", Name= "Administrador" });
builder.Entity<IdentityRole>().HasData(new IdentityRole { Id = "25F3226654FD457E99C35B9A62B9CE3C", Name = "DefaultUser" });
Along with the code above, I created a "standard" user, and I can pass the Role to him, here's the code:
builder.Entity<IdentityUserRole<string>>().HasData(new IdentityUserRole<string> { UserId = "0CD0E173758F4492B41EDD4A51D36BA5", RoleId = "6596B380EC604E9A8708924CCCD717EC" });
So it means that I am not able to do such a process in the request only, any idea how I can do this?
I'm changing the way i seed data on my app using entiy framework core. Previous to 2.1 version you cannot set the identity key value so I started migrating my code but now i have a problem with seeding Users and Roles from the Identity. How can i access userManager or RoleManager on my DbContext file or modelbinder extension?
Here is how i seed users and roles using a class and inject it in program.cs
public class DbInitializer
{
public static async Task Seed(ApplicationDbContext context, UserManager<User> userManager, RoleManager<Role> roleManager)
{
#region Identity
string[] roles = new string[] { "Developer", "Super Administrator", "Administrator", "User" };
foreach (string role in roles)
{
if (!context.Roles.Any(r => r.Name == role))
{
await roleManager.CreateAsync(new Role(role));
}
}
var user = new User
{
Name = "test",
Email = "test#test.com",
NormalizedEmail = "TEST#TEST.COM",
UserName = "test",
NormalizedUserName = "TEST",
EmailConfirmed = true,
PhoneNumberConfirmed = false,
SecurityStamp = Guid.NewGuid().ToString("D")
};
if (!context.Users.Any(u => u.UserName == user.UserName))
{
var password = new PasswordHasher<User>();
var hashed = password.HashPassword(user, "development");
user.PasswordHash = hashed;
var result = await userManager.CreateAsync(user);
}
await AssignRoles(userManager, user.UserName, roles);
#endregion
}
public static async Task<IdentityResult> AssignRoles(UserManager<User> userManager, string userName, string[] roles)
{
User user = await userManager.FindByNameAsync(userName);
var result = await userManager.AddToRolesAsync(user, roles);
return result;
}
}
program file
var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
var isDevelopment = environment == Environments.Development;
if (isDevelopment)
{
using var scope = host.Services.CreateScope();
var services = scope.ServiceProvider;
try
{
var context = services.GetRequiredService<ApplicationDbContext>();
var roleManager = services.GetRequiredService<RoleManager<Role>>();
var userManager = services.GetRequiredService<UserManager<User>>();
await DbInitializer.Seed(context, userManager, roleManager);//<---Do your seeding here
}
catch (Exception ex)
{
Log.Error(ex, "An error occurred while seeding the database.");
}
}
now i want to start using this instead after version 2.1
public static class ModelBuilderExtensions
{
public static void Seed(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<Author>().HasData(
new Author
{
AuthorId = 1,
FirstName = "William",
LastName = "Shakespeare"
}
);
modelBuilder.Entity<Book>().HasData(
new Book { BookId = 1, AuthorId = 1, Title = "Hamlet" },
new Book { BookId = 2, AuthorId = 1, Title = "King Lear" },
new Book { BookId = 3, AuthorId = 1, Title = "Othello" }
);
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Seed();
}
If you inherited from IdentityDbContext then you can get the users table by
modelBuilder.Entity<Users>().HasData(
new User
{
}
I'm getting this message when trying to update-database.
This is my Configuration.cs file with the seeder:
internal sealed class Configuration : DbMigrationsConfiguration<MiracleMachine.data.ApplicationDbContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = 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. E.g.
//
// context.People.AddOrUpdate(
// p => p.FullName,
// new Person { FullName = "Andrew Peters" },
// new Person { FullName = "Brice Lambson" },
// new Person { FullName = "Rowan Miller" }
// );
//
context.Props.AddOrUpdate(
p => p.PropName,
new Prop() { PropName = "sharpie" },
new Prop() { PropName = "coin" },
new Prop() { PropName = "playing cards" },
new Prop() { PropName = "coffee mug" },
new Prop() { PropName = "phone" },
new Prop() { PropName = "keys" },
new Prop() { PropName = "sunglasses" },
new Prop() { PropName = "headphones" },
new Prop() { PropName = "ring" },
new Prop() { PropName = "lighter" }
);
context.SaveChanges();
context.Theories.AddOrUpdate(
t => t.TheoryId,
new Theory()
{
TheoryId = 0,
TheoryName = "Production",
TheoryDescription = "Make it appear out of nowhere!"
},
new Theory()
{
TheoryId = 1,
TheoryName = "Vanish",
TheoryDescription = "Make it vanish into thin air!"
},
new Theory()
{
TheoryId = 2,
TheoryName = "Transportation",
TheoryDescription = "Make it vanish, and then reappear somewhere impossible!"
},
new Theory()
{
TheoryId = 3,
TheoryName = "Transformation", // This uses TWO props
TheoryDescription = "Cause one of these items to change into the other item!"
},
new Theory()
{
TheoryId = 4,
TheoryName = "Multiplication",
TheoryDescription = "Magically duplicate this item again and again!"
},
new Theory()
{
TheoryId = 5,
TheoryName = "Penetration", // This uses TWO props
TheoryDescription = "Cause the two items to inexplicably pass through each other"
},
new Theory()
{
TheoryId = 6,
TheoryName = "Restoration",
TheoryDescription = "Destroy the item in some way. Restore it."
},
new Theory()
{
TheoryId = 7,
TheoryName = "Levitation",
TheoryDescription = "Make the item float in mid-air!"
});
context.SaveChanges();
//////////////////////////////////////////// The following seeds user data
// ApplicationUser table seeder
UserStore<ApplicationUser> userStore = new UserStore<ApplicationUser>(context);
UserManager<ApplicationUser> userManager = new UserManager<ApplicationUser>(userStore);
RoleStore<Role> roleStore = new RoleStore<Role>(context);
RoleManager<Role> roleManager = new RoleManager<Role>(roleStore);
if (!roleManager.RoleExists("Admin"))
roleManager.Create(new Role { Name = "Admin" });
if (!roleManager.RoleExists("User"))
roleManager.Create(new Role { Name = "User" });
IdentityResult result = null; // Sets the result to null. Used for error checking.
/////////// Admin (1)
ApplicationUser admin1 = userManager.FindByName("MagicRawb");
if (admin1 == null)
{
admin1 = new ApplicationUser
{
FirstName = "Rob",
LastName = "Greenlee",
UserName = "magicrawb",
Email = "magicrawb#test.com"//,
//Gender = Gender.Male
};
}
result = userManager.Create(admin1, "asdfasdf");
if (!result.Succeeded)
{
string error = result.Errors.FirstOrDefault();
throw new Exception(error);
}
userManager.AddToRole(admin1.Id, "Admin"); // Add user1 to Admin role
admin1 = userManager.FindByName("magicrawb"); // Assign user1 data to variable user1
/////////// Admin (2)
ApplicationUser admin2 = userManager.FindByName("admin2");
if (admin2 == null)
{
admin2 = new ApplicationUser
{
FirstName = "Bekah",
LastName = "Sells",
UserName = "admin2",
Email = "admin2#test.com"//,
// Gender = Gender.Female
};
}
result = userManager.Create(admin2, "asdfasdf");
if (!result.Succeeded)
{
string error = result.Errors.FirstOrDefault();
throw new Exception(error);
}
userManager.AddToRole(admin2.Id, "Admin"); // Add user1 to Admin role
admin1 = userManager.FindByName("admin2"); // Assign user1 data to variable user1
/////////// User (1)
ApplicationUser user1 = userManager.FindByName("user1");
if (user1 == null)
{
user1 = new ApplicationUser
{
FirstName = "Lance",
LastName = "Burton",
UserName = "user1",
Email = "user1#test.com"//,
//Gender = Gender.Male
};
}
result = userManager.Create(user1, "asdfasdf");
if (!result.Succeeded)
{
string error = result.Errors.FirstOrDefault();
throw new Exception(error);
}
userManager.AddToRole(user1.Id, "User"); // Add user1 to Admin role
user1 = userManager.FindByName("user1"); // Assign user1 data to variable user1
/////////// User (2)
ApplicationUser user2 = userManager.FindByName("user2");
if (user2 == null)
{
user2 = new ApplicationUser
{
FirstName = "David",
LastName = "Stone",
UserName = "user2",
Email = "user2#test.com"
//Gender = Gender.Male
};
}
result = userManager.Create(user2, "asdfasdf");
if (!result.Succeeded)
{
string error = result.Errors.FirstOrDefault();
throw new Exception(error);
}
userManager.AddToRole(user2.Id, "User"); // Add user1 to Admin role
user2 = userManager.FindByName("user2"); // Assign user1 data to variable user1
context.SaveChanges();
}
}
}
First I was using AddOrUpdate by PropId and TheoryId, but wasn't actually setting the Id's. I thought this might be the problem and changed it. I've tried deleting the migrations and the ApplicationDbContext and redoing it completely (as per another similar question I found on here) and I'm still getting the same error.
EDIT : Maybe I should include the DbContext:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
this.Configuration.LazyLoadingEnabled = false;
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
public IDbSet<Prop> Props { get; set; }
public IDbSet<Theory> Theories { get; set; }
public IDbSet<NewTrick> NewTricks { get; set; }
}
I'm using EF for code-first migrations. When I update-database, I get this error message in the Nuget console:
Conflicting changes detected. This may happen when trying to insert multiple entities with the same key.
Here is my config.cs file with the Seed method:
internal sealed class Configuration : DbMigrationsConfiguration<MiracleMachine.data.ApplicationDbContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
protected override void Seed(MiracleMachine.data.ApplicationDbContext context)
{
context.Props.AddOrUpdate(
p => p.PropId,
new Prop() { PropName = "sharpie" },
new Prop() { PropName = "coin" },
new Prop() { PropName = "playing cards" },
new Prop() { PropName = "coffee mug" },
new Prop() { PropName = "phone" },
new Prop() { PropName = "keys" },
new Prop() { PropName = "sunglasses" },
new Prop() { PropName = "headphones" },
new Prop() { PropName = "ring" },
new Prop() { PropName = "lighter" }
);
context.SaveChanges();
context.Theories.AddOrUpdate(
t => t.TheoryId,
new Theory()
{
// TheoryId = 0,
TheoryName = "Production",
TheoryDescription = "Make it appear out of nowhere!"
},
new Theory()
{
// TheoryId = 1,
TheoryName = "Vanish",
TheoryDescription = "Make it vanish into thin air!"
},
new Theory()
{
// TheoryId = 2,
TheoryName = "Transportation",
TheoryDescription = "Make it vanish, and then reappear somewhere impossible!"
},
new Theory()
{
// TheoryId = 3,
TheoryName = "Transformation", // This uses TWO props
TheoryDescription = "Cause one of these items to change into the other item!"
},
new Theory()
{
// TheoryId = 4,
TheoryName = "Multiplication",
TheoryDescription = "Magically duplicate this item again and again!"
},
new Theory()
{
// TheoryId = 5,
TheoryName = "Penetration", // This uses TWO props
TheoryDescription = "Cause the two items to inexplicably pass through each other"
},
new Theory()
{
// TheoryId = 6,
TheoryName = "Restoration",
TheoryDescription = "Destroy the item in some way. Restore it."
},
new Theory()
{
// TheoryId = 7,
TheoryName = "Levitation",
TheoryDescription = "Make the item float in mid-air!"
});
context.SaveChanges();
//////////////////////////////////////////// The following seeds user data
// ApplicationUser table seeder
UserStore<ApplicationUser> userStore = new UserStore<ApplicationUser>(context);
UserManager<ApplicationUser> userManager = new UserManager<ApplicationUser>(userStore);
RoleStore<Role> roleStore = new RoleStore<Role>(context);
RoleManager<Role> roleManager = new RoleManager<Role>(roleStore);
if (!roleManager.RoleExists("Admin"))
roleManager.Create(new Role { Name = "Admin" });
if (!roleManager.RoleExists("User"))
roleManager.Create(new Role { Name = "User" });
IdentityResult result = null; // Sets the result to null. Used for error checking.
/////////// Admin (1)
ApplicationUser admin1 = userManager.FindByName("MagicRawb");
if (admin1 == null)
{
admin1 = new ApplicationUser
{
FirstName = "Rob",
LastName = "Greenlee",
UserName = "magicrawb",
Email = "magicrawb#test.com",
Gender = Gender.Male
};
}
result = userManager.Create(admin1, "asdfasdf");
if (!result.Succeeded)
{
string error = result.Errors.FirstOrDefault();
throw new Exception(error);
}
userManager.AddToRole(admin1.Id, "Admin"); // Add user1 to Admin role
admin1 = userManager.FindByName("magicrawb"); // Assign user1 data to variable user1
/////////// Admin (2)
ApplicationUser admin2 = userManager.FindByName("admin2");
if (admin2 == null)
{
admin2 = new ApplicationUser
{
FirstName = "Bekah",
LastName = "Sells",
UserName = "admin2",
Email = "admin2#test.com",
Gender = Gender.Female
};
}
result = userManager.Create(admin2, "asdfasdf");
if (!result.Succeeded)
{
string error = result.Errors.FirstOrDefault();
throw new Exception(error);
}
userManager.AddToRole(admin2.Id, "Admin"); // Add user1 to Admin role
admin1 = userManager.FindByName("admin2"); // Assign user1 data to variable user1
/////////// User (1)
ApplicationUser user1 = userManager.FindByName("user1");
if (user1 == null)
{
user1 = new ApplicationUser
{
FirstName = "Lance",
LastName = "Burton",
UserName = "user1",
Email = "user1#test.com",
Gender = Gender.Male
};
}
result = userManager.Create(user1, "asdfasdf");
if (!result.Succeeded)
{
string error = result.Errors.FirstOrDefault();
throw new Exception(error);
}
userManager.AddToRole(user1.Id, "User"); // Add user1 to Admin role
user1 = userManager.FindByName("user1"); // Assign user1 data to variable user1
/////////// User (2)
ApplicationUser user2 = userManager.FindByName("user2");
if (user2 == null)
{
user2 = new ApplicationUser
{
FirstName = "David",
LastName = "Stone",
UserName = "user2",
Email = "user2#test.com",
Gender = Gender.Male
};
}
result = userManager.Create(user2, "asdfasdf");
if (!result.Succeeded)
{
string error = result.Errors.FirstOrDefault();
throw new Exception(error);
}
userManager.AddToRole(user1.Id, "User"); // Add user1 to Admin role
user2 = userManager.FindByName("user2"); // Assign user1 data to variable user1
context.SaveChanges();
Database.SetInitializer(new MyInitializer());
}
}
internal class MyInitializer : MigrateDatabaseToLatestVersion<ApplicationDbContext, Configuration>
{
}
}
I set the Id's of Theory and Prop as the Key which I thought EF would auto generate. I didn't set any for props and commented them out on the theories, so I'm a bit confused as to what's happening.
In your AddOrUpdate method, you're using a field to match, but you're never setting it.
You should either set the id, or use another field to match. Ex:
context.Props.AddOrUpdate(
p => p.PropName,
new Prop() { PropName = "sharpie" },
new Prop() { PropName = "coin" },
new Prop() { PropName = "playing cards" },
new Prop() { PropName = "coffee mug" },
new Prop() { PropName = "phone" },
new Prop() { PropName = "keys" },
new Prop() { PropName = "sunglasses" },
new Prop() { PropName = "headphones" },
new Prop() { PropName = "ring" },
new Prop() { PropName = "lighter" });
I have the following code:
var roleEditionCNT = new Role { ApplicationName = "TTT", RoleName = "EDITION_CNT" };
var roleEditionKCD = new Role { ApplicationName = "TTT", RoleName = "EDITION_KCD" };
var roleEditionInterne = new Role { ApplicationName = "TTT", RoleName = "EDITION_INTERNE" };
var roleConsultationInterne = new Role { ApplicationName = "TTT", RoleName = "CONSULTATION_INTERNE" };
var roleConsultationExterne = new Role { ApplicationName = "TTT", RoleName = "CONSULTATION_EXTERNE" };
var roleAdministrator = new Role { ApplicationName = "TTT", RoleName = "ADMINISTRATOR" };
new List<Role>
{
roleEditionCNT,
roleEditionKCD,
roleEditionInterne,
roleConsultationInterne,
roleConsultationExterne,
roleAdministrator
}.ForEach(b => context.Roles.AddOrUpdate(m => m.RoleName, b));
Then I can do:
var myUser = new User
{
Company = "DELTOY",
FirstName = "BRYAN",
LastName = "KENETH",
Roles = new List<Role> { roleEditionCNT }
};
Now I would like to modify the way I assign roles like this:
var myUser = new User
{
Company = "DELTOY",
FirstName = "BRYAN",
LastName = "KENETH",
Roles = new List<Role> { new Role { ApplicationName = "TTT", RoleName = "EDITION_CNT" } }
};
This code compiled successfully but at runtime I got the error:
Violation of PRIMARY KEY constraint 'PK_Roles'. Cannot insert
duplicate key in object 'dbo.Roles'
By simply modifying the above code, it seems the system is trying to add a new record to the table Roles. How can I simply assign Role but not using the variable. I prefer to give rolename with a string.
Any idea?
In the second example you are trying to add a User with a new Role as opposed to assigning it to an existing Role. The Role you are trying to add already exists in the Roles table.
You can get the Role object into a variable like.
var role = context.First(p => p.RoleName == "EDITION_CNT");
and then assign it to the new User.
var myUser = new User
{
Company = "DELTOY",
FirstName = "BRYAN",
LastName = "KENETH",
Roles = new List<Role> { role }
};