Eseguire la migrazione da ASP.NET Core 1.x alla versione 2.0

Di Scott Addie

Questo articolo illustra come aggiornare un progetto ASP.NET Core 1.x esistente ad ASP.NET Core 2.0. La migrazione dell'applicazione ad ASP.NET 2.0 Core consente di sfruttare le molte nuove caratteristiche e i miglioramenti delle prestazioni.

Le applicazioni esistenti di ASP.NET Core 1.x si basano su modelli di progetto specifico della versione. Quando il framework di ASP.NET Core si evolve, i modelli del progetto fanno la stessa cosa, così come il codice di avvio in essi contenuti. Oltre ad aggiornare il framework di ASP.NET Core, è necessario aggiornare il codice dell'applicazione.

Prerequisiti

Vedere Introduzione ad ASP.NET Core.

Aggiornare Moniker della versione di .NET Framework di destinazione (TFM, Target Framework Moniker)

I progetti destinati a .NET Core devono usare il TFM di una versione successiva o uguale a .NET Core 2.0. Cercare il nodo <TargetFramework> nel file .csproj e sostituire il testo interno con netcoreapp2.0:

<TargetFramework>netcoreapp2.0</TargetFramework>

I progetti destinati a .NET Framework devono usare il TFM di una versione successiva o uguale a .NET Framework 4.6.1. Cercare il nodo <TargetFramework> nel file .csproj e sostituire il testo interno con net461:

<TargetFramework>net461</TargetFramework>

Nota

.NET core 2.0 offre una quantità di superficie maggiore rispetto a .NET Core 1.x. Se il destinatario è .NET Framework esclusivamente a causa della mancanza di API in .NET Core 1.x, avere .NET Core 2.0 come destinatario potrebbe funzionare.

Se il file di progetto contiene <RuntimeFrameworkVersion>1.{sub-version}</RuntimeFrameworkVersion>, vedere questo problema su GitHub.

Aggiornare la versione di .NET Core SDK in global.json

Se la soluzione si basa su un global.json file per specificare una versione specifica di .NET Core SDK, aggiornarne la version proprietà in modo da usare la versione 2.0 installata nel computer:

{
  "sdk": {
    "version": "2.0.0"
  }
}

Aggiornare i riferimenti del pacchetto

Il file .csproj in un progetto di 1.x elenca ogni pacchetto NuGet usato dal progetto.

In un progetto ASP.NET Core 2.0 destinato a .NET Core 2.0, un singolo riferimento al metapacchetto nel file .csproj sostituisce la raccolta di pacchetti:

<ItemGroup>
  <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.9" />
</ItemGroup>

Tutte le funzionalità di ASP.NET Core 2.0 e di Entity Framework Core 2.0 sono incluse nel metapacchetto.

I progetti di ASP.NET Core 2.0 con destinazione .NET Framework devono fare riferimento a singoli pacchetti NuGet. Aggiornamento dell'attributo Version di ogni <PackageReference /> nodo a 2.0.0.

Ad esempio, ecco l'elenco dei <PackageReference /> nodi usati in un progetto ASP.NET Core 2.0 tipico destinato a .NET Framework:

<ItemGroup>
  <PackageReference Include="Microsoft.AspNetCore" Version="2.0.0" />
  <PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.0.0" />
  <PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="2.0.0" />
  <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="2.0.0" />
  <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0" />
  <PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.ViewCompilation" Version="2.0.0" PrivateAssets="All" />
  <PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0" />
  <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.0.0" PrivateAssets="All" />
  <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.0.0" />
  <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.0.0" PrivateAssets="All" />
  <PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="2.0.0" />
  <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.0.0" PrivateAssets="All" />
</ItemGroup>

Il pacchetto Microsoft.Extensions.CommandLineUtils è stato ritirato. È ancora disponibile ma non è supportato.

Strumenti dell'interfaccia della riga di comando di .NET Core

Nel file .csproj aggiornare l'attributo Version di ogni nodo <DotNetCliToolReference /> a 2.0.0.

Ad esempio, ecco l'elenco degli strumenti dell'interfaccia della riga di comando usati in un progetto ASP.NET Core 2.0 tipico destinato a .NET Core 2.0:

<ItemGroup>
  <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.0" />
  <DotNetCliToolReference Include="Microsoft.Extensions.SecretManager.Tools" Version="2.0.0" />
  <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0" />
</ItemGroup>

Rinominare la proprietà di Fallback di destinazione del pacchetto

