Набор правил вызова FluentValidation и общие правила

У меня есть следующий класс

public class ValidProjectHeader : AbstractValidator<Projects.ProjectHeader>
    {
        public ValidProjectHeader()
        {

            RuleFor(x => x.LobId).Must(ValidateLOBIDExists);
            RuleFor(x => x.CreatedByUserId).NotEmpty();
            RuleFor(x => x.ProjectManagerId).NotEmpty();
            RuleFor(x => x.ProjectName).NotEmpty();
            RuleFor(x => x.SalesRepId).NotEmpty();
            RuleFor(x => x.DeliveryDate).NotEmpty();
            RuleFor(x => x.ProjectStatusId).NotEmpty();
            RuleFor(x => x.DeptartmentId).NotEmpty();
            RuleFor(x => x.CustomerId).NotEmpty();

            RuleSet("Insert", () =>
            {
                RuleFor(x => x.ProjectLines).Must(ValidateProjectLines).SetCollectionValidator(new ValidProjectLine());
            });
            RuleSet("Update", () =>
            {
                RuleFor(x => x.ProjectLines).SetCollectionValidator(new ValidProjectLine());
            });


        }

и то, что я пытаюсь сделать, это вызвать проверку с помощью набора правил, но я также хочу вернуть «общие» правила, когда я вызываю проверку с помощью набора правил.

код, который у меня есть для вызова проверки, выглядит следующим образом

public abstract class BaseValidator
    {
        private List<ValidationFailure> _errors;
        public bool IsValid { get; protected set; }
        public List<ValidationFailure> Errors
        {
            get { return _errors; }
            protected set { _errors = value; }
        }
        public virtual bool CallValidation()
        {
            Errors = new List<ValidationFailure>();
            ValidatorAttribute val = this.GetType().GetCustomAttributes(typeof(ValidatorAttribute), true)[0] as ValidatorAttribute;
            IValidator validator = Activator.CreateInstance(val.ValidatorType) as IValidator;
            FluentValidation.Results.ValidationResult result = validator.Validate(this);
            IsValid = result.IsValid;
            Errors = result.Errors.ToList();
            return result.IsValid;
        }

        public virtual bool CallValidation(string ruleSet)
        {
            Errors = new List<ValidationFailure>();
            ValidatorAttribute val = this.GetType().GetCustomAttributes(typeof(ValidatorAttribute), true)[0] as ValidatorAttribute;
            IValidator validator = Activator.CreateInstance(val.ValidatorType) as IValidator;
            FluentValidation.Results.ValidationResult result = validator.Validate(new FluentValidation.ValidationContext(this, new PropertyChain(), new RulesetValidatorSelector(ruleSet)));
            IsValid = result.IsValid;
            Errors = result.Errors.ToList();
            return result.IsValid;
        }

        public BaseValidator()
        {
            Errors = new List<ValidationFailure>();
        }
    }

Я могу вызвать метод CallValidation с членом ruleSet, но он также не вызывает "общие" правила.

Я знаю, что могу создать «Общий» набор правил для запуска этих правил, но в этом случае мне пришлось бы всегда вызывать проверку с помощью общего набора правил.

Можно ли как-нибудь вызвать RuleSet, а также вызвать общие правила.


person Qpirate    schedule 14.12.2012    source источник


Ответы (5)


Вместо этого вы можете сделать это:

using FluentValidation;
...
FluentValidation.Results.ValidationResult resultCommon =
    validator.Validate(parameter, ruleSet: "default, Insert");

Директива using необходима для переноса метода расширения Validate() из DefaultValidatorExtensions в область видимости, которая имеет свойство ruleSet. В противном случае у вас будет только метод Validate(), унаследованный от AbstractValidator<T>, который не имеет аргумента ruleSet.

person Neelima Reddy    schedule 31.03.2014
comment
Эта опция, похоже, не существовала в исходном коде git по крайней мере с 2009 года, что и привело меня сюда, поскольку документация неверна. - person Llama; 22.07.2016
comment
Отличный совет! В FluentValidation 6.2.1 регистр аргументов RuleSet отличается: ruleSet: вместо Ruleset:. Пример: validator.Validate(obj, ruleSet: default, Insert); - person Mark Meyerovich; 20.09.2016
comment
Информация об использовании настолько важна, большое спасибо за это, я не мог понять, как заставить это работать раньше. - person Machado; 24.03.2021

В вашем классе Validator создайте метод, включающий все «общие» правила, которые необходимо применять постоянно. Теперь вы можете вызвать этот метод

  • из вашего "создать" RuleSet
  • из-за пределов RuleSet

Пример

public class MyEntityValidator : AbstractValidator<MyEntity>
{
    public MyEntityValidator()
    {
        RuleSet("Create", () =>
            {
                RuleFor(x => x.Email).EmailAddress();
                ExecuteCommonRules();
            });

        ExecuteCommonRules();
    }

    /// <summary>
    /// Rules that should be applied at all times
    /// </summary>
    private void ExecuteCommonRules()
    {
        RuleFor(x => x.Name).NotEmpty();
        RuleFor(x => x.City).NotEmpty();
    }
}

Вы определяете RuleSet для действия в своем контроллере

[HttpPost]
public ActionResult Create([CustomizeValidator(RuleSet = "Create")]  MyEntity model)

Это гарантирует, что запросы на действие Create будут проверены с помощью RuleSet Create. Все остальные действия будут использовать вызов ExecuteCommonRules в контроллере.

person Nasser    schedule 12.05.2014

Я нашел один способ сделать это, добавив второй validator.Validate к методу CallValidation(string ruleSet) следующим образом

public virtual bool CallValidation(string ruleSet)
        {
            Errors = new List<ValidationFailure>();
            ValidatorAttribute val = this.GetType().GetCustomAttributes(typeof(ValidatorAttribute), true)[0] as ValidatorAttribute;
            IValidator validator = Activator.CreateInstance(val.ValidatorType) as IValidator;
            FluentValidation.Results.ValidationResult result = validator.Validate(new FluentValidation.ValidationContext(this, new PropertyChain(), new RulesetValidatorSelector(ruleSet)));
            FluentValidation.Results.ValidationResult resultCommon = validator.Validate(this);
            IsValid = (result.IsValid && resultCommon.IsValid);
            Errors = result.Errors.Union(resultCommon.Errors).ToList();
            return IsValid;
        }
person Qpirate    schedule 14.12.2012

Я только что попробовал ниже, и это работает

   [CustomizeValidator(RuleSet = "default, Create")
person harishr    schedule 13.11.2019
comment
Этот вопрос (хотя и очень старый) заключался в том, чтобы не работать с проверкой атрибута, а вызывать метод AbstractValidator‹T›.Validate. Пока это работает, я искал способ сделать это в коде. - person Qpirate; 13.11.2019

person    schedule
comment
ОП мог бы использовать некоторые объяснения для вашего ответа. - person Filip Veličković; 29.08.2020