fix(#226): heal Swashbuckle reserved-id state in the Issue #180 cleanup (net10.0)#227
Conversation
…up (net10.0) When a DTO is shared between a flattened [FromQuery]/[AsParameters] binding and a request body ([FromBody]/[FromForm]) in the same document, the Issue #180 cleanup left the type reserved-but-removed in SchemaRepository: a later body operation emitted a $ref to a component that no longer exists and the FluentValidation rules never reached the document (confirmed empirically by the new Phase 1 repro tests). On the net10.0 target (Swashbuckle 10.x) the cleanup now clears the internal reserved-id via the public SchemaRepository.ReplaceSchemaId API (10.1.0+) before removing a side-effect schema, so the repository stays consistent and the next operation binding the same type regenerates a full component. SwashbuckleSchemaProvider tracks Type -> schemaId for every GetSchemaForType call (including the Issue #209 ancestor walk) to make the healing possible. net8.0/net9.0 pin Swashbuckle 8.1.1 (no ReplaceSchemaId) and keep the 7.1.10 throwaway-recovery behavior; the fallback stays as a safety net everywhere. Tests: new SharedDtoMixedBindingTests (JSON body + form body) and an OPENAPI_V2 port of the #223 shared-DTO scenario — the first operation-filter coverage on net10.0. Full matrix green: net8.0 128, net9.0 128, net10.0 99. Design record: docs/adr/ADR-006-shared-dto-state-healing-cleanup.md (authored and validated via the /adr-autonomous pipeline, 2 iterations). Suggested-by: @jgarciadelanoceda (PR #224 discussion) Issue: #226 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
@claude review this PR |
|
Claude finished @avgalex's task in 5m 36s —— View job Review of PR #227
SummaryThis is a solid, well-scoped fix. The root-cause analysis (Swashbuckle's Strengths:
Nits (non-blocking):
No correctness issues found. The ADR ( |
…view nit) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Summary
Fixes #226: when the same DTO is bound as a flattened
[FromQuery]/[AsParameters]container by one endpoint and as a request body ([FromBody]/[FromForm]) by another, the Issue #180 cleanup left the type reserved-but-removed in Swashbuckle'sSchemaRepository— the body operation then emitted a$refto a component that no longer exists (an invalid document) and the FluentValidation rules never reached it. Reproduces with the defaultRemoveUnusedQuerySchemas = true.The dangling-
$refmechanism was confirmed empirically: the new Phase 1 repro tests fail pre-fix withSchemaRepository.Schemasempty while the type stays reserved.Fix (net10.0 target only)
The Issue #180 cleanup now heals the repository state using the public
SchemaRepository.ReplaceSchemaIdAPI (Swashbuckle 10.1.0+, domaindrivendev/Swashbuckle.AspNetCore#3708): the reservation is cleared together with the component removal, so the next operation binding the same type regenerates a full component and the rules reach the real document object.SwashbuckleSchemaProvidertracksType → schemaIdfor everyGetSchemaForTypecall (covers the parameters loop and the Issue Required property in optional nested type in[FromQuery]parameter is wrongly marked as required #209 ancestor-requiredness walk).FluentValidationOperationFiltercleanup:ReplaceSchemaId(type, tempId)before removal, then removes the temp entry; untracked ids keep the plain removal.internal); other packages (core, NSwag, AspNetCore.OpenApi) are untouched — their pipelines have noSchemaRepository/reserved-ids mechanic.Design record
docs/adr/ADR-006-shared-dto-state-healing-cleanup.md— options considered (incl. rejected reflection-based healing for net8/9 and the document-filter promotion), version matrix, consequences. Review artifacts indocs/reviews/.Thanks to @jgarciadelanoceda for suggesting the
ReplaceSchemaIdapproach in the PR #224 discussion.Tests
SharedDtoMixedBindingTests(net10.0/OPENAPI_V2): shared DTO[FromQuery]+[FromBody](JSON) and[FromQuery]+[FromForm]— both red pre-fix (dangling$ref), green post-fix.SharedDtoAcrossEndpointsTest:OPENAPI_V2port of the When one or more endpoints have the same Dto the firts one gets the FluentValidationRule and the next ones are not getting it #223 scenario — the net10.0 target previously had no shared-DTO operation-filter coverage at all.Release
version.props→ 7.1.11, CHANGELOG entry added.🤖 Generated with Claude Code