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; }
}
}