MVC IdentityServer Db Empty Usertable/Error seeding

Viewed 137

I'm new to MVC and I have this issue with my webserve that I can't seem to fix. In my Dbinit, I add a user to the user table and some ingredients to Ingredients table that I made. The ingredients get added to the table without any issues. The user, however, doesn't get added at all (dbo.AspNetUsers is empty).

When I run the program, I do get an exception in my Initialize task (in DbInitializer) > InvalidOperationException and as an error message "Error Seeding Database". This is an Exception I've implemented myself in Program.cs:

public static void Main(string[] args)
    {
      var host = BuildWebHost(args);

      using (var scope = host.Services.CreateScope())
      {
        var services = scope.ServiceProvider;
        try
        {
          var context = services.GetRequiredService<AppDbContext>();
          var dbInit = services.GetRequiredService<IDBInitializer>();

          dbInit.Initialize(context).GetAwaiter().GetResult();
        }
        catch (Exception ex)
        {
          var log = services.GetRequiredService<ILogger<Program>>();
          log.LogError(ex, "Error seeding Database.");
        }
       }

      host.Run();
    }

I'm not sure whether this Exception is related to my issue but I've been trying to fix it. My DbIinitializer inherits from an Interface which just contains the definition for the task. I call both IDBInitializer and DBInitializer in Startup.cs, where DBInitializer fails. Here is my DBInitializer code:

namespace mvcServer.Data
{
    public class DBInitializer : IDBInitializer
    {
      private readonly UserManager<User> userManager;
      private readonly RoleManager<IdentityRole> roleManager;

      public DBInitializer(UserManager<User> userManager, RoleManager<IdentityRole> roleManager)
      {
        this.userManager = userManager;
        this.roleManager = roleManager;
      }

    public async Task Initialize(AppDbContext context)
      {
        context.Database.EnsureCreated();

        // Look for any users
        if (context.Users.Any())
        {
          return; // Db has been seeded.
        }

      // Create roles
      await roleManager.CreateAsync(new IdentityRole("user"));

      // Populate Ingredients table
      context.Ingredients.AddRange(
        new Ingredient { Name = "Potato", Category = "Vegetable", Allergen = "Gluten", IsSafe = true },
        new Ingredient { Name = "Strawberry", Category = "Fruit", Allergen = "Sugar", IsSafe = false });

      await context.SaveChangesAsync();

        var user = new User
        {
          Name = "Andrea",
          Lastname = "X",
          AccessFailedCount = 0,
          Email = "andrea@gmail.com",
          NormalizedEmail = "ANDREA@GMAIL.COM",
          EmailConfirmed = false,
          LockoutEnabled = true,
          TwoFactorEnabled = false,
          UserName = "andrea",
          NormalizedUserName = "ANDREA"
        };

        var userResult = await userManager.CreateAsync(user, "Password123");
        var roleresult = await userManager.AddToRoleAsync(user, "user");

        if (userResult.Succeeded)
        {
          var currUser = await userManager.FindByNameAsync(user.UserName);

          // Assigns claims for security
          var claims = new List<Claim> {
                      new Claim(type: JwtClaimTypes.GivenName, value: user.Name),
                      new Claim(type: JwtClaimTypes.FamilyName, value: user.Lastname),
                  };
          await userManager.AddClaimsAsync(currUser, claims);

        }
        else
        {
          Debug.WriteLine(userResult.ToString());
        }
    }
  }
}

Is it because I add the ingredients using context.Ingredients.AddRange instead of the Async method? Although I've tried that and it does nothing. I'm also not sure whether I need to throw away my Migrations and restart completely when changing something like this.

Here's the Exception

System.InvalidOperationException
Message: Error seeding Database. Failed method:
Microsoft.AspNetCore.Identity.UserManager'1+<ValidateUserInternal>d_169.MoveNext

If I need to provide any more code or anything else let me know.

Edit: AppDbContext:

namespace mvcServer.Data
{
    public class AppDbContext : IdentityDbContext<User>
    {
      public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
      {
      }

    public DbSet<Ingredient> Ingredients { get; set; }
  }
}
1 Answers

After a lot of search I found the answer thanks to this post.

As answered by user "Daffy Punk" in that thread:

I am leaving this here for anyone that might have had a similar issue. I had exactly the same "symptoms". It turns out that the problem related to the password being stored not adhering to the configured password policy (at least one uppercase char, one lowercase char, etc etc).

As per below comments and answers, in general, the same vague error message is thrown when any of the user creation constraints or policies are not followed.

This might include the following:

Password policy not followed (this seems to be the most common cause) Required fields being passed through as empty strings / null Duplicate username or email There is really a wide range of issues which can cause this error to occur. If the above does not solve your problem, I suggest the following:

Familiarize yourself with the rules and policies for identityprovider as it was set up for your solution As per @Ted's answer below, trace or put a breakpoint on the UserManager.Create method to view the result, as this will likely reveal the cause of your problem.

In my case, the user I was creating's password simply did not meet the requirements set by me :)

Related