ASP.NET Web API から ASP.NET Core への移行

ASP.NET Core は、ASP.NET 4.x の MVC および Web API アプリ モデルを、ASP.NET Core MVC と呼ばれる単一のプログラミング モデルに結合します。

この記事では、ASP.NET Web API 2 の概要で作成した製品コントローラーを ASP.NET Core に移行する方法について説明します。

前提条件

新しい ASP.NET Core Web API プロジェクトを作成する

  1. [ファイル] メニューで [新規作成]>[プロジェクト] の順に選択します。
  2. 検索ボックスに「Web API」と入力します。
  3. [ASP.NET Core Web API] テンプレートを選択し、 [次へ] を選択します。
  4. [新しいプロジェクトの構成] ダイアログで、プロジェクトに ProductsCore という名前を付けて、[次へ] を選択します。
  5. [追加情報] ダイアログで、次を行います。
    1. [フレームワーク][.NET 6.0 (長期的なサポート)] になっていることを確認します。
    2. [コントローラーを使用する (最小限の API を使用する場合はオフにします)] チェック ボックスがオンになっていることを確認します。
    3. [OpenAPI サポートを有効にする] チェック ボックスをオフにします。
    4. [作成] を選択します

WeatherForecast テンプレート ファイルを削除する

  1. 新しい ProductsCore プロジェクトから WeatherForecast.csControllers/WeatherForecastController.cs のサンプル ファイルを削除します。
  2. Properties\launchSettings.json を開きます。
  3. launchUrl プロパティを weatherforcast から productscore に変更します。

ASP.NET Core Web API の構成

ASP.NET Core では、App_Start フォルダーまたは Global.asax ファイルを使用しません。 web.config ファイルは公開時に追加されます。 詳細については、「web.config ファイル」を参照してください。

Program.cs ファイルは以下の通りです。

  • Global.asax を置き換えます。
  • すべてのアプリ スタートアップ タスクを処理します。

詳細については、「ASP.NET Core でのアプリケーションのスタートアップ」をご覧ください。

ASP.NET Core Program.cs ファイルのアプリケーション スタートアップ コードを次に示します。

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();

var app = builder.Build();

// Configure the HTTP request pipeline.

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

製品モデルをコピーする

  1. ソリューション エクスプローラーで、プロジェクトを右クリックします。 [追加]>[新しいフォルダー] の順に選択します。 フォルダーに「Models」という名前を付けます。
  2. Models フォルダーを右クリックします。 [追加]>[クラス] の順に選択します。 クラスに「製品」という名前を付け、[追加] を選択します。
  3. テンプレート モデル コードを次のコードに置き換えます。
namespace ProductsCore.Models
{
    public class Product
    {
        public int Id { get; set; }
        public string? Name { get; set; }
        public string? Category { get; set; }
        public decimal Price { get; set; }
    }
}

上記の強調表示されたコードにより、以下が変更されます。

  • ? 注釈が追加され、Name プロパティと Category プロパティが null 許容参照型として宣言されました。

C# 8 で紹介した null 許容機能を利用することで、ASP.NET Core では、参照型の処理においてコード フロー分析が追加され、コンパイル時の安全性を高めることができます。 たとえば、null 参照例外に対する保護を提供します。

この場合の意図は、NameCategory を null 許容型にできることです。

ASP.NET Core 6.0 プロジェクトでは、既定で null 許容参照型が有効になります。 詳細については、「null 許容参照型」を参照してください。

ProductsController をコピーする

  1. Controllers フォルダーを右クリックします。
  2. [> コントローラーの追加...] を選択します。
  3. [新規スキャフォールディング アイテムの追加] ダイアログで、[MVC コントローラー - 空][追加] を選択します。
  4. コントローラーに ProductsController という名前を付け、[追加] を選択します。
  5. テンプレート コントローラー コードを次のコードに置き換えます。
using Microsoft.AspNetCore.Mvc;
using ProductsCore.Models;

namespace ProductsCore.Controllers;

[Route("api/[controller]")]
[ApiController]
public class ProductsController : ControllerBase
{
    Product[] products = new Product[]
    {
            new Product
            {
                Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1
            },
            new Product
            {
                Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M
            },
            new Product
            {
                Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M
            }
    };

    [HttpGet]
    public IEnumerable<Product> GetAllProducts()
    {
        return products;
    }

    [HttpGet("{id}")]
    public ActionResult<Product> GetProduct(int id)
    {
        var product = products.FirstOrDefault((p) => p.Id == id);
        if (product == null)
        {
            return NotFound();
        }
        return product;
    }
}

