2013-02-02 7 views
4

Je souhaite créer un attribut de validation personnalisé qui appelle d'autres attributs de validation.Attribut de validation personnalisé appelant un autre attribut de validation

Par exemple, je souhaite créer un attribut appelé PasswordValidationAttribute. Je veux qu'il décore la propriété sur laquelle il est défini avec RequiredAttribute, RegularExpressionAttribute et StringLengthAttribute avec divers paramètres définis (tels que l'expression régulière pour un mot de passe et une longueur de chaîne maximale et minimale).

Je me demande par où commencer, déterminer combien de travail est impliqué et déterminer si c'est possible. Une fois que cet attribut est appliqué à une propriété, je voudrais traiter correctement le ValidationMessageForHtmlHelper et faire un appel côté serveur. J'espère que je n'ai pas besoin de les redéfinir (sinon ce sera trop de travail).

Répondre

4

Pour .net 4 il pourrait ressembler à:

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] 
public class MyValidationAttribute : ValidationAttribute 
{ 
    private readonly bool isRequired; 

    public string Regex { get; set; } 

    public int StringLength { get; set; } 

    public MyValidationAttribute(bool isRequired) 
    { 
     this.isRequired = isRequired; 
    } 

    protected override ValidationResult IsValid(object value, ValidationContext validationContext) 
    { 
     var composedAttributes = ConstructAttributes().ToArray(); 
     if (composedAttributes.Length == 0) return ValidationResult.Success; 

     var errorMsgBuilder = new StringBuilder(); 
     foreach (var attribute in composedAttributes) 
     { 
      var valRes = attribute.GetValidationResult(value, validationContext); 
      if (valRes != null && !string.IsNullOrWhiteSpace(valRes.ErrorMessage)) 
       errorMsgBuilder.AppendLine(valRes.ErrorMessage); 
     } 
     var msg = errorMsgBuilder.ToString(); 
     if (string.IsNullOrWhiteSpace(msg)) 
      return ValidationResult.Success; 
     return new ValidationResult(msg); 
    } 

    private IEnumerable<ValidationAttribute> ConstructAttributes() 
    { 
     if (isRequired) 
      yield return new RequiredAttribute(); 
     if (Regex != null) 
      yield return new RegularExpressionAttribute(Regex); 
     if (StringLength > 0) 
      yield return new StringLengthAttribute(StringLength); 
    } 
} 

Utilisation:

[MyValidationAttribute(true, Regex = "[a-z]*", StringLength = 3)] 
public string Name { get; set; } 

Dans .net 3.5 il y a une limite, que vous ne pouvez pas Construire dynamiquement la valeur du message à partir des attributs sous-jacents (au moins, je n'ai pas pu y accéder). Vous ne pouvez définir qu'un seul message par attribut entier.

Tout a changé est à l'intérieur de la méthode IsValid.

public override bool IsValid(object value) 
{ 
    var composedAttributes = ConstructAttributes().ToArray(); 
    if (composedAttributes.Length == 0) return true; 
    return composedAttributes.All(a => a.IsValid(value)); 
} 

Note à ErrorMessage:

Valeur de retour de la méthode IsValid de ValidationAttribute dans .NET 3.5 n'est pas ValidationResult mais bool. Lorsque j'ai essayé de définir le ErrorMessage, j'ai reçu l'erreur value can be set only once.

+0

Cela semble très bien, je vais passer un test demain matin. – orangesherbert

Questions connexes