Crping.EFCore.Controller
10.2.2
dotnet add package Crping.EFCore.Controller --version 10.2.2
NuGet\Install-Package Crping.EFCore.Controller -Version 10.2.2
<PackageReference Include="Crping.EFCore.Controller" Version="10.2.2" />
<PackageVersion Include="Crping.EFCore.Controller" Version="10.2.2" />
<PackageReference Include="Crping.EFCore.Controller" />
paket add Crping.EFCore.Controller --version 10.2.2
#r "nuget: Crping.EFCore.Controller, 10.2.2"
#:package Crping.EFCore.Controller@10.2.2
#addin nuget:?package=Crping.EFCore.Controller&version=10.2.2
#tool nuget:?package=Crping.EFCore.Controller&version=10.2.2
Crping.EFCore.Controller
基于Crping.EFCore的WebApi的增、删、改、查、分页等常用方法实现!
版本更新说明
10.2.2
2026年9月15日 星期二
与
Crping.EFCore/Crping.EFCore.Common同步升至 10.2.2 —— ct 全量复查批次:端点签名零变更、升级零迁移、需重编译
行为增强 — 端点取消令牌透传(客户端断连即取消)
WebApiBaseController20 个端点将HttpContext.RequestAborted作为取消令牌透传 BLL:客户端中断请求后,进行中的 DB / 缓存操作随取消终止(此前会跑完无法取消)——经动作体透传而非签名加参,零签名变更不破坏子类 override;唯一例外UpdateAsync(单条更新链路 BLL → DAL params 形态暂无 ct 槽位,随 v10/v11 签名重构补齐,类 XML remarks 已注明)
健壮性 — 异常中间件取消令牌
ExceptionMiddleware写 ProblemDetails 响应补context.RequestAborted:客户端中断时错误响应写入可中途放弃- 客户端取消留痕日志加
logger.IsEnabled(LogLevel.Information)门控:禁用级别下不再白算日志参数(与 CacheManager 既有风格一致)
10.2.1
2026年9月15日 星期二
与
Crping.EFCore/Crping.EFCore.Common同步升至 10.2.1 —— 审计修复批次:公开 API 零变更、升级零迁移、需重编译
健壮性修复 — 异常中间件响应已开始守卫
ExceptionMiddlewarecatch-all 写响应前检查context.Response.HasStarted:响应开始后的异常(典型:动作返回体序列化中途失败/循环引用)记录告警后原样上抛——此前强设StatusCode会抛InvalidOperationException掘盖原始异常且客户端收到中断连接而非错误体(与 ASP.NET Core 内置异常处理的标准守卫一致;ExceptionMiddlewareTests新增"响应已开始"用例)
文档化
WebApiRootControllerXML 注释明示 BLL 必须以 Scoped 注册:控制器每请求向 BLL 写CurrentUserIdResolver(AsyncLocal,有流隔离)与CacheEnable(普通实例属性,无隔离),BLL 误注册为单例时后激活控制器会覆盖全局缓存开关、跨请求互踩
10.2.0
2026年9月14日 星期一
与
Crping.EFCore/Crping.EFCore.Common同步升至 10.2.0 —— 2 处破坏性变更 + 标注/透传补齐
破坏性变更 — 业务错误响应体统一 ProblemDetails
- 各端点 4xx/5xx 业务错误(
Error非 null)响应体由裸错误字符串(如"无权限")改为 RFC 7807ProblemDetails(Status/Title/Detail/Type,Content-Typeapplication/problem+json)——与端点ProducesResponseType(typeof(ProblemDetails))标注、异常路径(ExceptionHelper)三方一致,消费方按契约解析 4xx 不再失败;Error为 null 的纯状态码与 Data-only 载荷分支保持既有形态。按裸字符串解析业务错误的客户端需适配为problem.detail
破坏性变更 — soft/restore 成功码 200 → 204
DELETE {id}/soft与POST {id}/restore成功响应由 200 空体改 204(RFC 9110 不建议 200 无载荷,与 Update/toggle 族NoContent对齐);DELETE {id}(硬删)保持 200 + 被删实体不变——严格匹配 200 的客户端需适配
标注补齐
PATCH {id}/enable、PATCH {id}/audit、DELETE {id}/soft、POST {id}/restore补ProducesResponseType(typeof(ProblemDetails), 400)——BLL 对不支持接口的实体返回 BadRequest 但此前未在 OpenAPI 声明
新功能 — 批量审核透传 EnforceTransit
BatchAuditStatusRequest新增bool EnforceTransit(默认 false 向后兼容),PUT batch/audit/status可启用状态流转校验(BLL 能力此前未在 HTTP 面暴露)
行为改善 — 写后读绑定中间件 seed
ReadWriteRoutingMiddleware请求入口由复位写标志改 seed 全新请求状态对象(每请求私有实例,跨请求天然隔离),是写后读绑定标志可靠跨越 async 方法边界流动的前提(配合 Core 包持有者模式修复)
10.1.0
2026年9月13日 星期日
与
Crping.EFCore/Crping.EFCore.Common同步升至 10.1.0 —— kebab-case 路由风格组件化(新功能,零破坏性变更)
新功能 — AddEFCoreKebabCaseRouting 单行注册(功能独立,不与其他功能绑定)
- 新增
AddEFCoreKebabCaseRouting():把消费者应用验证过的 kebab-case 路由风格(小写字母 + 短横线)收敛为单行注册—— ①RouteTokenTransformerConvention+SlugifyParameterTransformer:[controller]/[action]/[area]等路由令牌派生段 slug 化(Topic → topic、TopicImage → topic-image、AuditLog → audit-log),OpenAPI 文档与出站链接同步呈现 kebab-case; ②AddRouting(LowercaseUrls = true / LowercaseQueryStrings = false):LinkGenerator 生成的出站 URL 兜底小写(路由匹配本身大小写不敏感;查询串保持原样,防业务参数被隐式转换)
// Program.cs —— 一行接入(替代手工挂 Convention + AddRouting + 本地转换器类三部件)
builder.Services.AddEFCoreKebabCaseRouting();
- 新增
SlugifyParameterTransformer(公共类,组件内置——非框架类型):([a-z0-9])([A-Z])边界插短横线 + 整体小写(IOutboundParameterTransformer,GeneratedRegex 预编译),可脱离本入口单独使用;连续大写缩写(如 ID)不插边界,需要时自行扩展 - 挂载防重:
TryAddEnumerable按注册层去重(net10 的RouteTokenTransformerConvention属IActionModelConvention,挂载经框架包装为内部 wrapper,无法在MvcOptions.Conventions里按类型识别)——重复调用只挂载一份,无副作用 - 功能独立边界:不触碰 MethodsEnable 端点开关、CacheEnable 与属性路由冲突检测(net10 的
RouteTokenTransformerConvention在端点构建期就地改写模板,令牌转换与开关治理正交);各端点 attribute 的字面量路由模板(如"list/keyset")仍由消费者按 kebab-case 书写,库不强制;消费者已自行添加RouteTokenTransformerConvention时请勿再调用本方法(两套转换逻辑叠加);LowercaseUrls/LowercaseQueryStrings由本方法显式固定,需覆盖可在调用后再配置RouteOptions(后到优先) - Demo 迁移:
Program.cs手工三部件 → 一行AddEFCoreKebabCaseRouting();Demo 本地SlugifyParameterTransformer.cs删除(改用组件内置版),kebab 路由行为零变化 - 测试:本批 +11(
KebabCaseRoutingTests单测 8:重复调用去重 / RouteOptions 配置 / 转换规则 Theory 6 例;KebabCaseRoutingIntegrationTests集成 3:kebab 路径可达 + LinkGenerator 出站小写短横线端到端、未注册对照组 404、与 MethodsEnable 共存互不干扰);全量 690 / 0 Failed / 2 Skipped,0 警告 - Common / Core 契约零变更(仅同步版本号);升级自 10.0.0 零迁移、需重编译
- 本版本起包内附带 XML 文档文件(
lib/net10.0/Crping.EFCore.Controller.xml)——消费方 IntelliSense 显示中文注释(此前 Controller 包不含 XML 文档,仅 Core 有)
10.0.0
2026年9月11日 星期五
与
Crping.EFCore/Crping.EFCore.Common同步升至 10.0.0 —— v10 破坏性收口线开启
- 无功能性变更,仅同步版本号(调参旋钮 init 化为 Core/Common 层变更,Controller 契约未变);需重编译(升级到 10.0.0 后全量重新编译,缓存开关等配置消费方零改动)
第二批增补 — 静态注册表下线(路由评审遗留,v9.14.0 / v9.15.0 登记)
- 删除三个静态注册表类:
MethodsEnableRegistry/MethodRouteRegistry/CacheEnableRegistry——Options/DI 通道(v9.14.0 / v9.15.0)成为唯一配置通道 - 删除控制器基类三个
[Obsolete]兼容垫片:RegisterMethodsEnable/RegisterMethodsRoutes/RegisterCacheEnable(子类静态构造函数注册形态随之终结) - 删除
WebApiRootController.MethodsEnable运行时只读视图属性(仅反映注册表通道、Options 通道恒 null、零消费者——语义不完整故随注册表移除) MethodsEnableConvention:移除注册表回退与「强制触发控制器静态构造函数」(RuntimeHelpers.RunClassConstructor)——遗留通道专属依赖;MethodRouteRegistry.Validate路由校验逻辑迁至MethodsEnableOptions.ValidateRoutes(UseRoutes与 appsettings 来源共用)- 生效性自检(
MethodsEnableEffectiveness)简化:AddEFCoreMethodsEnable自动挂载 Convention 后「配置了开关但漏挂生效机制」的结构性组合已不存在,诊断统一 Warning(原「注册过配置升格 Error」分支依赖注册表查询,随注册表移除) MethodsEnableOptions.For<TController>新增实例重载For<TController>(MethodsEnable config):支持派生开关类型(class MySwitches : MethodsEnable)注册,存防御性快照(原自定义开关只能经静态注册表投递)
迁移指南(9.25.0 → 10.0.0 第二批)
- 子类静态构造函数中的
RegisterMethodsEnable<TController>(config)→AddEFCoreMethodsEnable(o => o.For<TController>(...))(Program.cs 集中注册,自动挂载 Convention) RegisterMethodsRoutes<TController>(routes)→AddEFCoreMethodsEnable(o => o.UseRoutes<TController>(routes))RegisterCacheEnable<TController>(config)→AddEFCoreCacheEnable(o => o.For<TController>(...))- 依赖
controller.MethodsEnable运行时视图的代码:删除(Options 通道下该视图本就恒 null,端点开关照常生效)
第二批增补 — toggle 系 PUT 端点与 DELETE {id}/delete 移除(路由评审 v10 收口清单 ①②,v9.20.0 登记)
- 删除
PUT {id}/enable(ToggleEnableStatusAsync端点方法)——PATCH {id}/enable(v9.20.0 起并存)成为唯一形态,同一开关ToggleEnableStatusAsync门控、同一 BLL 委托 - 删除
PUT {id}/audit(ToggleAuditStatusAsync端点方法)——PATCH {id}/audit成为唯一形态 - 删除
DELETE {id}/delete端点 +MethodsEnable.ToggleDeleteStatusAsync开关——PATCH {id}/deleted(set 语义,独立开关SetDeleteStatusAsync)成为删除状态操作唯一端点 - 唯一配置面变化:消费者
ToggleDeleteStatusAsync = true→SetDeleteStatusAsync = true;直接调用 BLL 的消费者见 Core 包 Readme
PATCH /topic/{id}/enable # toggle 启用(唯一形态,原 PUT 移除)
PATCH /topic/{id}/audit # toggle 审核(唯一形态,原 PUT 移除)
PATCH /topic/{id}/deleted?isDeleted=true # set 删除状态(唯一形态,原 DELETE {id}/delete 移除)
第三批增补 — DELETE {id}/soft 的 reset 遗留参数移除(路由评审收口清单 ③,v9.19.0 登记)
DELETE {id}/soft?reset=true的查询参数切换语义形态终结:端点签名SoftDeleteAsync(TKey id, bool selfOnly = true)——软删除端点仅保留删除语义,恢复语义唯一入口POST {id}/restore(v9.19.0 拆分的独立端点)- 迁移:
DELETE {id}/soft?reset=true→POST {id}/restore;?reset=false调用点删参数即可 - 传递
?reset=true的既有客户端:参数被忽略(无绑定目标),行为等同默认软删除——需同步改造为 restore 调用,否则恢复操作会变成再次软删除(幂等无害但语义错误)
DELETE /topic/{id}/soft # 软删除(唯一语义,reset 参数移除)
POST /topic/{id}/restore # 恢复软删除(唯一恢复形态)
第四批增补 — 委托槽位接线改名(Core/Common 侧改名,Controller 方法不改名)
WebApiRootController构造函数接线同步更新(消费者无感):_bll.CurrentUserIdResolver = GetCurrentUserId;、_domain.CurrentUserIdResolver ??= .../AuthorizationResolver ??= .../AuthHeaderValueResolver ??= .../IdGenerator ??= ...——RHS 仍为 Controller 侧 protected 方法组- Controller 侧 protected 方法
GetCurrentUserId()/GetAuthorization()/GetAuthHeaderValue()不改名(动词短语,与 BLL/Domain 侧 Func 槽位的名词形态分层;子类覆写GetCurrentUserId()行为不变) - 迁移:消费者子类若直接访问
_bll.GetCurrentUserId/_domain.GetAuthorization/_domain.GetAuthHeaderValue/_domain.GenerateId槽位 → 改CurrentUserIdResolver/AuthorizationResolver/AuthHeaderValueResolver/IdGenerator(完整迁移表见 Core 包 Readme 10.0.0 第四批增补)
第五批增补 — 5 个写端点成功码标注修正(ProducesResponseType 与运行时对齐,纯文档契约修复零行为变更)
PUT {id}(UpdateAsync)/PATCH {id}/enable/PATCH {id}/audit/PUT {id}/audit/status/PATCH {id}/deleted的成功标注200 OK→204 NoContent——五个端点运行时本就返回 204 无响应体(DAL 单条更新成功ResultCode.NoContent、四个状态切换方法count > 0 ? ApiResult.NoContent() : ApiResult.NotFound()),v9.17.0 批次统一按「Create 201 / 其余 200」标注未逐端点核对,OpenAPI 契约与实际行为不符- 其余端点核对后维持原标注:
PUT batch/audit/status200 + 行数、DELETE {id}200 + 被删实体(ApiResult<TModel?>)、DELETE {id}/soft/POST {id}/restore200(ApiResult.Ok())、POST201 - 影响面:仅 OpenAPI/Swagger 响应契约元数据,运行时行为零变更(测试基线不变);依赖「204 端点返回 200」的客户端代码生成/前端预期需同步修正
PUT /topic/{id} # 204 NoContent(无响应体,原标注 200 修正)
PATCH /topic/{id}/enable # 204 NoContent
PATCH /topic/{id}/audit # 204 NoContent
PUT /topic/{id}/audit/status # 204 NoContent
PATCH /topic/{id}/deleted?isDeleted= # 204 NoContent
第六批增补 — {id}/deleted 端点 PATCH → PUT(动词分型主线收口,破坏性)
PATCH {id}/deleted→PUT {id}/deleted——幂等 set 语义(传目标值?isDeleted=,重发结果一致)按「幂等操作用 PUT」主线走 PUT,与PUT {id}/audit/status(set 审核状态)完全同构;v9.20.0 新增时选 PATCH 属历史折衷,v10.0.0 收口线内对齐- 参数、开关(
SetDeleteStatusAsync)、BLL 方法、204 成功码均不变,仅动词;v9.20.0 消费者迁移:PATCH {id}/deleted?isDeleted=→PUT {id}/deleted?isDeleted= - 至此动词分型矩阵无例外:幂等(
PUT {id}完整替换 /PUT {id}/audit/status/PUT batch/audit/status/PUT {id}/deletedset 目标值)→ PUT,非幂等(PATCH {id}/enable/PATCH {id}/audittoggle 翻转)→ PATCH
PUT /topic/{id}/deleted?isDeleted=true # set 删除状态(唯一形态,原 PATCH 修正)
9.25.0
2026年9月11日 星期五
与
Crping.EFCore/Crping.EFCore.Common同步升至 9.25.0
- 无功能性变更,仅同步版本号(Domain 事务编排助手
InTransactionAsync为 Core 层BaseDomain新增,零接口变更、Controller 契约未变)
9.24.0
2026年9月11日 星期五
与
Crping.EFCore/Crping.EFCore.Common同步升至 9.24.0
- 无功能性变更,仅同步版本号(BaseDomain 身份委托 AsyncLocal 化、SyncConfig 漏配诊断、Cache/Logger 未注入归 InvalidOperationException 均为 Core 层变更,Controller 契约未变;Web 注入路径每请求
??=注入行为不变)
9.23.0
2026年9月11日 星期五
与
Crping.EFCore/Crping.EFCore.Common同步升至 9.23.0
- 无功能性变更,仅同步版本号(BaseDomain.CurrentUserId 401 对齐、ShareDbContext null 守卫、BaseDomain XML 收口与 CacheManager 风格项均为 Core 层变更,Controller 契约未变)
9.22.0
2026年9月11日 星期五
与
Crping.EFCore/Crping.EFCore.Common同步升至 9.22.0
- 无功能性变更,仅同步版本号(MyDbContextFactory 时间源统一、工厂配置错误异常类型统一、构造参数守卫与重复连接名检测均为 Core 层变更,Controller 契约未变)
9.21.0
2026年9月12日 星期五
与
Crping.EFCore/Crping.EFCore.Common同步升至 9.21.0
- 无功能性变更,仅同步版本号(BLL 全家族 CancellationToken 透传、内存路径 owner 校验 NRE 修复、CurrentUserId 未设置归 401、Cache 属性 Obsolete 垫片均为 Core 层变更);Controller 端点透传
HttpContext.RequestAborted登记为后续独立批次评估
9.20.0
2026年9月12日 星期五
与
Crping.EFCore/Crping.EFCore.Common同步升至 9.20.0
新功能 — toggle 系动词修正(PUT → PATCH,路由评审 v10 候选 ①)
- 新增
PATCH {id}/enable(ToggleEnableStatusPatchAsync)与PATCH {id}/audit(ToggleAuditStatusPatchAsync):toggle 非幂等与 PUT 语义不符(PUT 按约定幂等,网络层超时重试会双翻转);修正只换动词,toggle 语义保留 - 新旧端点同一开关门控(
MethodsEnable.ToggleEnableStatusAsync/ToggleAuditStatusAsync)、同一 BLL 委托——消费者开启开关即同时获得 PUT / PATCH 双路由(OpenAPI 自然展示迁移路径),v10 删除 PUT 端点时配置零变动 - 遗留 PUT 端点保留,XML 注明「遗留端点(v10 移除)」;启动期冲突检测不误报(同模板不同 HTTP 方法为合法双端点)
新功能 — 删除状态 set 语义端点(PATCH {id}/deleted,路由评审 v10 候选 ②)
- 新增
PATCH {id}/deleted(SetDeleteStatusAsync):精确设置删除状态目标值(幂等),替代动词入路径的遗留DELETE {id}/deletetoggle 端点(v10 随ToggleDeleteStatusAsync开关一并移除) isDeleted走 query 绑定;selfOnly默认false(内容管理语义,与切换版一致);仅设置IsDeleted标志、不盖章/清理DeletedBy/DeletedAt——完整软删除语义用DELETE {id}/soft,完全恢复语义用POST {id}/restoreMethodsEnable新增SetDeleteStatusAsync开关(默认关闭);DemoDefaults 同步启用
PATCH /topic/{id}/enable # 新:切换启用(替代 PUT {id}/enable,同一开关)
PATCH /topic/{id}/audit # 新:切换审核(替代 PUT {id}/audit,同一开关)
PATCH /topic/{id}/deleted?isDeleted=true # 新:设为已删除(幂等,独立开关)
PUT /topic/{id}/enable # 遗留(v10 移除)
DELETE /topic/{id}/delete # 遗留 toggle(v10 移除)
v10 收口清单(「路由评审遗留」①②③ 全部闭环)
- 删
PUT {id}/enable、PUT {id}/audit(开关不变,消费者零感知) - 删
DELETE {id}/delete+MethodsEnable.ToggleDeleteStatusAsync开关——唯一配置面变化:ToggleDeleteStatusAsync = true需迁移为SetDeleteStatusAsync = true - 删
DELETE {id}/soft的reset参数(9.19.0 已登记)
(测试 +14:PatchToggleEndpointTests 7——PATCH enable/audit 委托与 selfOnly 透传、同开关双动词并存、PATCH deleted 双向委托、遗留 DELETE {id}/delete 保留;SetDeleteStatusTests 7——SQLite 真实落库,Core 侧详见 Crping.EFCore 包 Readme;全量 661 / 0 失败 / 2 跳过)
9.19.0
2026年9月12日 星期五
与
Crping.EFCore/Crping.EFCore.Common同步升至 9.19.0
新功能 — 恢复软删除独立端点(POST {id}/restore)
- 新增
RestoreAsync端点:POST {id}/restore,委托BLL.ResetSoftDeleteAsync(id, selfOnly)——selfOnly默认true(与软删除同为自助语义);MethodsEnable新增同名开关RestoreAsync(默认关闭,开启后才注册端点) - 设计动机:旧设计里「恢复」靠
DELETE {id}/soft?reset=true的查询参数切换——同一 URL 依参数变成两种相反语义,属路由设计反模式;独立端点让恢复显式、可独立开关、可独立授权 - 兼容性:旧参数行为原样保留(
DELETE {id}/soft?reset=true仍执行恢复),XML 文档已注明reset为遗留参数(v10 移除,届时软删除端点仅保留删除语义),现有消费者可渐进迁移到新端点
POST /topic/{id}/restore # 新:恢复软删除(推荐)
DELETE /topic/{id}/soft # 软删除(reset 参数遗留,v10 移除)
(测试 +4;全量 647 通过 / 0 失败)
9.18.0
2026年9月12日 星期五
与
Crping.EFCore/Crping.EFCore.Common同步升至 9.18.0
新功能 — {id} 路由约束自动注入
MethodsEnableConvention对开关启用且未注册自定义路由的{id}端点,按控制器闭合泛型TKey自动注入路由约束:int → {id:int}、long → {id:long}、Guid → {id:guid};string与自定义主键类型不注入(行为与旧版一致)- 语义修正:
TKey=long的控制器收到GET /topic/abc,旧行为匹配{id}后模型绑定失败返回 400「请求参数错误」;注入约束后请求不匹配端点,直接返回 404(路径不存在)——REST 语义正确,且不再进入无效模型绑定 - OpenAPI 的
id参数 schema 随约束推断类型格式,消费者代码生成更准确 - 经
UseRoutes()/RegisterMethodsRoutes()自定义模板的端点以消费者模板为准,不注入(是否带约束由消费者自行决定)
// 无需任何配置:MethodsEnable 开启端点后约束自动生效
// TKey=long 的控制器:GET /topic/{id:long}/raw —— 非匹配段("abc") → 404,不再误报 400
builder.Services.AddEFCoreMethodsEnable(o => o.For<TopicController>(n => { n.GetAsync = true; }));
(测试 +3;全量 643 通过 / 0 失败)
9.17.0
2026年9月12日 星期五
与
Crping.EFCore/Crping.EFCore.Common同步升至 9.17.0
修复 — 超时与身份声明语义
TimeoutException由 408 改映射 504 Gateway Timeout:408 语义是「客户端发送请求太慢」(服务端关闭空闲连接),服务端/下游操作超时惯用 504,且 5xx 自动不回传DetailGetCurrentUserId的 claim 值无法转换为用户主键类型时归 401(UnauthorizedAccessException)——旧行为FormatException→ 400「请求参数错误」(语义错位)、Guid等非 IConvertible 主键类型 →InvalidCastException→ 500- 新增 Guid 主键 TryParse 快速路径(
TUserKey = Guid的 claim 直接解析,不再经Convert.ChangeType)
修复 — MethodsEnable Options 解析沿继承链
MethodsEnableOptions.ResolveConfig/ResolveRoutes改为沿控制器继承链逐级 FullName → 短名查找:基类注册对派生控制器生效,与CacheEnableOptions.Resolve及两个静态注册表Get同语义,消除「同一概念三种行为」的不一致- Options 命中仍优先于遗留注册表回退,按控制器整体覆盖语义不变
新功能 — 端点 ProducesResponseType 元数据
WebApiBaseController全部 20 个端点标注成功码 + 常见错误码(400/401/404/409 按端点语义)+ProblemDetails(500),OpenAPI/Swagger 可生成响应契约- 注:C# 不允许特性引用外层泛型类的类型参数(CS0416/CS8968),
TModel/TKey载荷端点仅标注状态码
新功能 — ProblemDetails 携带 traceId
CreateProblemDetails新增可选traceId参数(Filter/Middleware 传HttpContext.TraceIdentifier),写入Extensions["traceId"]——错误响应与日志可按请求关联排查
文档 — selfOnly 默认值语义说明
- 启用/禁用与软删除属自助操作,
selfOnly默认true(仅操作自己创建的数据);审核与删除状态切换属内容管理操作,默认false(可操作全部数据)——分属两类语义,保持现值并在 XML 文档注明理由
优化 — 轻微项收尾(同版本补充)
- 当前用户 ID 解析统一:
GetCurrentUserId改为沿同名 claim 返回首个可转换的值,WebApiController/WebApiIntController/WebApiLongController三个派生类的手工遍历覆写删除(语义合并回基类;同名 claim 多值时取首个有效项,类仅保留 TUserKey 泛型特化) - 路由冲突检测令牌展开对齐 MVC 真实语义:
ExpandTokens支持[area]等ControllerModel.RouteValues令牌替换——不同[Area]控制器写相同模板字符串(如"[area]/items")不再误报跨控制器冲突(修复前启动 fail-fast 误报,实际两区域端点可正确路由) - 非泛型
ToActionResult显式列出Created分支(无载荷 → 201 无响应体),不再依赖兜底分支的隐式行为 CrossDomainSetupXML 文档注明:空来源列表将静默拒绝全部跨域请求;AllowCredentials与通配符"*"组合在首个跨域请求时抛出异常(CORS 规范禁止)
(测试 +12:Timeout 504、traceId、claim 归 401、Options 继承链、[area] 令牌展开等;全量口径与并行批次合并计算)
9.16.0
2026年9月12日 星期五
与
Crping.EFCore/Crping.EFCore.Common同步升至 9.16.0
修复 — 异常映射收窄(ExceptionHelper / ExceptionFilter / ExceptionMiddleware)
InvalidOperationException不再映射 409:EF LINQ 翻译失败、连接状态错误等大量基础设施场景都抛此类型——既不是业务冲突,且 409 < 500 会把异常消息(含查询片段/内部状态)经Detail回传客户端;统一落 500(Detail置 null)。业务冲突仍经ApiResult.Conflict返回,不走异常映射OperationCanceledException新增 503「请求已取消」映射:宿主停机/超时令牌等非客户端中断的取消不再误报 500「服务器内部错误」(Error 级日志误导运维)- 客户端中断(
RequestAborted已触发)由 Filter / Middleware 前置拦截:连接已断开,不生成响应、不记错误日志,仅信息级留痕
修复 — Forbidden 映射去 ForbidResult 依赖(ApiResultExtensions)
ForbidResult触发认证挑战,未注册认证方案的应用返回 Forbidden 时运行时抛异常 → 500;无Error改映射为纯 403 状态码(无外部依赖)- 泛型分支补
Error ?? Data回退:Forbidden(data)的数据载荷不再被丢弃(与 400/404/409 分支对齐)
优化 — DatabaseExtensions 移除 new() 约束
Migrate<TDb>()/EnsureCreated<TDb>()方法体仅从 DI 解析上下文,new()约束反而把只有(DbContextOptions)构造函数的合法 DI 上下文拒之门外——删除后两类上下文均可使用,调用方零影响
(测试 +7:本批三个测试类 33 → 40)
9.15.0
2026年9月12日 星期五
与
Crping.EFCore/Crping.EFCore.Common同步升至 9.15.0
新功能 — CacheEnable 缓存开关 Options/DI 集中配置(推荐,替代静态构造函数注册)
- 新增
AddEFCoreCacheEnable()双重载:委托配置与 appsettings 节绑定,按控制器类型在应用启动管线一处集中注册全部缓存开关——与AddEFCoreMethodsEnable()同构(显式配置 Replace 后到优先,注册顺序无关;仅控制器构造期消费,不支持运行时重载);无启动期生效机制(开关由控制器构造函数消费并同步到 BLL),本入口不涉及 Convention 挂载
// 委托形态
builder.Services.AddEFCoreCacheEnable(options =>
{
options.For<TopicController>(n => { n.GetDetailsAsync = true; n.GetAsync = true; });
options.For<MemberController>(n => n.GetTotalAsync = true);
});
// appsettings 节形态(键为控制器类型 FullName 或短名 Name)
builder.Services.AddEFCoreCacheEnable(builder.Configuration.GetSection(CacheEnableOptions.ConfigSection));
"Crping.EFCore.CacheEnable": {
"Controllers": {
"TopicController": { "GetDetailsAsync": true, "GetAsync": true }
}
}
- 配置查找顺序:控制器构造时 Options 沿继承链命中即用(每级 FullName 精确 → 短名 Name;基类注册对派生控制器生效,与静态注册表同语义;按控制器整体覆盖,不做属性级合并)→ 未命中回退静态注册表(兼容垫片)→ 均未注册为 null(各读端点默认不缓存)
- 注入方式为构造可选参数透传(与 TimeProvider 注入同构):
WebApiRootController构造链(WebApiBaseController/WebApiController/WebApiIntController/WebApiLongController)新增CacheEnableOptions? cacheEnableOptions = null尾参,MVC 经ActivatorUtilities激活控制器时自动注入已注册的 Options 单例;存量子类不透传时行为完全不变(回退静态注册表),需要 Options 通道的子类在构造函数追加该参数并转发 WebApiRootController.CacheEnable运行时视图改为返回构造时解析的实际生效配置(Options 或注册表),不再有「仅反映静态注册表通道」的局限
过时通告(Obsolete,warning 级,不破坏现有编译)
RegisterCacheEnable<TController>()标记[Obsolete]:推荐迁移到AddEFCoreCacheEnable();静态注册表遗留通道仍可用(Options 未配置该控制器时回退生效),计划随静态注册表在 v10 移除
(测试基线 568 → 588 +20)
9.14.0
2026年9月11日 星期四
与
Crping.EFCore/Crping.EFCore.Common同步升至 9.14.0
新功能 — MethodsEnable 端点开关 Options/DI 集中配置(推荐,替代静态构造函数注册)
- 新增
AddEFCoreMethodsEnable()双重载:委托配置与 appsettings 节绑定,按控制器类型在应用启动管线一处集中注册全部端点开关——无需静态构造函数、每控制器独立配置实例(无共享可变实例)、自动挂载MethodsEnableConvention(配置与生效机制绑定,从入口上根除「配置了开关但漏挂 Convention」的静默失效)
// 委托形态
builder.Services.AddEFCoreMethodsEnable(options =>
{
options.For<TopicController>(n => { n.CreateAsync = true; n.GetAsync = true; });
options.UseRoutes<TopicController>(new Dictionary<string, string> { [nameof(MethodsEnable.CreateAsync)] = "create-test" });
});
// appsettings 节形态(键为控制器类型 FullName 或短名 Name)
builder.Services.AddEFCoreMethodsEnable(builder.Configuration.GetSection(MethodsEnableOptions.ConfigSection));
"Crping.EFCore.MethodsEnable": {
"Controllers": {
"TopicController": { "CreateAsync": true, "GetAsync": true }
},
"Routes": {
"TopicController": { "CreateAsync": "create-test" }
}
}
- 显式配置 Replace 语义(后到优先):重复调用以最后一次为准,注册顺序无关(与
AddEFCoreCache一致);仅启动期消费(端点在启动时已移除/注册,运行时变更开关无意义),不支持运行时重载 - 配置查找顺序:Options 命中即用(按控制器整体覆盖,不做属性级合并)→ 未命中回退静态注册表(兼容垫片)
- 启动诊断:配置了不存在/未被发现控制器的键输出 WARN(拼写错误尽早暴露);短名命中多个同名控制器(不同命名空间)时 WARN 指引改用 FullName
启动期属性路由冲突检测(fail-fast,替代旧行为「启动静默通过、每请求 500 路由歧义」)
MapControllers构建端点时对启用端点做三层冲突检测,冲突即抛InvalidOperationException:- 单控制器内:HTTP 方法相交且合并路由模板相同的端点对(典型场景:子类以「同名、同路由、不同参数」端点替换基础端点但忘记关闭基础端点开关)
- 跨控制器:不同控制器上同模板同方法(如两个控制器写了相同
[Route]前缀) - 同动作重复 selector:同一动作两个完全相同的 selector(多 selector 误写 / 路由改写产物——编译期 ASP0023 分析器覆盖不了改写后的路由)
[controller]/[action]令牌展开后比较;同模板不同方法的端点(GET/POST 同路由)为合法双端点不误报- 路由模板注册时语法预校验(无效模板如缺少右花括号从端点构建期提前到注册时机抛出,消息携带控制器与开关名)
诊断与自检加固
- 开关生效性自检:派生 CRUD 控制器携带
[MethodEnable]端点但AddMethodsEnableConvention()未注册时,控制器构造期输出诊断(注册过开关配置升格 Error,否则 Warning),每控制器类型仅提示一次——漏挂生效机制的静默失效不再无声 - 子类自定义开关:
class MySwitches : MethodsEnable+[MethodEnable(nameof(MySwitches.MySwitch))]即参与开关治理(Convention 按配置实际类型解析开关属性) - 非 Crping 控制器误挂
[MethodEnable]:启动 WARN 指明继承错误(开关不生效、端点保持注册) - 三个注册表新增
Reset()(仅限测试/多宿主场景)
加固 — 注册表防御性快照
- 三个注册表(
MethodsEnableRegistry/MethodRouteRegistry/CacheEnableRegistry)注册时存储Clone()快照:多个控制器注册同一配置实例时互不泄漏,注册后修改原实例不影响已注册配置
其他
WebApiBaseController全部 20 个基础端点virtual(收尾GetKvpsAsync),消费者可覆写换路由
过时通告(Obsolete,warning 级,不破坏现有编译)
RegisterMethodsEnable<TController>()/RegisterMethodsRoutes<TController>()标记[Obsolete]:推荐迁移到AddEFCoreMethodsEnable();静态注册表遗留通道仍可用(Options 未配置该控制器时回退生效),计划随静态注册表在 v10 移除- 注意:
WebApiRootController.MethodsEnable运行时视图仅反映静态注册表通道,经AddEFCoreMethodsEnable()配置的控制器该属性返回 null(端点开关照常生效)
(测试基线 528 → 568 +40)
9.13.0
2026年9月2日 星期三
与
Crping.EFCore/Crping.EFCore.Common同步升至 9.13.0
- 无功能性变更,仅同步版本号(缓存滑动过期配置化为 Core/Common 层变更:新增
EFCoreCacheOptions全局配置与AddEFCoreCache配置入口,BLL 默认策略四层优先级,命中续期口径统一;Controller 契约未变)
9.12.0
2026年8月31日 星期一
与
Crping.EFCore/Crping.EFCore.Common同步升至 9.12.0
- 无功能性变更,仅同步版本号(缓存取消语义收窄为 Core 层变更,Controller 契约未变)
9.11.0
2026年8月31日 星期一
与
Crping.EFCore/Crping.EFCore.Common同步升至 9.11.0
- 无功能性变更,仅同步版本号(缓存键按需叶子求值 / 捕获段指纹上限 / 键长守卫为 Common/Core 层变更,Controller 契约未变)
9.10.0
2026年8月30日 星期日
与
Crping.EFCore/Crping.EFCore.Common同步升至 9.10.0
新增 — UserKeyName 可定制
WebApiRootController.UserKeyName由protected const改protected virtual属性:JWT claim 名("UserId")可覆写定制(如 "uid" / "sub"),无需整体覆写GetCurrentUserId
修复 — Authorization 解析
GetAuthHeaderValue改Split(' ', 2):方案与令牌间含多个空格时令牌整体保留(原按全部空格拆分导致多段返回 null);无空格单段值仍返回 null
(测试 +3:UserKeyName 覆写按自定义 claim 解析、多空格解析、无空格返回 null)
9.9.0
2026年8月29日 星期六
与
Crping.EFCore/Crping.EFCore.Common同步升至 9.9.0
加固 — 静态注册表线程安全
MethodsEnableRegistry/MethodRouteRegistry由普通Dictionary改为ConcurrentDictionary(与CacheEnableRegistry对齐):控制器静态构造函数并发注册 + 请求线程并发读取不再有损坏风险;注册/查找语义不变(同类型重复注册以后者为准,沿继承链查找含泛型开放类型)
9.8.0
2026年8月28日 星期五
与
Crping.EFCore/Crping.EFCore.Common同步升至 9.8.0
修复 — CacheEnableRegistry 线程安全
CacheEnableRegistry._configs由普通Dictionary改为ConcurrentDictionary:不同控制器静态构造函数可并发注册、请求线程同时读取,普通字典并发写/读有损坏风险;注册/查找语义不变(同类型重复注册以后者为准,沿继承链查找含泛型开放类型)
9.7.0
2026年8月26日 星期三
与
Crping.EFCore/Crping.EFCore.Common同步升至 9.7.0
- 无功能性变更,仅同步版本号(缓存键可读性/防穿透/DI 统一注册为 Common/Core 层变更,Controller 契约未变)
9.6.0
2026年8月24日 星期一
与
Crping.EFCore/Crping.EFCore.Common同步升至 9.6.0
- 无功能性变更,仅同步版本号(接口补齐为 Common/Core 层变更,Controller 契约未变)
9.5.0
2026年8月21日 星期五
与
Crping.EFCore/Crping.EFCore.Common同步升至 9.5.0
- 无功能性变更,仅同步版本号(GenerateId Snowflake 式位布局为 Core 层变更,Controller 契约未变)
9.4.0
2026年8月18日 星期二
与
Crping.EFCore/Crping.EFCore.Common同步升至 9.4.0
新功能 — 审核状态端点
PUT {id}/audit/status—SetAuditStatusAsync(精确设置审核状态,由MethodsEnable.SetAuditStatusAsync开关控制)PUT batch/audit/status—BatchSetAuditStatusAsync(批量设置审核状态,由MethodsEnable.BatchSetAuditStatusAsync开关控制);请求体统一为 DTOBatchAuditStatusRequest<TKey>(Ids+Status均在 body,required校验)MethodsEnable新增SetAuditStatusAsync/BatchSetAuditStatusAsync两个端点开关(默认关闭)
9.3.0
2026年8月18日 星期二
与
Crping.EFCore/Crping.EFCore.Common同步升至 9.3.0
- 无功能性变更,仅同步版本号(GetOrCreateAsync 嵌套事务修复为 Core 层变更,Controller 契约未变)
9.2.0
2026年8月18日 星期一
与
Crping.EFCore/Crping.EFCore.Common同步升至 9.2.0
- 无功能性变更,仅同步版本号(ResultCode 新增 5xx 枚举 + ApiResult InternalError 工厂为 Core 层变更,Controller 契约未变)
9.1.2
2026年8月16日 星期日
与
Crping.EFCore/Crping.EFCore.Common同步升至 9.1.2
新功能 — ToActionResult 兜底分支携带响应体
ResultCode未覆盖的状态码(如ApiResult.StatusCode(429))由裸StatusCodeResult改为:非泛型取Error、泛型Error ?? Data回退——有载荷走ObjectResult设状态码、无载荷走StatusCodeResult,与 400 / 404 / 409 分支行为对齐
9.1.1
2026年8月16日 星期日
与
Crping.EFCore/Crping.EFCore.Common同步升至 9.1.1
新功能 — ToActionResult 错误响应体
Unauthorized(error)→ 401 +UnauthorizedObjectResult;Forbidden(error)→ 403 +ObjectResult(ASP.NET Core 无 ForbidObjectResult)- 泛型
ToActionResult的 400 / 404 / 409 分支由Error ?? Data回退,错误消息与数据载荷均可渲染进响应体
9.1.0
2026年8月15日 星期六
与
Crping.EFCore/Crping.EFCore.Common同步升至 9.1.0
- 无功能性变更,仅同步版本号(ApiResult 静态工厂族与
EFCoreExt.WhereLike在 Core 层,Controller 透明)
9.0.0
2026年8月15日 星期六
与
Crping.EFCore/Crping.EFCore.Common同步升至 9.0.0
破坏性变更 — BLL 去 MVC 依赖(响应构造迁入本包)
- 新增
ApiResultExtensions.ToActionResult():BLL 的ApiResult/ApiResult<TData>→IActionResult统一映射(ResultCode→ 对应状态码与响应体) WebApiResponse响应构造与DatabaseExtensions(IApplicationBuilder扩展)由 Core 包迁入本包WebApiBaseController全部端点改为(await BLL.Xxx(...)).ToActionResult()映射(BLL 不再返回IActionResult,详见 Core Readme 9.0.0)
8.11.0
2026年8月13日 星期四
与
Crping.EFCore/Crping.EFCore.Common同步升至 8.11.0
破坏性变更 — 删除过时控制器别名
- 删除 3 个
[Obsolete]转发壳类:WebApiCoreController(→WebApiRootController)、WebApiForIntController(→WebApiIntController)、WebApiForLongController(→WebApiLongController)
新功能 — 写后读绑定请求边界复位中间件
- 新增
ReadWriteRoutingMiddleware+UseReadWriteRouting()(开启ReadWriteRouting.BindReadToWrite时须在请求管道注册)
优化
WebApiRootController.GetCurrentUserId改User.FindFirst(去三次 foreach +Convert.ChangeType装箱)、GetAuthorization改Request.Headers.Authorization
8.10.0
2026年8月13日 星期四
与
Crping.EFCore/Crping.EFCore.Common同步升至 8.10.0
- 无功能性变更,仅同步版本号(Keyset 游标格式定稿 / 列表 API 三态对齐 / 性能优化均在 Core 层 DAL/BLL 与 Common 层
KeysetCursor,Controller 透明)
8.9.0
2026年8月12日 星期三
与
Crping.EFCore/Crping.EFCore.Common同步升至 8.9.0
- 无功能性变更,仅同步版本号(ResolveSort 排序键解析虚方法在 Core 层 BLL,Controller 透明)
8.8.0
2026年8月11日 星期二
与
Crping.EFCore/Crping.EFCore.Common同步升至 8.8.0
- 无功能性变更,仅同步版本号(Keyset 排序键点分路径 / bool 排序键修复 / OrderBy 全能化重构在 Core 层 DAL/BLL,Controller 透明)
8.7.0
2026年8月11日 星期二
与
Crping.EFCore/Crping.EFCore.Common同步升至 8.7.0
破坏性变更 — 分页结果契约属性顺序调整与 required 强化
KeysetPage<T>/OffsetPage<T>的PageInfo/Pagination属性移至Items之前- 两个属性均改为
required init(移除默认值),调用方构造时必须显式提供所有属性 - 迁移指南:JSON 反序列化顺序可能变化,手动构造对象时需调整属性顺序或使用命名参数
8.6.0
2026年8月10日 星期一
与
Crping.EFCore/Crping.EFCore.Common同步升至 8.6.0
- 无功能性变更,仅同步版本号(OrderByExpr 任意表达式排序在 Core 层,Controller 透明)
8.5.0
2026年8月9日 星期日
与
Crping.EFCore/Crping.EFCore.Common同步升至 8.5.0
新功能 — 默认 Keyset 游标分页端点
- 新增
GET /list/keyset端点(GetKeysetPageAsync),基于 BLL/DAL 的GetKeysetPageAsync,直接返回KeysetPage两段式契约({ items, pageInfo }) - 参数:
cursor(游标令牌,null 表示首页)、direction(Next/Prev)、pageSize(默认 20),默认按 Id 降序(构建器未声明排序键时自动兜底) MethodsEnable新增GetKeysetPageAsync开关控制该端点,与 Offset 分页端点(GET /list/simple)对称
每个端点独立开关
GetDetailsForAdminAsync(GET {id}/for-admin)拆独立开关MethodsEnable.GetDetailsForAdminAsync(原复用GetDetailsAsync)GetForAdminEditorAsync(GET {id}/editor/for-admin)拆独立开关MethodsEnable.GetForAdminEditorAsync(原复用GetForEditorAsync)- 至此
WebApiBaseController全部 18 个端点均拥有独立开关,互不牵连
缓存开关注册(端点级,与 MethodsEnable 同模式)
- 新增
CacheEnableRegistry静态注册表 + 基类RegisterCacheEnable<TController>(config):在控制器静态构造函数中注册CacheEnable配置,控制器构造函数自动同步到BLL.CacheEnable(未注册的控制器为null,缓存默认关闭) CacheEnable仅控制 API 端点路径(BLL 门面方法);自定义业务方法显式传useCache: true/false三态参数自由控制,两者互不干扰- 缓存默认关闭(破坏性):注入
ICacheManager后端点默认不缓存,需注册CacheEnable且对应开关为true才缓存——详见 Core Readme 8.5.0 的缓存体系重构说明
8.4.0
2026年8月8日 星期六
与
Crping.EFCore/Crping.EFCore.Common同步升至 8.4.0
- 无功能性变更,仅同步版本号(TimeProvider 注入在 Core 层 BLL/DAL,Controller 透明)
8.3.0
2026年8月8日 星期六
与
Crping.EFCore/Crping.EFCore.Common同步升至 8.3.0
Controller 层健壮性与开关机制完善
GetCurrentUserId无 UserId claim 时抛 401(UnauthorizedAccessException,经 ExceptionFilter/Middleware 映射 401),不再返回默认值(int→0 / string→null),避免未登录请求以默认身份执行写操作MethodsEnableConvention启动 WARN 诊断:注入ILogger,对"未注册配置 / 开关关闭"的端点输出启动日志(新增 DI 扩展AddMethodsEnableConvention(),替代options.Conventions.Add(new MethodsEnableConvention());旧用法仍兼容但无诊断日志)- 端点自定义路由
RegisterMethodsRoutes<TController>():在静态构造函数中按开关名注册路由模板(如CreateAsync → "publish"),开关启用的端点路由改写为注册模板(相对控制器级[Route]前缀),未注册路由的端点使用 attribute 默认路由;开关关闭的端点仍被移除 MethodsEnable开关解析缓存 + 未知开关名清晰异常(启动时抛出并列出有效开关名,代替 NRE)ToggleDeleteStatusAsync拆独立开关(原复用SoftDeleteAsync)- 移除旧
GET /List端点(GetListAsync)与其MethodsEnable.GetListAsync开关——已被GET List/Offset(GetOffsetPageAsync)替代 WebApiRootController.MethodsEnable实例属性改只读(从注册表读取,未注册为 null),移除 setter——旧Configure()中设置实例属性的写法编译失败,强制走RegisterMethodsEnable<TController>注册- 删除零引用
MvcController;Utils.Migrate<TDb>/EnsureCreated<TDb>迁至Crping.EFCore包的DatabaseExtensions(命名空间变更,Breaking) ExceptionFilter/ExceptionMiddleware抽取公共ExceptionHelper.CreateProblemDetails- 日志类别对齐注入类型(
ILogger<WebApiRootController<...>>);Convention 仅处理继承自WebApiRootController<,,,,>的控制器;清理 Usings 残留
8.2.0
2026年8月8日 星期六
与
Crping.EFCore/Crping.EFCore.Common同步升至 8.2.0
破坏性变更 — 端点启用机制:405 开关 → 启动时移除(IApplicationModelConvention)
- 被禁用的端点不再注册路由(请求返回 404),且不出现在 OpenAPI 文档中;旧机制为方法内返回 405、文档仍可见
- 配置方式由实例
Configure()改为按控制器类型注册:各控制器静态构造函数调用RegisterMethodsEnable<TController>(config)(基类WebApiRootController提供),由MethodsEnableConvention在启动时读取并移除禁用端点 - 新增
MethodEnableAttribute:标注在WebApiBaseController各端点方法上,关联开关名;未标注的端点(子类自定义)不受开关控制 - 未注册配置的控制器:带开关特性的端点默认全部移除(与旧行为"默认禁用"语义一致)
- 新增 DI 扩展
AddMethodsEnableConvention():通过 DI 注入ILogger,启动时对"未注册配置 / 开关关闭"的端点输出 WARN 诊断日志,避免端点静默 404 难以排查(原options.Conventions.Add(new MethodsEnableConvention())用法仍兼容,但无诊断日志) WebApiRootController.MethodsEnable实例属性改为只读:返回注册表中本控制器类型注册的配置(未注册为 null),与实际生效开关一致;启用以RegisterMethodsEnable<TController>注册为准,实例上不可修改(旧Configure()中设置实例属性的写法编译失败,强制走新注册方式)
8.1.0
2026年8月8日 星期六
与
Crping.EFCore/Crping.EFCore.Common同步升至 8.1.0
- 无功能性变更,仅同步版本号(分页契约两段式重构在 Common / Core 层;Controller
GET /Page端点返回形状随契约变为{ items, pagination })
8.0.0
2026年8月7日 星期五
与
Crping.EFCore/Crping.EFCore.Common同步升至 8.0.0
- 无功能性变更,仅同步版本号(BLL 缓存方法新增
useCache参数对 Controller 调用透明,默认行为不变)
7.7.0
2026年8月7日 星期五
与
Crping.EFCore/Crping.EFCore.Common同步升至 7.7.0
破坏性变更 — 缓存注入切换
- 所有控制器基类(
WebApiRootController/MvcController/WebApiBaseController及其派生)构造参数由IDistributedCache?替换为ICacheManager?,Cache属性类型同步更新 - 消费者 DI 注册:
builder.Services.AddEFCoreRedisCache(redisConfig)一行完成(IConnectionMultiplexer+ICacheVersionStore+ICacheManager),另需AddStackExchangeRedisCache提供业务数据存储(v8.0.0 起方法名由AddCrpingRedisCache重命名)
缓存健壮性增强(2026-08-07)
GET /Details等投影端点(GetDetailsAsync/GetForEditorAsync/GetListItemAsync/GetSimpleAsync)经 BLL 详情投影缓存生效,键含投影指纹,不同投影互不串扰
7.6.0
2026年8月6日 星期四
与
Crping.EFCore/Crping.EFCore.Common同步升至 7.6.0
Offset 偏移分页端点
- 新增
GET /Page端点(GetOffsetPageAsync),直接返回OffsetPage契约(items + page + pageSize + recordCount + pageCount + hasNext + hasPrev),与 Keyset 响应结构统一 MethodsEnable新增GetOffsetPageAsync开关控制该端点- 旧
GET /List端点(GetListAsync)标记[Obsolete],返回形状不变,仍可用
安全加固(2026-08-07)
- 5xx 不再回传异常消息:
ExceptionFilter/ExceptionMiddleware对statusCode >= 500的Detail置为null,避免向客户端泄露堆栈 / SQL / 内部实现细节;4xx 仍返回异常消息便于排查
7.5.0
2026年8月6日 星期四
与
Crping.EFCore/Crping.EFCore.Common同步升至 7.5.0
- 无功能性变更,仅同步版本号(Keyset 分页重写在 DAL/BLL 层,Controller 透明)
7.4.0
2026年8月3日 星期一
与
Crping.EFCore/Crping.EFCore.Common同步升至 7.4.0
- 无功能性变更,仅同步版本号
7.3.0
2026年7月30日 星期三
与
Crping.EFCore/Crping.EFCore.Common同步升至 7.3.0
- 无功能性变更,仅同步版本号(底层 BLL 的时间类型变更对 Controller 层透明)
7.2.0
2026年7月28日 星期一
与
Crping.EFCore/Crping.EFCore.Common同步升至 7.2.0
- 无功能性变更,仅同步版本号
7.1.0
2026年7月28日 星期一
与
Crping.EFCore同步升至 7.1.0
新增类(向后兼容 — 旧类标记 [Obsolete])
WebApiRootController:控制器根基类,替代WebApiCoreController("Core" 名称易与 ASP.NET Core 混淆)WebApiIntController:基于 int 类型主键用户的控制器,替代WebApiForIntController(去掉 "For" 前缀)WebApiLongController:基于 long 类型主键用户的控制器,替代WebApiForLongController
重命名(向后兼容)
WebApiCoreController→WebApiRootController:旧类保留并继承新类,添加Dom属性向后兼容WebApiForIntController→WebApiIntController:旧类保留并继承新类WebApiForLongController→WebApiLongController:旧类保留并继承新类
7.0.0
2026年7月26日 星期日
与
Crping.EFCore同步升至 7.0.0
清理(破坏性变更 — 文件级)
- 删除 4 个全注释死代码文件(下游若手动引用以下类型会编译失败):
WebApiVersionController.cs(221 行注释,OpenAPI/版本路由相关)SwaggerExt.cs(94 行注释,已被Crping.ApiDoc.NSwag/Crping.ApiDoc.Scalar替代)SwaggerOptions.cs(37 行注释)SwaggerFilter.cs(26 行注释)
安全(行为变更 — 建议关注)
- 移除
MvcController与WebApiCoreController中GetCurrentUserId()的#if DEBUG分支- 之前:Debug 构建返回硬编码
"DebugUser",Release 构建从 JWT claims 读取 - 现在:始终从 JWT claims 读取 — 生产环境之前若依赖 Debug 构建的"假用户"行为,需要在配置或开发环境中显式 mock;不再有"Debug 即自动拥有任意身份"的隐式行为
- 这条与 AGENTS.md「反模式」§
#if DEBUG在生产路径中改变用户身份 一致:本次提交已修复
- 之前:Debug 构建返回硬编码
重构
- 提取
ExceptionHelper,ExceptionFilter的MapException逻辑由重复实现改为集中调用,消除 21 行的分散代码
修复
Utils.Migrate/Utils.EnsureCreated改用GetRequiredService<T>()解析DbContext/DbContextFactory,之前若服务未注册会静默吞错(null),现在会立即抛InvalidOperationException
内部(净状态未变)
IDomain中未使用的 HTTP 类型依赖相关 refactor(commit3eb4504)已被回退(65ae448),净状态未变
6.10.0
2026年7月14日 星期二
- 剥离
NSwagApiDocExt(移除AddAuthOpenApiDocument、UseAuthOpenApi扩展方法),OpenApi 文档生成由独立包Crping.ApiDoc.NSwag提供 - 移除
NSwag.AspNetCore包引用;显式声明Microsoft.AspNetCore.App共享框架引用以取代原本寄生于 NSwag 的隐式FrameworkReference - 清理不再需要的
Microsoft.AspNetCore.Http.Extensions与Microsoft.AspNetCore.Mvc.ViewFeatures包引用(已被共享框架覆盖)
6.9.0
2026年7月7日 星期二
- 新增
WebApiCoreController可直接被需要轻量控制器的场景使用
6.8.0
2026年6月14日 星期日
- 优化异常处理中间件
ExceptionMiddleware - 优化异常过滤器
ExceptionFilter
6.7.0
2026年2月26日 星期三
- 新增授权验证策略类
AuthPolicies,用于控制器方法的授权验证 - 为控制器方法添加管理员权限验证:
GetDetailsForAdminAsync和GetForAdminEditorAsync方法添加[Authorize(AuthPolicies.Admin)]特性
6.6.0
2026年2月6日 星期五
- 新增方法
ToggleDeleteStatusAsync
6.5.0
2026年2月6日 星期五
- 优化软删除相关方法逻辑
- 新增状态切换方法
ToggleEnableStatusAsync,ToggleAuditStatusAsync
6.4.0
2025年12月31日 星期三
- 优化所有命名空间
6.3.0
2025年12月28日 星期日
- 方法启用控制
MethodsEnable添加更多默认Get方法控制 WebApiBaseController新增更多Get方法
6.1.0
2025年12月25日 星期四
- 将方法禁用控制改为启动控制,默认禁用所有默认方法
6.0.0
2025年11月27日 星期四
- 升级为
.net10.0
5.1.0
2025年5月23日 星期五
- 新增方法
SoftDeleteAsync(...)
5.0.0
2024年11月17日 星期日
- 升级为
.net9.0 - 更新引用组件,并清理替换弃用的组件
4.11.0
2024年11月16日 星期六
- 新增类
ExceptionMiddleware,ExceptionFilter
4.10.0
2024年11月16日 星期六
AuthenticationHeaderValue修改为AuthHeaderValueGetAuthenticationHeaderValue()修改为GetAuthHeaderValue()- 新增类
MethodDisable以配置默认方法是否可用 - 为所有默认方法添加是否可用的控制
4.9.0
2024年11月14日 星期四
WebApiBaseController新增方法GetAuthenticationHeaderValue()以及属性AuthenticationHeaderValue
4.8.0
2024年11月14日 星期四
WebApiBaseController新增方法GetAuthorization()以及属性Authorization
4.7.0
2024年10月11日 星期五
- 优化构造方法
WebApiBaseController,并添加对SyncConfig()的调用
4.5.0
2024年7月17日 星期三
- 新增
Migrate(),EnsureCreated(...)
4.4.0
2024年4月13日 星期六
WebApiBaseController新增TDomain,并修改相关子类
4.3.0
2024年4月7日 星期日
- 新增领域对象属性
DO,并更名_dom_为_do
4.2.0
2024年4月7日 星期日
Controller相关类添加IDomain接口属性_dom_
4.1.0
2024年3月28日 星期四
- 新增:
WebApiBaseController,WebApiForIntController,WebApiForLongController
4.0.0
2024年1月27日 星期六
- 升级目标框架为
.net8.0 - 升级
Microsoft.Extensions.Configuration.Abstractions为8.0 - 与系列相关组件对齐版本号
3.19.0
2023-06-29
- 为所有泛型参数
TKey添加约束notnull - 为
MvcController的用户权限操作添加泛型TUserKey,并修改相关属性与方法,并重构GetCurrentUserId() - 为
WebApiController的用户权限操作添加泛型TUserKey,并修改相关属性与方法,并重构GetCurrentUserId() - 为
WebApiVersionController的用户权限操作添加泛型TUserKey,并修改相关属性与方法,并重构GetCurrentUserId()
3.18.0
2023-06-05
- 新增跨域管理:
CrossDomainSetup
3.17.0
2023-05-13
- 新增方法:
UseAuthSwaggerWithVersion()
3.16.0
2023-04-21
- 方法
UseAuthSwagger(...)去除参数,在内部通过DI获取所需数据 - 优化方法
AddAuthSwagger(...)
3.15.0
2023-04-15
- 项目启动可空类型
- 新增方法:
AddApiVersion - 新增属性:
BLL,Logger,Cache,并修改相关方法
3.12.0
2023-03-05
- 重命名创建与修改相关
API默认方法名
3.11.0
2023-02-24
GetTotalAsync新增参数lastDays
3.10.0
2023-02-08
- 新增
SwaggerExt类,新增方法AddAuthSwagger,UseAuthSwagger
3.9.0
2023-02-03
- 将运行时修改为
net7.0
3.8.0
2023-01-13
WebApiController新增方法Task<IActionResult> GetTotalAsync()WebApiVersionController新增方法Task<IActionResult> GetTotalAsync()
3.7.0
2023-01-03
- 新增全局引用
Global,并优化所有引用 - 优化所有命名空间,并更新对组件的引用
3.6.1
2022-12-09
- 删除MvcController中默认的
Index方法
3.6.0
2022-12-09
- 新增
MvcController
3.5.0
2022-11-23
- 升级
Swashbuckle.AspNetCore.SwaggerGen到6.4.0 - 更新对
Crping.EFCore 3.9.0的引用,使用EFCore 7.0.0
历史版本
- 3.4.1:更新引用组件版本
- 3.4.0:适配Crping.EFCore的更新,删除IRelatedBLL相关方法的使用
- 3.3.0:更新对Crping.EFCore 及 Common的引用,并对齐版本号
- 3.0.1:给方法添加判空逻辑
- 3.0.0:目标框架改为.net6.0
- 2.0.1:升级Swagger相关组件
- 2.0.0:与 Crping.EFCore 2.0 版本号对齐(EFCore 重大改版!!!)
- 1.2.1:更新对Crping.EFCore的引用
- 1.2.0:添加_bll.SetCurrentUserForRelatedBLL(GetCurrentUserId);
- 1.1.0:升级对Crping.EFCore的引用
- 1.0.0:支持普通WebApi,带版本控制WebApi
==注意:==
Crping.EFCore升级后,此组件需重新打包,保持对Crping.EFCore引用的同步更新,否则会出现“==方法未找到==”的问题
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Crping.EFCore (>= 10.2.2)
- Crping.Logger (>= 0.3.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 10.2.2 | 83 | 9/15/2026 |
| 10.2.0 | 91 | 9/14/2026 |
| 10.1.0 | 84 | 9/13/2026 |
| 10.0.0 | 95 | 9/11/2026 |
| 9.13.0 | 124 | 9/3/2026 |
| 9.12.0 | 103 | 8/31/2026 |
| 9.11.0 | 103 | 8/31/2026 |
| 9.10.0 | 103 | 8/30/2026 |
| 9.9.0 | 98 | 8/29/2026 |
| 9.8.0 | 101 | 8/29/2026 |
| 9.7.0 | 101 | 8/26/2026 |
| 9.6.0 | 106 | 8/24/2026 |
| 9.5.0 | 123 | 8/22/2026 |
| 9.4.0 | 136 | 8/18/2026 |
| 9.3.0 | 112 | 8/18/2026 |
| 9.2.0 | 99 | 8/18/2026 |
| 9.1.2 | 117 | 8/16/2026 |
| 9.1.1 | 106 | 8/16/2026 |
| 9.1.0 | 104 | 8/15/2026 |
| 9.0.0 | 106 | 8/14/2026 |