220 lines
5.8 KiB
Markdown
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)
|