Swagger and OpenAPI

Comprehensive guide to using Swagger and OpenAPI specifications with .NET REST APIs

The Evolution of API Documentation

In the rapidly evolving world of web services, effective documentation remains one of the most crucial aspects of API development. This is particularly important for REST APIs, which have become the dominant architectural style for building web APIs in ASP.NET Core and across the industry.

The Documentation Gap in Early REST APIs

In the early days of REST API development, there was a significant gap in standardized documentation and schema validation capabilities. While SOAP APIs had built-in mechanisms for service description through WSDL (Web Services Description Language), REST APIs initially lacked an equivalent standard.

This absence led to fragmented, proprietary documentation approaches across the industry. Organizations developed their own custom solutions with varying degrees of effectiveness:

  1. Ad-hoc HTML pages: Simple but difficult to maintain and keep synchronized with implementation
  2. Custom XML formats: Hard to interpret without specialized knowledge
  3. PDF documents and wikis: Often became outdated as APIs evolved
  4. Code comments: Limited visibility and accessibility for API consumers

These inconsistent approaches created several challenges:

  1. Lack of standardization: Developers needed to learn different documentation formats for each API
  2. Limited tooling: Custom documentation formats couldn’t leverage common tools
  3. No machine-readable contracts: Automated client generation was difficult or impossible
  4. Documentation drift: API implementations and documentation frequently became out of sync
  5. Poor developer experience: Without interactive documentation, API exploration was cumbersome

The Birth of Swagger

Swagger emerged in 2011 as an innovative solution to these documentation challenges. Created by Tony Tam at Wordnik, Swagger began as an open-source project focused on providing a machine-readable way to describe REST APIs. What set Swagger apart from previous attempts was its pragmatic approach combining:

  1. A specification format for describing API endpoints, parameters, responses, and data models
  2. Interactive documentation that developers could use to explore APIs in real-time
  3. Code generation tools for both client and server implementations across multiple languages
  4. Runtime validation capabilities to ensure API implementations matched their specifications
  5. Developer-first design that prioritized ease of use for API creators and consumers

Swagger’s approach represented a compilation of best practices from several open-source ideas, refined into a cohesive framework. Its machine-readable format (initially JSON, later supporting YAML) allowed for both human readability and programmatic processing, making it a true “single source of truth” for API documentation.

From Swagger to OpenAPI

Swagger’s growing popularity and industry adoption led to a significant milestone in its evolution - the transformation from a company-owned specification to an open industry standard.

The OpenAPI Initiative

The timeline of this evolution demonstrates how quickly the industry embraced the need for standardized API documentation:

  • 2015: SmartBear Software acquired Swagger from Wordnik
  • 2016: SmartBear donated the Swagger specification to the newly formed OpenAPI Initiative (OAI), under the Linux Foundation
  • The specification was renamed to “OpenAPI Specification” (OAS), while tools retained the Swagger name
  • 2017: OpenAPI Specification 3.0 was released, with significant enhancements over Swagger 2.0
  • 2021: OpenAPI Specification 3.1 was released, further improving the standard
  • 2023: OpenAPI continues to evolve with expanded tooling and integration capabilities

The founding members of the OpenAPI Initiative included industry giants such as Google, IBM, Microsoft, and others, signifying the broad industry consensus around the need for standardized API description formats.

Key OpenAPI Specification Versions

OpenAPI 2.0 (formerly Swagger 2.0)

  • Focused on simplicity and ease of adoption
  • JSON Schema draft 4 for model definitions
  • Limited support for callbacks and webhooks
  • Still widely used in production systems today

OpenAPI 3.0 (2017)

  • Introduced improved reusability through components
  • Enhanced security scheme definitions
  • Better support for modern authentication methods
  • Expanded server configuration options
  • Callbacks for webhook documentation
  • Improved schema object capabilities
  • Used by most modern ASP.NET Core applications

OpenAPI 3.1 (2021)

  • Full alignment with JSON Schema 2020-12
  • Support for webhooks as first-class citizens
  • Enhanced examples and improved compatibility
  • PathItems object at root level
  • Support for identifying API lifecycle status
  • Top-level description field
  • Starting to be adopted in newer ASP.NET Core applications

This transition represented a maturation of the API description ecosystem. By becoming an open standard under the Linux Foundation’s governance, the OpenAPI Specification ensured vendor neutrality and collaborative development. Today, OpenAPI is widely recognized as the industry standard for REST API description, with support across virtually all major programming languages and frameworks including ASP.NET Core.