Il file .csproj di un progetto 1.x ha usato un nodo PackageTargetFallback e una variabile:

<PackageTargetFallback>$(PackageTargetFallback);portable-net45+win8+wp8+wpa81;</PackageTargetFallback>

Rinominare il nodo e la variabile a AssetTargetFallback:

<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>

Aggiornare il metodo Main in Program.cs

Nei progetti di 1.x il metodo Main di Program.cs era simile al seguente:

using System.IO;
using Microsoft.AspNetCore.Hosting;

namespace AspNetCoreDotNetCore1App
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var host = new WebHostBuilder()
                .UseKestrel()
                .UseContentRoot(Directory.GetCurrentDirectory())
                .UseIISIntegration()
                .UseStartup<Startup>()
                .UseApplicationInsights()
                .Build();

            host.Run();
        }
    }
}

Nei progetti 2.0 il metodo Main di Program.cs è stato semplificato:

using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;

namespace AspNetCoreDotNetCore2App
{
    public class Program
    {
        public static void Main(string[] args)
        {
            BuildWebHost(args).Run();
        }

        public static IWebHost BuildWebHost(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>()
                .Build();
    }
}

L'adozione di questo nuovo modello 2.0 è altamente consigliabile ed è necessaria affinché le funzionalità di prodotto come le Migrazioni Entity Framework (EF) Core funzionino. Ad esempio, l'esecuzione di Update-Database dalla finestra della Console di Gestione pacchetti o di dotnet ef database update dalla riga di comando (nei progetti convertiti in ASP.NET Core 2.0) genera l'errore seguente:

Unable to create an object of type '<Context>'. Add an implementation of 'IDesignTimeDbContextFactory<Context>' to the project, or see https://go.microsoft.com/fwlink/?linkid=851728 for additional patterns supported at design time.

Aggiungere provider di configurazione

Nei progetti di 1. x viene usato il costruttore Startup per aggiungere i provider di configurazione a un'app. La procedura implica la creazione di un'istanza di ConfigurationBuilder, il caricamento di provider applicabili (variabili di ambiente, impostazioni dell'app e così via) e l'inizializzazione di un membro di IConfigurationRoot.

public Startup(IHostingEnvironment env)
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);

    if (env.IsDevelopment())
    {
        builder.AddUserSecrets<Startup>();
    }

    builder.AddEnvironmentVariables();
    Configuration = builder.Build();
}

public IConfigurationRoot Configuration { get; }

Nell'esempio precedente il membro Configuration viene caricato con le impostazioni di configurazione da appsettings.json e da un qualsiasi file appsettings.{Environment}.json corrispondente alla proprietà IHostingEnvironment.EnvironmentName. Questi file si trovano nello stesso percorso di Startup.cs.

Nei progetti 2.0 il codice di configurazione boilerplate relativo ai progetti 1. x viene eseguito in background. Le variabili di ambiente e le impostazioni dell'app vengono ad esempio caricate all'avvio. Il codice Startup.cs equivalente viene ridotto all'inizializzazione IConfiguration con l'istanza inserita:

public Startup(IConfiguration configuration)
{
    Configuration = configuration;
}

public IConfiguration Configuration { get; }

Per rimuovere i provider predefiniti aggiunti da WebHostBuilder.CreateDefaultBuilder, richiamare il metodo Clear nella proprietà IConfigurationBuilder.Sources all'interno di ConfigureAppConfiguration. Per aggiungere di nuovo i provider, usare il metodo ConfigureAppConfiguration in Program.cs:

public static void Main(string[] args)
{
    BuildWebHost(args).Run();
}

public static IWebHost BuildWebHost(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureAppConfiguration((hostContext, config) =>
        {
            // delete all default configuration providers
            config.Sources.Clear();
            config.AddJsonFile("myconfig.json", optional: true);
        })
        .Build();

La configurazione usata dal metodo CreateDefaultBuilder nel frammento di codice precedente può essere visualizzata qui.

Per altre informazioni, vedere Configurazione in ASP.NET Core.

Spostare il codice di inizializzazione del database

Nei progetti 1.x che usano EF Core 1.x, un comando come dotnet ef migrations add il seguente:

  1. Crea un'istanza dell'istanza Startup
  2. Richiama il metodo ConfigureServices per registrare tutti i servizi con inserimento di dipendenze, inclusi i tipi DbContext
  3. Esegue le attività necessarie

Nei progetti 2.0 che usano EF Core la versione 2.0 viene Program.BuildWebHost richiamato per ottenere i servizi dell'applicazione. A differenza della versione 1.x, questo ha l'effetto collaterale di richiamare Startup.Configure. Se l'app 1.x ha richiamato il codice di inizializzazione del database nel metodo Configure, possono verificarsi problemi imprevisti. Ad esempio, se il database non esiste ancora, il codice di seeding viene eseguito prima dell'esecuzione del EF Core comando Migrations. Questo problema causa l'esito negativo del comando dotnet ef migrations list se il database non esiste ancora.

Si consideri il codice di inizializzazione del seed 1.x seguente nel metodo Configure di Startup.cs:

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}");
});

