Rehia, le blog

Old and recent learnings and thoughts

Générer un PostBack en ASP.NET

24 January 2011

C’est la première fois en ASP.NET que je me retrouve confronté au problème suivant : Quel code javascript générer pour effectuer un postback vers le serveur sur une action quelconque ?

Tout est parti d’une action de maintenance qui a consisté à remplacer le vieillo prototype et sa « lightbox » par le très populaire jQuery et son « dialog ». Ces deux frameworks javascript disposent en effet chacun d’un composant de boite de dialogue. Pour limiter l’adhérence à l’une des technologies, j’ai donc « masqué » le composant dialog dans un

UserControl.

Déclarer un événement

Le clic sur l’un des deux boutons de mon UserControl génère un événement auquel la page dans laquelle il se situe peut s’abonner. Pour rappel, il faut déclarer un événement dans le UserControl de cette façon :

public event EventHandler ButtonLeftClick;

Notez qu’il n’est pas indispensable de déclarer votre propre delegate. Vous pouvez tout à fait utiliser EventHandler, si vous n’avez pas de données particulières à transmettre au handler de l’événement. Jusque là, rien de très exotique !

Maintenant, comment propager mon événement ? Comment le rattacher au clic du bouton de ma boîte de dialogue ? Tous les exemples trouvés sur le net montrent à quel point il est facile de le faire : il suffit de créer un handler dans le UserControl qui est associé à l’événement OnClick du bouton ASP.NET… Oui, mais voilà : un dialog jQuery est composé de boutons… jQuery !

Générer le PostBack

Nous voilà donc arrivé à notre question initiale : Comment générer un postback depuis la page web, sur le clic de mon bouton ?

L’une des solutions se trouve dans la classe ClientScriptManager, qui dispose, entre autres, de la méthode GetPostbackEventReference. Cette méthode, qui possède 4 surcharges, permet en effet de générer le code javascript qui va effectuer le postback. Il existe un certain nombre d’options permettant de paramétrer le postback. Il est notamment possible de définir :

  • l’url du postback avec ActionUrl, si cette url est différente de la page actuelle du navigateur;
  • si le postback est précédé de la validation du formulaire, avec PerformValidation, et le groupe de validation auquel le contrôle appartient, avec ValidationGroup;
  • l’activation de l’AutoPostBack, notamment pour les listes déroulantes, cases à cocher, radio boutons, etc.

Enfin, trois derniers paramètres, et non des moindres :

  • Argument, pour spécifier un argument quelconque,
  • TargetControl, qui est le UserControl lui-même, dans notre exemple.
  • et ClientSubmit, qu’il faut passer à true, pour permettre la génération du code javascript de postback.

Voici donc un exemple de code à insérer :

Page.ClientScript.GetPostBackEventReference(
    new PostBackOptions(this, this.ClientID, Request.RawUrl,
        false, true, false, true, false, string.Empty));

Et voici le code généré par ASP.NET dans le rendu HTML :

<input type="button" id="btnTest" value="Cliquer ici pour tester"
    onclick='javascript:WebForm_DoPostBackWithOptions(
        new WebForm_PostBackOptions("ctl00$MainContent$uc2",
            "MainContent_uc2", false, "", "/Default.aspx", false, true))' />

Il en existe évidemment d’autres, mais je vous renvoie pour cela à la documentation officielle dans le MSDN. Attention toutefois lors de l’utilisation de la méthode GetPostbackEventReference !

Première chose : si vous intégrez le javascript généré dans un code javascript plus large, il vous faut ajouter un « ; » en fin de script. La méthode ne génère en effet pas ce point-virgule, puisque ce code est utilisé la majorité du temps directement dans un événement onclick, onblur, onchange, etc.

Deuxième chose : dans notre exemple, il faut penser que le UserControl peut être ajouté plusieurs fois dans une page. Et si vous faites ce test, vous verrez qu’il ne suffit pas d’attacher un handler à l’événement du côté de la page, et détecter si un handler est attaché côté UserControl. En effet, vous aurez la drôle de surprise de voir que seul le handler du dernier user control déclaré dans la page est appelé ! Pour contourner cela, il est nécessaire de définir une valeur à l’option Argument. Et autant que possible il faut spécifier une valeur unique pour éviter là encore des surprises. La meilleure solution consiste à y renseigner le ClientID ou le UniqueID du UserControl.

Déclencher l’appel au handler

Dernière question qui peut se poser : à quel moment « détecter » qu’un postback concernant le UserControl a été réalisé, et comment déterminer s’il correspond bien à l’instance du UserControl (et pas à une autre) ?

Pour cela, il existe en ASP.NET deux interfaces : IPostBackEventHandler et IPostBackDataHandler. Le UserControl doit impélmenter l’une des deux interfaces. La première sert simplement à détecter qu’un événement a été levé. La deuxième sert en plus à vérifier si le UserControl a changé ou non d’état. Dans notre exemple, c’est la première interface, très simple d’usage, qui va nous intéresser.

L’interface IPostBackEventHandler dispose de la seule méthode RaisePostBackEvent.

void RaisePostBackEvent(string eventArgument);

Vous noterez que lorsqu’ASP.NET appelle cette méthode, il passe directement l’argument lié à l’événement. Cela tombe à point nommé puisque nous avons auparavant défini cet argument. Il suffit alors simplement de vérifier que l’argument correspond bien à celui de l’instance (d’où l’utilisation d’une valeur unique) pour déclencher l’appel au handler de la page.

public void RaisePostBackEvent(string eventArgument)
{
    if (eventArgument == this.ClientID & ButtonClick != null)
        ButtonClick(this, EventArgs.Empty);
}

Le fonctionnement événementiel totalement assumé

Lors de sa sortie, ASP.NET s’est clairement affiché comme une plateforme web de gestion d’événements. Il est parfois difficile de s’y retrouver et de faire les bons choix lorsque l’on ne maîtrise pas totalement le cycle de vie.

Cependant, la plateforme a su évoluer pour donner aux équipes les moyens de progresser et de simplifier grandement leurs développements… Encore faut-il être conscient des outils que l’on a à sa disposition !