【C#/ASP.NET】Minimal APIでWeb APIを定義してみる

# はじめに

MicrosoftのMinimal APIのチュートリアルをベースに、GET/PUT/POST/DELETEのWeb APIを定義して、動かしてみる。最後に、参考をまとめる。

# Minimal APIとは

簡略的なASP.NET APIを作成できる機能。
.NET6からサポートされている。

<b>利点</b>
ほんの数行でAPIを実装できる。GET/POST/PUT/DELETEのAPIの一例。

~~~C#
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () => "This is a GET");
app.MapPost("/", () => "This is a POST");
app.MapPut("/", () => "This is a PUT");
app.MapDelete("/", () => "This is a DELETE");

app.Run();
~~~

<b>欠点</b>
[ASP.NET MVCコントローラの一部機能はサポートされていない。
](https://docs.microsoft.com/ja-jp/aspnet/core/tutorials/min-web-api?view=aspnetcore-6.0&tabs=visual-studio#differences-between-minimal-apis-and-apis-with-controllers)


# 開発環境

- Visual Studio 2022
- ASP.NET and Web development
- .NET6

# 手順

## Web APIプロジェクトを作成する

本記事では、MinimalApiPracticeという名前のソリューションを使用しています。
下記2つの画像は[Microsoft のチュートリアル](https://docs.microsoft.com/ja-jp/aspnet/core/tutorials/min-web-api?view=aspnetcore-6.0&tabs=visual-studio#create-a-web-api-project)から引用。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156594/88bc5c90-7ae3-141c-e7a1-eb9f22708772.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156594/1cf7ff5a-0498-74f6-91c0-c0a97c90a223.png)

## 自動生成コードを確認する

Program.csに下記コードが記載されていることを確認する。
WeatherForecastというWeb APIと、SwaggerのWeb APIドキュメントが発行される。

<details><summary>自動生成コード</summary><div>

~~~C#
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

var summaries = new[]
{
    "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

app.MapGet("/weatherforecast", () =>
{
    var forecast = Enumerable.Range(1, 5).Select(index =>
       new WeatherForecast
       (
           DateTime.Now.AddDays(index),
           Random.Shared.Next(-20, 55),
           summaries[Random.Shared.Next(summaries.Length)]
       ))
        .ToArray();
    return forecast;
})
.WithName("GetWeatherForecast");

app.Run();

internal record WeatherForecast(DateTime Date, int TemperatureC, string? Summary)
{
    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
~~~

</div></details>


## アプリを実行する

### デバッカーなしで実行する(Ctrl + F5)

### ASP.NET Core SSL証明書を承認する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156594/f307cd1c-a2a5-9364-1aa3-3d155c61d2a4.png)

「はい」を選択する。

![証明書の発行.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156594/ce438436-f884-4fe0-d55e-a19314eb9315.png)
「はい」を選択する。

### ブラウザ上でSwaggerの起動を確認する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156594/b0549b27-929b-df58-02f6-b4857d51355e.png)

### GETのWeb APIを実行する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156594/984140c8-3724-fe3f-6b3c-5f9aab8d1100.png)

[Try it out]のあとに、[Execute] を実行する。Web APIの実行結果(Response)が表示される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156594/44628a32-13b3-bad1-bf5d-efd04822f934.png)

### Web APIの実行結果を確認する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156594/5cd6839f-eef3-f025-1af8-12e01cef07cf.png)


<details><summary>Web APIの実行結果</summary><div>

~~~
[
  {
    "date": "2022-02-24T01:09:03.8103012+09:00",
    "temperatureC": 19,
    "summary": "Chilly",
    "temperatureF": 66
  },
  {
    "date": "2022-02-25T01:09:03.810409+09:00",
    "temperatureC": 38,
    "summary": "Cool",
    "temperatureF": 100
  },
  {
    "date": "2022-02-26T01:09:03.8104115+09:00",
    "temperatureC": 37,
    "summary": "Balmy",
    "temperatureF": 98
  },
  {
    "date": "2022-02-27T01:09:03.8104117+09:00",
    "temperatureC": -14,
    "summary": "Cool",
    "temperatureF": 7
  },
  {
    "date": "2022-02-28T01:09:03.8104118+09:00",
    "temperatureC": -20,
    "summary": "Warm",
    "temperatureF": -3
  }
]
~~~

</div></details>

# Hello WorldのAPIを作成する

## 自動生成コードを書き換える

下記コードに変更する。

~~~~C#
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () => "Hello World!");

app.Run();
~~~~

## 起動時のURLからSwaggerを除く

やり方は2通り。

<b>(1)lanchSetting.jsonを直接編集する方法</b>

[Properties]->[launchSettings.json]を選択する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156594/adf087de-312d-572c-e55e-5918317de02d.png)

"launchUrl": "swagger"が2つあるため、消す。

<details><summary>launchSettings.json</summary><div>

~~~
{
  "$schema": "https://json.schemastore.org/launchsettings.json",
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:54276",
      "sslPort": 44381
    }
  },
  "profiles": {
    "MinimalApiPractice": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "swagger",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      },
      "applicationUrl": "https://localhost:7247;http://localhost:5247",
      "dotnetRunMessages": true
    },
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "launchUrl": "swagger",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}
~~~

