Overview of the FluentValidation library. Part 5. Conditions

You can set conditions through extension methods When And Unless to determine whether all previous validators (before the extension method is called) or a specific validator in a rule should be executed RuleFor. Applying an extension method When:

// Модель клиента
public class Customer
{
  // Имя
  public string? Forename { get; set; }
  // Фамилия
  public string? Surname { get; set; }
}

// Валидатор для модели клиента
public class CustomerValidator : AbstractValidator<Customer>
{
  public CustomerValidator()
  {
    // Оба свойства (Surname, Forename) должны быть заполнены, если заполнено одно из них
    RuleFor(customer => customer.Surname)
      .NotNull()
      .When(customer => customer.Forename is not null);

    RuleFor(customer => customer.Forename)
      .NotNull()
      .When(customer => customer.Surname is not null);
  }
}

Extension method Unless the opposite of an extension method Whenthe following code example will return the same result as the example above, since the condition is inverted:

// Модель клиента
public class Customer { ... }

// Валидатор для модели клиента
public class CustomerValidator : AbstractValidator<Customer>
{
  public CustomerValidator()
  {
    // Оба свойства (Surname, Forename) должны быть заполнены, если заполнено одно из них
    RuleFor(customer => customer.Surname)
      .NotNull()
      .Unless(customer => customer.Forename is null);

    RuleFor(customer => customer.Forename)
      .NotNull()
      .Unless(customer => customer.Surname is null);
  }
}

Default FluentValidaton applies the condition When, Unless for all previous validators in the rule RuleFor. If there is a need to specify a condition to the validator that immediately precedes the extension method When, Unless you need to explicitly indicate this through the enumeration value ApplyConditionTo.CurrentValidatorwhich is passed as the second argument to the extension method When, Unlessan example of use with an extension method When:

// Модель клиента
public class Customer
{
  // Название организации
  public string? OrgName { get; set; }
  // Имя
  public string? Forename { get; set; }
  // Фамилия
  public string? Surname { get; set; }
}

// Валидатор для модели клиента
public class CustomerValidator : AbstractValidator<Customer>
{
  public CustomerValidator()
  {
    // Должны быть заполнены поля Surname, Forename (одновременно) либо OrgName
    RuleFor(customer => customer.Surname)
      .NotNull()
        .When(customer => customer.OrgName is null && customer.Forename is not null, ApplyConditionTo.CurrentValidator)
      .Null()
        .When(customer => customer.OrgName is not null && customer.Forename is null, ApplyConditionTo.CurrentValidator);

    RuleFor(customer => customer.Forename)
      .NotNull()
        .When(customer => customer.OrgName is null && customer.Surname is not null, ApplyConditionTo.CurrentValidator)
      .Null()
        .When(customer => customer.OrgName is not null && customer.Surname is null, ApplyConditionTo.CurrentValidator);

      RuleFor(customer => customer.OrgName)
        .NotNull()
          .When(customer => customer.Surname is null && customer.Forename is null, ApplyConditionTo.CurrentValidator)
        .Null()
          .When(customer => customer.Surname is not null && customer.Forename is not null, ApplyConditionTo.CurrentValidator);
  }
}

Please note that I have highlighted the extension method call with an additional tab Whenbecause the argument is specified ApplyConditionTo.CurrentValidatorto emphasize the ownership of the extension method When only to the previous validator.

If the second parameter ApplyConditionTo not explicitly specified, it will take the value ApplyConditionTo.AllValidators default, which means the condition applies to all previous validators in the rule RuleFor.

If there is a need to specify a general condition for a group of rules RuleForyou can use the method When “top level” (from the base class AbstractValidator<T>) instead of an extension method Whenwhich is attached at the end of the rule or validator:

// Модель клиента
public class Customer { ... }

// Валидатор для модели клиента
public class CustomerValidator : AbstractValidator<Customer>
{
  public CustomerValidator()
  {
    // Должны быть заполнены поля Surname, Forename (одновременно) либо OrgName.
    // Если OrgName не заполнен, то
    When(customer => customer.OrgName is null, () =>
    {
      // Surname должен быть заполнен
      RuleFor(customer => customer.Surname)
        .NotNull();
      // Forename должен быть заполнен
      RuleFor(customer => customer.Forename)
        .NotNull();
      // OrgName должен быть не заполнен
      RuleFor(customer => customer.OrgName)
        .Null();
    })
    // Otherwise выполняется в случае, если условие When не удовлетворено (false)
    .Otherwise(() =>
    {
      // Surname должен быть не заполнен
      RuleFor(customer => customer.Surname)
        .Null();
      // Forename должен быть не заполнен
      RuleFor(customer => customer.Forename)
        .Null();
      // OrgName должен быть заполнен
      RuleFor(customer => customer.OrgName)
        .NotNull();
    });
  }
}

Calling a Method Otherwise optional, it can be called directly after calling When “top level”. Executed if the condition When not satisfied (false).

← Previous part

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *