9.7 KiB
9.7 KiB
name, description, compatibility, metadata
| name | description | compatibility | metadata | ||||
|---|---|---|---|---|---|---|---|
| api-design | RESTful API design standards for GoodGo microservices. Use for new API endpoints, DTOs, controllers, OpenAPI documentation, or standardized responses. | .NET 10+, ASP.NET Core, MediatR, Swashbuckle, Asp.Versioning |
|
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
/// <summary>
/// EN: Standard API response wrapper.
/// VI: Wrapper response API chuẩn.
/// </summary>
public class ApiResponse<T>
{
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
/// <summary>
/// EN: Controller for file operations.
/// VI: Controller cho các thao tác file.
/// </summary>
[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;
}
/// <summary>
/// EN: Get file by ID.
/// VI: Lấy thông tin file theo ID.
/// </summary>
[HttpGet("{fileId:guid}")]
[Authorize]
[SwaggerOperation(Summary = "Get file by ID")]
[SwaggerResponse(200, "File retrieved successfully")]
[SwaggerResponse(404, "File not found")]
public async Task<ActionResult<ApiResponse<FileDto>>> GetFile(
Guid fileId,
CancellationToken cancellationToken = default)
{
var userId = GetUserId();
if (string.IsNullOrEmpty(userId))
return Unauthorized(new ApiResponse<FileDto>
{
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<FileDto>
{
Success = false,
Error = "File not found"
});
return Ok(new ApiResponse<FileDto> { Success = true, Data = result });
}
private string? GetUserId() =>
User.FindFirstValue(ClaimTypes.NameIdentifier);
}
DTO with Records / DTO với Records
/// <summary>
/// EN: DTO for file information.
/// VI: DTO cho thông tin file.
/// </summary>
public record FileDto(
Guid Id,
string UserId,
string FileName,
string ContentType,
long FileSizeBytes,
string AccessLevel,
DateTime UploadedAt);
/// <summary>
/// EN: Result for user files query with pagination.
/// VI: Kết quả query files với phân trang.
/// </summary>
public record UserFilesResult(
IReadOnlyList<FileDto> Files,
int TotalCount);
/// <summary>
/// EN: Mapper from domain entities to DTOs.
/// VI: Mapper từ domain entities sang DTOs.
/// </summary>
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
/// <summary>
/// EN: Command for file upload.
/// VI: Command để upload file.
/// </summary>
public record UploadFileCommand(
Stream FileStream,
string FileName,
string ContentType,
long FileSize,
string UserId,
Guid? FolderId,
FileAccessLevel AccessLevel) : IRequest<UploadFileResult>;
/// <summary>
/// EN: Query for user files with pagination.
/// VI: Query lấy files với phân trang.
/// </summary>
public record GetUserFilesQuery(
string UserId,
int Skip = 0,
int Take = 20,
string? Search = null) : IRequest<UserFilesResult>;
List Endpoint with Pagination / Endpoint List với Phân Trang
[HttpGet]
[Authorize]
[SwaggerOperation(Summary = "Get user files")]
public async Task<ActionResult<ApiResponse<UserFilesResult>>> 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<UserFilesResult>
{
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<UserFilesResult>
{
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
// ❌ BAD: Trả về trực tiếp data
return Ok(result);
// ✅ GOOD: Dùng ApiResponse wrapper
return Ok(new ApiResponse<FileDto> { Success = true, Data = result });
2. Missing API Versioning / Thiếu API Versioning
// ❌ 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ữ
// ❌ BAD: Chỉ tiếng Anh
/// <summary>Get file by ID.</summary>
// ✅ GOOD: Song ngữ EN/VI
/// <summary>
/// EN: Get file by ID.
/// VI: Lấy thông tin file theo ID.
/// </summary>
4. Missing Swagger Annotations / Thiếu Swagger Annotations
// ❌ BAD: Không có Swagger annotations
[HttpGet("{fileId:guid}")]
public async Task<ActionResult<FileDto>> 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<ActionResult<ApiResponse<FileDto>>> GetFile(Guid fileId)
5. Returning 200 for Errors / Trả 200 Cho Lỗi
// ❌ BAD: 200 cho error
return Ok(new ApiResponse<FileDto> { Success = false, Error = "Not found" });
// ✅ GOOD: Đúng status code
return NotFound(new ApiResponse<FileDto> { 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
// Success response
{ "success": true, "data": {...}, "pagination": {...} }
// Error response
{ "success": false, "error": "Error message" }
Resources / Tài Nguyên
- API Versioning Strategy - Versioning patterns
- Error Handling Patterns - Error handling
- Middleware Patterns - Request handling
- Project Rules - Coding standards
- Skill Authoring - How to write skills