ASP Net Vol 2

download ASP Net Vol 2

of 192

Transcript of ASP Net Vol 2

Dveloppement WEB avec ASP.NET 1.1 VOLUME 2

[email protected] avril 2004

IntroductionLe volume 1 du cours ASP.NET a prsent les notions fondamentales de la programmation web, celles que l'on retrouve tout le temps, quelque soit la technologie de dveloppement utilise (Java, Php, Asp.net). Nous avons en particulier prsent la mthode MVC (Modle, Vue, Contrleur) prconise pour tout dveloppement web. Le volume 1 s'est attard essentiellement sur les parties Modle et Contrleur et peu sur les vues. Celles-ci taient construites sans fioritures avec le langage HTML. ASP.NET amne avec lui une bibliothque de composants permettant : la conception d'interfaces web plus riches sans dveloppement excessif la conception du contrleur de l'application comme un ensemble de gestionnaire d'vnements lis aux composants des vues L'criture d'une application web devient similaire celle d'une application windows o on dessine des interfaces avant d'crire les gestionnaires des vnements que celles-ci peuvent gnrer. Cependant, lorsqu'on essaie de raccrocher ce mode de conception au modle MVC, on s'aperoit qu'ils ne vont pas ensemble. Il n'est pas possible d'avoir un unique contrleur par lequel passent toutes les requtes des clients si l'application utilise des formulaires construits avec des composants ASP.NET. C'est fcheux car il nous faut alors choisir entre deux modes de conception ayant chacun un intrt. On peut cependant montrer qu'il est possible d'crire des application utilisant les composants riches d'ASP.NET si on accepte d'avoir plusieurs contrleurs au lieu d'un seul. Cette solution est souvent acceptable. Ce document expose comment construire des vues l'aide des composants ASP.NET appels composants serveur. C'est un long travail. Il existe beaucoup de composants et ceratins sont trs complexes. Ce volume 2 consacr aux seules vues est ainsi important en taille que celui consacr aux notions fondamentales. C'est de plus compltement propritaire puisque on ne retrouve pas les techniques qui vont tre exposes ni en Java ni en PHP. C'est pourquoi nous avons choisi de les isoler dans un volume part considrant qu'il fallait d'abord mariser les notions fondamentales de tout dveloppement web avant de s'intresser aux problmes de construction de vues. Le thme des composants serveur ASP.NET est tellement vaste que ce volume 2 n'arrive pas l'puiser. Les composants HTML serveur n'ont pas t exposs. Ils le seront peut-tre ultrieurement. Ce document comporte peut-tre encore des erreurs : toute suggestion constructive est la bienvenue l'adresse [email protected]. Serge Tah Juin 2004

1 Composants serveur ASP - 11.1 Introduction

Nous dcrivons dans ce chapitre, la technologie prconise dans ASP.NET pour construire l'interface utilisateur. Nous savons qu'il y a deux phases bien distinctes dans le traitement d'une page .aspx par le serveur web : 1. 2. il y a tout d'abord excution du contrleur de la page. Celui-ci est constitu par du code situ soit dans la page .aspx ellemme (solution WebMatrix) soit dans un fichier part (solution Visual Studio.NET). puis le code de prsentation de la page .aspx est excut pour tre transform en code HTML envoy au client.

contrleur de page Client

prsentation page

Serveur

ASP.NET offre trois bibliothques de balises pour crire le code de prsentation de la page : 1. les balises HTML classiques. C'est ce que nous avons utilis jusqu' maintenant. 2. les balises HTML serveur 3. les balises webforms Quelque soit la bibliothque de balises utilise, le rle du contrleur de page ne change pas. Il doit calculer la valeur des paramtres dynamiques apparaissant dans le code de prsentation. Jusqu' maintenant, ces paramtres dynamiques taient simples : c'taient des objets de type [String]. Ainsi si dans le code de prsentation on a une balise : le contrleur de page dclare une variable [nom] de type [String] et calcule sa valeur lorsque le contrleur de page a termin son travail et que le code de prsentation est excut pour gnrer la rponse HTML, la balise est remplace par la valeur calcule par le code de contrle On sait que le dcoupage contrleur/prsentation est arbitraire et qu'on peut mlanger code contrleur et code de prsenttaion dans la mme page. Nous avons expliqu pourquoi cette mthode tait dconseille et nous continuerons respecter le dcoupage contrle/prsentation. Les balises [HTML serveur] et [WebForms] permettent d'introduire dans le code de prsentation des objets plus complexes que le simple objet [String]. Cela prsente parfois un rel intrt. Prenons l'exemple d'un formulaire avec liste. Celle-ci doit tre prsente au client avec un code html qui ressemble ceci : option1 option2 option3

Le contenu de la liste et l'option slectionner sont des lments dynamiques et donc doivent tre gnrs par le contrleur de page. Nous avons dj rencontr ce problme et l'avons rsolu en mettant dans le code de prsentation la balise

Cette balise va tre remplace par la valeur [String] de la variable [uneListeHTML]. Cette valeur calcule par le contrleur devra tre le code HTML de la liste, c.a.d. "...". Ce n'est pas particulirement difficile faire et cela parat une solution lgante qui vite de mettre du code de gnration directement dans la partie prsentation de la page. Ici il y aurait une boucle avec des tests insrer dans celle-ci qui serait ainsi fortement "pollue". Nanmoins, cette mthode prsente un inconvnient. Le dcoupage contrle/prsentation d'une page sert aussi dlimiter deux domaines de comptence : celui du dveloppeur .NET qui s'occupe du contrleur de page celui de l'infographiste qui s'occupe de la partie prsentation de celle-ci Ici, on voit qu'on a transfr la gnration du code HTML de la liste dans le contrleur. L'infographiste peut vouloir agir sur ce code HTML pour modifier l'aspect "visuel" de la liste. Il sera oblig de travailler dans la partie [contrleur] et donc de sortir de son domaine de comptence avec les risques d'erreurs introduites malencontreusement dans le code que cela comporte. Composants serveur - 2 3/192

Les bibliothques de balises serveur rsolvent ce problme. Elles proposent un objet reprsentant une liste HTML. Ainsi la bibliothque [WebForms] offre la balise suivante : Cette balise reprsente un objet de type [ListBox] qui peut tre manipul par le contrleur de page. Cet objet a des proprits pour reprsenter les diffrentes options de la liste HTML et dsigner l'option slectionne. Le contrleur de page va donc donner les valeurs adquates ces proprits. Lorsque la partie prsentation va tre excute, la balise va tre remplace par le code HTML reprsentant l'objet [uneListe], c.a.d. le code "...". Pour l'instant, pas de diffrence fondamentale avec la mthode prcdente sinon une faon de coder oriente objet, ce qui est intressant. Revenons notre infographiste qui a besoin de modifier le "look" de la liste. Les balises serveur ont des attributs de style (BackColor, Bordercolor, BorderWidth, ...) qui permettent de fixer l'aspect visuel de l'objet HTML correspondant. Ainsi on pourra crire :

L'intrt est que l'infographiste reste dans le code de prsentation pour faire ces modifications. C'est un avantage certain vis vis de la mthode prcdente. Les bibliothques de balises serveur amnent donc des facilits dans la construction de la partie prsentation des pages, ce qu'on a appel dans les chapitres prcdents, l'interface utilisateur. Ce chapitre a pour but de les prsenter. On verra qu'elle propose parfois des objets complexes tels que des calendriers ou des tables lies des sources de donnes. Elles sont extensibles, c.a.d. que l'utilisateur peut crer sa propre bibliothque de balises. Il peut ainsi raliser une balise gnrant un bandeau dans une page. Toutes les pages utilisant cette balise auront alors le mme bandeau. La gnration HTML faite pour une balise s'adapte au type du navigateur client. Lorsque celui-ci fait une requte au serveur web, il envoie parmi ses enttes HTTP, un entte [User-Agent: xx] o [xx] identifie le client. Voici un exemple :User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040316

