ASP.NET Core MVC API 开发与调用规范文档
📋 文档概述
本文档记录了关于 ASP.NET Core MVC 中 API 控制器设计与客户端调用的详细讨论,包含参数绑定机制、安全最佳实践和多种客户端调用示例。
🏗️ 控制器架构
1. 基础控制器结构
namespace ddnsMainWeb.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class DnsHostController : ControllerBase
{
// 依赖注入
private readonly JsaitContext _db;
private readonly DnsApiService _dnsApiService;
private readonly IConfiguration _configuration;
private readonly ILogger<DnsHostController> _logger;
// 构造函数
public DnsHostController(
JsaitContext db,
DnsApiService dnsApiService,
IConfiguration configuration,
ILogger<DnsHostController> logger)
{
_db = db;
_dnsApiService = dnsApiService;
_configuration = configuration;
_logger = logger;
}
}
}
2. 请求/响应模型
// 请求模型
public class GetHostIpRequest { public string host { get; set; } }
public class ScriptUpdateIpRequest { public string username { get; set; } public string password { get; set; } public string client_ip { get; set; } }
public class ClientUpdateIpRequest { public string Token { get; set; } public string client_ip { get; set; } }
// 统一响应模型
public class DnsHostResponse
{
public bool success { get; set; }
public string message { get; set; }
public object data { get; set; }
}
🔐 API 安全设计
1. API Key 验证机制
// 在每个端点中验证 API Key
var apiKeyHeader = Request.Headers["X-Api-Key"].FirstOrDefault();
var expectedApiKey = _configuration["ClientConnectApi:ApiKey"];
if (string.IsNullOrEmpty(apiKeyHeader) || apiKeyHeader != expectedApiKey)
{
return Unauthorized(new DnsHostResponse
{
success = false,
message = "无效的API密钥"
});
}
2. 参数验证策略
// 必填参数验证
if (string.IsNullOrEmpty(host))
{
return BadRequest(new DnsHostResponse
{
success = false,
message = "主机名不能为空"
});
}
// IP 地址格式验证
if (!Tools.IsValidIp(request.client_ip))
{
return BadRequest(new DnsHostResponse
{
success = false,
message = "无效的IP地址格式"
});
}
🌐 API 端点设计
1. GET /api/DnsHost/get-ip - 获取主机IP地址
功能: 根据主机名查询当前DNS记录
参数绑定方式对比:
| 方式 | 代码示例 | 绑定源 | 特点 |
|---|---|---|---|
| 显式绑定 | [FromQuery] string host |
仅查询字符串 | 安全、明确 |
| 隐式绑定 | string host |
多源自动绑定 | 灵活但有风险 |
推荐使用显式绑定:
[HttpGet("get-ip")]
public async Task<IActionResult> GetHostIp([FromQuery] string host)
2. POST /api/DnsHost/script-update-ip - 脚本更新IP
功能: 通过用户名密码验证更新DNS记录
[HttpPost("script-update-ip")]
public async Task<IActionResult> ScriptUpdateIp([FromBody] ScriptUpdateIpRequest request)
3. POST /api/DnsHost/client-update-ip - 客户端更新IP
功能: 通过Token验证更新DNS记录
[HttpPost("client-update-ip")]
public async Task<IActionResult> ClientUpdateIp([FromBody] ClientUpdateIpRequest request)
📡 客户端调用示例
1. C# HttpClient 调用
public async Task<DnsHostResponse> GetHostIpAsync(string host)
{
_httpClient.DefaultRequestHeaders.Add("X-Api-Key", _apiKey);
string url = $"/api/DnsHost/get-ip?host={Uri.EscapeDataString(host)}";
var response = await _httpClient.GetAsync(url);
// ... 处理响应
}
2. curl 命令行调用
curl -X GET "https://api.example.com/api/DnsHost/get-ip?host=example.com" \
-H "X-Api-Key: your-api-key" \
-H "Content-Type: application/json"
3. PowerShell 调用
$headers = @{
"X-Api-Key" = $apiKey
"Content-Type" = "application/json"
}
$response = Invoke-RestMethod -Uri $url -Method GET -Headers $headers
4. JavaScript/TypeScript 调用
const response = await fetch(apiUrl, {
method: 'GET',
headers: {
'X-Api-Key': apiKey,
'Content-Type': 'application/json'
}
});
5. Python 调用
headers = {
"X-Api-Key": api_key,
"Content-Type": "application/json"
}
response = requests.get(url, headers=headers, params=params)
⚠️ 安全最佳实践
1. 参数绑定安全
- 始终使用显式绑定 (
[FromQuery],[FromBody],[FromRoute]) - 避免隐式多源绑定,防止意外数据注入
- 验证所有输入参数的来源和格式
2. API 密钥管理
- 使用配置系统管理 API Key
- 通过请求头传递 API Key
- 实现统一的验证中间件
3. 错误处理
- 使用统一的响应格式
- 记录详细的错误日志
- 不向客户端暴露敏感信息
4. 输入验证
// 多层级验证
if (string.IsNullOrEmpty(host)) // 空值检查
if (!Tools.IsValidIp(ip)) // 格式验证
if (host.Length > 255) // 长度限制
if (!Regex.IsMatch(host, @"^[a-zA-Z0-9.-]+$")) // 正则验证
🔄 参数绑定机制详解
ASP.NET Core 默认绑定顺序
- 查询字符串 (Query string)
- 路由值 (Route values)
- 表单数据 (Form data)
- 请求头 (Request headers)
- 请求体 (Request body)
显式绑定属性
[FromQuery]- 从查询字符串绑定[FromRoute]- 从路由参数绑定[FromForm]- 从表单数据绑定[FromBody]- 从请求体绑定[FromHeader]- 从请求头绑定
🛠️ 开发建议
1. 控制器设计原则
- 每个控制器关注单一业务领域
- 使用异步编程模式
- 实现统一的异常处理
- 记录关键操作日志
2. API 设计规范
- RESTful 风格 URL 设计
- 统一的响应格式
- 适当的 HTTP 状态码
- 版本化 API 端点
3. 性能优化
// 数据库查询优化
var dnsRecord = await _db.DnsRecords
.Where(d => d.Hostname == host && d.Status == 1)
.OrderByDescending(d => d.FreshDatetime)
.FirstOrDefaultAsync(); // 使用 FirstOrDefaultAsync 而非 ToListAsync
// 及时释放资源
using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
// 数据库操作
}
📊 响应状态码规范
| 状态码 | 含义 | 使用场景 |
|---|---|---|
| 200 OK | 请求成功 | 正常响应 |
| 400 Bad Request | 请求参数错误 | 参数验证失败 |
| 401 Unauthorized | 未授权 | API Key 无效 |
| 404 Not Found | 资源不存在 | DNS 记录不存在 |
| 500 Internal Server Error | 服务器内部错误 | 未处理的异常 |
🔍 调试与测试
1. 使用 Postman 测试
- 方法: GET
- URL:
https://localhost:5001/api/DnsHost/get-ip?host=example.com - Headers:
X-Api-Key: your-api-keyContent-Type: application/json
2. 日志记录策略
// 信息级别日志
_logger.LogInformation($"DNS记录更新成功: {hostname} -> {ip}");
// 警告级别日志
_logger.LogWarning($"DNS记录更新失败: {hostname} - API返回失败");
// 错误级别日志
_logger.LogError(ex, $"DNS记录更新异常: {hostname} - {ex.Message}");
📝 总结要点
- 参数绑定:优先使用显式绑定 (
[FromQuery]) 而非隐式绑定 - 安全第一:始终验证输入参数和 API 密钥
- 统一响应:使用标准化的响应格式
- 错误处理:实现全面的异常处理和日志记录
- 客户端兼容:提供多种客户端调用示例
- API 设计:遵循 RESTful 原则和 HTTP 语义
文档版本: 1.0
最后更新: $(date)
相关项目: ddnsMainWeb