2012-12-14 10 views
6

ho la seguente classechiamata set di regole e norme comuni 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()); 
      }); 


     } 

e quello che sto cercando di fare è chiamare la convalida con il rulset ma voglio anche tornare alle regole "comuni" quando chiamo il validazione con RuleSet.

del codice che ho per chiamare la validazione è il seguente

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

posso chiamare il metodo CallValidation con il membro ruleSet ma non chiama anche le regole "comuni".

So che posso creare un set di regole "comune" per l'esecuzione di queste regole, ma in tal caso dovrei chiamare la convalida con il set di regole comune sempre.

C'è un modo per chiamare il set di regole e anche chiamare le regole comuni.

risposta

3

ho trovato un modo per farlo è con l'aggiunta di un secondo validator.Validate al metodo CallValidation(string ruleSet) è come segue

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

Invece si potrebbe fare questo:

FluentValidation.Results.ValidationResult resultCommon = validator.Validate(parameter, Ruleset : "default, Insert"); 
+0

Questa opzione non sembra esistere nel codice sorgente git almeno dal 2009, che è quello che mi ha portato qui poiché la documentazione non è corretta. – john

+0

Ottimo consiglio! In FluentValidation 6.2.1 il caso argomento RuleSet è diverso: "ruleSet:" invece di "Ruleset:". Esempio: validator.Validate (obj, ruleSet: "default, Insert"); –

6

Nella classe Validator creare un metodo, che includa tutte le regole "comuni" che devono essere applicate in ogni momento. Ora è possibile chiamare questo metodo

  • dal RuleSet "creare"
  • al di fuori dello schema di gioco

Esempio

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

Si definisce il set di regole per un'azione nel controller

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

Ciò assicurerà che le richieste di azione Create verranno convalidate con RuleSet Create. Tutte le altre azioni utilizzeranno la chiamata a ExecuteCommonRules nel controller.

Problemi correlati