Files
pos-system/microservices/docs/en/skills/api-design.md
Ho Ngoc Hai 76d75c753b Migrate
2026-05-23 18:37:02 +07:00

220 lines
5.8 KiB
Markdown

# RESTful API Design Standards
> **Skill**: `api-design`
> **Compatibility**: .NET 10+, ASP.NET Core, MediatR, Swashbuckle, Asp.Versioning
## Overview
This skill provides standards for designing consistent, maintainable RESTful APIs across GoodGo microservices. It covers MediatR integration, response wrappers, OpenAPI documentation, and versioning strategies.
## When to Use
Apply this skill when:
- Creating new API endpoints
- Designing request/response DTOs
- Implementing controllers with MediatR
- Writing OpenAPI/Swagger documentation
- Standardizing error responses
- Implementing pagination and filtering
## Key Concepts
### Clean Architecture Layers
```
src/
├── ServiceName.API/ # Controllers, DTOs, Middleware
│ ├── Controllers/ # API Controllers
│ └── Application/ # Commands, Queries, Handlers
├── ServiceName.Domain/ # Entities, Aggregates, Interfaces
└── ServiceName.Infrastructure/ # Repositories, External Services
```
### Standard API Response
All endpoints use a consistent response wrapper:
```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" }
```
### URL Structure
```
/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
```
## Quick Start
### 1. Create Controller with 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. Use Record DTOs
```csharp
public record FileDto(
Guid Id,
string UserId,
string FileName,
string ContentType,
long FileSizeBytes,
string AccessLevel,
DateTime UploadedAt);
```
### 3. Implement 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 | 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 |
## Common Mistakes to Avoid
### ❌ Inconsistent Response Format
```csharp
// BAD: Returning raw data
return Ok(result);
```
### ✅ Use Response Wrapper
```csharp
// GOOD: Using ApiResponse wrapper
return Ok(new ApiResponse<FileDto> { Success = true, Data = result });
```
### ❌ Missing API Versioning
```csharp
// BAD: No versioning
[Route("api/files")]
```
### ✅ Include Version
```csharp
// GOOD: With API versioning
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/files")]
```
### ❌ Single Language Comments
```csharp
// BAD: English only
/// <summary>Get file by ID.</summary>
```
### ✅ Bilingual Documentation
```csharp
// GOOD: EN/VI bilingual
/// <summary>
/// EN: Get file by ID.
/// VI: Lấy thông tin file theo ID.
/// </summary>
```
## Related Skills
- [CQRS & MediatR](./cqrs-mediatr.md) - Command/Query patterns
- [Error Handling](./error-handling-patterns.md) - Exception handling
- [Testing Patterns](./testing-patterns.md) - API testing
- [Security](./security.md) - Authentication & authorization
## Additional Resources
- **Full Skill Reference**: [`.agent/skills/api-design/SKILL.md`](../../.agent/skills/api-design/SKILL.md)
- **Code Examples**: [`.agent/skills/api-design/references/REFERENCE.md`](../../.agent/skills/api-design/references/REFERENCE.md)
- **Project Rules**: [Project Standards](./project-rules.md)
---
**Vietnamese Version**: [Tiêu Chuẩn Thiết Kế RESTful API](../../vi/skills/api-design.md)