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
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Crping.EFCore.Controller" Version="10.2.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Crping.EFCore.Controller" Version="10.2.2" />
                    
Directory.Packages.props
<PackageReference Include="Crping.EFCore.Controller" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Crping.EFCore.Controller --version 10.2.2
                    
#r "nuget: Crping.EFCore.Controller, 10.2.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Crping.EFCore.Controller@10.2.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Crping.EFCore.Controller&version=10.2.2
                    
Install as a Cake Addin
#tool nuget:?package=Crping.EFCore.Controller&version=10.2.2
                    
Install as a Cake Tool

Crping.EFCore.Controller

基于Crping.EFCoreWebApi的增、删、改、查、分页等常用方法实现!

版本更新说明


10.2.2

2026年9月15日 星期二

Crping.EFCore / Crping.EFCore.Common 同步升至 10.2.2 —— ct 全量复查批次:端点签名零变更、升级零迁移、需重编译

行为增强 — 端点取消令牌透传(客户端断连即取消)

  • WebApiBaseController 20 个端点将 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 零变更、升级零迁移、需重编译

健壮性修复 — 异常中间件响应已开始守卫

  • ExceptionMiddleware catch-all 写响应前检查 context.Response.HasStarted:响应开始后的异常(典型:动作返回体序列化中途失败/循环引用)记录告警后原样上抛——此前强设 StatusCode 会抛 InvalidOperationException 掘盖原始异常且客户端收到中断连接而非错误体(与 ASP.NET Core 内置异常处理的标准守卫一致;ExceptionMiddlewareTests 新增"响应已开始"用例)

文档化

  • WebApiRootController XML 注释明示 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 7807 ProblemDetails(Status/Title/Detail/Type,Content-Type application/problem+json)——与端点 ProducesResponseType(typeof(ProblemDetails)) 标注、异常路径(ExceptionHelper)三方一致,消费方按契约解析 4xx 不再失败;Error 为 null 的纯状态码与 Data-only 载荷分支保持既有形态。按裸字符串解析业务错误的客户端需适配为 problem.detail

破坏性变更 — soft/restore 成功码 200 → 204

  • DELETE {id}/softPOST {id}/restore 成功响应由 200 空体改 204(RFC 9110 不建议 200 无载荷,与 Update/toggle 族 NoContent 对齐);DELETE {id}(硬删)保持 200 + 被删实体不变——严格匹配 200 的客户端需适配

标注补齐

  • PATCH {id}/enablePATCH {id}/auditDELETE {id}/softPOST {id}/restoreProducesResponseType(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 的 RouteTokenTransformerConventionIActionModelConvention,挂载经框架包装为内部 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.ValidateRoutesUseRoutes 与 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}/enableToggleEnableStatusAsync 端点方法)——PATCH {id}/enable(v9.20.0 起并存)成为唯一形态,同一开关 ToggleEnableStatusAsync 门控、同一 BLL 委托
  • 删除 PUT {id}/auditToggleAuditStatusAsync 端点方法)——PATCH {id}/audit 成为唯一形态
  • 删除 DELETE {id}/delete 端点 + MethodsEnable.ToggleDeleteStatusAsync 开关——PATCH {id}/deleted(set 语义,独立开关 SetDeleteStatusAsync)成为删除状态操作唯一端点
  • 唯一配置面变化:消费者 ToggleDeleteStatusAsync = trueSetDeleteStatusAsync = 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=truePOST {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 OK204 NoContent——五个端点运行时本就返回 204 无响应体(DAL 单条更新成功 ResultCode.NoContent、四个状态切换方法 count > 0 ? ApiResult.NoContent() : ApiResult.NotFound()),v9.17.0 批次统一按「Create 201 / 其余 200」标注未逐端点核对,OpenAPI 契约与实际行为不符
  • 其余端点核对后维持原标注:PUT batch/audit/status 200 + 行数、DELETE {id} 200 + 被删实体(ApiResult<TModel?>)、DELETE {id}/soft / POST {id}/restore 200(ApiResult.Ok())、POST 201
  • 影响面:仅 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}/deletedPUT {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}/deleted set 目标值)→ PUT,非幂等(PATCH {id}/enable / PATCH {id}/audit toggle 翻转)→ 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}/enableToggleEnableStatusPatchAsync)与 PATCH {id}/auditToggleAuditStatusPatchAsync):toggle 非幂等与 PUT 语义不符(PUT 按约定幂等,网络层超时重试会双翻转);修正只换动词,toggle 语义保留
  • 新旧端点同一开关门控MethodsEnable.ToggleEnableStatusAsync / ToggleAuditStatusAsync)、同一 BLL 委托——消费者开启开关即同时获得 PUT / PATCH 双路由(OpenAPI 自然展示迁移路径),v10 删除 PUT 端点时配置零变动
  • 遗留 PUT 端点保留,XML 注明「遗留端点(v10 移除)」;启动期冲突检测不误报(同模板不同 HTTP 方法为合法双端点)