Avec cette information, le serveur web peut connatre les capacits du client, notamment le type de code HTML qu'il sait grer. Il y a eu en effet, au fil du temps, plusieurs versions du langage HTML. Les navigateurs rcents comprennent les versions les plus rcentes du langage, ce que ne savent pas faire des navigateurs plus anciens. En fonction de l'entte HTTP [User-Agent:] que le client lui a envoy, le serveur lui enverra une version HTML qu'il saura comprendre. C'est une ide intressante et utile car le dveloppeur n'a alors pas se proccuper du type de navigateur client de son application. Enfin, des IDE volus comme Visual Studio.NET, WebMatrix, ... permettent une conception " la windows" de l'interface Web. Ces outils non indispensables, apportent cependant une aide dcisive au dveloppeur. Celui-ci dessine l'interface web l'aide de composants graphiques qu'ils dposent sur cette interface. Il a un accs direct aux proprits de chacun des composants de l'interface qu'il peut ainsi paramtrer sa guise. Ces proprits seront traduites dans le code HTML de prsentation de l'interface en attributs de la balise du composant. L'intrt pour le dveloppeur est qu'il n'a pas se rappeler ni la liste ni la syntaxe des attributs de chaque balise. C'est un avantage apprciable lorsqu'on ne connat pas parfaitement les bibliothques de balises serveur offertes par ASP.NET. Lorsque cette syntaxe est acquise, certains dveloppeurs pourront prfrer coder directement les balises dans le code de prsentation de la page sans passer par la phase conception graphique. Un IDE n'est plus alors utile. Un simple diteur de texte suffit. Selon la faon dont on travaille, l'accent est alors mis sur les composants (utilisation d'un IDE) ou les balises (utilisation d'un diteur de texte). Il y a quivalence entre ces deux termes. Le composant est l'objet qui va tre manipul par le code de contrle de la page. L'IDE nous donne accs ses proprits en phase de conception. Les valeurs donnes celles-ci sont traduites immdiatement dans les attributs de la balise du composant dans le code de prsentation. En phase d'excution, le code de contrle de la page va manipuler le composant et affecter des valeurs certaines de ses proprits. Le code de prsentation va lui gnrer le code HTML du composant en utilisant d'une part les attributs fixs la conception pour la balise serveur correspondante, d'autre part les valeurs des proprits du composant calcules par le code de contrle.

1.2 Le contexte d'excution des exemplesNous allons illustrer la conception des interfaces web base de composants serveur avec des programmes dont le contexte d'excution sera la plupart du temps le suivant : l'application web sera compose d'une unique page P contenant un formulaire F, le client fera sa premire requte directement cette page P. Cela consistera demander l'url de la page P avec un navigateur. C'est donc une requte GET qui sera faite sur cette url P. Le serveur dlivrera la page P et donc le formulaire F qu'elle contient, 3. l'utilisateur remplira celui-ci et le postera, c.a.d. qu'il fera une action qui forcera le navigateur poster le formulaire F au serveur. L'opration POST du navigateur sera toujours destination de la page P. Le serveur dlivrera de nouveau la page P avec le formulaire F, le contenu de ce dernier ayant pu tre modifi par l'action de l'utilisateur. Composants serveur - 2 4/192 1. 2.

4.

puis les tapes 2 et 3 reprendront.

C'est un processus d'excution bien particulier en-dehors duquel certains concepts exposs ci-aprs ne fonctionnent plus. Nous ne sommes plus dans un contexte d'architecture MVC dans lequel une application multi-pages est contrle par une page particulire que nous avons appele "contrleur d'application". Dans ce type d'architecture, le POST des formulaires ont pour cible le contrleur et non les formulaires eux-mmes. Or nous allons voir que construire un formulaire avec des composants serveur implique que ce formulaire soit post lui-mme.

1.3 Le composant Label1.3.1 UtilisationLa balise permet d'insrer un texte dynamique dans le code de prsentation d'une page. Ca ne fait donc pas davantage que la balise utilise jusqu' maintenant. L'tude de cette premire balise va nous permettre de dcouvrir le mcanisme des balises serveur. Nous crons une page avec une partie contrle [form1.aspx.vb] et une partie prsentation [form1.aspx] . Il s'agit d'afficher l'heure :

Ce problme a dj t trait dans le chapitre 2 et le lecteur est invit s'y reporter s'il souhaite savoir comment il avait t trait. Le code de prsentation [form1.aspx] est le suivant : Webforms

Nous introduisons la balise . Dans les bibliothque de balises, l'attribut [runat="server"] est obligatoire. L'attribut ID identifie le composant. Le contrleur devra le rfrencer avec cet identifiant. Le code du contrleur [form1.aspx.vb] est le suivant : ImportsSystem.Web.UI.WebControls

Public Class form1 Inherits System.Web.UI.Page Protected lblHeure As Label Private Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Init ' sauve la requte courante dans request.txt du dossier de la page Dim requestFileName As String = Me.MapPath(Me.TemplateSourceDirectory) + "\request.txt" Me.Request.SaveAs(requestFileName, True) End Sub Private Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load ' met l'heure dans lblHeure lblHeure.Text = "Il est " + Date.Now.ToString("T") End Sub End Class

Le contrleur doit donner une valeur l'objet [lblHeure] de type [System.Web.UI.WebControls.Label]. Tous les objets affichs par les balises appartiennent l'espace de noms [System.Web.UI.WebControls]. Aussi pourra-t-on importer systmatiquement cet espace de noms : ImportsSystem.Web.UI.WebControls

L'objet [Label] a diffrentes proprits dont la proprit [Text] qui reprsente le texte qui sera affich par la balise correspondante. Ici, nous mettons dans cette proprit l'heure courante. Nous le faisons dans la procdure [Form_Load] du Composants serveur - 2 5/192

contrleur qui est systmatiquement excut. Dans la procdure [Form_Init] qui elle aussi est toujours excute mais avant la procdure [Form_Load], nous mmorisons la requte du client dans un fichier [request.txt] du dossier de l'application. Nous aurons l'occasion d'examiner ce fichier pour comprendre certains aspects du fonctionnement des pages utilisant des balises serveur. L'objet [Label] possde de nombreuses proprits, mthodes et vnements. Le lecteur est invit lire la documentation sur la classe [Label] pour les dcouvrir. Dans la suite, il en sera toujours ainsi. Pour chaque balise, nous ne prsentons que les quelques proprits dont nous avons besoin.

1.3.2 Les testsNous plaons les fichiers (form1.aspx, form1.aspx.vb) dans un dossier et lanons Cassini avec les paramtres (,/form1). Puis nous demandons l'url [http://localhost/form1/form1.aspx]. Nous obtenons le rsultat suivant :

Le code HTML reu par le navigateur est le suivant : Webforms Il est 19:39:37

On voit que la balise serveur

a t transforme en le code HTML suivant :Il est 19:39:37

C'est la proprit [Text] de l'objet [lblHeure] qui a t plac entre les balises et . La requte faite par le client et mmorise dans [request.txt] est la suivante :GET /form1/form1.aspx HTTP/1.1 Cache-Control: max-age=0 Connection: keep-alive Keep-Alive: 300 Accept: application/x-shockwaveflash,text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,image/jpeg ,image/gif;q=0.2,*/*;q=0.1 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Accept-Encoding: gzip,deflate Accept-Language: en-us,en;q=0.5 Host: localhost User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040316

Rien que de trs normal.

1.3.3 Construire l'application avec WebMatrixNous avons construit le code de prsentation de la page [form1.aspx] la main. Cette mthode est utilisable si on connat les balises. Un simple diteur de texte suffit alors pour construire l'interface utilisateur. Pour dbuter, un outil de conception graphique alli une gnration de code automatique est souvent ncessaire parce qu'on ne connat pas la syntaxe des balises dont on a besoin. Nous construisons maintenant la mme application avec l'outil WebMatrix. Une fois WebMatrix lanc, nous choisissons l'option [File/New File] :

Composants serveur - 2

6/192

Nous crons une page ASP.NET appele [form2.aspx]. Une fois valid l'assistant prcdent, nous obtenons la fentre de conception de la page [form2.aspx] :

On rappelle que WebMatrix met le code de contrle de la page et celui de prsentation dans un mme fichier, ici [form2.aspx]. L'onglet [All] prsente le contenu de ce fichier texte. On peut constater ds maintenant qu'il n'est pas vide :

L'inconvnient de ce type d'outils est que souvent ils gnrent du code inutile. C'est le cas ici, o WebMatrix a gnr une balise HTML alors qu'on ne va pas construire de formulaire... Par ailleurs, on peut constater que le document n'a pas de balise . Nous remdions ces deux problmes sur le champ pour obtenir la nouvelle version suivante :

Composants serveur - 2

7/192

Ce que nous appelons le code contrleur va venir s'insrer entre les balises et , ce qui assure une sparation au moins visuelle entre les deux types de code : contrle et prsentation. Nous revenons sur l'onglet [Design] pour dessiner notre interface. Une liste de composants est disponible dans une fentre d'outils gauche de la fentre de conception :

La fentre d'outils offre l'accs deux types de composants : les composants [WebControls] qui se traduisent par des balises les composants [HTML Elements] qui se traduisent par des balises HTML classiques. Cependant, on peut ajouter aux attributs d'une balise HTML, l'attribut [runat="server"]. Dans ce cas, la balise HTML et ses attributs sont accessibles au contrleur via un objet ayant pour proprits celles de la balise HTML qu'il reprsente. On a appel prcdemment ces balises, les balises HTML serveur. Double-cliquons sur le composant [Label] de la liste de contrles [WebControls]. Dans l'onglet [Design] on obtient le rsultat suivant :

Dans l'onglet [All] le code est devenu le suivant : webforms Label

On peut remarquer tout d'abord qu'on a perdu la balise . Une balise a t gnre. Elle a un nom [Label1] et une valeur [Label]. Revenons sur l'onglet [Design] pour modifier ces deux valeurs. Nous y cliquons une fois sur le composant [Label] pour faire apparatre la fentre de proprits de ce composant, en bas droite :

Composants serveur - 2

8/192

Le lecteur est invit consulter les proprits de l'objet [Label]. Deux nous intressent ici : Text : c'est le texte que doit afficher le label - nous mettons la chane vide (c.a.d. rien) ID : c'est son identifiant - nous mettons lblHeure L'onglet [Design] devient ceci :

et le code de [All] devient : webforms

La partie prsentation de la page est finie. Il nous reste crire le code de contrle charg de mettre l'heure dans la proprit [Text] de [lblHeure]. Nous ajoutons dans l'onglet [All] le code suivant : Private Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load ' met l'heure dans lblHeure lblHeure.Text = "Il est " + Date.Now.ToString("T") End Sub webforms

On remarquera que dans le code contrleur, on ne dclare pas l'objet [lblHeure] comme il avait t fait prcdemment :Protected lblHeure As New System.Web.UI.WebControls.Label

En effet, tous les composants serveur de la partie prsentation font l'objet d'une dclaration implicite dans la partie code de contrle. Aussi les dclarer provoque une erreur de compilation, celle-ci indiquant que l'objet est dj dclar. Nous sommes prts pour l'excution. Nous prenons l'option [View/Start] ou le raccourci [F5]. Cassini est automatiquement lanc avec les paramtres suivants : Composants serveur - 2 9/192

Nous acceptons ces valeurs. Le navigateur par dfaut du systme est automatiquement lanc pour demander l'url [http://localhost/form2.aspx]. Nous obtenons le rsultat suivant :

Par la suite, nous utiliserons principalement l'outil WebMatrix afin de faciliter la construction et les tests des courts programmes que nous crirons.

1.4 Le composant Literal1.4.1 UtilisationLa balise permet d'insrer un texte dynamique dans le code de prsentation d'une page comme la balise . Son principal attribut est [Text] qui reprsente le texte qui sera insr tel quel dans le flux HTML de la page. Cette balise est suffisante si on n'a pas l'intention de mettre en forme le texte que l'on veut insrer dans le flux HTML. En effet si la classe [Label] permet de mettre en forme grce des attributs tels que [BorderColor, BorderWidth, Font, ...], la classe [Literal] n'a aucun de ces attributs. Le lecteur pourra reprendre intgralement l'exemple prcdent en remplaant le composant [Label] par un composant [Literal].

1.5 Le composant Button1.5.1 UtilisationLa balise permet d'insrer un bouton de type [Submit] dans un formulaire qui amne avec lui une gestion d'vnements semblable celle que l'on trouve dans les applications windows. C'est ce point qu'on veut approfondir ici. Nous crons la page [form3.aspx] suivante : 1 2

3 Cette page construite avec WebMatrix a trois composants : n 1 2 3 nomButton1 Button2 lblInfo

type Button Button Label

proprits text=Bouton1 text=Bouton2 text=

rle bouton submit bouton submit message d'information

Le code gnr par WebMatrix pour cette partie est le suivant :

Composants serveur - 2

10/192

asp:button

Nous retrouvons les composants [Button] et [Label] utiliss lors de la conception graphique de la page dans des balises . Notons la balise qui a t gnre automatiquement. C'est une balise HTML serveur, c.a.d. une balise HTML classique reprsente nanmoins par un objet manipulable par le contrleur. Le code HTML de la balise sera gnr partir de la valeur que le contrleur donnera cet objet. Ajoutons dans la partie contrleur du code, la procdure [Page_Init] qui gre l'vnement [Init] de la page. Nous y plaons le code qui sauvegarde la requte du client dans le fichier [request.txt]. Nous en aurons besoin pour comprendre le mcanisme des boutons. Private Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) ' sauve la requte courante dans request.txt du dossier de la page Dim requestFileName As String = Me.MapPath(Me.TemplateSourceDirectory) + "\request.txt" Me.Request.SaveAs(requestFileName, True) End Sub

On notera ci-dessus que nous n'avons pas mis la clause [Handles MyBase.Init] derrire la dclaration de la procdure [Page_Init]. En effet, l'vnement [Init] de l'objet [Page] a un gestionnaire par dfaut qui s'appelle [Page_Init]. Si on utilise ce nom de gestionnaire, la clause [Handles Page.Init] devient inutile. La mettre ne provoque cependant pas d'erreur.

1.5.2 TestsNous lanons l'application sous WebMatrix par [F5]. Nous obtenons la page suivante :

Le code HTML reu par le navigateur est le suivant : asp:button

Composants serveur - 2

11/192

Notons les points suivants : la balise s'est transforme en balise HTML

Deux attributs ont t fixs [method="post"] et [action="form3.aspx"]. Peut-on donner des valeurs diffrentes ces attributs ? Nous essaierons d'claircir ce point un peu plus loin. On retiendra ici que le formulaire sera post l'url [form3.aspx]. Deux autres attributs [name, id] ont t galement fixs. La plupart du temps, ils sont ignors. Cependant si la page contient du code Javascript excut ct navigateur, l'attribut [name] de la balise est utile. les balises sont devenues des balises HTML de boutons [submit]. Un clic sur l'un quelconque de ces boutons provoquera donc un "post" du formulaire [_ctl10] l'url [form3.aspx]. la balise est devenue une balise HTML un champ cach [__VIEWSTATE] a t gnr avec une valeur bizarre : type="hidden" name="__VIEWSTATE" value="dDwxNTY0NjIwMjUwOzs+2mcnJczeuvF2PEfvmtv7uiUhWUw="

Ce champ reprsente sous une forme code l'tat du formulaire envoy au client. Cet tat reprsente la valeur de tous les composants de celui-ci. Comme [__VIEWSTATE] fait partie du formulaire, sa valeur sera poste avec le reste au serveur. Cela permettra celui-ci de savoir quel composant du formulaire a chang de valeur et ventuellement de prendre des dcisions. Celles-ci prendront la forme d'vnements du type "le TextBox untel a chang de valeur".

1.5.3 Les requtes du clientUne fois obtenue la page [form3.aspx] dans le navigateur, redemandons-la puis regardons la requte qui a t envoye par le navigateur pour l'obtenir. On se rappelle que notre application la mmorise dans le fichier [request.txt] dans le dossier de l'application :GET /form3.aspx HTTP/1.1 Connection: keep-alive Keep-Alive: 300 Accept: application/x-shockwaveflash,text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,image/jpeg ,image/gif;q=0.2,*/*;q=0.1 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Accept-Encoding: gzip,deflate Accept-Language: en-us,en;q=0.5 Host: localhost User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040316

On a l un GET classique. Maintenons cliquons sur le bouton [Bouton1] de la page dans le navigateur. Il ne se passe apparemment rien. Pourtant nous savons que le formulaire a t post. C'est le code HTML de la page qui le dit. Cela est confirm par le nouveau contenu de [request.txt] :POST /form3.aspx HTTP/1.1 Connection: keep-alive Keep-Alive: 300 Content-Length: 80 Content-Type: application/x-www-form-urlencoded Accept: application/x-shockwaveflash,text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,image/jpeg ,image/gif;q=0.2,*/*;q=0.1 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Accept-Encoding: gzip,deflate Accept-Language: en-us,en;q=0.5 Host: localhost Referer: http://localhost/form3.aspx User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040316 __VIEWSTATE=dDwxNTY0NjIwMjUwOzs%2B2mcnJczeuvF2PEfvmtv7uiUhWUw%3D&Button1=Bouton1

Le premier entte HTTP indique bien que le client a fait un POST vers l'url [/form3.aspx]. La dernire ligne montre les valeurs postes : la valeur du champ cach __VIEWSTATE la valeur du bouton qui a t cliqu Composants serveur - 2 12/192

Si nous cliquons sur [Bouton2], les valeurs postes par le navigateur sont les suivantes :__VIEWSTATE=dDwxNTY0NjIwMjUwOzs%2B2mcnJczeuvF2PEfvmtv7uiUhWUw%3D&Button2=Bouton2

La valeur du champ cach est toujours la mme mais c'est la valeur de [Button2] qui a t poste. Le serveur peut donc savoir quel bouton a t utilis. Il va s'en servir pour dclencher un vnement qui pourra tre trait par la page, une fois que celle-ci aura t charge.

1.5.4 Grer l'vnement Click d'un objet ButtonRappelons le fonctionnement d'une page .aspx. Celle-ci est un objet driv de la classe [Page]. Appelons la classe drive [unePage]. Lorsque le serveur reoit une requte pour une telle page, un objet de type [unePage] est instanci par une opration new unePage(...). Puis ensuite, le serveur gnre deux vnements appels [Init] et [Load] dans cet ordre. L'objet [unePage] peut les grer en fournissant les gestionnaires d'vnements [Page_Init] et [Page_Load]. Ensuite d'autres vnements seront gnrs. Nous aurons l'occasion d'y revenir. Si la requte du client est un POST, le serveur gnrera l'vnement [Click] du bouton qui a provoqu ce POST. Si la classe [unePage] a prvu un gestionnaire pour cet vnement, celui-ci sera appel. Voyons ce mcanisme avec WebMatrix. Dans l'onglet [Design] de [form3.aspx], double-cliquons sur le bouton [Bouton1]. Nous sommes alors amens automatiquement dans l'onglet [Code], dans le corps d'une procdure appele [Button1_Click]. Pour mieux comprendre, allons dans l'onglet [All] et regardons la totalit du code. Les modifications suivantes ont t apportes : ... Sub Button1_Click(sender As Object, e As EventArgs) End Sub ... ...

Un nouvel attribut [onclick="Button1_Click"] a t ajout la balise de [Button1]. Cet attribut indique la procdure charge de traiter l'vnement [Click] sur l'objet [Button1], ici la procdure [Button1_Click]. Il ne nous reste plus qu' crire celle-ci :Sub Button1_Click(sender As Object, e As EventArgs) ' clic sur bouton 1 lblInfo.Text="Vous avez cliqu sur [Bouton1]" End Sub

La procdure met dans le label [lblInfo] un message d'information. Nous procdons de la mme faon pour le bouton [Bouton2] pour obtenir la nouvelle page [form3.aspx] suivante : Private Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) ' sauve la requte courante dans request.txt du dossier de la page Dim requestFileName As String = Me.MapPath(Me.TemplateSourceDirectory) + "\request.txt" Me.Request.SaveAs(requestFileName, True) End Sub Sub Button1_Click(sender As Object, e As EventArgs) ' clic sur bouton 1 lblInfo.Text="Vous avez cliqu sur [Bouton1]" End Sub Sub Button2_Click(sender As Object, e As EventArgs) ' clic sur bouton 2 lblInfo.Text="Vous avez cliqu sur [Bouton2]" End Sub

Composants serveur - 2

13/192

asp:button

Nous lanons l'excution par [F5] pour obtenir la page suivante :

Si nous regardons le code HTML reu, nous constaterons qu'il n'a pas chang vis vis de celui de la version prcdente de la page : asp:button

Si nous cliquons sur [Bouton1], nous obtenons la rponse suivante :

Le code HTML reu pour cette rponse est le suivant : asp:button

Composants serveur - 2

14/192

Vous avez cliqu sur [Bouton1]

Nous pouvons constater que le champ cach [__VIEWSTATE] a chang de valeur. Cela reflte le changement de valeur du composant [lblInfo].

1.5.5 Les vnements de la vie d'une application ASP.NETLa documentation ASP.NET donne la liste des vnements gnrs par le serveur au cours de la vie d'une application : lors de la toute premire requte que reoit l'application, l'vnement [Start] sur l'objet [HttpApplication] de l'application va tre gnr. Cet vnement peut tre gr par la procdure [Application_Start] du fichier [global.asax] de l'application.

Ensuite nous allons avoir une srie d'vnements qui vont se rpter pour chaque requte reue : si la requte n'a pas envoy de jeton de session, une nouvelle session est dmarre et un vnement [Start] sur l'objet [Session] associ la requte est gnr. Cet vnement peut tre gr par la procdure [Session_Start] du fichier [global.asax] de l'application. le serveur gnre l'vnement [BeginRequest] sur l'objet [HttpApplication]. Il peut tre gr par la procdure [Application_BeginRequest] du fichier [global.asax] de l'application. le serveur charge la page demande par la requte. Il va instancier un objet [Page] puis gnrer deux vnements sur cet objet : [Init] puis [Load]. Ces deux vnements peuvent tre grs par les procdure [Page_Init] et [Page_Load] de la page. partir des valeurs postes reues, le serveur va gnrer d'autres vnements : [TextChanged] pour un composant [TextBox] qui a chang de valeur, [CheckedChanged] pour un bouton radio qui a chang de valeur, [SelectedIndexChanged] pour une liste qui a chang d'lment slectionn, ... Nous aurons l'occasion de mentionner les principaux vnements pour chacun des composants serveur que nous allons prsenter. Chaque vnement E sur un objet nomm O peut tre gr par une procdure portant le nom O_E. l'ordre de gestion des vnements prcdents n'est pas garanti. Aussi les gestionnaires ne doivent-ils faire aucune hypothse sur cet ordre. On est cependant assur que l'vnement [Click] du bouton qui a provoqu le POST est trait en dernier. une fois la page prte, le serveur va l'envoyer au client. Avant, il gnre l'vnement [PreRender] qui peut tre gr par la procdure [Page_PreRender] de la page. une fois la rponse HTML envoye au client, la page va tre dcharge de la mmoire. Deux vnements seront gnrs cette occasion [Unload] et [Disposed]. La page peut utiliser ces vnements pour librer des ressources.

L'application peut galement recevoir des vnements en-dehors d'une requte client : l'vnement [End] sur un objet [Session] de l'application se produit lorsqu'une session se termine. Cela peut se produire sur une demande explicite du code d'une page soit parce que la dure de vie accorde la session est dpass. La procdure [Session_End] du fichier [global.asax] gre cet vnement. On y libre en gnral des ressources obtenues dans [Session_Start]. l'vnement [End] sur l'objet [HttpApplication] de l'application se produit lorsque l'application se termine. Cela se produit notamment lorsqu'on arrte le serveur Web. La procdure [Application_End] du fichier [global.asax] gre cet vnement. On y libre en gnral des ressources obtenues dans [Application_Start].

On retiendra les points suivants : le modle vnementiel prcdent s'appuie sur des changes HTTP client-serveur classiques. On le voit parfaitement lorsqu'on examine les enttes HTTP changs. le traitement des vnements prcdents se fait toujours ct serveur. Le clic sur un bouton peut bien sr tre trait par un script Javascript ct serveur. Mais il ne s'agit pas alors d'un vnement serveur et on est l dans une technologie indpendante de ASP.NET. A quel moment sont traits les vnements, qu'ils soient traits du ct serveur (vnements lis aux composants serveur) ou du ct navigateur par des scripts Javascript ? Composants serveur - 2 15/192

Prenons l'exemple d'une liste droulante. Lorsque l'utilisateur change l'lment slectionn dans celle-ci, l'vnement (changement de l'lment slectionn) peut tre trait ou non et s'il est trait il peut l'tre diffrents moments. si on souhaite le traiter immdiatement, on a deux solutions : o il peut tre trait par le navigateur l'aide d'un script Javascript. Le serveur n'intervient alors pas. Pour que cela soit possible, il faut que la page puisse tre reconstruite avec des valeurs prsentes dans la page. o il peut tre trait par le serveur. Pour cela, il n'y a qu'une solution : le formulaire doit tre envoy au serveur pour traitement. On a donc une opration [submit]. On verra que dans ce cas, on utilise un composant serveur appel [DropDownList] et on fixe son attribut [AutoPostBack] [true]. Cela veut dire qu'en cas de changement d'lment slectionn dans la liste droulante, le formulaire doit tre immdiatement post au serveur. Le serveur gnre dans ce cas, pour l'objet [DropDownList] un code HTML associ une fonction Javascript charge de faire un [submit] ds que l'vnement "changement de l'lment slectionn" se produit. Ce [submit] postera le formulaire au serveur et dans celui-ci des champs cachs seront positionns pour indiquer que le [post] provient d'un changement de slection dans la liste droulante. Le serveur gnrera alors l'vnement [SelectedIndexChanged] que la page pourra grer. o si on souhaite le traiter mais pas immdiatement, on fixe l'attribut [AutoPostBack] du composant serveur [DropDownList] [false]. Le serveur gnre dans ce cas, pour l'objet [DropDownList] le code HTML classique d'une liste sans fonction Javascript associe. Rien ne se passe alors lorsque l'utilisateur change la slection de la liste droulante. Cependant, lorsqu'il va valider le formulaire par un bouton [submit] par exemple, le serveur va pouvoir reconnatre qu'il y a eu un changement de slection. Nous avons en effet vu que le formulaire envoy au serveur avait un champ cach [__VIEWSTATE] reprsentant sous une forme code l'tat de tous les lments du formulaire envoy. Lorsque le serveur reoit le nouveau formulaire post par le client, il va pouvoir vrifier si la liste droulante a chang ou non d'lment slectionn. Si oui, il va gnrer l'vnement [SelectedIndexChanged] que la page pourra alors grer. Pour distinguer ce mcanisme du prcdent, certains auteurs disent que l'vnement "changement de slection" a t mis "en cache" lorsqu'il s'est produit sur le navigateur . Il ne sera trait par le serveur que lorsque le navigateur lui postera le formulaire, la suite souvent d'un clic sur un bouton [submit]. o enfin si on ne souhaite pas traiter l'vnement, on fixe l'attribut [AutoPostBack] du composant serveur [DropDownList] [false] et on n'crit pas le gestionnaire de son vnement [SelectedIndexChanged]. Une fois compris le mcanisme de traitement des vnements, le dveloppeur ne concevra pas une application web comme une application windows. En effet, si un changement de slection dans un combobox d'une application windows peut tre utilis pour changer immdiatement l'aspect du formulaire dans lequel se trouve celui-ci, on hsitera davantage traiter cet vnement immdiatement dans une application web s'il implique un "post" du formulaire au serveur donc un aller-retour rseau entre le client et le serveur. C'est pourquoi, la proprit [AutoPostBack] des composants serveur est mise [false] par dfaut. Par ailleurs, le mcanisme [AutoPostBack] qui s'appuie sur des scripts javascript gnrs automatiquement par le serveur web dans le formulaire envoy au client ne peut tre utilis que si on est sr que le navigateur client a autoris l'excution des scripts javascript sur son navigateur. Les formulaires sont donc souvent construits de la faon suivante : les composants serveur du formulaire ont leur proprit [AutoPostBack] [false] le formulaire a un ou des boutons chargs de faire le [POST] du formulaire on crit dans le code contrleur de la page, les gestionnaires des seuls vnements qu'on veut grer, le plus souvent l'vnement [Click] sur un des boutons.

