Indiko.Blocks.API.Swagger
2.1.1
dotnet add package Indiko.Blocks.API.Swagger --version 2.1.1
NuGet\Install-Package Indiko.Blocks.API.Swagger -Version 2.1.1
<PackageReference Include="Indiko.Blocks.API.Swagger" Version="2.1.1" />
<PackageVersion Include="Indiko.Blocks.API.Swagger" Version="2.1.1" />
<PackageReference Include="Indiko.Blocks.API.Swagger" />
paket add Indiko.Blocks.API.Swagger --version 2.1.1
#r "nuget: Indiko.Blocks.API.Swagger, 2.1.1"
#:package Indiko.Blocks.API.Swagger@2.1.1
#addin nuget:?package=Indiko.Blocks.API.Swagger&version=2.1.1
#tool nuget:?package=Indiko.Blocks.API.Swagger&version=2.1.1
Indiko.Blocks.API.Swagger
Swagger/OpenAPI documentation block for generating interactive API documentation with authentication support and API versioning.
Overview
This package provides automatic Swagger/OpenAPI documentation generation for ASP.NET Core Web APIs, with built-in support for JWT Bearer authentication, API versioning, XML documentation, and custom filters.
Features
- Swagger UI: Interactive API documentation and testing interface
- OpenAPI 3.0: Standard OpenAPI specification generation
- API Versioning: Automatic versioning support with URL segments
- JWT Authentication: Built-in Bearer token authentication UI
- XML Documentation: Automatic XML comment inclusion
- Custom Filters: Operation filters for enhanced documentation
- Deep Linking: Direct links to specific API operations
- Deprecated APIs: Visual indicators for deprecated endpoints
- Response Examples: Support for request/response examples
- Auto-Discovery: Automatic endpoint discovery
Installation
dotnet add package Indiko.Blocks.API.Swagger
Quick Start
Enable Swagger Block
using Indiko.Hosting.Web;
public class Startup : WebStartup
{
public Startup(IConfiguration configuration, IWebHostEnvironment environment)
: base(configuration, environment)
{
}
protected override bool AddControllersWithViews => false;
protected override bool EnableForwardedHeaderOptions => false;
protected override bool ForceHttps => true;
// Swagger is automatically enabled via block system
}
Configuration (appsettings.json)
{
"SwaggerOptions": {
"Enabled": true,
"Title": "My API",
"Description": "RESTful API for My Application",
"ApiPrefix": "api",
"TermsOfService": "https://example.com/terms",
"Contact": {
"Name": "API Support",
"Email": "support@example.com",
"Url": "https://example.com/support"
},
"License": {
"Name": "MIT",
"Url": "https://opensource.org/licenses/MIT"
}
}
}
Access Swagger UI
Once configured, Swagger UI is available at:
https://localhost:5001/
Or specifically:
https://localhost:5001/swagger
API Versioning
Define Versioned Controllers
using Asp.Versioning;
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiVersion("1.0")]
public class UsersController : ControllerBase
{
/// <summary>
/// Gets all users
/// </summary>
/// <returns>List of users</returns>
/// <response code="200">Returns the list of users</response>
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<IActionResult> GetUsers()
{
// Implementation
return Ok(users);
}
/// <summary>
/// Gets a specific user by ID
/// </summary>
/// <param name="id">User ID</param>
/// <returns>User details</returns>
/// <response code="200">Returns the user</response>
/// <response code="404">User not found</response>
[HttpGet("{id}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> GetUser(Guid id)
{
// Implementation
return Ok(user);
}
}
Multiple API Versions
// Version 1.0
[ApiController]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiVersion("1.0")]
public class UsersV1Controller : ControllerBase
{
[HttpGet]
public IActionResult GetUsers()
{
// V1 implementation
return Ok(usersV1);
}
}
// Version 2.0
[ApiController]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiVersion("2.0")]
public class UsersV2Controller : ControllerBase
{
[HttpGet]
public IActionResult GetUsers()
{
// V2 implementation with more features
return Ok(usersV2);
}
}
// Deprecated version
[ApiController]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiVersion("1.0", Deprecated = true)]
public class OrdersV1Controller : ControllerBase
{
[HttpGet]
public IActionResult GetOrders()
{
// Old implementation
return Ok(orders);
}
}
XML Documentation
Enable XML Documentation in Project
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
</Project>
Document Your APIs
/// <summary>
/// User management controller
/// </summary>
[ApiController]
[Route("api/v{version:apiVersion}/[controller]")]
public class UsersController : ControllerBase
{
/// <summary>
/// Creates a new user
/// </summary>
/// <param name="command">User creation data</param>
/// <returns>Created user ID</returns>
/// <remarks>
/// Sample request:
///
/// POST /api/v1/users
/// {
/// "firstName": "John",
/// "lastName": "Doe",
/// "email": "john.doe@example.com"
/// }
///
/// </remarks>
/// <response code="201">User created successfully</response>
/// <response code="400">Invalid request data</response>
/// <response code="409">Email already exists</response>
[HttpPost]
[ProducesResponseType(typeof(Guid), StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status409Conflict)]
public async Task<IActionResult> CreateUser([FromBody] CreateUserCommand command)
{
var userId = await _mediator.Send<CreateUserCommand, Guid>(command);
return CreatedAtAction(nameof(GetUser), new { id = userId }, userId);
}
}
Authentication Documentation
JWT Bearer Authentication
The Swagger UI includes built-in JWT Bearer token authentication:
- Click the "Authorize" button at the top right
- Enter your token in the format:
Bearer {your-token} - Click "Authorize"
- All subsequent requests include the token
Require Authentication
using Microsoft.AspNetCore.Authorization;
[ApiController]
[Route("api/v{version:apiVersion}/[controller]")]
[Authorize] // Requires authentication for all actions
public class SecureController : ControllerBase
{
[HttpGet]
public IActionResult GetSecureData()
{
return Ok(secureData);
}
[HttpPost]
[AllowAnonymous] // Allow anonymous access to specific action
public IActionResult PublicEndpoint()
{
return Ok("Public data");
}
}
Custom Attributes
Implementation Notes
using Indiko.Blocks.API.Swagger.Attributes;
[ApiController]
[Route("api/v{version:apiVersion}/[controller]")]
public class ProductsController : ControllerBase
{
[HttpGet]
[ImplementationNotes("This endpoint returns a cached list of products. Cache expires after 5 minutes.")]
public IActionResult GetProducts()
{
return Ok(products);
}
}
Request/Response Examples
Using Swashbuckle Annotations
using Swashbuckle.AspNetCore.Annotations;
public class CreateUserCommand
{
/// <example>John</example>
public string FirstName { get; set; }
/// <example>Doe</example>
public string LastName { get; set; }
/// <example>john.doe@example.com</example>
public string Email { get; set; }
}
[HttpPost]
[SwaggerOperation(
Summary = "Creates a new user",
Description = "Creates a new user account with the provided information",
OperationId = "CreateUser",
Tags = new[] { "Users" }
)]
[SwaggerResponse(201, "User created successfully", typeof(Guid))]
[SwaggerResponse(400, "Invalid request data")]
[SwaggerResponse(409, "Email already exists")]
public async Task<IActionResult> CreateUser([FromBody] CreateUserCommand command)
{
var userId = await _mediator.Send<CreateUserCommand, Guid>(command);
return CreatedAtAction(nameof(GetUser), new { id = userId }, userId);
}
Custom Operation Filters
The block includes several built-in filters:
AddBearerAuthHeaderOperationFilter
Adds Bearer token authentication to operations with [Authorize] attribute.
AuthenticationResponseCodesOperationFilter
Automatically adds 401 (Unauthorized) and 403 (Forbidden) response codes to secured endpoints.
ImplementationNotesAttributeFilter
Processes [ImplementationNotes] attribute and adds notes to Swagger documentation.
LowercaseDocumentsFilter
Converts all URLs to lowercase in the Swagger documentation.
Advanced Configuration
Custom Swagger Options
public class CustomSwaggerBlock : SwaggerBlock
{
public CustomSwaggerBlock(IConfiguration configuration, ILogger logger)
: base(configuration, logger)
{
}
public override void ConfigureServices(IServiceCollection services)
{
base.ConfigureServices(services);
// Add custom filters
services.Configure<SwaggerGenOptions>(options =>
{
options.OperationFilter<MyCustomOperationFilter>();
options.DocumentFilter<MyCustomDocumentFilter>();
});
}
}
Group by Tags
[ApiController]
[Route("api/v{version:apiVersion}/[controller]")]
[Tags("User Management")]
public class UsersController : ControllerBase
{
// All endpoints grouped under "User Management"
}
Security Schemes
OAuth2 Configuration
services.AddSwaggerGen(options =>
{
options.AddSecurityDefinition("OAuth2", new OpenApiSecurityScheme
{
Type = SecuritySchemeType.OAuth2,
Flows = new OpenApiOAuthFlows
{
AuthorizationCode = new OpenApiOAuthFlow
{
AuthorizationUrl = new Uri("https://identity.example.com/connect/authorize"),
TokenUrl = new Uri("https://identity.example.com/connect/token"),
Scopes = new Dictionary<string, string>
{
{ "api", "API Access" },
{ "profile", "Profile Access" }
}
}
}
});
});
File Upload Documentation
/// <summary>
/// Uploads a file
/// </summary>
/// <param name="file">File to upload</param>
[HttpPost("upload")]
[Consumes("multipart/form-data")]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<IActionResult> UploadFile(IFormFile file)
{
// Implementation
return Ok(new { FileName = file.FileName, Size = file.Length });
}
Enum Documentation
/// <summary>
/// User status
/// </summary>
public enum UserStatus
{
/// <summary>User is active</summary>
Active = 0,
/// <summary>User is inactive</summary>
Inactive = 1,
/// <summary>User is suspended</summary>
Suspended = 2
}
Best Practices
- Always Add XML Comments: Document all public APIs with XML comments
- Use ProducesResponseType: Specify all possible response types
- Version Your APIs: Use semantic versioning (v1.0, v2.0)
- Group Related Endpoints: Use Tags to organize endpoints
- Example Values: Provide example values for properties
- Deprecation: Mark deprecated endpoints clearly
- Security: Document authentication requirements
- Error Responses: Document all possible error scenarios
Swagger UI Features
- Try it out: Test endpoints directly from the browser
- Model Schemas: View request/response models
- Authorization: Test authenticated endpoints
- Download Spec: Download OpenAPI specification (JSON/YAML)
- Deep Linking: Share links to specific endpoints
- Code Generation: Generate client code
Production Considerations
Disable in Production
public override void Configure(IApplicationBuilder app, IServiceProvider serviceProvider, IHostEnvironment environment)
{
if (environment.IsDevelopment())
{
base.Configure(app, serviceProvider, environment);
}
}
Or with Configuration
{
"SwaggerOptions": {
"Enabled": false // Disable in production
}
}
URL Routing
Swagger UI is available at multiple URLs:
/- Root (default)/swagger- Explicit Swagger path/swagger/v1/swagger.json- OpenAPI spec for v1/swagger/v2/swagger.json- OpenAPI spec for v2
Target Framework
- .NET 10
Dependencies
Swashbuckle.AspNetCore(6.5+)Swashbuckle.AspNetCore.FiltersSwashbuckle.AspNetCore.AnnotationsAsp.Versioning.Mvc.ApiExplorerIndiko.Blocks.Common.Abstractions
License
See LICENSE file in the repository root.
Related Packages
Indiko.Blocks.API.Compression- Response compressionIndiko.Blocks.API.FeatureManagement- Feature flagsIndiko.Blocks.API.Idempotency- Idempotent requestsIndiko.Blocks.Security.Authentication.ASPNetCore- Authentication
Resources
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Asp.Versioning.Mvc.ApiExplorer (>= 8.1.0)
- Indiko.Blocks.Common.Abstractions (>= 2.1.1)
- Microsoft.Extensions.DependencyModel (>= 10.0.0)
- Swashbuckle.AspNetCore (>= 10.0.1)
- Swashbuckle.AspNetCore.Annotations (>= 10.0.1)
- Swashbuckle.AspNetCore.Filters (>= 10.0.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.1.1 | 620 | 12/2/2025 |
| 2.1.0 | 614 | 12/2/2025 |
| 2.0.0 | 268 | 9/17/2025 |
| 1.7.23 | 182 | 9/8/2025 |
| 1.7.22 | 166 | 9/8/2025 |
| 1.7.21 | 173 | 8/14/2025 |
| 1.7.20 | 181 | 6/23/2025 |
| 1.7.19 | 209 | 6/3/2025 |
| 1.7.18 | 178 | 5/29/2025 |
| 1.7.17 | 201 | 5/26/2025 |
| 1.7.15 | 153 | 4/12/2025 |
| 1.7.14 | 176 | 4/11/2025 |
| 1.7.13 | 172 | 3/29/2025 |
| 1.7.12 | 158 | 3/28/2025 |
| 1.7.11 | 193 | 3/28/2025 |
| 1.7.10 | 167 | 3/28/2025 |
| 1.7.9 | 163 | 3/28/2025 |
| 1.7.8 | 174 | 3/28/2025 |
| 1.7.5 | 205 | 3/17/2025 |
| 1.7.4 | 169 | 3/16/2025 |
| 1.7.3 | 167 | 3/16/2025 |
| 1.7.2 | 183 | 3/16/2025 |
| 1.7.1 | 198 | 3/11/2025 |
| 1.7.0 | 201 | 3/11/2025 |
| 1.6.8 | 229 | 3/11/2025 |
| 1.6.7 | 271 | 3/4/2025 |
| 1.6.6 | 139 | 2/26/2025 |
| 1.6.5 | 141 | 2/20/2025 |
| 1.6.4 | 137 | 2/20/2025 |
| 1.6.3 | 139 | 2/5/2025 |
| 1.6.2 | 139 | 1/24/2025 |
| 1.6.1 | 160 | 1/24/2025 |
| 1.6.0 | 164 | 1/16/2025 |
| 1.5.2 | 124 | 1/16/2025 |
| 1.5.1 | 175 | 11/3/2024 |
| 1.5.0 | 148 | 10/26/2024 |
| 1.3.2 | 168 | 10/24/2024 |
| 1.3.0 | 162 | 10/10/2024 |
| 1.2.5 | 154 | 10/9/2024 |
| 1.2.4 | 169 | 10/8/2024 |
| 1.2.1 | 135 | 10/3/2024 |
| 1.2.0 | 169 | 9/29/2024 |
| 1.1.1 | 163 | 9/23/2024 |
| 1.1.0 | 178 | 9/18/2024 |
| 1.0.33 | 179 | 9/15/2024 |
| 1.0.28 | 186 | 8/28/2024 |
| 1.0.27 | 196 | 8/24/2024 |
| 1.0.26 | 173 | 7/7/2024 |
| 1.0.25 | 163 | 7/6/2024 |
| 1.0.24 | 171 | 6/25/2024 |
| 1.0.23 | 172 | 6/1/2024 |
| 1.0.22 | 180 | 5/14/2024 |
| 1.0.21 | 167 | 5/14/2024 |
| 1.0.20 | 204 | 4/8/2024 |
| 1.0.19 | 191 | 4/3/2024 |
| 1.0.18 | 201 | 3/23/2024 |
| 1.0.17 | 194 | 3/19/2024 |
| 1.0.16 | 192 | 3/19/2024 |
| 1.0.15 | 194 | 3/11/2024 |
| 1.0.14 | 193 | 3/10/2024 |
| 1.0.13 | 180 | 3/6/2024 |
| 1.0.12 | 187 | 3/1/2024 |
| 1.0.11 | 180 | 3/1/2024 |
| 1.0.10 | 169 | 3/1/2024 |
| 1.0.9 | 197 | 3/1/2024 |
| 1.0.8 | 171 | 2/19/2024 |
| 1.0.7 | 186 | 2/17/2024 |
| 1.0.6 | 158 | 2/17/2024 |
| 1.0.5 | 152 | 2/17/2024 |
| 1.0.4 | 190 | 2/7/2024 |
| 1.0.3 | 160 | 2/6/2024 |
| 1.0.1 | 183 | 2/6/2024 |
| 1.0.0 | 225 | 1/9/2024 |
| 1.0.0-preview99 | 215 | 12/22/2023 |
| 1.0.0-preview98 | 174 | 12/21/2023 |
| 1.0.0-preview97 | 154 | 12/21/2023 |
| 1.0.0-preview96 | 190 | 12/20/2023 |
| 1.0.0-preview94 | 137 | 12/18/2023 |
| 1.0.0-preview93 | 344 | 12/13/2023 |
| 1.0.0-preview92 | 154 | 12/13/2023 |
| 1.0.0-preview91 | 211 | 12/12/2023 |
| 1.0.0-preview90 | 173 | 12/11/2023 |
| 1.0.0-preview89 | 189 | 12/11/2023 |
| 1.0.0-preview88 | 276 | 12/6/2023 |
| 1.0.0-preview87 | 175 | 12/6/2023 |
| 1.0.0-preview86 | 169 | 12/6/2023 |
| 1.0.0-preview85 | 166 | 12/6/2023 |
| 1.0.0-preview84 | 183 | 12/5/2023 |
| 1.0.0-preview83 | 251 | 12/5/2023 |
| 1.0.0-preview82 | 192 | 12/5/2023 |
| 1.0.0-preview81 | 183 | 12/4/2023 |
| 1.0.0-preview80 | 159 | 12/1/2023 |
| 1.0.0-preview77 | 179 | 12/1/2023 |
| 1.0.0-preview76 | 173 | 12/1/2023 |
| 1.0.0-preview75 | 169 | 12/1/2023 |
| 1.0.0-preview74 | 191 | 11/26/2023 |
| 1.0.0-preview73 | 197 | 11/7/2023 |
| 1.0.0-preview72 | 157 | 11/6/2023 |
| 1.0.0-preview71 | 183 | 11/3/2023 |
| 1.0.0-preview70 | 184 | 11/2/2023 |
| 1.0.0-preview69 | 133 | 11/2/2023 |
| 1.0.0-preview68 | 157 | 11/2/2023 |
| 1.0.0-preview67 | 162 | 11/2/2023 |
| 1.0.0-preview66 | 130 | 11/2/2023 |
| 1.0.0-preview65 | 190 | 11/2/2023 |
| 1.0.0-preview64 | 161 | 11/2/2023 |
| 1.0.0-preview63 | 161 | 11/2/2023 |
| 1.0.0-preview62 | 191 | 11/1/2023 |
| 1.0.0-preview61 | 164 | 11/1/2023 |
| 1.0.0-preview60 | 155 | 11/1/2023 |
| 1.0.0-preview59 | 152 | 11/1/2023 |
| 1.0.0-preview58 | 169 | 10/31/2023 |
| 1.0.0-preview57 | 165 | 10/31/2023 |
| 1.0.0-preview56 | 158 | 10/31/2023 |
| 1.0.0-preview55 | 171 | 10/31/2023 |
| 1.0.0-preview54 | 140 | 10/31/2023 |
| 1.0.0-preview53 | 141 | 10/31/2023 |
| 1.0.0-preview52 | 138 | 10/31/2023 |
| 1.0.0-preview51 | 160 | 10/31/2023 |
| 1.0.0-preview50 | 178 | 10/31/2023 |
| 1.0.0-preview48 | 144 | 10/31/2023 |
| 1.0.0-preview46 | 168 | 10/31/2023 |
| 1.0.0-preview45 | 175 | 10/31/2023 |
| 1.0.0-preview44 | 155 | 10/31/2023 |
| 1.0.0-preview43 | 149 | 10/31/2023 |
| 1.0.0-preview42 | 137 | 10/30/2023 |
| 1.0.0-preview41 | 160 | 10/30/2023 |
| 1.0.0-preview40 | 159 | 10/27/2023 |
| 1.0.0-preview39 | 178 | 10/27/2023 |
| 1.0.0-preview38 | 149 | 10/27/2023 |
| 1.0.0-preview37 | 185 | 10/27/2023 |
| 1.0.0-preview36 | 146 | 10/27/2023 |
| 1.0.0-preview35 | 148 | 10/27/2023 |
| 1.0.0-preview34 | 138 | 10/27/2023 |
| 1.0.0-preview33 | 170 | 10/26/2023 |
| 1.0.0-preview32 | 165 | 10/26/2023 |
| 1.0.0-preview31 | 178 | 10/26/2023 |
| 1.0.0-preview30 | 170 | 10/26/2023 |
| 1.0.0-preview29 | 171 | 10/26/2023 |
| 1.0.0-preview28 | 153 | 10/26/2023 |
| 1.0.0-preview27 | 185 | 10/26/2023 |
| 1.0.0-preview26 | 165 | 10/25/2023 |
| 1.0.0-preview25 | 220 | 10/23/2023 |
| 1.0.0-preview24 | 192 | 10/23/2023 |
| 1.0.0-preview23 | 152 | 10/23/2023 |
| 1.0.0-preview22 | 172 | 10/23/2023 |
| 1.0.0-preview21 | 151 | 10/23/2023 |
| 1.0.0-preview20 | 172 | 10/20/2023 |
| 1.0.0-preview19 | 180 | 10/19/2023 |
| 1.0.0-preview18 | 174 | 10/18/2023 |
| 1.0.0-preview16 | 217 | 10/11/2023 |
| 1.0.0-preview14 | 202 | 10/10/2023 |
| 1.0.0-preview13 | 169 | 10/10/2023 |
| 1.0.0-preview12 | 160 | 10/9/2023 |
| 1.0.0-preview11 | 178 | 10/9/2023 |
| 1.0.0-preview101 | 140 | 1/5/2024 |