跳到主要内容

API 分层

HTTP 接入层负责协议转换:路由、模型绑定、认证/权限特性、状态码和 Swagger 分组。业务查询、事务和状态变化由 Application Service 或 Domain Manager 完成。

Controller 在哪里

四个主业务模块已将大部分 Controller 拆到独立 HttpApi 项目:

业务边界Controller 项目Core 依赖
CmsKitsrc/Services/CmsKit/FreeKit.CmsKit.HttpApiFreeKit.CmsKit
Identitysrc/Services/Identity/FreeKit.Identity.HttpApiFreeKit.Identity
Membersrc/Services/Identity/FreeKit.Member.HttpApiFreeKit.Member
Platformsrc/Services/Platform/FreeKit.Platform.HttpApiFreeKit.Platform

Identity 还有四个历史上保留在 Infrastructure 项目中的 Controller:文件、公共附件、普通设置和管理设置,位于 FreeKit.Identity.Infrastructure/Application。文档和依赖图应如实保留这个例外,不要把它描述成纯持久化项目。

CmsKit HttpApi 按业务域继续组织:

Controllers/
├── Admin/
├── Community/
├── Content/
├── Discovery/
├── Engagement/
└── Governance/

路由与 Swagger 分组

当前没有全局的 Area 路由生成器。Controller 使用显式 [Route][ApiExplorerSettings] 只决定 Swagger 分组。

模块主要基础路由Swagger GroupName例外
Identity / Member/api/identity/*identity无统一 [Area] 要求
CmsKit 公共端/api/cms/*cms部分 Controller 带 [Area("cms")]
CmsKit 管理端/api/cms/admin/*cms-admin管理权限通常在 Action 上声明
Platform/api/plat/*plat/api/dailyhot/api/v1/* 是显式历史路由

真实示例:

[ApiExplorerSettings(GroupName = "cms")]
[Area("cms")]
[Route("api/cms/articles")]
[ApiController]
public sealed class ArticleController(IArticleService service)
: FreeKitController
{
[HttpGet("{id}")]
[AllowAnonymous]
public Task<ArticleDto> GetAsync(Guid id)
{
return service.GetAsync(id);
}
}

Area、模块 key 和 URL 前缀是独立信息。不要将 Platform 的 Area 写成 platform,也不要假设 [module] 会自动应用到所有 Controller。

PathBase

Host 在端点之前调用:

string pathBase = builder.Configuration
.GetValue<string>("ASPNETCORE_PATHBASE") ?? string.Empty;
app.UsePathBase(new PathString(pathBase));

开发环境主 Host 的 PathBase 是 /kit_api,因此文章地址是 /kit_api/api/cms/articles/{id};Controller 自身的 Route 仍写成 api/cms/articles,不要把部署前缀硬编码进模块。

没有通用 API Versioning

仓库当前没有基于 [ApiVersion]{version:apiVersion} 的统一版本协商配置。以下路径只是 Controller 写死的 URL:

  • /api/v1/classic-crypto
  • /api/v1/JSON
  • /api/v1/sm

它们不能证明整个 API 已启用版本控制。新增接口应延续所属模块现有路由;如果未来引入 API Versioning,需要先在 Web BuildingBlock 统一配置,再迁移 Controller。

Controller 基类与认证

  • KitApiControllerBase 只提供 [ApiController]
  • FreeKitController 额外提供 [Authorize],默认要求登录。
  • 匿名接口在 Action 或 Controller 上显式使用 [AllowAnonymous]
  • 当前用户和仓储应在 Application Service 中使用,不要向 Controller 基类虚构 CurrentUser 属性。

权限策略

仓库同时存在标准 policy 和 KitAuthorizeAttribute 两种写法。

标准 policy 示例来自 Identity:

[HttpGet]
[Authorize(IdentityPermissions.Users.GetList)]
public Task<PagedResultDto<UserDto>> GetListAsync(
[FromQuery] UserQuery query)
{
return userService.GetListAsync(query);
}

KitAuthorize 示例来自 Platform ShortUrl:

[HttpGet]
[KitAuthorize("Platform.ShortUrl", "短链接管理")]
public Task<PagedResultDto<ShortUrlDto>> GetListAsync(
[FromQuery] ShortUrlQuery query)
{
return shortUrlService.GetListAsync(query);
}

授权链路为:

  1. FreeKitController 或权限特性要求身份认证。
  2. KitAuthorizationPolicyProvider 为权限字符串动态创建 policy。
  3. ValidTokenHandler 校验当前 Token/会话状态。
  4. ValidPermissionHandler 通过 PermissionStore 检查用户、角色和岗位授权。

无效 Token 返回 401,Token 有效但缺少权限返回 403。权限扫描同步由 PermissionUtilPermissionManager.InitPermissionAsync 完成;主 Host 当前只在 DEBUG 下调用 MigrationStartAsync(),生产发布不能依赖启动时自动创建新权限,需在发布流程中显式迁移或初始化。

DTO 与 JSON 契约

Controller 的输入输出使用 Application/Contracts 中的请求和响应 DTO,不直接返回可变领域聚合。模型验证由 [ApiController] 和全局 InvalidModelStateResponseFactory 处理。

API 边界统一使用 Newtonsoft.Json:

  • 引用 Newtonsoft 特性,或依赖默认属性命名。
  • 不要在公开 DTO 上只写 [JsonPropertyName] 等 System.Text.Json 专属特性。
  • 外部 HTTP 客户端的内部 DTO 可以独立选择 System.Text.Json。

异步业务方法使用 Async 后缀;Controller Action 可以沿用 ASP.NET Core 命名习惯,但当前新代码也优先保持 Async 以便和 Service 对齐。

SignalR 也属于 HttpApi

  • CmsKitHttpApiModuleStartup.Configure 映射 /hubs/notifications
  • IdentityHttpApiModuleStartup.Configure 映射 /hubs/onlineuser

Hub 使用 ValidTokenHubFilter 并通过 Redis 扩展横向广播。后台 Host 只引用 Core 时不会暴露这些端点。

主 Host 文档入口

FreeKit.Host 当前注册五个 Swagger 文档:

  • v1
  • identity
  • plat
  • cms
  • cms-admin

开发地址分别挂在 https://localhost:7000/kit_api/swagger,RapiDoc 路由为 /kit_api/r

源码索引

  • src/BuildingBlocks/IGeekFan.FreeKit.Infrastructure/Application/FreeKitController.cs
  • src/BuildingBlocks/IGeekFan.FreeKit.Infrastructure/Authorization/KitAuthorizationPolicyProvider.cs
  • src/BuildingBlocks/IGeekFan.FreeKit.Infrastructure/Authorization/Permissions/KitAuthorizeAttribute.cs
  • src/Services/Host/FreeKit.Host/Program.cs
  • src/Services/CmsKit/FreeKit.CmsKit.HttpApi/Controllers
  • src/Services/Identity/FreeKit.Identity.HttpApi/Controllers
  • src/Services/Platform/FreeKit.Platform.HttpApi

相关文档