Set Fluent Validator by condition

47 views Asked by At

I'm trying to set validator for `Address` depends on item existence, but I wanna use RuleFor and other handy methods rather that manually log every error with `ValidationContext` but it seems like when I'm trying to do it via `CustomAsync`, it's just skipped and rules for `RequestAddressValidator` skipped.

Do you have any ideas on how to make RequestAddressValidator rules working?

public class RequestModel
{
    public required string Id { get; init; }

    public Address? Address { get; init; }
}

public class Address
{
    public required string Line1 { get; init; }
    public required string Line2 { get; init; }
}

public class RequestAddressValidator: AbstractValidator<Address>
{
    public RequestAddressValidator()
    {
        RuleFor(x => x.Line1).NotEmpty();
        RuleFor(x => x.Line2).NotEmpty();
    }
}

public class RequestModelValidator: AbstractValidator<RequestModel>
{
    public RequestModelValidator(IApiClient apiClient)
    {
        RuleFor(x => x)
            .Custom((requestModel, context) =>
            {
                var item = apiClient.GetByIdAsync(requestModel.Id);

                if (item != null)
                {
                    RuleFor(x => x.Address).SetValidator(new RequestAddressValidator());
                }
            });
    }
}
1

There are 1 answers

0
pfx On

You need to use CustomAsync and await that apiClient.GetByIdAsync call.

See asynchronous validation

public class RequestModelValidator: AbstractValidator<RequestModel>
{
    public RequestModelValidator(IApiClient apiClient)
    {
        RuleFor(x => x)
            .CustomAsync(async (requestModel, context, cancellationToken) =>
            {
                var item = await apiClient.GetByIdAsync(requestModel.Id);

                if (item != null)
                {
                    RuleFor(x => x.Address).SetValidator(new RequestAddressValidator());
                }
            });
    }
}

Also pay attention to the notices on that page, especially the one about the automatic validation with ASP.NET.

Since you have this question tagged with ASP.NET and you are using asynchronous validation, you need to use manual validation; making that validator.ValidateAsync call yourself.

If your validator contains asynchronous validators or asynchronous conditions, it’s important that you always call ValidateAsync on your validator and never Validate. If you call Validate, then an exception will be thrown.

You should not use asynchronous rules when using automatic validation with ASP.NET as ASP.NET’s validation pipeline is not asynchronous.