ASP.NET から ASP.NET Core への移行Migrate from ASP.NET to ASP.NET Core

著者: Isaac LevinBy Isaac Levin

この記事は、ASP.NET アプリを ASP.NET Core に移行するための参考ガイドです。This article serves as a reference guide for migrating ASP.NET apps to ASP.NET Core.

必須コンポーネントPrerequisites

.NET Core SDK 2.2 以降.NET Core SDK 2.2 or later

ターゲット フレームワークTarget frameworks

ASP.NET Core プロジェクトを使うと、開発者は、.NET Core と .NET Framework のどちらか一方または両方を対象にして柔軟に開発できます。ASP.NET Core projects offer developers the flexibility of targeting .NET Core, .NET Framework, or both. 最も適切なターゲット フレームワークの決定については、「サーバー アプリ用 .NET Core と .NET Framework の選択」をご覧ください。See Choosing between .NET Core and .NET Framework for server apps to determine which target framework is most appropriate.

.NET Framework を対象にする場合は、プロジェクトで個々の NuGet パッケージを参照する必要があります。When targeting .NET Framework, projects need to reference individual NuGet packages.

.NET Core を対象にすると、ASP.NET Core メタパッケージのおかげで、さまざまな明示的パッケージ参照をしなくて済みます。Targeting .NET Core allows you to eliminate numerous explicit package references, thanks to the ASP.NET Core metapackage. Microsoft.AspNetCore.App メタパッケージをプロジェクトにインストールします。Install the Microsoft.AspNetCore.App metapackage in your project:

<ItemGroup>
   <PackageReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>

メタパッケージを使うと、メタパッケージ内で参照されているパッケージはアプリでは展開されません。When the metapackage is used, no packages referenced in the metapackage are deployed with the app. .NET Core ランタイム ストアにはこれらのアセットが含まれており、パフォーマンス向上のためにプリコンパイルされています。The .NET Core Runtime Store includes these assets, and they're precompiled to improve performance. 詳細については、ASP.NET Core 用の Microsoft.AspNetCore.App メタパッケージに関する記事を参照してください。See Microsoft.AspNetCore.App metapackage for ASP.NET Core for more detail.

プロジェクトの構造の違いProject structure differences

.csproj ファイルの形式は、ASP.NET Core では簡素化されています。The .csproj file format has been simplified in ASP.NET Core. いくつかの重要な変更は次のとおりです。Some notable changes include:

  • ファイルがプロジェクトの一部と見なされるためにファイルを明示的に含める必要はありません。Explicit inclusion of files isn't necessary for them to be considered part of the project. これにより、大規模なチームで作業する場合に XML のマージが競合するリスクが軽減されます。This reduces the risk of XML merge conflicts when working on large teams.

  • 他のプロジェクトを GUID で参照することはなくなり、ファイルの読みやすさが向上します。There are no GUID-based references to other projects, which improves file readability.

  • Visual Studio でアンロードせずにファイルを編集することができます。The file can be edited without unloading it in Visual Studio:

    Visual Studio 2017 の CSPROJ の編集コンテキスト メニュー オプション

Global.asax ファイルの置換Global.asax file replacement

ASP.NET Core では、アプリをブートストラップする新しいメカニズムが導入されました。ASP.NET Core introduced a new mechanism for bootstrapping an app. ASP.NET アプリケーションのエントリ ポイントは、Global.asax ファイルです。The entry point for ASP.NET applications is the Global.asax file. ルート構成、フィルター、領域の登録などのタスクは、Global.asax ファイルで処理されます。Tasks such as route configuration and filter and area registrations are handled in the Global.asax file.

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
    }
}

