Lezione 4 – Inizializzazione Tabella Utenti
Finora abbiamo visto come accedere ad un database SQL Server e come modificare lo schema base del Identity Model per aggiungere campi che ci serviranno in seguito per vendita dei prodotti del sito. Ora vediamo come fare il seed (seminare/inizializzare) di una tabella del DB.
Iniziamo creando il nuovo folder Services,
dove inseriremo la classe SeedData.
public class SeedUserList
{
public string Name { get; set; }
public string Role { get; set; }
public SeedUserList(string name, string role)
{
Name = name;
Role = role;
}
}
public class SeedData
{
public static void InitializeIdentity(IServiceProvider serviceProvider)
{
string userPWD = "pwdadmin";
var context = new ApplicationDbContext(serviceProvider.GetRequiredService>());
string[] roleNames = { "Admin", "PowerUser", "User", "Guest", "Member" };
var roleStore = new RoleStore(context);
foreach (var roleName in roleNames)
{
if (!context.Roles.Any(r => r.Name == roleName))
{
var role = new IdentityRole
{
Name = roleName,
NormalizedName = roleName.ToUpper()
};
roleStore.CreateAsync(role).Wait();
}
}
SeedUserList[] userNames = {
new SeedUserList("admin@local.net", "Admin".ToUpper()),
new SeedUserList("poweruser@local.net ", "PowerUser".ToUpper()),
new SeedUserList("user@local.net", "User".ToUpper()),
new SeedUserList("guest@local.net", "Guest".ToUpper())
};
var userStore = new UserStore(context);
foreach (var seeduser in userNames)
{
var testuser = userStore.FindByNameAsync(seeduser.Name).Result;
if (testuser == null)
{
var user = new ApplicationUser();
var password = new PasswordHasher();
user.UserName = seeduser.Name;
user.Email = user.UserName;
user.NormalizedUserName = user.UserName.ToUpper();
user.NormalizedEmail = user.UserName.ToUpper();
user.PasswordHash = password.HashPassword(user, userPWD);
user.Name = user.UserName;
user.Address = "";
user.City = "";
user.State = "IT";
user.Country = "Italia";
user.PostalCode = "";
user.FiscalCode = "";
user.EmailConfirmed = true;
user.ConsensoViewEmail = false;
user.ConsensoCookie = true;
user.HasRoles = true;
user.EntryDate = DateTime.Now;
userStore.CreateAsync(user).Wait();
userStore.AddToRoleAsync(user, seeduser.Role).Wait();
}
}
}
}
Il codice da inserire è composto da due classi. La prima SeedUserList è una classe che definisce una semplice lista che useremo per l’inizializzazione dei nuovi utenti di default. La seconda è SeedData che conterrà i metodi di inizializzazione delle tabelle del DB. Iniziamo con InitializeIdentity che richiede un paramento IServiceProvider. Il codice di InitializeIdentity è abbastanza comprensibile nella sua semplicità. In particolare notiamo la variabile context che verrà definita come ApplicationDbContext e servirà ad accedere ai metodi del DBContext per verificare se uno della lista dei Role da inserire è già presente o meno. Per l’inserimento del nuovo Role usiamo RoleStore che aggiornerà il DB automaticamente alla fine dell’inserimento. Per gli utenti usiamo invece lo UserStore che ci permette la creazione e l’assegnazione del ruolo, e che provvederà automaticamente all’aggiornamento del DB.
Inseriamo le using relative alle librerie di classi per non incorrere in errori di compilazione.
//ETBWDDEV v
var scope = app.Services.CreateScope();
var serviceProvider = scope.ServiceProvider;
try
{
//var context = serviceProvider.GetRequiredService<ApplicationDbContext>();
//context.Database.Migrate();
SeedData.InitializeIdentity(serviceProvider);
//SeedData.InitializeDB(serviceProvider);
}
catch (Exception ex)
{
var logger = serviceProvider.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "Un errore si è verificato durante il caricamento del DB.");
}
//ETBWDDEV ^
Iniziamo creando il ServiceProvider ed entriamo nel blocco try-catch per evitare di avere eccezioni che non ci facciamo capire l’errore in corso e eseguiamo il metodo SeedData.InitializeIdentity.
Compiliamo e lanciamo il debug.
L’applicazione andrà in errore di runtime e avremo una pagina di eccezione con le informazioni necessarie per la ricerca dell’errore:
“An unhandled exception occurred while processing the request.
InvalidOperationException: No service for type
'Microsoft.AspNetCore.Identity.UserManager`1[Microsoft.AspNetCore.Identity.IdentityUser]'
has been registered. …”
Viene riportato che il tipo
Microsoft.AspNetCore.Identity.UserManager`1[Microsoft.AspNetCore.Identity.IdentityUser]
Non è stato definito/creato. Possiamo notare che fa parte del tipo IdentityUser, ma noi l’abbiamo sostituito con ApplicationUser. Quindi l’errore dovrebbe essere questo. In qualche punto del codice si fa riferimento a IdentityUser al posto di ApplicationUser.
Se andiamo a controllare sotto troviamo il file dal quale è partita l’eccezione: _Layout.cshtml. Controlliamo il file alla ricerca di IdentityUser, ma non lo troviamo.
Possiamo notare però che ne codice HTML è presente la partial View _LoginPartial.cshtml.
Correggiamo IdentityUser con ApplicationUser nelle due richieste di inject e rilanciamo il debug. Adesso funziona tutto correttamente.
Nella prossima lezione andremo a creare ed inizializzare altre tabelle del DB.