Creiamo un progetto App Web Asp .Net Core MVC ,una volta creato il progetto scrivete nella “Console di Gestione Pacchetti ":
Install-Package Microsoft.EntityFrameworkCore.Tools
vi consiglio di usare il seguente comando per visualizzare le funzionalità proprie del package appena installato :
per saperne di più digitate nella console di gestione pacchetti "Get-Help about_EntityFrameworkCore" e premete invio :-) ,
considerato che nell'esempio useremo Sql Server con lo Scaffold DB Context dobbiamo installare il pacchetto Microsoft.EntityFrameworkCore.SqlServer ed a tal fine eseguiamo il seguente comando
Install-Package Microsoft.EntityFrameworkCore.SqlServer
in seguito eseguite il comando Scaffold-DbContext per creare il dbcontext che verrà utilizzato dall'applicazione , questo modo di creare il dbcontext è detto “Database First” ovvero si parte dal db esistente per creare le entità dell'applicazione,
supponiamo di utilizzare il database Northwind https://github.com/Microsoft/sql-server-samples/tree/master/samples/databases/northwind-pubs ,apritelo con Sql Management Studio e cliccate su Execute ,ora dovremmo avere il database Northwind popolato.
A questo punto possiamo eseguire con successo il comando :
Scaffold-DbContext "Data Source=(localdb)\mssqllocaldb;Initial Catalog=Northwind;Integrated Security=True" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -ContextDir Context -Context NorthwindContext
Come risultato avremo una directory Context dentro la quale troveremo il file NorthwindContext.cs ,esso contiene la “mappatura” del database fisico nelle entità,avremo inoltre una nuova directory Models che contiene le classi che rappresentano le tabelle del db
, in models troviamo le classi relative alle tabelle del db , qui sotto la lista non completa :
Per vedere l'utilizzo pratico di quanto appena fatto andiamo sulla dir controller ,tasto destro-> aggiungi-> controller:
clicchiamo su Aggiungi
scegliamo ,ad esempio Customer come classe e NorthwindContext come contesto ,clicchiamo su Aggiungi ,eseguita la procedura di Scaffolding da parte di Visual Studio andiamo a vedere la directory Controllers
all'interno della cartella troviamo un nuovo controller riferito alla gestione dei Customers ,prima di vedere il controller in azione spostiamo la nostra attenzione al file Program.cs e troviamo
questo metodo definisce le regole di route ,se non settiamo nessun percorso (oltre al nome del server) verranno usati i default ,ovvero verrà selezionato il controller Home e l'action Index del controller Home ,se nel path di route abbiamo solo Customers (il nome del controller) verrà chiamata l'azione di default ovvero Index
se andiamo sotto la directory Views/Home/ troveremo il file Index.cshtml che contiene il messaggio di Welcome.
Nel file Program dobbiamo aggiungere il dbcontext :
builder.Services.AddDbContext<NorthwindContext>(options =>options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
il valore DefaultConnection è ricavato dalla sezione ConnectionStrings valore della chiave “DefaultConnection” del file appsettings.json che vedete qua sotto:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"ConnectionStrings": {
"DefaultConnection": "Data Source=(localdb)\\mssqllocaldb;Initial Catalog=Northwind;Integrated Security=True"
},
"AllowedHosts": "*"
}
Mandiamo in esecuzione il programma cliccando su Esegui o premendo F5 , proviamo ora a chiamare il CustomersController aggiungendo alla barra dell'indirizzo “Customers” , così :
https://localhost:7074/Customers
ed otteniamo:
Osserviamo le action dentro il controller :
l'action Create senza parametri è chiamata da un anchor tag helper dentro la pagina Index.cshtml sotto Views/Customers , il codice è <a asp-action="Create">Create New</a> , l'attributo asp-controller è stato omesso poiché se non viene specificato nessun controller è chiamato il controller di default che chiama la vista corrente,avremmo potuto scrivere <a asp-controller="Customers" asp-action="Create">Create New</a> ed ottenuto lo stesso risultato.La prima create si occupa quindi di reinviarci alla view dove inseriremo i dati del nuovo customer , la seconda create raccoglie i dati inseriti e crea un nuovo customer sul db. Il primo Create riceve una richiesta get da un link , il secondo riceve una richiesta di tipo post da un form ,il method non è specificato poiché di default vale “post” : <form asp-action="Create"> è quindi equivalente ad <form asp-action="Create" method="post">
Aggiungiamo Identity al progetto :
se partiamo con un progetto nuovo in fase di creazione del progetto con Visual Studio possiamo scegliere “Account Individuali” oppure da riga di comando “dotnet new mvc –auth Individual --use-local-db” per aggiungere Identity.Per aggiungere Identity in un progetto esistente dobbiamo invece seguire una procedura:
1) installiamo i seguenti due package:
Install-Package Microsoft.AspNetCore.Identity.EntityframeworkCore
Install-Package Microsoft.AspNetCore.Identity.UI
2) dobbiamo far derivare NorthwindContext da IdentityDbContext ovvero:
public class NorthwindContext : IdentityDbContext {
...….......
…..............
}
3) configuriamo i servizi di Identity aggiungendoli ai services della classe Program:
builder.Services.AddDefaultIdentity<IdentityUser>() .AddEntityFrameworkStores<NorthwindContext >();
in questo modo NorthwindContext erediterà il mapping specifico di Identity e sarà possibile gestire i dati relativi agli utenti utilizzando le tabelle a questo preposte,
per utilizzare il mapping aggiungiamo la chiamata al metodo base.OnModelCreating (builder) all'interno del metodo OnModelCreating (che potete trovare nella classe NorthwindContext) ,in pratica :
protected override void OnModelCreating(ModelBuilder modelBuilder)
{ base.OnModelCreating(modelBuilder);
//qui segue il nostro codice di mapping
}
è chiaro quindi che viene chiamato il metodo OnModelCreating della classe IdentityDbContext passandogli il modelBuilder ,essendo aspnetcore opensource possiamo andare a vedere dove Identity definisce la struttura delle identità che lo vanno a definire:
https://github.com/dotnet/aspnetcore/blob/main/src/Identity/EntityFrameworkCore/src/IdentityUserContext.cs
4) per continuare la nostra procedura dobbiamo aggiungere due middleware :
app.UseAuthorization();
i middleware devono essere aggiunti nel punto “giusto” ,al contrario dei services , un punto adatto potrebbe essere dopo il routing :
app.UseRouting();
5)poichè la UI di Identity usa le razor pages dobbiamo abilitare le razor pages aggiungendo il servizio RazorPages nel file Program così :
builder.Services.AddRazorPages()
ed il middleware MapRazorPages nel seguente modo prima di app.Run():
app.MapRazorPages();
6) il modello concettuale ora contiene anche le identità di Identity , per allinearlo con il database dobbiamo creare una migration usando il comando Add-Migration scegliendo un nome significativo per la migration ad esempio Add-Migration Identity , eseguiamo il comando a cui facciamo seguire il comando “Update-Database” che porta le modifiche sul database fisico
7) aggiungiamo la partial view _LoginPartial.cshtml ,dobbiamo chiamare questa LoginPartial nel file _Layout.cshtml
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item"><a class="nav-link text-dark" asp-area="" asp-controller="Home" asp- action="Index">Home</a></li>
<partial name="_LoginPartial" />
</div>
Vediamo cosa contiene la LoginPartial fornita da Identity :
@inject SignInManager<IdentityUser> SignInManager
@inject UserManager<IdentityUser> UserManager
<ul class="navbar-nav">
@if (SignInManager.IsSignedIn(User))
{
<a id="manage" class="nav-link text-dark" asp-area="Identity" asp- page="/Account/Manage/Index" title="Manage">Hello @UserManager.GetUserName(User)!</a>
</li><li class="nav-item">
<form id="logoutForm" class="form-inline" asp-area="Identity" asp-page="/Account/Logout" asp-route-returnUrl="@Url.Action("Index", "Home", new { area = "" })"><button id="logout" type="submit" class="nav-link btn btn-link text-dark border-0">Logout</button></form>
</li>
} else {
<a class="nav-link text-dark" id="register" asp-area="Identity" asp- page="/Account/Register">Register</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" id="login" asp-area="Identity" asp- page="/Account/Login">Login</a>
</li>
}
</ul>