上記の強調表示されたコードは、次のように変更され、ASP.NET Core に移行されます。

  • ASP.NET Core に存在しない次の ASP.NET 4.x コンポーネントの using ステートメントを削除します。

    • ApiController クラス
    • System.Web.Http 名前空間
    • IHttpActionResult インターフェイス
  • using ProductsApp.Models; ステートメントを using ProductsCore.Models; に変更します。

  • ルート名前空間を ProductsCore に設定します。

  • ApiControllerControllerBase に変更します。

  • using Microsoft.AspNetCore.Mvc; を追加して、ControllerBase 参照を解決します。

  • GetProduct アクションの戻り値の型を IHttpActionResult から ActionResult<Product> に変更します。 詳細については、「コントローラー アクションの戻り値の型」を参照してください。

  • GetProduct アクションの return ステートメントを次のステートメントに簡略化します。

    return product;
    
  • 次のセクションで説明する以下の属性を追加します。

    • [Route("api/[controller]")]
    • [ApiController]
    • [HttpGet]
    • [HttpGet("{id}")]

ルート指定

ASP.NET Core では、エンドポイント ルーティング ミドルウェアがミドルウェア パイプライン全体をラップする最小限のホスティング モデルが提供されるため、UseEndpoints または UseRouting に対する明示的な呼び出しを行ったり、ルートを登録したりすることなく、WebApplication に直接ルートを追加できます。

UseRouting は引き続きルート一致が発生する場所を指定するために使用できますが、UseRouting はミドルウェア パイプラインの先頭でルートを照合する必要がある場合は明示的に呼び出す必要はありません。

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();

var app = builder.Build();

// Configure the HTTP request pipeline.

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

注: ルートは、パイプラインの "最後" で、WebApplication execute に直接追加されます。

移行された ProductsController でのルーティング

移行された ProductsController には、次の強調表示された属性が含まれます。

using Microsoft.AspNetCore.Mvc;
using ProductsCore.Models;

namespace ProductsCore.Controllers;

[Route("api/[controller]")]
[ApiController]
public class ProductsController : ControllerBase
{
    Product[] products = new Product[]
    {
            new Product
            {
                Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1
            },
            new Product
            {
                Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M
            },
            new Product
            {
                Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M
            }
    };

    [HttpGet]
    public IEnumerable<Product> GetAllProducts()
    {
        return products;
    }

    [HttpGet("{id}")]
    public ActionResult<Product> GetProduct(int id)
    {
        var product = products.FirstOrDefault((p) => p.Id == id);
        if (product == null)
        {
            return NotFound();
        }
        return product;
    }
}
  • [Route] 属性では、コントローラーの属性ルーティング パターンを構成します。

  • [ApiController] 属性により、属性ルーティングは、このコントローラー内のすべてのアクションの要件になります。

  • 属性ルーティングでは、[controller][action] などのトークンがサポートされます。 実行時、各トークンはそれぞれ、属性が適用されたコントローラーまたはアクションの名前に置き換えられます。 トークンには次の利点があります。

    • ルートにハード コーディングされた文字列を使用する必要性を減らすか、不要にします。
    • 自動的な名前変更時のリファクタリングが適用された場合、ルートと、対応するコントローラーおよびアクションとの同期が確実に維持されます。
  • HTTP Get 要求は、次の属性を持つ ProductController アクションに対して有効になります。

    • [HttpGet] 属性が GetAllProducts アクションに適用されました。
    • [HttpGet("{id}")] 属性が GetProduct アクションに適用されました。

移行したプロジェクトを実行し、/api/products を参照します。 例: https://localhost:<port>/api/products。 3 つの製品の完全なリストが表示されます。 [https://www.microsoft.com](/api/products/1) を参照します。 最初の製品が表示されます。

サンプル コードを表示またはダウンロードします (ダウンロード方法)。

その他のリソース

この記事では、ASP.NET 4.x Web API から ASP.NET Core MVC に移行するために必要な手順について説明します。

サンプル コードを表示またはダウンロードします (ダウンロード方法)。

前提条件

ASP.NET 4.x Web API プロジェクトを確認する

この記事では、「ASP.NET Web API 2 の概要」で作成した ProductsApp プロジェクトを使用します。 このプロジェクトでは、基本の ASP.NET 4.x Web API プロジェクトは次のように構成されています。

Global.asax.cs で、WebApiConfig.Register が呼び出されます。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Routing;

namespace ProductsApp
{
    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            GlobalConfiguration.Configure(WebApiConfig.Register);
        }
    }
}

WebApiConfig クラスは、App_Start フォルダー内にあり、静的な Register メソッドが含まれています。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;

namespace ProductsApp
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services

            // Web API routes
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }
}

前の クラスは次のとおりです。

  • 属性ルーティングの構成。ただし、実際には使用されません。
  • ルーティング テーブルの構成。 サンプル コードでは、URL が /api/{controller}/{id} の形式と一致することを想定しています。{id}は省略できます。

以下のセクションでは、Web API プロジェクトを ASP.NET Core MVC に移行する方法について説明します。

移行先のプロジェクトを作成する