1.6 Le composant TextBox1.6.1 UtilisationLa balise permet d'insrer un champ de saisie dans le code de prsentation d'une page. Nous crons une page [form4.aspx] pour obtenir la prsentation suivante : 1 2

3 4 Cette page construite avec WebMatrix a les composants suivants : n nom type proprits rle 16/192

Composants serveur - 2

1 2 3 3

TextBox1 TextBox2 lblInfo1 lblInfo2

TextBox AutoPostback=true Text= TextBox AutoPostback=false Text= Label text= Label text=

champ de saisie champ de saisie message d'information sur le contenu de [TextBox1] message d'information sur le contenu de [TextBox2]

Le code gnr par WebMatrix pour cette partie est le suivant : asp:textbox Texte 1 : Texte 2 :

Das l'onglet [Design], double-cliquons sur le composant [TextBox1]. Le squelette du gestionnaire de l'vnement [TextChanged] de cet objet est alors gnr (onglet [All]) : Sub TextBox1_TextChanged(sender As Object, e As EventArgs) End Sub ... ... ....

L'attribut [OnTextChanged="TextBox1_TextChanged"] a t ajout la balise pour dsigner le gestionnaire de l'vnement [TextChanged] sur [TextBox1]. C'est la procdure [TextBox1_Changed] que nous crivons maintenant.Sub TextBox1_TextChanged(sender As Object, e As EventArgs) ' changement de texte lblInfo1.text=Date.now.Tostring("T") + ": evt [TextChanged] 1=["+textbox1.Text+"]" End Sub