Swagger vs. OpenAPI: Understanding the Distinction

The terminology around Swagger and OpenAPI can sometimes cause confusion, especially for teams new to the ecosystem. Understanding the precise distinction is important for clear communication and proper implementation:

Key Terminology Clarified

  • OpenAPI refers to the specification itself (the standard document format)
  • Swagger now primarily refers to the toolset that implements the OpenAPI specification

This distinction is similar to how HTML (the specification) relates to web browsers (the tools that implement the specification). When speaking precisely:

  • You create an “OpenAPI document” or “OpenAPI specification”
  • You use “Swagger tools” such as Swagger UI, Swagger Editor, or Swagger Codegen

In Practice: How Developers Use the Terms

In practice, many developers and organizations still use the terms interchangeably, especially since much of the tooling retains the Swagger name. You’ll commonly hear phrases like:

  • “Let’s add Swagger to our API” (meaning implementing OpenAPI documentation)
  • “Check the Swagger docs” (referring to OpenAPI documentation rendered by Swagger UI)
  • “The Swagger endpoint is available at /swagger” (meaning the OpenAPI document endpoint)

In ASP.NET Core applications, this terminology overlap is particularly evident:

  • The Swashbuckle.AspNetCore package integrates OpenAPI into your ASP.NET Core application
  • The endpoint serving the OpenAPI document is typically configured at /swagger/v1/swagger.json
  • The UI for viewing the documentation is accessed at /swagger

Choosing the Right Terminology

To avoid confusion, especially in technical documentation or team communication:

  • Use “OpenAPI” when referring to the specification format itself
  • Use “Swagger UI” when referring specifically to the interactive documentation interface
  • Use “Swagger tools” when referring to the broader toolset (UI, Editor, Codegen)
  • Specify versions clearly: “OpenAPI 3.0” rather than just “OpenAPI”

For ASP.NET Core developers, being precise helps when searching for documentation or resolving issues related to specific parts of the ecosystem.

The Modern Swagger Toolset

Swagger offers a comprehensive ecosystem of tools that support the full API development lifecycle. These tools have evolved significantly since their introduction and now provide a robust foundation for API development, documentation, and testing.

1. Swagger Editor

The Swagger Editor is a browser-based tool that allows developers to write OpenAPI specifications with real-time validation and visualization. The latest version includes:

  • Live Validation: Immediate feedback on specification errors with detailed error messages
  • Interactive Documentation: Real-time preview of how the API will look in Swagger UI
  • Syntax Highlighting: Enhanced support for both YAML and JSON formats with modern editor features
  • Auto-completion: Intelligent contextual suggestions based on the OpenAPI specification
  • Keyword Assistance: Help text and documentation for OpenAPI keywords
  • Split-View Mode: Edit specification and see documentation simultaneously
  • Import/Export Capabilities: Easy sharing and collaboration options

Try it out: Swagger Editor

2. Swagger UI

Swagger UI transforms OpenAPI specifications into interactive documentation. The latest versions offer:

  • Interactive API Testing: Make API calls directly from the browser with full parameter support
  • OAuth 2.0 Support: Complete OAuth flow integration for secured API testing
  • Request/Response Examples: Clear visualization of expected data formats and actual responses
  • Deep Linking: Direct links to specific operations for easy sharing
  • Filter and Search: Quickly find operations in complex APIs
  • Plugin Architecture: Extensible for custom functionality
  • Responsive Design: Works across devices and screen sizes
  • Dark Mode Support: Improved readability in different environments
  • Customizable Themes: Brand-aligned visual options

Swagger UI Example

3. Swagger Codegen & OpenAPI Generator

Swagger Codegen has evolved into two main projects: the original Swagger Codegen and the community-driven OpenAPI Generator (a fork that has gained significant adoption). Both automate the generation of client libraries, server stubs, and API documentation:

  • Multiple Language Support: Generates code in 50+ programming languages
  • Server Framework Options: Supports various server frameworks including ASP.NET Core, Spring Boot, Node.js, and more
  • Client Libraries: Creates strongly-typed client SDKs for easy API consumption
  • Custom Templates: Allows for customization of generated code
  • Configuration Options: Fine-grained control over generated code style and structure
  • CI/CD Integration: Command-line tools for integration with build pipelines

Resources:

4. Swagger Hub