SeedData.Initialize(app.ApplicationServices);

Nei progetti 2.0 spostare la chiamata SeedData.Initialize al metodo Main di Program.cs:

var host = BuildWebHost(args);

using (var scope = host.Services.CreateScope())
{
    var services = scope.ServiceProvider;

    try
    {
        // Requires using RazorPagesMovie.Models;
        SeedData.Initialize(services);
    }
    catch (Exception ex)
    {
        var logger = services.GetRequiredService<ILogger<Program>>();
        logger.LogError(ex, "An error occurred seeding the DB.");
    }
}

host.Run();

A partire dalla versione 2.0, non è una buona prassi eseguire alcuna operazione in BuildWebHost ad eccezione della compilazione e della configurazione dell'host Web. Tutto ciò che riguarda l'esecuzione dell'applicazione deve essere gestito all'esterno di BuildWebHost, in genere nel metodo Main di Program.cs.

Verificare l'impostazione di compilazione delle visualizzazioni di Razor

Tempi di avvio dell'applicazione più rapidi e aggregazioni pubblicate più piccole sono di importanza fondamentale per l'utente. Per questi motivi, la compilazione delle visualizzazioni di Razor è abilitata per impostazione predefinita in ASP.NET Core 2.0.

L'impostazione della proprietà MvcRazorCompileOnPublish su true non è più necessaria. A meno che non si disabiliti la compilazione delle visualizzazioni, la proprietà può essere rimossa dal file .csproj.

Quando la destinazione è .NET Framework, è necessario fare comunque riferimento in modo esplicito al pacchetto NuGet Microsoft.AspNetCore.Mvc.Razor.ViewCompilation nel file .csproj:

<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.ViewCompilation" Version="2.0.0" PrivateAssets="All" />

Basarsi sulle funzionalità "light-up" di Application Insights

Un semplice programma di installazione di strumentazione delle prestazioni dell'applicazione è importante. È ora possibile basarsi sulle nuove funzionalità "light-up" di Application Insights disponibili negli strumenti di Visual Studio 2017.

Per impostazione predefinita, i progetti ASP.NET Core 1.1 creati in Visual Studio 2017 hanno aggiunto Application Insights. Se non si usa Application Insights SDK direttamente, al di fuori di Program.cs e Startup.cs, seguire questa procedura:

  1. Se la destinazione è .NET Core, rimuovere il nodo <PackageReference /> seguente dal file .csproj:

    <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.0.0" />
    
  2. Se la destinazione è .NET Core, rimuovere la chiamata del metodo di estensione UseApplicationInsights da Program.cs:

    public static void Main(string[] args)
    {
        var host = new WebHostBuilder()
            .UseKestrel()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseIISIntegration()
            .UseStartup<Startup>()
            .UseApplicationInsights()
            .Build();
    
        host.Run();
    }
    
  3. Rimuovere la chiamata API lato client di Application Insights da _Layout.cshtml. Comprende le due righe di codice seguenti:

    @inject Microsoft.ApplicationInsights.AspNetCore.JavaScriptSnippet JavaScriptSnippet
    @Html.Raw(JavaScriptSnippet.FullScript)
    

Se si usa Application Insights SDK direttamente, continuare a farlo. Il metapacchetto 2.0 comprende la versione più recente di Application Insights, pertanto viene visualizzato un errore di downgrade del pacchetto se si fa riferimento a una versione precedente.

Adottare l'autenticazione e i miglioramenti di Identity

ASP.NET Core 2.0 include un nuovo modello di autenticazione e diverse modifiche significative di ASP.NET Core Identity. Se il progetto è stato creato con l'autenticazione Account utente individuali abilitata o se è stata aggiunta manualmente l'autenticazione o Identity, vedere Eseguire la migrazione di autenticazione e Identity ad ASP.NET 2.0 Core.

Risorse aggiuntive