sur

[TextBox1].

Texte

Dans la procdure, nous crivons dans le label [lblInfo1] un message signalant l'vnement et indiquant le contenu de [TextBox1]. On fait de mme pour [TextBox2]. Nous indiquons galement l'heure pour mieux suivre le traitement des vnements. Le code final de [form4.aspx] est le suivant : Private Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) ' sauve la requte courante dans request.txt du dossier de la page Dim requestFileName As String = Me.MapPath(Me.TemplateSourceDirectory) + "\request.txt"

Composants serveur - 2

17/192

Me.Request.SaveAs(requestFileName, True) End Sub Sub TextBox1_TextChanged(sender As Object, e As EventArgs) ' changement de texte lblInfo1.text=Date.now.Tostring("T") + ": evt [TextChanged] sur [TextBox1]. Texte 1=["+textbox1.Text+"]" End Sub Sub TextBox2_TextChanged(sender As Object, e As EventArgs) ' changement de texte lblInfo2.text=Date.now.Tostring("T") + ": evt [TextChanged] sur [TextBox2]. Texte 2=["+textbox2.Text+"]" End Sub asp:textbox Texte 1 : Texte 2 :

Nous avons ajout la procdure [Page_Init] pour mmoriser la requte du client comme dans l'exemple prcdent.

1.6.2 TestsNous lanons l'application sous WebMatrix par [F5]. Nous obtenons la page suivante :

Le code HTML reu par le navigateur est le suivant : asp:textbox Texte 1 : Texte 2 : onchange="__doPostBack('TextBox1','')"

Il y a beaucoup de choses dans ce code qui ont gnres automatiquement par le serveur. Notons les points suivants : il y a trois champs cachs : [__VIEWSTATE] que nous avons dj rencontr, [__EventTarget] et [__EventArgument]. Ces deux derniers champs sont utiliss pour grer l'vnement navigateur "change" sur le champ de saisie [TextBox1] les balises serveur ont donn naissance aux balises HTML qui correspondent aux champs de saisie la balise serveur a donn naissance une balise ayant un attribut [onchange="__doPostBack('TextBox1','')"]. Cet attribut dit qu'en cas de changement du contenu de [TextBox1], la fonction Javascript [_doPostBack(...)] doit tre excute. Celle-ci est la suivante :

Que fait la fonction ci-dessus ? Elle affecte une valeur chacun des deux champs cachs [__EventTarget] et [__EventArgument] puis poste le formulaire. Celui-ci est donc envoy au serveur. C'est l'effet [AutoPostBack]. L'vnement navigateur "change" provoque l'excution du code "__doPostBack('TextBox1','')". On en dduit que dans le formulaire post, le champ cach [__EventTarget] aura la valeur 'TextBox1' et le champ cach [__EventArgument] la valeur ''. Cela permettra au serveur de connatre le composant qui a provoqu le POST. la balise serveur a donn naissance une balise classique parce que son attribut [AutoPostBack] n'tait pas positionn [true]. la balise indique que le formulaire sera post [form4.aspx] :

Faisons notre permier test. Tapons un texte dans le premier champ de saisie :

puis mettons le curseur dans le second champ de saisie. Aussitt, nous obtenons une nouvelle page : Composants serveur - 2

19/192

Que s'est-il pass ? Lorsque le curseur a quitt le premier champ de saisie, le navigateur a vrifi si le contenu de celui-ci avait chang. C'tait le cas. Il a donc gnr ct navigateur, l'vnement [change] sur le champ HTML [TextBox1]. Nous avons vu alors qu'une fonction Javascript s'excutait et postait le formulaire [form4.aspx]. Cette page a donc t recharge par le serveur. Les valeurs postes par le formulaire ont permis au serveur de savoir son tour que le contenu de la balise serveur [TextBox1] avait chang. La procdure [TextBox1_Changed] a donc t excute ct serveur. Elle a plac un message dans le label [lblInfo1]. Une fois cette procdure termine, [form4.aspx] a t envoye au navigateur. C'est pourquoi nous avons maintenant un texte dans [lblInfo1]. Ceci dit, on peut s'tonner d'avoir quelque chose dans le champ de saisie [TextBox1]. En effet, aucune procdure excute ct serveur n'affecte de valeur ce champ. On a l un mcanisme gnral des formulaires web ASP.NET : le serveur renvoie le formulaire dans l'tat o il l'a reu. Pour cela, il raffecte aux composants la valeur qui a t poste pour eux par le client. Pour certains composants, le client ne poste aucune valeur. C'est le cas par exemples des composants qui sont traduits en balises HTML . On se souvient que le formulaire a un champ cach [__VIEWSTATE] qui reprsente l'tat du formulaire lorsqu'il est envoy au client. Cet tat est la somme des tats de tous les composants du formulaire y compris les composants s'il y en a. Comme le champ cach [__VIEWSTATE] est post par le navigateur client, le serveur est capable de restituer l'tat prcdent de tous les composants du formulaire. Il ne lui reste plus qu' modifier ceux qui ont vu leur valeur change par le POST. Regardons maintenant dans [request.txt] la requte qui a t faite par le navigateur :POST /form4.aspx HTTP/1.1 Connection: keep-alive Keep-Alive: 300 Content-Length: 137 Content-Type: application/x-www-form-urlencoded Accept: application/x-shockwaveflash,text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,image/jpeg ,image/gif;q=0.2,*/*;q=0.1 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Accept-Encoding: gzip,deflate Accept-Language: en-us,en;q=0.5 Host: localhost Referer: http://localhost/form4.aspx User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040316 __EVENTTARGET=TextBox1&__EVENTARGUMENT=&__VIEWSTATE=dDwtMTY4MDc0MTUxOTs7PoqpeSYSCX7lCiWZvw5p7u%2B%2FOrTD&T extBox1=premier+texte&TextBox2=

On voit parfaitement le POST ainsi que les paramtres posts. Revenons notre navigateur et saisissons un texte dans le second champ de saisie :

Composants serveur - 2

20/192

Revenons sur le champ de saisie n 1 pour saisir un nouveau texte : rien ne se passe cette fois-ci. Pourquoi ? parce que le champ de saisie [TextBox2] n'ayant pas sa proprit [AutoPostBack] [true], la balise gnre pour lui ne gre pas l'vnement [Change] comme le montre son code HTML :

Aucun vnement ne se produit donc lorsqu'on quitte le champ de saisie n 2. Maintenant entrons un nouveau texte dans le champ n 1 :

Quittons le champ de saisie n 1. Aussitt l'vnement [Change] sur ce champ est dtect et le formulaire post au serveur qui renvoie en retour la page suivante :

Que s'est-il pass ? Tout d'abord, le navigateur a post le formulaire. On retrouve ce fait dans la requte du client mmorise dans [request.txt] :POST /form4.aspx HTTP/1.1 .... User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040316 __EVENTTARGET=TextBox1&__EVENTARGUMENT=&__VIEWSTATE=dDwtMTY4MDc0MTUxOTt0PDtsPGk8MT47PjtsPHQ8O2w8aTwxPjtpPD U%2BOz47bDx0PHA8cDxsPFRleHQ7PjtsPHByZW1pZXIgdGV4dGU7Pj47Pjs7Pjt0PHA8cDxsPFRleHQ7PjtsPDE4OjQyOjI5OiBldnQgW1 RleHRDaGFuZ2VkXSBzdXIgW1RleHRCb3gxXS4gVGV4dGUgMT1bcHJlbWllciB0ZXh0ZV07Pj47Pjs7Pjs%2BPjs%2BPjs%2BxLOermpUUU z5rTAa%2FFsjda6lVmo%3D&TextBox1=troisi%C3%A8me+texte&TextBox2=second+texte

