跳到主要内容
版本:3.0.0

Controller

Controller 这一层别写重。
它主要做四件事:

  • 接收 HTTP 请求
  • 完成路由与参数绑定
  • 调用 ContractService
  • 通过 ApiControllerBase 返回标准响应

这些事情尽量别放在 Controller 里:

  • 直接编写复杂业务逻辑
  • 直接拼写 SQL
  • 直接把数据库实体返回给前端

一个常见写法

通常直接继承 ApiControllerBase

using Aegis.Core.Infrastructure.Controller;
using Aegis.Transfer.Responses;
using Aegis.Webapi.Contract;
using Microsoft.AspNetCore.Mvc;

namespace Aegis.Webapi.BaseDemo.Controllers;

public class UserController : ApiControllerBase
{
private readonly IUserContract _userService;
private readonly ILogger<UserController> _logger;

public UserController(IUserContract userService, ILogger<UserController> logger)
{
_userService = userService;
_logger = logger;
}

[HttpPost("GetUsers")]
public async Task<ApiResponse> GetUsers(GetUsersRequest request)
{
var result = await _userService.GetUsersAsync(request);
return SuccessListResult(result);
}
}

入参怎么放

简单参数直接写

idcode 这样的简单查询参数,可以直接放在方法签名中。

[HttpGet("GetUser")]
public async Task<ApiResponse> GetUser(long id)

复杂参数单独建 Request

只要参数开始变复杂,就建议建立 Request 类,并放在 Dto 项目的 Requests 目录中。

平时按下面几条写就够:

  • 统一使用 record
  • 优先使用 init
  • 为请求建立对应的 Validator
  • 不把数据库字段直接暴露给前端

示例:

public record GetUsersRequest
{
public string Name { get; init; }
public int Age { get; init; }
}

放在 Dto 项目的 Requests 目录下会比较顺手。

参数绑定

HttpPost 场景下,不带标记的复杂对象通常来自请求体。
如果你需要从查询串读取参数,可以显式标记 [FromQuery]

[HttpGet("GetList")]
public async Task<ApiResponse> GetList([FromQuery] PageListRequest request)

返回值怎么统一

对外公开的方法统一返回 ApiResponse
具体是单对象还是列表,不靠方法签名区分,而是靠 ApiControllerBase 里的返回方法区分。

具体可以看 ApiControllerBase

最小接口应该长什么样

最小闭环其实很简单:

  1. Request 进入 Controller
  2. Controller 调用 IUserContract 或具体 Service
  3. Service 从 Repository 获取数据
  4. Controller 使用 SuccessResultSuccessListResult 返回
  5. 在 Swagger 中可以直接调试验证

如果你想继续看返回包装和响应方法,接着读 ApiControllerBase