從 ASP.NET Core 1.x 遷移至 2.0

作者:Scott Addie

在本文中,我們會逐步引導您將現有的 ASP.NET Core 1.x 專案更新為 ASP.NET Core 2.0。 將應用程式移轉至 ASP.NET Core 2.0 可讓您充分利用許多新功能和效能改進

現有的 ASP.NET Core 1.x 應用程式是根據特定版本的專案範本。 隨著 ASP.NET Core 架構發展,其中內含的專案範本和起始程式碼也跟著演進。 除了更新 ASP.NET Core 架構之外,您還需要更新應用程式的程式碼。

必要條件

請參閱 ASP.NET Core 使用者入門

更新 Target Framework Moniker (TFM)

以 .NET Core 為目標的專案應該使用版本大於或等於 .NET Core 2.0 的 TFM。 在 .csproj 檔案中搜尋 <TargetFramework> 節點,並以 netcoreapp2.0 取代其內部文字:

<TargetFramework>netcoreapp2.0</TargetFramework>

以 .NET Framework 為目標的專案應該使用版本大於或等於 .NET Framework 4.6.1 的 TFM。 在 .csproj 檔案中搜尋 <TargetFramework> 節點,並以 net461 取代其內部文字:

<TargetFramework>net461</TargetFramework>

注意

.NET Core 2.0 提供了比 .NET Core 1.x 更大的介面區。 如果您只是因為 .NET Core 1.x 中遺漏了 API 而以 .NET Framework 為目標,以 .NET Core 2.0 為目標可能有效。

如果專案檔包含 <RuntimeFrameworkVersion>1.{sub-version}</RuntimeFrameworkVersion>,請參閱這個 GitHub 問題 \(英文\)。

更新 global.json 中的 .NET Core SDK 版本

如果您的解決方案依賴 global.json 檔案而以特定的 .NET Core SDK 版本為目標,請將其 version 屬性更新為使用電腦上安裝的 2.0 版:

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

更新套件參考

1.x 專案中的 .csproj 檔案列出專案所使用的每個 NuGet 套件。

在以 .NET Core 2.0 為目標的 ASP.NET Core 2.0 專案中,.csproj 檔案中的單一中繼套件參考會取代套件的集合:

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

中繼套件包含 ASP.NET Core 2.0 和 Entity Framework Core 2.0 的所有功能。

以 .NET Framework 為目標時,ASP.NET Core 2.0 專案應該繼續參考個別的 NuGet 套件。 將每個 <PackageReference /> 節點的 Version 屬性更新為 2.0.0。

例如,以下是以 .NET Framework 為目標的典型 ASP.NET Core 2.0 專案所使用的 <PackageReference /> 節點清單:

<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>

套件 Microsoft.Extensions.CommandLineUtils淘汰。 其仍然可供使用,但不受支援。

更新 .NET Core CLI 工具

.csproj 檔案中,將每個 <DotNetCliToolReference /> 節點的 Version 屬性更新為 2.0.0。

例如,以下是以 .NET Core 2.0 為目標的典型 ASP.NET Core 2.0 專案所使用的 CLI 工具清單:

<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>

重新命名套件目標後援屬性

1.x 專案的 .csproj 檔案使用 PackageTargetFallback 節點和變數:

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

將節點與變數都重新命名為 AssetTargetFallback

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

更新 Program.cs 中的 Main 方法

在 1.x 專案中,Program.csMain 方法看起來像這樣:

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();
        }
    }
}

在 2.0 專案中,Program.csMain 方法已經過簡化:

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();
    }
}

強烈建議您採用這個新的 2.0 模式,像Entity Framework (EF) Core 移轉這類的產品功能必須有這個模式才能運作。 例如,從 [套件管理員主控台] 視窗執行 Update-Database 或從命令列 (在轉換成 ASP.NET Core 2.0 的專案中) 執行 dotnet ef database update 會產生下列錯誤:

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.

新增組態提供者

在 1.x 專案中,若要將組態提供者新增至應用程式,必須透過 Startup 建構函式。 其中涉及的步驟包括建立 ConfigurationBuilder 的執行個體、載入適用的提供者 (環境變數、應用程式設定等等),以及初始化 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; }

上述範例載入 Configuration 成員時,會使用 appsettings.json 與所有 appsettings.{Environment}.json 檔案中符合 IHostingEnvironment.EnvironmentName 屬性的組態設定。 這些檔案的位置與 Startup.cs 的路徑相同。

