in ASPNET Core, Informatica, Programmazione

Migrazione da Asp.Net Core 5 a Asp.Net Core 6

Siamo ormai arrivati al rilascio di .Net Core 8.0 che avverrà nelle prossime settimane. Se al momento sono ancora presenti applicazioni sviluppate in ASP.Net 5, l’aggiornamento che preferisco è quello a ASP.Net 6 in modo da essere pronti al prossimo rilascio LTS.

Attualmente ritengo che non sia necessario passare direttamente alla versione 7, dal momento che la versione 8 è in uscita a breve. Per le versioni che sono già state migrate alla versione 8, in un prossimo post vedremo quali saranno i passi da effettuare.

Il passaggio di versione è composto da una serie di passi che verrano descritti all’interno di questo post.

Il primo passo riguarda l’aggiornamento del progetto, modificando il target framework all’interno del file .csproj:

<PropertyGroup>
    <!-- <TargetFramework>net5.0</TargetFramework> -->
    <TargetFramework>net6.0</TargetFramework>
    
</PropertyGroup>

In questo modo viene impostato il progetto come progetto nativo ASP.Net Core 6.0. Siamo quindi pronti per effettuare l’aggiornamento dei pacchetti nuget in modo da essere aggiornati al nostro target framework. Per poter effettuare l’aggiornamento è sufficiente posizionarsi all’interno di Strumenti -> Gestione Pacchetti Nuget -> Aggiornamenti.

Ad esempio in questa fase verranno aggiornati automaticamente i pacchetti relativi ad entity framework e quelli legati a Identity.

In ASPNet.Core 5 la configurazione dell’applicazione veniva gestita all’interno di due file separati: Program.cs e Startup.cs. In ASPNet.Core 6 invece tutto viene gestito all’interno del file Program.cs.

Normalmente all’interno del progetto rinomino il file Program.cs in Program.old e Startup.cs a Startup.old, in modo da mantere comunque un backup delle configurazioni precedenti.

La struttura del file Program.cs nella versione ASP.Net Core 5:

public class Program
{
      public static void Main(string[] args) {
            CreateHostBuilder(args).Build().Run();
      }
      public static IHostBuilder CreateHostBuilder(string[] args) {
            return Host.CreateDefaultBuilder(args).
            ConfigureWebHostDefaults(x => x.UseStartup <Startup> ());
      }
}

La struttura del file Startup.cs nella versione ASP.Net Core 5:

public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.UseResponseCompression();
    }
}

La struttura del file Program.cs di un nuovo progetto ASP.Net Core 6 :

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Come possiamo vedere la configurazione viene effettuata creando il builder, associandogli i vari services che poi vengono attivati al momento della creazione/run dell’app.

Vediamo quindi le principali differenze tra i due metodi configurazione.

Program.cs in ASP.NET Core 5

public class Program
{
      public static void Main(string[] args) {
            CreateHostBuilder(args).Build().Run();
      }
      public static IHostBuilder CreateHostBuilder(string[] args) {
            return Host.CreateDefaultBuilder(args).
            ConfigureWebHostDefaults(x => x.UseStartup <Startup> ());
      }
}

Si tratta in pratica di una console applicazione all’interno della quale viene richiamato il metodo CreateHostBuilder.

Program.cs in ASP.NET Core 6

var builder = WebApplication.CreateBuilder(args);
// Add services to the container
builder.Services.AddControllers();
var app = builder.Build();
// Configure the HTTP request pipeline
app.UseAuthorization();
app.MapControllers();
app.Run();

Come si può notare la configurazione viene semplificata, creando il builder e da questo l’app che viene eseguita utilizzando app.Run().

Aggiunta di un middleware in ASP.NET Core 5

L’aggiunta di un middleware passa dall’utilizzo della classe Startup. Nell’esempio viene aggiunto il middleware che consente di aggiungere la compressione nelle risposte:

public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.UseResponseCompression();
    }
}

Aggiunta middleware in ASP.NET Core 6

Nella nuova versione l’aggiunta avviene utilizzando:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseResponseCompression();
app.Run();

Sicuramente molto piu leggibile e tutta all’interno dell’unico file Program.cs.

Aggiunta di services in ASP.NET Core 5

Anche l’aggiunta di service all’interno di ASP.NET Core 5 passa dal file Startup.cs:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        // Add built-in services
        services.AddMemoryCache();
        services.AddRazorPages();
        services.AddControllersWithViews();
        // Add a custom service
        services.AddScoped<IProductRepository, ProductRepository>();
    }
}

in particolare dal metodo ConfigureServices che accetta in ingresso tramite DI , IServiceCollections.

Aggiunta di services in ASP.NET Core 6

Nell’ottica della semplificazione, nella versione 6 ci troviamo di fronte alla registrazione effettuata inline all’interno dell’unico file Program.cs:

var builder = WebApplication.CreateBuilder(args);
// Add built-in services
builder.Services.AddMemoryCache();
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
// Add a custom service
builder.Services.AddScoped<IProductRepository, ProductRepository>();
var app = builder.Build();

Infine anche la fase di logging è stata semplificata, e la configurazione può essere effettuata direttamente nel file Program.cs:

var builder = WebApplication.CreateBuilder(args);
//Clear default logging providers
builder.Logging.ClearProviders();
//Code to add services to the container
builder.Logging.AddConsole();
var app = builder.Build();

Esitono ancora tre punti da tenere in considerazione:

  • abilitazione dei nullable
  • abilitazione degli implicit using
  • modifica dei namespaces

All’interno del file .csproj è possibile abilitare i nullable e gli implicit using usando:

<PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

impostando il valori Nullable e di ImplicitUsings a enable. In un prossimo post vedremo il loro significato.

Per quanto riguarda la modifica dei namespaces (anche se non è necessaria) è possibile modifiare le classi nel seguente modo:

// Old version
namespace CoolApplication
{
    public class User
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
    }
}

// New version
namespace CoolApplication;

public class User
{
    public int Id { get; set; }
    public string FirstName { get; set; }
}

Impostando i namespaces direttamente all’inizio del file, senza la necessità di includere tutta la classe.