feat(ADR-007): promote FluentValidationDocumentFilter to a supported opt-in pipeline (UseDocumentFilter, v7.2.0)#228
Conversation
…opt-in pipeline (UseDocumentFilter) The document filter processes the whole document at once and performs the Issue #180 cleanup once at the end, so per-operation shared-DTO state issues (#223/#226) cannot occur in this pipeline — on ALL target frameworks, including net8.0/net9.0 where the 7.1.11 ReplaceSchemaId healing API does not exist. Parity with the default schema + operation filter pipeline: - required-marking with the whole-dot-path check (#209) - request bodies and encoding.contentType for [FromForm] (#216) - multi-validator support, allOf/oneOf/anyOf traversal - $ref preservation for unmodified properties (#198, net10.0) - every operation of a multi-verb path is processed (was: first only) - reserved-id healing in the cleanup on net10.0 (#226 mechanism) The #209 and #216 logic is extracted into internal components (ParameterRequiredResolver, RequestBodyRuleApplicator) shared by both pipelines so they cannot drift. Robustness: top-level try/catch, ServiceProviderValidatorRegistry fallback, injected rule provider honored (new optional ctor parameter, appended last — source-compatible), dead code and logging/nullability cleanups. Public API (additive, minor): RegistrationOptions.UseDocumentFilter; ExperimentalUseDocumentFilter kept as an [Obsolete] forwarding alias. Default pipeline unchanged; a future major may switch the default. Tests: new DocumentFilterParityTests (8 on OpenApi v1, 6 on OPENAPI_V2, incl. an investigation test pinning that enum schemas ARE emitted as $refs). Full matrix green: net8.0 136, net9.0 136, net10.0 105. Verified live: samples/MinimalApi switched to the document-filter pipeline; swagger.json confirms #180/#209/#216 and the #226 mixed body+query shape. Release: version.props 7.2.0 + CHANGELOG entry. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
4a2f312 to
ef28a11
Compare
Removes the ADR-006/ADR-007 design and review documents from git (they are maintained locally by the maintainer) and replaces in-code ADR references with issue references so nothing points at files that are not in the repo. No code changes — comments, CHANGELOG and README wording only. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…opt-in pipeline (UseDocumentFilter) The document filter processes the whole document at once and performs the Issue #180 cleanup once at the end, so per-operation shared-DTO state issues (#223/#226) cannot occur in this pipeline — on ALL target frameworks, including net8.0/net9.0 where the 7.1.11 ReplaceSchemaId healing API does not exist. Parity with the default schema + operation filter pipeline: - required-marking with the whole-dot-path check (#209) - request bodies and encoding.contentType for [FromForm] (#216) - multi-validator support, allOf/oneOf/anyOf traversal - $ref preservation for unmodified properties (#198, net10.0) - every operation of a multi-verb path is processed (was: first only) - reserved-id healing in the cleanup on net10.0 (#226 mechanism) The #209 and #216 logic is extracted into internal components (ParameterRequiredResolver, RequestBodyRuleApplicator) shared by both pipelines so they cannot drift. Robustness: top-level try/catch, ServiceProviderValidatorRegistry fallback, injected rule provider honored (new optional ctor parameter, appended last — source-compatible), dead code and logging/nullability cleanups. Public API (additive, minor): RegistrationOptions.UseDocumentFilter; ExperimentalUseDocumentFilter kept as an [Obsolete] forwarding alias. Default pipeline unchanged; a future major may switch the default. Tests: new DocumentFilterParityTests (8 on OpenApi v1, 6 on OPENAPI_V2, incl. an investigation test pinning that enum schemas ARE emitted as $refs). Full matrix green: net8.0 136, net9.0 136, net10.0 105. Verified live: samples/MinimalApi switched to the document-filter pipeline; swagger.json confirms #180/#209/#216 and the #226 mixed body+query shape. Release: version.props 7.2.0 + CHANGELOG entry. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> chore: keep ADR/review process artifacts out of the repository Removes the ADR-006/ADR-007 design and review documents from git (they are maintained locally by the maintainer) and replaces in-code ADR references with issue references so nothing points at files that are not in the repo. No code changes — comments, CHANGELOG and README wording only. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ithub.com/micro-elements/MicroElements.Swashbuckle.FluentValidation into feature/adr-007-document-filter-promotion
|
@claude review this PR |
|
Claude finished @avgalex's task in 3m 11s —— View job Review: ADR-007 document-filter promotion (v7.2.0)
Note: I was not able to run OverallThis is a well-executed refactor. Extracting the #209/#216 logic into Minor observations (non-blocking)
Correctness spot-checks
No blocking issues found. Nice work on the shared-component extraction and the multi-verb |
…avior change (PR #228 review) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Thanks for the review. Point-by-point:
Test matrix from the PR description is confirmed by this PR's CI run (both jobs green). |
Summary
Implements ADR-007: the experimental
FluentValidationDocumentFilteris promoted to a supported opt-in pipeline at full functional parity with the default schema + operation filter pipeline.The document filter processes the whole document at once and performs the Issue #180 cleanup once at the end, so the per-operation shared-DTO state bug class (#223/#226) cannot occur in this pipeline — on all target frameworks, including net8.0/net9.0 where the 7.1.11
ReplaceSchemaIdhealing API does not exist.What's inside
Parity (previously missing in the document filter):
[FromQuery]parameter is wrongly marked as required #209) — was entirely absentencoding.contentTypefor[FromForm](Add support for media types #216) — was entirely absentGetValidators),allOf/oneOf/anyOftraversal,$refpreservation for unmodified properties (7.1.2 replaces schema reference with copy of schema #198, net10.0)FindParampreviously inspected only the first operation)No-drift architecture: the #209 and #216 logic is extracted into internal components (
ParameterRequiredResolver,RequestBodyRuleApplicator) shared by both pipelines. The operation filter refactor is semantics-preserving — all pre-existing tests pass unchanged.Robustness fixes (long-standing rot): top-level try/catch (a throwing validator no longer kills document generation),
ServiceProviderValidatorRegistryfallback, injectedIFluentValidationRuleProviderhonored, dead code removed, logger category fixed, record nullability,[Obsolete("Есть повтор")]leftover resolved.Public API (additive, minor):
RegistrationOptions.UseDocumentFilter(defaultfalse— the default pipeline is unchanged);ExperimentalUseDocumentFilterkept as an[Obsolete]forwarding alias; new optional ctor parameter onFluentValidationDocumentFilter(appended last — source-compatible). A future major version may switch the default (separate ADR).Tests
DocumentFilterParityTests: 8 tests on OpenApi v1 (net8/net9) + 6 on OPENAPI_V2 (net10), covering Required property in optional nested type in[FromQuery]parameter is wrongly marked as required #209 (incl. optional-ancestor negative case), Add support for media types #216 encoding, JSON body, shared-DTO query+body (When one or more endpoints have the same Dto the firts one gets the FluentValidationRule and the next ones are not getting it #223/Follow-up (#223): body-bound shared DTO ([FromBody]/[FromForm]) may not receive rules when the same type is flattened as [FromQuery] #226 structural pin), multi-verb, multi-validator, 7.1.2 replaces schema reference with copy of schema #198 refs, reserved-id healing, and a gap-7 investigation test that pins the fact that Swashbuckle emits enum schemas as$refs (repository-resolution of$refparameter schemas remains future both-pipelines work per ADR-007).samples/MinimalApiswitched to the document-filter pipeline; the generated swagger.json confirms the Validators for records used with [AsParameters] create unused component schemas #180 cleanup, live required-marking, constraint copy-back, and rules on theSampleDTO bound as both[FromBody]and[FromQuery](the Follow-up (#223): body-bound shared DTO ([FromBody]/[FromForm]) may not receive rules when the same type is flattened as [FromQuery] #226 mixed shape).Design process
The change was designed through an ADR process (4 review iterations) and implemented phase-by-phase with per-phase test gates; the design/review artifacts are maintained outside the repository.
Release
version.props→ 7.2.0 (minor: additive API, default behavior unchanged), CHANGELOG entry added.🤖 Generated with Claude Code
Behavior note (from review)
Constructing
FluentValidationDocumentFilterwith neithervalidatorRegistrynorserviceProvidernow throwsArgumentNullException(matching the sibling filters) instead of silently producing a filter that applies no rules. The DI registration path (AddFluentValidationRulesToSwagger) is unaffected.