C# Academy · Lesson

OpenAPI, Versioning & Deployment

Generate Swagger/OpenAPI docs, version APIs, and deploy a Minimal API to Azure App Service or containers.

Lesson 4 of 413 steps

OpenAPI, Versioning & Deployment is a free C# Academy lesson on CoddyKit. This is lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the C# Academy learning path, and your progress syncs across the web and the CoddyKit app. The C# Academy course includes 4 lessons in total.

OpenAPI in Minimal APIs

OpenAPI (formerly Swagger) generates interactive API documentation. In .NET 9, AddOpenApi() is built-in. For earlier versions, use Swashbuckle.AspNetCore.

Adding Swagger with Swashbuckle

Install Swashbuckle, configure it in services, and add the middleware to serve the spec and Swagger UI.

// dotnet add package Swashbuckle.AspNetCore

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(opt =>
    opt.SwaggerDoc("v1", new() { Title = "Products API", Version = "v1" }));

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

Annotating Endpoints for OpenAPI

Use Produces, ProducesProblem, WithSummary, and WithDescription to enrich the generated OpenAPI specification.

app.MapGet("/products/{id}", GetProduct)
   .WithName("GetProductById")
   .WithSummary("Get a product by ID")
   .WithDescription("Returns the product matching the given numeric ID.")
   .Produces<ProductDto>(200)
   .Produces<ProblemDetails>(404)
   .WithTags("Products");

API Versioning with Route Groups

A simple versioning strategy uses route groups prefixed with the version. No extra package needed for basic versioning.

var v1 = app.MapGroup("/api/v1").WithTags("v1");
var v2 = app.MapGroup("/api/v2").WithTags("v2");

v1.MapGet("/products", GetProductsV1);
v2.MapGet("/products", GetProductsV2); // different DTO shape

// Clients use /api/v1/products or /api/v2/products

Asp.Versioning for Header/Query Versioning

The Asp.Versioning.Http package adds query-string, header-based, and URL-segment versioning to Minimal APIs with full OpenAPI integration.

// dotnet add package Asp.Versioning.Http

builder.Services.AddApiVersioning(opt =>
{
    opt.DefaultApiVersion = new ApiVersion(1, 0);
    opt.AssumeDefaultVersionWhenUnspecified = true;
    opt.ApiVersionReader = new QueryStringApiVersionReader("api-version");
});

// /products?api-version=2.0
app.MapGet("/products", GetProducts)
   .HasApiVersion(2, 0);

Generating a Separate Spec per Version

Configure Swashbuckle to generate separate OpenAPI documents for each version, so consumers see only the endpoints relevant to their version.

builder.Services.AddSwaggerGen(opt =>
{
    opt.SwaggerDoc("v1", new() { Title = "API", Version = "v1" });
    opt.SwaggerDoc("v2", new() { Title = "API", Version = "v2" });
});

app.UseSwaggerUI(opt =>
{
    opt.SwaggerEndpoint("/swagger/v1/swagger.json", "v1");
    opt.SwaggerEndpoint("/swagger/v2/swagger.json", "v2");
});

Publishing a Self-Contained Binary

Publish your Minimal API as a self-contained single binary — no .NET runtime needed on the target machine.

# Publish for Linux x64 as self-contained
dotnet publish -c Release -r linux-x64 --self-contained true

# Run the output binary
./bin/Release/net9.0/linux-x64/publish/MyApi

# Optionally single-file:
# dotnet publish -c Release -r linux-x64 -p:PublishSingleFile=true

Containerizing with Docker

Package the API in a Docker image using the official .NET base images. A multi-stage Dockerfile keeps the final image small.

# Dockerfile (multi-stage)
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
WORKDIR /src
COPY . .
RUN dotnet publish -c Release -o /app

FROM mcr.microsoft.com/dotnet/aspnet:9.0
WORKDIR /app
COPY --from=build /app .
ENTRYPOINT ["dotnet", "MyApi.dll"]

# Build and run
# docker build -t my-api .
# docker run -p 8080:8080 my-api

Deploying to Azure App Service

Deploy directly to Azure App Service from the CLI. The service handles scaling, certificates, and custom domains.

# Publish to folder first
dotnet publish -c Release -o ./publish

# Deploy to Azure App Service
az webapp up \
  --name my-products-api \
  --resource-group myRG \
  --runtime DOTNETCORE:9.0 \
  --sku B1

# View logs
az webapp log tail --name my-products-api --resource-group myRG

Health Checks

Add health check endpoints so orchestrators (Kubernetes, Azure) can verify your API is alive and ready to serve traffic.

builder.Services.AddHealthChecks()
    .AddDbContextCheck<AppDbContext>()
    .AddUrlGroup(new Uri("https://api.external.com/ping"), "external");

app.MapHealthChecks("/health");
app.MapHealthChecks("/health/ready", new HealthCheckOptions
{
    Predicate = hc => hc.Tags.Contains("ready")
});

Real-World: Production Checklist

A production Minimal API should include these settings for correctness, observability, and security.

// builder configuration
builder.Services.AddProblemDetails();
builder.Services.AddHealthChecks();
builder.Services.AddRateLimiter(...);
builder.Services.AddOutputCache();

// app pipeline
app.UseHttpsRedirection();
app.UseExceptionHandler();
app.UseRateLimiter();
app.UseOutputCache();
app.UseAuthentication();
app.UseAuthorization();

app.MapHealthChecks("/health");
// ... your endpoints
app.Run();

Quick Check

Which method makes endpoint metadata (Produces, WithSummary, etc.) visible to OpenAPI tooling in Minimal APIs?

Recap: OpenAPI, Versioning & Deployment

Key takeaways:

  • AddEndpointsApiExplorer + Swashbuckle = Swagger UI for Minimal APIs
  • Annotate with Produces, WithSummary, WithTags for rich OpenAPI docs
  • Simple versioning via route groups; Asp.Versioning for advanced scenarios
  • Publish self-contained or Docker image for flexible deployment
  • Add health checks for Kubernetes/Azure readiness probes
Free to start

Learn C# with an AI tutor — free

Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.

Courses
93
Lessons
346

Frequently Asked Questions

Is the “OpenAPI, Versioning & Deployment” lesson free?

Yes — the full text of “OpenAPI, Versioning & Deployment” is free to read here on the web. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the C# Academy course, upgrade to CoddyKit PRO. The C# Academy course includes 4 lessons in total.

What will I learn in “OpenAPI, Versioning & Deployment”?

Generate Swagger/OpenAPI docs, version APIs, and deploy a Minimal API to Azure App Service or containers. You practise C# Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start C# Academy?

No prior experience is required. C# Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 4 of 4.

How long does the “OpenAPI, Versioning & Deployment” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this C# Academy lesson?

Yes. Every C# Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Creating Your First Minimal API
  2. Route Groups, Parameters & Validation
  3. Middleware & Filters in Minimal APIs
  4. OpenAPI, Versioning & Deployment
← Back to C# Academy