Web API基础

一、架构设计与原理

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.csProgram.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状态码和验证机制
  • 采用依赖注入和异步编程模式
相关推荐
To_OC7 小时前
别再串行写 await 了,Promise.all 才是并行请求的正确打开方式
前端·javascript·promise
vipbic7 小时前
中后台越做越乱后,我用插件化把它救回来了
前端·vue.js
Hyyy7 小时前
Computer Use 适合做什么,不适合做什么——一次真实使用后的思考
前端
小和尚同志8 小时前
前端 AI 单元测试思考与落地
前端·人工智能·aigc
invicinble9 小时前
c端系统,其实更像一个信息展示平台
前端
李姆斯10 小时前
管理是否可以被完全量化
前端·产品经理·团队管理
名字还没想好☜10 小时前
Next.js 中间件实战:鉴权、重定向与 A/B 分流
开发语言·前端·javascript·中间件·react·next.js
广州灵眸科技有限公司11 小时前
瑞芯微RV1126B开发板(EASY-EAI-PI2) INI文件操作
java·前端·javascript·网络·人工智能
kaiking_g11 小时前
vue项目中,静态导入 vs 动态导入 详解
前端·javascript·vue.js
江华森11 小时前
Web 开发基础:HTTP 与 REST
前端·网络协议·http