Même si je fais du web de façon intensive depuis plusieurs années, je n’ai jamais creusé les contrôles de databinding tout prêt de ASP.NET (ni 1.1, ni 2.0). Je peux même dire que je suis novice avec les GridView, FormView et autres DetailView.
Je suis confronté à ces contrôles depuis quelques mois maintenant dans le cadre de projets qui en tirent parti. Je dois dire que je commence à être séduit par ce mode de fonctionnement même si je reste accro aux « custom templated controls« .
Sauf que la semaine dernière j’ai découvert que la FormView a un fonctionnement que je n’aime pas du tout et qu’il est important de connaître pour bien maîtriser ce que l’on fait. Admettons que dans la FormView, vous placiez un LinkButton et un CustomValidator pour vérifier une condition. Le LinkButton a la propriété CausesValidation à true. Vous branchez l’événement click sur votre méthode et là, tout bascule, en déboguant, vous vous apercevez que la validation (votre méthode OnServerValidate) est appelée 2 fois.
La validation est garantie par la propriété CausesValidation du bouton comme on peut le voir ci-dessous dans la méthode RaisePostBackEvent du LinkButton via Reflector.
protected virtual void RaisePostBackEvent(string eventArgument)
{
base.ValidateEvent(this.UniqueID, eventArgument);
if (this.CausesValidation)
{
this.Page.Validate(this.ValidationGroup);
}
this.OnClick(EventArgs.Empty);
this.OnCommand(new CommandEventArgs(this.CommandName, this.CommandArgument));
}
Mais qui appelle donc la validation une seconde fois ? On peut voir aussi dans cette méthode qu’un LinkButton lève l’événement Click mais aussi l’événement Command, même si on n’a pas précisé de CommandName. Le problème, c’est qu’un événement Command utilise le mécanisme de Bubbling (méthode OnBubbleEvent) et remonte dans la hierarchie de contrôle jusqu’à ce que quelqu’un l’intercepte. Et devinez qui le prend en charge ? La FormView !!
Sans vérifier si la FormView est à même de prendre en charge la commande (représentée par le paramètre CommandName), elle lance la validation comme on peut le voir dans le code de la méthode OnBubbleEvent().
if (causesValidation && (this.Page != null))
{
this.Page.Validate(validationGroup);
}
Ce qui fait que si vous préférez utiliser l’événement Click, vous aurez 2 validations de la page (ou du ValidationGroup).
La solution :
- utiliser l’événement Command de la FormView pour faire vos traitements dans les boutons se trouvant en son sein.
- mettre la propriété CausesValidation à false et appeler manuellement Page.Validate() dans la méthode qui gère l’événement Click
Moralité : FormView stinks !