Composants serveur - 2

21/192

Le serveur commence par restituer aux composants leurs valeurs prcdentes grce au champ cach [__VIEWSTATE] que le client lui a envoy. Grce aux champs posts [TextBox1] et [TextBox2] il va affecter aux composants [TextBox1] et [TextBox2] les valeurs qui lui ont t postes. C'est par ce mcanisme que le client va retrouver le formulaire tel qu'il a t post. Puis, toujours grce aux champs posts [__VIEWSTATE], [TextBox1] et [TextBox2], le serveur va dcouvrir que les valeurs des champs de saisie [TextBox1] et [TextBox2] ont chang. Il va donc gnrer les vnements [TextChanged] pour ces deux objets. Le procdures [TextBox1_TextChanged] et [TextBox2_TextChanged] vont tre excutes et les labels [labelInfo1] et [labelInfo2] recevoir une nouvelle valeur. Puis la page [form4.aspx] ainsi modifie est renvoye au client. Maintenant nous modifions de nouveau le champ de saisie n 1 :

Lorsque nous sortons le curseur de saisie du champ 1, l'vnement [Change] se produit sur le navigateur. Ensuite la squence d'vnements dj explique (post du navigateur vers le serveur, ..., envoi de la rponse du serveur) se droule. On obtient la rponse suivante :

A cause de l'heure affiche pour chacun des messages, on voit que seule la procdure [TextBox1_Changed] a t excute sur le serveur. La procdure [TextBox2_TextChanged] n'a pas t excute parce que justement la valeur de [TextBox2] n'a pas chang. Enfin, mettons un nouveau texte dans le champ n 2 :

Composants serveur - 2

22/192

Puis plaons le curseur sur le champ n 1 puis remettons-le sur le champ n 2. La page ne change pas. Pourquoi ? Parce que nous ne changeons pas la valeur du champ n 1, l'vnement navigateur [Change] ne se produit pas lorsque nous quittons ce champ. Du coup, le formulaire n'est pas post au serveur. Donc rien ne change sur la page. C'est le fait que le contenu de [lblInfo2] ne change pas qui nous montre qu'il n'y a pas de POST. S'il y en avait un, le serveur dtecterait que le contenu de [TextBox2] a chang et devrait reflter ce fait dans [lblInfo2]. On retiendra de cet exemple qu'il n'y a pas d'intrt mettre la proprit [AutoPostBack] d'un [TextBox] [true]. Cela provoque un aller-retour client-serveur inutile la majeure partie du temps.

1.6.3 Le rle du champ __VIEWSTATENous avons vu que le serveur mettait systmatiquement un champ cach appel __VIEWSTATE dans le formulaire qu'il gnrait. Nous avons dit que ce champ reprsentait l'tat du formulaire et que si on lui retournait ce champ cach, le serveur tait capable de reconstituer la valeur prcdente du formulaire. L'tat d'un formulaire est la somme des tats de ses composants. Chacun d'eux a une proprit [EnableViewState] valeur boolenne indiquant si l'tat du composant doit tre plac ou non dans le champ cach [__VIEWSATE]. Par dfaut cette proprit a la valeur [true] faisant que l'tat de tous les composants d'un formulaire est plac dans [__VIEWSTATE]. Quelquefois, ce n'est pas souhaitable. Faisons quelques expriences pour mieux comprendre le rle de la proprit [EnableViewState]. Mettons cette proprit [false] pour les deux champs de saisie :... ... ...

Excutons maintenant l'application et tapons un premier texte dans le champ n 1 avant de passer dans le champ n 2. Un POST est alors fait vers le serveur et on obtient la rponse suivante :

Tapons un texte dans le champ n 2, modifions celui du champ n 1 puis revenons dans le champ n 2 (dans cet ordre). Un nouveau POST est fait vers le serveur et nous obtenons la rponse suivante :

Composants serveur - 2

23/192

Pour l'instant, tout est comme avant. Maintenant modifions le contenu du champ n 1 puis passons dans le champ n 2. Un nouveau POST est fait. La rponse du serveur est la suivante :

Cette fois-ci, il y a un changement. Le serveur a dtect un vnement [TextChanged] sur le champ n 2 puisque l'heure de [lblInfo2] a t modifie. Or il n'y avait pas de changement. Ceci s'explique par la proprit [EnableViewState=false] de [TextBox2]. Elle fait que le serveur n'a pas mis dans le champ [__VIEWSTATE] du formulaire, l'tat prcdent de [TextBox2]. Cela revient lui affecter la chane vide comme tat prcdent. Lorsque le POST du au changement du contenu de [TextBox1] s'est produit, le serveur a compar la valeur actuelle de [TextBox2] qui tait [deux] sa valeur prcdente (la chane vide). Il a en conclu que [TextBox2] avait chang de valeur et a gnr l'vnement [TextChanged] pour [TextBox2]. On peut valider ce fonctionnement en mettant la chane vide dans [TextBox2]. D'aprs ce qui vient d'tre expliqu, le serveur ne devrait pas gnrer l'vnement [TextChanged] pour [TextBox2]. Essayons :

C'est bien ce qui s'est pass. L'heure et le contenu de [lblInfo2] montrent que la procdure [TextBox2_TextChanged] n'a pas t excute. Ceci compris, examinons la proprit [EnableViewState] des quatre composants du formulaire :TextBox1 TextBox2 lblInfo1 lblInfo2

on souhaite maintenir l'tat de ce composant afin que le serveur sache s'il a chang ou non idem on ne souhaite pas maintenir l'tat de ce composant. On veut que le texte soit recalcul chaque nouveau POST. S'il n'est pas recalcul, il doit tre vide. Tout cela est bien obtenu avec [EnableViewState=false] idem

Notre page de prsentation devient la suivante :... ... ....

Composants serveur - 2

24/192

... ...

Refaisons la mme srie de tests que prcdemment. L o nous avons obtenu l'cran

version 1

nous obtenons maintenant : version 2

Dans cette tape, on changeait le contenu du champ 1 sans changer celui du champ 2 faisant en sorte que la procdure [TextBox2_TextChanged] n'tait pas excute ct serveur ce qui impliquait que le champ [lblInfo2] ne recevait pas de nouvelle valeur. Il est donc affich avec sa valeur prcdente. Dans la version 1 [EnableViewState=true] cette valeur prcdente tait la valeur sasie. Dans la version 2 [EnableViewState=false], cette valeur prcdente est la chane vide. Il est parfois inutile de conserver l'tat prcdent des composants. Plutt que de mettre [EnableViewState=false] pour chacun d'eux on peut dclarer que la page ne doit pas maintenir son tat. Cela se fait dans la directive [Page] du code de prsentation :

