跳到主要内容

7.3 联调、验收与扩展

学习目标​

  • 分别验证 API 契约和 WPF 交互,定位错误所在边界。
  • 重现慢请求、取消、超时及 404,检查状态是否恢复。
  • 区分教学样例与持久化、多用户产品的工程要求。

从可观察的结果开始​

先在 Windows 安装 .NET 10 SDK,确认 dotnet --list-sdks 有 10.x;运行时列表不能证明具备编译工具。完整操作说明在本地 examples/TaskDesk/README.md。交付机器仅有运行时,不能把下面清单理解为已经在该机器完成的运行验收。

在仓库根目录构建两个项目,然后按 API 契约 先启动 API,再启动客户端:

dotnet build examples/TaskDesk/TaskDesk.Api/TaskDesk.Api.csproj
dotnet build examples/TaskDesk/TaskDesk.Client/TaskDesk.Client.csproj

确认 API 返回正确数组后,运行契约检查。脚本需要已运行的 API,会创建并清理临时任务,检查标题去空格、完成结果、查询、400、404 和删除的 204。

powershell -NoProfile -File examples/TaskDesk/Verify-Api.ps1

契约检查不涵盖绑定和窗口行为。以下 UI 验收必须另行完成。

场景观察结果
自动加载列表显示初始两条数据,状态栏显示已加载
空白输入新增不可用;服务端也拒绝直接提交空白标题
新增与完成标题去空格,新增默认未完成,完成后勾选更新
删除删除成功后移除行,清理被删除的选中项
API 不可用显示连接错误,窗口可移动,按钮恢复
选中项过期另一个客户端删除后,完成显示 404,刷新同步
忙碌四个操作按钮禁用,取消可用,状态文本可见
请求中关闭先取消等待,之后窗口与进程退出

主动制造慢请求​

本机 API 太快时,取消可能来不及按下,这不表示取消机制失效。为了验收,在 TaskDesk.Api/Program.cs 中临时替换原 GET 映射为下面完整映射,不要添加第二个同路由处理器,然后重启 API。原文件已导入 TodoStore;验收后恢复原映射。

Program.cs:临时慢请求映射
app.MapGet("/api/todos", async (TodoStore store, CancellationToken cancellationToken) =>
{
await Task.Delay(TimeSpan.FromSeconds(30), cancellationToken);
return Results.Ok(store.GetAll());
});

刷新后观察等待状态,点击取消,预期显示取消并恢复按钮。再次刷新且不取消,客户端 15 秒超时后显示超时。延迟使用异步等待,不能在窗口线程用 Thread.Sleep;否则界面连取消按钮都无法处理。

取消 token 中止的是等待和网络操作。若 POST 已经在 API 完成但响应未送达,客户端取消后仍可能没有显示新增任务。此时先刷新确认,直接重试可能产生重复记录。真正的产品可以增加幂等请求标识,不能靠按钮禁用保证网络级别的“只执行一次”。

按边界排查失败​

连接错误先独立访问 http://localhost:5080/api/todos,再检查输出目录的 appsettings.json。400 先看请求标题;404 先确认任务是否已被其他客户端删除。200 但列表不显示时,在调试输出检查绑定与 JSON,而不是继续修改 API。

命令恢复问题先检查 IsBusy 是否在 finally 中复位,以及它是否通知四个操作命令。UI 线程错误则检查集合是否从后台线程修改。Service 可以不捕获 UI 上下文,ViewModel 仍应在窗口线程恢复并更新集合,详见 异步线程。

扩展顺序​

先通过 ITodoService 注入可控测试桩:模拟延迟、400 和异常,验证忙碌及恢复;再把内存存储换成数据库,加入版本号并返回冲突;然后实施登录与服务端资源授权,最后处理分页、搜索、发布和日志。每一步都保持契约清晰,不要同时引入所有机制。

本例 typed client 在主窗口期间持有,适合固定本机地址。长期运行并访问远程服务时,还要规划连接池与 DNS 更新。用户令牌需要安全存储,服务端机密不能放进客户端配置。远程通信应采用可信 HTTPS,不通过关闭证书验证解决配置问题;参见 HTTP 与认证。

下一阶段见 Prism 进阶:用独立的 PrismStudy 学习容器、区域导航、对话框和模块,再按 实战扩展练习 将 TaskDesk API 接入任务服务。

常见问题​

为什么重新启动 API 后客户端仍有旧数据? 窗口状态不会自动随另一进程重置,主动刷新才能获得最新快照。

契约脚本通过是否等于项目通过? 它只证明运行中的 API 满足脚本断言;WPF 的通知、选择、取消和关闭还要验收。

练习与验收​

提交一份本地验收记录:SDK 版本、两项目构建结果、契约脚本结果、取消与超时各一次、请求中关闭一次。只填写实际观察到的结果。再为“取消新增后重复提交”设计验证步骤,并说明为何先刷新比直接重试更可靠。

官方资料​