Миграция с 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. Найдите в файле .csproj узел <TargetFramework> и замените его содержимое на netcoreapp2.0:
<TargetFramework>netcoreapp2.0</TargetFramework>
Проекты, предназначенные для .NET Framework, должны использовать моникер целевой платформы версии не ниже .NET Framework 4.6.1. Найдите в файле .csproj узел <TargetFramework> и замените его содержимое на 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 в файле VersionCSPROJ<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
В проектах версии 1.x в файлах .csproj использовался узел PackageTargetFallback и переменная:
<PackageTargetFallback>$(PackageTargetFallback);portable-net45+win8+wp8+wpa81;</PackageTargetFallback>
Переименуйте этот узел и переменную в AssetTargetFallback:
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
Обновление метода Main в файле Program.cs
В проектах версии 1.x метод Main в файле 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();
}
}
}
В проектах версии 2.0 метод Main в файле 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, делает следующее.
- Создает экземпляр
Startup. - Вызывает метод
ConfigureServices, чтобы зарегистрировать все службы с использованием вставки зависимостей (включая типыDbContext). - Выполняет свои требуемые задачи.
В проектах 2.0, где используется EF Core 2.0, вызывается Program.BuildWebHost, чтобы получить службы приложений. В отличие от 1.x, это также приводит к вызову Startup.Configure. Если ваше приложение 1.x вызвало код инициализации базы данных в своем методе Configure, могут возникнуть непредвиденные проблемы. Например, если база данных еще не существует, код заполнения запускается до выполнения команды миграции EF Core. Из-за этой проблемы, если база данных еще не существует, команда dotnet ef migrations list не срабатывает.
В качестве примера из версии 1.x возьмем следующий код инициализации заполнения в методе Configure из Startup.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, необходимо по-прежнему явно указывать ссылку на пакет NuGet Microsoft.AspNetCore.Mvc.Razor.ViewCompilation в файле .csproj:
<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 для Application Insights напрямую вне файлов Program.cs и Startup.cs, выполните указанные ниже действия.
Для работы с .NET Core удалите из файла
.csprojследующий узел<PackageReference />:<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.0.0" />Для работы с .NET Core удалите вызов метода расширения
UseApplicationInsightsиз файлаProgram.cs:public static void Main(string[] args) { var host = new WebHostBuilder() .UseKestrel() .UseContentRoot(Directory.GetCurrentDirectory()) .UseIISIntegration() .UseStartup<Startup>() .UseApplicationInsights() .Build(); host.Run(); }Удалите вызов API на стороне клиента Application Insights из файла
_Layout.cshtml. Этот вызов включает две строки кода:@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.