0Pricing
C# Academy · レッスン

初めてのMinimal APIの作成

Minimal APIプロジェクトを立ち上げ、ルートハンドラーを定義し、最小限の定型コードで型付きの結果を返します。

「初めてのMinimal APIの作成」はCoddyKit上の無料C# Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC# Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C# Academyコースには全4レッスンが含まれています。

Minimal APIとは

Minimal APIは.NET 6で導入され、最小限の定型コードでHTTPエンドポイントを構築できます。コントローラーやアクション属性は不要で、Program.csに直接定義したルートハンドラーだけを使用します。マイクロサービスや軽量なAPIに最適です。

最もシンプルなMinimal API

わずか数行で完全なHTTP APIを構築できます。MapGet、MapPost、MapPut、MapDeleteメソッドで、各HTTP動詞のルートハンドラーを定義します。

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

app.MapGet("/", () => "Hello, Minimal API!");
app.MapGet("/ping", () => Results.Ok(new { status = "pong" }));

app.Run();
// That's it — no Startup.cs, no controllers

適切なHTTPレスポンスのためのTyped Results

正しいHTTPステータスコードとコンテンツタイプには、ResultsまたはTypedResultsを使用してください。OpenAPIスキーマの推論にはTypedResultsが推奨されます。

app.MapGet("/products/{id}", async (int id, AppDbContext db) =>
{
    var product = await db.Products.FindAsync(id);
    return product is null
        ? Results.NotFound()
        : Results.Ok(product);
});

app.MapPost("/products", async (Product product, AppDbContext db) =>
{
    db.Products.Add(product);
    await db.SaveChangesAsync();
    return Results.Created($"/products/{product.Id}", product);
});

ルートパラメーターとクエリ文字列

ルートパラメーターはURLパスから取得され、クエリ文字列パラメーターはクエリから自動的にバインドされます。リクエストボディはJSONからデシリアライズされます。

// Route param {id} + query param ?includeDeleted
app.MapGet("/orders/{id}", async (
    int id,
    bool includeDeleted = false,
    AppDbContext db) =>
{
    var query = db.Orders.AsQueryable();
    if (!includeDeleted) query = query.Where(o => !o.IsDeleted);
    var order = await query.FirstOrDefaultAsync(o => o.Id == id);
    return order is null ? Results.NotFound() : Results.Ok(order);
});

ルートハンドラーでの依存性注入

DIコンテナーに登録されたサービスは、ルートハンドラーのパラメーターとして直接注入できます。フレームワークが自動的に解決します。

builder.Services.AddScoped<ProductService>();

app.MapGet("/products", async (ProductService svc) =>
{
    var products = await svc.GetAllAsync();
    return Results.Ok(products);
});

app.MapDelete("/products/{id}", async (int id, ProductService svc) =>
{
    var deleted = await svc.DeleteAsync(id);
    return deleted ? Results.NoContent() : Results.NotFound();
});

リクエストボディのバインディング

登録済みサービスに一致するパラメーターは注入され、それ以外のパラメーターはリクエストボディからバインドされます(デフォルトはJSON)。必要に応じて[FromBody]を明示的に使用してください。

record CreateProductRequest(string Name, decimal Price, int Stock);

app.MapPost("/products", async (
    CreateProductRequest req,
    ProductService svc) =>
{
    var product = await svc.CreateAsync(req.Name, req.Price, req.Stock);
    return TypedResults.Created($"/products/{product.Id}", product);
});

異なるステータスコードの返却

Resultsには、一般的なすべてのHTTPレスポンス向けのファクトリメソッドが用意されています。意味的に正しいREST APIを構築するために使用してください。

app.MapPut("/products/{id}", async (int id, Product update, AppDbContext db) =>
{
    var existing = await db.Products.FindAsync(id);
    if (existing is null) return Results.NotFound();

    existing.Name  = update.Name;
    existing.Price = update.Price;
    await db.SaveChangesAsync();
    return Results.Ok(existing);
});

// Other useful Results:
// Results.BadRequest("message")
// Results.Conflict()
// Results.UnprocessableEntity(errors)
// Results.Accepted()

WithNameとWithTagsによるメタデータの追加

