Il 0% ha trovato utile questo documento (0 voti)
110 visualizzazioni300 pagine

Core

Il documento descrive .NET Core, la piattaforma open source e cross-platform di Microsoft per lo sviluppo di applicazioni. Viene spiegato cosa è .NET Core, come è strutturato, quali linguaggi supporta e come installarlo e usarlo. Vengono inoltre descritti concetti chiave come .NET Standard, gli strumenti della CLI di .NET Core e le differenze rispetto a .NET Framework.

Caricato da

user404
Copyright
© All Rights Reserved
Per noi i diritti sui contenuti sono una cosa seria. Se sospetti che questo contenuto sia tuo, rivendicalo qui.
Formati disponibili
Scarica in formato PDF, TXT o leggi online su Scribd
Il 0% ha trovato utile questo documento (0 voti)
110 visualizzazioni300 pagine

Core

Il documento descrive .NET Core, la piattaforma open source e cross-platform di Microsoft per lo sviluppo di applicazioni. Viene spiegato cosa è .NET Core, come è strutturato, quali linguaggi supporta e come installarlo e usarlo. Vengono inoltre descritti concetti chiave come .NET Standard, gli strumenti della CLI di .NET Core e le differenze rispetto a .NET Framework.

Caricato da

user404
Copyright
© All Rights Reserved
Per noi i diritti sui contenuti sono una cosa seria. Se sospetti che questo contenuto sia tuo, rivendicalo qui.
Formati disponibili
Scarica in formato PDF, TXT o leggi online su Scribd

ASP.

NET Core
Daniele Bochicchio
Chief Digital Officer @icubedsrl
Microsoft Regional Director
Microsoft [Link] MVP

Network Manager @aspitalia


danieleb@[Link]
@dbochicchio
Cos’è .NET Core
Piattaforma di sviluppo cross-platform
Windows, macOS, Linux
Flexible deployment
Side-by-side o machine-wide
Open source su GitHub
Supportato da Microsoft
Eredita Base Class Library di .NET Framework 4.6
Rivisto: no dipendenze Windows
Compatibile .NET Framework, Xamarin and Mono
Com’è fatto .NET Core
.NET Runtime
• Type system, assembly loading
• RyuJIT, GC
• Native interop
Framework libraries
• System.*
• IO, Network, Data, Patterns
• Distribuiti tramite NuGet
.NET Core SDK
• Tools
• Compilatori
dotnet host app
• Lancia app e ospita il runtime
Linguaggi
C# e F# da .NET Core 1
VB arrivato con .NET Core 2
Si compilano tramite SDK
Editor testuali
• Multi piattaforma: Visual Studio Code, Sublime Text, Vim
• Windows: Visual Studio
.NET Core app = sono tutte console app
Usato è usato anche da:
• [Link] Core
• Windows 10 Universal Windows Platform (UWP)
• [Link]
Installazione
Microsoft .NET Core
• CoreCLR runtime
• dotnet app launcher
Microsoft .NET Core SDK
• Gestione pacchetti
• Compilazione
Dal sito [Link]
• Windows: installer
• Linux (Ubuntu, debian, Fedora, openSuse, CentOS): scripts
• macOS: installer
• Docker: microsoft/dotnet:latest
Architettura
Ambiente
• x86 (Windows)
• x64
• ARM64 e ARM32 in arrivo

90% codice condiviso

Codice specifico
• CoreCLR
• [Link] e [Link]
.NET Core CLI (Command Line Interface)
Linea di comando
• cmd, powershell, bash
Intero ciclo di sviluppo
Cross platform
• Windows, MacOS, Linux (Ubuntu, debian, Fedora, openSuse, CentOS)
Distribuito con .NET Core runtime
• Side by side (multiversione)
• .NET Core SDK per sviluppare, altrimenti solo launcher
Perché?
• Strumento base degli IDE
• Gestione Entity Framework, Cache, Bundling ecc
Comandi di .NET Core CLI
New
• Linguaggio: C#, F#, VB
• Tipologie: console, web, lib, xunittest
• Eventualmente usare yeoman
Restore
• Sulla base delle reference di progetto (o [Link])
• Nuget v3: cache, performante
• No Powershell
Build
• Incremental compilation
• Portable o self-contained
• Multi framework: .NET Core o .NET Framework
• Multi runtime (osx, deb)
• Script pre/post build
Demo
DotNet CLI exploration
Comandi di .NET Core CLI
Run
• Compila e lancia
• Multi target framework
• Diverso da dotnet [Link]
Test
• Unit test, nunit o xunit
• Motori installati via NuGet
• Sezione testRunner in [Link]
Pack
• Pacchetto nuget, con i simboli
Publish
• Deployment su cartella
• Script pre/post publish
Tools
Comandi aggiuntivi
• Deploy mediante NuGet
• Sostituiscono Powershell
Usati e creati da Microsoft
• [Link]
• [Link]
• [Link]
• [Link]
• [Link]
• [Link]
Terze parti
• [Link]
.NET Standard Library
Specifiche per set API
• BCL indipendente dalla
piattaforme

Comune a tutti i runtime


• .NET Core, .NET Framework

Garanzia di compatibilità
• Anche all’indietro grazie alle
versioni
• Più comodo rispetto a PCL

Official Artifacts da seguire


.NET Standard Library
Ogni versione è retro- .NET Standard 1.01.0 1.11.1 1.21.2 1.31.3 1.41.4 1.51.5 1.61.6 2.02.0
compatibile con le .NET Core 1.01.0 1.01.0 1.01.0 1.01.0 1.01.0 1.01.0 1.01.0 2.02.0
precedenti .NET Framework

1.6: .NET Core 1 (con .NET Core 1.x 4.54.5 4.54.5 [Link].1 4.64.6 [Link].1 [Link].2
SDK))
2.0: .NET Core 2
.NET Framework
(con .NET Core 2.0 4.54.5 4.54.5 [Link].1 4.64.6 [Link].1 [Link].1 [Link].1 [Link].1
SDK)
Mono 4.64.6 4.64.6 4.64.6 4.64.6 4.64.6 4.64.6 4.64.6 5.45.4
[Link] 10.010.0 10.010.0 10.010.0 10.010.0 10.010.0 10.010.0 10.010.0 10.1410.14
[Link] 3.03.0 3.03.0 3.03.0 3.03.0 3.03.0 3.03.0 3.03.0 3.83.8
[Link] 7.07.0 7.07.0 7.07.0 7.07.0 7.07.0 7.07.0 7.07.0 8.08.0

10.0.1629910.0. 10.0.1629910.0. 10.0.1629910.0.


UWP 10.010.0 10.010.0 10.010.0 10.010.0 10.010.0
16299 16299 16299

Windows 8.08.0 8.08.0 8.18.1

Windows Phone 8.18.1 8.18.1 8.18.1

Silverlight per
8.08.0
Windows Phone
.NET Standard Library
Pacchetti NuGet
• Estrema modularizzazione
• Assembly/Package per namespace

Pacchetti ufficiali e terze parti con target multipli


• Netxxx (es: net461): target su .NET Framework
• netstandardx.x (es. netstandard1.6): target su .NET Standard
• Compatibile quindi con .NET Core e .NET Framework 4.6.1
• netcoreappx.x (es. netcoreapp1.0): target su .NET Core

[Link]
• Metapackage: insieme di tutti i pacchetti .NET STandard
[Link]
• Metapackage: insieme di tutti i pacchetti .NET Core
Cosa vuol dire .NET Standard 2
Grazie agli shim inclusi in .NET Standard 2, si può referenziare
qualsiasi libreria .NET Framework – senza compilazione
Si ha accesso ad una miriade di funzionalità che mancavano in
.NET Core 1.x
• SmptClient ☺
• DataSet 
• [Link] 
• +20K API e il 70% dei package di NuGet
Comparazione con .NET Framework
App model
• .NET Core supporta solo console e [Link]
• WPF, WinForms non supportati perché specifici per Windows
• Tecnicamente possono esserci pacchetti NuGet per WPF, per esempio, compatibili .NET
Standard, ma funzionanti solo su Windows
API
• La maggior parte in comune, ma in assembly diversi (riorganizzati)
• Non API specifiche di Windows
• No Code Access Security

.NET Core è multi piattaforma e open source


• .NET Framework è read only per un sottoinsieme
Console application con .NET Core
public class Program
Entry point {
• In [Link] public static void Main(string[] args)
{
• Metodo statico Main [Link]("Hello world!");
}
Parametri opzionali attraverso args }
Namespace [Link]
• Lettura e scrittura
• Colorazione
Esecuzione
• dotnet run: compila, necessario SDK installato
• dotnet nomedll: lancia l’assembly compilato
csproj
Con VS 2017 .NET Core <Project Sdk="[Link]">
ha il classico csproj <PropertyGroup>
• Ma è una versione semplificata <VersionPrefix>1.0.0</VersionPrefix>
<VersionSuffix>alpha</VersionSuffix>
• Nelle preview veniva usato
<TargetFrameworks>netcoreapp2
[Link] </TargetFrameworks>
</PropertyGroup>

Ogni framework ha opzionalmente </Project>

• Specifiche dipendenze
• Dipendenze su GAC
• Opzioni di compilazione
csproj
<Target Name="MyPreCompileTarget"
Script da eseguire BeforeTargets="Build">
• Prima e dopo compilazione o pubblicazione <Exec Command="[Link]" />
</Target>
• Array o singola istruzione <Target Name="MyPostCompileTarget"
• Bat, cmd, sh, bash, DOS AfterTargets="Publish">
<Exec Command="[Link]" />
<Exec Command="[Link]" />
</Target>

Opzioni del runtime <PropertyGroup>


<ServerGarbageCollection>true</ServerGarbageCollection>
• Modalità del Garbage Collection <ConcurrentGarbageCollection>true</ConcurrentGarbageCollection>
<RetainVMGarbageCollection>true</RetainVMGarbageCollection>
• Utile in [Link] <!– esempio, non sono valori suggeriti -->
• Impostazioni del thread pool <ThreadPoolMinThreads>10</ThreadPoolMinThreads>
<ThreadPoolMaxThreads>100</ThreadPoolMaxThreads>
</ProeprtyGroup>
Compilazione
Genera in release dotnet publish –c release
• Cartella release\netcoreapp2.0

[Link]
• l’applicazione con l’entry point

[Link]
• le runtimeOptions specificate nel progetto (opzionale)

[Link]
• lista di tutte le dipendenze. Necessario in ambienti dinamici, come [Link]
Framework-dependent deployments
Modello predefinito
dotnet publish –c release -f netcoreapp2.0

Si distribuisce
• App con le dipendenze (comprese .NET Core libraries)
• Non il .NET Core Runtime
• Possibile variazione di comportamento in caso di patch

Richiesto .NET Core sulla target machine


• (Microsoft Azure per esempio già ne dispone)

Parametro -f necessario solo se multi framework


• Default è già netcoreapp2.0
Self-contained deployments
Si distribuisce
• App con le dipendenze (comprese .NET Core libraries)
• .NET Core Runtime
• Controllo totale
Non è richiesto .NET Core sulla target machine
Si indicano i runtime da supportare
"runtimes": {
"win10-x64": {},
"osx.10.10-x64": {}
Occorre generare più output per piattaforma }
• Maggiori dimensioni

dotnet publish -c release -r win10-x64


dotnet publish -c release -r osx.10.10-x64
Sviluppare librerie
Ha senso che siano compatibili con .NET Framework

frameworks => netstandard2


• O altra versione, secondo la tabella