このアプローチでは、アプリケーションとその展開先のサーバーが、実装を妨げるような方法で結合されます。This approach couples the application and the server to which it's deployed in a way that interferes with the implementation. 結合を切り離すため、複数のフレームワークを一緒に使うさらにクリーンな方法を提供する OWIN が導入されました。In an effort to decouple, OWIN was introduced to provide a cleaner way to use multiple frameworks together. OWIN は、必要なモジュールのみを追加するためのパイプラインを提供します。OWIN provides a pipeline to add only the modules needed. ホスティング環境は、Startup 関数を取得して、サービスとアプリの要求パイプラインを構成します。The hosting environment takes a Startup function to configure services and the app's request pipeline. Startup は、ミドルウェアのセットをアプリケーションに登録します。Startup registers a set of middleware with the application. アプリケーションは、要求ごとに、既存のハンドラーのセットに対するリンク リストのヘッド ポインターを指定して、各ミドルウェア コンポーネントを呼び出します。For each request, the application calls each of the middleware components with the head pointer of a linked list to an existing set of handlers. 各ミドルウェア コンポーネントは、要求処理パイプラインに 1 つ以上のハンドラーを追加できます。Each middleware component can add one or more handlers to the request handling pipeline. これは、新しいリストのヘッドであるハンドラーへの参照を返すことによって行われます。This is accomplished by returning a reference to the handler that's the new head of the list. 各ハンドラーは、リスト内の次のハンドラーを記憶して呼び出します。Each handler is responsible for remembering and invoking the next handler in the list. ASP.NET Core では、アプリケーションへのエントリ ポイントは Startup であり、Global.asax に依存する必要はなくなりました。With ASP.NET Core, the entry point to an application is Startup, and you no longer have a dependency on Global.asax. .NET Framework で OWIN を使うときは、パイプラインとして次のようなものを使います。When using OWIN with .NET Framework, use something like the following as a pipeline:

using Owin;
using System.Web.Http;

namespace WebApi
{
    // Note: By default all requests go through this OWIN pipeline. Alternatively you can turn this off by adding an appSetting owin:AutomaticAppStartup with value “false”. 
    // With this turned off you can still have OWIN apps listening on specific routes by adding routes in global.asax file using MapOwinPath or MapOwinRoute extensions on RouteTable.Routes
    public class Startup
    {
        // Invoked once at startup to configure your application.
        public void Configuration(IAppBuilder builder)
        {
            HttpConfiguration config = new HttpConfiguration();
            config.Routes.MapHttpRoute("Default", "{controller}/{customerID}", new { controller = "Customer", customerID = RouteParameter.Optional });

            config.Formatters.XmlFormatter.UseXmlSerializer = true;
            config.Formatters.Remove(config.Formatters.JsonFormatter);
            // config.Formatters.JsonFormatter.UseDataContractJsonSerializer = true;

            builder.UseWebApi(config);
        }
    }
}

これにより既定のルートが構成され、既定では Json 経由の XmlSerialization です。This configures your default routes, and defaults to XmlSerialization over Json. 必要に応じて、このパイプラインに他のミドルウェアを追加します (サービスの読み込み、構成設定、静的ファイルなど)。Add other Middleware to this pipeline as needed (loading services, configuration settings, static files, etc.).

ASP.NET Core は同様のアプローチを使いますが、エントリを処理するために OWIN には依存しません。ASP.NET Core uses a similar approach, but doesn't rely on OWIN to handle the entry. 代わりに、(コンソール アプリケーションと同じように) Program.csMain メソッドを通して行われ、そこから Startup が読み込まれます。Instead, that's done through the Program.cs Main method (similar to console applications) and Startup is loaded through there.

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

namespace WebApplication2
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateWebHostBuilder(args).Build().Run();
        }

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>();
    }
}

Startup は、Configure メソッドを含む必要があります。Startup must include a Configure method. Configure では、必要なミドルウェアをパイプラインに追加します。In Configure, add the necessary middleware to the pipeline. (既定の Web サイト テンプレートからの) 次の例では、拡張メソッドにより、以下をサポートするパイプラインが構成されます。In the following example (from the default web site template), extension methods configure the pipeline with support for:

  • エラー ページError pages
  • HTTP Strict Transport SecurityHTTP Strict Transport Security
  • HTTP への HTTP リダイレクトHTTP redirection to HTTPS
  • ASP.NET Core MVCASP.NET Core MVC
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseMvc();
}

ホストとアプリケーションは切り離されており、将来別のプラットフォームに柔軟に移動できます。The host and application have been decoupled, which provides the flexibility of moving to a different platform in the future.

注意

ASP.NET Core のスタートアップとミドルウェアについて詳しくは、「ASP.NET Core でのアプリケーションのスタートアップ」をご覧くださいFor a more in-depth reference to ASP.NET Core Startup and Middleware, see Startup in ASP.NET Core

構成を保存するStore configurations

ASP.NET では保存の設定がサポートされています。ASP.NET supports storing settings. これらの設定は、たとえば、アプリケーションが展開された環境のサポートに使われます。These setting are used, for example, to support the environment to which the applications were deployed. 一般的な方法は、すべてのカスタム キー/値ペアを、Web.config ファイルの <appSettings> セクションに保存するというものでした。A common practice was to store all custom key-value pairs in the <appSettings> section of the Web.config file:

<appSettings>
  <add key="UserName" value="User" />
  <add key="Password" value="Password" />
</appSettings>

