29 dicembre 2019 16:17
Un progetto reale Blazor per imparare il nuovo framework UI
Se nell’ultimo anno non hai vissuto in un’isola deserta e ti occupi di sviluppo con tecnologie MS, saprai già cosa sia Blazor e forse concorderai con me che potrebbe essere una grande rivoluzione nel mondo delle WebApp/SPA (Single Pages Application). È vero, lo dicevano anche di Silverlight e di altri framework/plug-in/cazzilli che poi sappiamo che fine abbiano fatto.
Qui però mi sento di dire che siamo davanti a una cosa diversa e che potrebbe veramente fare la differenza ed essere lo strumento con il quale potremmo, nei prossimi 3/5 anni, avere a che fare maggiormente. Non illudiamoci che sia eterna, tutto avanza ed è giusto che ci sia un ricambio di tools/linguaggi per stare dietro alle nuove esigenze (o vogliamo rimpiangere VB6 e Cobol?).
Personalmente quando ho letto “basta JavaScript/TypeScript/jQuery e fratellini vari” e “non servirà più dover scegliere tra framework js come Angular, Vue, React”, prima mi sono asciugato le lacrime dalla commozione, e poi ho deciso che dovevo prendermi un po’ di tempo per approfondire e capire bene quanto ci sia dietro a questo nuovo framework.
Benedetta fu una lieve influenza che mi tenne in autunno 3 giorni a casa dove potei iniziare a giocarci: a 53 anni, e con 30 di IT sulle spalle, entusiasmarsi ancora per una nuova tecnologia e fare le 2 di notte finché non ti riesce di fare andare quel pezzo di codice non è del tutto scontato e soprattutto per la parte di Front End/UI pensavo ormai di essere “vecchio” e che non fosse più di mio appannaggio. Ecco, il primo grande merito di Blazor, imho è quello di ridare speranza a gente come me (dev ormai amatoriali) che è ancora possibile fare un’applicazione da zero full-stack conoscendo solo C# e HTML/CSS.

Il Progetto WST
Sono dell’avviso che per imparare una nuova tecnologia i piccoli esempi come Hello World o Counter alla fine servano poco, così come ovviamente partire con un progetto troppo grande come un CRM o una Intranet. Mi serviva quindi un progettino semplice ma che coprisse un po’ tutti gli ambiti di una app enterprise.
Visto che ormai una demo o un progetto-test senza dei Dati meteo non si può considerare tale (anche il template ufficiale di un Blazor project usa i Weather Forecast) cosa c’è di meglio che provare a implementare qualcosa che magari ogni tanto ti viene utile?
Partendo quindi dalla disponibilità dei servizi OpenData della Provincia di Bolzano e dal lavoro che avevo già iniziato lo scorso anno per un progetto su PowerBI, ho buttato giù un po’ di “pages” ognuna con una sfida diversa per quanto riguarda l’approccio al framework Blazor Server Side; ho scelto infatti il primo dei due flavours, in quanto quello client-only basato su WebAssembly è disponibile solo in preview e preferisco concentrarmi su cose che siano in RTM e usabili in produzione (se devo anche preoccuparmi dei bug delle preview siamo a posto...).
È nato quindi WST/MMA, acronimo di Weather South Tyrol/Wetter SüdTirol/Meteo AltoAdige) una webapp che potrebbe venirmi anche utile: guardare l'evoluzione della temperatura (odierna o di ieri o dell'anno scorso come paragone) per sapere come vestirsi prima di uscire per un giro in bici; verificare le condizioni di vento o neve prima di una sciata; togliersi qualche curiosità statistica per confermare o smentire teorie o leggende, ecc.