Visual Studio で新しい空のソリューションを作成し、移行する ASP.NET 4.x Web API プロジェクトを追加します。

  1. [ファイル] メニューで [新規作成]>[プロジェクト] の順に選択します。
  2. [空のソリューション] テンプレートを選択し、[次へ] を選択します。
  3. ソリューションに WebAPIMigrationという名前を付けます。 [作成] を選択します
  4. 既存の ProductsApp プロジェクトをソリューションに追加します。

移行先の新しい API プロジェクトを追加します。

  1. 新しい ASP.NET Core Web Application プロジェクトをソリューションに追加します。
  2. [新しいプロジェクトの構成] ダイアログで、プロジェクトに ProductsCore という名前を付けて、[作成] を選択します。
  3. [新しい ASP.NET Core Web アプリケーションを作成する] ダイアログで、 [.NET Core][ASP.NET Core 3.1] が選択されていることを確認します。 [API] プロジェクト テンプレートを選択し、 [作成] を選択します。
  4. 新しい ProductsCore プロジェクトから WeatherForecast.csControllers/WeatherForecastController.cs のサンプル ファイルを削除します。

以上で、ソリューションに 2 つのプロジェクトが含まれました。 以降のセクションでは、ProductsApp プロジェクトの内容を ProductsCore プロジェクトに移行する方法について説明します。

構成の移行

ASP.NET Core では、App_Start フォルダーまたは Global.asax ファイルを使用しません。 さらに、web.config ファイルは、公開時に追加されます。

Startup クラス:

  • Global.asax を置き換えます。
  • すべてのアプリ スタートアップ タスクを処理します。

詳細については、「ASP.NET Core でのアプリケーションのスタートアップ」をご覧ください。

モデルとコントローラーを移行する

次のコードは、ASP.NET Core 用に更新される ProductsController を示しています。

using ProductsApp.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Web.Http;

namespace ProductsApp.Controllers
{
    public class ProductsController : ApiController
    {
        Product[] products = new Product[] 
        { 
            new Product
            {
                Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1
            }, 
            new Product
            {
                Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M
            }, 
            new Product
            {
                Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M
            } 
        };

        public IEnumerable<Product> GetAllProducts()
        {
            return products;
        }

        public IHttpActionResult GetProduct(int id)
        {
            var product = products.FirstOrDefault((p) => p.Id == id);
            if (product == null)
            {
                return NotFound();
            }
            return Ok(product);
        }
    }
}

ProductsController を ASP.NET Core 用に更新します。

  1. Controllers/ProductsController.csModels フォルダーを元のプロジェクトから新しいプロジェクトにコピーします。
  2. コピーしたファイルのルート名前空間を ProductsCore に変更します。
  3. using ProductsApp.Models; ステートメントを using ProductsCore.Models; に更新します。

ASP.NET Core には、次のコンポーネントはありません。

  • ApiController クラス
  • System.Web.Http 名前空間
  • IHttpActionResult インターフェイス

次の変更を行います。

  1. ApiControllerControllerBase に変更します。 using Microsoft.AspNetCore.Mvc; を追加して、ControllerBase 参照を解決します。

  2. using System.Web.Http;を削除します。

  3. GetProduct アクションの戻り値の型を IHttpActionResult から ActionResult<Product> に変更します。

  4. GetProduct アクションの return ステートメントを次のように簡略化します。

    return product;
    

ルーティングを構成する

ASP.NET Core API プロジェクト テンプレートには、生成されたコードにエンドポイント ルーティング構成が含まれます。

次の UseRouting および UseEndpoints の呼び出しでは、次のことを行います。

  • ルートの一致とエンドポイントの実行をミドルウェア パイプラインに登録します。
  • ProductsApp プロジェクトの App_Start/WebApiConfig.cs ファイルを置き換えます。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseHttpsRedirection();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

ルーティングを次のように構成します。

  1. ProductsController を次の属性でマークします。

    [Route("api/[controller]")]
    [ApiController]
    

    前述の [Route] 属性では、コントローラーの属性ルーティング パターンを構成します。 [ApiController] 属性により、属性ルーティングは、このコントローラー内のすべてのアクションの要件になります。

    属性ルーティングでは、[controller][action] などのトークンがサポートされます。 実行時、各トークンはそれぞれ、属性が適用されたコントローラーまたはアクションの名前に置き換えられます。 トークンには次の利点があります。

    • プロジェクト内のマジック文字列の数が削減されます。
    • 自動的な名前変更時のリファクタリングが適用された場合、ルートと、対応するコントローラーおよびアクションとの同期が確実に維持されます。
  2. ProductsController アクションに対する HTTP Get 要求を有効にします。

    • [HttpGet] 属性を GetAllProducts アクションに適用します。
    • [HttpGet("{id}")] 属性を GetProduct アクションに適用します。

移行したプロジェクトを実行し、/api/products を参照します。 3 つの製品の完全なリストが表示されます。 [https://www.microsoft.com](/api/products/1) を参照します。 最初の製品が表示されます。

その他のリソース