2010-08-01 5 views
9

Je souhaite étendre les validateurs asp.net de sorte que je puisse faire dépendre un validateur d'un autre. La situation que j'ai est que nous devons valider une date dans une zone de texte. Normalement j'utiliserais juste une combinaison d'un RequiredFieldValidator (pour s'assurer que la date est fournie), CompareValidator (pour s'assurer que la date est une date) et finalement un RangeValidator (pour s'assurer que la date est dans la limite requise). Le problème avec ceci est que les validateurs ne dépendent pas les uns des autres, de sorte que l'utilisateur verrait probablement tous les trois messages à la fois pour chaque validateur alors que tout ce que nous voulons qu'ils voient est le message le plus pertinent, c'est-à-dire que s'ils ont entré "abc" dans la zone de texte de date, il ne serait pas approprié de leur montrer le message indiquant que la date n'était pas dans la plage valide (même si techniquement je suppose que c'est vrai).Extension des validateurs ASP.NET

Actuellement, pour fournir ce type de fonctionnalité, nous utilisons un CustomValidator et mettons simplement les trois validations dans le gestionnaire d'événements de validation du serveur et modifions le message d'erreur par programmation en fonction de la validation échouée.

Je voudrais normaliser cela un peu plus car il se passe un peu dans cette application, je me dis que si je peux rendre les validateurs dépendants les uns des autres cela résoudra le problème et nous permettra également de faire usage du client validation latérale plutôt que d'avoir à faire une publication spécialement pour gérer la validation personnalisée. L'idée est que si un validateur dépend d'un autre si ce "maître" est valide alors le dépendant effectuera sa validation normale (EvaluateIsValid()) sinon si le validateur maître n'est pas valide alors les autres valideurs dépendants seront valide.

J'ai trouvé la solution suivante en héritant des divers contrôles de validateur qui ont déjà été fournis dans le framework.

public class RequiredFieldDependentValidator : RequiredFieldValidator 
{ 
    [Description("The validation control to depend on for determining if validation should occur")] 
    public string ValidationControlToDependOn 
    { 
     get 
     { 
      object obj = ViewState["ValidationControlToDependOn"]; 
      if (obj != null) return (string) obj; 
      return null; 
     } 
     set 
     { 
      Control control = FindControl(value); 
      if (control is IValidator) 
       ViewState["ValidationControlToDependOn"] = value; 
      else 
       throw new HttpException("ValidationControlToDependOn is not a validation control"); 
     } 
    } 

    protected override bool EvaluateIsValid() 
    { 
     IValidator validationControlToDependOn = FindControl(ValidationControlToDependOn) as IValidator; 

     if(validationControlToDependOn != null) 
     { 
      return !validationControlToDependOn.IsValid || base.EvaluateIsValid(); 
     } 

     return base.EvaluateIsValid(); 
    } 

Actuellement, j'ai juste codé pour la RequiredFieldValidator, idéalement, je voudrais offrir cette fonctionnalité pour tous les validateurs, mais je ne vois pas une façon de le faire sans copier le code ci-dessus dans une classe similaire pour chaque Type de validateur individuel Je souhaite fournir cette fonctionnalité, donc s'il y a des problèmes, je vais devoir revenir en arrière et modifier ce code sur chaque type de validateur individuellement. Y at-il un moyen de "centraliser" ce code et de le rendre facilement utilisable dans les validateurs sans avoir à écrire entièrement les validateurs pour pouvoir modifier la classe dont ils héritent de plus bas dans la ligne.

Cheers,

Répondre

0

Vous pourriez vouloir regarder dans un WebControlAdapter.

Fondamentalement, vous permet de remplacer certaines méthodes de WebControls (conditionnellement pour certains navigateurs en cas de besoin, mais ici peut être pour tous).

Dans votre cas, vous souhaiterez remplacer la méthode EvaluateIsValid et vérifier si le contrôle a une dépendance sur un validateur 'parent'. Par exemple, un adaptateur TextBox que nous avons récemment créé pour rendre un attribut 'maxlength' au contrôle.

Public Class TextBoxAdapter 
     Inherits WebControlAdapter 

     Private ReadOnly Property TextBoxControl() As TextBox 
      Get 
       Return DirectCast(MyBase.Control, TextBox) 
      End Get 
     End Property 

     Protected Overrides Sub RenderBeginTag(ByVal writer As System.Web.UI.HtmlTextWriter) 
      If TextBoxControl.TextMode = TextBoxMode.MultiLine AndAlso TextBoxControl.MaxLength > 0 Then 
       writer.AddAttribute("maxlength", TextBoxControl.MaxLength.ToString) 
      End If 

      MyBase.RenderBeginTag(writer) 
     End Sub 
    End Class 

Pour l'utiliser, il suffit de créer un fichier .browser dans votre répertoire App_Browsers et la configuration de l'adaptateur là:

<browsers> 
    <browser refID="Default"> 
     <controlAdapters> 
      <adapter controlType="System.Web.UI.WebControls.TextBox" 
       adapterType="TextBoxAdapter" /> 
     </controlAdapters> 
    </browser> 
</browsers> 

La seule complication qui reste dans votre cas est de savoir comment stocker le validateur dépendante pour que EvaluateIsValid ait accès à ce répertoire. Vous pouvez considérer un contrôle non rendu comme Onof suggéré ou autre Viewstate/Cookie/autre mécanisme de stockage.

1

Vous pourriez remplacer la méthode Valider en vous la base de la page. Pour ajouter les informations de dépendance de validation dans la page que vous pouvez mettre en œuvre un contrôle non rendu:

<my:ValidationDependency TargetControl="RegExp1" Dependency="Required1" /> 
0

vous pouvez avoir ValidationControlToDependOn propriété à partir de la liste de type et ajoutez les validateurs dans la liste. Nous pouvons donc supposer que le validateur ajouté plus tard dépend du validateur ajouté avant.

afin que votre protected override bool EvaluateIsValid()

changera quelque peu

foreach(IValidator validator in ValidationControlToDependOn) 
{ 
return !validator.IsValid; 

} 
+0

cela ne rendrait-il pas chaque validateur de la page dépendant du précédent? Et je pense que je devrais toujours sous-classer chaque validateur –

0

Je suis à la recherche dans les extensions de contrôle qui semble comme il pourrait être prometteur, mais je ne peux pas trouver beaucoup d'exemples de faire quoi que ce soit mais des choses AJAX avec elle.

+0

J'ai essayé, mais vous ne pouvez pas remplacer une méthode du contrôle étendu. IMO la seule façon d'éviter le sous-classement est de surcharger Page.Validate(). – onof

Questions connexes