SwaggerHub (by SmartBear) is a cloud-based platform for API design, development, and documentation:

  • Collaborative Editing: Team-based API design with role-based access control
  • Version Control: Track changes and manage API versions
  • Standardization: Enforce organizational standards across APIs
  • Mock Services: Auto-generated mocks for API testing
  • Integration Options: Connects with GitHub, GitLab, Bitbucket, and other tools
  • Domain Management: Manage and reuse components across multiple APIs
  • Advanced Security: Protect sensitive API documentation

5. Swagger Inspector

Swagger Inspector is a tool for testing and auto-generating OpenAPI definitions from existing APIs:

  • API Testing: Simple, quick testing of REST, SOAP, and GraphQL APIs without any setup
  • Specification Generation: Create OpenAPI definitions from actual API calls
  • History Tracking: Keeps a record of your API calls for future reference
  • Team Sharing: Collaborate on API testing with team members
  • Export Capability: Share or save results of API testing
  • Integration with SwaggerHub: Seamless workflow for documenting discovered APIs

6. Swagger Parser

Swagger Parser provides validation and normalization capabilities for OpenAPI documents:

  • Schema Validation: Ensure conformance to the OpenAPI specification
  • Reference Resolution: Handle internal and external references
  • Format Conversion: Convert between YAML and JSON formats
  • Multiple Version Support: Works with OpenAPI 2.0, 3.0, and 3.1
  • Bundling: Create standalone OpenAPI documents with resolved references

Swagger in the .NET Ecosystem

In the .NET ecosystem, OpenAPI/Swagger integration has evolved significantly with the maturation of ASP.NET Core. Modern ASP.NET Core applications have particularly strong support for OpenAPI, with integration available for both controller-based APIs and the newer minimal API approach.

OpenAPI Support in ASP.NET Core

ASP.NET Core offers robust OpenAPI support through:

  1. Built-in API Explorer: ASP.NET Core includes the Microsoft.AspNetCore.OpenApi package with basic OpenAPI support
  2. Third-Party Libraries: Two major libraries dominate the ecosystem - Swashbuckle and NSwag
  3. Minimal API Integration: Direct OpenAPI annotation support for modern minimal APIs
  4. Code Analysis: API analyzers to detect and fix common API documentation issues

In the .NET world, Swagger integration is primarily achieved through the Swashbuckle and NSwag libraries, each with their own strengths:

Swashbuckle for ASP.NET Core

Swashbuckle is the most widely used OpenAPI implementation for ASP.NET Core, with a focus on ease of integration and compatibility with standard ASP.NET Core patterns. It’s maintained by both the community and Microsoft, ensuring strong alignment with ASP.NET Core’s evolution.

Key Features of Swashbuckle

  • Automatic API Discovery: Works with ASP.NET Core’s API Explorer to find endpoints
  • XML Documentation: Integrates with C# XML documentation comments
  • Customization Options: Extensive filters for schema, operation, and document customization
  • Authorization Support: Built-in handling for standard auth schemes
  • Minimal API Support: Full support for ASP.NET Core minimal APIs
  • Performance Optimizations: Efficient generation and caching of documents
  • Standard Compliance: Strong adherence to OpenAPI specifications

Basic Implementation

Here’s a standard implementation of Swashbuckle in an ASP.NET Core application:

// Program.cs in an ASP.NET Core application
var builder = WebApplication.CreateBuilder(args);

// Register controllers or minimal API endpoints
builder.Services.AddControllers();

// Add OpenAPI document generation and configuration
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(options =>
{
    options.SwaggerDoc("v1", new OpenApiInfo 
    { 
        Title = "My Task API", 
        Version = "v1",
        Description = "An API for managing tasks",
        Contact = new OpenApiContact
        {
            Name = "API Support",
            Email = "[email protected]",
            Url = new Uri("https://example.com/support")
        },
        License = new OpenApiLicense
        {
            Name = "MIT",
            Url = new Uri("https://opensource.org/licenses/MIT")
        }
    });
    
    // Add XML comments for enhanced documentation
    string xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
    string xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFilename);
    options.IncludeXmlComments(xmlPath);
    
    // Enable annotations (required when using [SwaggerOperation] and similar attributes)
    options.EnableAnnotations();
    
    // Configure basic authentication option
    options.AddSecurityDefinition("basic", new OpenApiSecurityScheme
    {
        Name = "Authorization",
        Type = SecuritySchemeType.Http,
        Scheme = "basic",
        In = ParameterLocation.Header,
        Description = "Basic Authorization header using the Bearer scheme."
    });
    
    // Apply the authentication globally
    options.AddSecurityRequirement(new OpenApiSecurityRequirement
    {
        {
            new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference
                {
                    Type = ReferenceType.SecurityScheme,
                    Id = "basic"
                }
            },
            Array.Empty<string>()
        }
    });
});