アプリケーションでは、System.Configuration 名前空間内の ConfigurationManager.AppSettings コレクションを使ってこれらの設定を読み取ります。Applications read these settings using the ConfigurationManager.AppSettings collection in the System.Configuration namespace:

string userName = System.Web.Configuration.ConfigurationManager.AppSettings["UserName"];
string password = System.Web.Configuration.ConfigurationManager.AppSettings["Password"];

ASP.NET Core では、アプリケーションの構成データを任意のファイルに保存し、ミドルウェアのブートストラップの一部として読み込むことができます。ASP.NET Core can store configuration data for the application in any file and load them as part of middleware bootstrapping. プロジェクト テンプレートで使われる既定のファイルは、appsettings.json です。The default file used in the project templates is appsettings.json:

{
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  },
  "AppConfiguration": {
    "UserName": "UserName",
    "Password": "Password"
  }
}

アプリケーション内部の IConfiguration のインスタンスにこのファイルを読み込むには、Startup.cs が使われます。Loading this file into an instance of IConfiguration inside your application is done in Startup.cs:

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

public IConfiguration Configuration { get; }

アプリでは、Configuration から読み取って設定を取得します。The app reads from Configuration to get the settings:

string userName = Configuration.GetSection("AppConfiguration")["UserName"];
string password = Configuration.GetSection("AppConfiguration")["Password"];

このアプローチにはプロセスをより堅牢にする拡張機能があります。たとえば、依存性の注入 (DI) を使ってサービスとこれらの値を読み込むことができます。There are extensions to this approach to make the process more robust, such as using Dependency Injection (DI) to load a service with these values. DI アプローチは、厳密に型指定された構成オブジェクトのセットを提供します。The DI approach provides a strongly-typed set of configuration objects.

// Assume AppConfiguration is a class representing a strongly-typed version of AppConfiguration section
services.Configure<AppConfiguration>(Configuration.GetSection("AppConfiguration"));

注意

ASP.NET Core の構成について詳しくは、「ASP.NET Core の構成」をご覧ください。For a more in-depth reference to ASP.NET Core configuration, see Configuration in ASP.NET Core.

ネイティブな依存性の注入Native dependency injection

大規模で拡張性の高いアプリケーションを構築するときの重要な目標は、コンポーネントとサービスの疎な結合です。An important goal when building large, scalable applications is the loose coupling of components and services. 依存性の注入はこれを実現するための一般的な手法であり、ASP.NET Core のネイティブなコンポーネントです。Dependency Injection is a popular technique for achieving this, and it's a native component of ASP.NET Core.

ASP.NET アプリでは、開発者はサードパーティのライブラリに依存して依存性の注入を実装します。In ASP.NET apps, developers rely on a third-party library to implement Dependency Injection. Unity はそのようなライブラリの 1 つであり、Microsoft Patterns & Practices によって提供されます。One such library is Unity, provided by Microsoft Patterns & Practices.

Unity で依存性の注入を設定する例は、UnityContainer をラップする IDependencyResolver の実装です。An example of setting up Dependency Injection with Unity is implementing IDependencyResolver that wraps a UnityContainer:

using Microsoft.Practices.Unity;
using System;
using System.Collections.Generic;
using System.Web.Http.Dependencies;

public class UnityResolver : IDependencyResolver
{
    protected IUnityContainer container;

    public UnityResolver(IUnityContainer container)
    {
        if (container == null)
        {
            throw new ArgumentNullException("container");
        }
        this.container = container;
    }

    public object GetService(Type serviceType)
    {
        try
        {
            return container.Resolve(serviceType);
        }
        catch (ResolutionFailedException)
        {
            return null;
        }
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        try
        {
            return container.ResolveAll(serviceType);
        }
        catch (ResolutionFailedException)
        {
            return new List<object>();
        }
    }

    public IDependencyScope BeginScope()
    {
        var child = container.CreateChildContainer();
        return new UnityResolver(child);
    }

    public void Dispose()
    {
        Dispose(true);
    }

    protected virtual void Dispose(bool disposing)
    {
        container.Dispose();
    }
}

UnityContainer のインスタンスを作成し、サービスを登録して、HttpConfiguration の依存関係リゾルバーをコンテナー用の UnityResolver の新しいインスタンスに設定します。Create an instance of your UnityContainer, register your service, and set the dependency resolver of HttpConfiguration to the new instance of UnityResolver for your container:

public static void Register(HttpConfiguration config)
{
    var container = new UnityContainer();
    container.RegisterType<IProductRepository, ProductRepository>(new HierarchicalLifetimeManager());
    config.DependencyResolver = new UnityResolver(container);

    // Other Web API configuration not shown.
}