{
dependencies => [Link] "dependencies":{
"[Link]":"1.6.0"
},
"frameworks":{
"netstandard1.3":{}
}
}
Demo
Cos’è [Link] Core?
Una rivoluzionaria versione di [Link]
Basato su .NET Core
Un taglio netto rispetto al passato
Completamente riscritta
Cross-platform
Born in the cloud
Performante
[Link] Core
Milestone Data
Beta6 27/07/2015
Beta7 2/09/2015
Beta8 15/10/2015
RC1 Novembre 2015
RC2 Maggio 2016
1.0.0* Giugno 2016
1.1.1** Marzo 2017
1.2 Q2 2017
2.0 Q3 2017
2.1 Q1 2018

I tool di VS 2015 sono in preview ** I tool sono solo per VS 2017


[Link]
Che fine ha fatto [Link] 5?
[Link] Core 1.0 è [Link] 5
Nel 2016 è stato cambiato di nome, per chiarire meglio che è un framework
tutto nuovo
Troverete ogni tanto riferimenti non aggiornati in documentazione e su
internet
[Link] 4.6 e [Link] Core
[Link] 2017

.NET Framework 4.6 .NET Core


.NET Framework per tutti gli scenari a cui siamo Librerie modulari e runtime ottimiazzato per il
abituati e solo su Windows cloud, cross-platform
MSBuild -> [Link]
[Link] CodeDOM -> [Link] Application DNX (Roslyn)

4.x Loose, GAC,


NuGet
Libraries NuGet

Application
FCL, GAC, NuGet NuGet

Open Source
Frameworks
IIS, [Link]
IIS Web Server Kestrel
Application
[Link] DNX
Host
Platform .NET BCL & FCL
.NET BCL & FCL
Libraries .NET on NuGet
.NET CLR
.NET CLR Runtime .NET Core CLR

IIS: [Link] Runtime


DNX
Exe: OS Loader
[Link]
Operating Windows, OSX, Core
Windows
System Linux
[Link] Core 101
[Link] Core = runtime + [Link] MVC + [Link] Web API
Usando [Link] Core finiamo inevitabilmente ad usare [Link] MVC
Addio [Link]
• Configurazione basata su codice/JSON
Modulare e componentizzabile
Gira su IIS o Self-hosted
• Kestrel
Dependency Injection già integrata
L’app web è di fatto una app console
• Vedi [Link] dentro il progetto
Novità di [Link] Core 2
Performance migliorate
Partenza più rapida, maggior numero di richieste al secondo
Partenza più rapida
Template semplificati
Benefici introdotti da .NET Core 2
.NET Standard 2, etc
Refactoring di componenti chiave
Runtime, hosting con IIS, autenticazione, logging
Si installa da [Link]
Server
[Link] è disegnato per essere disaccoppiato dal server
Tradizionalmente, [Link] è stato legato ad IIS
[Link] Core gira su IIS sfruttandolo come reverse proxy
Ci sono due server web:
• [Link] (Kestrel, cross-platform)
• [Link] (WebListener, Windows)
La configurazione è nel file [Link]
IIS vs Kestrel
Usando VS, viene usato IIS Express come reverse proxy
Usando IIS
• Possiamo optare per un HttpModule che fa da reverse proxy
• O usare WebListener, che gira direttamente su [Link]:
• più performante
• supporto all'autenticazione di Windows
• varie applicazioni in ascolto sulla stessa porta TCP
• uso di Server Name Indication, ovvero la possibilità di installare vari certificati SSL per lo stesso indirizzo IP del server;
• HTTP/2 su TLS (sfruttabile da Windows 10)
• invio diretto di file statici
• Caching delle risposte
• Supporto a WebSockets (da Windows 8 in poi)

Usando Kestrel
• È sempre necessario un reverse proxy
Possiamo implementare un server custom, implementando le classi IHttpRequestFeature e
IHttpResponseFeature
Demo
Esempio di Middleware: i file statici
Offre un ponte tra [Link] Core e le funzionalità aggiuntive
Ad esempio, i file statici sono supportati attraverso un MiddleWare
• Vedi [Link] / Configure -> UseStaticFiles
C’è una nuova impostazione del progetto, per gestire i file statici
• Vedi wwwroot
• Vedi UseContentRoot in [Link]
Se si vogliono vedere file aggiuntivi, bisogna utilizzare UseDirectoryBrowser
Se si vuole servire una pagina di default statica, bisogna utilizzare
UseDefaultFiles (prima di UseStaticFiles)
Demo
Dov’è il [Link]?
Esiste solo per compatibilità con IIS
Sostituito da un file chiamato [Link]
I parametri di configurazione sono in file JSON
• Con supporto degli environement

Dichiarazione in codice vs parsing a runtime di un file XML


[Link]
Classe che definisce l’entry point
Può stare in un assembly esterno, basta specificare la chiave
Hosting:Application
Può a propria volta accettare DI nel costruttore
Gestisce la Configuration attraverso un ConfigurationBuilder
Accende le opzioni di [Link] Core
• Es: file statici, MVC, etc
Semplificazione del progetto con .NET
Core 2
Aggiunta di un nuovo metapackage che include tutti i pacchetti di
uso comune
• [Link]
[Link]
Resta possibile referenziare i singoli pacchetti a mano
Runtime Store
• Contiene tutti gli asset di runtime, precompilati, che non vengono
scaricati da NuGet – usa il nuovo metapackage
WebHostBuild di default
Tutto già preconfigurato per gli scenari più diffusi
Dependency Injection
• Motore di Inversion Of Control integrato
• Gestione del ciclo di vita (lifetime) dell’istanza
• Possibilità di utilizzare plugin per motori di terze parti
• [Link] include già un motore di DI
DI con [Link] Core
Per configurare [Link]
public void ConfigureServices(IServiceCollection services)
{

[Link]<IMyService, MyService>();
[Link]<IMyRepository, MyRepository>();
}

AddTransient: ogni richiesta crea un’istanza. Indicato per servizi stateless.


AddScoped: un’istanza per richiesta (es: Repository, Context di Entity
Framework)
AddSingleton: l’istanza viene creata alla prima richiesta e poi conservata.
Come usare la DI
Costruttore nei controller
public class MyRepository : IMyRepository
{
private readonly ApplicationDbContext _dbContext;

public MyRepository(ApplicationDbContext dbContext)


{
_dbContext = dbContext;
}
}

Oppure con [FromServices]


public IActionResult Index([FromServices] customerRepository)
{
...
}
IoC
È anche possibile accedere ai servizi con [Link]
È comunque suggerito fare uso di DI quando possibile
Possiamo specificare un nostro IoC container così:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
...
// Autofac
var containerBuilder = new ContainerBuilder();
[Link]<DefaultModule>();
[Link](services);
var container = [Link]();
return new AutofacServiceProvider(container);
}

In questo caso usiamo Autofac e la DI va configurata in DefaultModule


Demo
Environment
Di default [Link] ha 3 ambienti preconfigurati (nome case insensitive)
• Development
• Staging
• Production

Il valore attuale viene letto dalla variabile ASPNETCORE_ENVIRONMENT


• Definibile nel [Link], nella config, su env variable, Azure, etc

Le informazioni per lo sviluppo sono persistite in un file chiamato


[Link] dentro la directory Properties
IHostingEnvironment in Razor
Basta utilizzare il tag environment per fare output di pezzi di markup
differenti, ad esempio per gestire i CSS diversi tra ambienti

<environment names="Development">
...
</environment>
<environment names="Staging,Production">
...
</environment>
Convenzioni per startup
Se esiste una classe con nome Startup{EnvironmentName}, viene utilizzata
quella al posto di Startup
• Es: StartupDevelopment

Stesso discoro per il metodo Configure che vedremo a breve


Torniamo su [Link]
È l’entry point della configurazione
Rappresenta tutto quello che deve essere necessario al runtime per
funzionare
Carica servizi, middleware
Configura l’IoC
Gestisce gli environment
Il metodo Configure
Gestisce come [Link] risponderà alle richieste
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
[Link]([Link]("Logging"));
[Link]();

if ([Link]())
{
[Link]();
[Link]();
[Link]();
}
else
{
[Link]("/Home/Error");
}

[Link]();

[Link]();

