or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

annotations.mdaspnetcore-integration.mdcli-commands.mdcore-document-model.mdcsharp-client-generation.mddocument-generation.mdindex.mdtypescript-client-generation.md
tile.json

annotations.mddocs/

Annotations

NSwag provides a comprehensive set of attributes (annotations) for customizing OpenAPI document generation. These attributes allow developers to add metadata, customize operation behavior, and control how APIs are documented without modifying the underlying business logic.

Operation Attributes

OpenApiOperationAttribute

Specifies operation metadata including ID, summary, and description.

[AttributeUsage(AttributeTargets.Method)]
public class OpenApiOperationAttribute : Attribute
{
    public OpenApiOperationAttribute(string operationId);
    public OpenApiOperationAttribute(string summary, string description);
    public OpenApiOperationAttribute(string operationId, string summary, string description);
    
    public string Summary { get; }
    public string Description { get; }
}

Usage Example

[HttpGet("{id}")]
[OpenApiOperation(
    "GetUserById",
    "Retrieve a user by ID",
    "Gets a specific user from the database using their unique identifier"
)]
public async Task<ActionResult<User>> GetUser(int id)
{
    // Implementation
}

OpenApiTagAttribute

Adds a single tag to an operation or controller.

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class OpenApiTagAttribute : Attribute
{
    public OpenApiTagAttribute(string name);
    
    public string Name { get; set; }
    public string Description { get; set; }
    public string DocumentationDescription { get; set; }
    public string DocumentationUrl { get; set; }
    public bool AddToDocument { get; set; }
}

Usage Example

[OpenApiTag("Users")]
public class UsersController : ControllerBase
{
    // Controller actions
}

// Or with additional properties:
// [OpenApiTag("Users") { Description = "Operations related to user management", DocumentationUrl = "https://docs.example.com/users" }]

OpenApiTagsAttribute

Adds multiple tags to an operation.

[AttributeUsage(AttributeTargets.Method)]
public class OpenApiTagsAttribute : Attribute
{
    public string[] Tags { get; set; }
    
    public OpenApiTagsAttribute(params string[] tags);
}

Usage Example

[HttpPost]
[OpenApiTags("Users", "Creation", "Authentication")]
public async Task<ActionResult<User>> CreateUser(CreateUserRequest request)
{
    // Implementation
}

Parameter Attributes

OpenApiBodyParameterAttribute

Specifies metadata for request body parameters.

[AttributeUsage(AttributeTargets.Parameter)]
public class OpenApiBodyParameterAttribute : Attribute
{
    public string Name { get; set; }
    public string Description { get; set; }
    public Type Type { get; set; }
    public bool Required { get; set; } = true;
}

Usage Example

[HttpPost]
public async Task<ActionResult> UpdateUser(
    [OpenApiBodyParameter(
        Name = "userData",
        Description = "User data to update",
        Type = typeof(UpdateUserRequest),
        Required = true
    )] UpdateUserRequest request)
{
    // Implementation
}

OpenApiFileAttribute

Specifies file upload parameters.

[AttributeUsage(AttributeTargets.Parameter)]
public class OpenApiFileAttribute : Attribute
{
    public string Name { get; set; }
    public string Description { get; set; }
    public bool Required { get; set; } = true;
}

Usage Example

[HttpPost("upload")]
public async Task<ActionResult> UploadFile(
    [OpenApiFile(
        Name = "file",
        Description = "The file to upload",
        Required = true
    )] IFormFile file)
{
    // Implementation
}

Response Attributes

ResponseTypeAttribute

Specifies the response type and status code for an operation.

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class ResponseTypeAttribute : Attribute
{
    public int StatusCode { get; set; }
    public Type Type { get; set; }
    public string Description { get; set; }
    
    public ResponseTypeAttribute(int statusCode);
    public ResponseTypeAttribute(int statusCode, Type type);
}

Usage Example

[HttpGet("{id}")]
[ResponseType(200, typeof(User), Description = "User found and returned")]
[ResponseType(404, Description = "User not found")]
[ResponseType(400, typeof(ValidationError), Description = "Invalid user ID")]
public async Task<ActionResult<User>> GetUser(int id)
{
    // Implementation
}

