Skip to content

Numeric bounds from short/byte-typed rules are silently dropped (IsNumeric doesn't recognize Int16) #222

Description

@send0xx

Validation rules whose bounds are short (or other small integer types like byte/ushort) do not produce minimum/maximum in the generated schema. The rules are matched (IBetweenValidator/IComparisonValidator conditions pass), but the apply action silently does nothing.

The cause is the numeric type check used by the default Between and Comparison rules:

https://github.com/micro-elements/MicroElements.Swashbuckle.FluentValidation/blob/v7.1.7/src/MicroElements.OpenApi.FluentValidation/Core/Extensions.cs#L19

short is not in the list, so betweenValidator.From.IsNumeric() returns false and the bound is skipped. Int16 is a valid OpenAPI type - the generator itself emits "type": "integer", "format": "int16" for the same property, it just loses the constraints.

How To Reproduce:

public class Sample
{
    public short Quantity { get; set; }
}

public class SampleValidator : AbstractValidator<Sample>
{
    public SampleValidator()
    {
        RuleFor(x => x.Quantity).InclusiveBetween((short)1, (short)99);
    }
}

Generated schema:

"quantity": { "type": "integer", "format": "int16" }

Expected:

"quantity": { "type": "integer", "format": "int16", "minimum": 1, "maximum": 99 }

This can't be worked around at the validator definition site: for a short property, InclusiveBetween/GreaterThanOrEqualTo overloads only accept short bounds, so ValueToCompare/From/To are always boxed shorts.

Expected behavior

All integer/floating primitive types should be treated as numeric, e.g.:

internal static bool IsNumeric(this object value) =>
    value is sbyte or byte or short or ushort or int or uint or long or ulong
        or float or double or decimal or BigInteger;

NumericToDecimal already handles them all via Convert.ToDecimal.

Versions

  • MicroElements.AspNetCore.OpenApi.FluentValidation 7.1.7 (net10.0)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions