Blazor Server: come passare dalle versione 6 alla versione 8… e vivere felici

Usare Blazor in hosting su Azure è veramente un incubo: occorre correre, correre, correre ad ogni cambio di release !

Recentemente ho dovuto duplicare un’applicativo Blazor scritto in versione 6, che da un bel pò vive felicemente in hosting su Azure, in un’altro hosting e…. sopresa delle sorprese… su Azure è impossibile creare uno spazio compatible con questa vecchia (ma non così vecchia… direi) versione.

Partendo dal fatto che in realtà questa affermazione non è del tutto precisa, perchè in realtà è possibile in Azure creare hosting di versioni precedenti usando qualche trucco, mi sono detto: bè già che ci siamo aggiorniamo la versione del progetto Blazor, non sarà poi tanto difficile gestire le complicazioni risultanti…..

Invece…. è stato un mezzo disastro. In Blazor 8 è sono cambiate mille cose, e gestire questo upgrade non è stato per nulla scontato.

Ecco nel seguito alcune note di lavoro che spero possano servirVi se Vi trovate nella stessa mia situazione.

Upgrade Progetto

La prima cosa da fare è aggiornare il progetto.

       <Project Sdk="Microsoft.NET.Sdk.Web">

    <PropertyGroup>
        <TargetFramework>net8.0</TargetFramework>
    </PropertyGroup>
    

Fatto questo occorre mettere mano alle versioni delle dipendenze NuGet, e aggiornarle in modo sensato in modo tale da essere compatibili con .Net 8.

Per esempio nel mio caso il progetto usa Entity Framework Core: tutti i pacchetti li ho passati alla versione 8.x

Qui c’è poco da dire: occorre armarsi di pazienza e fare gli upgrade del caso. Al 99% si tratta di fare un’upgrade all’ultime versione, ma dipende dalla complessità del progetto ovviamente.

Modifiche a _Imports.razor

Aggiungere le righe seguenti per semplificare il lavoro successivo

@using System.Net.Http.Json
@using static Microsoft.AspNetCore.Components.Web.RenderMode
@using Microsoft.AspNetCore.Components.Web.Virtualization

Passiamo a SSR

….ehm… cioè ?

In Blazor 8 è stata cambiata la modalità di rendering: ora si chiama SSR/Static Server-Side Rendering.

In pratica questo significa dire che il path seguito dalle richieste in ingresso sono variate.

Nulla di preoccupante: occorre solo mettere mano a qualche file.

Program.cs

//Inizio file
app.MapRazorComponents&lt;App&gt;()
    .AddInteractiveServerRenderMode();

....

//Verso fine file
app.MapRazorComponents&lt;App&gt;()
    .AddInteractiveServerRenderMode();

//Commentare la seguente parte: non serve più
//app.UseEndpoints(endpoints =&gt;
//{
//    endpoints.MapControllers();
//    endpoints.MapBlazorHub();
//    endpoints.MapRazorPages();
//    endpoints.MapFallbackToPage("/_Host");
//});
//app.MapControllers();
//app.MapBlazorHub();

//app.MapFallbackToPage("/_Host");
&#91;/code]

Qui ho anche aggiunto componenti server interattivi e abilitato la modalità di rendering server interattiva (ovvero il buon vecchio Blazor Server, per intenderci).

Da _Host.cshtml a App.razor

Tradizionalmente le app Blazor Server sono state servite tramite una Razor Page iniziale chiamata _Host.cshtml.

Questa fungeva da “starting-point” per la web app, ed era il posto delegato dove impostare i fogli di stile, script, ecc.

Ora è cambiato tutto (mannaggia a loro….): lo starting point ora è il componente App.razor.

Quindi occorre fare il seguente.

  1. Rinominare il file esistente in App.razor in Routes.razor
  2. Rinominare la pagina _Host.cshtml in App.razor
  3. Spostare la pagina App.razor appenda rinominata nella root del progetto.

Ora in questo file dobbiamo lavorare un pò: ecco l’aspetto finale che dovrebbe avere alla fine.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <base href="/" />
    <link rel="stylesheet" href="bootstrap/bootstrap.min.css" />
    <link rel="stylesheet" href="app.css" />
    <link rel="icon" type="image/png" href="favicon.png" />
    <HeadOutlet @rendermode ="@(new InteractiveServerRenderMode(false))" />
</head>

<body>
    <Routes @rendermode ="@(new InteractiveServerRenderMode(false))" />
    <script src="_framework/blazor.web.js"></script>
</body>

</html>

Oss.: La nuova versione di Blazor ha impostato di default il prerendering. Siccome nel mio caso non usavo questa funzionalità nemmeno sulla versione precedente allora l’ho disabilitata.

new InteractiveServerRenderMode(false)

Da site.css ad app.css

Rinominare e spostare il file come di seguito

da wwwroot/css/site.css ad wwwroot/app.css

Se presente cancelallare in alto la seguente riga, per evitare errori improvvidi.

@import url('open-iconic/font/css/open-iconic-bootstrap.min.css');
...

Rimozione markup superflui

All’inizio del file dovreste trovare una cosa del genere, che potete tranquillamente cancellare perchè non più utili

@page "/"
@using Microsoft.AspNetCore.Components.Web
@namespace BlazorMigrationDemo.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Aggiornamento del tag base

Aggiorna il tag base per puntare a "/" invece di "~/".

...
<base href="/" />
...

Gestione nuovi file script

Puoi tranquillamente rimuovere questa riga:

<script src="_framework/blazor.server.js"></script>

E sostituirla con questa.

<script src="_framework/blazor.web.js"></script>

Utilizzo componente Routes

Ricordi come hai rinominato il tuo vecchio componente App.razor in Routes.razor? Ora è arrivato il momento di usarlo !

<Routes @rendermode ="@(new InteractiveServerRenderMode(false))" />

Note Finali

So per certo che non bastano le note e osservazioni che Vi ho mostrato: infatti ci sono altri mille piccoli interventi da fare sul codice per sfruttare le nuove funzionaltià presenti in .Net 8.

Ma certamente quanto sopra Vi permette di avere un punto d’inizio, certamente funzionante in ogni sua parte.