API Documentation with Swagger
Generate interactive API documentation with Swagger/OpenAPI.
By EMEPublished: February 20, 2025
swaggeropenapiapi documentationaspnet core
A Simple Analogy
Swagger is like a living user manual for your API. It documents endpoints, request/response formats, and you can test the API right from the documentation.
Why Swagger?
- Self-documenting: Generate docs from code
- Interactive: Test endpoints from browser
- Standardized: OpenAPI specification
- Client generation: Auto-generate SDKs
- Contract: API contract for frontend/backend
Setup
// Program.cs
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
options.RoutePrefix = string.Empty; // Show at root
});
}
app.Run();
Endpoint Documentation
[ApiController]
[Route("api/[controller]")]
public class OrdersController : ControllerBase
{
/// <summary>
/// Get order by ID
/// </summary>
/// <param name="id">Order ID</param>
/// <returns>Order details</returns>
[HttpGet("{id}")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(OrderDto))]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<ActionResult<OrderDto>> GetOrder(int id)
{
var order = await _orderService.GetAsync(id);
if (order == null) return NotFound();
return Ok(order);
}
/// <summary>
/// Create new order
/// </summary>
/// <remarks>
/// Sample request:
///
/// POST /api/orders
/// {
/// "customerId": "cust-123",
/// "items": [
/// {
/// "productId": "p1",
/// "quantity": 2,
/// "price": 29.99
/// }
/// ]
/// }
/// </remarks>
[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created, Type = typeof(OrderDto))]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<ActionResult<OrderDto>> CreateOrder(CreateOrderRequest request)
{
if (!ModelState.IsValid) return BadRequest(ModelState);
var order = await _orderService.CreateAsync(request);
return CreatedAtAction(nameof(GetOrder), new { id = order.Id }, order);
}
}
Model Documentation
public class OrderDto
{
/// <summary>
/// Unique order identifier
/// </summary>
public int Id { get; set; }
/// <summary>
/// Customer ID who placed the order
/// </summary>
[Required]
public string CustomerId { get; set; }
/// <summary>
/// Order items
/// </summary>
[MinLength(1)]
public List<OrderItemDto> Items { get; set; }
/// <summary>
/// Total order amount in USD
/// </summary>
[Range(0.01, double.MaxValue)]
public decimal Total { get; set; }
/// <summary>
/// Order status (Pending, Confirmed, Shipped, Delivered, Cancelled)
/// </summary>
public OrderStatus Status { get; set; }
}
Advanced Configuration
builder.Services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo
{
Title = "Order API",
Version = "v1",
Description = "API for managing orders",
Contact = new OpenApiContact
{
Name = "Support",
Email = "support@example.com"
}
});
// Include XML comments
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
options.IncludeXmlComments(xmlPath);
// Add security definition
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Description = "JWT Authorization header",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
Scheme = "Bearer"
});
options.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
new string[] {}
}
});
});
Custom Swagger UI
app.UseSwaggerUI(options =>
{
options.DocumentTitle = "Order API Documentation";
options.DefaultModelsExpandDepth(0); // Don't expand schemas by default
options.DefaultModelExpandDepth(2); // But expand specific ones
// Custom CSS
options.InjectStylesheet("/swagger-ui.css");
// Multiple API versions
options.SwaggerEndpoint("/swagger/v1/swagger.json", "API V1");
options.SwaggerEndpoint("/swagger/v2/swagger.json", "API V2");
});
Exclude from Documentation
[ApiExplorerSettings(IgnoreApi = true)]
[HttpPost("internal/process")]
public async Task<IActionResult> InternalProcess()
{
// Not shown in Swagger
}
Best Practices
- Document thoroughly: Include examples
- Use response types: Specify all outcomes
- Validate inputs: Annotate constraints
- Version APIs: Support multiple versions
- Keep updated: Docs should match code
Related Concepts
- API versioning strategies
- OpenAPI code generation
- API gateway documentation
- GraphQL schema
Summary
Swagger transforms code documentation into interactive API references. Use XML comments and response type annotations to auto-generate comprehensive, testable documentation.