在 2.0 專案中,1.x 專案固有的模板組態程式碼會在幕後執行。 例如,環境變數及應用程式設定會在啟動時載入。 對等的 Startup.cs 程式碼會縮減成為插入執行個體的 IConfiguration 初始化:

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

public IConfiguration Configuration { get; }

若要移除 WebHostBuilder.CreateDefaultBuilder 所新增的預設提供者,請叫用 ConfigureAppConfigurationIConfigurationBuilder.Sources 屬性上的 Clear 方法。 若要將提供者新增回來,請利用 Program.cs 中的 ConfigureAppConfiguration 方法:

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();

此處 \(英文\) 有前述程式碼片段中 CreateDefaultBuilder 方法所使用的組態。

如需詳細資訊,請參閱 ASP.NET Core 中的組態

移動資料庫初始化程式碼

在使用 EF Core 1.x 的 1.x 專案中,dotnet ef migrations add 這類命令會執行下列作業:

  1. Startup 執行個體具現化
  2. 叫用 ConfigureServices 方法以註冊所有具相依性導入的服務 (包括 DbContext 類型)
  3. 執行其必要工作

在使用 EF Core 2.0 的 2.0 專案中,則會叫用 Program.BuildWebHost 來取得應用程式服務。 與 1.x 不同的是,這會有叫用 Startup.Configure 的額外副作用。 如果您的 1.x 應用程式在其 Configure 方法中叫用了資料庫初始化程式碼,可能會發生未預期的問題。 例如,如果資料庫尚未存在,植入程式碼會在 EF Core 移轉命令執行前就執行程式碼。 如果資料庫尚不存在,這個問題會造成 dotnet ef migrations list 命令失敗。

請考慮在 Startup.csConfigure 方法中使用下列 1.x 植入初始化程式碼:

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

SeedData.Initialize(app.ApplicationServices);

在 2.0 專案中,將 SeedData.Initialize 呼叫移到 Program.csMain 方法:

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();

從 2.0 開始,除了建置及設定網頁主機外,並不適合在 BuildWebHost 中執行任何作業。 有關執行應用程式的任何作業都應該在 BuildWebHost 外處理 — 通常會在 Program.csMain 方法中處理。

檢閱 Razor 檢視編譯設定

更快速的應用程式啟動時間和較小的發行組合對您而言極為重要。 基於這些原因,預設會在 ASP.NET Core 2.0 中啟用 Razor 檢視編譯

已不再需要將 MvcRazorCompileOnPublish 屬性設定為 true。 除非您停用檢視編譯,否則屬性可能會從 .csproj 檔案中移除。

以 .NET Framework 為目標時,仍然需要在 .csproj 檔案中明確參考 Microsoft.AspNetCore.Mvc.Razor.ViewCompilation NuGet 套件:

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

依賴 Application Insights「啟動」功能

輕鬆安裝應用程式效能檢測很重要。 您現在可以依賴 Visual Studio 2017 工具中提供的 Application Insights「啟動」功能。

根據預設,在 Visual Studio 2017 中建立的 ASP.NET Core 1.1 專案已新增 Application Insights。 如果您不要直接使用 Application Insights SDK,請在 Program.csStartup.cs 之外,遵循下列步驟:

  1. 如果以 .NET Core 為目標,請從 .csproj 檔案中移除下列 <PackageReference /> 節點:

    <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.0.0" />
    
  2. 如果以 .NET Core 為目標,請從 Program.cs 中移除 UseApplicationInsights 擴充方法引動過程:

    public static void Main(string[] args)
    {
        var host = new WebHostBuilder()
            .UseKestrel()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseIISIntegration()
            .UseStartup<Startup>()
            .UseApplicationInsights()
            .Build();
    
        host.Run();
    }
    
  3. _Layout.cshtml 中移除 Application Insights 用戶端 API 呼叫。 它包含下列兩行程式碼:

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

如果您要直接使用 Application Insights SDK,請繼續執行這項操作。 2.0 中繼套件含有最新版本的 Application Insights,因此如果您參考的是較舊的版本,就會出現套件降級錯誤。

採用 authentication/Identity 改進功能

ASP.NET Core 2.0 具有新的驗證模型和對 ASP.NET Core Identity 的一些重大變更。 如果您在啟用個別使用者帳戶的情況下建立專案,或如果已手動新增驗證或 Identity,請參閱將驗證和 Identity 遷移至 ASP.NET Core 2.0

其他資源