Dal menu di sinistra ecco quindi la lista delle pagine e dei vari temi riguardanti la parte tecnologica.
Pagina
|
Scopo
|
Concetti Blazor
|
Misure per Stazione
|
Ritorna la situazione “attuale” (l’ultima rilevazione, max 10 minuti fa) oppure nel passato di una singola stazione dando anche la sua posizione in due viste di GoogleMaps
|
EditForm, Validazione, one-way e two-way binding, eventi, lifecycle della pagina,
component riutilizzabili (es la card del sensore, la mappa, il Pageheading con titolo e sottotitolo). Bind vs OnChange.
|
Misure per Sensore
|
Ritorna per ogni stazione la situazione “attuale” (l’ultima rilevazione, max 10 minuti fa) oppure nel passato di un singolo sensore.
|
Custom DataGrid (una semplice table con colonne sortable)
|
Trend
|
Grafici della tendenza di un sensore secondo varie misure
|
Recupero dati server-side da un database, EF Core 3.1 Code First, Chart libreria DevExpress
|
Top Records
|
Recupero dei valori “top” di alcuni sensori
|
Uso di View e Stored Procedure con EF Core (Keyless Entity Type)
|
Mappa Stazioni
|
Mappa delle stazioni divise per tipo
|
Uso di Google Maps con JsInterop con Markers e InfoWindow.
|
Contact
|
Feedback form con spedizione Messaggio via mail
|
Validation, spedizione mail con System.Net (riuso di una mia vecchissima libreria .Net 4.5…. funziona anche quella!)
|
My 2 cents on Blazor
TL;DR => è una figata!
Scherzi a parte, scrivere una SPA con Blazor è veramente divertente e facile anche se alcune cose non sono proprio rose e fiori. L’error handling ad esempio non mi piace particolarmente in quanto talvolta devi usare la console dev del Browser (se hai settato bene CircuitOptions.DetailedErrors), talvolta esce una pagina di IISexpress altre volte devi arrangiarti a capire in che punto il tuo codice si è fermato. Dal punto di vista della velocità di sviluppo della parte puramente HTML, se fai partire l’app con CTRL-F5 (senza debug) puoi fare una specie di Edit & Continue ma il tempo di reload della SPA è abbastanza lungo (con la versione server-side) e quindi banali aggiustamenti di margin/padding, immagini, ecc. diventano fastidiosi.
To code-behind or not ? In questo progetto, per pigrizia, ho evitato di usare l’approccio con la parte .cs esterna e ho tenuto html/razor/c# tutto in un’unica pagina (@code {} )…Mah! Mi viene da sorridere quando penso che siamo partiti dalle pagine ASP classic, poi -letteralmente inorriditi dallo spaghetti code- siamo passati alle Web Forms e MVC (separazione assoluta) per poi piano piano attraverso Razor Pages e ora Blazor tornare alla commistione di elementi.
Se dobbiamo sicuramente toglierci il cappello per come Blazor sia stato concepito e riesca a funzionare così bene (un processo server-side che comunica via SignalR solo i delta di cosa è cambiato nel DOM ha del miracoloso!) c’è da dire che ogni tanto non è così facile capire il suo Lifecycle, soprattutto se infarciamo i nostri metodi di operazioni asincrone. Spesso i nostri componenti custom non sono ancora disponibili se vogliamo cambiarne qualche parameter properties (tra l’altro solo attraverso un metodo perché l’uso diretto è deprecated), e talvolta mi è capitato per disperazione di spargere una manciata di StateHasChanged() come si faceva con DoEvents in VB :-)
Infine il deploy...abituati a buttare su il singolo file aspx o cs modificato, qui le cose si fanno più complicate. È vero che il comando Publish viene molto in aiuto, ma per ogni piccolezza di modifica (a parte sui file contenuti nella wwwroot) bisogna ri-pubblicare/copiare, stoppando il sito da IIS (altrimenti la dll non è sovrascrivibile).
Javascript non si usa veramente più?
Purtroppo no… Ho cercato di limitare veramente al minimo l’uso di JSInterop, ma per la parte relativa alle Google Maps è stato d’obbligo farci ricorso. Gli stessi Admin Template (volevo usarne uno molto famoso e ricco come quelli di Metronic) sono infarciti di jQuery per operazioni banali come aprire e chiudere una sidebar o gestire il responsive del layout. Scrivere componenti Blazor js-free sarà la sfida (e forse il business) del futuro ed infatti le grosse società di componenti (DevExpress, Syncfusion, Telerik) ci si sono già buttate dentro.
Documentazione, Books, Social, Hype
Il successo di una tecnologia si misura anche da quanto materiale si trova in rete sia in termini di documentazione che di user-generated-content su social, forum, stackoverflow, ecc. E devo dire che in pochi mesi l’hype per Blazor è molto cresciuto. Ho comprato i libri di Michael Washington e di Jon Hilton per un approccio iniziale ad esempi (e per ringraziarli economicamente della loro opera di sharing). Mi è piaciuto molto questo libro di Daniel Roth, anche se è incompleto e attendo avidamente la versione definitiva, mentre ammiro molto Steve Sanderson che tiene una demo di un’ora senza un minimo di tentennamento o pausa.
Oltre Blazor
A contorno di Blazor ho rinfrescato/imparato/approfondito diverse tecnologie a conferma del fatto che ormai per scrivere una semplice webapp sono necessarie molte competenze che spaziano dal Front-End, al Back-End e alla parte sistemistica.
Entities e Biz
Ogni buon progetto dovrebbe iniziare dalla modellazione delle entità di Dominio e così ho fatto creando classi POCO relative a Stazioni, Tipi di Sensori, Misurazioni, ecc. Queste entità sono ovviamente state usate in tutti i progetti della Solutions (i servizi API, il Biz, la UI, una console app che ogni notte si salva i valori di una particolare stazione e calcola le medie/max/min giornaliere per tutte le 120 stazioni e i 15 sensori). Il Business Layer è ovviamente colui che fornisce ai vari strati le varie List<> o i singoli oggetti implementando regole e eventuali validazioni server-side.
WebAPI wrapper
I dati, come dicevo all’inizio, provengono da webservices esposti dal sito della Provincia di Bolzano. Non piacendomi però la struttura e il naming che avevano dato, ho scritto una serie di servizi REST ASP.NET Core 3 che espongono mie entità. Cosí facendo inoltre mi sono messo al riparo sapendo che i miei servizi implementano CORS (Cross-origin resource sharing, requisito obbligatorio per la versione Blazor Client Side) cosa che non ero sicuro per quelli esterni.
Ho usato solo la “nuova” System.Text.JSON al posto del collaudato e famoso JSON.Net di Newtonsoft senza particolari problemi (occhio solo che per default è case sensitive). Tutte le chiamate allo strato dei servizi avvengono quindi su una mia WebAPI che a occhio e croce introduce solo un piccolissimo overhead rispetto alla fonte originale.
Per documentarli tramite la Swagger UI ho scelto NSwag (senza nessun valido motivo rispetto a Swashbuckle).

