Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing validation based on type using FluentValidation

I have a simply model like so:

[Validator(typeof(EntryModelValidator))]
public class EntryModel : BaseNopEntityModel
{
  public virtual string ProductActionValue { get; set; }
}

I'm using FluentValidation to validate the saving of the model. The issue is that when the user saves the values on the form, in certain situations ProductActionValue needs to be saved as an int (it will of course always be saved as a string, but it needs to be parseable as an int).

I have the following Validation rule which ensures the value is not empty:

 RuleFor(x => x.ProductCriteriaValue)
            .NotEmpty()
            .WithMessage(localizationService.GetResource("Common.FieldRequired"));

I tried adding the following rule to validate as an int:

 RuleFor(x => Int32.Parse(x.ProductCriteriaValue))
            .GreaterThanOrEqualTo(1)
            .When(x => (ProductCriteriaTypes)x.ProductCriteriaTypeId == ProductCriteriaTypes.ProductCreatedGreaterThanXDays || (ProductCriteriaTypes)x.ProductCriteriaTypeId == ProductCriteriaTypes.ProductCreatedLessThanXDays)
            .WithMessage(localizationService.GetResource("Common.FieldRequired"));

But this just throws FluentValidation runtime errors. Is there anyway to acheive this?

Thanks in advance Al

UPDATED TO REFLECT AHMAD'S SOLUTION:

   {
        RuleFor(x => x.ProductCriteriaValue)
            .Must(BeANumber)
            .WithMessage(localizationService.GetResource("Common.FieldRequired"));
   }

    private bool BeANumber(string value)
    {
        int result;
        if (Int32.TryParse(value, out result))
        {
            return result >= 1;
        }
        return false;
    }
like image 558
higgsy Avatar asked Mar 28 '26 08:03

higgsy


1 Answers

You can use the Predicate Validator (aka Must):

RuleFor(x => x.ProductCriteriaValue)
    .Must(x => Int32.Parse(x.ProductCriteriaValue) >= 1)
    .When(x => (ProductCriteriaTypes)x.ProductCriteriaTypeId == ProductCriteriaTypes.ProductCreatedGreaterThanXDays || (ProductCriteriaTypes)x.ProductCriteriaTypeId == ProductCriteriaTypes.ProductCreatedLessThanXDays)
    .WithMessage(localizationService.GetResource("Common.FieldRequired"));

Of course, this assumes that the parse won't fail. Will ProductCriteriaValue always be a number and parse fine? If so, this is ok. Otherwise, you might want to check this better by using Int32.TryParse and changing the predicate as follows:

    .Must(x =>
    {
        int result;
        if (Int32.TryParse(x.ProductCriteriaValue, out result))
        {
            return result >= 1;
        }
        return false;
    })
like image 105
Ahmad Mageed Avatar answered Mar 30 '26 02:03

Ahmad Mageed



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!