Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Atteint de JavaScriptite Aiguë [Cyril Durand]

Expert ASP.net Ajax et WCF, Cyril Durand parle dans son blog de point techniques sur ASP.net, ASP.net Ajax, JavaScript, WCF et .net en général. Cyril est également consultant indépendant, n'hésitez pas à le contacter pour de l'assistance sur vos projets

Actualités

  • Blog de Cyril DURAND, passionné de JavaScript, Ajax, ASP.net et tout ce qui touche au developpement Web Client-Side.

    N'hésitez pas à me contacter pour vos projets .net : architecture, accompagnement, formation, ...

    View Cyril Durand's profile on LinkedIn
    hit counters


    Expertise Commerce server et BizTalk

PostBackControl - UpdatePanel et la communication client / serveur

Les UpdatePanels permettent de définir une zone à rafraichir plutôt que toute la page lors de postback. Ils s'intègrent parfaitement à ASP.net, en effet il suffit de mettre la partie à rafraichir à l'intérieur d'un updatepanel, et si un contrôle contenu par celui-ci fait un postback alors seul le contenu de l'UpdatePanel se met à jour côté client. Aucune manipulation de JavaScript ni quoi que ce soit est nécessaire, c'est la une grande force de ASP.net Ajax.

Mais c'est aussi le problème, il n'est pas aisé pour un développeur JavaScript de demander le rafraichissement d'un UpdatePanel. Une bidouille consiste à passer par un LinkButton et de demander à JavaScript de cliquer dessus pour déclencher le postback. Comme il s'agit d'une bidouille, je me suis décidé à faire un contrôle qui ne fais que déclencher un postback : Le PostBackControl.

Quel est le but de ce contrôle ? Permettre de déclencher un postback proprement en JavaScript afin de rafraichir certains UpdatePanels.

Tout d'abord il faut créer un nouveau contrôle qui implémente l'interface IPostBackEventHandler. Cette interface est très importante puisque c'est elle qui gère le postback. Vous pouvez retrouver l'intégralité du contrôle sur ASPFr.com : PostBackControl - communication client/serveur avec les UpdatePanels et voici un exemple d'utilisation : Charger dynamiquement un contrôle à l'ouverture d'une modalpopup

Quelques précisions sur le fonctionnement interne d'un UpdatePanel

J'aimerais ajouter ici quelques précisions concernant le fonctionnement interne des UpdatePanels.

Prenoms cette page :

<asp:UpdatePanel runat="server" UpdateMode="Conditional"> <ContentTemplate> <asp:Literal runat="server" ID="litHour" /> <asp:LinkButton runat="server" ID="lbShowHour" OnClick="lbShowHour_Click" Text="Affiche l'heure" /> </ContentTemplate> </asp:UpdatePanel>

Que se passe-t-il lorsque l'on clique sur le bouton "Affiche l'heure" ? Bien sur le literal est mis à jour via une requête Ajax, mais comment en arrive t'on jusque là ? Que se passe-t-il en interne ?

Tout d'abord analysons le code HTML généré :

<script type="text/javascript"> Sys.WebForms.PageRequestManager.getInstance()._updateControls( ['tctl00$CPH1$ctl00'], [], [], 90); </script> <div id="ctl00_CPH1_ctl00"> <a id="ctl00_CPH1_lbShowHour" href="javascript:__doPostBack('ctl00$CPH1$lbShowHour','')"> Affiche l'heure</a> </div>

On remarque l'appel à PageRequestManager._updateControls, avec en premier argument un tableau des UniqueID de tous les UpdatePanels présents dans la page.

Lorsque l'on click sur notre bouton, la méthode __doPostBack est appelé, cette méthode n'est pas la classique méthode introduite par ASP.net mais une autre version que ASP.net Ajax redéfinit. C'est ici que l'on détermine si oui ou non le postback se fera via Ajax ou alors via un classique POST. Pour définir ce comportement, la méthode va traduire le UniqueID en ClientID du contrôle déclenchant le postback en remplaçant les '$' par des '_' Ainsi il est possible de récupérer l'élément HTML. ASP.net Ajax recherche ensuite si le contrôle est contenu dans un UpdatePanel en remontant l'arbre DOM via une recherche récursive.

Concrétement dans notre cas :

  1. On click sur le bouton
  2. La méthode __doPostBack('ctl00$CPH1$lbShowHour','') (redéfinit par ASP.net Ajax) est appelé
  3. 'ctl00$CPH1$lbShowHour' est traduit en 'ctl00_CPH1_btnShowHour' pour récupérer l'élément HTML correspondant
  4. On vérifie les ID des éléments parent du contrôle pour voir s'il est contenu dans le tableau du premier argument de la méthode PageRequestManager._updateControls. Si oui alors le contrôle est contenu dans un UpdatePanel, il s'agit alors d'un AsyncPostBack.

Le cas plus haut est assez simple mais comment cela fonctionne lorsque j'utilise des AsyncPostBackTrigger et PostBackTrigger :

