Skip to content

Releases: micro-elements/MicroElements.Swashbuckle.FluentValidation

7.1.8

Choose a tag to compare

@avgalex avgalex released this 01 Jul 19:16
2e8c074

🔒 Security fix — Issue #220

Closes the transitive high-severity advisory GHSA-v5pm-xwqc-g5wc / CVE-2026-49451 (CVSS 7.5, CWE-674 Uncontrolled Recursion — a circular $ref schema could stack-overflow the OpenAPI reader; availability / process-termination only).

  • Bumped Swashbuckle.AspNetCore.SwaggerGen 10.0.010.2.1 on the net10.0 target, which resolves the transitive Microsoft.OpenApi from the vulnerable 2.3.0 to the patched 2.7.5.
  • The net8.0 / net9.0 targets use Swashbuckle 8.1.1Microsoft.OpenApi v1 and were never in the advisory range — left unchanged.
  • No public API or OpenAPI output changes — dependency + version bump only.

📎 IFormFile media type & file size validation — Issue #216

Stable rollup of the work previously shipped as 7.1.8-beta.1 / 7.1.8-beta.2:

  • New File-level FluentValidation rules in MicroElements.OpenApi.FluentValidation.FileUpload: .FileContentType(params string[]), .MaxFileSize(long), .MinFileSize(long), .FileSizeBetween(long, long) on IRuleBuilder<T, IFormFile>.
  • Swashbuckle, NSwag, and Microsoft.AspNetCore.OpenApi emit multipart/form-data encoding.contentType for file parts and append the allowed types / size limits to the file property description.
  • Purely additive / opt-in — output only changes when the new rules are used.

Full changelog: https://github.com/micro-elements/MicroElements.Swashbuckle.FluentValidation/blob/master/CHANGELOG.md

7.1.8-beta.2

7.1.8-beta.2 Pre-release
Pre-release

Choose a tag to compare

@avgalex avgalex released this 21 Jun 10:16

Pre-release for #216 — tracks PR #218.

Adds to 7.1.8-beta.1: Microsoft.AspNetCore.OpenApi now emits encoding.contentType for the file part (the backend Scalar uses), so the allowed media types are machine-readable in the document, not only in the description:

multipart/form-data:
  schema: { $ref: "#/components/schemas/UploadProductImageRequest" }   # net10
  encoding:
    File:
      contentType: "image/jpeg, image/png"

Works on net9 (inline form schema) and net10 (resolves the whole-body $ref component to find the part name). Backend matrix is now content-type+size on all three backends, both as description and encoding.contentType.

Pre-release built from branch feature/issue-216-media-types (not yet merged to master).

7.1.8-beta.1

7.1.8-beta.1 Pre-release
Pre-release

Choose a tag to compare

@avgalex avgalex released this 20 Jun 17:40

Pre-release for #216 — media type (content type) & file size validation for IFormFile uploads. Tracks PR #218.

New File-level FluentValidation rules (MicroElements.OpenApi.FluentValidation.FileUpload):

RuleFor(x => x.File)
    .NotNull()
    .FileContentType("image/jpeg", "image/png")
    .MaxFileSize(2 * 1024 * 1024);

Also: .MinFileSize(long), .FileSizeBetween(long, long). They enforce at runtime and drive OpenAPI.

Backend content type + size in description encoding.contentType
Swashbuckle ✅ (net8/9 = OAS 3.0; net10 = OAS 3.1)
NSwag ✅ via FluentValidationOperationProcessor (encodingType — NSwag limitation)
Microsoft.AspNetCore.OpenApi ❌ not emitted

Additive / opt-in — no existing document output changes. See CHANGELOG and PR #218.

Pre-release built from branch feature/issue-216-media-types (not yet merged to master).

7.1.7

Choose a tag to compare

@avgalex avgalex released this 20 Jun 12:55
ad34293

Stable release 7.1.7 — promotes 7.1.7-beta.3 to stable.

