从 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 核心框架的发展,项目模板和它们中包含的初学者代码也是如此。 除了更新 ASP.NET Core 框架之外,还需要更新应用程序的代码。

先决条件

请参阅 ASP.NET Core 入门

更新目标框架名字对象 (TFM)

面向 .NET Core 的项目应使用大于或等于 .NET Core 2.0 的版本 TFM 。 查找<TargetFramework>节点在.csproj文件中,并将其内部文本替换为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"
  }
}

更新包引用

.csproj 1.x 项目中的文件列出了项目使用的每个 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 的所有功能都包含在元包中。

ASP.NET 面向 .NET Framework 的 Core 2.0 项目应继续引用单个 NuGet 包。 将 Version 每个 <PackageReference /> 节点的属性更新为 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 CLI 工具

.csproj 文件中,将 Version 每个 <DotNetCliToolReference /> 节点的属性更新为 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>

重命名软件包目标回退属性

.csproj 1.x 项目的文件使用了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.cs 方法已被简化: Main

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 模式,并且需要使用 实体框架(EF)核心迁移 等产品功能才能正常工作。 例如,从包管理器控制台窗口运行Update-Database或从命令行运行dotnet ef database update(在转换为 ASP.NET Core 2.0 的项目上)将生成以下错误:

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

前面的示例从appsettings.json加载配置设置,并从匹配IHostingEnvironment.EnvironmentName属性的任何appsettings.{Environment}.json文件中加载Configuration成员。 这些文件的位置与Startup.cs的路径相同。

在 2.0 项目中,1.x 项目固有的样本配置代码在幕后运行。 例如,在启动时加载环境变量和应用设置。 等效Startup.cs代码被简化为IConfiguration,通过注入实例进行初始化:

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

public IConfiguration Configuration { get; }

若要删除由WebHostBuilder.CreateDefaultBuilder添加的默认提供程序,请在ConfigureAppConfiguration内部的IConfigurationBuilder.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 的项目中,命令 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 命令失败。

请考虑以下 1.x 种子初始化代码在Startup.csConfigure方法中:

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 开始,除了生成和配置 Web 主机之外,不建议在 BuildWebHost中执行任何操作。 任何与运行应用程序相关的内容都应该在 BuildWebHost 外部处理,通常在 Program.cs 中的 Main 方法中进行。

查看 Razor 视图编译设置

更快的应用程序启动时间和较小的已发布捆绑包对你至关重要。 出于这些原因, Razor 视图编译 默认在 ASP.NET Core 2.0 中启用。

不再需要将 MvcRazorCompileOnPublish 属性设置为 true。 除非禁用视图编译,否则该属性可能会从 .csproj 文件中删除。

面向 .NET Framework 时,仍需显式引用 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 “亮起”功能。

默认情况下,ASP.NET Visual Studio 2017 中创建的 Core 1.1 项目添加了 Application Insights。 如果没有直接在Program.csStartup.cs环境中使用 Application Insights SDK,请执行以下步骤:

  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,因此,如果引用较旧版本,将显示包降级错误。

采用身份验证/Identity 改进

ASP.NET Core 2.0 具有新的身份验证模型,对 ASP.NET Core Identity进行了大量重大更改。 如果您在创建项目时启用了个人用户帐户,或者您已手动添加身份验证,请参阅 迁移身份验证和 Identity 到 ASP.NET Core 2.0

其他资源