<asp:UpdatePanel runat="server" UpdateMode="Conditional"> <ContentTemplate> <asp:Literal runat="server" ID="litHour" /> <asp:LinkButton runat="server" ID="lbShowHourPostBack" OnClick="lbShowHour_Click" Text="Affiche l'heure" /> </ContentTemplate> <Triggers> <asp:AsyncPostBackTrigger ControlID="lbShowHourAsync" /> <asp:PostBackTrigger ControlID="lbShowHourPostBack" /> </Triggers> </asp:UpdatePanel> <asp:LinkButton ID="lbShowHourAsync" runat="server" OnClick="lbShowHour_Click" Text="Affiche l'heure" />

C'est ici qu'interviennent les 2 autres arguments de la méthode _updateControls :

<script type="text/javascript"> Sys.WebForms.PageRequestManager.getInstance()._updateControls( ['tctl00$CPH1$ctl00'], ['ctl00$CPH1$lbShowHourAsync'], ['ctl00$CPH1$lbShowHourPostBack'], 90); </script>

Comme vous vous en doutez, les nouveaux arguments seront utilisé lors de la recherche de l'UpdatePanel parent (recherche récursive).

Quel rapport avec mon contrôle ? Puisque celui-ci n'a pas besoin de rendu HTML je l'ai simplement fait hériter de Control, il n'est donc lié à aucun élément HTML, la recherche récursive de l'UpdatePanel ne peut alors pas s'effectuer, ASP.net fait un classique postback. J'ai donc enregistré manuellement le contrôle comme faisant un AsyncPostBack.

ScriptManager sc = ScriptManager.GetCurrent(this.Page); if (sc != null) sc.RegisterAsyncPostBackControl(this);

Plus concrétement, cela a pour effet d'ajouter l'id de mon contrôle dans tableau du 2ème argument de la méthode _updateControls. Ainsi, j'arrive bien à faire une requête Ajax. Par contre l'UpdatePanel contenant le contrôle n'est pas rafraichis. Pourquoi ? Pour le savoir il faut s'interesser au contenu POST de la requête XHR d'un AsyncPostBack.

Parmi les champs POST envoyé il y a un champ caché qui porte le nom du ScriptManager, voici ces valeurs.

#cas du Linkbutton ctl00$SC1 ctl00$CPH1$ctl00|ctl00$CPH1$lbShowHour #cas du PostBackControl ctl00$SC1 ctl00$SC1|ctl00$CPH1$pbcTest

On voit qu'il y a 2 valeurs séparé par un pipe (|). La première valeur est l'UpdatePanel qui réclame l'AsyncPostback alors que le second correspond au contrôle le déclenchant. Le problème se situe ici : c'est JavaScript qui décide quel UpdatePanel il doit rafraichir. Notre contrôle ne générant aucun élément HTML, JavaScript n'a aucun moyen de savoir à quel UpdatePanel il appartient.

Les solutions possibles sont de rajouter manuellement un trigger dans l'UpdatePanel qui contient le PostBackControl ou alors rajouter automatiquement un trigger en regardant les parents jusqu'a obtenir un UpdatePanel au niveau du controle C# voir même d'appeler la méthode Update de l'UpdatePanel à rafraichir dans l'événement CallBack. Mais la solution que j'ai choisi est de générer du HTML, pour cela il nous suffit d'hériter de WebControl plutôt que de Control, ainsi un élément span avec un ID sera généré et il n'y aura plus de problème.

Mais est-ce normal que ASP.net Atlas ne fasse pas automatiquement cette recherche ? Il me semble que dans les versions beta d'Atlas, cette recherche était faite mais ca a été supprimé pour des raisons de performances, en effet l'utilisation d'un contrôle qui ne génère aucun HTML mais effectue un PostBack est très rare ...

[Edit]

Voici un exemple d'utilisation : Charger dynamiquement un contrôle à l'ouverture d'une modalpopup

Posted: mercredi 10 octobre 2007 03:19 par cyril
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :

Commentaires

sebmafate a dit :

Excellent... je sens que ça va rendre service !

# octobre 10, 2007 09:43

EliseD a dit :

article très interessant !

# octobre 10, 2007 11:55
Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- Merci par Blog de Jérémy Jeanson le 10-01-2019, 20:47

- Office 365: Script PowerShell pour auditer l’usage des Office Groups de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 11:02

- Office 365: Script PowerShell pour auditer l’usage de Microsoft Teams de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 10:39

- Office 365: Script PowerShell pour auditer l’usage de OneDrive for Business de votre tenant par Blog Technique de Romelard Fabrice le 04-25-2019, 15:13

- Office 365: Script PowerShell pour auditer l’usage de SharePoint Online de votre tenant par Blog Technique de Romelard Fabrice le 02-27-2019, 13:39

- Office 365: Script PowerShell pour auditer l’usage d’Exchange Online de votre tenant par Blog Technique de Romelard Fabrice le 02-25-2019, 15:07

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Stream Portal par Blog Technique de Romelard Fabrice le 02-21-2019, 17:56

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Video Portal par Blog Technique de Romelard Fabrice le 02-18-2019, 18:56

- Office 365: Script PowerShell pour extraire les Audit Log basés sur des filtres fournis par Blog Technique de Romelard Fabrice le 01-28-2019, 16:13

- SharePoint Online: Script PowerShell pour désactiver l’Option IRM des sites SPO non autorisés par Blog Technique de Romelard Fabrice le 12-14-2018, 13:01