Fixed

  • Nested [FromQuery] fixes (#209 + #211) now also apply to the native Microsoft.AspNetCore.OpenApi transformer and the experimental Swashbuckle DocumentFilter (Issue #213)
    • FluentValidationOperationTransformer now follows the same reachability + ancestor-required rules as the Swashbuckle OperationFilter
    • The experimental FluentValidationDocumentFilter no longer copies value constraints onto a flattened nested parameter whose nested validation is not wired from the root validator
    • GetMethodInfo now resolves the action method from ControllerActionDescriptor (MVC controllers), not only minimal-API endpoint metadata
    • NSwag is unaffected (it has no [FromQuery] parameter flattening)
  • A validator for a nested type bound via [FromQuery] was reflected in the OpenAPI document even when it was not wired into the root validator via SetValidator/ChildRules (Issue #211)
    • Nested rules are now applied only when the SetValidator/ChildRules chain from the action's root [FromQuery] validator actually reaches the leaf container
    • Behavioral change: when no validator is registered for the root [FromQuery] type, a flattened nested parameter is left unconstrained — matching runtime
  • A required leaf property inside an optional nested type bound via [FromQuery] was wrongly marked as a required parameter (Issue #209)
    • A flattened nested parameter is now marked required only when every ancestor segment of the dot-path is required
    • Value constraints (e.g. minLength) still apply to an optional nested parameter when it is provided

Full changelog: CHANGELOG.md

7.1.7-beta.3

7.1.7-beta.3 Pre-release
Pre-release

Choose a tag to compare

@avgalex avgalex released this 17 Jun 20:25
241530b
  • Fixed: The nested [FromQuery] fixes (#209 + #211) now also apply to the native Microsoft.AspNetCore.OpenApi transformer and the experimental Swashbuckle DocumentFilter (Issue #213)
    • FluentValidationOperationTransformer (package MicroElements.AspNetCore.OpenApi.FluentValidation) previously set a nested parameter required from the leaf validator alone — ignoring both whether the SetValidator/ChildRules chain reaches the leaf (#211) and whether every ancestor of the dot-path is required (#209). It now follows the same reachability + ancestor-required rules as the Swashbuckle OperationFilter
    • The experimental FluentValidationDocumentFilter no longer copies value constraints onto a flattened nested parameter whose nested validation is not wired from the root validator (#211)
    • GetMethodInfo now resolves the action method from ControllerActionDescriptor (MVC controllers), not only minimal-API endpoint metadata, so the dot-path root type can be resolved for controller actions
    • NSwag is unaffected (it has no [FromQuery] parameter flattening)
  • Fixed: A validator for a nested type bound via [FromQuery] was reflected in the OpenAPI document even when it was not wired into the root validator via SetValidator/ChildRules (Issue #211)
    • FluentValidationOperationFilter resolved the leaf container's validator directly from the registry (by ModelMetadata.ContainerType), so a nested NotEmpty() marked the flattened parameter (e.g. RequiredSubType.SubProperty) as required even though FluentValidation never validates an unwired child object — the OpenAPI doc claimed required, but the API accepted requests without it
    • Fix: for a flattened nested parameter, nested rules are now applied only when the SetValidator/ChildRules chain from the action's root [FromQuery] validator actually reaches the leaf container; otherwise the parameter is left unconstrained, matching runtime behavior
    • When the root container type cannot be resolved, prior behavior is preserved (no regression for existing nested-parameter scenarios)
    • Behavioral change: when no validator is registered for the root [FromQuery] type (only a leaf/child validator is registered), a flattened nested parameter is now left unconstrained — matching runtime, where no validation runs without a root validator
  • Fixed: A required leaf property inside an optional nested type bound via [FromQuery] was wrongly marked as a required parameter (Issue #209)
    • The 7.1.1 fix (Issue #162) made nested [FromQuery] validation match the leaf property name, but FluentValidationOperationFilter then set required based solely on the leaf type, ignoring whether the ancestor segment of the dot-path was optional
    • Because two nested properties of the same leaf type share one schema/validator (e.g. OptionalSubType.SubProperty and RequiredSubType.SubProperty), a NotEmpty() on the leaf marked both flattened parameters as required
    • Fix: a flattened nested parameter is now marked required only when every ancestor segment of the dot-path is required — resolved from the action's root [FromQuery] type, combining the native schema required (e.g. the C# required modifier) with FluentValidation NotNull/NotEmpty rules
    • Value constraints (e.g. minLength) still apply to an optional nested parameter when it is provided
    • When the root container type cannot be resolved, prior behavior is preserved (no regression for existing nested-parameter scenarios)

7.1.7-beta.2

7.1.7-beta.2 Pre-release
Pre-release

Choose a tag to compare

@avgalex avgalex released this 17 Jun 07:52
a6fa097
  • Fixed: A validator for a nested type bound via [FromQuery] was reflected in the OpenAPI document even when it was not wired into the root validator via SetValidator/ChildRules (Issue #211)
    • FluentValidationOperationFilter resolved the leaf container's validator directly from the registry (by ModelMetadata.ContainerType), so a nested NotEmpty() marked the flattened parameter (e.g. RequiredSubType.SubProperty) as required even though FluentValidation never validates an unwired child object — the OpenAPI doc claimed required, but the API accepted requests without it
    • Fix: for a flattened nested parameter, nested rules are now applied only when the SetValidator/ChildRules chain from the action's root [FromQuery] validator actually reaches the leaf container; otherwise the parameter is left unconstrained, matching runtime behavior
    • When the root container type cannot be resolved, prior behavior is preserved (no regression for existing nested-parameter scenarios)
    • Behavioral change: when no validator is registered for the root [FromQuery] type (only a leaf/child validator is registered), a flattened nested parameter is now left unconstrained — matching runtime, where no validation runs without a root validator
  • Fixed: A required leaf property inside an optional nested type bound via [FromQuery] was wrongly marked as a required parameter (Issue #209)
    • The 7.1.1 fix (Issue #162) made nested [FromQuery] validation match the leaf property name, but FluentValidationOperationFilter then set required based solely on the leaf type, ignoring whether the ancestor segment of the dot-path was optional
    • Because two nested properties of the same leaf type share one schema/validator (e.g. OptionalSubType.SubProperty and RequiredSubType.SubProperty), a NotEmpty() on the leaf marked both flattened parameters as required
    • Fix: a flattened nested parameter is now marked required only when every ancestor segment of the dot-path is required — resolved from the action's root [FromQuery] type, combining the native schema required (e.g. the C# required modifier) with FluentValidation NotNull/NotEmpty rules
    • Value constraints (e.g. minLength) still apply to an optional nested parameter when it is provided
    • When the root container type cannot be resolved, prior behavior is preserved (no regression for existing nested-parameter scenarios)

7.1.6

Choose a tag to compare

@avgalex avgalex released this 02 Jun 16:01
2ee3c55

Stable 7.1.6 (supersedes the unreleased 7.1.5 betas).

Changes

  • Fixed: $ref replaced with an inline copy (and the child component left orphaned) when a nested object's constraints come from ChildRules or an inline child validator (#198, #206).
    • The 7.1.3 fix restored unmodified $refs, but when the nested type had no standalone validator its component schema gained its required only after the parent's inline snapshot — the stale required diverged and defeated the restore check. The Required comparison in HasValidationConstraintChanges is now directional.
    • SetValidator (with a standalone child validator) was already correct; BigInteger/enum per-model constraints (#146/#176) continue to work.
  • Added: ConditionalRulesMode option to control how .When()/.Unless() conditional rules are handled (Exclude (default) / Include / IncludeWithWarning) (#203).
  • Fixed: Multiple .Matches() rules on one property rendered incorrectly (only the first pattern shown). They are now combined into a single pattern via lookahead assertions, across Swashbuckle, MicroElements.AspNetCore.OpenApi.FluentValidation, and NSwag (#204, #205).
    • Changed: default of SchemaGenerationOptions.UseAllOfForMultipleRules truefalse; set it to true to keep the legacy allOf representation.

NuGet: https://www.nuget.org/packages/MicroElements.Swashbuckle.FluentValidation/7.1.6

7.1.6-beta.1

7.1.6-beta.1 Pre-release
Pre-release

Choose a tag to compare

@avgalex avgalex released this 02 Jun 13:35
ae7b81d

Pre-release for the upcoming 7.1.6.

Changes since 7.1.5-beta.2

  • Fixed: $ref still replaced with an inline copy (and the child component left orphaned) when nested object constraints come from ChildRules or an inline child validator (#198, #206).
    • The 7.1.3 fix restored unmodified $refs, but when the nested type has no standalone validator its component schema gains its required only after the parent's inline snapshot is taken, so the stale required diverged and defeated the restore check — leaving an inline copy and an orphaned component.
    • Fix: the Required comparison in HasValidationConstraintChanges is now directional — restoration is only blocked when the inline copy carries a required entry the component lacks.
    • SetValidator (with a standalone child validator) was already correct; BigInteger/enum per-model constraints (#146/#176) continue to work.

NuGet: https://www.nuget.org/packages/MicroElements.Swashbuckle.FluentValidation/7.1.6-beta.1

7.1.5-beta.2

7.1.5-beta.2 Pre-release
Pre-release

Choose a tag to compare

@avgalex avgalex released this 16 May 12:18

Pre-release for the upcoming 7.1.5.

Changes since 7.1.5-beta

  • Fixed: Multiple .Matches() rules on one property displayed incorrectly — only the first pattern shown, property duplicated (#204, #205).
    • Multiple patterns were placed into separate allOf subschemas, which Swagger UI/Redoc/Scalar collapse, keeping only the first pattern.
    • Now multiple .Matches() rules are combined into a single pattern via lookahead assertions, preserving .Matches() semantics and rendering correctly.
    • Applied to all providers: Swashbuckle, MicroElements.AspNetCore.OpenApi.FluentValidation, and NSwag.
    • Behavior change: SchemaGenerationOptions.UseAllOfForMultipleRules default truefalse; set it to true to keep the legacy allOf representation.

Already in 7.1.5-beta

  • Added: ConditionalRulesMode option to control how .When()/.Unless() conditional rules are handled during schema generation (#203).

See CHANGELOG.md for full details.

v7.1.5-beta

v7.1.5-beta Pre-release
Pre-release

Choose a tag to compare

@avgalex avgalex released this 01 Apr 12:05

What's New

ConditionalRulesMode option (Issue #203)

Controls how conditional validation rules (.When(), .Unless()) are handled during OpenAPI schema generation.

Modes:

  • Exclude (default) — conditional rules are excluded from schema (backward-compatible)
  • Include — conditional rules are included in schema
  • IncludeWithWarning — same as Include, but logs a warning for each conditional rule

Usage:

services.AddFluentValidationRulesToSwagger(options =>
{
    options.ConditionalRules = ConditionalRulesMode.Include;
});

Why: When users write .When(x => x.Prop is not null) as a null-guard, validation constraints (minLength, maxLength, etc.) were silently dropped from the schema. This option lets users opt-in to including those constraints.