SwaggerResponseAttribute

Legacy response specification attribute (maintained for backward compatibility).

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class SwaggerResponseAttribute : Attribute
{
    public int StatusCode { get; set; }
    public Type Type { get; set; }
    public string Description { get; set; }
    
    public SwaggerResponseAttribute(int statusCode, Type type = null, string description = null);
}

SwaggerDefaultResponseAttribute

Specifies the default response for an operation.

[AttributeUsage(AttributeTargets.Method)]
public class SwaggerDefaultResponseAttribute : Attribute
{
    public Type Type { get; set; }
    public string Description { get; set; }
    
    public SwaggerDefaultResponseAttribute(Type type = null, string description = null);
}

Control Attributes

OpenApiIgnoreAttribute

Excludes operations, parameters, or properties from OpenAPI generation.

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property)]
public class OpenApiIgnoreAttribute : Attribute
{
}

Usage Examples

// Ignore entire operation
[HttpGet("internal")]
[OpenApiIgnore]
public ActionResult InternalOperation()
{
    // This operation won't appear in OpenAPI spec
}

// Ignore parameter
[HttpGet]
public ActionResult GetData(
    string publicParam,
    [OpenApiIgnore] string internalParam)
{
    // internalParam won't appear in OpenAPI spec
}

// Ignore property in model
public class User
{
    public string Name { get; set; }
    
    [OpenApiIgnore]
    public string InternalId { get; set; }
}

OpenApiControllerAttribute

Specifies controller-level metadata.

[AttributeUsage(AttributeTargets.Class)]
public class OpenApiControllerAttribute : Attribute
{
    public string Name { get; set; }
    public string Description { get; set; }
}

Usage Example

[OpenApiController(
    Name = "User Management",
    Description = "API endpoints for managing user accounts"
)]
public class UsersController : ControllerBase
{
    // Controller actions
}

Extension and Processing Attributes

OpenApiExtensionDataAttribute

Adds custom extension data to operations.

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class OpenApiExtensionDataAttribute : Attribute
{
    public string Key { get; set; }
    public object Value { get; set; }
    
    public OpenApiExtensionDataAttribute(string key, object value);
}

Usage Example

[HttpPost]
[OpenApiExtensionData("x-rate-limit", 100)]
[OpenApiExtensionData("x-cache-duration", "5m")]
public async Task<ActionResult> CreateResource(CreateResourceRequest request)
{
    // Implementation
}

OpenApiOperationProcessorAttribute

Specifies a custom operation processor for an operation.

[AttributeUsage(AttributeTargets.Method)]
public class OpenApiOperationProcessorAttribute : Attribute
{
    public Type Type { get; set; }
    public object[] Arguments { get; set; }
    
    public OpenApiOperationProcessorAttribute(Type type, params object[] arguments);
}

Usage Example

[HttpGet]
[OpenApiOperationProcessor(typeof(CustomOperationProcessor), "customArgument")]
public ActionResult GetData()
{
    // Custom processor will be applied to this operation
}

// Custom processor implementation
public class CustomOperationProcessor : IOperationProcessor
{
    private readonly string _argument;
    
    public CustomOperationProcessor(string argument)
    {
        _argument = argument;
    }
    
    public bool Process(OperationProcessorContext context)
    {
        // Custom processing logic
        return true;
    }
}

Special Behavior Attributes

WillReadBodyAttribute

Indicates that an operation will read the request body, affecting parameter binding.

[AttributeUsage(AttributeTargets.Method)]
public class WillReadBodyAttribute : Attribute
{
}

Usage Example

[HttpPost]
[WillReadBody]
public async Task<ActionResult> ProcessData([FromBody] string rawData)
{
    // This operation reads the raw request body
}

Comprehensive Example

Here's a comprehensive example showing multiple annotations working together:

