--- name: api-design description: RESTful API design standards for GoodGo microservices. Use for new API endpoints, DTOs, controllers, OpenAPI documentation, or standardized responses. compatibility: ".NET 10+, ASP.NET Core, MediatR, Swashbuckle, Asp.Versioning" metadata: author: Velik Ho version: "2.0" --- # RESTful API Design Standards / Tiêu Chuẩn Thiết Kế RESTful API Standards for designing consistent, maintainable APIs in GoodGo microservices. ## When to Use This Skill / Khi Nào Sử Dụng Use this skill when: - Creating new API endpoints / Tạo API endpoints mới - Designing request/response DTOs / Thiết kế DTOs - Implementing controllers with MediatR / Triển khai controllers với MediatR - Writing OpenAPI/Swagger documentation / Viết tài liệu OpenAPI/Swagger - Standardizing error responses / Chuẩn hóa error responses - Implementing pagination, filtering / Triển khai pagination, filtering ## Core Concepts / Khái Niệm Cốt Lõi ### Clean Architecture Layers / Các Tầng Clean Architecture ``` src/ ├── ServiceName.API/ # Controllers, DTOs, Middleware │ ├── Controllers/ # API Controllers │ └── Application/ # Commands, Queries, Handlers ├── ServiceName.Domain/ # Entities, Aggregates, Interfaces └── ServiceName.Infrastructure/ # Repositories, External Services ``` ### API Response Wrapper / Wrapper Response Chuẩn ```csharp /// /// EN: Standard API response wrapper. /// VI: Wrapper response API chuẩn. /// public class ApiResponse { public bool Success { get; set; } public T? Data { get; set; } public string? Error { get; set; } public PaginationInfo? Pagination { get; set; } } public record PaginationInfo( int Page, int Limit, int Total, int TotalPages); ``` ### URL Structure / Cấu Trúc URL ``` /api/v{version}/{resource}/{id?}/{sub-resource?} GET /api/v1/files # List files POST /api/v1/files # Create file GET /api/v1/files/{id} # Get file by ID PUT /api/v1/files/{id} # Update file DELETE /api/v1/files/{id} # Delete file GET /api/v1/files/{id}/versions # Get file versions ``` ## Key Patterns / Mẫu Chính ### Controller with MediatR / Controller với MediatR ```csharp /// /// EN: Controller for file operations. /// VI: Controller cho các thao tác file. /// [ApiController] [ApiVersion("1.0")] [Route("api/v{version:apiVersion}/files")] [SwaggerTag("File Management - Upload, download, and manage files")] public class FilesController : ControllerBase { private readonly IMediator _mediator; public FilesController(IMediator mediator) { _mediator = mediator; } /// /// EN: Get file by ID. /// VI: Lấy thông tin file theo ID. /// [HttpGet("{fileId:guid}")] [Authorize] [SwaggerOperation(Summary = "Get file by ID")] [SwaggerResponse(200, "File retrieved successfully")] [SwaggerResponse(404, "File not found")] public async Task>> GetFile( Guid fileId, CancellationToken cancellationToken = default) { var userId = GetUserId(); if (string.IsNullOrEmpty(userId)) return Unauthorized(new ApiResponse { Success = false, Error = "User ID not found" }); var query = new GetFileQuery(fileId, userId); var result = await _mediator.Send(query, cancellationToken); if (result == null) return NotFound(new ApiResponse { Success = false, Error = "File not found" }); return Ok(new ApiResponse { Success = true, Data = result }); } private string? GetUserId() => User.FindFirstValue(ClaimTypes.NameIdentifier); } ``` ### DTO with Records / DTO với Records ```csharp /// /// EN: DTO for file information. /// VI: DTO cho thông tin file. /// public record FileDto( Guid Id, string UserId, string FileName, string ContentType, long FileSizeBytes, string AccessLevel, DateTime UploadedAt); /// /// EN: Result for user files query with pagination. /// VI: Kết quả query files với phân trang. /// public record UserFilesResult( IReadOnlyList Files, int TotalCount); /// /// EN: Mapper from domain entities to DTOs. /// VI: Mapper từ domain entities sang DTOs. /// public static class FileDtoMapper { public static FileDto ToDto(this StorageFile file) => new( file.Id, file.UserId, file.FileName, file.ContentType, file.FileSizeBytes, file.AccessLevel.ToString(), file.UploadedAt); } ``` ### Request Validation / Validation Request ```csharp /// /// EN: Command for file upload. /// VI: Command để upload file. /// public record UploadFileCommand( Stream FileStream, string FileName, string ContentType, long FileSize, string UserId, Guid? FolderId, FileAccessLevel AccessLevel) : IRequest; /// /// EN: Query for user files with pagination. /// VI: Query lấy files với phân trang. /// public record GetUserFilesQuery( string UserId, int Skip = 0, int Take = 20, string? Search = null) : IRequest; ``` ### List Endpoint with Pagination / Endpoint List với Phân Trang ```csharp [HttpGet] [Authorize] [SwaggerOperation(Summary = "Get user files")] public async Task>> GetFiles( [FromQuery] int skip = 0, [FromQuery] int take = 20, [FromQuery] string? search = null, CancellationToken cancellationToken = default) { var userId = GetUserId(); if (string.IsNullOrEmpty(userId)) return Unauthorized(new ApiResponse { Success = false, Error = "User ID not found" }); var query = new GetUserFilesQuery(userId, skip, take, search); var result = await _mediator.Send(query, cancellationToken); return Ok(new ApiResponse { Success = true, Data = result, Pagination = new PaginationInfo( Page: skip / take + 1, Limit: take, Total: result.TotalCount, TotalPages: (int)Math.Ceiling(result.TotalCount / (double)take)) }); } ``` ## Common Mistakes / Lỗi Thường Gặp ### 1. Inconsistent Response Format / Response Format Không Nhất Quán ```csharp // ❌ BAD: Trả về trực tiếp data return Ok(result); // ✅ GOOD: Dùng ApiResponse wrapper return Ok(new ApiResponse { Success = true, Data = result }); ``` ### 2. Missing API Versioning / Thiếu API Versioning ```csharp // ❌ BAD: Không có versioning [Route("api/files")] // ✅ GOOD: Có API versioning [ApiVersion("1.0")] [Route("api/v{version:apiVersion}/files")] ``` ### 3. No Bilingual XML Comments / Thiếu Comment Song Ngữ ```csharp // ❌ BAD: Chỉ tiếng Anh /// Get file by ID. // ✅ GOOD: Song ngữ EN/VI /// /// EN: Get file by ID. /// VI: Lấy thông tin file theo ID. /// ``` ### 4. Missing Swagger Annotations / Thiếu Swagger Annotations ```csharp // ❌ BAD: Không có Swagger annotations [HttpGet("{fileId:guid}")] public async Task> GetFile(Guid fileId) // ✅ GOOD: Đầy đủ Swagger annotations [HttpGet("{fileId:guid}")] [SwaggerOperation(Summary = "Get file by ID")] [SwaggerResponse(200, "File retrieved successfully")] [SwaggerResponse(404, "File not found")] public async Task>> GetFile(Guid fileId) ``` ### 5. Returning 200 for Errors / Trả 200 Cho Lỗi ```csharp // ❌ BAD: 200 cho error return Ok(new ApiResponse { Success = false, Error = "Not found" }); // ✅ GOOD: Đúng status code return NotFound(new ApiResponse { Success = false, Error = "File not found" }); ``` ## Quick Reference / Tham Chiếu Nhanh ### HTTP Methods & Status Codes | Method | Action | Success | Error Codes | |--------|--------|---------|-------------| | **GET** | Retrieve | 200 | 404 | | **POST** | Create | 200/201 | 400, 409 | | **PUT** | Full update | 200 | 400, 404 | | **PATCH** | Partial update | 200 | 400, 404 | | **DELETE** | Remove | 200/204 | 404 | ### Common Error Codes | Code | Meaning | When to Use | |------|---------|-------------| | 400 | Bad Request | Validation errors | | 401 | Unauthorized | Missing/invalid token | | 403 | Forbidden | No permission | | 404 | Not Found | Resource doesn't exist | | 409 | Conflict | Duplicate resource | | 422 | Unprocessable | Business rule violation | | 429 | Too Many Requests | Rate limited | ### Controller Attributes | Attribute | Purpose | |-----------|---------| | `[ApiController]` | Enable API behaviors | | `[ApiVersion("1.0")]` | API versioning | | `[Authorize]` | Require authentication | | `[SwaggerTag("Description")]` | Swagger grouping | | `[SwaggerOperation]` | Endpoint documentation | | `[SwaggerResponse]` | Response documentation | ### ApiResponse Format ```csharp // Success response { "success": true, "data": {...}, "pagination": {...} } // Error response { "success": false, "error": "Error message" } ``` ## Resources / Tài Nguyên - [API Versioning Strategy](../api-versioning-strategy/SKILL.md) - Versioning patterns - [Error Handling Patterns](../error-handling-patterns/SKILL.md) - Error handling - [Middleware Patterns](../middleware-patterns/SKILL.md) - Request handling - [Project Rules](../project-rules/SKILL.md) - Coding standards - [Skill Authoring](../skill-authoring/SKILL.md) - How to write skills