var app = builder.Build();

// Configure the HTTP request pipeline
if (app.Environment.IsDevelopment())
{
    // Add the OpenAPI document generator middleware
    app.UseSwagger(options =>
    {
        // Customize swagger.json generation
        options.RouteTemplate = "api/swagger/{documentname}/swagger.json";
    });
    
    // Add the Swagger UI middleware
    app.UseSwaggerUI(options =>
    {
        // Customize Swagger UI
        options.SwaggerEndpoint("/api/swagger/v1/swagger.json", "My Task API v1");
        options.RoutePrefix = "api/swagger";
        options.DocExpansion(Swashbuckle.AspNetCore.SwaggerUI.DocExpansion.None);
        options.DefaultModelsExpandDepth(-1); // Hide schemas section
    });
}

app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.Run();

NSwag: Beyond Documentation

NSwag is a comprehensive .NET library that provides powerful OpenAPI/Swagger tooling with several advanced capabilities beyond basic documentation generation. While Swashbuckle focuses primarily on documentation, NSwag offers a complete suite of tools for both API documentation and client/server code generation, making it particularly valuable for projects where code generation is a priority.

Key Features of NSwag

  • Dual Approach Support: Implements both code-first (generate specs from code) and spec-first (generate code from specs) workflows
  • Rich Client Generation: Creates strongly-typed client libraries with more configuration options than Swashbuckle
  • Multiple Language Support: Generates clients for C#, TypeScript, JavaScript, and other languages
  • Complete API Lifecycle: Covers the entire API development process from design to implementation
  • Integration Options: Seamlessly fits into ASP.NET Core with dependency injection support
  • AspNetCore.OpenApi Middleware: Serves OpenAPI documents with minimal configuration
  • Extensive Customization: Provides detailed configuration options for document generation
  • Command-line Integration: Offers CLI tools for automation in CI/CD pipelines
  • Runtime Documentation: Updates API docs at runtime based on actual implementation
  • Open Source Community: Active development with regular updates and community contributions

When to Choose NSwag

NSwag is particularly well-suited for:

  1. Projects requiring automated client generation (frontend SDKs from backend APIs)
  2. Teams working with both OpenAPI specifications and implementation simultaneously
  3. Microservice architectures where API contracts need to be enforced
  4. Projects that need TypeScript client generation for frontend applications
  5. Advanced customization of the OpenAPI document generation process
  6. CI/CD pipelines that automate API documentation and client generation

Modern NSwag Implementation

Here’s a contemporary implementation of NSwag in an ASP.NET Core application with best practices:

// Program.cs in an ASP.NET Core 8.0 application
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using NJsonSchema;
using NJsonSchema.Generation;
using NSwag;
using NSwag.AspNetCore;
using NSwag.Generation.Processors.Security;
using System;
using System.Linq;

var builder = WebApplication.CreateBuilder(args);

// Register controllers or minimal API endpoints
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer(); // Required for API discovery

// Add NSwag OpenAPI document generator with modern configuration
builder.Services.AddOpenApiDocument(config =>
{
    // Basic information
    config.Title = "My Task API";
    config.Version = "v1";
    config.Description = "A RESTful API for managing tasks";
    
    // Add API versioning support
    config.DocumentName = "v1";
    config.ApiGroupNames = new[] { "v1" };
    
    // Enable JSON Schema validation
    config.SchemaSettings.SchemaType = SchemaType.OpenApi3;
    
    // Improved null handling for .NET 6+ applications
    config.SchemaSettings.DefaultReferenceTypeNullHandling = 
        ReferenceTypeNullHandling.NotNull;
    
    // Use System.Text.Json for better performance
    config.SerializerSettings = new System.Text.Json.JsonSerializerOptions
    {
        PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase,
        WriteIndented = true
    };
    
    // Add API security definitions
    config.AddSecurity("JWT", Enumerable.Empty<string>(),
        new OpenApiSecurityScheme
        {
            Type = OpenApiSecuritySchemeType.Http,
            Scheme = "bearer",
            BearerFormat = "JWT",
            Description = "Enter your JWT token in the format: Bearer {token}"
        }
    );
    
    // Apply security requirements to operations
    config.OperationProcessors.Add(
        new OperationSecurityScopeProcessor("JWT"));
    
    // Add server URLs for different environments
    config.AddServer(new OpenApiServer
    {
        Url = "https://api.example.com",
        Description = "Production API"
    });
    
    config.AddServer(new OpenApiServer
    {
        Url = "https://staging-api.example.com",
        Description = "Staging API"
    });
    
    // Customize schema generation
    config.SchemaSettings.GenerateEnumMappingDescription = true;
    config.SchemaSettings.UseXmlDocumentation = true;
    
    // Add tag descriptions
    config.TagDescriptions.Add("Tasks", "API endpoints for managing tasks");
    config.TagDescriptions.Add("Users", "API endpoints for user operations");
});

