Reputation: 774
Using the template built into VS2017 for Core 2 MVC with Authentication. Trying to seed the database with Users and Roles. Roles work well, they seed. Users always return an error saying "Cannot be NULL", i think its because this line at the end of the initialize function cannot actually find the user
await _userManager.AddToRoleAsync(await _userManager.FindByNameAsync(user), "Administrator");
I used this post to build it: https://gist.github.com/mombrea/9a49716841254ab1d2dabd49144ec092
NOTE - This post is for Core 1.0 and I am using Core 2.0, that might be why I am having problems.
As mentioned, I can seed Roles but the user is not creating itself. Once i figure this out I will try multiple users, i already did a test creating multiple roles.
Here is the Initializer Class
//Taken from :
//https://gist.github.com/mombrea/9a49716841254ab1d2dabd49144ec092
public interface IdentityDBIitializer
{
void Initialize();
}
public class LatestUserDBInitializer : IdentityDBIitializer
{
private readonly ApplicationDbContext _context;
private readonly UserManager<ApplicationUser> _userManager;
private readonly RoleManager<IdentityRole> _roleManager;
public LatestUserDBInitializer(
ApplicationDbContext context,
UserManager<ApplicationUser> userManager,
RoleManager<IdentityRole> roleManager)
{
_context = context;
_userManager = userManager;
_roleManager = roleManager;
}
//This example just creates an Administrator role and one Admin users
public async void Initialize()
{
//create database schema if none exists
_context.Database.EnsureCreated();
//If there is already an Administrator role, abort
//if (_context.Roles.Any(r => r.Name == "Administrator")) return;
//Create the Administartor Role
//await _roleManager.CreateAsync(new IdentityRole("Administrator"));
//Create the default Admin account and apply the Administrator role
string user = "[email protected]";
string password = "z0mgchangethis";
await _userManager.CreateAsync(new ApplicationUser { UserName = user, Email = user, EmailConfirmed = true }, password);
await _userManager.AddToRoleAsync(await _userManager.FindByNameAsync(user), "Administrator");
}
}
Here is my STartup:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<POSContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("UKFest2018Context")));
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("UKFestIdentityContext")));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
// Add Database Initializer
services.AddScoped<IdentityDBIitializer, LatestUserDBInitializer>();
// Add application services.
services.AddTransient<IEmailSender, EmailSender>();
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IdentityDBIitializer dBInitializer)
{
if (env.IsDevelopment())
{
app.UseBrowserLink();
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseAuthentication();
//Seeds Identity DB
dBInitializer.Initialize();
//UserRoleInitializer.InitializeUsersAndRoles(app.ApplicationServices);
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
Upvotes: 1
Views: 1396
Reputation: 1980
wew, same issue when i was working on .NET Core 2 Betas...
It could either mean that the credentials did not comply with your configurations. Or, in my case, I had to obtain the dbcontext and managers via an IServiceProvider.
You can do this at the end of Configure(...)
// Data seeding
await Data.DataSeeder.SeedDatabase(app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope());
Have a data seeder class that uses an IServiceScope to hook up with the dependencies, poof
public class DataSeeder
{
public static async Task SeedDatabase(IServiceScope scope)
{
try
{
CounterDbContext context = scope.ServiceProvider.GetService<CounterDbContext>();
CustoUserManager userManager = scope.ServiceProvider.GetRequiredService<CustoUserManager>();
CustoRoleManager roleManager = scope.ServiceProvider.GetRequiredService<CustoRoleManager>();
// SEED USER CODE HERE
// SEED USER CODE HERE
// SEED USER CODE HERE
// SEED USER CODE HERE
if (!context.CurrencyTypes.Any()) {
string[,] currencyTypes = new string[,] {
{ "Crypto", "CRYPTO" },
{ "Fiat Money", "FIAT" }
};
for (int i = 0; i < currencyTypes.GetLength(0); i++)
{
CurrencyType cType = new CurrencyType()
{
Name = currencyTypes[i, 0],
TypeShortForm = currencyTypes[i, 1],
};
context.CurrencyTypes.Add(cType);
}
context.SaveChanges(firstUser.Id);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
}
This could be messy... The above was the seeding class right? Here's how you do it for the users.
#if DEBUG
string[] CreateUsers = { "nixholas"};
string[] CreateNames = { "Nicholas" };
string[] CreateEmails = { "[email protected]" };
string defaultPassword = "P@ssw0rd";
// Seed the roles first
// https://stackoverflow.com/questions/34343599/how-to-seed-users-and-roles-with-code-first-migration-using-identity-asp-net-mvc
if (!roleManager.Roles.Any())
{
foreach (UserRoleType role in Enum.GetValues(typeof(UserRoleType)))
{
var newRole = new Role();
newRole.Name = role.ToString();
await roleManager.CreateAsync(newRole);
}
}
if (await userManager.FindByEmailAsync(CreateEmails[0]) == null)
{
for (int i = 0; i < CreateUsers.Length; i++)
{
User user = new User
{
Email = CreateEmails[i],
UserName = CreateUsers[i],
Name = CreateNames[i]
};
await userManager.CreateAsync(user, defaultPassword);
// Setup
await userManager.UpdateSecurityStampAsync(user);
user.NormalizedUserName = user.UserName;
user.NormalizedEmail = user.Email;
await userManager.UpdateNormalizedUserNameAsync(user);
await userManager.UpdateNormalizedEmailAsync(user);
await userManager.UpdateAsync(user);
// Email Automated Setup
var token = await userManager.GenerateEmailConfirmationTokenAsync(user);
await userManager.ConfirmEmailAsync(user, token);
await userManager.AddToRoleAsync(user, "Owner");
}
}
Upvotes: 0
Reputation: 30046
For your issue, it is caused by that your password is not valid which causes the creating user failed. Then, await _userManager.FindByNameAsync(user)
will return null instead of the expected User.
You could try the Password like 1qaz@WSX.
You could refer enter link description here to find the default requirements.
Upvotes: 1