新功能 — 删除状态 set 语义端点(PATCH {id}/deleted,路由评审 v10 候选 ②)

  • 新增 PATCH {id}/deletedSetDeleteStatusAsync):精确设置删除状态目标值(幂等),替代动词入路径的遗留 DELETE {id}/delete toggle 端点(v10 随 ToggleDeleteStatusAsync 开关一并移除)
  • isDeleted 走 query 绑定;selfOnly 默认 false(内容管理语义,与切换版一致);仅设置 IsDeleted 标志、不盖章/清理 DeletedBy / DeletedAt——完整软删除语义用 DELETE {id}/soft,完全恢复语义用 POST {id}/restore
  • MethodsEnable 新增 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}/enablePUT {id}/audit(开关不变,消费者零感知)
  • DELETE {id}/delete + MethodsEnable.ToggleDeleteStatusAsync 开关——唯一配置面变化ToggleDeleteStatusAsync = true 需迁移为 SetDeleteStatusAsync = true
  • DELETE {id}/softreset 参数(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 自动不回传 Detail
  • GetCurrentUserId 的 claim 值无法转换为用户主键类型时归 401UnauthorizedAccessException)——旧行为 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 无响应体),不再依赖兜底分支的隐式行为
  • CrossDomainSetup XML 文档注明:空来源列表将静默拒绝全部跨域请求;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.UserKeyNameprotected constprotected virtual 属性:JWT claim 名("UserId")可覆写定制(如 "uid" / "sub"),无需整体覆写 GetCurrentUserId

修复 — Authorization 解析

  • GetAuthHeaderValueSplit(' ', 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/statusSetAuditStatusAsync(精确设置审核状态,由 MethodsEnable.SetAuditStatusAsync 开关控制)
  • PUT batch/audit/statusBatchSetAuditStatusAsync(批量设置审核状态,由 MethodsEnable.BatchSetAuditStatusAsync 开关控制);请求体统一为 DTO BatchAuditStatusRequest<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 + UnauthorizedObjectResultForbidden(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 响应构造与 DatabaseExtensionsIApplicationBuilder 扩展)由 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.GetCurrentUserIdUser.FindFirst(去三次 foreach + Convert.ChangeType 装箱)、GetAuthorizationRequest.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)对称

每个端点独立开关

  • GetDetailsForAdminAsyncGET {id}/for-admin)拆独立开关 MethodsEnable.GetDetailsForAdminAsync(原复用 GetDetailsAsync
  • GetForAdminEditorAsyncGET {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 时抛 401UnauthorizedAccessException,经 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/OffsetGetOffsetPageAsync)替代
  • WebApiRootController.MethodsEnable 实例属性改只读(从注册表读取,未注册为 null),移除 setter——旧 Configure() 中设置实例属性的写法编译失败,强制走 RegisterMethodsEnable<TController> 注册
  • 删除零引用 MvcControllerUtils.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 / ExceptionMiddlewarestatusCode >= 500Detail 置为 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

重命名(向后兼容)

  • WebApiCoreControllerWebApiRootController:旧类保留并继承新类,添加 Dom 属性向后兼容
  • WebApiForIntControllerWebApiIntController:旧类保留并继承新类
  • WebApiForLongControllerWebApiLongController:旧类保留并继承新类

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 行注释)

安全(行为变更 — 建议关注)

  • 移除 MvcControllerWebApiCoreControllerGetCurrentUserId()#if DEBUG 分支
    • 之前:Debug 构建返回硬编码 "DebugUser",Release 构建从 JWT claims 读取
    • 现在:始终从 JWT claims 读取 — 生产环境之前若依赖 Debug 构建的"假用户"行为,需要在配置或开发环境中显式 mock;不再有"Debug 即自动拥有任意身份"的隐式行为
    • 这条与 AGENTS.md「反模式」§#if DEBUG 在生产路径中改变用户身份 一致:本次提交已修复

重构

  • 提取 ExceptionHelperExceptionFilterMapException 逻辑由重复实现改为集中调用,消除 21 行的分散代码

修复

  • Utils.Migrate / Utils.EnsureCreated 改用 GetRequiredService<T>() 解析 DbContext / DbContextFactory,之前若服务未注册会静默吞错(null),现在会立即抛 InvalidOperationException

内部(净状态未变)

  • IDomain 中未使用的 HTTP 类型依赖相关 refactor(commit 3eb4504)已被回退(65ae448),净状态未变

6.10.0

2026年7月14日 星期二
  • 剥离 NSwagApiDocExt(移除 AddAuthOpenApiDocumentUseAuthOpenApi 扩展方法),OpenApi 文档生成由独立包 Crping.ApiDoc.NSwag 提供
  • 移除 NSwag.AspNetCore 包引用;显式声明 Microsoft.AspNetCore.App 共享框架引用以取代原本寄生于 NSwag 的隐式 FrameworkReference
  • 清理不再需要的 Microsoft.AspNetCore.Http.ExtensionsMicrosoft.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,用于控制器方法的授权验证
  • 为控制器方法添加管理员权限验证:GetDetailsForAdminAsyncGetForAdminEditorAsync 方法添加 [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日 星期六
  • 新增类 ExceptionMiddlewareExceptionFilter

4.10.0

2024年11月16日 星期六
  • AuthenticationHeaderValue 修改为 AuthHeaderValue
  • GetAuthenticationHeaderValue() 修改为 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日 星期四
  • 新增:WebApiBaseControllerWebApiForIntControllerWebApiForLongController

4.0.0

2024年1月27日 星期六
  • 升级目标框架为.net8.0
  • 升级Microsoft.Extensions.Configuration.Abstractions8.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
  • 新增属性:BLLLoggerCache,并修改相关方法

3.12.0

2023-03-05
  • 重命名创建与修改相关API默认方法名

3.11.0

2023-02-24
  • GetTotalAsync新增参数lastDays

3.10.0

2023-02-08
  • 新增SwaggerExt类,新增方法AddAuthSwaggerUseAuthSwagger

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.SwaggerGen6.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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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
Loading failed