var app = builder.Build();

// Configure middleware pipeline
if (app.Environment.IsDevelopment())
{
    // Add the OpenAPI document generator middleware
    app.UseOpenApi(options =>
    {
        options.Path = "/api/swagger/{documentName}/swagger.json";
        options.PostProcess = (document, _) =>
        {
            document.Info.Contact = new OpenApiContact
            {
                Name = "API Support Team",
                Email = "[email protected]",
                Url = "https://example.com/support"
            };
        };
    });

    // Add the Swagger UI middleware with modern styling
    app.UseSwaggerUi3(options =>
    {
        options.Path = "/api/swagger";
        options.DocumentPath = "/api/swagger/{documentName}/swagger.json";
        options.EnableTryItOut = true;
        options.OAuth2Client = new OAuth2ClientSettings
        {
            ClientId = "swagger-ui",
            AppName = "Swagger UI"
        };
        
        // Modern theme customization
        options.CustomInlineStyles = 
            ".swagger-ui .topbar { background-color: #1a365d; } " +
            ".swagger-ui .info .title { color: #0078d7; }";
    });
    
    // Add ReDoc as an alternative documentation UI
    app.UseReDoc(options =>
    {
        options.Path = "/api/docs";
        options.DocumentPath = "/api/swagger/v1/swagger.json";
        options.SpecUrl = "/api/swagger/v1/swagger.json";
        options.HideHostname = true;
        options.HideDownloadButton = false;
        options.ExpandResponses = "200,201";
    });
}

app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();

Choosing Between Swashbuckle and NSwag

Both Swashbuckle and NSwag are excellent tools for implementing OpenAPI in ASP.NET Core applications, but they have different strengths and philosophies. Understanding these differences can help you select the right tool for your specific needs.

Feature Comparison

FeatureSwashbuckleNSwag
MaintenanceActively maintained by both community and MicrosoftActively maintained by community
IntegrationTight integration with ASP.NET CoreFlexible integration with various .NET platforms
PhilosophyFocused on documentationFull API lifecycle (docs + code generation)
ASP.NET Core SupportExcellentExcellent
OpenAPI Versions2.0, 3.02.0, 3.0, 3.1
Client GenerationLimited (via Swagger Codegen)Built-in, robust
TypeScript GenerationLimitedExcellent
CustomizationThrough filters and optionsExtensive configuration options
Documentation UISwagger UI onlySwagger UI, ReDoc support
PerformanceGoodGood
Microsoft BackingStrong (part of ASP.NET Core templates)Limited
Learning CurveGentleSteeper (more features)

When to Choose Swashbuckle

Swashbuckle is an excellent choice when:

  1. You’re new to OpenAPI: Swashbuckle offers a simpler entry point with less configuration
  2. You primarily need API documentation: Your focus is on documenting your API rather than code generation
  3. You want Microsoft-backed integration: As part of the default ASP.NET Core templates, it’s tightly integrated
  4. You prefer simplicity: You want a straightforward configuration with sensible defaults
  5. You’re using ASP.NET Core minimal APIs: The integration is particularly smooth

When to Choose NSwag

NSwag is particularly valuable when:

  1. You need client generation: You want to generate TypeScript, C#, or other clients from your API
  2. You have complex documentation needs: You need more control over the documentation generation
  3. You work with multiple OpenAPI versions: You need support for the latest OpenAPI 3.1 features
  4. You want flexible UI options: You want to use ReDoc or other UI options alongside Swagger UI
  5. You have a polyglot architecture: You need to generate clients for multiple programming languages

