Миграция с 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.

Обновление моникера целевой платформы (TFM)

Проекты, предназначенные для .NET Core, должны использовать моникер целевой платформы версии не ниже .NET Core 2.0. <TargetFramework> Найдите узел в файле и замените его внутренний .csproj текст netcoreapp2.0следующим:

<TargetFramework>netcoreapp2.0</TargetFramework>

Проекты, предназначенные для .NET Framework, должны использовать моникер целевой платформы версии не ниже .NET Framework 4.6.1. <TargetFramework> Найдите узел в файле и замените его внутренний .csproj текст net461следующим:

<TargetFramework>net461</TargetFramework>

Примечание.

.NET Core 2.0 обеспечивает гораздо большую контактную зону по сравнению с .NET Core 1.x. Если вы используете .NET Framework только из-за отсутствия нужных API в .NET Core 1.x, скорее всего, .NET Core 2.0 удовлетворит ваши потребности.

Если файл проекта содержит <RuntimeFrameworkVersion>1.{sub-version}</RuntimeFrameworkVersion>, см. эту проблему на GitHub.

Обновление версии пакета SDK для .NET Core в global.json

Если решение использует global.json файл для целевой версии пакета SDK для .NET Core, обновите его version свойство, чтобы использовать версию 2.0, установленную на компьютере:

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

Обновление ссылок на пакеты

Файл .csproj в проекте 1.x перечисляет каждый пакет NuGet, используемый проектом.

В проекте ASP.NET Core 2.0, предназначенном для .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 Core 2.0, предназначенных для .NET Framework, по-прежнему должны использоваться ссылки на отдельные пакеты NuGet. Измените значение атрибута Version каждого узла <PackageReference /> на 2.0.0.

Например, вот список узлов <PackageReference />, используемых в типичном проекте ASP.NET Core 2.0, предназначенном для .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>

Пакет Microsoft.Extensions.CommandLineUtils был снят с учета. Он по-прежнему доступен, но не поддерживается.

Обновление средств CLI для .NET Core

.csproj В файле обновите Version атрибут каждого <DotNetCliToolReference /> узла до версии 2.0.0.

Например, вот список средств CLI, используемых в типичном проекте ASP.NET Core 2.0, предназначенном для .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>

Переименование свойства PackageTargetFallback

Файл .csproj проекта 1.x использовал PackageTargetFallback узел и переменную:

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

Переименуйте этот узел и переменную в AssetTargetFallback:

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

Обновление метода Main в файле Program.cs

В проектах Main 1.x метод Program.cs выглядел следующим образом:

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

В проектах Main 2.0 метод Program.cs был упрощен:

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 из консоли диспетчера пакетов или команды 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; }

В примере выше происходит загрузка элемента 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 поставщиков по умолчанию, вызовите метод Clear для свойства IConfigurationBuilder.Sources внутри ConfigureAppConfiguration. Чтобы добавить поставщиков ConfigureAppConfiguration обратно, используйте метод в 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();

Конфигурацию, используемую в предыдущем фрагменте кода методом CreateDefaultBuilder, можно посмотреть здесь.

Дополнительные сведения см. в разделе Конфигурация в ASP.NET Core.

Перенос кода инициализации базы данных

В проектах 1.x с помощью EF Core 1.x команда, например dotnet ef migrations add следующая:

  1. Создает экземпляр Startup.
  2. Вызывает метод ConfigureServices, чтобы зарегистрировать все службы с использованием вставки зависимостей (включая типы DbContext).
  3. Выполняет свои требуемые задачи.

В проектах 2.0, использующих EF Core 2.0, Program.BuildWebHost вызывается для получения служб приложений. В отличие от 1.x, это также приводит к вызову Startup.Configure. Если ваше приложение 1.x вызвало код инициализации базы данных в своем методе Configure, могут возникнуть непредвиденные проблемы. Например, если база данных еще не существует, начальный код запускается до EF Core выполнения команды Migrations. Из-за этой проблемы, если база данных еще не существует, команда dotnet ef migrations list не срабатывает.

Рассмотрим следующий код начальной инициализации 1.x в методе ConfigureStartup.cs:

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

SeedData.Initialize(app.ApplicationServices);

В проектах 2.0 переместите SeedData.Initialize вызов Main метода 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();

Начиная с версии 2.0, делать в BuildWebHost что-либо помимо сборки и настройки веб-узла не рекомендуется. Все, что касается работы приложения, должно обрабатываться вне BuildWebHost —обычно в методе MainProgram.cs.

Проверка параметра компиляции представлений Razor

Сокращение времени запуска приложений и уменьшение размеров публикуемых пакетов крайне важны. По этой причине в ASP.NET Core 2.0 по умолчанию включена компиляция представлений Razor.

Присваивать свойству MvcRazorCompileOnPublish значение true больше не нужно. Если вы не отключите компиляцию представлений .csproj , свойство может быть удалено из файла.

При выборе платформа .NET Framework необходимо явно ссылаться на Microsoft.AspNetCore.Mvc.Razor. ViewCompilation NuGet package in your .csproj file:

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

Использование подсветки функций Application Insights

Простота настройки инструментария для обеспечения производительности приложений имеет большое значение. Теперь вам доступны новые функции подготовки Application Insights в составе средств Visual Studio 2017.

При создании проектов ASP.NET Core 1.1 в Visual Studio 2017 служба Application Insights добавлялась по умолчанию. Если вы не используете пакет SDK для приложений Аналитика напрямую, за пределами Program.cs и Startup.csвыполните следующие действия.

  1. Если вы используете .csproj .NET Core, удалите следующий <PackageReference /> узел из файла:

    <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.0.0" />
    
  2. Если целевой UseApplicationInsights объект .NET Core, удалите вызов метода расширения из Program.cs:

    public static void Main(string[] args)
    {
        var host = new WebHostBuilder()
            .UseKestrel()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseIISIntegration()
            .UseStartup<Startup>()
            .UseApplicationInsights()
            .Build();
    
        host.Run();
    }
    
  3. Удалите вызов _Layout.cshtmlAPI на стороне клиента Аналитика приложения. Этот вызов включает две строки кода:

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

Если вы используете пакет SDK для Application Insights напрямую, продолжайте делать это. Метапакет версии 2.0 включает в себя последнюю версию Application Insights, поэтому при попытке сослаться на более старую версию возникает ошибка понижения уровня пакета.

Внедрение улучшений проверки подлинности или Identity

В ASP.NET Core 2.0 реализована новая модель проверки подлинности и внесен ряд важных изменений в ASP.NET Core Identity. Если при создании проекта вы включили отдельные учетные записи пользователей либо вручную добавили проверку подлинности или Identity, см. сведения на странице Миграция на другой метод проверки подлинности и Identity в ASP.NET Core 2.0.

Дополнительные ресурсы