エンドポイントにメタデータを付与すると、ドキュメントとルーティングを改善できます。整理されたOpenAPI出力には、WithName、WithTags、WithSummaryを使用してください。

app.MapGet("/products/{id}", GetProduct)
   .WithName("GetProductById")
   .WithTags("Products")
   .WithSummary("Retrieves a product by its ID")
   .Produces<Product>()
   .Produces(404);

static async Task<IResult> GetProduct(int id, AppDbContext db)
{
    var p = await db.Products.FindAsync(id);
    return p is null ? Results.NotFound() : Results.Ok(p);
}

Minimal APIでの認可

RequireAuthorization()を適用してエンドポイントを保護するか、AllowAnonymous()を使って保護の対象外にします。ポリシーはコントローラーの場合と同じように機能します。

builder.Services.AddAuthentication().AddJwtBearer();
builder.Services.AddAuthorization();

app.UseAuthentication();
app.UseAuthorization();

app.MapGet("/profile", (ClaimsPrincipal user) =>
    Results.Ok(user.Identity!.Name))
   .RequireAuthorization();

app.MapGet("/public", () => "No auth needed")
   .AllowAnonymous();

static メソッドによる整理

より大規模な API では、ルートハンドラーを static メソッドまたは拡張メソッドに移動して、Program.cs をすっきりと見通しよく保ちます。

// Extension method groups endpoints by feature
public static class ProductEndpoints
{
    public static void MapProductEndpoints(this WebApplication app)
    {
        app.MapGet("/products",    GetAll);
        app.MapGet("/products/{id}", GetById);
        app.MapPost("/products",   Create);
    }

    private static async Task<IResult> GetAll(AppDbContext db)
        => Results.Ok(await db.Products.AsNoTracking().ToListAsync());

    // ... other handlers
}

// In Program.cs:
app.MapProductEndpoints();

実践:完全な CRUD Minimal API

Todo リソースの完全な CRUD API です。簡潔でテストしやすく、本番環境にも対応できます。

app.MapGet("/todos", async (AppDbContext db) =>
    Results.Ok(await db.Todos.AsNoTracking().ToListAsync()));

app.MapGet("/todos/{id}", async (int id, AppDbContext db) =>
{
    var todo = await db.Todos.FindAsync(id);
    return todo is null ? Results.NotFound() : Results.Ok(todo);
});

app.MapPost("/todos", async (Todo todo, AppDbContext db) =>
{
    db.Todos.Add(todo);
    await db.SaveChangesAsync();
    return Results.Created($"/todos/{todo.Id}", todo);
});

app.MapDelete("/todos/{id}", async (int id, AppDbContext db) =>
{
    int n = await db.Todos.Where(t => t.Id == id).ExecuteDeleteAsync();
    return n > 0 ? Results.NoContent() : Results.NotFound();
});

確認問題

Minimal API のルートハンドラーは、登録済みの DI サービスをどのように受け取りますか。

まとめ:最初の Minimal API の作成

重要なポイント:

  • MapGet/Post/Put/Delete を使うと、Program.cs にルートハンドラーを直接定義できます
  • Results / TypedResults を使って、適切な HTTP ステータスコードを返します
  • ルート、クエリ、ボディ、DI のパラメーターはすべて自動的にバインドされます
  • 認証には RequireAuthorization() と AllowAnonymous() を使用します
  • 拡張メソッドまたはルートグループを使って、大規模な API を整理します

よくある質問

「初めてのMinimal APIの作成」レッスンは無料ですか?

はい。「初めてのMinimal APIの作成」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C# Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C# Academyコースには全4レッスンが含まれています。

「初めてのMinimal APIの作成」で何を学びますか?

Minimal APIプロジェクトを立ち上げ、ルートハンドラーを定義し、最小限の定型コードで型付きの結果を返します。 ブラウザで直接実行するハンズオンコードでC# Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

C# Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのC# Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。

「初めてのMinimal APIの作成」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このC# Academyレッスンでコードを書いて実行できますか?

はい。すべてのC# Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 初めてのMinimal APIの作成
  2. ルートグループ、パラメーターと検証
  3. Minimal APIのミドルウェアとフィルター
  4. OpenAPI、バージョニングとデプロイ
← C# Academyに戻る