Migration Considerations

If you’re considering migrating between the two:

  • Swashbuckle to NSwag: Focus on the client generation capabilities, but be prepared for more configuration
  • NSwag to Swashbuckle: Simplify your setup, but you’ll need to find alternative client generation solutions

Integration Example

You can even use both libraries together in some scenarios:

// Program.cs
var builder = WebApplication.CreateBuilder(args);

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

// Add both OpenAPI implementations
builder.Services.AddSwaggerGen(options =>
{
    options.SwaggerDoc("v1", new OpenApiInfo { Title = "My API - Swashbuckle", Version = "v1" });
});

builder.Services.AddOpenApiDocument(config =>
{
    config.DocumentName = "v1_nswag";
    config.Title = "My API - NSwag";
    config.Version = "v1";
});

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    // Swashbuckle endpoints
    app.UseSwagger(options =>
    {
        options.RouteTemplate = "swagger/{documentName}/swagger.json";
    });
    app.UseSwaggerUI(options =>
    {
        options.SwaggerEndpoint("/swagger/v1/swagger.json", "My API - Swashbuckle");
        options.RoutePrefix = "swagger";
    });
    
    // NSwag endpoints
    app.UseOpenApi(options =>
    {
        options.Path = "/api-docs/{documentName}/openapi.json";
    });
    app.UseSwaggerUi3(options =>
    {
        options.Path = "/api-docs";
        options.DocumentPath = "/api-docs/{documentName}/openapi.json";
        options.DocumentTitle = "My API - NSwag";
    });
    app.UseReDoc(options =>
    {
        options.Path = "/redoc";
        options.DocumentPath = "/api-docs/v1_nswag/openapi.json";
    });
}

app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();

Swagger with ASP.NET Core Minimal APIs

ASP.NET Core 6.0+ introduced Minimal APIs, a simplified approach to building HTTP APIs with less ceremony. Swagger integration with Minimal APIs requires some specific considerations:

OpenAPI Support for Minimal APIs

Microsoft has enhanced the OpenAPI support for Minimal APIs with each release:

  • ASP.NET Core 6.0: Basic support through additional packages
  • ASP.NET Core 7.0: Enhanced metadata capabilities and simplified configuration
  • ASP.NET Core 8.0: Comprehensive annotations and built-in description capabilities

Implementation Example

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;

var builder = WebApplication.CreateBuilder(args);

// Register services for API exploration and Swagger generation
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(options =>
{
    options.SwaggerDoc("v1", new OpenApiInfo
    {
        Title = "Tasks API",
        Version = "v1",
        Description = "A minimal API for managing tasks"
    });
});

var app = builder.Build();


// Configure the API documentation
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

// Define a tasks API group
var tasksApi = app.MapGroup("/api/tasks").WithTags("Tasks");

// GET all tasks
tasksApi.MapGet("/", async (ITaskRepository repository) =>
    await repository.GetAllTasksAsync())
    .WithName("GetAllTasks")
    .WithOpenApi(operation =>
    {
        operation.Summary = "Gets all available tasks";
        operation.Description = "Retrieves the complete collection of tasks in the system";
        operation.Responses["200"].Description = "Successfully retrieved all tasks";
        return operation;
    });

// GET task by ID
tasksApi.MapGet("/{id}", async (int id, ITaskRepository repository) =>
{
    var task = await repository.GetTaskByIdAsync(id);
    return task is null ? Results.NotFound() : Results.Ok(task);
})
.WithName("GetTaskById")
.WithOpenApi(operation =>
{
    operation.Summary = "Gets a specific task by its ID";
    operation.Parameters[0].Description = "The unique identifier of the task";
    operation.Responses["200"].Description = "Task found and returned successfully";
    operation.Responses["404"].Description = "Task with the specified ID was not found";
    return operation;
});

// POST new task
tasksApi.MapPost("/", async (TaskCreateModel taskCreateModel, ITaskRepository repository) =>
{
    var createdTask = await repository.CreateTaskAsync(taskCreateModel);
    return Results.CreatedAtRoute(
        "GetTaskById", 
        new { id = createdTask.Id }, 
        createdTask);
})
.WithName("CreateTask")
.WithOpenApi();

// PUT update task
tasksApi.MapPut("/{id}", async (int id, TaskUpdateModel taskUpdate, ITaskRepository repository) =>
{
    if (await repository.UpdateTaskAsync(id, taskUpdate))
    {
        return Results.NoContent();
    }
    
    return Results.NotFound();
})
.WithName("UpdateTask")
.WithOpenApi();

