前言
ASP.NET Core Web API提供了强大的框架来构建RESTful服务。本文将系统介绍Web API的核心概念、最佳实践和实用技巧,帮助开发者快速掌握API开发技能。
文章目录
- 前言
- 一、架构设计与原理
- 二、控制器开发详解
- 三、HTTP动词与RESTful设计
- 四、路由配置与参数绑定
- 五、数据验证与错误处理
- 六、状态码最佳实践
- 七、配置与启动
- 总结
一、架构设计与原理
Web API基于HTTP协议,遵循RESTful设计原则。它将应用程序的业务功能通过统一的接口暴露给客户端,实现前后端分离的架构模式。
二、控制器开发详解
控制器是Web API的核心组件,负责处理HTTP请求并返回响应。使用 [ApiController]
特性可以启用API相关的行为增强。
[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();}
}
三、HTTP动词与RESTful设计
RESTful API使用HTTP动词表示不同的操作类型,每个动词都有特定的语义和用途:
最佳实践:
- GET:幂等且安全,用于查询数据
- POST:非幂等,用于创建资源
- PUT:幂等,用于完整替换资源
- DELETE:幂等,用于删除资源
四、路由配置与参数绑定
ASP.NET Core提供了灵活的路由系统,支持多种参数绑定方式:
[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);}
}
五、数据验证与错误处理
数据验证是API安全性和稳定性的重要保障:
// 数据传输对象 (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));}
}
六、状态码最佳实践
正确使用HTTP状态码可以提升API的可读性和用户体验:
// 成功响应
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 - 服务器错误
七、配置与启动
在 Startup.cs
或 Program.cs
中配置Web API服务:
// 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();
总结
Web API开发的核心在于设计清晰的接口契约、处理好数据验证和错误情况,以及遵循RESTful原则。通过合理的架构设计和代码组织,可以构建出高质量、易维护的API服务。
关键要点:
- 使用
[ApiController]
启用API增强功能 - 实施完整的CRUD操作和错误处理
- 合理使用HTTP状态码和验证机制
- 采用依赖注入和异步编程模式
推荐学习资源:
- ASP.NET Core Web API 官方文档
- REST API 设计指南
- HTTP状态码完整参考