必要な場所に IProductRepository を挿入します。Inject IProductRepository where needed:

public class ProductsController : ApiController
{
    private IProductRepository _repository;

    public ProductsController(IProductRepository repository)  
    {
        _repository = repository;
    }

    // Other controller methods not shown.
}

依存性の注入は ASP.NET Core の一部であるため、Startup.csConfigureServices メソッドに独自のサービスを追加できます。Because Dependency Injection is part of ASP.NET Core, you can add your service in the ConfigureServices method of Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    // Add application services.
    services.AddTransient<IProductRepository, ProductRepository>();
}

Unity でそうであったように、リポジトリは任意の場所に挿入できます。The repository can be injected anywhere, as was true with Unity.

注意

依存関係の挿入について詳しくは、「依存関係の挿入」をご覧ください。For more information on dependency injection, see Dependency injection.

静的ファイルの提供Serve static files

Web 開発の重要な部分は、静的なクライアント側アセットを提供する機能です。An important part of web development is the ability to serve static, client-side assets. 静的なファイルの最も一般的な例は、HTML、CSS、Javascript、およびイメージです。The most common examples of static files are HTML, CSS, Javascript, and images. これらのファイルは、アプリ (または CDN) の公開された場所に保存され、要求によって読み込めるように参照される必要があります。These files need to be saved in the published location of the app (or CDN) and referenced so they can be loaded by a request. このプロセスは、ASP.NET Core で変更されました。This process has changed in ASP.NET Core.

ASP.NET では、静的ファイルはさまざまなディレクトリに保存され、ビューで参照されます。In ASP.NET, static files are stored in various directories and referenced in the views.

ASP.NET Core では、構成が変更されていない限り、静的ファイルは "Web ルート" ( <コンテンツ ルート>/wwwroot) に保存されます。In ASP.NET Core, static files are stored in the "web root" (<content root>/wwwroot), unless configured otherwise. ファイルは、Startup.Configure から UseStaticFiles 拡張メソッドを呼び出すことによって、要求パイプラインに読み込まれます。The files are loaded into the request pipeline by invoking the UseStaticFiles extension method from Startup.Configure:

public void Configure(IApplicationBuilder app)
{
    app.UseStaticFiles();
}

注意

.NET Framework を対象にする場合は、NuGet パッケージ Microsoft.AspNetCore.StaticFiles をインストールします。If targeting .NET Framework, install the NuGet package Microsoft.AspNetCore.StaticFiles.

たとえば、wwwroot/images フォルダー内のイメージ アセットには、ブラウザーから http://<app>/images/<imageFileName> などの場所でアクセスできます。For example, an image asset in the wwwroot/images folder is accessible to the browser at a location such as http://<app>/images/<imageFileName>.

注意

ASP.NET Core での静的ファイルの提供について詳しくは、静的ファイルに関するページをご覧ください。For a more in-depth reference to serving static files in ASP.NET Core, see Static files.

複数値の CookieMulti-value cookies

複数値の Cookie は ASP.NET Core ではサポートされていません。Multi-value cookies aren't supported in ASP.NET Core. 値ごとに Cookie を 1 つ作成します。Create one cookie per value.

部分的なアプリの移行Partial app migration

部分的にアプリを移行する方法の 1 つは、IIS サブアプリケーションを作成し、アプリの URL 構造を維持しながら ASP.NET 4.x から ASP.NET Core に特定のルートのみを移動することです。One approach to partial app migration is to create an IIS sub-application and only move certain routes from ASP.NET 4.x to ASP.NET Core while preserving the URL structure the app. たとえば、applicationHost.config ファイルからのアプリの URL 構造について考えてみます。For example, consider the URL structure of the app from the applicationHost.config file:

<sites>
    <site name="Default Web Site" id="1" serverAutoStart="true">
        <application path="/">
            <virtualDirectory path="/" physicalPath="D:\sites\MainSite\" />
        </application>
        <application path="/api" applicationPool="DefaultAppPool">
            <virtualDirectory path="/" physicalPath="D:\sites\netcoreapi" />
        </application>
        <bindings>
            <binding protocol="http" bindingInformation="*:80:" />
            <binding protocol="https" bindingInformation="*:443:" sslFlags="0" />
        </bindings>
    </site>
    ...
</sites>

ディレクトリの構造:Directory structure:

.
├── MainSite
│   ├── ...
│   └── Web.config
└── NetCoreApi
    ├── ...
    └── web.config

その他の技術情報Additional resources