# TodoList **Repository Path**: ymjake/todo-list ## Basic Information - **Project Name**: TodoList - **Description**: 这是一个专注于垂直切片架构的学习模板 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-02-28 - **Last Updated**: 2026-07-14 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # TodoList `TodoList` 是一个小型 ASP.NET Core 示例项目,定位是一个偏务实的 Vertical Slice Architecture 模板。 业务本身刻意保持简单:用户注册、登录,然后对待办事项进行创建、查询、完成和删除。重点不在业务复杂度,而在于用一个足够小的项目把接口分层、CQRS、验证、持久化、日志和本地编排这些工程能力串起来。 ## 项目结构 - `src/TodoList.Api`:Minimal API、功能切片、领域模型、EF Core、Dapper 查询、认证授权、Swagger、API 版本控制、组合根 - `src/Aspire.AppHost`:Aspire 编排,负责启动 Api、PostgreSQL、Seq - `src/Aspire.ServiceDefaults`:Aspire Service Defaults、健康检查、服务发现、OpenTelemetry 基础配置 - `tests/TodoList.IntegrationTests`:基于 Aspire 的 HTTP / 数据库切片集成测试 ## 技术特点 - Vertical Slice Architecture - 自定义轻量 CQRS 分发 + 装饰器 - FluentValidation - Minimal APIs - API Versioning - Swagger / OpenAPI - JWT 认证 - EF Core + PostgreSQL - Dapper 读侧支持 - OpenTelemetry + Seq - 数据初始化 - xUnit、Shouldly、Respawn、Aspire 集成测试 - AspNetCore常用中间件配置 ## 当前实现亮点 ### 1. 不依赖第三方中介者库 项目没有继续使用 `MediatR` 或 `Mediator.SourceGenerator`,而是改成了项目内自己的轻量 CQRS 分发实现: - `ICommandDispatcher` - `IQueryDispatcher` - 基于运行时请求类型缓存 handler wrapper 这样可以保留 CQRS 的代码组织方式,同时减少额外依赖,也更方便后续继续演进自己的基础设施抽象。 ### 2. 横切逻辑通过装饰器处理 日志和验证没有堆在 endpoint 或 dispatcher 里,而是通过开放泛型装饰器挂在 handler 外层: - `ValidationDecorator` - `LoggingDecorator` 这样 handler 本身只关心业务,结构更接近真实项目中可演进的写法。 ### 3. CORS 采用白名单配置 模板没有使用 `AllowAnyOrigin` 作为默认策略,而是通过 `Cors:AllowedOrigins` 做来源白名单,并把 CORS 精确应用到版本化 API 路由组上,更适合作为可复用模板。 ## 主要接口 所有业务接口统一挂在 `/api/v1` 下: - `POST /api/v1/users/register` - `POST /api/v1/users/login` - `GET /api/v1/users/me` - `POST /api/v1/todos` - `GET /api/v1/todos` - `GET /api/v1/todos/{id}` - `PUT /api/v1/todos/{id}/complete` - `DELETE /api/v1/todos/{id}` ## 启动方式 使用 Aspire AppHost 启动完整本地环境: ```powershell dotnet run --project src\Aspire.AppHost\Aspire.AppHost.csproj ``` 启动后可通过 Aspire Dashboard 访问: - Api - PostgreSQL - Seq 如果单独启动 Api,需要自行提供 `ConnectionStrings:Database`: ```powershell dotnet run --project src\TodoList.Api\TodoList.Api.csproj ``` Swagger 地址: ```text http://localhost:5000/swagger ``` ## 验证 ```powershell dotnet build TodoList.slnx dotnet test tests\TodoList.IntegrationTests\TodoList.IntegrationTests.csproj ``` 测试策略以切片集成测试为主,从 HTTP 入口验证路由、认证授权、验证器装饰器、ProblemDetails、持久化和重要业务分支。 受保护接口的集成测试参考 Microsoft 官方的 Mock authentication 做法:测试宿主使用 `WebApplicationFactory` / `ConfigureTestServices` 注册 `TestAuthHandler`,通过 `Authorization: TestScheme` 注入测试用户 claims。这样 `Todos` 这类 slice 测试不需要真实调用 `Register/Login` 获取 JWT,避免不同 slice 的测试互相耦合。参考文档: 当前测试基础设施中,Aspire 负责启动真实 PostgreSQL,`WebApplicationFactory` 负责启动可替换 DI 的测试 API host,`TestAuthHandler` 只存在于测试项目中。 当前领域模型保持轻量,没有为薄 handler 保留专门的单元测试项目。后续如果出现真正复杂的领域逻辑,例如状态机、日期规则、优先级策略或重复任务生成规则,可以把逻辑提取到领域模型、领域服务或普通策略类中,再补充无基础设施依赖的快速单元测试。 集成测试依赖 `Aspire.Hosting.Testing`,需要本地可用的 Docker 或兼容容器运行时。 ## 项目说明 这个项目的领域规模故意很小,目标不是做一个功能丰富的待办系统,而是沉淀一个更适合继续扩展的 ASP.NET Core 项目骨架。 如果后面继续往上加模块,可以自然承接: - 更复杂的 CQRS 场景 - 更完整的授权模型 - 领域事件 / Outbox - 缓存与限流策略 - 更细粒度的观测和运维能力