- Introduced new documentation for Agent Skills, detailing best practices, code patterns, common pitfalls, and quick references across various categories such as Architecture, Data Access, Security, Error Handling, Testing, Infrastructure, Communication, and Documentation. - The documentation is structured to facilitate easy navigation and understanding, supporting developers in implementing consistent patterns on the GoodGo Platform. - Both English and Vietnamese versions are provided to ensure accessibility for a wider audience.
220 lines
6.0 KiB
Markdown
220 lines
6.0 KiB
Markdown
# Tiêu Chuẩn Thiết Kế RESTful API
|
|
|
|
> **Skill**: `api-design`
|
|
> **Compatibility**: .NET 10+, ASP.NET Core, MediatR, Swashbuckle, Asp.Versioning
|
|
|
|
## Tổng Quan
|
|
|
|
Skill này cung cấp tiêu chuẩn thiết kế RESTful APIs nhất quán, dễ bảo trì cho GoodGo microservices. Bao gồm tích hợp MediatR, response wrappers, OpenAPI documentation, và chiến lược versioning.
|
|
|
|
## Khi Nào Sử Dụng
|
|
|
|
Áp dụng skill này khi:
|
|
- Tạo API endpoints mới
|
|
- Thiết kế request/response DTOs
|
|
- Triển khai controllers với MediatR
|
|
- Viết tài liệu OpenAPI/Swagger
|
|
- Chuẩn hóa error responses
|
|
- Triển khai pagination và filtering
|
|
|
|
## Khái Niệm Cốt Lõi
|
|
|
|
### 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
|
|
```
|
|
|
|
### Response API Chuẩn
|
|
|
|
Tất cả endpoints sử dụng response wrapper nhất quán:
|
|
|
|
```csharp
|
|
public class ApiResponse<T>
|
|
{
|
|
public bool Success { get; set; }
|
|
public T? Data { get; set; }
|
|
public string? Error { get; set; }
|
|
public PaginationInfo? Pagination { get; set; }
|
|
}
|
|
```
|
|
|
|
**Success response:**
|
|
```json
|
|
{ "success": true, "data": {...}, "pagination": {...} }
|
|
```
|
|
|
|
**Error response:**
|
|
```json
|
|
{ "success": false, "error": "Error message" }
|
|
```
|
|
|
|
### Cấu Trúc URL
|
|
|
|
```
|
|
/api/v{version}/{resource}/{id?}/{sub-resource?}
|
|
|
|
GET /api/v1/files # Liệt kê files
|
|
POST /api/v1/files # Tạo file
|
|
GET /api/v1/files/{id} # Lấy file theo ID
|
|
PUT /api/v1/files/{id} # Cập nhật file
|
|
DELETE /api/v1/files/{id} # Xóa file
|
|
GET /api/v1/files/{id}/versions # Lấy versions của file
|
|
```
|
|
|
|
## Bắt Đầu Nhanh
|
|
|
|
### 1. Tạo Controller với MediatR
|
|
|
|
```csharp
|
|
[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;
|
|
|
|
[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 ct = default)
|
|
{
|
|
var result = await _mediator.Send(new GetFileQuery(fileId), ct);
|
|
|
|
return result == null
|
|
? NotFound(new ApiResponse<FileDto> { Success = false, Error = "File not found" })
|
|
: Ok(new ApiResponse<FileDto> { Success = true, Data = result });
|
|
}
|
|
}
|
|
```
|
|
|
|
### 2. Sử Dụng Record DTOs
|
|
|
|
```csharp
|
|
public record FileDto(
|
|
Guid Id,
|
|
string UserId,
|
|
string FileName,
|
|
string ContentType,
|
|
long FileSizeBytes,
|
|
string AccessLevel,
|
|
DateTime UploadedAt);
|
|
```
|
|
|
|
### 3. Triển Khai Pagination
|
|
|
|
```csharp
|
|
[HttpGet]
|
|
public async Task<ActionResult<ApiResponse<UserFilesResult>>> GetFiles(
|
|
[FromQuery] int skip = 0,
|
|
[FromQuery] int take = 20,
|
|
CancellationToken ct = default)
|
|
{
|
|
var result = await _mediator.Send(new GetUserFilesQuery(skip, take), ct);
|
|
|
|
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))
|
|
});
|
|
}
|
|
```
|
|
|
|
## HTTP Methods & Status Codes
|
|
|
|
| Method | Hành Động | Success | Error Codes |
|
|
|--------|-----------|---------|-------------|
|
|
| **GET** | Lấy dữ liệu | 200 | 404 |
|
|
| **POST** | Tạo mới | 200/201 | 400, 409 |
|
|
| **PUT** | Cập nhật toàn bộ | 200 | 400, 404 |
|
|
| **PATCH** | Cập nhật một phần | 200 | 400, 404 |
|
|
| **DELETE** | Xóa | 200/204 | 404 |
|
|
|
|
## Mã Lỗi Phổ Biến
|
|
|
|
| Code | Ý Nghĩa | Khi Nào Dùng |
|
|
|------|---------|--------------|
|
|
| 400 | Bad Request | Lỗi validation |
|
|
| 401 | Unauthorized | Thiếu/sai token |
|
|
| 403 | Forbidden | Không có quyền |
|
|
| 404 | Not Found | Resource không tồn tại |
|
|
| 409 | Conflict | Resource trùng lặp |
|
|
| 422 | Unprocessable | Vi phạm business rule |
|
|
| 429 | Too Many Requests | Bị rate limit |
|
|
|
|
## Lỗi Thường Gặp Cần Tránh
|
|
|
|
### ❌ Response Format Không Nhất Quán
|
|
```csharp
|
|
// SAI: Trả về raw data
|
|
return Ok(result);
|
|
```
|
|
|
|
### ✅ Dùng Response Wrapper
|
|
```csharp
|
|
// ĐÚNG: Dùng ApiResponse wrapper
|
|
return Ok(new ApiResponse<FileDto> { Success = true, Data = result });
|
|
```
|
|
|
|
### ❌ Thiếu API Versioning
|
|
```csharp
|
|
// SAI: Không có versioning
|
|
[Route("api/files")]
|
|
```
|
|
|
|
### ✅ Có Version
|
|
```csharp
|
|
// ĐÚNG: Với API versioning
|
|
[ApiVersion("1.0")]
|
|
[Route("api/v{version:apiVersion}/files")]
|
|
```
|
|
|
|
### ❌ Comment Một Ngôn Ngữ
|
|
```csharp
|
|
// SAI: Chỉ tiếng Anh
|
|
/// <summary>Get file by ID.</summary>
|
|
```
|
|
|
|
### ✅ Tài Liệu Song Ngữ
|
|
```csharp
|
|
// ĐÚNG: Song ngữ EN/VI
|
|
/// <summary>
|
|
/// EN: Get file by ID.
|
|
/// VI: Lấy thông tin file theo ID.
|
|
/// </summary>
|
|
```
|
|
|
|
## Skills Liên Quan
|
|
|
|
- [CQRS & MediatR](./cqrs-mediatr.md) - Mẫu Command/Query
|
|
- [Xử Lý Lỗi](./error-handling-patterns.md) - Exception handling
|
|
- [Mẫu Testing](./testing-patterns.md) - API testing
|
|
- [Bảo Mật](./security.md) - Authentication & authorization
|
|
|
|
## Tài Nguyên Bổ Sung
|
|
|
|
- **Tài Liệu Skill Đầy Đủ**: [`.agent/skills/api-design/SKILL.md`](../../.agent/skills/api-design/SKILL.md)
|
|
- **Ví Dụ Code**: [`.agent/skills/api-design/references/REFERENCE.md`](../../.agent/skills/api-design/references/REFERENCE.md)
|
|
- **Quy Tắc Dự Án**: [Tiêu Chuẩn Dự Án](./project-rules.md)
|
|
|
|
---
|
|
|
|
**English Version**: [RESTful API Design Standards](../../en/skills/api-design.md)
|