FluentValidation: Check if one of two fields are empty

别等时光非礼了梦想. 提交于 2019-11-30 01:18:17
Zabavsky

You can use When/Unless condition:

RuleFor(m => m.FirstName).NotEmpty().When(m => string.IsNullOrEmpty(m.LastName));
RuleFor(m => m.LastName).NotEmpty().When(m => string.IsNullOrEmpty(m.FirstName));

or

RuleFor(m => m.FirstName).NotEmpty().Unless(m => !string.IsNullOrEmpty(m.LastName));
RuleFor(m => m.LastName).NotEmpty().Unless(m => !string.IsNullOrEmpty(m.FirstName));

As for your second question, FluentValidation works with client-side validation, but not all rules are supported. Here you can find validators, that are supported on the client-side:

  1. NotNull/NotEmpty
  2. Matches (regex)
  3. InclusiveBetween (range)
  4. CreditCard
  5. Email
  6. EqualTo (cross-property equality comparison)
  7. Length

For rules that are not in the list you have to write your own FluentValidationPropertyValidator and implement GetClientValidationRules. You can find a few samples of this on the StackOverflow by doing simple search.

Try this

RuleFor(person => person).Must(person => !string.IsNullOrEmpty(person.FirstName) || !string.IsNullOrEmpty(person.LastName))

I did like this to check charges entered are same to previous one or not. If charges are same as previous one than it'll give an error. This worked for me.

public class CasualMealChargeValidator : AbstractValidator<CasualMealCharge>
{
    public CasualMealChargeValidator(CasualMealCharge CMC)
    {
        //RuleFor(x => x.BankName).NotEmpty().When(pm => pm.PaymentMode == "Cheque").WithMessage("Enter Bank.");
        RuleFor(x => x).Must(x => x.DN != CMC.DN || x.BF != CMC.BF || x.LN != CMC.LN).WithMessage("Not Saved - Meal charges are same as current charges.").WithName("CMFor");
    }
}

I don't know that library, but if you just want to check those two properties for null, then you can use this:

RuleFor(person => person.FirstName ?? person.LastName).NotNull();

EDIT This doesn't work, because it throws an InvalidOperationException. Use Zabavsky's solution instead.

A nice rule-set to check if one of two fields are empty, as well as coming up with meaningful error codes is the following:

public CustomerSourceValidator()
    {
        CascadeMode = CascadeMode.StopOnFirstFailure;

        RuleFor(x => x)
            .NotNull().WithErrorCode("source_id_or_email_required")
            .When(source => source.Email == null && source.Id == null);

        RuleFor(x => x.Id)
            .NotNull().WithErrorCode("source_id_required")
            .Matches(CommonValidationRegex.CustomerIdRegexString).WithErrorCode("source_id_invalid")
            .When(source => source.Id != null);

        RuleFor(x => x.Email)
            .NotNull().WithErrorCode("source_email_required")
            .Matches(CommonValidationRegex.EmailRegexString).WithErrorCode("source_email_invalid")
            .When(source => source.Email != null);
    }

Finally, this worked for me. I wanted to validate three properties where at least one is required. It returns an error message only once.

RuleFor(p => p).Cascade(CascadeMode.StopOnFirstFailure)
            .Must(p => !string.IsNullOrWhiteSpace(p.FirstName))
            .When(p => p.Id == 0 && string.IsNullOrWhiteSpace(p.LastName)).WithMessage("At least one is required (Id, FirstName, LastName).")
            .Must(p => !string.IsNullOrWhiteSpace(p.LastName))
            .When(p => p.Id == 0 && string.IsNullOrWhiteSpace(p.FirstName)).WithMessage("At least one is required (Id, FirstName, LastName).")
            .Must(p => p.Id != 0)
            .When(p => string.IsNullOrWhiteSpace(p.FirstName) && string.IsNullOrWhiteSpace(p.LastName)).WithMessage("At least one is required (Id, FirstName, LastName).");
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!