一、控制器设计:MVC架构的核心枢纽

在ASP.NET Core中,控制器是处理HTTP请求的"交通指挥中心"。它接收请求、协调业务逻辑,并返回响应。下面是一个典型的控制器示例,展示了RESTful风格的设计:

[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    private readonly IProductService _service;

    // 依赖注入服务层
    public ProductsController(IProductService service)
    {
        _service = service;
    }

    // GET: api/products
    [HttpGet]
    public async Task<IActionResult> GetAll()
    {
        var products = await _service.GetAllAsync();
        return Ok(products); // 200状态码 + JSON数据
    }

    // GET: api/products/5
    [HttpGet("{id}")]
    public async Task<IActionResult> GetById(int id)
    {
        var product = await _service.GetByIdAsync(id);
        if (product == null) return NotFound(); // 404处理
        return Ok(product);
    }
}

关键设计原则:

  1. 保持控制器"瘦"——仅处理HTTP相关逻辑
  2. 使用[ApiController]特性自动验证模型
  3. 通过ActionResult<T>明确返回类型

二、中间件集成:请求处理流水线

中间件就像洋葱的层层包裹,每个组件都能处理请求和响应。我们来看一个自定义日志中间件的实现:

public class RequestLogMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger _logger;

    public RequestLogMiddleware(
        RequestDelegate next, 
        ILogger<RequestLogMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        var stopwatch = Stopwatch.StartNew();
        
        try
        {
            await _next(context); // 调用下一个中间件
        }
        finally
        {
            stopwatch.Stop();
            _logger.LogInformation(
                $"请求 {context.Request.Path} 耗时 {stopwatch.ElapsedMilliseconds}ms");
        }
    }
}

// 在Startup中注册
public void Configure(IApplicationBuilder app)
{
    app.UseMiddleware<RequestLogMiddleware>();
    // 其他中间件...
}

典型应用场景:

  • 异常处理(UseExceptionHandler
  • 静态文件服务(UseStaticFiles
  • 身份验证(UseAuthentication

三、EF Core数据访问:优雅的数据库交互

Entity Framework Core提供了强大的LINQ查询能力。以下是带有事务管理的仓储模式示例:

public class ProductRepository : IProductRepository
{
    private readonly AppDbContext _context;

    public ProductRepository(AppDbContext context)
    {
        _context = context;
    }

    public async Task AddWithTransactionAsync(Product product)
    {
        using var transaction = await _context.Database.BeginTransactionAsync();
        
        try
        {
            await _context.Products.AddAsync(product);
            await _context.SaveChangesAsync();
            
            // 模拟关联操作
            await _context.ProductLogs.AddAsync(
                new ProductLog { ProductId = product.Id, Action = "Create" });
                
            await _context.SaveChangesAsync();
            await transaction.CommitAsync();
        }
        catch
        {
            await transaction.RollbackAsync();
            throw;
        }
    }

    // 复杂查询示例
    public async Task<List<Product>> GetExpensiveProductsAsync(decimal minPrice)
    {
        return await _context.Products
            .Where(p => p.Price > minPrice)
            .Include(p => p.Category) // 加载关联数据
            .OrderByDescending(p => p.Price)
            .AsNoTracking() // 只读场景优化
            .ToListAsync();
    }
}

性能优化技巧:

  1. 使用AsNoTracking减少内存开销
  2. 通过Include/ThenInclude控制关联加载
  3. 批量操作考虑ExecuteUpdate/ExecuteDelete(EF Core 7+)

四、综合应用场景与技术选型

电商系统案例:

// 组合中间件、控制器和EF Core的完整流程
[Authorize]
[ApiController]
public class OrderController : ControllerBase
{
    private readonly IOrderService _service;

    [HttpPost("checkout")]
    public async Task<IActionResult> Checkout([FromBody] CheckoutDto dto)
    {
        // 模型验证自动执行(得益于[ApiController])
        var result = await _service.ProcessOrderAsync(
            User.GetUserId(), // 从认证中间件获取用户ID
            dto.Items);
            
        return result.Success ? 
            Ok(new { OrderId = result.OrderId }) : 
            BadRequest(result.Error);
    }
}

技术对比:
| 方案 | 优点 | 缺点 | |---------------|--------------------------|-----------------------| | 原生ADO.NET | 极致性能 | 开发效率低 | | Dapper | 轻量级,适合简单查询 | 复杂映射需要手工处理 | | EF Core | 开发体验好,功能全面 | 学习曲线较陡 |

五、注意事项与最佳实践

  1. 并发控制

    [HttpPut("{id}")]
    public async Task<IActionResult> UpdateProduct(
        int id, 
        [FromBody] ProductUpdateDto dto)
    {
        var product = await _context.Products
            .FirstOrDefaultAsync(p => p.Id == id);
    
        if (product == null) return NotFound();
    
        // 乐观并发检查
        if (product.Version != dto.Version)
            return Conflict("数据已被修改");
    
        // 更新操作...
    }
    
  2. 安全建议

    • 始终使用参数化查询防止SQL注入
    • 生产环境禁用开发人员异常页面
    • 实施适当的CORS策略
  3. 性能陷阱

    • N+1查询问题(可通过Include或显式加载避免)
    • 大对象序列化(考虑使用[JsonIgnore]或DTO投影)

六、总结与展望

现代ASP.NET Core开发已经形成了清晰的模式:精简的控制器作为入口,可插拔的中间件处理横切关注点,EF Core提供高效的数据库访问。随着.NET 8的发布,诸如原生AOT编译、改进的Minimal API等特性将进一步丰富技术选型。建议在实际项目中根据团队熟悉度和业务复杂度,在开发效率与运行时性能之间找到平衡点。