Contattaci
Lasciaci i tuoi riferimenti, saremo felici di contattarti il prima possibile e organizzare una consulenza gratuita.
The chosen one: .NET 5
.NET 5, il successore di .NET Core 3.1 e .NETFramework 4.8, mira a fornire agli sviluppatori .NET una nuova esperienza disviluppo multipiattaforma. Mette ordine alla frammentazione dell'universo .NET che si è verificata nel corso degli anni e apporta nuove straordinarie funzionalità. Di seguito i cinque punti su cui concentrarci per capire agevolmente quali sono i punti di forza dell’ultima release per gli sviluppatori di casa Microsoft.
1. Piattaforma Unificata
La prima cosa che c’è da sapere è che .NET 5offre una nuova visione unificata del mondo .NET.
Se abbiamo già lavorato con .NET, dovremmo essere a conoscenza della sua frammentazione di piattaforme sin dalla sua prima versione nel 2002. .NET Framework è stato inizialmente progettato per Windows, ma la sua specifica di runtime, nota anche come Common Language Infrastructure(CLI), fu standardizzata come ECMA335.
Questa standardizzazione consentì a chiunque di creare la propria implementazione del runtime .NET. Infatti non si attese molto per veder comparirne i primi all’orizzonte: abbiamo Mono per sistemi basati su Linux, Silverlight per applicazioni basate su browser, framework .NET Compact e Micro per dispositivi mobili e con risorse limitate e così via.
Per questi motivi, Microsoft decise di scrivere .NET Core da zero pensando esclusivamente alla compatibilità multipiattaforma. Queste diverse implementazioni hanno sollevato la necessità di capire “dove” potrebbe essere eseguito un pacchetto .NET.
Dovresti creare versioni diverse della tua libreria per distribuirla? La risposta a questa domanda fu .NET Standard, ovvero una specifica formale delle API comuni che dovresti aspettarti tra le implementazioni della CLI. In altre parole, se crei la tua libreria per uno specifico .NET Standard, avrai la garanzia che verrà eseguita su tutti i runtime che implementano tale specifica.
Si comprende dunque che, in questa situazione disordinata, la compatibilità di implementazione desiderata non era così facile da ottenere. Questo è il motivo per cui .NET 5 appare in scena.
La nuova piattaforma .NET è il successore unificato delle varie versioni .NET: .NET Framework, .NET Standard, .NET Core,Mono, ecc. È ufficialmente la prossima versione di .NET Core 3.1, ma sostanzialmente determina la fine di .NET Framework, .NET Standard e le altre varianti che hanno causato grossi grattacapi agli sviluppatori .NET.
.NET 5 fornisce un set comune di API che allinea le diverse implementazioni di runtime. Questo set di API è identificato dal Net5.0 Target Framework Moniker (TFM), che è il token impostato nel progetto .NET per specificare il framework di destinazione. Ciò consente l'esecuzione dell'applicazione su qualsiasi implementazione di runtime che supporta .NET 5. Tuttavia, è comunque possibile compilare applicazioni per una piattaforma specifica. Ad esempio, per creare un'applicazione che utilizza l'API di Windows, è necessario specificare il TFM net5.0-windows. In questo modo, la creazione di un'applicazione specifica per la piattaforma è una tua scelta, non una scelta che dipende dall'implementazione di runtime che stai utilizzando per sviluppare la tua applicazione.
Naturalmente, realizzare questa piattaforma unificata ha richiesto uno sforzo significativo e una riorganizzazione dell'architettura interna. Alcune funzionalità sono state rimosse dal set diAPI di base, come vedrai più avanti, ma la piattaforma ha ottenuto un miglioramento generale delle prestazioni.
Mentre il nuovo .NET 5 viene fornito con l'obiettivo di unificazione della piattaforma, il piano iniziale è cambiato a causa del COVID-19. In effetti, .NET 5 pone le basi dell'unificazione, ma sarà completato con .NET 6 a novembre 2021. Con tale rilascio, otterremo la versione stabile della nuova Universal UI ed anche il supporto per i TFM specifici per Android ( net6.0-android) e iOS (net6.0-ios).
2. Nuove funzionalità in C#
La seconda cosa da tenere a mente riguarda C#..NET 5 include C# 9, la nuova versione del principale linguaggio di programmazione della piattaforma .NET. Ci sono diverse nuove funzionalità, e di seguito ne troveremo un piccolissimo assaggio, giusto per farci “venir fame”.
Dichiarazioni Top-Level
Tra le nuove funzionalità, una delle più notevoli è l'introduzione di dichiarazioni top-level (o di primo livello). Per sapere cosa sono, diamo un'occhiata al seguente programma:
Ebbene, il precedente blocco potrà essere tranquillamente sostituito dal semplice ed unico:
Le istruzioni top-level consentono di concentrarsi su ciò che conta davvero in piccoli programmi e utilità per console e utilizzare C# con un approccio più orientato agli script.
Tipi di record
Un'altra interessante novità sono i tipi di record. Con i record, possiamo dichiarare un tipo di riferimento immutabile, ovvero un tipo basato sulla classe che non può essere modificato dopo la sua creazione. Un esempio di tipo di riferimento immutabile incorporato è la classe System.String. Dopo aver creato un'istanza di System.String, non è più possibile modificarne il valore.
Considera la seguente dichiarazione del tipo di record:
Possiamo creare un istanza del record Person come faremmo per una classe, ma non ne possiamo alterare ad esempio la proprietà FirstName.
Potremo comunque confrontare due istanze del record Person come si trattassero di tipologie primitive:
Init setters
C# 9 aggiunge anche la funzione di init setters per definire proprietà che possono essere solo inizializzate. Consideriamo la seguente definizione di classe:
Questa classe definisce una persona con proprietà LastName e FirstName che possono essere inizializzate, ma non modificate. La proprietà Address può essere invece modificata in qualsiasi momento:
3. .NET MAUI, the Universal UI
Come terzo punto, dobbiamo sapere che .NET 5offre un nuovo modo di creare interfacce utente multipiattaforma. Grazie al framework UI dell'app multipiattaforma .NET, noto anche come .NET MAUI, saremo in grado di creare interfacce utente per Android, iOS, macOS e Windows con un unico progetto.
In realtà, questa funzionalità è ancora incorso e verrà rilasciata con .NET 6, ma possiamo iniziare a dare un'occhiata a .NET MAUI per essere pronto quando verrà rilasciato ufficialmente fin dal .NET 5.
.NET MAUI può essere considerato un'evoluzione di Xamarin.Forms, il framework open source per la creazione di app iOS eAndroid con un'unica base di codice .NET. Ma questo nuovo framework propone un modello universale per la creazione di interfacce utente su piattaforme mobilie desktop.
Oltre al buon vecchio Model-View-ViewModel(MVVM) pattern, .NET MAUI supporta anche il recentissimo Model-View-Update(MVU).
4. Supporto Single-File Applications
Altra grande feature che otterremo in .NET 5 è il supporto alle single-file applications, ovvero applicazioni pubblicate e distribuite come un singolo file. Ciò significa che la nostra applicazione e tutte le sue dipendenze sono raggruppate in un unico file.
Ad esempio, supponiamo di eseguire il seguente comando all'interno della cartella del nostro progetto .NET 5:
Otterremo un singolo file contenente l’intera applicazione creata per Linux, tutte le dipendenze usate nel progetto ed il runtime .NET (--self-contained true). Ciò significa che non è nemmeno necessario installare il runtime .NET sul computer/server di destinazione.
Naturalmente, si potranno specificare questi parametri nella configurazione del progetto:
Notate bene che questa funzionalità non usa lo stesso approccio delle applicazioni a file singolo che puoi compilare in .NETCore 3.1. In .NET Core 3.1. L'applicazione a file singolo è solo un modo per creare pacchetti binari: in fase di esecuzione vengono poi scompattati in una cartella temporanea, caricati ed eseguiti. In .NET 5, l'applicazione a file singolo ha una nuova struttura interna e viene eseguita direttamente senza penalizzazioni delle prestazioni.
A questo link è possibile trovare la documentazione di questa tipologia di rilascio.
5. Tecnologie non più supportate
Per ultimo punto, è obbligo parlare anche dichi esce dal ciclo delle tecnologie supportate, non solo dei nuovi arrivati.
Come detto sopra, la revisione dell'architettura e il tentativo di rendere .NET 5 un vero e proprio framework di programmazione multipiattaforma ha portato alla rimozione di alcune. funzionalità supportate in .NET Framework. Diamo una rapida occhiata alle funzionalità rimosse e alle possibili alternative.
Web Forms
Per molto tempo, ASP.NET Web Forms è stata la principale tecnologia per creare interfacce utente web dinamiche. Tuttavia, non è un segreto che la sua durata fosse strettamente legata al destino di .NETFramework. .NET Core non supporta Web Form, quindi il fatto che non sia più supportato in .NET 5 non dovrebbe essere una grande novità.
Tuttavia, abbiamo alcune alternative per creare interfacce utente web. Se stiamo realizzando applicazioni web tradizionali, Razor Pages è una di queste alternative. Se vuoi creare applicazioni a pagina singola, puoi usare invece Blazor.
Windows Communication Foundation (WCF)
Anche WCF, il framework di comunicazione tradizionale per Windows, sarà deprecato. Questo può sembrare un po' scioccante per gli sviluppatori che lo hanno utilizzato per creare le loro applicazioni orientate ai servizi. Tuttavia, è abbastanza comprensibile se ci rendiamo conto che l'obiettivo principale di .NET 5 è diventare un framework multipiattaforma.
L'alternativa a WCF consigliata da Microsoft è la migrazione a gRPC.Ma se abbiamo nostalgia di WCF o vuoi preparare una transizione graduale, puoi provare il progetto open source CoreWCF.
Windows Workflow Foundation
Infine, .NET 5 non includerà nemmeno WindowsWorkflow Foundation, la tecnologia del motore del flusso di lavoro disponibile in .NET Framework. Non esiste un sostituto ufficiale per questa tecnologia.Tuttavia, potremo usare un progetto di porting open source, CoreWF, per tentare di spostare i flussi di lavoro esistenti su .NET 5 o crearne di nuovi.
Primi Passi Insieme
Nella seconda parte di questo articolo sperimenteremo insieme la creazione di un nuovo progetto web tramite VisualStudio sfruttando il framework .NET 5 e mettendo subito alla prova il suo aspetto multipiattaforma, pubblicandolo su di una macchina Linux (Ubuntu).
Non temiate la lunghezza della scrollbar verticale del vostro browser, la guida è stata resa il più user-friendly possibile riportando intere porzioni di codice e schermate dei “punti salienti”,ecco spiegato il motivo della sua lunghezza.
Creiamo il nuovo progetto con Visual Studio
Creiamo il nuovo progetto cross platform “MyCrossPlatformApp”partendo dal template “ASP.NET Core Web App”. Se non si trova il suddetto template tra quelli disponibili, assicurarsi di aver selezionato la voce “All platforms” e soprattutto che sia installata sul vostro Visual Studio la relativa SDK.
NB! E’ essenziale selezionare come Target Framework -> .NET 5
Una volta completato lo scaffolding del nuovo progetto possiamo tranquillamente procedere con la sua pubblicazione.
Non sono necessarie ulteriori modifiche essendo il nostro obiettivo ultimo l’esecuzione del progetto su una macchinaLinux. Possiamo comunque provare a far partire il progetto per assicurarci che non contenga errori (e che Visual Studio non stia tentando di nascosto di sabotarci…).
Il risultato sarà la classica pagina di benvenuto del template selezionato.
Eradicati i nostri dubbi riguardo la bontà della compilazione del progetto, possiamo finalmente pubblicarlo.
Il risultato della pubblicazione sarà una cartella contenente exe, dll e files di configurazione del nostro applicativo, compilati per il rilascio sulla nostra piattaforma desiderata.
Procediamo dunque cliccando col destro sulla nostra soluzione nell’explorer di Visual Studio e selezionando la voce Publish.
Questo avvierà il wizard di creazione di un nuovo Profilo di Pubblicazione.
Delle varie modalità di pubblicazione, sceglieremo la più grezza e legacy, ovvero la pubblicazione su cartella/folder.In questo modo, lasciando tutte le impostazioni di default proposte nella successiva schermata, avremo il nostro risultato nella sotto cartella di progetto bin\Release\net5.0\publish .
Una volta creato il nuovo profilo di pubblicazione possiamo procedere cliccando dapprima su Publish (1) ed inseguito esaminando il risultato cliccando sulla cartella di output (2).
Et voilà! Una volta terminata la pubblicazione su cartella possiamo chiudere con VisualStudio ed iniziare a dedicarci alla nostra macchina Linux. Essendo il progetto compilato con un framework multipiattaforma (.NET5), nella cartella bin\Release\net5.0\publish avremo tutto il necessario per far partire l’app su qualsiasi SistemaOperativo in cui è installabile la relativa runtime.
Di seguito procederemo con la pubblicazione sull’ultima versione server Debian e l’ultima versione long-term support di Ubuntu Server.
UBUNTU 20.04 LTS & Apache
Prerequisiti
- Salvo particolarissime eccezioni o esigenze, sarebbe ideale cominciare a riscaldarci sul terminale con la solita sfilza di formalismi necessari a partire con tutti i repository e pacchetti aggiornati:
- sudo apt-get update
- sudo apt-get upgrade
- sudo apt-get dist-upgrade
- sudo apt-get autoclean
- sudo apt-get autoremove
- Nonostante sia un appunto banale e per molti scontato, tengo a precisare che per trasferire il nostro progetto sul server Ubuntu in questa guida faremo uso del protocollo SFTP. Sarà dunque necessario installare sulla macchina in questione la versione server di SSH (se non già presente) con il comando:
- sudo apt-get install openssh-server
Step#1 – Installazione Runtimes
Per prima cosa dobbiamo assicurarci che siano installate le runtime di .NET5 e ASP.NET Core 5. Procediamo con il seguente comando per listarle tutte:
dotnet --list-runtimes
Se il risultato dovesse essere il seguente(“command not found”) allora dobbiamo fare un passetto indietro, installandone almeno una.
Installare le runtime .NET non è complicato.
come già visto per l’SSH, possiamo tranquillamente procedere con la loro installazione tramite il packet manager di Ubuntu apt:
- Runtime .NET5
sudo apt-get install dotnet-runtime-5.0 - Runtime ASP.NET Core 5
sudo apt-get install aspnetcore-runtime-5.0
Con gran probabilità, arrivati a questo puntovi scontrerete con la mancanza dei pacchetti dotnet-runtime-5.0 e aspnetcore-runtime-5.0negli attuali repository della vostra macchina, come da screen di seguito (“Unable to locate package (…)”) .
Non disperate: oltre alla guida ufficialeMicrosoft per l’aggiunta del repository (LINK) potrete nuovamente fare affidamento a quanto segue di questa guida. Infatti, per l’aggiunta dei repository ufficiali Microsoft sul nostro server Ubuntu basterà eseguire i seguenti comandi:
curl -sSLhttps://packages.microsoft.com/keys/microsoft.asc | sudo tee/etc/apt/trusted.gpg.d/microsoft.asc
sudo apt-add-repository https://packages.microsoft.com/ubuntu/20.04/prod
sudo apt-get update
A questo punto saremo in grado di ritentare con successo l’installazione delle runtime .NET come descritto poche righe addietro, assicurandoci infine che compaiano nella lista fornita dal comando:
dotnet --list-runtimes
Step#2 – Installazione & Config. Apache
Dobbiamo sapere che le applicazioni .Net vengono eseguite su server Kestrel. Il nostro web server Apache fungerà da server proxy e gestirà il traffico dall’esterno della macchinare indirizzandolo al server Kestrel. Possiamo dunque vedere il nostro web serverApache come un middle layer per l’applicazione .Net .
Di seguito vedremo come installare e configurare un’installazione pulita di Apache sul nostro server Ubuntu per servire la nostra applicazione.
Diamo quindi i seguenti comando per installareApache ed abilitare in seconda battutati i moduli proxy, proxy_http, proxy_html e proxy_wstunnel.
sudo apt-get install apache2
sudo a2enmod proxy proxy_http proxy_html proxy_wstunnel
sudo a2enmod rewrite
systemctl restart apache2
Possiamo confermare la corretta installazione di Apache navigando con un browser all’indirizzo del nostro server. Se tutto è andato liscio, il risultato sarà la pagina di default di Apache con tanto di messaggio evidenziato IT WORKS come da screen:
Arrivati a questo punto, dovremo creare un file conf per configurare il nostro proxy su Apache.
Forniamo dunque il seguente comando per entrare nell’editor di testo nano :
sudo nano /etc/apache2/conf-enabled/netcore.conf
Copiamo ora la seguente configurazione nel file vuoto appena aperto per poi salvarlo con la combinazione (per chi non la conoscesse) CTRL+O -> INVIO -> CTRL+X .
NB! La porta 5000è quella usata di default dal server Kestrel con cui si eseguono le applicazioni .Net
<VirtualHost *:80>
ServerName localhost
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:5000/
ProxyPassReverse /http://127.0.0.1:5000/
RewriteEngine on
RewriteCond %{HTTP:UPGRADE}^WebSocket$ [NC]
RewriteCond %{HTTP:CONNECTION}Upgrade$ [NC]
RewriteRule /(.*)ws://127.0.0.1:5000/$1 [P]
ErrorLog/var/log/apache2/netcore-error.log
CustomLog/var/log/apache2/netcore-access.log common
</VirtualHost>
Ora con il seguente comando ci assicuriamo che non siano presenti errori nella configurazione appena create su Apache:
sudo apachectl configtest
A prescindere dai vari warning segnati, se riceviamo infine il messaggio Syntax OK possiamo procedere con il riavvio di Apache:
sudo service apache2 restart
Effettuando nuovamente la navigazione con un browser puntando all’indirizzo della nostra macchina, ci accorgeremo di non avere più la pagina di default di Apache esposta, bensì un messaggio di ServiceUnavailable . Risultato del tutto normale poiché Apache sta già funzionando da server proxy, mirando in realtà alla porta 5000 della macchina sulla quale non è ancora stata avviata la nostra applicazione .Net conKestrel.
Step#3– Spostamento Progetto & Creazione Servizio
E’ giunto ora il momento di riversare il nostro progetto compilato sul nostro server Linux.
Come anticipato nelle premesse di questa guida, uno degli strumenti più comodi per chi lavora su una macchina Windows è WinSCP, con il quale potremo trasferire files tramite SFTP.
Prima di spostare i files, sarebbe utile creare preventivamente la cartella di destinazione del progetto, che nel nostro caso si chiamerà MyCrossPlatformAppe sarà nella home della mia utenza cerini.
cd /home/cerini
mkdir MyCrossPlatformApp
Ecco che una volta connessi con WinSCP potremo spostare comodamente il progetto nella cartella appena creata anche con un semplice Drag&Drop.
Possiamo finalmente testare il corretto funzionamento della nostra soluzione crossplatform e della bontà della configurazione del reverse proxy di Apache avviando l’applicazione e facendo di conseguenza partire il server Kestrel sulla porta 5000 col comando:
dotnet MyCrossPlatformApp.dll
Visitando nuovamente col browser la nostra macchina, il messaggio di “ServiceUnavailable” sarà soltanto un lontano ricordo.
Rimane soltanto un ultimo “problema”:
l’esecuzione dell’applicazione è contestualizzata all’istanza di terminale che ha lanciato il comando dot, dunque fin quando non ne termineremo l’esecuzione con la combinazione di comandi CTRL+C, l’istanza di questo terminale sarà occupata da questo unico job, impedendoci di usarla per qualsiasi altro task.
E’qui che entrano in gioco i service di Ubuntu. Un service (o servizio se preferite in italiano) su Ubuntu costituisce la gestione regolarizzata di uno o più processi in totale autonomia dell’OS ed in background.
Trai vari parametri configurabili di un servizio, troviamo quelli che ne definiscono il tempo di esecuzione, partenza e comportamento in caso di errore, come ad esempio il riavvio od un nuovo tentativo ad una certa distanza temporale.
I servizi su Ubuntu sono facilmente gestibili con il comando service o il suo sinonimo systemctl, fornendo come parametro l’operazione da effettuare sul servizio specificato: enable, disable, stop, start, restart e status.
Creiamo dunque il file di configurazione per il servizio che si occuperà di avviare (e tenere avviata) la nostra applicazione .NET sul server.
Come in precedenza, usiamo l’editor nano per creare il suddetto file:
sudo nano/etc/systemd/system/MyCrossPlatformApp.service
Avviato l’editor del nuovo file vuoto, possiamo copiare al suo interno la seguente configurazione, salvandola infine con CTRL+O -> INVIO-> CTRL+X :
[Unit]
Description=ASP .NET Web Application
[Service]
WorkingDirectory=/home/cerini/MyCrossPlatformApp
ExecStart=/usr/bin/dotnet /home/cerini/MyCrossPlatformApp/MyCrossPlatformApp.dll
Restart=always
# Restart service after 10 seconds if the dotnet service crashes:
RestartSec=10
SyslogIdentifier=dotnet5-demo
User=www-data
Environment=ASPNETCORE_ENVIRONMENT=Production
[Install]
WantedBy=multi-user.target
Tra le config più interessanti troviamo la WorkingDirectory con cui diamo il contesto della cartella di esecuzione, ExecStart che definisce il vero e proprio comando da eseguire (dotnet + dll), Restart e RestartSec con cui definiamo il comportamento in caso di errore/crash del servizio.
Possiamo dunque abilitare il servizio e tentarne l’avvio:
sudo systemctl enableMyCrossPlatformApp
sudo systemctl startMyCrossPlatformAppt
Controlliamo infine che sia correttamente partito con:
sudo systemctl statusMyCrossPlatformApp
La prova del nove la potrete tranquillamente avere navigando come al solito dal vostro browser.
Provare per credere! E se vi sentite fortunati (e ne avete la possibilità) provate a riavviare il vostro server: il servizio avvierà la vostra applicazione .NET automaticamente una volta ripartito Ubuntu.
Articolo a cura di Luca Cerini, Senior Developer in Orbyta Tech, 07/09/2021