0

In my Seed() method of Configuration.cs, I'm getting some errors when adding data:

Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.

StackTrace

at System.Data.Entity.Internal.InternalContext.SaveChanges()

My Configuration.cs file with seed data:

namespace MarginWorkbenchNG.Migrations
{
using System;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Linq;
using System.Collections.Generic;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;

internal sealed class Configuration : DbMigrationsConfiguration<MarginWorkbenchNG.Models.ApplicationDbContext>
{
 public Configuration()
 {
  AutomaticMigrationsEnabled = true;
  AutomaticMigrationDataLossAllowed = true;   // added - BM:
  ContextKey = "MarginWorkbenchNG.Models.ApplicationDbContext";
 }

 protected override void Seed(MarginWorkbenchNG.Models.ApplicationDbContext context)
 {

  var hasher = new PasswordHasher();

  // **** Causing "Validation failed" errors on line 80 of AccountController.cs ****
  context.Roles.AddOrUpdate(
   new IdentityRole { Name = "SystemAdministrator" }                
  );
  context.Users.AddOrUpdate(                
   new Models.ApplicationUser { Company = "ICAP", EmailConfirmed = true, FirstName = "Admin", LastName = "Demo", UserName = "admin@rzr.com", Email = "admin@rzr-risk.com", PasswordHash = hasher.HashPassword("test123") },
   new Models.ApplicationUser { Company = "ICAP", EmailConfirmed = true, FirstName = "Trader", LastName = "Demo", UserName = "trade@rzr.com", Email = "trade@rzr.com", PasswordHash = hasher.HashPassword("test123") }
  );

  context.SaveChanges();

 }
}
}

I have made a couple of minor changes to my ApplicationUser class in IdentityModels.cs, and I can certainly see the table schema changes any time I modify this class (i.e. I have auto-migration set to true). However, Seed() method fails.

public class ApplicationUser : IdentityUser
{
  // added Company, Name to profile - BM:
  public string Company { get; set; }
  public string FirstName { get; set; }
  public string LastName{ get; set; }        

  public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
  {
    // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
    var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
    // Add custom user claims here
    return userIdentity;
  }
}

FYI: At some point, when the AppNetUsers table was empty, the seed data was successful.

However, it's totally inconsistent now. I've deleted the records in AppNetUsers, and yet the Seed() method is stil failing. I don't understand.

**** UPDATE **** If I change the DB name in my web.config file, I can force it to create a brand new DB - and the seed() data works fine !

 <connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=MyDevBox;Initial Catalog=TestDB2;Integrated Security=True" providerName="System.Data.SqlClient" />  

However, I still don't understand the exceptions in my Seed() method above when I try to RE-CREATE the DB ?

thank you, Bob

bob.mazzo
  • 5,183
  • 23
  • 80
  • 149
  • Can you include the console output that happens when you try to seed (and it fails)? And include your Seed method. – toddmo Mar 09 '16 at 18:54
  • 2
    Please provide the failing source code in the seed() method? – Stephen Reindl Mar 09 '16 at 18:56
  • @toddmo, yes of course. I forgot the actual seed data. – bob.mazzo Mar 09 '16 at 19:56
  • 1
    Yes, use RoleManager & UserManager. On another note, when you use AddOrUpdate you should supply the field to check for existance: http://stackoverflow.com/questions/10007351/entity-framework-code-first-addorupdate-method-insert-duplicate-values – Steve Greene Mar 09 '16 at 20:28

1 Answers1

2

Don't add Identity objects directly to your DbContext use role manager and user manager instead:

protected override void Seed(MarginWorkbenchNG.Models.ApplicationDbContext context)
{
    var userManager = new ApplicationUserManager(new UserStore<Models.ApplicationUser>(context));
    var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));

    if (!roleManager.RoleExists("SystemAdministrator"))
        roleManager.Create(new IdentityRole("SystemAdministrator"));

    var adminUser = userManager.FindByName("admin@rzr.com");
    if (adminUser == null)
    {
         adminUser = new ApplicationUser
         {
             Company = "ICAP", 
             EmailConfirmed = true, 
             FirstName = "Admin", 
             LastName = "Demo", 
             UserName = "admin@rzr.com", 
             Email = "admin@rzr-risk.com"
         };
         userManager.Create(adminUser,"thePassword");
    }
    // adding roles to the user if necessary 
    if (!userManager.IsInRole(adminUser.Id, "SystemAdministrator"))
        userManager.AddToRole(adminUser.Id, "SystemAdministrator");

}
bob.mazzo
  • 5,183
  • 23
  • 80
  • 149
Sam FarajpourGhamari
  • 14,601
  • 4
  • 52
  • 56
  • I edited the post to show `` , based on c# suggested change. – bob.mazzo Mar 09 '16 at 21:07
  • I read that the `AddOrUpdate()` method would take care of checking whether the records exists or not. Perhaps not in the context of users and roles ? – bob.mazzo Mar 09 '16 at 21:08
  • 1
    It checks but you have to say which property is unique and must be checked, Also it would much better to let user manager create your user and add necessary logic then send it to context. – Sam FarajpourGhamari Mar 09 '16 at 21:12
  • 1
    I've accepted your edit. But you could add relevant namespace to prevent the error. – Sam FarajpourGhamari Mar 09 '16 at 21:15
  • I did add the Models namespace, yes. – bob.mazzo Mar 09 '16 at 21:24
  • do I need to basically repeat this code for say 10 users ? – bob.mazzo Mar 09 '16 at 21:35
  • Yes. but just adding user part. And If you have more than role you have to repeat adding new rule part for each role also. – Sam FarajpourGhamari Mar 09 '16 at 21:39
  • in the previous MVC 4 version of this project, the developer created the roles with `List(Identityroles>` then did `roles.ForEach(x => roleManager.Create(x));`. But for the users, he did basically what you did except within a `.ForEach()` – bob.mazzo Mar 09 '16 at 22:15
  • Yap. You could put the repeating parts to a loop like `foreach` or whatever you want. The point is use user manager and role manager to add users and roles to the context and check to see if user or role already exist or not. – Sam FarajpourGhamari Mar 09 '16 at 22:20
  • one thing. I'm getting an exception `UserId not found` as soon as I hit `if (!userManager.IsInRole(adminUser.Id, "SystemAdministrator"))` . – bob.mazzo Mar 09 '16 at 23:05
  • I found this post, but your code looks just like his: http://stackoverflow.com/questions/29095425/checking-if-a-user-is-in-a-role-in-asp-net-mvc-identity – bob.mazzo Mar 09 '16 at 23:19
  • 1
    put `adminUser = userManager.FindByName("admin@rzr.com");` statement again after `userMannager.Create(..` method to fetch created method from db again. – Sam FarajpourGhamari Mar 10 '16 at 08:19
  • thank you very kindly for your assistance. It all works great. I had some `PasswordValidator` class errors. I hadn't properly disabled certain properties, so the seed password was failing due to dashes in the password value. I really appreciate it. – bob.mazzo Mar 10 '16 at 19:41