[ApiController]
[Route("api/[controller]")]
[OpenApiController(
    Name = "User Management API",
    Description = "Complete user lifecycle management"
)]
[OpenApiTag(
    Name = "Users",
    Description = "User account operations",
    ExternalDocumentationUrl = "https://docs.example.com/users"
)]
public class UsersController : ControllerBase
{
    [HttpGet]
    [OpenApiOperation(
        OperationId = "GetAllUsers",
        Summary = "List all users",
        Description = "Retrieves a paginated list of all users in the system"
    )]
    [ResponseType(200, typeof(PagedResult<User>), Description = "Users retrieved successfully")]
    [ResponseType(400, typeof(ValidationError), Description = "Invalid pagination parameters")]
    [OpenApiExtensionData("x-rate-limit", 1000)]
    public async Task<ActionResult<PagedResult<User>>> GetUsers(
        [FromQuery] int page = 1,
        [FromQuery] int size = 20,
        [OpenApiIgnore] string internalFilter = null)
    {
        // Implementation
    }

    [HttpGet("{id}")]
    [OpenApiOperation(
        OperationId = "GetUserById",
        Summary = "Get user by ID",
        Description = "Retrieves a specific user by their unique identifier"
    )]
    [ResponseType(200, typeof(User), Description = "User found")]
    [ResponseType(404, Description = "User not found")]
    [ResponseType(400, typeof(ValidationError), Description = "Invalid user ID")]
    public async Task<ActionResult<User>> GetUser(int id)
    {
        // Implementation
    }

    [HttpPost]
    [OpenApiOperation(
        OperationId = "CreateUser",
        Summary = "Create new user",
        Description = "Creates a new user account with the provided information"
    )]
    [OpenApiTags("Users", "Creation")]
    [ResponseType(201, typeof(User), Description = "User created successfully")]
    [ResponseType(400, typeof(ValidationError), Description = "Invalid user data")]
    [ResponseType(409, Description = "User already exists")]
    public async Task<ActionResult<User>> CreateUser(
        [OpenApiBodyParameter(
            Name = "user",
            Description = "User information for account creation",
            Required = true
        )] CreateUserRequest request)
    {
        // Implementation
    }

    [HttpPost("{id}/avatar")]
    [OpenApiOperation(
        OperationId = "UploadUserAvatar",
        Summary = "Upload user avatar",
        Description = "Uploads an avatar image for the specified user"
    )]
    [ResponseType(200, typeof(User), Description = "Avatar uploaded successfully")]
    [ResponseType(400, typeof(ValidationError), Description = "Invalid file or user ID")]
    [ResponseType(404, Description = "User not found")]
    public async Task<ActionResult<User>> UploadAvatar(
        int id,
        [OpenApiFile(
            Name = "avatar",
            Description = "Avatar image file (JPEG, PNG, max 5MB)",
            Required = true
        )] IFormFile avatar)
    {
        // Implementation
    }

    [HttpDelete("{id}")]
    [OpenApiOperation(
        OperationId = "DeleteUser",
        Summary = "Delete user",
        Description = "Permanently deletes a user account and all associated data"
    )]
    [ResponseType(204, Description = "User deleted successfully")]
    [ResponseType(404, Description = "User not found")]
    [ResponseType(409, Description = "User cannot be deleted due to dependencies")]
    [OpenApiExtensionData("x-destructive", true)]
    public async Task<ActionResult> DeleteUser(int id)
    {
        // Implementation
    }

    [HttpGet("internal-stats")]
    [OpenApiIgnore] // This endpoint won't appear in OpenAPI documentation
    public ActionResult GetInternalStats()
    {
        // Internal operation not exposed in API documentation
    }
}

// Supporting models with annotations
public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
    
    [OpenApiIgnore] // Internal tracking field
    public DateTime InternalTimestamp { get; set; }
}

public class CreateUserRequest
{
    [Required]
    public string Name { get; set; }
    
    [Required]
    [EmailAddress]
    public string Email { get; set; }
    
    public string Bio { get; set; }
}

This comprehensive example demonstrates how annotations can be used to create rich, well-documented APIs with proper metadata, response specifications, and custom behaviors while maintaining clean separation between business logic and API documentation concerns.