OpenAPI/Swagger Integration
Sannr provides seamless integration with OpenAPI/Swagger documentation generators, automatically converting your validation attributes into OpenAPI schema constraints. This ensures your API documentation stays synchronized with your validation rules.
Overview
Traditional approaches require manual maintenance of both validation attributes and OpenAPI schema definitions. Sannr eliminates this duplication by automatically generating schema constraints from your validation attributes.
Setup
1. Install Dependencies
Ensure you have Swashbuckle.AspNetCore installed:
dotnet add package Swashbuckle.AspNetCore2. Configure SwaggerGen
In your Program.cs, add the Sannr OpenAPI integration:
using Sannr.OpenApi;
var builder = WebApplication.CreateBuilder(args);
// Add Swagger with Sannr integration
builder.Services.AddSwaggerGen(options =>
{
options.AddSannrValidationSchemas();
});
var app = builder.Build();
app.UseSwagger();
app.UseSwaggerUI();How It Works
Sannr uses a schema filter that post-processes OpenAPI schemas generated by Swashbuckle. The filter examines your model properties, detects Sannr validation attributes, and applies the corresponding OpenAPI constraints.
Schema Filter Process
- Base Schema Generation: Swashbuckle creates the initial OpenAPI schema
- Attribute Detection: Sannr filter scans properties for validation attributes
- Constraint Application: Validation rules are converted to OpenAPI constraints
- Schema Enhancement: The schema is updated with validation constraints
Supported Attributes
| Sannr Attribute | OpenAPI Constraint | Example |
|---|---|---|
[EmailAddress] | format: "email" | "email": {"type": "string", "format": "email"} |
[Url] | format: "uri" | "website": {"type": "string", "format": "uri"} |
[Range(min, max)] | minimum, maximum | "age": {"type": "integer", "minimum": 18, "maximum": 120} |
[StringLength(max, min)] | minLength, maxLength | "name": {"type": "string", "minLength": 2, "maxLength": 100} |
[FileExtensions] | format: "file" | "avatar": {"type": "string", "format": "file"} |
Complete Example
Model Definition
using Sannr;
public class UserRegistrationRequest
{
[Required, EmailAddress]
public string Email { get; set; } = string.Empty;
[Required, StringLength(100, MinimumLength = 2)]
public string FirstName { get; set; } = string.Empty;
[Required, StringLength(100, MinimumLength = 2)]
public string LastName { get; set; } = string.Empty;
[Range(13, 120)]
public int Age { get; set; }
[Url]
public string? Website { get; set; }
[Phone]
public string? PhoneNumber { get; set; }
[CreditCard]
public string? CreditCardNumber { get; set; }
[FileExtensions]
public string? ProfileImagePath { get; set; }
}Generated OpenAPI Schema
{
"UserRegistrationRequest": {
"type": "object",
"properties": {
"email": {
"type": "string",
"format": "email"
},
"firstName": {
"type": "string",
"minLength": 2,
"maxLength": 100
},
"lastName": {
"type": "string",
"minLength": 2,
"maxLength": 100
},
"age": {
"type": "integer",
"minimum": 13,
"maximum": 120
},
"website": {
"type": "string",
"format": "uri"
},
"phoneNumber": {
"type": "string"
},
"creditCardNumber": {
"type": "string"
},
"profileImagePath": {
"type": "string",
"format": "file"
}
},
"required": ["email", "firstName", "lastName"]
}
}Benefits
1. Single Source of Truth
Validation rules and API documentation are always synchronized. When you update validation attributes, the OpenAPI schema automatically reflects the changes.
2. Reduced Boilerplate
Eliminates the need for manual schema definitions and custom MapType configurations in SwaggerGen setup.
3. Type Safety
Validation attributes are checked at compile-time, preventing runtime errors from invalid schema definitions.
4. Maintainability
Changes to validation logic automatically propagate to API documentation without additional maintenance.
Limitations
Required Properties
The [Required] attribute currently doesn't set the required array in OpenAPI schemas. Required properties should be handled at the schema level by Swashbuckle's base functionality.
Complex Validations
Custom validators and model-level validations don't generate OpenAPI constraints. These require manual documentation or custom schema filters.
Conditional Validations
Attributes like [RequiredIf] don't affect OpenAPI schemas as they represent runtime conditional logic.
Troubleshooting
Schema Not Generated
- Ensure
AddSannrValidationSchemas()is called in SwaggerGen options - Verify the Sannr package is installed
- Check that model properties have Sannr validation attributes
Incorrect Constraints
- Verify attribute parameters match expected values
- Check for typos in attribute names
- Ensure attributes are from the
Sannrnamespace, notSystem.ComponentModel.DataAnnotations
Build Errors
- Confirm Swashbuckle.AspNetCore version compatibility
- Check for conflicting schema filters
- Verify Sannr package is correctly referenced
Advanced Usage
Custom Schema Filters
You can combine Sannr's automatic schema generation with custom filters:
builder.Services.AddSwaggerGen(options =>
{
options.AddSannrValidationSchemas();
// Add custom filters for complex validations
options.SchemaFilter<CustomValidationFilter>();
});Integration with API Versioning
Works seamlessly with API versioning libraries like ASP.Versioning:
builder.Services.AddSwaggerGen(options =>
{
options.AddSannrValidationSchemas();
// API versioning configuration
options.DocInclusionPredicate((name, api) => true);
});Migration from Manual Schemas
Before (Manual)
builder.Services.AddSwaggerGen(options =>
{
options.MapType<UserRequest>(() => new OpenApiSchema
{
Type = "object",
Properties = new Dictionary<string, OpenApiSchema>
{
["email"] = new() { Type = "string", Format = "email" },
["age"] = new() { Type = "integer", Minimum = 18, Maximum = 120 }
}
});
});After (Automatic)
builder.Services.AddSwaggerGen(options =>
{
options.AddSannrValidationSchemas(); // Single line!
});
// Model automatically generates schema
public class UserRequest
{
[EmailAddress] public string Email { get; set; }
[Range(18, 120)] public int Age { get; set; }
}Testing
The OpenAPI integration includes comprehensive unit tests covering:
- Attribute-to-constraint mapping
- Multiple attributes on single properties
- Edge cases and error handling
- Schema filter integration
Run tests with:
dotnet test --filter OpenApiIntegrationTests