OpenAPI documents

ASP.NET Core · Practical · 10 min

An OpenAPI document powers interactive docs, client generation and contract testing.

ASP.NET Core can describe its endpoints as an OpenAPI document. Since .NET 9 this is built in through the Microsoft.AspNetCore.OpenApi package (included in the webapi template); Swashbuckle is no longer part of the template.

builder.Services.AddOpenApi();
app.MapOpenApi();        // serves /openapi/v1.json

In ASP.NET Core 10 the document uses OpenAPI 3.1 by default, and you can also serve YAML (app.MapOpenApi("/openapi/{documentName}.yaml")).

The generator reads what it can from your code: routes, parameter types and binding sources, request bodies, and response types from TypedResults and Results<...> unions. Add more with metadata:

  • .WithName("GetTodo") (operationId), .WithSummary(...), .WithDescription(...), .WithTags("Todos").
  • .Produces<T>(201), .ProducesProblem(404) when the return type doesn't say it.
  • XML doc comments are picked up when GenerateDocumentationFile is enabled (ASP.NET Core 10).
  • Document and operation transformers customize the output, e.g. adding security schemes.

The package only produces JSON; for a UI, add Swagger UI (Swashbuckle.AspNetCore.SwaggerUI) or Scalar (Scalar.AspNetCore) pointing at the document, usually only in Development.

Treat the document as a contract: generate typed clients from it (NSwag, Kiota, openapi-generator) and diff it in CI to catch breaking changes.

Example

// dotnet add package Microsoft.AspNetCore.OpenApi
using Microsoft.AspNetCore.Http.HttpResults;

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

if (app.Environment.IsDevelopment())
    app.MapOpenApi();                         // GET /openapi/v1.json

app.MapGet("/todos/{id:int}", Results<Ok<Todo>, NotFound> (int id) =>
        id == 1 ? TypedResults.Ok(new Todo(1, "Write docs")) : TypedResults.NotFound())
   .WithName("GetTodo")
   .WithSummary("Get a todo by id")
   .WithTags("Todos");

app.Run();
// /openapi/v1.json contains:
//   "openapi": "3.1.x", paths./todos/{id}.get.operationId: "GetTodo",
//   responses 200 (schema Todo) and 404

public record Todo(int Id, string Title);

Remember

  • AddOpenApi + MapOpenApi serve /openapi/v1.json
  • TypedResults and Results<...> document responses automatically
  • Add names, summaries and tags with With* methods
  • UI tools like Swagger UI or Scalar are separate add-ons

Check yourself

  1. Why do TypedResults help OpenAPI generation?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: learn.microsoft.com/en-us/aspnet/core/fundamentals/openapi/overview

Builds on

Unlocks

Nothing builds on this yet.