</div></details>

<b>(2)デバックのプロパティからlanchSetting.jsonを編集する</b>

[デバック]->[プロパティ]を開く。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156594/0ae95b90-781f-a498-e064-12ab0ae2cd59.png)

[プロファイルの起動]->[URLの欄]からswaggerを消す。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156594/c3bc36ce-6130-0197-132e-4708c2b4e0d3.png)

ソリューション名、IIS Expressのそれぞれから削除する。

## アプリを実行する

<b>成功時</b>

ブラウザ画面に下記文字列が出力される。

~~~
Hello World!
~~~

<b>失敗時</b>

例)
起動時のURLからSwaggerの設定を除外し忘れた場合、404になる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156594/3a7aaad7-0d01-fad1-c6f4-8aaee68e4cb3.png)




# Swaggerを設定する

SwaggerからAPIを実行するため、Swaggerの設定を戻す。
コメントの記載がある箇所が追加したコード。

~~~~~C#
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.MapGet("/", () => "Hello World!");
app.Run();
~~~~~

起動時のURLからSwaggerにSwaggerを追加する。

Swaggerの画面は下記の通り。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156594/982a87a2-5bfc-5566-db3a-bb24b32ad95b.png)


# GET/PUT/POST/DELETEのAPIを定義する

使用したコードは下記の通り

~~~~C#
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

// Web API Definition 
app.MapGet("/testGet", () => "This is a GET");
app.MapPost("/testPost", () => "This is a POST");
app.MapPut("/testPut", () => "This is a PUT");
app.MapDelete("/testDelete", () => "This is a DELETE");

app.Run();
~~~~

Swaggerの画面は下記の通り。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156594/fa34dd36-3624-810a-c4ad-3126d4505610.png)

それぞれのAPI 実行結果は下記の通り。

| No | Request URL| Response body |
|:-|:-|:-|
|1  |https://localhost:7247/testGet|This is a GET|
|2  |https://localhost:7247/testPost|This is a POST|
|3  |https://localhost:7247/testPut|This is a PUT|
|4  |https://localhost:7247/testDelete|This is a DELETE|



# 参考

[Minimal API の概要](https://docs.microsoft.com/ja-jp/aspnet/core/fundamentals/minimal-apis?view=aspnetcore-6.0)
[チュートリアル: ASP.NET Core で Minimal Web API を作成する](https://docs.microsoft.com/ja-jp/aspnet/core/tutorials/min-web-api?view=aspnetcore-6.0&tabs=visual-studio)
[ASP.NET Core、最小限の API、.NET 6 を使用して Web アプリとサービスを作成する](https://docs.microsoft.com/ja-jp/learn/paths/aspnet-core-minimal-api/)