一、架构设计与原理
Web API[基于HTTP协议],遵循RESTful设计原则。它将应用程序的业务功能通过统一的接口暴露给客户端,实现前后端分离的架构模式。
客户端
HTTP请求
路由系统
控制器
业务逻辑
数据访问
数据库
JSON响应
二、控制器开发详解
控制器是Web API的核心组件,负责处理HTTP请求并返回响应。使用 [ApiController]
特性可以启用API相关的行为增强。
csharp
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
private readonly IProductService _productService;
public ProductsController(IProductService productService)
{
_productService = productService; // 依赖注入
}
// GET: api/products - 获取所有产品
[HttpGet]
public async Task<ActionResult<IEnumerable<Product>>> GetProducts()
{
try
{
var products = await _productService.GetAllAsync();
return Ok(products);
}
catch (Exception ex)
{
return StatusCode(500, new { message = "获取产品失败", error = ex.Message });
}
}
// GET: api/products/5 - 根据ID获取产品
[HttpGet("{id:int}")]
public async Task<ActionResult<Product>> GetProduct(int id)
{
if (id <= 0)
return BadRequest("产品ID必须大于0");
var product = await _productService.GetByIdAsync(id);
return product == null ? NotFound($"未找到ID为{id}的产品") : Ok(product);
}
// POST: api/products - 创建新产品
[HttpPost]
public async Task<ActionResult<Product>> CreateProduct([FromBody] CreateProductDto productDto)
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
var product = await _productService.CreateAsync(productDto);
return CreatedAtAction(nameof(GetProduct), new { id = product.Id }, product);
}
// PUT: api/products/5 - 更新产品
[HttpPut("{id:int}")]
public async Task<IActionResult> UpdateProduct(int id, [FromBody] UpdateProductDto productDto)
{
if (id != productDto.Id)
return BadRequest("路径ID与请求体ID不匹配");
var updated = await _productService.UpdateAsync(productDto);
return updated ? NoContent() : NotFound();
}
// DELETE: api/products/5 - 删除产品
[HttpDelete("{id:int}")]
public async Task<IActionResult> DeleteProduct(int id)
{
var deleted = await _productService.DeleteAsync(id);
return deleted ? NoContent() : NotFound();
}
}
AI写代码csharp
运行
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
三、HTTP动词与RESTful设计
RESTful API使用HTTP动词表示不同的操作类型,每个动词都有特定的语义和用途:
GET
获取资源
POST
创建资源
PUT
完整更新
PATCH
部分更新
DELETE
删除资源
最佳实践:
- GET:幂等且安全,用于查询数据
- POST:非幂等,用于创建资源
- PUT:幂等,用于完整替换资源
- DELETE:幂等,用于删除资源
四、路由配置与参数绑定
ASP.NET Core提供了灵活的路由系统,支持多种参数绑定方式:
csharp
[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
// 路由约束示例
[HttpGet("{id:int:min(1)}")] // 整数且最小值为1
[HttpGet("name/{name:alpha}")] // 仅字母
[HttpGet("page/{page:int:range(1,100)}")] // 范围约束
// 复杂参数绑定
[HttpGet("search")]
public IActionResult SearchUsers(
[FromQuery] string keyword, // 查询字符串参数
[FromQuery] int page = 1, // 带默认值
[FromQuery] int pageSize = 10,
[FromHeader] string userAgent = "") // 请求头参数
{
var users = SearchUsers(keyword, page, pageSize);
return Ok(new
{
data = users,
pagination = new { page, pageSize, total = users.Count() },
userAgent
});
}
// 复杂对象绑定
[HttpPost("register")]
public async Task<IActionResult> Register(
[FromBody] UserRegisterDto request, // JSON请求体
[FromServices] IUserService userService) // 服务注入
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
var result = await userService.RegisterAsync(request);
return result.Success ? Ok(result) : BadRequest(result.Errors);
}
}
AI写代码csharp
运行
123456789101112131415161718192021222324252627282930313233343536373839
五、数据验证与错误处理
数据验证是API安全性和稳定性的重要保障:
csharp
// 数据传输对象 (DTO)
public class CreateProductDto
{
[Required(ErrorMessage = "产品名称不能为空")]
[StringLength(100, MinimumLength = 2, ErrorMessage = "产品名称长度应在2-100字符之间")]
public string Name { get; set; }
[Required]
[Range(0.01, double.MaxValue, ErrorMessage = "价格必须大于0")]
public decimal Price { get; set; }
[StringLength(500, ErrorMessage = "描述长度不能超过500字符")]
public string Description { get; set; }
[EmailAddress(ErrorMessage = "邮箱格式不正确")]
public string ContactEmail { get; set; }
}
// 全局异常处理中间件
public class GlobalExceptionMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<GlobalExceptionMiddleware> _logger;
public GlobalExceptionMiddleware(RequestDelegate next, ILogger<GlobalExceptionMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
_logger.LogError(ex, "处理请求时发生未处理的异常");
await HandleExceptionAsync(context, ex);
}
}
private async Task HandleExceptionAsync(HttpContext context, Exception exception)
{
context.Response.ContentType = "application/json";
var response = exception switch
{
ArgumentException => new { StatusCode = 400, Message = "参数错误", Details = exception.Message },
KeyNotFoundException => new { StatusCode = 404, Message = "资源未找到" },
UnauthorizedAccessException => new { StatusCode = 401, Message = "未授权访问" },
_ => new { StatusCode = 500, Message = "服务器内部错误" }
};
context.Response.StatusCode = response.StatusCode;
await context.Response.WriteAsync(JsonSerializer.Serialize(response));
}
}
AI写代码csharp
运行
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
六、状态码最佳实践
正确使用HTTP状态码可以提升API的可读性和用户体验:
kotlin
// 成功响应
return Ok(data); // 200 - 请求成功
return Created(location, data); // 201 - 资源已创建
return NoContent(); // 204 - 操作成功,无返回内容
// 客户端错误
return BadRequest(errors); // 400 - 请求格式错误
return Unauthorized(); // 401 - 未认证
return Forbid(); // 403 - 无权限
return NotFound(); // 404 - 资源不存在
return Conflict(); // 409 - 资源冲突
// 服务器错误
return StatusCode(500, message); // 500 - 服务器错误
AI写代码csharp
运行
1234567891011121314
七、配置与启动
在 Startup.cs
或 Program.cs
中配置Web API服务:
ini
// Program.cs (NET 6+)
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
// 自定义模型验证错误响应
options.InvalidModelStateResponseFactory = context =>
{
var errors = context.ModelState.Values
.SelectMany(v => v.Errors)
.Select(e => e.ErrorMessage);
return new BadRequestObjectResult(new { errors });
};
});
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(); // API文档
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
AI写代码csharp
运行
123456789101112131415161718192021222324252627282930313233
总结
Web API开发的核心在于设计清晰的接口契约、处理好数据验证和错误情况,以及遵循RESTful原则。通过合理的架构设计和代码组织,可以构建出高质量、易维护的API服务。
关键要点:
- 使用
[ApiController]
启用API增强功能 - 实施完整的CRUD操作和错误处理
- 合理使用HTTP状态码和验证机制
- 采用依赖注入和异步编程模式