EF Core 3.1
Dovendo/volendo usare dei dati presenti in un Database SQL ho esplorato per la prima volta a fondo l’approccio Code First. Da purista del Db, sono sempre partito con la modellazione delle tabelle e poi tramite scaffold ricavavo le entities. Oggi però sembra sia di moda e con certi vantaggi l’approccio opposto ed in effetti concentrarsi sul Domain Model e poi sul repository ha un senso. Quello che mi lascia un po’ perplesso è se le Migration che creano e soprattutto tengono aggiornato lo schema del DB siano sempre impeccabili. Con poche tabelle e senza dati dentro, tutto è sempre filato liscio, ma temo che in un db molto complicato e con l’impossibilità di spaccare integrità referenziali per fare un ALTER TABLE comincino a sorgere problemi.
Per motivi didattici ho mischiato un po’ di DataAnnotation e un po’ di Fluent Api; ovviamente la seconda è da preferire per mantenere pulite e linde le Entità e certe cose (indici, computed columns, keyless entity, ecc.) le si possono fare solo con quelle.
Bootstrap 4
Per quanto riguarda l’aspetto grafico sono partito da un semplice template di admin mischiato con quello del template standard di Microsoft entrambi basati su Bootstrap 4: il famoso framework UI sebbene faciliti molto il layout della pagina, talvolta mi lascia ancora molto perplesso su come dopo 30 anni di HTML/CSS ancora non esista qualcosa di più semplice che non dover imparare decine di nomi di classi per fare operazioni banali. È ovvio che è molto comodo fare un mb-0 per impostare un margin bottom nullo, ma quando vedi cose del genere solo per uno stupido searchbox

ti chiedi cosa sia andato storto nell’evoluzione dell’HTML/CSS. Talvolta invidio molto chi usa Wix/Squarespace e compagnia bella e il loro drag-n-drop.
Let's Encrypt
Ormai avere anche il più banale dei siti non in https sembra essere peccato mortale e quindi, non volendo investire in un certificato a pagamento, ho testato gli SSL free di Let's Encrypt con questa comodissima applicazione (Win Acme) che fa tutto lei direttamente dentro IIS. Semplicissimo e veloce.
Conclusioni
I’m in Love with Blazor! C’è poco altro da dire. Quasi sicuramente sarà la nostra scelta aziendale per un grosso progetto software che ci terrà impegnati tutto il 2020. Presumo che questo non sarà l’ultimo post sull’argomento.
UPDATE 10/3/2020:
Dopo l'uscita della ultima preview di WebAssembly ho provato a fare un piccolo progetto su un argomento ahimé scontato in questo periodo che si può installare anche come PWA. Se richiamato da browser (in https mi raccomando) può essere installato come fosse un'applicazione desktop (icona, menu start, uninstall, ecc.). Qui sotto come si presenta su Chrome e Edge Chromium.

UPDATE 15/5/2020:
Mi scocciava lasciare due domini come meteo-altoadige.it e wetter-suedtirol.it, che non avrei detto liberi, inutilizzati. Li ho quindi acquistati e associati a questa SPA. Sarà lo stimolo per andare a studiare come gestire globalization e localization in Blazor.