Core
Core
NET Core
Daniele Bochicchio
Chief Digital Officer @icubedsrl
Microsoft Regional Director
Microsoft ASP.NET MVP
Codice specifico
• CoreCLR
• System.IO e System.Security.Cryptography.Algorithms
.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 project.json)
• 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 file.dll
Test
• Unit test, nunit o xunit
• Motori installati via NuGet
• Sezione testRunner in project.json
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
• Microsoft.Extensions.SecretManager.Tools
• Microsoft.DotNet.Watcher.Tools
• Microsoft.AspNetCore.Server.IISIntegration.Tools
• Microsoft.EntityFrameworkCore.Tools
• Microsoft.AspNetCore.Razor.Tools
• Microsoft.Extensions.Caching.SqlConfig.Tools
Terze parti
• BundlerMinifier.Core
.NET Standard Library
Specifiche per set API
• BCL indipendente dalla
piattaforme
Garanzia di compatibilità
• Anche all’indietro grazie alle
versioni
• Più comodo rispetto a PCL
1.6: .NET Core 1 (con .NET Core 1.x 4.54.5 4.54.5 4.5.14.5.1 4.64.6 4.6.14.6.1 4.6.24.6.2
SDK))
2.0: .NET Core 2
.NET Framework
(con .NET Core 2.0 4.54.5 4.54.5 4.5.14.5.1 4.64.6 4.6.14.6.1 4.6.14.6.1 4.6.14.6.1 4.6.14.6.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
Xamarin.iOS 10.010.0 10.010.0 10.010.0 10.010.0 10.010.0 10.010.0 10.010.0 10.1410.14
Xamarin.Mac 3.03.0 3.03.0 3.03.0 3.03.0 3.03.0 3.03.0 3.03.0 3.83.8
Xamarin.Android 7.07.0 7.07.0 7.07.0 7.07.0 7.07.0 7.07.0 7.07.0 8.08.0
Silverlight per
8.08.0
Windows Phone
.NET Standard Library
Pacchetti NuGet
• Estrema modularizzazione
• Assembly/Package per namespace
https://www.nuget.org/packages/NETStandard.Library
• Metapackage: insieme di tutti i pacchetti .NET STandard
https://www.nuget.org/packages/Microsoft.NETCore.App
• 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
• System.XML
• +20K API e il 70% dei package di NuGet
Comparazione con .NET Framework
App model
• .NET Core supporta solo console e ASP.NET
• 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
• 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="generateCode.cmd" />
</Target>
• Array o singola istruzione <Target Name="MyPostCompileTarget"
• Bat, cmd, sh, bash, DOS AfterTargets="Publish">
<Exec Command="obfuscate.cmd" />
<Exec Command="removeTempFiles.cmd" />
</Target>
outputName.dll
• l’applicazione con l’entry point
outputName.runtimeconfig.json
• le runtimeOptions specificate nel progetto (opzionale)
outputName.deps.json
• lista di tutte le dipendenze. Necessario in ambienti dinamici, come ASP.NET
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
{
dependencies => NETStandard.Library "dependencies":{
"NETStandard.Library":"1.6.0"
},
"frameworks":{
"netstandard1.3":{}
}
}
Demo
Cos’è ASP.NET Core?
Una rivoluzionaria versione di ASP.NET
Basato su .NET Core
Un taglio netto rispetto al passato
Completamente riscritta
Cross-platform
Born in the cloud
Performante
ASP.NET 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
Application
FCL, GAC, NuGet NuGet
Open Source
Frameworks
IIS, HTTP.SYS
IIS Web Server Kestrel
Application
System.Web DNX
Host
Platform .NET BCL & FCL
.NET BCL & FCL
Libraries .NET on NuGet
.NET CLR
.NET CLR Runtime .NET Core CLR
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 ASP.NET Core e le funzionalità aggiuntive
Ad esempio, i file statici sono supportati attraverso un MiddleWare
• Vedi Startup.cs / Configure -> UseStaticFiles
C’è una nuova impostazione del progetto, per gestire i file statici
• Vedi wwwroot
• Vedi UseContentRoot in Program.cs
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 web.config?
Esiste solo per compatibilità con IIS
Sostituito da un file chiamato Startup.cs
I parametri di configurazione sono in file JSON
• Con supporto degli environement
<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
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseIdentity();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
Il metodo ConfigureServices
Per configurare ASP.NET
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddMvc();
ConfigureServices
• Consente di gestire i servizi utilizzati dall’applicazione
• Sfrutta il meccanismo di Dependency Injection di ASP.NET
Demo
Logging
Integrato all’interno del runtime
Legato all’interfaccia ILoggerFactory o ILogger<T>
var logger = loggerFactory.CreateLogger("LogCategory");
logger.LogInformation("No items found");
List.cshtml
(View)
ProductsController
(Controller)
Edit.cshtml
(View)
Product
(Model) SQL
ASP.NET MVC vs WebForms
Sono modelli paralleli
• WebForm per facilità
• MVC per controllo totale
MVC è il futuro
• ASP.NET Core 1 = .NET Core + ASP.NET Core MVC + WebAPI
• ASP.NET 4.6 = .NET Framework 4.6 + ASP.NET MVC 5/Core MVC + WebAPI
ASP.NET 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
View Controller
La chiamata di una pagina con MVC
Con ASP.NET normale viene usata la pagina fisica
• A meno che non si usino HttpHandler
La View è una pagina con codice HTML e server side con lo stesso nome
dell’action del Controller
• Es List.cshtml, Details.cshtml, etc.
/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
<h1>@Model.Title</h1>
<p>Prezzo: @Model.Price.ToString()</p>
@
La "chiocciolina" magica
Istruzione su singola riga
<p>Path: @myFilePath</p>
<p>@myQuote</p>
@{
@* Questo è un commento in linea. *@
var theVar = 17;
}
If/else/else if switch
for foreach
while
@Html.Partial("_Partial", Model)
PartialView async
ASP.NET Core introduce il supporto per le partial async
Utile per migliorare la scalabilità, qualora ci sia codice async nella view
@await Html.PartialAsync("_List")
Sfruttare le layout view nel progetto
Consente di centralizzare un layout comune a tutte le view
<!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 MyBookShop.Models.BookViewModel
@{ ViewBag.Title = Model.Title; }
<h2>Libro</h2>
<p>
@Model.Title
</p>
<p>
@Model.Author
</p>
<p>
@Model.Category
</p>
Sfruttare le layout view nel progetto
Impostare ogni volta la pagina di layout può essere tedioso e ripetitivo
Limita la manutenzione
<environment names="Development">
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css" />
</environment>
<environment names="Staging,Production">
<link rel="stylesheet"
href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.6/css/bootstrap.min.css"
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
asp-fallback-test-class="sr-only"
asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
</environment>
Importazione globale per View
Possiamo registrare funzionalità a livello globale nel file
Shared\_ViewImports.cshtml
@using WebApplication1
@using WebApplication1.Model
@using Microsot.AspNetCore.Identity
@using Microsoft.AspNetCore.Mvc.Razor
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
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
<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 ASP.NET 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.
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
services.Configure<RazorViewEngineOptions>(options =>
{
options.AreaViewLocationFormats.Clear();
options.AreaViewLocationFormats.Add("/Backoffice/{2}/Views/{1}/{0}.cshtml");
options.AreaViewLocationFormats.Add("/Backoffice/{2}/Views/Shared/{0}.cshtml");
options.AreaViewLocationFormats.Add("/Views/Shared/{0}.cshtml");
});
Indicare l’area
A differenza di ASP.NET MVC, in ASP.NET 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 project.json, 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
@myService.Message()
Demo
View Components
Novità di ASP.NET MVC: sembrano partial view, ma sono più potenti
Sono indicati quando oltre alla logica di rendering, c’è anche logica
applicativa
<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
<!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 Html.EditorFor/TextBoxFor
<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 Html.ValidationSummary
<div asp-validation-
summary="ValidationSummary.ModelOnly"></div>
Tag helper: select
Genera un tag <select> con le opzioni specificate all’interno della proprietà
Items
E’ l’alternativa di Html.DropDownListFor
<select asp-for="Country"
asp-items="Model.Countries"></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
[HtmlTargetElement(TagStructure = TagStructure.WithoutEndTag)]
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/bootstrap.css" />
<link rel="stylesheet" href="~/dev/site.css" />
</environment>
<environment names="Staging,Production">
<link rel="stylesheet" href="~/prod/bootstrap.css" />
<link rel="stylesheet" href="~/prod/site.css" />
</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
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });
}
…ad ASP.NET 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
// equivalente
app.UseMvcWithDefaultRoute();
}
Personalizzazione
È possibile personalizzare il comportamento di routing semplicemente
aggiungendo constraint sulle proprietà o eventuali token per gestire, ad
esempio, la localizzazione
routes.MapRoute(
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 Microsoft.AspNetCore.Routing.Constraints
{
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
[HttpGet("custom/url/to/destination")]
public IActionResult Destination()
{
return View();
}
Demo
Entity Framework
• ORM di Microsoft basato sul .NET Framework
• Insieme di tecnologie ADO.NET 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
• https://github.com/aspnet/EntityFramework
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
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
Siamo dev
• Focus sul domain design
• C# ci è più familiare delle query di SQL
Runtime su NuGet
Tooling su Microsoft Download Center
Ultima versione inclusa in Visual Studio
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; }
} }
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; }
}
[Key]
public int MyPrimaryKey { get; set; }
Model e Entity Mapping
Configurazione dello schema per tutto il database
Configurazione dello schema per singola tabella
context.Students.AddRange(fakeStudents);
context.SaveChanges();
base.Seed(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; }
} }
Android
ASP.NET ASP.NET Core OS X
LIBRARIES
BASE
COMMON INFRASTRUCTURE
EF6.x EF Core
Nuove tipologie di database
Relazionali e non-relazionali
Alcuni provider
Componenti pay-per-play
EF Core
EF6 non era così male…
Per le PCL con .NET Core sono stati aggiunti nuovi comandi:
dotnet ef migrations add {MigrationName}
dotnet ef migrations remove
dotnet ef database update
Novità:
• Linq Translator migliorato
• DbSet.Find
• 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
ChangeTracker.AutoDetectChangesEnabled = false;
var result = base.SaveChanges(acceptAllChangesOnSuccess);
ChangeTracker.AutoDetectChangesEnabled = true;
return result;
}
Custom conventions
Non c’è più l’interfaccia IStoreModelConvention di EF6
Query
Miglioramento di LINQ Translator (GroupBy sul DB), Lazy Loading
Schema
Aggiornamento del modello dal DB
Operazioni CRUD
Seed dei dati
Simple command interception
.NET Standard 2
Supporto anche per Xamarin
Filters
Consentono di aggiungere comportamenti a controller
ed action
Ad esempio:
• [Authorize]
• [HttpPost]
Globali (Startup.cs)
Locali (su controller o action)
L'infrastruttura dei filtri
Simili agli HttpModule di ASP.NET
Sono pensati per ASP.NET 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)
{
...
services.AddMvc(option =>
{
// istanza per ogni richiesta
option.Filters.Add(new MyFilterAttribute());
// ogni richiesta crea una nuova istanza
option.Filters.Add(typeof(MyFilterAttribute ()));
});
}
}
Registazione locale dei filtri
// verrà utilizzata la DI
// dobbiamo ricordarci di registrare MyFilterAttribute
[ServiceFilter(typeof(MyFilterAttribute))]
public IActionResult Index()
{
return View();
}
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 = ASP.NET 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 ASP.NET Core
<configuration>
<system.webserver>
<modules>
<add name="HelloWorldModule" type="HelloWorldModule"/>
</modules>
</system.webserver>
</configuration>
Dopo: Middleware
E’ un componente software inserito in una pipeline che consente di gestire
le richieste e le risposte
[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 web.config
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 web.config
L’ordine di esecuzione è gestito da una serie di eventi BeginRequest,
AuthenticationRequest, ecc
L’ordine di esecuzione è configurabile nel web.config
Migrare da HttpModule a Middleware
Middleware
Basato su provider
• modello estendibile facilmente con provider, Entity Framework già incluso
app.UseCookieAuthentication(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 HttpContext.Authentication.SignInAsync("MyCookieMiddlewareInstance",
principal,
new AuthenticationProperties
{
ExpiresUtc = DateTime.UtcNow.AddMinutes(20),
IsPersistent = true
});
https://docs.microsoft.com/en-us/aspnet/core/migration/1x-to-
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
Microsoft.AspNetCore.DataProtection
• Espone tutto il core del sistema di protezione di ASP.NET, inclusa la gestione delle
chiavi, operazioni di crittografia e configurazioni.
Microsoft.AspNetCore.DataProtection.Extensions
• 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
Microsoft.AspNetCore.DataProtection.SystemWeb
• Può essere installato nelle applicazioni .NET 4.x per gestire il «vecchio» machinekey
con il nuovo layer di sicurezza
Microsoft.AspNetCore.Cryptography.KeyDerivation
• 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
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
CookieName = ".AspNetCore.Cookies",
TicketDataFormat = new AspNetTicketDataFormat(new DataProtectorShim(
DataProtectionProvider.Create(new DirectoryInfo(@"c:\shared-keys\"))
.CreateProtector("Microsoft.AspNetCore.Authentication.Coo
kies.CookieAuthenticationMiddleware",
"Cookies",
"v2")))
});
Rimpiazzare <machineKey>
Il nuovo sistema di protezione di ASP.NET Core può essere utilizzato per
rimpiazzare machineKey su applicativi ASP.NET 4.5.1+
<add key="aspnet:dataProtectionStartupType"
value="DataProtectionDemo.MyDataProtectionStartup, DataProtectionDemo" />
Demo
Meccanismi di Caching
I dati memorizzati all’interno della cache sono accessibili molto più
velocemente rispetto all’accesso diretto alla sorgente
services.addMemoryCache();
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)
.RegisterPostEvictionCallback(key,value,reason,substate){…}
Per la configurazione:
Specificare la dipendenza nel project.json
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
Get(…)
Set(…)
Usando un’istanza di
IDistributedCache e non SqlServerCache
Response Caching
Cache specifica per le risposte HTTP gestite tramite action di
ASP.NET 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
Node.js
$> Node –v
$> npm install NomePackage
Node.js – Perché?
Compilazione del linguaggio di programmazione JavaScript:
Nessun nuovo linguaggio da impare!
Programmazione asincrona
[Route("api/[controller]")]
// GET api/values/5
[HttpGet("{id}")]
CORS (Cross-Origin Requests)
In chiamate Ajax, sono tutti URL diversi
• http://example.com
• http://example.net
• http://example.com:9000/foo.htm
• https://example.com/foo.html
• http://www.example.com/foo.htm
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 ASP.NET 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
[HttpGet]
public string Get()
{
return _localizer["About Title"];
}
}
Localizzazione: le basi
Si può usare anche l’interfaccia IHtmlLocalizer per fare encoding di Html
[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 Microsoft.AspNetCore.Mvc.Localization
@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 ASP.NET Core
Resources/Controllers.HomeController.it.resx Punto
// aggiungiamo la localizzazione
services.AddLocalization(options => options.ResourcesPath = "Resources");
}
Supporto alle DataAnnotations
Le DataAnnotations hanno di default un messaggio che viene utilizzato
durante la validazione, possiamo sfruttarlo e localizzarlo
app.UseRequestLocalization(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
http://localhost:5000/?culture=it-IT&ui-culture=en-US
AcceptLanguageHeaderRequestCultureProvider
• Non è un metodo infallibile
CookieRequestCultureProvider
RequestCultureProvider custom
Si possono anche creare provider custom, grazie alla Dependency Injection
di ASP.NET Core
services.Configure<RequestLocalizationOptions>(options =>
{
var supportedCultures = new[] { new CultureInfo("en-US"), new CultureInfo("it") };
.UseIISIntegration()
.UseWebListener(options =>
{
options.EnableResponseCaching = true;
var auth = options.ListenerSettings.Authentication;
auth.AllowAnonymous = true;
auth.Schemes = AuthenticationSchemes.NTLM;
})
Microsoft.AspNetCore.Server.Kestrel
.UseKestrel()
Docker
Docker è un container per il deploy di applicazioni e servizi
Prerequisiti
• Visual Studio 2015 Update3
• Microsoft ASP.NET Core SDK
• Visual Studio 2015 Tools for Docker
• Docker for Windows
https://github.com/aspnet/SignalR
Demo
SignalR con ASP.NET 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
P.IVA 07284390965