Skip to content

Validator for nested type in [FromQuery] parameter is considered even when not used #211

@cremor

Description

@cremor

Example controller method:

[HttpGet]
public ActionResult<string> Get([FromQuery] FilterType filter)
{
    var validationResult = _filterTypeValidator.Validate(filter);

    if (!validationResult.IsValid)
    {
        return BadRequest(validationResult.Errors);
    }

    return filter.ToString();
}

Example types and validators:

public sealed record class FilterType
{
    public required FilterSubType RequiredSubType { get; init; }
}

public sealed record class FilterSubType
{
    public string? SubProperty { get; init; }
    public string? SubProperty2 { get; init; }
}

public sealed class FilterTypeValidator : AbstractValidator<FilterType>
{
    public FilterTypeValidator(IValidator<FilterSubType> filterSubTypeValidator)
    {
        RuleFor(x => x.RequiredSubType)
            .NotNull();
            // The 'FilterSubType.SubProperty' is marked as required even without the following line of code.
            //.SetValidator(filterSubTypeValidator);
    }
}

public sealed class FilterSubTypeValidator : AbstractValidator<FilterSubType>
{
    public FilterSubTypeValidator()
    {
        RuleFor(x => x.SubProperty).NotEmpty();
    }
}

Observation
The section Nested objects (SetValidator / ChildRules) in your readme explicitly mentions how you need to call nested validators. But even if you don't do that (like in my sample above with the SetValidator call commented out) the FilterSubType.SubProperty is still marked as required in the OpenAPI document.

So the API documentation claims that the property is required, but if you then actually call the API without that parameter (e.g. https://localhost:7095/api/test?RequiredSubType.SubProperty2=dummyValue) the validation doesn't fail.

Question
Is this by design? I'd understand if this is required for some other use case (e.g. types in request bodies) or if it makes the implementation easier. But if it's an easy fix then it would be nice to have.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    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