FluentValidation Call RuleSet and Common Rules

余生长醉 提交于 2019-12-03 17:33:28

问题


I have the following class

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());
            });


        }

and what i am trying to do is call the validation with the rulset but i also want to return the "common" rules when i call the validation with the RuleSet.

the Code I have for calling the validation is as follows

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>();
        }
    }

I can call the Method CallValidation with the member ruleSet but it is not calling the "common" rules also.

I know I can create a "Common" RuleSet for running these rules but in that case i would have to call the validation with the Common RuleSet always.

Is there any way I can call the RuleSet and also call the common rules.


回答1:


Instead you could do this:

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

The using directive is required to bring the Validate() extension method from DefaultValidatorExtensions into scope, which has the ruleSet property. Otherwise you will only have the Validate() method available from inheriting AbstractValidator<T>, which doesn't have a ruleSet argument.




回答2:


In your Validator class create a method, that includes all "common" rules that need to be applied at all times. Now you can call this method

  • from your "create" RuleSet
  • from outside of the RuleSet

Example

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();
    }
}

You define the RuleSet for an action in your controller

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

This will insure that requests to action Create will be validated with the RuleSet Create. All other action will use the call to ExecuteCommonRules in controller.




回答3:


I have found one way to do it by adding a second validator.Validate to the CallValidation(string ruleSet) method it is as follows

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;
        }



回答4:


I just tried below and it works

   [CustomizeValidator(RuleSet = "default, Create")


来源:https://stackoverflow.com/questions/13877227/fluentvalidation-call-ruleset-and-common-rules

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!