[Link](routes =>
{
[Link](
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
Il metodo ConfigureServices
Per configurare [Link]
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
[Link]<ApplicationDbContext>(options =>
[Link]([Link]("DefaultConnection")));

[Link]<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();

[Link]();

// Add application services.


[Link]<IEmailSender, AuthMessageSender>();
[Link]<ISmsSender, AuthMessageSender>();
}
In dettaglio
Use
• Consente di aggiungere funzionalità esterne attraverso il Middleware

ConfigureServices
• Consente di gestire i servizi utilizzati dall’applicazione
• Sfrutta il meccanismo di Dependency Injection di [Link]
Demo
Logging
Integrato all’interno del runtime
Legato all’interfaccia ILoggerFactory o ILogger<T>
var logger = [Link]("LogCategory");
[Link]("No items found");

// con ILogger<T> non serve creare il logger esplicitamente


// logger = ILogger<Todo> che arriva da DI
[Link]("No items found");

Di default viene registrato un logger che scrive su Console/Output Windows


di VS
Si possono agganciare provider esterni
Verbosità di logging
Trace
• Livello più dettagliato, in genere riservato allo sviluppatore
Debug
• Informazioni utili solo al debug
Information
• Informazioni utili per tracciare il flusso applicativo
Warning
• Informazioni utili a tracciare stati non previsti
Error
• Da utilizzare per tracciare errori
Critical
• Da utilizzare per tracciare errori gravi o crash
Logging v2
ILoggingFactory e co sono integrati di default all’interno di [Link],
anziché [Link]
Il motore di DI registra già tutti i servizi di logging
Provider e filtri aggiuntivi vanno specificati in [Link]
Vedi [Link]

Già inclusa la possibilità di fare logging su


Console
Debug
EventLog
AzureAppServices
TraceSource (solo .NET Framework)
EventSource
Utilizzare le verbosità
Ci sono degli extension method con nome (es: LogInformation), oppure si può
utilizzare Log([Link]…)
Ogni tipo di verbosità consente di passare informazioni aggiuntive, come ad
esempio
• Messaggio dettagliato di testo
• EventID
• Exception

Possiamo gestire il livello di verbosità in [Link]/Configure


[Link]([Link]("Logging"));
[Link]([Link]);
Il livello corrente viene letto da [Link]
Demo
Gestione degli errori
La gestione degli errori avviene in [Link]/Configure
Grazie agli Environment, differenziamo il comportamento in base
all’ambiente
Negli altri casi, viene utilizzato il Controller specificato, con una view che
mostra l’errore

Di default non viene differenziato in base al codice HTTP di errore, ma


possiamo utilizzare questo codice per farlo:
[Link]("~/errors/{0}");
Demo
[Link] Core = [Link] MVC
[Link] Core include MVC e WebAPI in un solo motore
Di fatto, [Link] Core, al netto del runtime, è [Link] Core MVC

MVC = Model View Controller


• Pattern per disegnare la UI

Rispetto ad [Link] MVC, [Link] Core MVC ha diverse novità


Come funziona MVC
[Link] Web
Browser Server
[Link]

[Link]
(View)
ProductsController
(Controller)
[Link]
(View)
Product
(Model) SQL
[Link] MVC vs WebForms
Sono modelli paralleli
• WebForm per facilità
• MVC per controllo totale

MVC è per la testabilità


• TDD (Test Driven Development)
• Certezza che l’interfaccia non produca errori

MVC è il futuro
• [Link] Core 1 = .NET Core + [Link] Core MVC + WebAPI
• [Link] 4.6 = .NET Framework 4.6 + [Link] MVC 5/Core MVC + WebAPI
[Link] MVC
MVC non è il 3 tier
• È specifico dell’interfaccia
3 tier è un concetto architetturale
MVC è un concetto di design del software

Model
• Oggetti di business
View
• Presentazione
Controller
• Logica
Parliamo di pattern
MVC sta per Model View Controller

Ma in realtà [Link] MVC, come JSP/Struts in Java è basato su Model 2


• [Link]
MVC in pillole
Il Model ha il compito di contenere i
dati da visualizzare ed i metodi che ne
permettono l'accesso al nostro engine
di persistenza dati

La View ha il compito di visualizzare i


dati da mostrare nella nostra User
Interface

Il Controller è il vero cuore, si occupa


delle iterazioni con l'utente invocando i
metodi presenti nel Model e
cambiando l'output della nostra
interfaccia tramite la View
Obiettivi di MVC
Separation of Concerns
• Testing
• Red/Green TDD
• Alta manutenibilità (tutto è testabile)

Estendibile e pluggabile con maggior facilità


• Con WebForm spesso il modello di estendibilità porta lavoro aggiuntivo (vedi control
adapter)
MVC in dettaglio
Il browser richiede /Products/
La Route viene gestita
Model Il controller viene attivato
Il metodo del controller è invocato
Il controller fa quello che s’ha da fare
Render della View, passando i ViewData

View Controller
La chiamata di una pagina con MVC
Con [Link] normale viene usata la pagina fisica
• A meno che non si usino HttpHandler

Con [Link] MVC la chiamata viene indirizzata al Controller

L’URL Routing interno rigira la chiamata

Il Controller deve ereditare da una classe base Controller del namespace


[Link].
Demo
La View con MVC
Dopo Controller e Model entra in gioco la View

La View è una pagina con codice HTML e server side con lo stesso nome
dell’action del Controller
• Es [Link], [Link], etc.

Il dato prelevato è nel Model e passato al Controller tramite il metodo View,


per visualizzare le informazioni a video
Demo
Novità di [Link] Core MVC
[Link] Core MVC semplifica il concetto di controller
• Una qualsiasi classe che restituisca in un metodo il tipo IActionResult è una Action

I controller possono essere POCO


• Plain Old CLR Objection, cioè classi che non ereditano per forza da Controller

Un controller ha action che restituiscono risposte diverse


• View
• Servizi REST
• Immagini
• Testo
• etc
Come funziona l’interazione
URL:

/Products/Edit/5
ProductsController
(Controller) /Products/Edit/5 [POST]

Product
(Model) SQL
View
Le action solitamente non ritornano semplici stringhe
Normalmente le action restituiscono un’istanza del tipo ActionResult o un
tipo derivato
Le action sono un componente molto importante dei controller
• Possono restituire una view
• Possono restituire un file
• Possono fare il redirect
La view per convenzione deve stare in
• Views/<ControllerName>/<ViewName>.cshtml
• Views/Shared/<ViewName>.cshtml

Possiamo comunque indicare la view che vogliamo


I controlli?
Andati. Non ci sono, non sarebbe “giusto” per il modello

La classe HtmlHelper ci aiuta


• @[Link](…)

Partial View con [Link]


• Ci ricordano gli User Control

[Link] Core introduce i tag Helper


Passare dati dal controller alla View
Il Controller può passare dati in modo semplicissimo alla View
Nella Action, è sufficiente istanziare la classe ViewResult, passando al
costruttore i dati del modello
public ActionResult BookView()
{
return View(new BookViewModel
{
Title = "[Link] Core Guida completa",
Author = "Daniele Bochicchio",
Category = "[Link]",
Price = 19.99,
ReleaseDate = [Link](-40)
});
}
Definizione del Model
Il model è una classe che incapsula i dati ad uso e consumo della View
Non ci sono convenzioni sui nomi

public class BookViewModel


{
public string Title { get; set; }
public string Category { get; set; }
public string Author { get; set; }
public double Price { get; set; }
public bool OnSale { get; set; }
public DateTime ReleaseDate { get; set; }
}
Recupero del modello nella View
La view può recuperare il modello
@model BookViewModel

<h1>@[Link]</h1>
<p>Prezzo: @[Link]()</p>

Se non viene specificato il modello, la View è dinamica e funzionerà


comunque (perdiamo l’IntelliSense in Visual Studio)
Passaggio di parametri
Possiamo utilizzare ViewData e ViewBag
ViewData["Message"] = "messaggio";
[Link] = "messaggio";

ViewBag prevede un accesso dinamico al contento del ViewData, quindi


non richiede casting

Sostanzialmente sono la stessa cosa


Demo
View e Razor
Razor è il View engine di default per [Link]
La sua sintassi è basata su C#

@
La "chiocciolina" magica
Istruzione su singola riga

@{ var theMonth = [Link]; }


<p>Valore numerico del mese corrente: @theMonth</p>
Istruzione multi riga
@{
var outsideTemp = 35;
var weatherMessage = "Ciao, ci sono " + outsideTemp + " gradi.";
}

<p>Previsioni di oggi: @weatherMessage</p>

Ogni riga di codice, termina come in C# con il ;


È possibile dichiarare le variabili, utilizzando var
Uso di \ in una stringa
@{ var myFilePath = @"C:\MyFolder\"; }

<p>Path: @myFilePath</p>

Le stringhe devono essere racchiuse tra virgolette

In caso la stringa rappresenti un percorso dobbiamo utilizzare l’operatore @,


esattamente come in C#
Virgolette nelle stringhe
@{ var myQuote = @"Il mio libro preferito è: ""[Link] Core"""; }

<p>@myQuote</p>

Se le stringhe contengono le virgolette è sufficiente raddoppiarle


Sintassi e tip
@if (IsPost) {
<p>Ciao, oggi è @[Link] e questo è un post!</p>
}
else {
<p>Ciao <em>straniero</em>, oggi è: <br /> </p> @[Link]
}

Razor permette di innestare codice client con codice server


Sintassi e tip
@if (IsPost) {
@: Oggi è: <br /> @[Link]
<br />
@[Link] @:is the <em>current</em> time.
}

È possibile inserire testo semplice in linea utilizzando @

È possibile anche inserire più righe, semplicemente precedendo ogni riga


con @
Sintassi e tip
@* Commento singolo. *@

@* Commento multi riga.


Generalmente continuerà su altre righe ancora. *@

@{
@* Questo è un commento in linea. *@
var theVar = 17;
}

È possibile aggiungere commenti sia nell’HTML che nel codice

In alternativa in un blocco di codice è possibile utilizzare la sintassi di C#


Da VS -> CTRL+K, CTRL+C – CTRL+K, CTRL+U
Operatori e loop

If/else/else if switch

for foreach

while

Necessitano sempre di un blocco di { } in cui racchiudere il codice


Partial View
View parziale (può essere tipizzata) e condivisa

Le view parziali devono essere salvante dentro la dir Shared o in quella


delle View
• Sarà una partial view globale o solo di un gruppo di view

Consente di evitare la duplicazione di codice

Per convenzione si preferisce utilizzare il carattere underscore come


prefisso di tutte le partial view

@[Link]("_Partial", Model)
PartialView async
[Link] Core introduce il supporto per le partial async
Utile per migliorare la scalabilità, qualora ci sia codice async nella view

@await [Link]("_List")
Sfruttare le layout view nel progetto
Consente di centralizzare un layout comune a tutte le view

Viene chiamata (per convenzione) è _Layout.cshtml

Non è una view tipizzata, perché sarà utilizzata in un gran numero di


situazioni e vogliamo lasciare alle singole action la flessibilità di utilizzare il
model più consono alla view che dovrà essere mostrata
Sfruttare le layout view nel progetto

<!DOCTYPE html>
<html>
<head>... </head>
<body> Nella pagina di layout @RenderBody
<div id="body"> determina dove il contenuto deve
@RenderBody() essere renderizzato
</div>
</body>
</html>
Sfruttare le layout view nel progetto
Nella pagina inseriamo il contenuto e specifichiamo la pagina di layout
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}

@model [Link]
@{ [Link] = [Link]; }

<h2>Libro</h2>
<p>
@[Link]
</p>
<p>
@[Link]
</p>
<p>
@[Link]
</p>
Sfruttare le layout view nel progetto
Impostare ogni volta la pagina di layout può essere tedioso e ripetitivo

Limita la manutenzione

All’interno di Views\_ViewStart.cshtml imposta globalmente la Layout View


per tutte le pagine

Basta sovrascriverla localmente nella View per non utilizzarla


Environment
Possiamo diversificare il markup in base all’ambiente

<environment names="Development">
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/[Link]" />
<link rel="stylesheet" href="~/css/[Link]" />
</environment>
<environment names="Staging,Production">
<link rel="stylesheet"
href="[Link]
asp-fallback-href="~/lib/bootstrap/dist/css/[Link]"
asp-fallback-test-class="sr-only"
asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
<link rel="stylesheet" href="~/css/[Link]" asp-append-version="true" />
</environment>
Importazione globale per View
Possiamo registrare funzionalità a livello globale nel file
Shared\_ViewImports.cshtml

@using WebApplication1
@using [Link]
@using [Link]
@using [Link]
@addTagHelper *, [Link]
Il file _ViewStart
Possiamo esegurie codice per ogni View aggiungendolo all’interno del
Shared\_ViewStart.cshtml
Generalmente viene sfruttato per registrare globalmente una layout page
Definire sezioni aggiuntive in una
layout view
Possiamo definire nuove sezioni
• anche opzionali

_Layout.cshtml _view.cshtml

<footer> @section Footer {


@RenderSection("Footer") <p>Footer della content view</p>
@RenderSection("OptionalSection", false) }
</footer>
Verifica dell’esistenza di una sezione

<div id="footer">
@if (IsSectionDefined("Footer"))
{
@RenderSection("Footer")
}
È possibile verificare
else l’esistenza della sezione e,
{
<p>Contenuto di default definito su layout view</p>
in alternativa, mostrare del
} contenuto standard
@RenderSection("OptionalSection", required: false)
</div>
Demo
Progetti complessi: le Aree
In [Link] MVC la struttura di directory del progetto non rispecchia, a
differenza di quanto accade in WebForm, l'effettivo path delle pagine, che
invece è determinato esclusivamente dalle regole di routing.

Al contrario, esse hanno esclusivamente la funzione di contenitori, secondo


una struttura ben definita che stabilisce dove posizionare i vari file di model,
controller e view.

SCENARIO: Pensiamo per esempio al caso di un CMS, in cui magari abbiamo sia una parte pubblica,
visibile a tutti, che una sezione di backoffice amministrativo, magari con differenti layout, pattern di
routing e regole di accesso
Aggiungere un’area
Creare una directory Areas sotto la root
• All’interno aggiungere le directory Controllers, Views

In particolare, [Link] Core andrà a cercare le view così:


• /Areas/<Area>/Views/<Controller>/<Action>.cshtml
• /Areas/<Area>/Views/Shared/<Action>.cshtml
• /Views/Shared/<Action>.cshtml
Registrare un’area
Possiamo customizzare la registrazione in questo modo

[Link]<RazorViewEngineOptions>(options =>
{
[Link]();
[Link]("/Backoffice/{2}/Views/{1}/{0}.cshtml");
[Link]("/Backoffice/{2}/Views/Shared/{0}.cshtml");
[Link]("/Views/Shared/{0}.cshtml");
});
Indicare l’area
A differenza di [Link] MVC, in [Link] Core l’area viene indicata
dall’attributo Area

[Area("Backoffice")]
public class HomeController : Controller
{

}
Pubblicazione delle aree
Di deafult le aree non vengono pubblicate
Occorre modificare il file [Link], aggiunendo il riferimento

"publishOptions": {
"include": [
"Areas/**/*.cshtml",
....
....
]
Demo
Injection dei servizi
Possiamo fare injection in maniera semplice, registrando l’injection e poi
facendo riferimento nel controller

public void ConfigureServices(IServiceCollection services)


{
[Link]<IMyService, MyService>();
}

public IActionResult About([FromServices] IMyService service)


{
ViewData["Message"] = [Link]();
return View();
}
Injection dei servizi
In alternativa è sempre possibile iniettare la dipendenza dal costruttore del
controller

[Link] Core supporta questi lifetime


• Transient
• Scoped
• Singleton
Injection dei servizi nelle view
Si può iniettare un servizio anche nelle View, usando @inject

@inject IMyService myService

@[Link]()
Demo
View Components
Novità di [Link] MVC: sembrano partial view, ma sono più potenti

Non usano il model binding, ma usa il modello passato

Sono indicati quando oltre alla logica di rendering, c’è anche logica
applicativa

Concettualmente sono molto simili ai Custom Control


Creare un View Component
Bisogna creare una classe che eredita da ViewComponent e finisce con il
suffisso ViewComponent

Decorare la classe con [ViewComponent]

Come i controller, un View Component deve essere pubblico, non astratto e


il suo nome è quello indicato al netto del suffisso obbligatorio

Definisce la logica nel suo metodo InvoceAsync


Creare un View Component
Le View saranno cercate in
• Views/<controller>/Components/<viewcomponent>/<name>.cshtml
• Views/Shared/Components/<viewcomponent>/<name>.cshtml
Il nome di default è Default.

Possiamo ritornare direttamente un ViewComponent da una Action, al posto


di una View

Oppure invocarlo da codice


@await [Link]("Menu", new { ShowAll = true })
Demo
Tag Helper: che cosa sono
I tag helper permettono a codice server-side di generare codice HTML
Possono essere invocati in base al nome dell’elemento o dell’attributo
I tag helper sono come gli html helper, ma riducono l’utilizzo di sintassi C#
all’interno della pagina
Codice più leggibile e mantenibile
Supporto all’IntelliSense di Visual Studio

<label asp-for="Email"></label>
<label for="Email">Email</label>
Aggiungere un Tag Helper
Si possono aggiungere i tag helper sfruttando la direttiva @addTagHelper,
di solito all’interno del file _ViewImports

Allo stesso modo è possibile rimuovere uno specifico tag helper all’interno di
una pagina specificando la direttiva @removeTagHandler

@addTagHelper "*, TagHelperNamespace"


@removeTagHelper "MyTagHelper, TagHelperNamespace"
Disabilitare un tag helper
E possibile specificare l’utilizzo dei tag helper su tutti i controlli tranne che su
un attributo specifico
E’ sufficiente aggiungere all’apertura del tag HTML il carattere «!»

<!span asp-validation-for="Email"
class="text-danger"></!span>
Gestire le form
Eliminare l’utilizzo degli HTML helper semplifica il codice generato,
soprattutto all’interno delle form di inserimento dati
Grazie agli helper per controller ed action, si può semplificare la navigazione
durante il metodo POST

<form asp-controller="Demo"
asp-action="Register"
asp-route="CustomRoute"
method="post">
<!-- Input and Submit elements -->
</form>
Gestire le form
Se lato controller nella action in HTTP POST è impostato l’attributo
[ValidateAntiForgeryToken], allora verrà aggiunto in automatico nella form
un campo hidden con il Request Validation Token per prevenire attacchi
cross-site

<input name="__RequestVerificationToken"
type="hidden"
value="XXX" />
Attributo di input
Imposta l’attributo type in base alla proprietà nel modello e alla
DataAnnotation associata (tranne se è esplicitamente impostato)
Genera la validazione secondo gli standard HTML5 in base al modello con
gli attributi data-val-*
E’ l’equivalente di [Link]/TextBoxFor

<input asp-for="<Expression Name>" />


La validazione: validation message
Il tag helper di input aggiunge gli attributi di validazione client-side in base
alle DataAnnotation trovate sul modello. La validazione avviene anche lato
server nel caso che il javascript sia disattivato nel browser
E’ il corrispondente di [Link]

<span asp-validation-for="Email"></span>

<span class="field-validation-valid"
data-valmsg-for="Email"
data-valmsg-replace="true"></span>
La validazione: validation summary
Viene utilizzato per mostrare un report dei messaggi di validazione
E’ il corrispondente di [Link]

<div asp-validation-
summary="[Link]"></div>
Tag helper: select
Genera un tag <select> con le opzioni specificate all’interno della proprietà
Items
E’ l’alternativa di [Link]

<select asp-for="Country"
asp-items="[Link]"></select>
Tag Helper custom
Un TagHelper è una classe che implementa dall’interfaccia ITagHelper, ma
per comodità si eredita direttamente da TagHelper per avere accesso al
metodo Process

Per convenzione è meglio utilizzare il nome del tag seguito da TagHelper,


ma non è obbligatorio.

public class EmailTagHelper : TagHelper


{
public override void Process(TagHelperContext context, TagHelperOutput output)
{
[Link] = "a"; // Sostituisce il tag <email> con <a>
}
}
Tag Helper custom
Context contiene le informazioni associate all’esecuzione del tag
corrispondente

Output contiene invece le informazioni relative all’elemento HTML


corrispondente al tag sorgente

public class EmailTagHelper : TagHelper


{
public override void Process(TagHelperContext context, TagHelperOutput output)
{
[Link] = "a"; // Sostituisce il tag <email> con <a>
}
}
Tag Helper custom
Per rendere il tag helper custom raggiungibile ed utilizzabile, è necessario
registrarlo con la direttiva @addTagHelper (come wildcard, oppure tramite
nome esplicito)

@addTagHelper "*, TagHelperCustomNamespace"


Tag Helper custom
E’ possibile aggiungere attributi personalizzati all’elemento HTML
renderizzato
public class EmailTagHelper : TagHelper
{
public string MailTo { get; set; }

public override void Process(TagHelperContext context, TagHelperOutput output)


{
[Link] = "a"; // Replaces <email> with <a> tag

var address = MailTo + "@" + EmailDomain;


[Link]("href", "[Link] + address);
[Link](address);
}
}
Tag Helper custom
Se le proprietà vengono create con sintassi Pascal-case, allora gli attributi
vengono analizzati con sintassi lower-kebab case

<email mail-to="" />

E’ anche possibile accettare proprietà complesse, in questo caso si deve


passare l’intero oggetto così come verrà interpretato da C#
Tag Helper custom
E’ possibile decorare i tag helper custom con degli attributi per ridefinire il
comportamento

[HtmlTargetElement(TagStructure = [Link])]

L’ordine di valutazione di questi attributi può alterare il risultato.


Due proprietà separate da virgola all’interno dello stesso attributo vengono
valutate come AND, se fanno parte di attributi differenti sono valutate come
OR.
Gestione degli ambienti
[Link] Core utilizza una particolare variabile d’ambiente che serve a
descrivere l’ambiente in uso.

ASPNETCORE_ENVIRONMENT
Development, Staging, Production, Custom
Gestione degli ambienti
L’accesso via HTML agli ambienti è consentito attraverso l’uso del tag
helper di environment

<environment names="Development">
<link rel="stylesheet" href="~/dev/[Link]" />
<link rel="stylesheet" href="~/dev/[Link]" />
</environment>
<environment names="Staging,Production">
<link rel="stylesheet" href="~/prod/[Link]" />
<link rel="stylesheet" href="~/prod/[Link]" />
</environment>
Razor Pages
Semplificazione del modello di View
• La pagina ha sia logica che codice
Il contenuto è all’interno della directory Pages
Comode per scenari semplificati
Demo
Gli URL con MVC
Classe ProductsController

I metodi diventano Action


• Metodo Categories()
• [Link]
• Metodo List(string category)
• [Link]
• Metogo Details(int id)
• [Link]
Da [Link] MVC…
La magia avviene nella classe RouteConfig, richiamata allo startup dal
[Link]

Viene sfruttato il ModelBinding per associare i parametri della route

public static void RegisterRoutes(RouteCollection routes)


{
[Link]("{resource}.axd/{*pathInfo}");

[Link](
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = [Link] });
}
…ad [Link] Core
La magia avviene nella classe Startup all’interno del metodo Configure
Il metodo UseMvc crea una nuova istanza di RouteMiddleware e la
aggiunge alla pipeline di esecuzione

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)


{
[Link](routes =>
{
[Link](name: "default",
template: "{controller}/{action}/{id?}",
defaults: new { controller = "Home", action = "Index" });
});

// equivalente
[Link]();
}
Personalizzazione
È possibile personalizzare il comportamento di routing semplicemente
aggiungendo constraint sulle proprietà o eventuali token per gestire, ad
esempio, la localizzazione

[Link](
name: "us_english_products",
template: "en-US/Products/{id}",
defaults: new { area = "Backoffice", controller = "Products",
action = "Details" },
constraints: new { id = new IntRouteConstraint() },
dataTokens: new { locale = "en-US" });
Constraint per route
I parametri inclusi tra parentesi graffe devono fare match altrimenti la route
viene ignorata
Il carattere «?» rappresenta un valore opzionale
Il carattere «.» per le estensioni dei file è comunque un valore opzionale
Le constraint sono classi che implementano IRouteConstraint e possono
forzare il tipo di un parametro
namespace [Link]
{
public class IntRouteConstraint : IRouteConstraint
{id:int} {
{active:bool} public IntRouteConstraint();
}
{name:lenght(5,20)} }
Attribute routing
Il routing può essere definito anche come attributo nella decorazione del
metodo corrispondente

In questo caso non viene calcolato il nome del controller perché verrà
mappato sempre su Home

[Route("")]
[Route("Home")]
[Route("Home/Index")]
public IActionResult MyIndex()
{
return View("Index");
}
Gestione dei conflitti
Può succedere che ci siano due o più metodi corrispondenti alla stessa
route: in questo caso viene generato un conflitto

In caso di conflitti, se MVC non è in grado di trovare una «best» route, verrà
generata una AmbiguousActionException

Per evitarli, è bene:


• Specificare dettagliatamente il routing tramite attribute routing
• Impostare HTTP Verb specifici come decorazione dei metodi
• Considerare una route di fallback e di default per gestire un eventuale redirect
Ottenere l’url
E’ possibile recuperare l’url da una action attraverso la classe Url che
analizzerà la route corrispondente
Viene utilizzato anche con i tag helper per la gestione delle form

public IActionResult Source()


{
// Genera /custom/url/to/destination
var url = [Link](nameof(Destination));
return Content($"Url generato: {url}");
}

[HttpGet("custom/url/to/destination")]
public IActionResult Destination()
{
return View();
}
Demo
Entity Framework
• ORM di Microsoft basato sul .NET Framework
• Insieme di tecnologie [Link] per lo sviluppo software
• Definisce un modello di astrazione dei dati
• Traduce il nostro codice in query comprensibili dal DBMS
• Disaccoppiamento tra applicazione e dati
• Posso mantenere la stessa rappresentazione anche se cambia il modello fisico (es.
da SQL Server ad Oracle)
• Open source
• [Link]
Cos’è un ORM?
• È una tecnica per convertire dati da type system incompatibili
• Da database ad object-oriented

• 3 caratteristiche fondamentali
• Mapping
• Definisce come il database si «incastra» negli oggetti e viceversa
• Fetching
• Sa come recuperare i dati dal database e materializzare i rispettivi oggetti
• Persistenza del grafo
• Sa come salvare le modifiche agli oggetti, generando le query SQL corrispondenti
Entity Framework: cos’è?
Entity Client Data Provider
• Livello di astrazione, che rende utilizzabile EF con più sorgenti dati

Entity Data Model


• Rappresenta il modello di mapping tra database ed oggetti

LINQ to Entities
• Flavour di LINQ che consente di utilizzare tutti gli operatori in unione con le entity di EF

Entity SQL
• Linguaggio speciale per interrogare EF con un linguaggio indipendente dal database
utilizzato, consentendo di creare facilmente query dinamiche
Come funziona
Diversi approcci
Database-First
• Il modello viene importato da un DB esistente
• Se modifico il database posso (quasi) sempre aggiornare il modello
Model-First
• Il modello del database viene creato dal designer di Visual Studio
• L’implementazione fisica è basata sul modello generato
• Non favorisce il riutilizzo del codice né la separazione tra contesto ed entità
• Poichè il modello definisce il DB, eventuali sue modifiche verranno perse
Code-First
• Il modello viene creato dal nostro codice
• L’implementazione fisica è basata sul nostro codice
Perché Code-First?
L’EDMX può essere complicato

Non siamo DBA


• Non ci dobbiamo occupare di mapping
• Non dobbiamo fare ottimizzazioni sul database

Siamo dev
• Focus sul domain design
• C# ci è più familiare delle query di SQL

Gli altri approcci non sono supportati da EF Core


Stato di Entity Framework

Runtime su NuGet
Tooling su Microsoft Download Center
Ultima versione inclusa in Visual Studio

Nuovi componenti su NuGet


Componenti Core runtime dentro .NET
Tooling in Visual Studio

Runtime nel .NET Framework


Tooling in Visual Studio
Il DbContext
Il DbSet
• E’ una classe che rappresenta le entity
• Serve per fare operazioni CRUD
• E’ definito come DbSet<TEntity>
• I metodi più utilizzati sono:
• Add, Remove, Find, SqlQuery
• Vengono mappate tutte le sue proprietà che hanno getter e setter
impostati
Il DbContext
public class Context : DbContext
{
public DbSet<Student> Students { get; set; }
public Context() : base("name=MyDBConnnectionString")
{
}
}

<?xml version="1.0" encoding="utf-8"?>


<configuration>
<connectionStrings>
<add name="MyDBConnectionString" connectionString="data source=\SQLEXPRESS;in
itial catalog=dbName;integrated security=True;MultipleActiveResultSets=True;App=En
tityFramework" providerName="[Link]" />
</connectionStrings>
</configuration>
Primary Key
public class Student public class Student
{ {
public int StudentID { get; set; } public int MyPrimaryKey { get; set; }

public string StudentName { get; set; } public string StudentName { get; set; }
public DateTime DateOfBirth { get; set; } public DateTime DateOfBirth { get; set; }
public Teacher Teacher { get; set; } public Teacher Teacher { get; set; }
} }

Convenzione sul nome della chiave Non usa la convenzione di code-first


primaria: Genera una ModelValidation
• Id Exception se non gestita con le
• <NomeClasse>ID DataAnnotations
Foreign Key
public class Student public class Course
{ {
public int StudentID { get; set; } public int CourseId { get; set; }

public string StudentName { get; set; } public string CourseName { get; set; }
public DateTime DateOfBirth { get; set; } public Teacher Teacher { get; set; }
public IList<Student> Students { get; set; }
public int CourseId { get; set; } }
public Course Course { get; set; }
}

La ForeignKey viene generata automaticamente da code-first ogni volta che


viene individuata una navigation property
Sempre bene rispettare le stesse convenzioni della PrimaryKey
DataAnnotations e Fluent API
Le DataAnnotations sono attributi che servono a specificare il
comportamento per fare l’override delle convenzioni di code-first
Possono influenzare le singole proprietà
• Namespace [Link]
• Key, Required, MaxLenght…
Possono influenzare lo schema del database
• Namespace [Link]
• Table, Column, NotMapped…
Le DataAnnotations sono limitate. Per il set completo bisogna andare di
Fluent API
DataAnnotations: Key
Override della convenzione sulla PrimaryKey
Viene applicato alle proprietà di una classe

[Key]
public int MyPrimaryKey { get; set; }
Model e Entity Mapping
Configurazione dello schema per tutto il database
Configurazione dello schema per singola tabella

protected override void OnModelCreating(DbModelBuilder modelBuilder)


{
[Link]("Admin");

//Map entity to table


[Link]<Student>().ToTable("StudentInfo");
[Link]<Student>().ToTable("StandardInfo", "anotherSchema");
}
Property Mapping
Configurazione della chiave primaria
[Link]<Student>().HasKey<int>(s => [Link]);

Configurazione di altre proprietà


[Link]<Student>().Property(p => [Link])
.HasColumnName("Eta")
.HasColumnOrder(3)
.HasColumnType("datetime2")
.IsRequired();
Metodo Seed
E’ integrato con il processo di inizializzazione del database
Serve per fornire dei dati di testing in fase di sviluppo

public class MyInitializer : CreateDatabaseIfNotExists<Context>


{
protected override void Seed(Context context)
{
var fakeStudents = new List<Student>();
[Link](new Student() { Name = "Studente 1" });
[Link](new Student() { Name = "Studente 2" });
[Link](new Student() { Name = "Studente 3" });

[Link](fakeStudents);
[Link]();
[Link](context);
}
}
Ereditarietà
Table per Hierarchy (TPH)
• Una classe per tutta la struttura di ereditarietà
• La tabella generata contiene un discriminante per distinguere gli elementi
• Strategia di default di Entity Framework
Table per Type (TPT)
• Una tabella per ogni classe della ereditarietà
Table per Class (TPC)
• Una tabella per ogni classe dell’ereditarietà ad esclusione del tipo astratto
• Le proprietà della classe astratta andranno dentro quelle concrete
Struttura di partenza
Table per hierarchy 1/2
Implementazione del modello
public abstract class BillingDetail public class CreditCard : BillingDetail
{ {
public int BillingDetailId { get; set; } public int CardType { get; set; }
public string Owner { get; set; } public string ExpiryMonth { get; set; }
public string Number { get; set; } public string ExpiryYear { get; set; }
} }

public class BankAccount : BillingDetail


{
public string BankName { get; set; }
public string Swift { get; set; }
}

public class Context : DbContext


{
public DbSet<BillingDetail> BillingDetails { get; set; }
}
Table per hierarchy 2/2
Implementazione fisica

I dati si recuperano con una query normalissima


[Link]<CreditCard>().ToList();
Demo
Entity Framework
Configurazione per [Link] Core
EF6.x non è compilato per .NET Core
Possiamo fare il deployment solo su Windows e non abbiamo tutti i vantaggi offerti
da EF Core
Ci obbliga a rimanere su Windows e non abbiamo tutti i vantaggi offerti da EFCore
EF Core è una versione riscritta di EF per .NET Core
• Supporto a nuove piattaforme e database
• Batching durante SaveChanges
• Client eval per query LINQ
• Shadow state property
• SQL Server sequences
• Alternate keys
Nuove funzionalità
Supporto a nuove piattaforme
Supporto a nuovi database

Batching durante SaveChanges


Client eval per query LINQ
Shadow state property
SQL Server sequences
Alternate keys
.NET FRAMEWORK .NET CORE XAMARIN

WPF Windows Forms UWP iOS


MODELS
APP

Android
[Link] [Link] Core OS X
LIBRARIES
BASE

Base Class Library Core Library Mono Class Library

COMMON INFRASTRUCTURE

Compilers Languages Runtime components

EF6.x EF Core
Nuove tipologie di database
Relazionali e non-relazionali

Alcuni provider

Solo relazionali per la v1.0.0


Core leggero ed estendibile
Stesse core API che già usiamo…

Costruito sopra una serie di servizi

Ottimizzato per memory e CPU usage

Componenti pay-per-play
EF Core
EF6 non era così male…

…ma c’è bisogno di cambiare


EF Core & EF6.x
EF6.x è stabile…

EF Core è una v2…


EF Core & EF6.x
EF6.x può essere (ancora) la scelta giusta

Valutare i requisiti per EF Core

Da EF6.x a EF Core? “Port” != “upgrade”


Configurazione di EF Core
Eliminata la connection string all’interno del costruttore!
Generalmente si iniettano direttamente i settings

public class BloggingContext : DbContext


{
public DbSet<Blog> Blogs { get; set; }

// Setup the database to connect to


protected override void OnConfiguring(DbContextOptionsBuilder options)
{
[Link](optionsBuilder);
[Link](@"myConnectionString");
}
}
Mapping
Riscritta completamente la parte relativa ai provider
Lunga vita alla Dependency Injection!

var serviceProvider = [Link]<IServiceProvider>();


var typeMapper = [Link]<IRelationalTypeMapper>();
Migration
Sono ancora validi i «vecchi» comandi di EF6.x

Per le PCL con .NET Core sono stati aggiunti nuovi comandi:
dotnet ef migrations add {MigrationName}
dotnet ef migrations remove
dotnet ef database update

Lato applicativo si può controllare la migrazione con Migrate


[Link]();
Dall’EDMX al futuro
L’EDMX non è supportato da EFCore, è richiesto un nuovo modello

Sono necessari questi pacchetti di NuGet:


[Link]
[Link].{Provider}.Design

Si genera il nuovo modello tramite scaffolding:


Scaffold-DbContext "<connection string>" <database provider name>
Demo
Entity Framework Core
EF Core 1.1
Rilasciato con .NET Core 1.1

Novità:
• Linq Translator migliorato
• [Link]
• Supporto a tabelle memory-optimized in SQL Server
• Explicit Loading
• ChangeTracker API da EF6.x
• Connection resiliency
• Service replacement semplificato
• Oltre 1000 bug fix
Interceptor

public override int SaveChanges(bool acceptAllChangesOnSuccess)


{
[Link]();

foreach (var entry in [Link]().Where(e => [Link] == [Link]))


{
//modify [Link] here
}

[Link] = false;
var result = [Link](acceptAllChangesOnSuccess);
[Link] = true;
return result;
}
Custom conventions
Non c’è più l’interfaccia IStoreModelConvention di EF6

protected override void OnModelCreating(ModelBuilder modelBuilder)


{
foreach (var entityType in [Link]())
foreach (var property in [Link]())
{
var columnName = [Link]().ColumnName;

if ([Link] > 30)


throw new InvalidOperationException($"La colonna {columnName} non può essere più
lunga di 30 caratteri");
}
}
Seeding
Non esiste più il seeding di EF6, bisogna farlo tramite interceptor allo startup

using (var scope = [Link]<IServiceScopeFactory>().CreateScope())


{
var ctx = [Link]<Context>();
[Link]();
[Link]();
}

public static void EnsureSeedData(this Context context)


{
[Link](new Person("Matteo", "Tumiati", 25));
}
EF Core 2
Modello
Supporto ai complex types
Simple type conversions
Spatial data types
Relazioni molti-a-molti con TPT e TPC

Query
Miglioramento di LINQ Translator (GroupBy sul DB), Lazy Loading

Schema
Aggiornamento del modello dal DB

Integrazione con Visual Studio


Wizard per l’importazione dal database
EF Core 2
Provider
Supporto a Redis e a database non relazionali

Operazioni CRUD
Seed dei dati
Simple command interception

Operazioni specifiche sui relazionali


Supporto alle stored procedure (senza FromSql)

.NET Standard 2
Supporto anche per Xamarin
Filters
Consentono di aggiungere comportamenti a controller
ed action

Ad esempio:
• [Authorize]
• [HttpPost]

Globali ([Link])
Locali (su controller o action)
L'infrastruttura dei filtri
Simili agli HttpModule di [Link]
Sono pensati per [Link] Core

Dal punto di vista strettamente pratico, si tratta di classi che implementano una
serie di interfacce, ognuna specifica per una particolare funzionalità.
Tipologie di filtri
Action filter: implementano l'interfaccia IActionFilter e ci consentono di
gestire le fasi immediatamente precedenti e successive all'esecuzione della
action
Result filter: simili ai precedenti, implementano l'interfaccia IResponseFilter
e ci danno la possibilità di iniettare codice nelle fasi immediatamente
precedenti e successive all'esecuzione del result di una action
Exception filter: implementano IExceptionFilter e contengono codice che
gestisce situazioni di errore, permettendo di intercettare un'eccezione non
gestita sul server
Authorization filter: implementano IAuthorizationFilter e ci permettono di
gestire le policy secondo cui consentire l'esecuzione di una determinata
action
Ordine d’esecuzione dei filtri
Controller: OnActionExecuting
Global: OnActionExecuting
Class: OnActionExecuting
Method: OnActionExecuting
Method: OnActionExecuted
Class: OnActionExecuted
Global: OnActionExecuted
Controller: OnActionExecuted
Impostare un filtro
A livello di classe o metodo, mettere Order < 0

[MyFilter(Order=-1)]
public IActionResult Index()
{
return View();
}
Costruire un custom filter
Classe che eredita da FilterAttribute

OnAuthorization
• prima dell'esecuzione della action per verificare l’accesso
OnActionExecuting
• subito prima dell'esecuzione del codice della action
OnActionExecuted
• appena dopo l'esecuzione della action
OnResultExecuting
• subito prima dell'esecuzione del risultato ritornato dalla action
OnResultExecuted
• appena dopo il termine dell'elaborazione del risultato
OnException
• nel caso in cui il flusso di gestione della richiesta abbia sollevato un'eccezione
Registazione globale dei filtri
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
...
[Link](option =>
{
// istanza per ogni richiesta
[Link](new MyFilterAttribute());
// ogni richiesta crea una nuova istanza
[Link](typeof(MyFilterAttribute ()));
});
}
}
Registazione locale dei filtri
// verrà utilizzata la DI
// dobbiamo ricordarci di registrare MyFilterAttribute
[ServiceFilter(typeof(MyFilterAttribute))]
public IActionResult Index()
{
return View();
}

// non necessita di registrazione via DI


[TypeFilter(typeof(MyFilterAttribute),
Arguments = new object[] { "Param1", "Value" })]
public IActionResult Index()
{
return View();
}
Utilizzo dei filtri su Controller/Action
I filtri possono essere applicati più volte a:
• Controller
• Action

[HandleError(ExceptionType = typeof(DbException), View = "DatabaseError")]


[HandleError(ExceptionType = typeof(AppException), View = "ApplicationError")]
public class ProductController
{
}
Filtri custom

public class MyActionFilter : ActionFilterAttribute


{
}

I filtri estendono una delle classi base a seconda del tipo di filtro da implementare
È possibile controllare l’ordine d’esecuzione dei filtri appartenente al solito tipo
impostando la proprietà Order
Esempi di filtri
Action Filter
• Per gestire il ciclo di vita della action/view
Resource Filter
• Per gestire un output sotto forma di risorsa
Exception Filter
• Per gestire un errore custom (es: risposta in JSON per WebAPI,
anziché pagina di errori in HTML)
Result Filter
• Per gestire direttamente il risultato
Demo
Filtri o Middleware
Sono simil in scope
Filtri = MVC
MiddleWare = [Link] Core
I filtri hanno il vantaggio di stare più vicino ad MVC, quindi
accedo alle sue caratteristiche
• Es: model validation
• Es: ViewData/ViewBag
Middleware evoluzione di HttpModule
HttpModule: prima di [Link] Core

HttpModule: moduli riutilizzabili inseriti nella pipeline e vengono attivati da


eventi definiti all’interno di HttpApplication

Middleware: unione di HttpModule e HttpHandler. Eseguono operazioni


intermedie durante l’elaborazione delle richieste.

Middleware: possono produrre un risultato, in questo caso sono l’ultima


operazione della pipeline
Prima: HttpHandler e HttpModule
• HttpModule implementano l’interfaccia IHttpModule
• Necessitano la registrazione nel file [Link]
• HttpHandler implementano l’interfaccia IHttpHanderler
• HttpHandler: processi che vengono eseguiti in risposta ad una richiesta

<configuration>
<[Link]>
<modules>
<add name="HelloWorldModule" type="HelloWorldModule"/>
</modules>
</[Link]>
</configuration>
Dopo: Middleware
E’ un componente software inserito in una pipeline che consente di gestire
le richieste e le risposte

Ogni componente esegue le operazioni e le invia come richieste al


componente successivo

Ogni componente può eseguire operazioni prima e dopo il prossimo


componente della pipeline
Middleware
Le richieste vengono eseguite una di seguito all’altra

Ogni elemento può interrompere l’esecuzione della pipeline (short-circuiting)

Nel template di default (in sequenza)


• Error handling
• Static file server
• Authentication
• MVC
Middleware
In .NET core le richieste vengono gestite implementando IApplicationBuilder
Metodi Run, Map e Use
La configurazione viene passata al metodo Configure della classe Startup (nel
file [Link])
Possibilità di utilizzare chiamate a metodi anomini
Possibilità di utilizzare chiamate a classi intermedie (Middleware)
Middleware
L’ordine in cui vengono aggiunti i middleware è l’ordine in cui hanno effetto
sulle richieste (e al contrario sulle risposte)

Run: interrompe l’esecuzione della pipeline. Dovrebbe essere inserito al


termine della pipeline

Map: consente di mappare le richieste in base ad un particolare path

es. [Link]("/maptest", HandleMapTest);

Use: consente di aggiungere un delegato alla richiesta


Middleware come Filter
[Link] Core 1.1 introduce la possibilità di registrare un
Middleware direttamente come se fosse un filtro

[MiddlewareFilter(typeof(CompressionPipeline))]
public IEnumerable<Product> Index()
{
return GetAllProducts();
}
Migrare da HttpModule a Middleware
Prima del Middelware: HttpModule
Handler:
Classi che implementano IHttpHandler
Usati per gestire richieste con un nome file o estensione
Configurati nel file [Link]
Migrare da HttpModule a Middleware
Prima del Middelware: HttpModule

Modules
Classi che implementano IHttpModule
Chiamati ad ogni richiesta
Possono interrompere la pipeline
Possono creare una risposta HTTP oppure crearne custom
Configurati nel [Link]
L’ordine di esecuzione è gestito da una serie di eventi BeginRequest,
AuthenticationRequest, ecc
L’ordine di esecuzione è configurabile nel [Link]
Migrare da HttpModule a Middleware
Middleware

HttpModules, HttpHandler, [Link] e [Link] sono obosoleti

Il ruolo degli HttpModules e HttpHanlder è unificato

Le pipeline possono inviare le richieste ad uno specifico Middleware,


non solo in base ad un URL specifico, ma anche in base a headers,
querystring ecc.
Migrare da HttpModule a Middleware
Middleware

Sono simili ai moduli


Invocati ad ogni richiesta
Possono interrompere una richiesta, senza passarla al prossimo
middleware
Possibilità di creare risposte HTTP custom
Migrare da HttpModule a Middleware
Middleware

Middleware e Moduli sono processati in ordine differente


L’ordine del middleware sono gestiti in base all’ordine in cui sono inseriti
nella pipeline

L’ordine delle risposte viene gestito in ordine inverso rispetto alle


richieste: l’ordine per gli HttpModules per richieste e risposte è lo stesso
Migrare da HttpModule a Middleware
Demo migrazione – INTEGRARE
• [Link]
• [Link]
• [Link]
handler-code-to-middleware
Identità e sicurezza
Authorization e differenze rispetto al passato
[Link] Identity
CookieAuthentication
Data Protection
[Link] Identity
Nuovo sistema di gestione dell’identity basato sul concetto di claim
• Un claim è una dichiarazione: es "username" = "Daniele"

Basato su provider
• modello estendibile facilmente con provider, Entity Framework già incluso

Supporta provider multipli per il login


• Cookie, social, Active Directory, Office 365, Federation, etc
[Link] Identity
Ha già tutta la logica necessaria a gestire two-factor authentication, reset dei
PIN via SMS/mail
• Il template di default di VS si occupa di creare un po’ tutto

Si integra alla perfezione con Controller/View


Demo
Cookie Middleware
Se non vogliamo gestire con gli automatismi di [Link] Identity, possiamo
gestire con Cookie Middleware
Saremo responsabili di gestire gli utenti e sfrutteremo un cookie per
assicurarci che il ticket di authentication sia giusto
In [Link], prima di UseMvc:

[Link](new CookieAuthenticationOptions()
{
AuthenticationScheme = "MyCookieMiddlewareInstance",
LoginPath = new PathString("/Account/Unauthorized/"),
AccessDeniedPath = new PathString("/Account/Forbidden/"),
AutomaticAuthenticate = true,
AutomaticChallenge = true
});
Gestire il cookie di autenticazione
È sufficiente, dopo aver controllato il database, fare una chiamata come la
seguente
await [Link]("MyCookieMiddlewareInstance",
principal,
new AuthenticationProperties
{
ExpiresUtc = [Link](20),
IsPersistent = true
});

Per fare logout


await [Link]("MyCookieMiddlewareInstance");
Autenticazione
Con [Link] 1.x l’autenticazione è configurata con Middleware
Con [Link] 2 l’autenticazione è configurata con i Services
• Supporto a Cookie, OpenID Connect, JWT Bearer, Facebook, Twitter,
Google, Microsoft Account

Nuove estensioni ad HttpContext anziché utilizzare


IAuthenticationManager

[Link]
2x/identity-2x
Demo
Data Protection
Le applicazioni web hanno spesso bisogno di salvare dati in modo sicuro
• DPAPI è per applicazioni desktop
• Azure Right Management è pensato per il cloud

[Link] Core ha un intero stack dedicato alla sicurezza out-of-the-box


• Pensato principalmente per rimpiazzare machinekey
• Garantisce un meccanismo di persistenza affidabile
• Performance senza precedenti

E’ pensato per gli sviluppatori


• Configurazione ed API semplici, non richiede conoscenze di algoritmi di cifratura
3 audience differenti
Sviluppatore che deve scrivere l’applicativo web
• L’applicativo deve essere subito pronto e funzionante
• Richiede le Consumer API

Sviluppatore di framework e sistemisti


• Adatto a chi ha alcune configurazioni non-standard
• Richiede le Configuration API

Chiunque abbia custom policy


• Per tutti gli esperti di sicurezza che devono implementare soluzioni totalmente custom
• Richiede le Extensibility API
5 pacchetti di NuGet
[Link]
• Perfetto per le Consumer API

[Link]
• Espone tutto il core del sistema di protezione di [Link], inclusa la gestione delle
chiavi, operazioni di crittografia e configurazioni.

[Link]
• Adatto per chi ha bisogno delle Extensibility API
• Niente dependency injection
• Include la possibilità di gestire la durata di protezione del payload
5 pacchetti di NuGet
[Link]
• Può essere installato nelle applicazioni .NET 4.x per gestire il «vecchio» machinekey
con il nuovo layer di sicurezza

[Link]
• Implementazione dell’algoritmo PBKDF2 per la gestione delle password
Data Protection: Consumer API
Viene creato un IDataProtector per ogni scopo di utilizzo e quindi viene
protetto/rivelato il contenuto

private readonly IDataProtector _protector;

public HomeController(IDataProtectionProvider provider)


{
_protector = [Link]("MyProtector");
ProtectAndUnprotectData("Hello world");
}

private void ProtectAndUnprotectData(string input)


{
string protectedPayload = _protector.Protect(input);
string unprotectedPayload = _protector.Unprotect(protectedPayload);
}
Data Protection: Consumer API
I componenti vanno creati con purpose differenti, altrimenti dall’esterno è
facile replicare il comportamento e risalire al contenuto originale
E’ possibile passare una lista di stringhe come purpose, ma null non è
ammesso
Ambiente multi tenant
Tutti i purpose sono concatenabili, garantendo sicurezza ma facilità di
sviluppo
Limitare la durata del payload
Scenario: token generato per il reset della password, dopo 24 ore non è più
valido

public HomeController(IDataProtectionProvider provider)


{
var protector = [Link]("MyProtector");
_timeLimitedProtector = [Link]();
}

public IActionResult Index()


{
_protectedData = _timeLimitedProtector.Protect("Hello world", [Link](15));
ViewData["Message"] = _protectedData;
return View();
}
Password hashing
Le funzioni di derivazione per fare password hashing sono incluse in un
pacchetto separato che non ha dipendenze con tutto il sistema di data
protection.

private string HashPassword(string password)


{
// genera una chiave di cifratura random a 128-bit
byte[] salt = new byte[128 / 8];
using (var rng = [Link]())
{
[Link](salt);
}

// genera una chiave con l'algoritmo PBKDF2


var keyDerivation = KeyDerivation.Pbkdf2(password, salt, KeyDerivationPrf.HMACSHA1, 10000, 256 / 8);
return Convert.ToBase64String(keyDerivation);
}
Data Protection: Configuration API
E’ possibile applicare configurazioni custom attraverso ConfigureServices
I sistemisti possono impostare dei valori di default attraverso HKLM
• HKLM\SOFTWARE\Microsoft\DotNetPackages\[Link]

public void ConfigureServices(IServiceCollection services)


{
[Link]()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\directory\")) // Percorso dove salvare le chiavi
.ProtectKeysWithDpapi() // Cifratura automatica con DPAPI
.SetDefaultKeyLifetime([Link](10)) // La durata di default delle chiavi è 90 giorni
.SetApplicationName("MyApplicationName") // Consente di condividere il payload protetto tra due app
.UseCryptographicAlgorithms(new AuthenticatedEncryptionSettings() // Configurazione di nuovi algoritmi
{
EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC,
ValidationAlgorithm = ValidationAlgorithm.HMACSHA256
});
}
Dove vengono mantenute le chiavi
Microsoft Azure
• Nella cartella virtuale "%HOME%\[Link]\DataProtection-Keys"
• Questa cartella è sincronizzata con tutte le macchine che hostano l’app

Se è presente un profilo utente


• Nella cartella "%LOCALAPPDATA%\[Link]\DataProtection-Keys"
• Se il sistema operativo è Windows, verrà usato DPAPI di default

Se l’applicativo gira in IIS


• Dentro HKLM in un registro protetto da ACL
Chiave di esempio
<?xml version="1.0" encoding="utf-8"?>
<key id="80732141-ec8f-4b80-af9c-c4d2d1ff8901" version="1">
<creationDate>2015-03-19T23:32:02.3949887Z</creationDate>
<activationDate>2015-03-19T23:32:02.3839429Z</activationDate>
<expirationDate>2015-06-17T23:32:02.3839429Z</expirationDate>
<descriptor deserializerType="{deserializerType}">
<descriptor>
<encryption algorithm="AES_256_CBC" />
<validation algorithm="HMACSHA256" />
<enc:encryptedSecret decryptorType="{decryptorType}" xmlns:enc="...">
<encryptedKey>
<!-- This key is encrypted with Windows DPAPI. -->
<value>AQAAANCM...8/zeP8lcwAg==</value>
</encryptedKey>
</enc:encryptedSecret>
</descriptor>
</descriptor>
</key>
Data Protection: Extensibility API
Permettono di ridefinire tutto il ciclo di cifratura a partire dall’interfaccia
IAuthenticatedEncryption
Condivisione di authentication cookie
con [Link] 4.x
Le applicazioni [Link] 4.x che fanno uso di Katana come middleware per
generare i cookie, possono essere configurate per essere generare cookie
compatibili con il middleware di [Link] Core
• Katana = UseCookieAuthentication

Supporto dal framework 4.5.1+

E’ necessario installare da NuGet il pacchetto


[Link]
Condivisione di authentication cookie
con [Link] 4.x

[Link](new CookieAuthenticationOptions
{
AuthenticationType = [Link],
CookieName = ".[Link]",
TicketDataFormat = new AspNetTicketDataFormat(new DataProtectorShim(
[Link](new DirectoryInfo(@"c:\shared-keys\"))
.CreateProtector("[Link]
[Link]",
"Cookies",
"v2")))
});
Rimpiazzare <machineKey>
Il nuovo sistema di protezione di [Link] Core può essere utilizzato per
rimpiazzare machineKey su applicativi [Link] 4.5.1+

Bisogna installare da NuGet il pacchetto


[Link]

Verranno aggiunte queste righe nel [Link]


<machineKey compatibilityMode="Framework45" dataProtectorType="..." />
<add key="aspnet:dataProtectionStartupType" value="" /></appSettings>
Rimpiazzare <machineKey>
Poiché le chiavi sono salvate dentro il file system, questo meccanismo non
funzionerà se l’applicativo è distribuito in un sistema scalabile: si crea una
classe custom a partire da DataProtectionStartup
public class MyDataProtectionStartup : DataProtectionStartup
{
public override void ConfigureServices(IServiceCollection services)
{
[Link]()
.SetApplicationName("my-app")
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\shared-keys\"))
.ProtectKeysWithCertificate("thumbprint");
}
}
Rimpiazzare <machineKey>
Rimpiazziamo la riga aggiunta automaticamente all’installazione del
pacchetto di NuGet con l’implementazione specifica della classe custom
appena creata

<add key="aspnet:dataProtectionStartupType"
value="[Link], DataProtectionDemo" />
Demo
Meccanismi di Caching
I dati memorizzati all’interno della cache sono accessibili molto più
velocemente rispetto all’accesso diretto alla sorgente

Miglioramento delle prestazioni delle applicazioni in termini di


performance e scalabilità

Applicazioni su server multipli devono gestire una cache distribuita


Sono previsti numerose modalità di caching, incluso il Memory
Caching

Memory Cache si utilizza implementando l’interfaccia IMemoryCache


In Memory Caching - Configurazione
Gestita tramite Dependency Injection modificando il metodo
ConfigureServices aggiungendo:

[Link]();

Modifica del progetto, aggiungendo una reference a:


[Link]

Inserire all’interno del nostro controller o nel controller del nostro middleware
un’istanza di IMemoryCache
In Memory Caching – Lettura/Scrittura
Il metodo Invoke consente di ritornare i dati presenti all’interno della cache

Metodo Get e metodo TryGet per ottenere dati dalla cache (key per la
ricerca del dato nella cache

Metodo Set per salvare un valore nella cache (key per il recupero e
MemoryCacheEntryOptions)

E’ possibile impostare un ExpireTimes per i dati memorizzati all’interno della


cache
In Memory Caching - Callbacks
Possibilità di gestire callback:

Al momento della Set è possibile aggiungere

.RegisterPostEvictionCallback(key,value,reason,substate){…}

Reason Type: None


Removed
Replaced
Expired
TokenExpired
Capacity
In Memory Caching – Distributed
Cache
Migliora la gestione nella Cache nel cloud
La cache è coerente su tutti i server
La cache viene mantenuta anche in caso di riavvio del singolo server
L’archivio sorgente ha meno accessi

Utilizzo dell’interfaccia IDistributedCache, sia in modalità sincrona che


asincrona

Per la configurazione:
Specificare la dipendenza nel [Link]
Configurare l’implementazione di IDistributedCache nel ConfigureServices(…)
Richiedere un’istanza di IDistributedCache all’interno del nostro Middleware o nel controller
In Memory Chaching
Possibilità di utilizzo con Redis localmente o con Azure

Possibilità di utilizzo con Sql Distributed Cache utilizzando:


• [Link]: 1.0.0-preview2-final
• dotnet sql-cache create DataSource nomeDb

Get(…)
Set(…)

Usando un’istanza di
IDistributedCache e non SqlServerCache
Response Caching
Cache specifica per le risposte HTTP gestite tramite action di
[Link] MVC Core
Riduce il numero di richieste che un client o proxy deve effettuare
verso il server web
Cache-Control:
• Public
• Private
• No-cache
Response Caching
ResponseCacheAttribute: utilizzato per specificare gli header
che un controller utilizza per la gestione della cache

• Duration
• Location
• NoStore
• VeryByHeader
• CacheProfileName
• Order
Demo
Strumenti per lo sviluppo Client Side
Bower
Grunt

Gulp

npm
Yeoman
[Link]

[Link] : framework per la realizzazione di applicazioni utilizzando


Javascript

L’idea: utilizzare un linguaggio tipicamente cliente-side per la realizzazione


di applicazioni server-side

Basato su un modello event-driven: si esegue un’azione quando succede


qualcosa.

Gestione delle azioni in modalità asincrona


[Link]
Il funzionamento sincrono è di tipo sequenziale

Le chiamate Ajax : per natura sono chiamate di tipo asincrono

Si basa su Chrome’s Engine V.8 Javascript

Multipiattaforma : Windows, Mac e Linux


[Link] - Installazione
Sito di riferimento: [Link]

Utilizzo a linea di comando:

$> Node –v
$> npm install NomePackage
[Link] – Perché?
Compilazione del linguaggio di programmazione JavaScript:
Nessun nuovo linguaggio da impare!

Programmazione asincrona

Trasmissione tramite protocollo HTTP: velocità e affidabilità

Ampia community di sviluppatori e di package utilizzabili

Tool integrati all’interno di Visual Studio


[Link]
Attorno a [Link] sono nati una serie di tools che permettono di
automatizzare operazioni ricorrenti:

• Minimizzare file .css e/o javascript


• Concatenamento di file
• Ottimizzazione immagini

L’infrastruttura comune è quella di [Link]


Package Manager
Molto spesso si utilizzano componenti di terze parti all’interno di progetti
• Preprocessori di file CSS
• Strumenti di compressione dati
• Strumenti per semplificare il codice

L’utilizzo di pacchetti provenienti da fonti differenti: perdita di tempo!

Problemi di dipendenza tra i pacchetti: meglio risolverle automaticamente

Fonti differenti: sorgenti datati!


Package Manager
La soluzione è l’utilizzo di Package Manager

Tipicamente sono programmi a linea di comando

I più diffusi in ambito Web


• npm : presente nativamente in [Link] (npm is not an acronym)
• Bower: si autodefinisce un package manager per il web
npm (Node Package Manager)
Npm è il sistema di gestione dei pacchetti integrato in [Link]
E’ possibile ricercare i pacchetti [Link]
Repository centralizzato in cui sono presenti migliaia di progetti

In particolare sono presenti pacchetti per il web:


• Gulp
• Grunt
• Yeoman
• Autoprefixer
• BrowserSync
Bower
Sito di riferimento: [Link]
Rende più semplice e rapido l’utilizzo di librerie per il web

Nel suo repository sono presenti tra gli altri:


• Bootstrap
• AngularJS
• jQuery
• Font Awesome
• jQuery UI
Bower vs npm
Potremmo trovare pacchetti disponibile per entrambi
Entrambi permettono lo scaricamento di pacchetti rapidamente
Entrambi a linea di comando
Bower per la gestione di pacchetti front-end
Bower incluso nel progetto finale
Npm pacchetti legati allo sviluppo
Npm NON incluso nel progetto finale
Creazione di una soluzione con npm
Requisito [Link]: [Link]
Scaricato automaticamente
Per aggiornare la versione: npm install npm –g
Posizionarsi all’interno della cartella progetto
Inizializzare un progetto:

$> npm init

Ci verranno richieste una serie di domande


Al termine verrà creato il file [Link]
npm Gestione dei pacchetti
Home del progetto: [Link]
E’ prevista la ricerca di pacchetti specifici
E’ possibile ricercare anche direttamente dalla linea di comando

npm search <package>

E’ possibile installare il pacchetto

npm install <package>


Bower Gestione dei pacchetti
Home del progetto: [Link]
E’ prevista la ricerca di pacchetti specifici
Non è prevista la possibilità di ricercare pacchetti da linea di comando

E’ possibile installare il pacchetto

bower install <package>


Utilizzo dei pacchetti scaricati – npm
I pacchetti (tipicamente) vengono utilizzati da linea di comando

Comandi con funzionalità differenti


• Compilazione
• Compressione
• Combinazione di file

Possibilità di automatizzare i task impostando task runners


Gulp
Prerequisito: [Link]

Scrittura del codice utilizzando il runtime JavaScript di Chrome (V8)

Permette di automatizzare le operazioni più frequenti

Si aggiunge ad un progetto esistente creato con:

$> npm init


Gulp
Esempio di Task
• Analisi del codice JavaScript
• Compilazione dei file .less
• Concatenazione dei file JavaScript per ridurre le richieste HTTP
• Minificazione e rinominazione dei file creati
Minifying
E’ un processo che consente di ottimizzare le dimensioni di un file

Le operazioni di ottimizzazione non influenzano il normale funzionamento


del codice

Semplicemente vengono effettuate operazioni di eliminazione di spazi,


newline, commenti, ecc…
Grunt
Consente di creare task a partire da codice scritto in JavaScript

Disponibile tramite npm

Disponibili differenti plugin

Utilizzato per task come la minificazione, compilazione e operazioni di


unit testing
Yeoman
Creazione della struttura di un’applicazione a partire da template
Utilizza [Link], Bower e Grunt
Disponibili numerosi template online (anche per .NET Core)
Template aspnet e aspnetcore-spa

$> npm install -g yo bower grunt-cli


$> npm install -g generator-webapp
$> yo webapp
Demo
Sviluppo di servizi con [Link] Core
[Link] Core ha template per la creazione di:
• Servizi basati su Web API
• Web Application
• Empty Application

Dependency Injection (Costructor Injection / Service Injection)

Non utilizza la [Link]


Sviluppo di servizi con [Link] Core
[Link] Core utilizza [Link] per la configurazione

I controller WebApi diventano normali controller


• Non sono più presenti ApiController, [Link] e IHttpActionResult

Utilizzo di UseMvc() per la configurazione del routing basato su


attributi/rotte

[Route("api/[controller]")]

// GET api/values/5
[HttpGet("{id}")]
CORS (Cross-Origin Requests)
In chiamate Ajax, sono tutti URL diversi
• [Link]
• [Link]
• [Link]
• [Link]
• [Link]

Si usa CORS per consentire certi domini


Abilitare CORS
Prima si configura il servizio
public void ConfigureServices(IServiceCollection services)
{
[Link]();
}

Poi si configurano le policy


public void Configure(IApplicationBuilder app, IHostingEnvironment env,
ILoggerFactory loggerFactory)
{
...
[Link](builder => [Link]("[Link]
...
}
Anche in MVC
Basta usare gli attributi
• DisableCors: per disabilitare
• EnableCors: per abilitare

Sono filtri che agiscono su Controller/Action o globalmente


Demo
Internazionalizzazione
E’ fondamentale per rendere il sito web raggiungibile da chiunque
E’ la «somma» di globalizzazione e localizzazione

Globalizzazione
• Supporto a diverse culture per quanto riguarda input, display ed ouput dei dati
(formato di data e ora, numeri, valuta, case e text orientation, comparazione di
stringhe, etc…)

Localizzazione
• Supporto di nuove lingue (tramite ResourceManager)
Supporto da [Link] Core
Middleware
Supporto ai file .resx
Se ci fanno comodo, si possono usare i TagHelper
Localizzazione: le basi
Si parte dalla Dependency Injection dell’interfaccia IStringLocalizer
• Sfrutta ancora la parte funzionante di ResourceManager e ResourceReader

Non contiene altro che un dizionario con le chiavi ed i valori corrispondenti


da associare

Non richiede obbligatoriamente i file .resx per partire


• Viene fatto un controllo sull’esistenza della chiave dentro il dizionario, se non esiste
viene ritornato il valore stesso
• Nelle chiavi ci può anche essere html (ma è sconsigliato)
Localizzazione: le basi
Esempio di applicativo WebAPI

public class AboutController : Controller


{
private readonly IStringLocalizer<AboutController> _localizer;

public AboutController(IStringLocalizer<AboutController> localizer)


{
_localizer = localizer;
}

[HttpGet]
public string Get()
{
return _localizer["About Title"];
}
}
Localizzazione: le basi
Si può usare anche l’interfaccia IHtmlLocalizer per fare encoding di Html

public class AboutController : Controller


{
private readonly IHtmlLocalizer<AboutController> _localizer;

public AboutController(IHtmlLocalizer<AboutController> localizer)


{
_localizer = localizer;
}

[HttpGet]
public LocalizedHtmlString Get(string name)
{
return _localizer["<b>Hello</b><i> {0}</i>", name];
}
}
Localizzazione: la view
Esiste un localizer specifico per la view: IViewLocalizer
• Continuano ad essere supportati anche IStringLocalizer e IHtmlLocalizer

@using [Link]
@inject IViewLocalizer ViewLocalizer

<h2>@ViewLocalizer["Hello World"]</h2>
Lavorare con le risorse
Si utilizzano i .resx per localizzare il testo in funzione della lingua
• Classico dizionario chiave-valore

I .resx possono essere specifici per Controller, View e tutti i file che sono nel
progetto [Link] Core

E’ sempre bene creare un file [Link]


• X è il nome del file
• LC è il Language Code (formato ISO)
• Senza il language code viene creata una normale classe, da evitare!
Convenzioni delle risorse
Poiché tutti i file sono localizzabili tramite file di risorse, c’è bisogno di
sfruttare delle convenzioni

Nome della risorsa Notazione

Resources/[Link] Punto

Resources/Controllers/[Link] Cartelle (percorso)


Convenzioni delle risorse
Anche «Resources» come percorso è configurabile

public void ConfigureServices(IServiceCollection services)


{
[Link]();

// aggiungiamo la localizzazione
[Link](options => [Link] = "Resources");
}
Supporto alle DataAnnotations
Le DataAnnotations hanno di default un messaggio che viene utilizzato
durante la validazione, possiamo sfruttarlo e localizzarlo

public void ConfigureServices(IServiceCollection services)


{
[Link]().AddDataAnnotationsLocalization();
}

[Required(ErrorMessage = "Il campo Password è obbligatorio")]


[DataType([Link])]
[Display(Name = "Password")]
public string Password { get; set; }
Middleware per la localizzazione
Per impostare valori di default per le lingue, per indicare quali sono le lingue
supportate (e così via), è disponibile un middleware

var supportedCultures = new[] { new CultureInfo("en"), new CultureInfo("it") };

[Link](new RequestLocalizationOptions
{
DefaultRequestCulture = new RequestCulture("it", "it"),
SupportedCultures = supportedCultures, // globalizzazione...
SupportedUICultures = supportedCultures // localizzazione
});
RequestCultureProvider
Ogni richiesta viene analizzata e parsata la lista di RequestCultureProvider
per determinare in modo efficiente qual è la lingua da utilizzare

QueryStringRequestCultureProvider
• Di solito viene utilizzato solo per scopi di debug
[Link]

AcceptLanguageHeaderRequestCultureProvider
• Non è un metodo infallibile

CookieRequestCultureProvider
RequestCultureProvider custom
Si possono anche creare provider custom, grazie alla Dependency Injection
di [Link] Core

[Link]<RequestLocalizationOptions>(options =>
{
var supportedCultures = new[] { new CultureInfo("en-US"), new CultureInfo("it") };

[Link] = new RequestCulture(culture: "en-US", uiCulture: "en-US");


[Link] = supportedCultures;
[Link] = supportedCultures;

[Link](0, new CustomRequestCultureProvider(async context =>


{
return new ProviderCultureResult("en");
}));
});
Demo
Pubblicazione su IIS
Integrazione con IIS

Necessario includere il package [Link]


all’interno delle reference

Per poter utilizzare il middleware di IIS è necessario aggiungere a


WebHostBuilder:

.UseIISIntegration()

Non è utilizzabile su sistemi operativi differenti (solo Windows)

Possibilità di estendere con IISOptions


IIS con WebListener
Scelta da preferire, perché si basa su [Link] (più performante)
Occorre rimuovere Kestrel e poi aggiungere in WebHostBuilder

.UseWebListener(options =>
{
[Link] = true;
var auth = [Link];
[Link] = true;
[Link] = [Link];
})

V2: WebListener rinominato in [Link]


• Utilizzato per l’hosting di [Link] Core su IIS
Kestrel
Web server multi piattaforma sviluppato con librerie asincrone
• Si usa in reverse proxy
• [v2] Nuova proprietà Limit per modificare i limiti di risposta
• [v2] Nuove feature che lo rendono direttamente esponibile via internet

[Link]

Necessario includere il package all’interno del file [Link]


Per poter utilizzare il middleware di Kestrel è necessario aggiungere a
WebHostBuilder:

.UseKestrel()
Docker
Docker è un container per il deploy di applicazioni e servizi

Prerequisiti
• Visual Studio 2015 Update3
• Microsoft [Link] Core SDK
• Visual Studio 2015 Tools for Docker
• Docker for Windows

Aggiungere alla solution il supporto a Docker, verranno aggiunti i file:


• [Link]
• dockerfile
• [Link]
• dockerTask.ps1
Docker
Dockertask.ps1 è lo script PowerShell generato automaticamente per
solution corrente
$> docker-machine ls

Dal prompt di PowerShell è possibile visualizzare lo stato delle vm docker

Per effettuare il build ed il run


$> DockerTask.ps1 –Build –Environment Release
$> DockerTask.ps1 –Run –Environment Release
Demo
SPA Templates
Template per SPA già pronti per
• Angular (4)
• Aurelia
• [Link]
• [Link]
• [Link]+Redux
Angular e React già inclusi, gli altri scaricabili
Semplificano la creazione di un nuovo progetto SPA con backend
basato su [Link] Core
Performance con [Link] Core 2
25% di richieste al secondo in più, a parità di codice
<1 secondo per l’avvio dell’app
Razor View compilation
• Attivo di default
• View pronta a generare l’HTML, perché non compilata dinamicamente

Ditelo ai vostri amici ☺


One more thing
[Link] Core SignalR
Arriva nelle prossime settimane
Riscritto per [Link] Core
Client library slegata da jQuery

[Link]
Demo
SignalR con [Link] Core
© 2018 iCubed Srl
La diffusione di questo materiale per scopi differenti da quelli per cui se
ne è venuti in possesso è vietata.

iCubed s.r.l.
Piazza Durante, 8 20131 MILANO
Phone: +39 02 57501057
[Link] 07284390965

Potrebbero piacerti anche