Dans ce cas, quelque soit la valeur de sa proprit [EnableViewState], l'tat d'un composant n'est pas mis dans le champ cach [__VIEWSTATE]. Tout se passe alors comme si son tat prcdent tait la chane vide. Utilisons maintenant le client [curl] pour mettre en lumire d'autres mcanismes. Nous demandons tout d'abord l'url [http://localhost/form4.aspx] :dos>curl --include --url http://localhost/form4.aspx HTTP/1.1 200 OK Server: Microsoft ASP.NET Web Matrix Server/0.6.0.0 Date: Sun, 04 Apr 2004 17:51:14 GMT Cache-Control: private Content-Type: text/html; charset=utf-8 Content-Length: 1077 Connection: Close

asp:textbox Texte 1 : Texte 2 : onchange="__doPostBack('TextBox1','')"

Nous recevons du serveur le code HTML de [form4.aspx]. Il n'est pas diffrent de celui qu'avait reu le navigateur. Rappelons ici, la requte faite par le navigateur lorsqu'il postait le formulaire :POST /form4.aspx HTTP/1.1 Connection: keep-alive ... User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7b) Gecko/20040316 __EVENTTARGET=TextBox1&__EVENTARGUMENT=&__VIEWSTATE=dDwtMTY4MDc0MTUxOTs7PoqpeSYSCX7lCiWZvw5p7u%2B%2FOrTD&T extBox1=premier+texte&TextBox2=

Faisons ce mme POST mais sans envoyer le champ [__VIEWSTATE] :dos>curl --include --url http://localhost/form4.aspx --data __EVENTTARGET=TextBox1 --data __EVENTARGUMENT= --data TextBox1=premier+texte --data TextBox2= ................... Texte 1 : Texte 2 : 19:57:48: evt [TextChanged] sur [TextBox1]. Texte 1=[premier texte] ..............

On notera les points suivants : le serveur a dtect un vnement [TextChanged] sur [TextBox1] puisqu'il a gnr le texte [lblInfo1]. L'absence de [__VIEWSTATE] ne l'a pas gn. En son absence, il suppose que la valeur prcdente d'un champ de saisie est la chane vide. il a t capable de remettre le texte post pour [TextBox1] dans l'attribut [value] de la balise [TextBox1] afin que le champ [TextBox1] rapparaisse avec la valeur saisie. Pour cela, il n'a pas besoin de [__VIEWSTATE] mais seulement de la valeur poste pour [TextBox1] Maintenant, refaisons la mme requte sans rien changer. Nous obtenons la nouvelle rponse suivante :dos>curl --include --url http://localhost/form4.aspx --data __EVENTTARGET=TextBox1 --data __EVENTARGUMENT= --data TextBox1=premier+texte --data TextBox2=

Texte 1 : curl --include --url http://localhost/form4.aspx --data __EVENTTARGET=TextBox1 --data __EVENTARGUMENT= --data TextBox2=second+texte --data TextBox1= ...... Texte 1 : Texte 2 : 20:11:54: evt [TextChanged] sur [TextBox2]. Texte 2=[second texte] ......

En l'absence de [__VIEWSTATE] la valeur prcdente de [TextBox1] a t considre comme la chane vide. La valeur poste de [TextBox1] tant galement la chane vide, l'vnement [TextChanged] sur [TextBox1] n'a pas t gnr. La procdure [TextBox1_TextChanged] n'a pas t excute et donc le champ [lblInfo1] n'a pas reu de nouvelle valeur. On sait que dans ce cas, le composant garde son ancienne valeur. Or ici, ce n'est pas le cas, [lblInfo1] a perdu sa valeur prcdente. Ceci, parce que cette valeur est cherche dans [__VIEWSTATE]. Comme ce champ est absent, la chane vide a t affecte [lblInfo1]. Pour [TextBox2], le serveur a compar sa valeur poste [second texte] sa valeur prcdente. En l'absence de [__VIEWSTATE], cette valeur prcdente est gale la chaine vide. La valeur poste de [TextBox2] tant diffrente de la chane vide, l'vnement [TextChanged] sur [TextBox2] a t gnr. La procdure [TextBox2_TextChanged] a t excute et le champ [lblInfo2] a reu une nouvelle valeur. On peut se demander si les paramtres [__EVENTTARGET] et [__EVENTARGUMENT] sont bien utiles. En n'envoyant pas ces paramtres, le serveur ne saura pas par quel vnement a t provoqu le [submit]. Essayons :dos>curl --include --url http://localhost/form4.aspx --data TextBox2=second+texte --data TextBox1=premier+texte .............................. Texte 1 : Texte 2 : .....................

On voit qu'aucun vnement [TextChanged] n'a t trait. Par ailleurs, les champs posts [TextBox1] et [TextBox2] ne retrouvent pas leurs valeurs postes. Tout se passe en fait comme si on avait fait un GET. Tout redevient normal si on a le champ [__EVENTTARGET] dans les champs posts, mme s'il n'a pas de valeur :

Composants serveur - 2

27/192

dos>curl --include --url http://localhost/form4.aspx --data __EVENTTARGET= --data TextBox2=second+texte -data TextBox1=premier+texte ....... Texte 1 : Texte 2 : 20:34:14: evt [TextChanged] sur [TextBox1]. Texte 1=[premier texte] 20:34:14: evt [TextChanged] sur [TextBox2]. Texte 2=[second texte] ........

1.6.4 Autres proprits du composant TextBoxLe composant serveur [TextBox] permet galement de gnrer les balises HTML et .., c.a.d. les balises correspondant respectivement un champ de saisie protge et un champ de saisie multilignes. Cette gnration est contrle par la proprit [TextMode] du composant [TextBox]. Elle a trois valeurs possibles : valeurSingleLine MultiLine Password

balise HTML gnre ...

Composants serveur - 2

64/192

On voit que ce code est beaucoup plus important que celui reu par [Mozilla]. Nous n'entrerons pas dans les dtails. La diffrence vient du fait que le serveur a inclus des fonctions javascript dans le document HTML envoy. Pourquoi deux codes HTML diffrents alors que l'url demande par les deux navigateurs est la mme ? Nous avons eu l'occasion de dire que la technologie ASP.NET faisait que le serveur adaptait le document HTML envoy au client au niveau de ce client. Il existe sur le march diffrents navigateurs n'ayant pas toutes les mmes capacits. Les navigateurs Microsoft et Netscape par exemple, n'utilisent pas la mme modlisation objet pour le document qu'ils reoivent. Aussi le code Javascript pour manipuler ce document ct navigateur prsente-t-il des diffrences entre les deux navigateurs. De mme, les diteurs ont cr des versions successives de leur navigateur amliorant sans cesse leurs capacits. Aussi un document HTML compris par IE5 peut ne pas l'tre par IE3. Nous avons ci-dessus un exemple de cette adaptation du serveur au niveau de son client. Pour une raison qui n'a pas t approfondie ici, le serveur web a estim que le client [Mozilla] n'avait pas la capacit de grer le code javascript de validation. Aussi ce code n'a-t-il pas t plac dans le document HTML qui lui a t envoy et la validation s'est faite ct serveur. Pour [IE6], ce code javascript a t inclus dans le document HTML envoy, comme nous pouvons le voir. Pour le voir l'oeuvre, faisons l'exprience suivante : arrtons le serveur web utilisons le bouton [Envoyer] sans remplir le champ [nom] Nous obtenons la nouvelle page suivante :

C'est bien le navigateur qui a plac le message d'erreur. En effet, le serveur est arrt. On peut s'en assurer en mettant quelque chose dans le champ [nom] et en validant. Cette fois la rponse est la suivante :

Que s'est-il pass ? Le navigateur a excut le code Javascript de validation. Ce code a dit que la page tait valide. Le navigateur a donc post le formulaire au serveur web qui tait arrt. Le navigateur s'en est aperu et a affich la page ci-dessus. Si on relance le serveur, tout redevient normal. Que retenir de cet exemple ? l'intrt de la notion de composant de validation qui permet de renvoyer au client tout formulaire incorrect l'intrt du [VIEWSTATE] qui permet de renvoyer ce formulaire tel qu'il a t saisi la facult d'adaptation du serveur son client. Celui-ci est identifi par l'entte HTTP [User-Agent:] qu'il envoie au serveur. Ce n'est donc pas le serveur qui "devine" qui il a affaire. Cette facult d'adaptation prsente un grand intrt pour le dveloppeur qui n'a pas se proccuper du type de client de son application.

2.2.3 CompareValidatorNous construisons la page [comparevalidator1.aspx] suivante :

Composants serveur - 2

65/192

1 2

3 5 n 1 2 3 nomcmbChoix1 cmbChoix2 CompareValidator1

4

type DropDownList DropDownList CompareValidator

4

CompareValidator2

CompareValidator

5

btnEnvoyer

Button

proprits EnableViewState=true EnableViewState=true EnableViewState=false EnableClientScript=true ErrorMessage=Choix 1 invalide ValeurToCompare=? Operator=NotEqual Type=string EnableViewState=false EnableClientScript=true ErrorMessage=Choix 2 invalide ControlToCompare=? Operator=NotEqual Type=string EnableViewState=false CausesValidation=true

rle liste droulante liste droulante composant de validation

composant de validation

bouton [submit]

Le composant [CompareValidator] sert comparer deux valeurs entre-elles. Les oprateurs utilisables sont [Equal, NotEqual, LessThan, LessThanEqual, GreaterThan, GreaterThanEqual]. La premire valeur est fixe par la proprit [ControlToValidate], la seconde par [ValueToCompare] si la valeur prcdente doit tre compare une constante, ou par [ControlToCompare] si elle doit tre compare la valeur d'un autre composant. Les proprits importantes du composant [CompareValidator] sont les suivantes :ControlToValidate EnableClientScript ErrorMessage ValeurToCompare ControlToCompare Operator Type

champ dont le contenu doit tre contrl par le composant boolen - vrai indique que le contenu du champ prcdent doit tre contrl galement ct client le message d'erreur que le composant doit afficher en cas d'erreur dtecte valeur laquelle doit tre compare la valeur du champ [ControlToValidate] composant la valeur duquel doit tre compare la valeur du champ [ControlToValidate] oprateur de comparaison entre les deux valeurs type des valeurs comparer

Le code de prsentation de cette page est le suivant : Demande du dossier de candidature au DESS [--Options du DESS pour lesquelles vous candidatez--] Option1* Option2

Composants serveur - 2

66/192

? Automatique Informatique ? Automatique Informatique

Les contraintes de validation de la page sont les suivantes : la valeur slectionne dans [cmbChoix1] doit tre diffrente de la chane "?". Ceci implique les proprits suivantes pour le composant [CompareValidator1] : Operator=NotEqual, ValueToCompare=?, Type=string la valeur slectionne dans [cmbChoix2] doit tre diffrente de celle slectionne dans [cmbChoix1]. Ceci implique les proprits suivantes pour le composant [CompareValidator2] : Operator=NotEqual, ControlToCompare=cmbChoix1, Type=string Nous excutons cette application. Voici un exemple de page reue au cours des changes client-serveur :

Si la mme page est demande par Internet Explorer 6, du code Javascript est inclus dans celle-ci qui amne un fonctionnement lgrement diffrent. Les ventuelles erreurs sont signales ds que l'utilisateur change de valeur dans l'une des listes droulantes. C'est une amlioration du confort de l'utilisateur.

2.2.4 CustomValidator, RangeValidatorNous construisons la page [customvalidator1.aspx] suivante :

Composants serveur - 2

67/192

1 2 7 4 6

3

5 8 n1 2

nomcmbDiplomes CompareValidator2

type DropDownList CompareValidator

proprits EnableViewState=true EnableViewState=false EnableClientScript=true ErrorMessage=Diplme invalide Operator=NotEqual ValueToCompare=? Type=String EnableViewState=false

rle liste droulante composant de validation du contrle [1]

3 4

txtAutreDiplome CustomValidator1

TextBox CustomValidator

champ de saisie

EnableViewState=false composant de EnableClientScript=true validation du champ [3] ErrorMessage=Prcision diplme invalide ClientValidationFunction=chkAutreDiplome EnableViewState=false champ de saisie

5 6

txtAnDiplome RangeValidator1

TextBox RangeValidator

EnableViewState=false composant de EnableClientScript=true validation du champ [5] ErrorMessage=Anne diplme doit tre dans l'intervalle [1990,2004] MinValue=1990 MaxValue=2004 Type=Integer ControlToValidate=txtAnDiplome composant de validation du champ [5]

7

RequiredFieldValidator2

RequiredFieldValidator EnableViewState=false EnableClientScript=true ErrorMessage=Anne diplme requise ControlToValidate=txtAnDiplome Button EnableViewState=false CausesValidation=true

8

btnEnvoyer

bouton [submit]

Le champ [RangeValidator] sert vrifier que la valeur d'un contrle se trouve entre deux bornes [MinValue] et [MaxValue]. Ses proprits sont les suivantes :ControlToValidate EnableClientScript ErrorMessage MinValue MaxValue Type

champ dont la valeur doit tre contrle par le composant boolen - vrai indique que le contenu du champ prcdent doit tre contrl galement ct client le message d'erreur que le composant doit afficher en cas d'erreur dtecte valeur min de la valeur du champ contrler valeur max de la valeur du champ contrler type de la valeur du champ contrler

Le champ [CustomValidator] permet de faire des validations que ne savent pas faire les composants de validation proposs par ASP.NET. Cette validation est faite par une fonction crite par le dveloppeur. Celle-ci est excute ct serveur. Comme le Composants serveur - 2 68/192

contrle peut tre fait galement ct client, le dveloppeur peut tre amen dvelopper une fonction javascript qu'il inclura dans le document HTML. Ses proprits sont les suivantes :ControlToValidate EnableClientScript ErrorMessage ClientValidationFunction

champ dont la valeur doit tre contrle par le composant boolen - vrai indique que le contenu du champ prcdent doit tre contrl galement ct client le message d'erreur que le composant doit afficher en cas d'erreur dtecte la fonction excuter ct client

Le code de prsentation de la page est le suivant : ... Demande du dossier de candidature au DESS [--Votre dernier diplme--] Diplme* ? [Autre] Matrise DESS DEA Si [Autre], prcisez Anne d'obtention*

Composants serveur - 2

69/192

L'attribut [OnServerValidate] du composant [CustomValidator] permet de prciser la fonction charge de la valisation ct serveur. Ci-dessus le composant [CustomValidator1] fait appel la procdure [CustomValidator1_ServerValidate_1] suivante : Sub CustomValidator1_ServerValidate_1(sender As Object, e As ServerValidateEventArgs) ' le champ [txtAutreDiplome] doit tre non vide si [cmbDiplomes]=[autre] e.isvalid=not (cmbDiplomes.selecteditem.text="[Autre]" and txtAutreDiplome.text.trim="") _ and not (cmbDiplomes.selecteditem.text"[Autre]" and cmbDiplomes.selecteditem.text"?" and txtAutreDiplome.text.trim"") End Sub ....

Une fonction de validation associe un composant [CustomValidator] reoit deux paramtres : sender : objet ayant provoqu l'vnement e : l'vnement. La procdure doit positionner l'attribut [e.IsValid] vrai si les donnes vrifies sont correctes, faux sinon. Ici, les vrifications faites sont les suivantes : la liste droulante [cmbDiplomes] ne peut avoir [?] pour valeur. C'est vrifi par le composant [CompareValidator2] l'utilisateur slectionne un diplme dans la liste droulante [cmbDiplomes]. Si son diplme n'existe pas dans la liste, il a la possibilit de slectionner l'option [Autre] de la liste. Il doit alors indiquer son diplme dans le champ de saisie [txtAutreDiplome]. Si [Autre] est slectionne dans [cmbDiplomes] alors le champ [txtAutreDiplome] doit tre non vide. Si ni [Autre], ni [?] n'est slectionne dans [cmbDiplomes] alors le champ [txtAutreDiplome] doit tre vide. Ceci est vrifi par la fonction associe au composant [CustomValidator1]. l'anne d'obtention du diplme doit tre dans l'intervalle [1900-2004]. Ceci est vrifi par [RangeValidator1]. Cependant si l'utilisateur ne met rien dans le champ, la fonction de validation de [RangeValidator1] n'est pas utilise. Aussi ajoute-t-on le composant [RequiredFieldValidator2] pour vrifier la prsence d'un contenu. Ceci est une rgle gnrale. Le contenu d'un champ n'est pas vrifi si celui-ci est vide. Le seul cas o il l'est, est celui o il est associ un composant [RequiredFieldValidator]. Voici un exemple d'excution dans le navigateur [Mozilla] :

Si nous utilisons le navigateur [IE6], nous pouvons ajouter une fonction de validation ct client pour le composant [CustomValidator1]. Pour cela, ce composant a les proprits suivantes : EnableClientScript=true ClientValidationFunction=chkAutreDiplome La fonction [chkAutreDiplome ] est la suivante :

Composants serveur - 2

70/192

function chkAutreDiplome(source,args){ // vrifie la validit du champ txtAutreDiplome with(document.frmCandidature){ diplome=cmbDiplomes.options[cmbDiplomes.selectedIndex].text; args.IsValid= !(diplome=="[Autre]" && txtAutreDiplome.value=="") && ! (diplome!="[Autre]" && diplome!="?" && txtAutreDiplome.value!=""); } }

La fonction [chkAutreDiplome] reoit les mmes deux paramtres que la fonction serveur [CustomValidator1_ServerValidate_1] : source : l'objet qui a provoqu l'vnement args : l'vnement. Celui-ci a un attribut [IsValid] qui doit tre positionn vrai par la fonction si les donnes vrifies sont correctes. Une valeur faux affichera l'endroit du composant de validation le message d'erreur qui lui est associ et le formulaire ne sera pas post au serveur.

2.2.5 RegularExpressionValidatorNous construisons la page [regularexpressionvalidator1.aspx] suivante :

1 2 3

4 n1 2 3 4

nomtxtMel RequiredFieldValidator3 RegularExpressionValidator1 btnEnvoyer

type TextBox RequiredFieldValidator

proprits EnableViewState=true ControlToValidate=txtMel Display=Dynamic RegularExpressionValidator ControlToValidate=txtMel Display=Dynamic Button EnableViewState=false CausesValidation=true

rle champ de saisie composant de validation du contrle [1] composant de validation du contrle [1] bouton [submit]

Ici, nous voulons vrifier le format d'une adresse lectronique. Nous le faisons avec un composant [RegularExpressionValidator] qui permet de vrifier la validit d'un champ l'aide d'une expression rgulire. Rappelons-ici qu'une expression rgulire est un modle de chane de caractres. On vrifie donc le contenu d'un champ vis vis d'un modle. Comme le contenu d'un champ n'est pas vrifi s'il est vide, il nous faut galement un composant [RequiredFieldValidator] pour vrifier que l'adresse lectronique n'est pas vide. La classe [RegularExpressionValidator] a des proprits analogues aux classes des composants dj tudis :ControlToValidate EnableClientScript ErrorMessage RegularExpression Display

champ dont la valeur doit tre contrle par le composant boolen - vrai indique que le contenu du champ prcdent doit tre contrl galement ct client le message d'erreur que le composant doit afficher en cas d'erreur dtecte l'expression rgulire laquelle le contenu de [ControlToValidate] va tre compar mode d'affichage : Static : le champ est toujours prsent mme s'il n'affiche pas de message d'erreur, Dynamic : le champ n'est prsent que s'il y a un message d'erreur, None : le msg d'erreur n'est pas affich. Ce champ existe galement pour les autres composants mais il n'avait pas t utilis jusqu' maintenant.

L'expression rgulire modle d'une adresse lectronique pourrait tre la suivante : \s*[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+\s* Une adresse lectronique est de la forme [[email protected]...]. Il y a obligatoirement au moins un champ avant le signe @ et au moins deux champs derrire. Ces champs sont constitus de caractres alphanumriques et du signe -. Le caractre alphanumrique est reprsent par le symbole \w. La squence [\w-] signifie le caractre \w ou le caractre -. Le signe + derrire Composants serveur - 2 71/192

une squence S signifie que celle-ci peut se rpter 1 ou plusieurs fois, le signe * signifie ? qu'elle peut se rpter 0 ou plusieurs fois, le signe ? qu'elle peut se rpter 0 ou 1 fois. Un champ de l'adresse lectronique correspond au modle [\w-]+. Le fait qu'il y ait obligatoirement au moins un champ avant le signe @ et au moins deux aprs, spars par le signe . correspond au modle : [\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+. On peut laisser l'utilisateur mettre des espaces devant et aprs l'adresse. On les enlvera lors du traitement. Une suite d'espaces ventuellement vide est reprsente par le modle \s*. D'o l'expression rgulire de l'adresse lectonique : \s*[\w-]+(\.[\w]+)*@[\w-]+(\.[\w-]+)+\s*. Le code de prsentation de la page est alors le suivant : Demande du dossier de candidature au DESS [--Votre adresse lectronique o sera envoy le dossier de candidature--]

2.2.6 ValidationSummaryPour des raisons esthtiques, on peut vouloir rassembler les messages d'erreurs en un unique endroit comme dans l'exemple suivant [summaryvalidator1.aspx] o nous avons runi dans une unique page tous les exemples prcdents :

Composants serveur - 2

72/192

Tous les contrles de validation ont les proprits suivantes : [Display=Dynamic] qui fait que les contrles n'occupent pas d'espace dans la page si leur message d'erreur est vide [EnableClientScript=false] pour interdire toute validation ct client [Text=*]. Ce sera le message affich en cas d'erreur, le contenu de l'attribut [ErrorMessage] tant lui affich par le contrle [ValidationSummary] que nous prsentons ci-dessous. Cet ensemble de contrles est place dans un composant [Panel] appele [vueFormulaire]. Dans un autre composant [Panel] appel [vueErreurs], nous plaons un contrle [ValidationSummary] :

1

2

n 1 2

nomValidationSummary1

lnkErreursToFormulaire

type proprits ValidationSummary HeaderText=Les erreurs suivantes se sont produites, EnableClientScript=false, ShowSummary=true LinkButton CausesValidation=false

rle affiche les erreurs de tous les contrles de validation de la page lien de retour au formulaire

Pour le lien [lnkErreursToFormulaire], il n'y a pas lieu d'activer la validation puisque ce lien ne poste aucune valeur vrifier. Composants serveur - 2 73/192

Lorsque toutes les donnes sont valides, on prsente l'utilisateur la vue [infos] suivante :

1

n 1

nomlblInfo

type Label

proprits

rle message d'information destination de l'utilisateur

Le code de prsentation de cette page est le suivant : Demande du dossier de candidature au DESS Retour au formulaire ....

Voici quelques exemples de rsultats obtenus. Nous validons la vue [formulaire] sans saisir de valeurs :

Composants serveur - 2

74/192

Le bouton [Envoyer] nous donne la rponse suivante :

C'est la vue [erreurs] qui a t affiche. Si nous utilisons le lien de retour au formulaire, nous retrouvons celui-ci dans l'tat suivant :

Composants serveur - 2

75/192

C'est la vue [formulaire]. On remarquera le caractre [*] prs des donnes errones. C'est le champ [Text] des contrles de validation qui a t affich. Si nous remplissons correctement les champs, nous obtiendrons la vue [infos] :

Le code de contrle de la page est le suivant : ' procdure excute au chargement de la page Sub page_Load(sender As Object, e As EventArgs) ' la 1re requte, on prsente la vue [formulaire] if not ispostback then afficheVues(true,false,false) end if end sub sub afficheVues(byval formulaireVisible as boolean, _ erreursVisible as boolean, infosVisible as boolean) ' jeu de vues vueFormulaire.visible=formulaireVisible vueErreurs.visible=erreursVisible vueInfos.visible=infosVisible end sub Sub CustomValidator1_ServerValidate(sender As Object, e As ServerValidateEventArgs) ... End Sub Sub CustomValidator2_ServerValidate(sender As Object, e As ServerValidateEventArgs) ... End Sub

Composants serveur - 2

76/192

Sub CustomValidator1_ServerValidate_1(sender As Object, e As ServerValidateEventArgs) ... End Sub Sub lnkErreursToFormulaire_Click(sender As Object, e As EventArgs) ' affiche la vue formulaire afficheVues(true,false,false) ' refait les contrles de validit Page.validate End Sub Sub btnEnvoyer_Click(sender As Object, e As EventArgs) ' la page est-elle valide ? if not Page.IsValid then ' on affiche la vue [erreurs] afficheVues(false,true,false) else ' sinon la vue [infos] lblInfo.Text="Le dossier de candidature au DESS IAIE a t envoy l'adresse ["+ _ txtMel.Text + "]. Nous vous en souhaitons bonne rception.

Le secrtariat du DESS." afficheVues(false,false,true) end if end sub ...

Dans la procdure [Page_Load] excute chaque requte du client, nous affichons la vue [formulaire], les autres tant caches. Ceci est fait seulement lors de la premire requte. La procdure fait appel une procdure utilitaire [afficheVues] qui on passe trois boolens pour faire afficher ou non les trois vues. Lorsque la procdure [btnEnvoyer_Click] est appele, les vrifications de donnes ont t faites. Le bouton [btnEnvoyer] la proprit [CausesValidation=true] qui force cette vrification des donnes. Tous les contrles de validation ont t excuts et leur proprit [IsValid] positionne. Celle-ci indique si la donne vrifie par le contrle tait valide ou non. Par ailleurs, la proprit [IsValid] de la page elle-mme a t galeemnt positionne. Elle est [vrai] uniquement si la proprit [IsValid] des tous les contrles de validation de la page ont la valeur [vrai]. Ainsi la procdure [btnEnvoyer_Click] commence-t-elle par vrifier si la page est valide ou non. Si elle est invalide, on fait afficher la vue [erreurs]. Celle-ci contient le contrle [ValidationSummary] qui reprend les attributs [ErrorMessage] de tous les contrles (voir copie d'cran plus haut). Si la page est valide, c'est la vue [infos] qui est affiche avec un message d'information. La procdure [lnkErreursToFormulaire_Click] est charge de faire afficher la vue [formulaire] dans l'tat o elle a t valide. Tous les champs de saisie de la vue [formulaire] ayant la proprit [EnableViewState=true], leur tat est automatiquement rgnr. Curieusement, l'tat des composants de validation n'est lui pas restitu. On pouvait s'attendre en effet, au retour de la vue [erreurs] voir les contrles errons afficher leur champ [Text]. Ce n'est pas le cas. On a donc forc la validation des donnes en utilisant la mthode [Page.Validate] de la page. Ceci doit tre fait une fois que le panel [vueFormulaire] a t rendu visible. Il y a donc au total deux validations. Ceci serait viter dans la pratique. Ici, l'exemple nous permettait d'introduire de nouvelles notions sur la validation de page.

2.3 Composants ListControl et liaison de donnesUn certain nombre des composants serveur tudis permettent d'afficher une liste de valeurs (DropDownList, ListBox). D'autres que nous n'avons pas encore prsents permettent d'afficher plusieurs listes de valeurs dans des tables HTML. Pour tous, il est possible, par programme, d'associer une par une les valeurs des listes au composant associ. Il est possible galement d'associer des objets plus complexes ces composants tels des objets de type [Array], [ArrayList], [DataSet], [HashTable], ... ce qui simplifie le code qui associe les donnes au composant. On appelle cette association, une liaison de donnes. Tous les composants drivs de la classe [ListControl] peuvent tre associs une liste de donnes. Il s'agit des composants [DropDownList], [ListBox], [CheckButtonList], [RadioButtonList]. Chacun de ces composants peut tre li une source de donnes. Celle-ci peut tre diverse : [Array], [ArrayList], [DataTable], [DataSet], [HashTable],...., de faon gnrale un objet implmentant l'une des interfaces IEnumerable, ICollection, IListSource. Nous ne prsenterons que quelques-uns s'entre-eux. Un objet [DataSet] est un objet image d'une base de donnes relationnelles. C'est donc un ensemble de tables lies par des relations. L'objet [DataTable] reprsente une telle table. La source de donnes affecte les proprits [Text] et [Value] de chacun des membres [Item] de l'objet [ListControl]. Si T est la valeur de [Text] et V la valeur de [Value], la balise HTML gnre pour chaque lment de [ListControl] est la suivante :DropDownList, ListBox CheckButtonList RadioButtonList

T T T 77/192

Composants serveur - 2

L'association d'un composant [ListControl] une source de donnes se fait au travers des proprits suivantes :DataSource DataMember DataTextField DataValueField

une source de donnes [Array], [ArrayList], [DataTable], [DataSet], [HashTable], ... dans le cas o la source de donnes est un [DataSet], reprsente le nom de la table utiliser comme source de donnes. La vritable source de donnes est alors une table. dans le cas o la source de donnes est une table ([DataTable],[DataSet]), reprsente le nom de la colonne de la table qui va donner ses valeurs au champ [Text] des lments du [ListControl] dans le cas o la source de donnes est une table ([DataTable],[DataSet]), reprsente le nom de la colonne de la table qui va donner ses valeurs au champ [Value] des lments du [ListControl]

L'association d'un composant [ListControl] une source de donnes n'initialise pas le composant avec les valeurs de la source de donnes. C'est l'opration [ListControl].DataBind qui le fait. Selon la nature de la source de donnes, l'association de celle-ci un composant [ListControl] se fera de faon diffrente :Array A ArrayList AL DataTable DT

DataSet DS

HashTable HT

[ListControl].DataSource=A les champs [Text] et [Value] des lments de [ListControl] auront pour valeurs les lments de A [ListControl].DataSource=AL les champs [Text] et [Value] des lments de [ListControl] auront pour valeurs les lments de AL [ListControl].DataSource=DT, [ListControl].DataTextField="col1", [ListControl]. DatavalueField ="col2" o col1 et col2 sont deux colonnes de la table DT. Les champs [Text] et [Value] des lments de [ListControl] auront pour valeurs celles des colonnes col1 et col2 de la table DT [ListControl].DataSource=DS , [ListControl].DataSource="table" o "table" est le nom d'une des tables de DS. [ListControl].DataTextField="col1", [ListControl]. DatavalueField ="col2" o col1 et col2 sont deux colonnes de la table "table". Les champs [Text] et [Value] des lments de [ListControl] auront pour valeurs celles des colonnes col1 et col2 de la table "table" [ListControl].DataSource=HT , [ListControl].DataTextField="key", [ListControl]. DatavalueField ="value" o [key] et [value] sont respectivement les cls et les valeurs de HT.

Nous mettons en pratique ces informations sur l'exemple [databind1.aspx] suivant :

1

2

3

4

Composants serveur - 2

78/192

Nous avons l cinq liaisons de donnes avec chaque fois quatre contrles de type [DropDownList], [ListBox], [CheckBoxList] et [RadioButtonList]. Les cinq liaisons tudies diffrent par leurs sources de donnes : liaison source de donnes Array ArrayList DataTable DataSet HashTable

1 2 3 4 5

2.3.1 Code de prsentation des composantsLe code de prsentation des contrles de la liaison 1 est le suivant :

Celui des liaisons 2 5 est identique au numro de liaison prs.

2.3.2 Liaison une source de donnes de type ArrayLa liaison des quatre contrles [ListBox] ci-dessus se fait de la faon suivante dans la procdure [Page_Load] du code de contrle :' les donnes globales dim textes() as string={"un","deux","trois","quatre"} dim valeurs() as string={"1","2","3","4"} dim myDataListe as new ArrayList dim myDataTable as new DataTable("table1") dim myDataSet as new DataSet dim myHashTable as new HashTable ' procdure excute au chargement de la page Sub page_Load(sender As Object, e As EventArgs) if not IsPostBack then ' on cre les sources des donnes qu'on va lier aux composants createDataSources ' liaison un tableau [Array] bindToArray ' liaison une liste [ArrayList] bindToArrayList ' liaison une table [DataTable] bindToDataTable ' liaison un groupe de donnes [DataSet] bindToDataSet ' liaison un dictionnaire [HashTable] bindToHashTable end if End Sub sub createDataSources ' cre les sources de donnes qui seront lies aux composants ' arraylist dim i as integer for i=0 to textes.length-1 myDataListe.add(textes(i)) next ' datatable ' on dfinit ses deux colonnes myDataTable.Columns.Add("id",Type.GetType("System.Int32")) myDataTable.Columns.Add("texte",Type.GetType("System.String")) ' on remplit la table dim ligne as DataRow for i=0 to textes.length-1 ligne=myDataTable.NewRow

Composants serveur - 2

79/192

ligne("id")=i ligne("texte")=textes(i) myDataTable.Rows.Add(ligne) next ' dataset - une seule table myDataSet.Tables.Add(myDataTable) ' hashtable for i=0 to textes.length-1 myHashTable.add(valeurs(i),textes(i)) next end sub ' liaison tableau sub bindToArray ' l'association aux composants with DropDownList1 .DataSource=textes .DataBind end with with ListBox1 .DataSource=textes .DataBind end with with CheckBoxList1 .DataSource=textes .DataBind end with with RadioButtonList1 .DataSource=textes .DataBind end with ' la slection des lments ListBox1.Items(1).Selected=true ListBox1.Items(3).Selected=true CheckBoxList1.Items(0).Selected=true CheckBoxList1.Items(3).Selected=true DropDownList1.SelectedIndex=2 RadioButtonList1.SelectedIndex=1 end sub sub bindToArrayList .... end sub sub bindToDataTable ... end sub sub bindToDataSet ... end sub

La liaison des contrles aux donnes ne se fait ici qu' la premire requte. Ensuite les contrles garderont leurs lments par le mcanisme du [VIEWSTATE]. La liaison est faite dans la procdure [bindToArray]. La source de donnes tant de type [Array], seul le champ [DataSource] des composants [ListControl] est initialis. Le remplissage du contrle avec les valeurs de la source de donnes associe est ralise par la mthode [ListControl].DataBind. Ce n'est qu'aprs, que les objets [ListControl] ont des lments. On peut alors slectionner certains d'entre-eux.

2.3.3 Liaison une source de donnes de type ArrayListLa source de donnes [myDataListe] est initialise dans la procdure [createDataSources] :' les donnes globales dim textes() as string={"un","deux","trois","quatre"} dim myDataListe as new ArrayList .. ' procdure excute au chargement de la page Sub page_Load(sender As Object, e As EventArgs) if not IsPostBack then ' on cre les sources des donnes qu'on va lier aux composants createDataSources ... end if End Sub sub createDataSources ' cre les sources de donnes qui seront lies aux composants

Composants serveur - 2

80/192

' arraylist dim i as integer for i=0 to textes.length-1 myDataListe.add(textes(i)) next ... end sub

La liaison des quatre contrles [ListBox] de la liaison 2 se fait de la faon suivante dans la procdure [bindToArrayList] du code de contrle :' liaison arraylist sub bindToArrayList ' l'association aux composants with DropDownList2 .DataSource=myDataListe .DataBind end with with ListBox2 .DataSource=myDataListe .DataBind end with with CheckBoxList2 .DataSource=myDataListe .DataBind end with with RadioButtonList2 .DataSource=myDataListe .DataBind end with ' la slection des lments ListBox2.Items(1).Selected=true ListBox2.Items(3).Selected=true CheckBoxList2.Items(0).Selected=true CheckBoxList2.Items(3).Selected=true DropDownList2.SelectedIndex=2 RadioButtonList2.SelectedIndex=1 end sub

La source de donnes tant de type [ArrayList], seul le champ [DataSource] des composants [ListControl] est initialis.

2.3.4 Source de donnes de type DataTableLa source de donnes [myDataTable] est initialise dans la procdure [createDataSources] :' les donnes globales dim textes() as string={"un","deux","trois","quatre"} dim myDataTable as new DataTable("table1") ... ' procdure excute au chargement de la page Sub page_Load(sender As Object, e As EventArgs) if not IsPostBack then ' on cre les sources des donnes qu'on va lier aux composants createDataSources ... end if End Sub sub createDataSources ' cre les sources de donnes qui seront lies aux composants ... ' datatable ' on dfinit ses deux colonnes myDataTable.Columns.Add("id",Type.GetType("System.Int32")) myDataTable.Columns.Add("texte",Type.GetType("System.String")) ' on remplit la table dim ligne as DataRow for i=0 to textes.length-1 ligne=myDataTable.NewRow ligne("id")=i ligne("texte")=textes(i) myDataTable.Rows.Add(ligne) next ... end sub

Composants serveur - 2

81/192

On commence par construire un objet [DataTable] avec deux colonnes [id] et [texte]. La colonne [id] alimentera le champ [Value] des lments des [ListControl] et la colonne [texte] leurs champs [Text]. La construction du [DataTable] avec deux colonnes se fait de la faon suivante :myDataTable.Columns.Add("id",Type.GetType("System.Int32")) myDataTable.Columns.Add("texte",Type.GetType("System.String"))

On cre donc une table deux colonnes : la premire appele "id" est de type entier la seconde appele "texte" est de type chane de caractres La structure de la table tant cre, on peut la remplir avec le code suivant :dim ligne as DataRow for i=0 to textes.length-1 ligne=myDataTable.NewRow ligne("id")=i ligne("texte")=textes(i) myDataTable.Rows.Add(ligne) next

La colonne [id] va contenir des entiers [0,1,..,n] alors que la colonne [texte] va contenir les valeurs du tableau [data]. Ceci fait, la table [dataListe] est remplie. La liaison des quatre contrles [ListBox] de la liaison 3 se fait de la faon suivante dans la procdure [bindToDataTable] du code de contrle :' liaison datatable sub bindToDataTable ' l'association aux composants with DropDownList3 .DataSource=myDataTable .DataValueField="id" .DataTextField="texte" .DataBind end with w