ASP.NET Core Web APIのバージョン管理

## はじめに

Web APIをバージョンアップする際に、互換性の無いAPIに変更したいケースが出てきます。

例えば

```
GET /api/products/
```

というAPIがあったとします。現在動いているクライアント側に影響を与えないようにするには、

```
GET /api/productsV2/
```

など別の名前にするのが手取り早いですが、大量のAPIのあるアプリだとメンテナンスが煩雑となりあまり良い方法とは言えません。

最初からバージョン管理を意識した設計をしておく方がなにかと都合が良いです。

```
GET /api/v1/products/
```
```
GET /api/v2/products/
```

のようにするのが一般的なようです。
ASP.NET Core Web APIでも、バージョン管理を簡単に行える方法が用意されているので、ここではそれを簡単に説明します。

※ ここでは.NET 6 での例を示します。

## パッケージのインストール

`Microsoft.AspNetCore.Mvc.Versioning`をNugetパッケージマネージャを使用してインストールします。

1. ソリューションエクスプローラーで、プロジェクトを右クリックし「NuGetパッケージの管理(N)...」を選択します。

2. 参照タブをクリックし、検索欄に`Microsoft.AspNetCore.Mvc.Versioning`を入力します。

3. 検索結果に、`Microsoft.AspNetCore.Mvc.Versioning`が表示されるので、これを選択します。

4. 右側のペインにインストールボタンが表示されるので、インストールボタンをクリックします。

5. 変更のプレビューダイアログで「OK」ボタンをクリックします。

6. ライセンスの同意ダイアログで「I Accept」ボタンをクリックします。

これで、`Microsoft.AspNetCore.Mvc.Versioning` パッケージがプロジェクト参照に追加されます。

## バージョン管理サービスを構成する

次にWeb API のプロジェクトの Program.cs を以下のように変更します。


```cs
//  usingを追加
using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

// 次の行を追加
builder.Services.AddApiVersioning(options =>
{
    options.ReportApiVersions = true;
    options.DefaultApiVersion = new ApiVersion(1, 0);
});

var app = builder.Build();

// 以下省略
```

ReportAPIVersions プロパティを trueにすると、API は応答ヘッダーでバージョンを返すことができます。このオプションをオンにして API を呼び出すと、api-supported-versionにバージョン番号が設定されます。

![2022-11-13 14_24_28-https___localhost_7174_api_v1_weatherforecast.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29415/c374fcb2-9e87-15b1-0573-2e8052eff02e.png)



## APIにバージョニングを適用する

ここでは、Web APIのプロジェクトを新規作成した時に、自動で作成される `WeatherForecastController`を例に取りましょう。

まずは、ControllersフォルダにV1フォルダを作成し、`WeatherForecastController.cs`を移動します。

これらの操作をソリューションエクスプローラーからやると、名前空間も自動で変更してくれます。

```cs
namespace WebApiExample.Controllers.V1
 {
    ...
```

このコントローラクラスにバージョニングを適用します。

```cs
    [ApiController]
    [ApiVersion("1.0")]
    [Route("api/v{version:apiVersion}/[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        ...

```

[ApiVersion]属性を追加し、[Route]属性を変更します。

## 動かしてみる

F5キーを押してデバッグしてみます。ブラウザが起動するので、ここで以下のURLを指定します。

```
https://localhost:7174/api/v1/weatherforecast
```

※ 7174のポート番号は環境により異なるかもしれません。

ブラウザにjsonが表示されれば成功です。

![2022-11-13 11_19_39-https___localhost_7174_api_v1_weatherforecast - 個人 - Microsoft​ Edge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29415/881f11d6-c0b0-ea1c-2c3a-61bebf5430f3.png)


## 終わりに

とても簡単にAPIのバージョン管理ができますね。
Version2を追加するならば、V2 フォルダを作成し、そこに、Version2用の`WeatherForecastController.cs`を追加すれば良いことになります。
ファイル名やクラス名を変更する必要はありませんので管理がとても楽になります。


## おまけ

Program.csを以下のようにすれば、URLではなく、QueryStringやHeaderでバージョン情報を指定することもできるみたいです。

```cs
using Microsoft.AspNetCore.Mvc.Versioning;

... 略 ...

builder.Services.AddApiVersioning(options =>
{
    options.ReportApiVersions = true;
    options.DefaultApiVersion = new ApiVersion(1, 0);
    options.ApiVersionReader = ApiVersionReader.Combine(
        new QueryStringApiVersionReader("api-version"),
        new HeaderApiVersionReader("X-version")
    );
});
```


（僕はやったことないので、興味ある方は試してみてください。）