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.

vs2022.png
aspnetcore.svg
entiryfrm.svg

Lezioni Food Shop

Inserite le prime lezioni
1/23/2022 12:00:00 AM

Inizia una nuova serie di Lezioni per la realizzazione di siti (Web App) per la vendita onli ...