// DELETE task
tasksApi.MapDelete("/{id}", async (int id, ITaskRepository repository) =>
{
    if (await repository.DeleteTaskAsync(id))
    {
        return Results.NoContent();
    }
    
    return Results.NotFound();
})
.WithName("DeleteTask")
.WithOpenApi();

app.Run();

// Task models
public record TaskModel(int Id, string Title, bool IsCompleted, TaskPriority Priority, DateTime? DueDate);
public record TaskCreateModel(string Title, TaskPriority Priority, DateTime? DueDate);
public record TaskUpdateModel(string Title, bool? IsCompleted, TaskPriority? Priority, DateTime? DueDate);

public enum TaskPriority
{
    Low, 
    Medium, 
    High, 
    Critical
}

// Repository interface (implementation would be injected)
public interface ITaskRepository
{
    Task<IEnumerable<TaskModel>> GetAllTasksAsync();
    Task<TaskModel?> GetTaskByIdAsync(int id);
    Task<TaskModel> CreateTaskAsync(TaskCreateModel taskCreate);
    Task<bool> UpdateTaskAsync(int id, TaskUpdateModel taskUpdate);
    Task<bool> DeleteTaskAsync(int id);
}

Enhanced Minimal API Swagger Configuration

For more elaborate setups, you can enhance Minimal API documentation with additional configuration:

// Program.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using System;
using System.IO;
using System.Reflection;

var builder = WebApplication.CreateBuilder(args);

// Add services for API documentation
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(options =>
{
    options.SwaggerDoc("v1", new OpenApiInfo
    {
        Title = "Minimal Tasks API",
        Version = "v1",
        Description = "A modern minimal API for task management"
    });
    
    // Include XML comments if available
    var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
    var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFilename);
    if (File.Exists(xmlPath))
    {
        options.IncludeXmlComments(xmlPath);
    }
    
    // Add JWT Bearer authentication
    options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
    {
        Description = "JWT Authorization header using the Bearer scheme. Enter 'Bearer' [space] and then your token",
        Name = "Authorization",
        In = ParameterLocation.Header,
        Type = SecuritySchemeType.ApiKey,
        Scheme = "Bearer"
    });
    
    options.AddSecurityRequirement(new OpenApiSecurityRequirement
    {
        {
            new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference
                {
                    Type = ReferenceType.SecurityScheme,
                    Id = "Bearer"
                }
            },
            Array.Empty<string>()
        }
    });
    
    // Configure operation IDs for better client generation
    options.CustomOperationIds(apiDescription =>
        apiDescription.TryGetMethodInfo(out var methodInfo)
            ? methodInfo.Name
            : null);
});

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger(options =>
    {
        options.RouteTemplate = "api/swagger/{documentName}/swagger.json";
    });
    
    app.UseSwaggerUI(options =>
    {
        options.SwaggerEndpoint("/api/swagger/v1/swagger.json", "API v1");
        options.RoutePrefix = "api/swagger";
        options.DocumentTitle = "Task API Documentation";
        options.DefaultModelsExpandDepth(1); // Limit model expansion
    });
}

// Define API endpoints
// ...

app.Run();

Best Practices for Minimal API Swagger Documentation

When using Swagger with Minimal APIs, consider these best practices:

  1. Use Descriptive Route Names: Consistently use WithName() for all endpoints to ensure proper operation naming
  2. Add OpenAPI Annotations: Use WithOpenApi() to provide detailed metadata for each operation
  3. Group Related Endpoints: Use MapGroup() and WithTags() to organize related functionality
  4. Enable XML Comments: Configure your project to generate XML documentation and include it in Swagger
  5. Consider Response Types: Document all possible response types that your API can return
  6. Add Examples: Provide examples of request/response payloads for complex operations
  7. Enable SchemaFilter: Implement custom SchemaFilters for complex model documentation
  8. Use Operation Filters: Add OperationFilters to automate common documentation patterns
  9. Document Security Requirements: Clearly specify security requirements for protected endpoints
  10. Test Documentation Regularly: Verify your Swagger UI provides useful information to API consumers

Enhanced Resources and Further Learning

Official Documentation

.NET Libraries and Tools

Books and Tutorials

Community Resources and Tools

API Design Guidelines and Standards