Minimal API入門:C#とASP.NET Coreで始めるシンプルなWeb API開発

はじめに

近年、C#でWeb APIを実装する方法として注目されているのがMinimal APIです。
これはASP.NET Coreに追加された新機能で、従来のControllerを使わずにエンドポイントを記述できます。

コード量は非常に少ない一方で、ASP.NETの豊富な機能(ミドルウェア、認証、DIなど)はそのまま利用可能です。
そのため、小さなAPIから本格的な開発まで、幅広い用途に対応できます。

今回はC#やASP.NET Core初心者でも気軽に体験できるよう、簡単なサンプルから、本番のAPIサーバーに適用できる構成の作り方までひと通り確認してみます。

環境構築

今回はWindows環境で、Visual Studio Codeで開発する場合を想定します。

  1. .NET SDKをインストールする
  2. VSCodeに拡張機能「C# Dev Kit」を追加する
  3. 空のフォルダを作成し、VSCodeで開く
  4. VSCodeターミナルを起動(Ctrl+Shift+@)し、以下のコマンドを入力する
dotnet new web -n <プロジェクト名>
cd <プロジェクト名>

dotnet new webを実行すると、Minimal API形式のASP.NET Coreプロジェクトが生成されます。
このテンプレートが、そのままシンプルなAPIの土台になります。

Minimal APIの基本

まずは、作成されたProgram.csを以下のように編集します。

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

// リソース'/'にGETされたときの処理
app.MapGet("/", () =>
{
    // ステータスコード200(OK)とJSONボディを返す
    return Results.Ok(new { message = "Hello World" });
});

app.Run();

アプリケーションを実行し、ブラウザで http://<your-host>:5220/ にアクセスするとJSONが表示されます。
※ポート番号は環境によって異なる場合があります。
これが最小構成のMinimal APIです。

レスポンス制御

Minimal APIでは Results を使ってHTTPレスポンスを作ります。

Results.Ok(object? value) // 200
Results.Created(string uri, object? value)  // 201 uriはLocationヘッダーの値
Results.BadRequest(object? error) // 400
Results.InternalServerError() // 500
Results.StatusCode(int statusCode) // 指定のステータス

基本的には、オブジェクトを渡せばJSONとして返却されます。
ASP.NET Coreが自動的にシリアライズとContent-Typeの設定を行います。

パラメータの取得

パスやクエリ文字列から値を取得できます。
ルート定義と引数名が一致していれば自動的にバインドされます。

// URL例:/users/1?page=2
app.MapGet("/users/{id}", (int id, int? page) =>
{
    return Results.Ok(new { id, page });
    // レスポンスボディ: {"id":1,"page":2}
});

JSONボディの取得

ASP.NET Coreの機能で、JSONは自動でデシリアライズされます。

//リクエストボディ例:'{ "id": 34,  "name": "Name" }'
app.MapPost("/users", (User user) => Results.Created($"/users/{user?.Id}", user));

app.Run();

// デシリアライズ用クラス
public record User(int Id, string Name);

HttpContextの取得

ASP.NET CoreのHttpContextを取得して、もっと複雑な処理も可能です。
以下はレスポンスヘッダをセットする例です。

app.MapGet("/", (HttpContext context) =>
{
    // レスポンスの Cache-Control ヘッダを設定
    context.Response.Headers.CacheControl = $"public,max-age=3600";
    // レスポンスの独自ヘッダを設定
    context.Response.Headers["X-Custom-Header"] = "XXXXX";
    return Results.Ok(new { message = "OK" });
});

エンドポイントのグループ化とファイル分離

機能が増えてくると、すべてをProgram.csに書くのは管理が難しくなります。
エンドポイントをグループ化したり、拡張メソッドを使ってファイルを分割したりすることで、規模が大きくなっても構造を保ちやすくなります。

グループ化

Minimal APIでは、同じURLプレフィックスを持つエンドポイントを MapGroup を使ってまとめることができます。
これにより、APIの構造が整理され、読みやすくなります。

例えば users リソースのエンドポイントを定義する場合、次のように書くことができます。

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

// 'users' リソースのグループ
var users = app.MapGroup("/users");

// GET /users/{id}
users.MapGet("/{id}", (int id) => Results.Ok(id));
// POST /users
users.MapPost("", (string user) => Results.Created($"/users/{user}", user));

app.Run();

拡張メソッド

拡張メソッドを使うと、エンドポイント定義をProgram.csから別ファイルに移すことができます。

例として、プロジェクト内にMapUserEndpointExtensions.csを作成します。

public static class MapUserEndpointExtensions
{
    // WebApplicationを拡張する
    public static void MapUserEndpoints(this WebApplication app)
    {
        // リソース'users'のグループ
        var users = app.MapGroup("/users");

        // GET /users/{id}
        users.MapGet("/{id}", (int id) => Results.Ok(id));
        // POST /users
        users.MapPost("", (string user) => Results.Created($"/users/{user}", user));
    }
}

Program.csにて、先ほど作成した MapUserEndpoints を呼び出します。

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

// 拡張メソッドを呼び出す
app.MapUserEndpoints();

app.Run();

さいごに

Minimal APIは、C#でWeb APIを実装する際の有力な選択肢です。
記述は簡潔ですが、ASP.NET Coreの基盤はそのまま利用でき、複雑な要件も思いのままです。
C#でAPI開発を検討している方は、一度試してみてはいかがでしょうか。

株式会社SPで一緒に働いてみませんか?

SPはエンジニアの成長を大切にする会社です。

ご興味ある方は一度気軽な雰囲気で、カジュアル面談はいかがでしょうか?

どのような課題を
解決したいですか?

株式会社SPでは、お客様の取り組みに寄り添いながら、
課題解決を伴走支援していきます。

まずはお気軽にこちらからお問い合わせください。

お問い合わせ・相談する(無料)