pam aspnet

230
Construction d'une application à trois couches avec ASP.NET 2.0, C#, Spring.Net et NHibernate serge.tahe at istia.univ-angers.fr, juin 2010 http://tahe.developpez.com/dotnet/pam-aspnet 1/230

Upload: jean-pierre-kouame

Post on 12-Aug-2015

105 views

Category:

Documents


0 download

TRANSCRIPT

Construction d'une application trois couches avec ASP.NET 2.0, C#, Spring.Net et NHibernate

serge.tahe at istia.univ-angers.fr, juin 2010

http://tahe.developpez.com/dotnet/pam-aspnet

1/230

1

Introduction

Nous souhaitons crire une application .NET permettant un utilisateur de faire des simulations de calcul de la paie des assistantes maternelles de l'association " Maison de la petite enfance " d'une commune. Nous nous intresserons autant l'organisation du code DotNet de l'application qu'au code lui-mme. L'application finale, que nous appellerons [SimuPaie] aura la structure trois couches suivante :

Application [simupaie] 1 Utilisateur 33 - couche [ui]

Application

2

2couche [mtier]

1couche [dao]

Donnes

Spring IoC

la couche [1-dao] (dao=Data Access Object) s'occupera de l'accs aux donnes. Celles-ci seront places dans une base de donnes. la couche [2-mtier] s'occupera de l'aspect mtier de l'application, le calcul de la paie. la couche [3-ui] (ui=User Interface) s'occupera de la prsentation des donnes l'utilisateur et de l'excution de ses requtes. Nous appelons [Application] l'ensemble des modules assurant cette fonction. Elle est l'interlocuteur de l'utilisateur. les trois couches seront rendues indpendantes grce l'utilisation d'interfaces .NET l'intgration des diffrentes couches sera ralise par Spring IoC

Le traitement d'une demande d'un client se droule selon les tapes suivantes : 1. le client fait une demande l'application. 2. l'application traite cette demande. Pour ce faire, elle peut avoir besoin de l'aide de la couche [mtier] qui elle-mme peut avoir besoin de la couche [dao] si des donnes doivent tre changes avec la base de donnes. L'application reoit une rponse de la couche [mtier]. 3. selon celle-ci, elle envoie la vue (= la rponse) approprie au client. L'interface prsente l'utilisateur peut avoir diverses formes : 1. 2. 3. 4. une application console : dans ce cas, la vue est une suite de lignes de texte. une application graphique windows : dans ce cas, la vue est une fentre windows une application web : dans ce cas, la vue est une page HTML ...

Nous crirons diffrentes versions de cette application : 1. 2. 3. une version ASPNET comportant un unique formulaire et construite avec une architecture une couche. une version identique la prcdente mais avec des extensions Ajax une version ASP.NET s'appuyant sur une architecture trois couches o la couche d'accs aux donnes est implmente avec le framework NHibernate. Elle aura toujours l'unique formulaire de la version 1. 4. une version 4 ASP.NET multi-vues et mono-page avec l'architecture trois couches de la version 3. 5. la partie serveur d'une application client / serveur o le serveur est implment par un service web s'appuyant sur l'architecture en couches de la version 3. 6. la partie client de l'application client / serveur prcdente, implmente par une couche ASP.NET. 7. une version 7 ASP.NET multi-vues et multi-pages avec l'architecture trois couches de la version 3. 8. une version 8 ASP.NET multi-vues et multi-pages cliente du service web de la version 5. 9. une version 9 ASP.NET multi-vues et multi-pages avec l'architecture trois couches de la version 3 o la couche d'accs aux donnes est implmente par des classes de Spring qui facilitent l'utilisation du framework NHibernate. 10. une version 10 implmente en FLEX et cliente du service web de la version 5. Pr-requis

http://tahe.developpez.com/dotnet/pam-aspnet

2/230

Dans une chelle [dbutant-intermdiaire-avanc], ce document est dans la partie [intermdiaire]. Sa comprhension ncessite divers pr-requis qu'on pourra trouver dans certains des documents que j'ai crits : 1. 2. 3. 4. Programmation ASP.NET [http://tahe.developpez.com/dotnet/aspnet/vol1] et [http://tahe.developpez.com/dotnet/ aspnet/vol2] Langage C# 2008 : [http://tahe.developpez.com/dotnet/csharp/] : classes, interfaces, hritage, polymorphisme [Spring IoC], disponible l'url [http://tahe.developpez.com/dotnet/springioc]. Prsente les bases de l'inversion de contrle (Inversion of Control) ou injection de dpendances (Dependency Injection) du framework Spring.Net [http://www.springframework.net]. [Construction d'une application web trois couches avec Spring et VB.NET - Parties 1 et 2], disponibles aux url [http://tahe.developpez.com/dotnet/web3tier-part1] et [http://tahe.developpez.com/dotnet/web3tier-part2]. Ces deux articles prsentent une application simplifie d'achats de produits sur le web. Son architecture 3 couches implmente le modle MVC.

Des conseils de lecture sont parfois donns au dbut des paragraphes de ce document. Ils rfrencent les documents prcdents. Outils Les outils utiliss dans cette tude de cas sont librement disponibles sur le web. Ce sont les suivants :

Visual C# 2008, Visual Web Developer Express 2008, SQL Server Express 2005 disponibles l'url [http://www.microsoft.com/express/downloads/]. Spring IoC pour l'instanciation des services ncessaires l'application, disponible l'url [http://www.springframework.net/] voir galement [3] NHibernate pour la couche d'accs aux donnes du SGBD [http://sourceforge.net/projects/nhibernate/] NUnit : [http://www.nunit.org] pour les tests unitaires.

http://tahe.developpez.com/dotnet/pam-aspnet

3/230

2

Une rapide introduction ASP.NET

Nous nous proposons ici d'introduire, l'aide de quelques exemples, les concepts d'ASP.NET qui nous seront utiles dans la suite du document. Cette introduction ne permet pas de comprendre les subtilits des changes client / serveur d'une application web. Pour cela, on pourra lire :

Programmation ASP.NET [http://tahe.developpez.com/dotnet/aspnet/vol1] et [http://tahe.developpez.com/dotnet/ aspnet/vol2]

Cette introduction est faite pour ceux qui voudraient aller vite en acceptant, dans un premier temps, de laisser dans l'ombre des points qui peuvent tre importants. La suite du document permet d'approfondir ces derniers. Ceux qui connaissent ASP.NET peuvent passer directement au paragraphe 3, page 36.

2.1 Un projet exemple2.1.1 Cration du projet

2 1

3

4 5

en [1], on cre un nouveau projet avec Visual Web Developer en [2], on choisit un projet web en Visual C# en [3], on indique qu'on veut crer une application web ASP.NET en [4], on donne un nom l'application. Un dossier sera cr pour le projet avec ce nom. en [5], on indique le dossier parent du dossier [4] du projet

8 6 7

en [6], le projet cr [Default.aspx] est une page web cre par dfault. Elle contient des balises HTML et des balises ASP.NET

http://tahe.developpez.com/dotnet/pam-aspnet

4/230

[Default.aspx.cs] contient le code de gestion des vnements provoqus par l'utilisateur sur la page [Defaul.aspx] affiche dans son navigateur [Default.aspx.designer.cs] contient la liste des composants ASP.NET de la page [Default.aspx]. Chaque composant ASP.NET dpos sur la page [Default.aspx] donne naissance la dclaration de ce composant dans [Default.aspx.designer.cs]. [Web.config] est le fichier de configuration du projet ASP.NET. [References] est la liste des Dll utilises par le projet web. Ces Dll sont des bibliothques de classes que le projet est amen utiliser. En [7] la liste des Dll mises par dfaut dans les rfrences du projet. La plupart sont inutiles. Si le projet doit utiliser une Dll non liste en [7], celle-ci peut tre ajoute par [8].

2.1.2

La page [Default.aspx]

Si on excute le projet par [Ctrl-F5], la page [Default.aspx] est affiche dans un navigateur : 3 1 4 2

en [1], l'Url du projet web. Visual Web Developer a un serveur web intgr qui est lanc lorsqu'on demande l'excution d'un projet. Il coute sur un port alatoire, ici 1490. Le port d'coute est habituellement le port 80. En [1], aucune page n'est demande. Dans ce cas, c'est la page [Default.aspx] qui est affiche, d'o son nom de page par dfaut. en [2], la page [Default.aspx] est vide. dans Visual Web Developer, la page [Default.aspx] [3] peut tre construite visuellement (onglet [Design]) ou l'aide de balises (onglet [Source]) en [4], la page [Defaul.aspx] en mode [Design]. On la construit en y dposant des composants que l'on trouve dans la bote outils [5].

5

6

Le mode [Source] [6] donne accs au code source de la page :1. 2. 3. 4. 5. 6. 7. 8. 9.

http://tahe.developpez.com/dotnet/pam-aspnet

5/230

10. 11. 12. 13. 14.

la ligne 1 est une directive ASP.NET qui liste certaines proprits de la page la directive Page s'applique une page web. Il y a d'autres directives telles que Application, WebService, ... qui s'applique d'autres objets ASP.NET l'attribut CodeBehind indique le fichier qui gre les vnements de la page l'attribut Language indique le langage .NET utilis par le fichier CodeBehind l'attribut Inherits indique le nom de la classe dfinie l'intrieur du fichier CodeBehind l'attribut AutoEventWireUp="true" indique que la liaison entre un vnement dans [Default.aspx] et son gestionnaire dans [Defaul.aspx.cs] se fait par le nom de l'vnement. Ainsi l'vnement Load sur la page [Default.aspx] sera trait par la mthode Page_Load de la classe Intro._Default dfinie par l'attribut Inherits. les lignes 4-14 dcrivent la page [Defaul.aspx] l'aide de balises : Html classiques telles que la balise ou ASP.NET. Ce sont les balises qui ont l'attribut runat="server". Les balises ASP.NET sont traites par le serveur web avant envoi de la page au client. Elles sont transformes en balises Html. Le navigateur client reoit donc une page Html standard dans laquelle il n'existe plus de balises ASP.NET.

La page [Default.aspx] peut tre modifie directement partir de son code source. C'est parfois plus simple que de passer par le mode [Design]. Nous modifions le code source de la faon suivante :1. 2. 3. 4. 5. 6. Introduction ASP.NET 7. 8. 9. Introduction ASP.NET 10. 11. 12. 13. 14. 15.

En ligne 6, nous donnons un titre la page grce la balise Html . En ligne 9, nous introduisons un texte dans le corps () de la page. Si nous excutons le projet (Ctrl-F5), nous obtenons le rsultat suivant dans le navigateur :

2.1.3

Les fichiers [Default.aspx.designer.cs] et [Default.aspx.cs]

Le fichier [Default.aspx.designer.cs] dclare les composants de la page [Defaul.aspx] :1. 2. 3. 4. 5. 6. 7. 8. 9. //-----------------------------------------------------------------------------// // Ce code a t gnr par un outil. // Version du runtime :2.0.50727.3603 // // Les modifications apportes ce fichier peuvent provoquer un comportement incorrect et seront perdues si // le code est rgnr. // //------------------------------------------------------------------------------

http://tahe.developpez.com/dotnet/pam-aspnet

6/230

10. 11. namespace Intro { 12. 13. 14. public partial class _Default { 15. 16. /// 17. /// Contrle form1. 18. /// 19. /// 20. /// Champ gnr automatiquement. 21. /// Pour modifier, dplacez la dclaration de champ du fichier de concepteur dans le fichier codebehind. 22. /// 23. protected global::System.Web.UI.HtmlControls.HtmlForm form1; 24. } 25. }

On trouve dans ce fichier la liste des composants ASP.NET de la page [Default.aspx] ayant un identifiant. Ils correspondent aux balises de [Default.aspx] ayant l'attribut runat="server" et l'attribut id. Ainsi le composant de la ligne 23 ci-dessus correspond la balise

de [Default.aspx]. Le dveloppeur interagit peu avec le fichier [Default.aspx.designer.cs]. Nanmoins ce fichier est utile pour connatre la classe d'un composant particulier. Ainsi on voit ci-dessous que le composant form1 est de type HtmlForm. Le dveloppeur peut alors explorer cette classe pour en connatre les proprits et mthodes. Les composants de la page [Default.aspx] sont utiliss par la classe du fichier [Default.aspx.cs] :1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. using using using using using using System; System.Collections.Generic; System.Linq; System.Web; System.Web.UI; System.Web.UI.WebControls;

namespace Intro { public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { } } }

On notera que la classe dfinie dans les fichiers [Default.aspx.cs] et [Default.aspx.designer.cs] est la mme (ligne 10) : Intro._Default. C'est le mot cl partial qui rend possible d'tendre la dclaration d'une classe sur plusieurs fichiers, ici deux. Ligne 10, ci-dessus, on voit que la classe [_Default] tend la classe [Page] et hrite de ses vnements. L'un d'entre-eux est l'vnement Load qui se produit lorsque la page est charge par le serveur web. Ligne 12, la mthode Page_Load qui gre l'vnement Load de la page. C'est gnralement ici qu'on initialise la page avant son affichage dans le navigateur du client. Ici, la mthode Page_Load ne fait rien. La classe associe une page web, ici la classe Intro._Default, est cre au dbut de la requte du client et dtruite lorsque la rponse au client a t envoye. Elle ne peut donc servir mmoriser des informations entre deux requtes. Pour cela il faut utiliser la notion de session utilisateur.

2.2 Les vnements d'une page web ASP.NETNous construisons la page [Default.aspx] suivante :1. 2. 3. 4.

http://tahe.developpez.com/dotnet/pam-aspnet

7/230

5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42.

Introduction ASP.NET Introduction ASP.NET Nom Age Evnements traits par le serveur

Le mode [Design] de la page est le suivant :

Le fichier [Default.aspx.designer.cs] est le suivant :1. namespace Intro { 2. public partial class _Default { 3. protected global::System.Web.UI.HtmlControls.HtmlForm form1; 4. protected global::System.Web.UI.WebControls.TextBox TextBoxNom; 5. protected global::System.Web.UI.WebControls.TextBox TextBoxAge; 6. protected global::System.Web.UI.WebControls.Button ButtonValider; 7. protected global::System.Web.UI.WebControls.ListBox ListBoxEvts; 8. } 9. }

http://tahe.developpez.com/dotnet/pam-aspnet

8/230

On y retrouve tous les composants ASP.NET de la page [Default.aspx] ayant un identifiant. Nous faisons voluer le fichier [Default.aspx.cs] comme suit :1. using System; 2. 3. namespace Intro 4. { 5. public partial class _Default : System.Web.UI.Page 6. { 7. protected void Page_Init(object sender, EventArgs 8. { 9. // on note l'vnement 10. ListBoxEvts.Items.Insert(0, string.Format("{0}: DateTime.Now.ToString("hh:mm:ss"))); 11. } 12. 13. protected void Page_Load(object sender, EventArgs 14. { 15. // on note l'vnement 16. ListBoxEvts.Items.Insert(0, string.Format("{0}: DateTime.Now.ToString("hh:mm:ss"))); 17. } 18. 19. protected void ButtonValider_Click(object sender, 20. { 21. // on note l'vnement 22. ListBoxEvts.Items.Insert(0, string.Format("{0}: DateTime.Now.ToString("hh:mm:ss"))); 23. } 24. } 25. }

e) Page_Init",

e) Page_Load",

EventArgs e) ButtonValider_Click",

La classe [_Default] (ligne 5) traite trois vnements :

l'vnement Init (ligne 7) qui se produit lorsque la page a t initialise l'vnement Load (ligne 13) qui se produit lorsque la page a t charge par le serveur web. L'venement Init se produit avant l'vnement Load. l'vnement Click sur le bouton ButtonValider (ligne 19) qui se produit lorsque l'utilisateur clique sur le bouton [Valider]

La gestion de chacun de ces trois vnements consiste ajouter un message au composant Listbox nomm ListBoxEvts. Ce message affiche l'heure de l'vnement et le nom de celui-ci. Chaque message est plac en dbut de liste. Aussi les messsages placs en haut de la liste sont les plus rcents. Lorsqu'on excute le projet, on obtient la page suivante : 2

3

1

On voit en [1] que les vnements Page_Init et Page_Load se sont produits dans cet ordre. On rappelle que l'vnement le plus rcent est en haut de la liste. Lorsque le navigateur demande la page [Default.aspx] directement par son Url [2], il le fait par une commande

http://tahe.developpez.com/dotnet/pam-aspnet

9/230

HTTP (HyperText Transfer Protocol) appele GET. Une fois la page charge dans le navigateur, l'utilisateur va provoquer des vnements sur le page. Par exemple il va cliquer sur le bouton [Valider] [3]. Les vnements provoqus par l'utilisateur une fois la page charge dans le navigateur, dclenchent une requte la page [Default.aspx] mais cette fois-ci avec une commande HTTP appele POST. Pour rsumer :

le chargement initial d'une page P dans un navigateur est faite par une opration HTTP GET les vnements qui se produisent ensuite sur la page produisent chaque fois une nouvelle requte vers la mme page P mais cette fois avec une commande HTTP POST. Il est possible pour une page P de savoir si elle a t demande avec une commande GET ou une commande POST, ce qui lui permet de se comporter diffremment si c'est ncessaire, ce qui est la plupart du temps le cas.

Demande initiale d'une page ASPX : GET

Navigateur1

Serveur web

Html2

Page ASPX

en [1], le navigateur demande la page ASPX via une commande HTTP GET sans paramtres. en [2], le serveur web lui envoie en rponse le flux HTML traduction de la page ASPX demande.

Traitement d'un vnement produit sur la page affiche par le navigateur : POST

Navigateur1

Serveur web

Html2

Page ASPX

en [1], lors d'un vnement sur la page Html, le navigateur demande la page ASPX dj acquise avec une opration GET, cette fois avec une commande HTTP POST accompagne de paramtres. Ces paramtres sont les valeurs des composants qui se trouvent l'intrieur de la balise de la page HTML affiche par le navigateur. On appelle ces valeurs, les valeurs postes par le client. Elles vont tre exploites par la page ASPX pour traiter la demande du client. en [2], le serveur web lui envoie en rponse le flux HTML traduction de la page ASPX demande initialement par le POST ou bien d'une autre page s'il y a eu transfert de page ou redirection de page.

Revenons notre page exemple :

http://tahe.developpez.com/dotnet/pam-aspnet

10/230

2

3

1

4

en [2], la page a t obtenue par un GET. en [1], on voit les deux vnements qui se sont produits lors de ce GET

Si, ci-dessus, l'utilisateur clique sur le bouton [Valider] [3], la page [Default.aspx] va tre demande avec un POST. Ce POST sera accompagn de paramtres qui seront les valeurs de tous les composants inclus dans la balise de la page [Default.aspx] : les deux TextBox [TextBoxNom, TextBoxAge], le bouton [ButtonValider], la liste [ListBoxEvts]. Les valeurs poste pour les composants sont les suivantes : TextBox : la valeur saisie Button : le texte du bouton, ici le texte "Valider" Listbox : le texte du message slectionn dans le ListBox En rponse du POST, on obtient la page [4]. C'est de nouveau la page [Default.aspx]. C'est le comportement normal, moins qu'il y ait transfert ou redirection de page par les gestionnaires d'vnements de la page. On peut voir que deux nouveaux vnements se sont produits :

l'vnement Page_Load qui s'est produit lors du chargement de la page l'vnement ButtonValider_Click qui s'est produit cause du clic sur le bouton [Valider]

On peut remarquer que : l'vnement Page_Init ne s'est pas produit sur l'opration HTTP POST alors qu'il s'tait produit sur l'vnement HTTP GET l'vnement Page_Load se produit tout le temps que ce soit sur un GET ou un POST. C'est dans cette mthode qu'on a en gnral besoin de savoir si on a affaire un GET ou un POST. l'issue du POST, la page [Default.aspx] a t renvoye au client avec les modifications apportes par les gestionnaires d'vnements. C'est toujours ainsi. Une fois les vnements d'une page P traits, cette mme page P est renvoye au client. Il y a deux faons d'chapper cette rgle. Le dernier gestionnaire d'vnement excut peut transfrer le flux d'excution une autre page P2. rediriger le navigateur client vers une autre page P2. Dans les deux cas, c'est la page P2 qui est renvoye au navigateur. Les deux mthodes prsentent des diffrences sur lesquelles nous reviendrons. l'vnement ButtonValider_Click s'est produit aprs l'vnement Page_Load. C'est donc ce gestionnaire qui peut prendre la dcision du transfert ou de la redirection vers une page P2. la liste des vnements [4] a gard les deux vnements affichs lors du chargement initial GET de la page [Default.aspx]. C'est surprenant lorsqu'on sait que la page [Default.aspx] a t recre lors du POST. On devrait retrouver la page [Default.aspx] avec ses valeurs de conception avec donc un ListBox vide. L'excution des gestionnaires Page_Load et ButtonValider_Click devrait y mettre ensuite deux messages. Or on en trouve quatre. C'est le mcanisme du VIEWSTATE qui explique cela. Lors du GET initial, le serveur web envoie la page [Default.aspx] avec une balise HTML appel champ cach (ligne 10 ci-dessous).1. 2. 3. 4. Introduction ASP.NET 5.

http://tahe.developpez.com/dotnet/pam-aspnet

11/230

6. 7. Introduction ASP.NET 8. 9. 10. 11. 12. ..............................

Dans le champ d'id "__VIEWSTATE" le serveur web met sous forme code la valeur de tous les composants de la page. Il le fait aussi bien sur le GET initial que sur les POST qui suivent. Lorsqu'un POST sur une page P se produit :

le navigateur demande la page P en envoyant dans sa requte les valeurs de tous les composants qui sont l'intrieur de la balise . Ci-dessus, on peut voir que le composant "__VIEWSTATE" est l'intrieur de la balise . Sa valeur est donc envoye au serveur lors d'un POST. la page P est instancie et initialise avec ses valeurs de construction le composant "__VIEWSTATE" est utilis pour redonner aux composants la valeurs qu'ils avaient lorsque la page P avait t envoye prcdemment. C'est ainsi par exemple, que la liste des vnements [4] retrouve les deux premiers messages qu'elle avait lorsqu'elle a t envoye en rponse au GET initial du navigateur. les composants de la page P prennent ensuite les valeurs postes par le navigateur. A ce moment l, le formulaire de la page P est dans l'tat o l'utilisateur l'a post. l'vnement Page_Load est trait. Ici il rajoute un message la liste des vnements[4]. l'vnement qui a provoqu le POST est trait. Ici ButtonValider_Click rajoute un message la liste des vnements[4]. la page P est renvoye. Les composants ont pour valeur : soit la valeur poste, c.a.d. la valeur que le composant avait dans le formulaire lorsque celui a t post au serveur soit une valeur donne par l'un des gestionnaires d'vnements. Dans notre exemple, les deux composants TextBox retrouveront leur valeur poste car les gestionnaires d'vnements n'y touchent pas la liste des vnements [4] retrouve sa valeur poste, c.a.d. tous les vnements dj inscrits dans la liste, plus deux nouveaux vnements crs par les mthodes Page_Load et ButtonValider_Click.

Le mcanisme du VIEWSTATE peut tre activ ou inhib au niveau de chaque composant. Inhibons-le pour le composant [ListBoxEvts] :

2

1 3

en [1], le VIEWSTATE du composant [ListBoxEvts] est inhib. Celui des TextBox [2] est activ par dfaut. en [3], les deux vnements renvoys aprs le GET initial

http://tahe.developpez.com/dotnet/pam-aspnet

12/230

6 7 4

5

8

en [4], on a rempli le formulaire et on clique sur le bouton [Valider]. Un POST vers la page [Default.aspx] va tre fait. en [6], le rsultat renvoy aprs un Clic sur le bouton [Valider] le mcanisme du VIEWSTATE activ explique que les TextBox [7] aient gard leur valeur poste en [4] le mcanisme du VIEWSTATE inhib explique que le composant [ListBoxEvts] [8] n'ait pas gard son contenu [5].

2.3 Gestion des valeurs postesNous allons nous intresser ici aux valeurs postes par les deux TextBox lorsque l'utilisateur clique sur le bouton [Valider]. La page [Default.aspx] en mode [Design] volue comme suit :

2

1

Le code source de l'lment rajout en [1] est le suivant :1. 2. Elments posts au serveur : 3. 4.

Nous utiliserons le composant [LabelPost] pour afficher les valeurs saisies dans les deux TextBox [2]. Le code du gestionnaire d'vnements [Default.aspx.cs] volue comme suit :1. using System; 2.

http://tahe.developpez.com/dotnet/pam-aspnet

13/230

3. namespace Intro 4. { 5. public partial class _Default : System.Web.UI.Page 6. { 7. protected void Page_Init(object sender, EventArgs e) 8. { 9. // on note l'vnement 10. ListBoxEvts.Items.Insert(0, string.Format("{0}: Page_Init", DateTime.Now.ToString("hh:mm:ss"))); 11. } 12. 13. protected void Page_Load(object sender, EventArgs e) 14. { 15. // on note l'vnement 16. ListBoxEvts.Items.Insert(0, string.Format("{0}: Page_Load", DateTime.Now.ToString("hh:mm:ss"))); 17. } 18. 19. protected void ButtonValider_Click(object sender, EventArgs e) 20. { 21. // on note l'vnement 22. ListBoxEvts.Items.Insert(0, string.Format("{0}: ButtonValider_Click", DateTime.Now.ToString("hh:mm:ss"))); 23. // on affiche le nom et l'ge 24. LabelPost.Text = string.Format("nom={0}, age={1}", TextBoxNom.Text.Trim(), TextBoxAge.Text.Trim()); 25. } 26. } 27. }

Ligne 24, on met jour le composant LabelPost :

LabelPost est de type [System.Web.UI.WebControls.Label] (cf Default.aspx.designer.cs). Sa proprit Text reprsente le texte affich par le composant. TextBoxNom et TextBoxAge sont de type [System.Web.UI.WebControls.TextBox]. La proprit Text d'un composant TextBox est le texte affich dans la zone de saisie. la mthode Trim() limine les espaces qui peuvent prcder ou suivre une chane de caractres

Comme il a t expliqu prcdemment, lorsque la mthode ButtonValider_Click est excute, les composants de la page ont la valeur qu'ils avaient lorsque la page a t poste par l'utilisateur. Les proprits Text des deux TextBox ont donc pour valeur les textes saisis par l'utilisateur dans le navigateur. Voici un exemple :

2

3 1

4

5

en [1], les valeurs postes en [2], la rponse du serveur. en [3], les TextBox ont retrouv leur valeur poste par le mcanisme du VIEWSTATE activ

http://tahe.developpez.com/dotnet/pam-aspnet

14/230

en [4], les messages du composant ListBoxEvts sont issus des mthodes Page_Init, Page_Load, ButtonValider_Click et d'un VIEWSTATE inhib en [5], le composant LabelPost a obtenu sa valeur par la mthode ButtonValider_Click. On a bien rcupr les deux valeurs saisies par l'utilisateur dans les deux TextBox [1].

On voit ci-dessus que la valeur poste pour l'ge est la chane "yy", une valeur illgale. Nous allons rajouter la page des composants appels validateurs. Ils servent vrifier la validit de donnes postes. Cette validit peut tre vrifie deux endroits :

sur le client. Une option de configuration du validateur permet de demander ou non que les tests soient faits sur le navigateur. Ils sont alors faits par du code JavaScript embarqu dans la page Html. Lorsque l'utilisateur fait un POST des valeurs saisies dans le formulaire, celles-ci sont tout d'abord vrifies par le code Javascript. Si un des tests choue, le POST n'est pas effectu. On vite ainsi un aller-retour avec le serveur rendant ainsi la page plus ractive. sur le serveur. Si les tests ct client peuvent tre facultatifs, ct serveur ils sont obligatoires qu'il y ait eu vrification ou non ct client. En effet, lorsqu'une page reoit des valeurs postes, elle n'a pas possibilit de savoir si elles ont t vrifies par le client avant leur envoi. Ct serveur, le dveloppeur doit donc toujours vrifier la validit des donnes postes.

La page [Default.aspx] volue comme suit :1. 2. 3. 4. 5. 6. Introduction ASP.NET 7. 8. 9. Introduction ASP.NET 10. 11. 12. 13. 14. 15. Nom 16. 17. 18. 19. 20. 23. 24. 25. 26. 27. Age 28. 29. 30. 31. 32. 35. 39. 40. 41. 42. 43. 45. 46. 47. Evnements traits par le serveur 48. 49. 50. 51.

http://tahe.developpez.com/dotnet/pam-aspnet

15/230

52. 53. Elments posts au serveur : 54. 55. 56. 57. Elments valids par le serveur : 58. 59. 60. 61. 62. 63.

Les validateurs ont t rajouts aux lignes 20, 32 et 35. Ligne 58, un composant Label est utilis pour afficher les valeurs postes valides. Ligne 60, un un composant Label est utilis pour afficher un message d'erreur s'il y a des erreurs de saisie. La page [Default.aspx] en mode [Design] est la suivante :

1

4

2

3

les composants [1] et [2] sont de type RequiredFieldValidator. Ce validateur vrifie qu'un champ de saisie est non vide. le composant [3] est de type RangeValidator. Ce validateur vrifie qu'un champ de saisie contient une valeur entre deux bornes. en [4], les proprits du validateur [1].

Nous allons prsenter les deux types de validateurs au travers de leurs balises dans le code de la page [Default.aspx] :

ID : l'identifiant du composant ControlToValidate : le nom du composant dont la valeur est vrifie. Ici on veut que le composant TextBoxNom n'ait pas une valeur vide (chane vide ou suite d'espaces) ErrorMessage : message d'erreur afficher dans le validateur en cas de donne invalide. EnableClientScript : boolen indiquant si le validateur doit tre excut galement ct client. Cet attribut a la valeur True par dfaut lorsqu'il n'est pas explicitement positionn comme ci-dessus. Display : mode d'affichage du validateur. Il y a deux modes : static (dfaut) : le validateur occupe de la place sur la page mme s'il n'affiche pas de message d'erreur dynamic : le validateur n'occupe pas de place sur la page s'il n'affiche pas de message d'erreur.

http://tahe.developpez.com/dotnet/pam-aspnet

16/230

Type : le type de la donne vrifie. Ici l'ge est un entier. MinimumValue, MaximumValue : les bornes dans lesquelles doit se trouver la valeur vrifie

La configuration du composant qui provoque le POST joue un rle dans le mode de validation. Ici ce composant est le bouton [Valider] : Text="Valider"

CausesValidation : fixe le mode automatique ou nom des validations ct serveur. Cet attribut a la valeur par dfaut "True" s'il n'est pas explicitement mentionn. Dans ce cas, ct client, les validateurs ayant EnableClientScript True sont excuts. Le POST n'a lieu que si tous les validateurs ct client russissent. ct serveur, tous les validateurs prsents sur la page sont automatiquement excuts avant le traitement de l'vnement qui a provoqu le POST. Ici, ils seraient excuts avant l'excution de la mthode ButtonValider_Click. Dans cette mthode, il est possible de savoir si toutes les validations ont russi ou non. Page.IsValid est "True" si elles ont toutes russi, "False" sinon. Dans ce dernier cas, on peut arrter le traitement de l'vnement qui a provoqu le POST. La page poste est renvoye telle qu'elle a t saisie. Les validateurs ayant chou affichent alors leur message d'erreur (attribut ErrorMessage). Si CausesValidation a la valeur False, alors ct client, aucun validateur n'est excut ct serveur, c'est au dveloppeur de demander lui-mme l'excution des validateurs de la page. Il le fait avec la mthode Page.Validate(). Selon le rsultat des validations, cette mthode positionne la proprit Page.IsValid "True" ou "False".

Dans [Default.aspx.cs] le code de traitement de ButtonValider_Click volue comme suit :1. protected void ButtonValider_Click(object sender, EventArgs e) 2. { 3. // on note l'vnement 4. ListBoxEvts.Items.Insert(0, string.Format("{0}: ButtonValider_Click", DateTime.Now.ToString("hh:mm:ss"))); 5. // on affiche le nom et l'ge 6. LabelPost.Text = string.Format("nom={0}, age={1}", TextBoxNom.Text.Trim(), TextBoxAge.Text.Trim()); 7. // la page est-elle valide ? 8. Page.Validate(); 9. if (!Page.IsValid) 10. { 11. // msg d'erreur global 12. LabelErreursSaisie.Text = "Veuillez corriger les erreurs de saisie..."; 13. LabelErreursSaisie.Visible = true; 14. return; 15. } 16. // on cache le msg d'erreur 17. LabelErreursSaisie.Visible = false; 18. // on affiche le nom et l'ge valids 19. LabelValidation.Text = string.Format("nom={0}, age={1}", TextBoxNom.Text.Trim(), TextBoxAge.Text.Trim()); 20. }

Dans le cas o le bouton [Valider] a son attribut CausesValidation True et les validateurs leur attribut EnableClientScript True, la mthode ButtonValider_Click n'est excute que lorsque les valeurs postes sont valides. On peut se demander alors le sens du code que l'on trouve partir de la ligne 8. Il faut se rappeler qu'il est toujours possible d'crire un client programm qui poste des valeurs non vrifies la page [Default.aspx]. Donc celle-ci doit toujours refaire les tests de validit.

ligne 8 : lance l'excution de tous les validateurs de la page. Dans le cas o le bouton [Valider] a son attribut CausesValidation True, ceci est fait automatiquement et il n'y a pas lieu de le refaire. Il y a ici redondance. lignes 9-15 : cas o l'un des validateurs a chou lignes 16-19 : cas o tous les validateurs ont russi

Voici deux exemples d'excution :

http://tahe.developpez.com/dotnet/pam-aspnet

17/230

1

4

2

5

3

6

7

en [1], un exemple d'excution dans le cas o : le bouton [Valider] a sa proprit CausesValidation True les validateurs ont leur proprit EnableClientScript True Les messages d'erreurs [2] ont t affichs par les validateurs excuts ct client par le code Javascript de la page. Il n'y a pas eu de POST vers le serveur comme le montre le label des lments posts [3]. en [4], un exemple d'excution dans le cas o : le bouton [Valider] a sa proprit CausesValidation False les validateurs ont leur proprit EnableClientScript False Les messages d'erreurs [5] ont t affichs par les validateurs excuts ct serveur. Comme le montre [6], il y a bien eu un POST vers le serveur. En [7], le message d'erreur affich par la mthode [ButtonValider_Click] dans le cas d'erreurs de saisie.

8

9 10

en [8] un exemple obtenu avec des donnes valides. [9,10] montrent que les lments posts ont t valids. Lorsqu'on fait des tests rpts, il faut mettre False la proprit EnableViewState du label [LabelValidation] afin que le message de validation ne reste pas affich au fil des excutions.

http://tahe.developpez.com/dotnet/pam-aspnet

18/230

2.4 Gestion des donnes de porte ApplicationRevenons sur l'architecture d'excution d'une page ASPX :

Navigateur1

Serveur web

Html2

Page ASPX

La classe de la page ASPX est instancie au dbut de la requte du client et dtruite la la fin de celle-ci. Aussi elle ne peut servir mmoriser des donnes entre deux requtes. On peut vouloir mmoriser deux types de donnes :

des donnes partages par tous les utilisateurs de l'application web. Ce sont en gnral des donnes en lecture seule. Trois fichiers sont utiliss pour mettre en oeuvre ce partage de donnes : [Web.Config] : le fichier de configuration de l'application [Global.asax, Global.asax.cs] : permettent de dfinir une classe, appele classe globale d'application, dont la dure de vie est celle de l'application, ainsi que des gestionnaires pour certains vnements de cette mme application. La classe globale d'application permet de dfinir des donnes qui seront disponibles pour toutes les requtes de tous les utilisateurs. des donnes partages par les requtes d'un mme client. Ces donnes sont mmorises dans un objet appele Session. On parle alors de session client pour dsigner la mmoire du client. Toutes les requtes d'un client ont accs cette session. Elles peuvent y stocker et y lire des informations

Navigateur1

Serveur web

Mmoire Application Mmoire Session

Html2

Page ASPX

Ci-dessus, nous montrons les types de mmoire auxquels a accs une page ASPX : la mmoire de l'application qui contient la plupart du temps des donnes en lecture seule et qui est accessible tous les utilisateurs. la mmoire d'un utilisateur particulier, ou session, qui contient des donnes en lecture / criture et qui est accessible aux requtes successives d'un mme utilisateur. non reprsente ci-dessus, il existe une mmoire de requte, ou contexte de requte. La requte d'un utilisateur peut tre traite par plusieurs pages ASPX successives. Le contexte de la requte permet une page 1 de transmettre de l'information une page 2. Nous nous intressons ici aux donnes de porte Application, celles qui sont partages par tous les utilisateurs. La classe globale de l'application peut tre cre comme suit :

http://tahe.developpez.com/dotnet/pam-aspnet

19/230

2 1

3

en [1], on ajoute un nouvel lment au projet en [2], on ajoute la classe d'application globale en [3], on garde le nom par dfaut [Global.asax] pour le nouvel lment

5

4

en [4], deux nouveaux fichiers ont t ajouts au projet en [5], on affiche le balisage de [Global.asax]

la balise Application remplace la balise Page qu'on avait pour [Default.aspx]. Elle identifie la classe d'application globale Codebehind : dfinit le fichier dans lequel est dfinie la classe d'application globale Inherits : dfinit le nom de cette classe

La classe Intro.Global gnre est la suivante :1. using System; 2. 3. namespace Intro 4. { 5. public class Global : System.Web.HttpApplication 6. { 7. 8. protected void Application_Start(object sender, EventArgs e) 9. { 10.

http://tahe.developpez.com/dotnet/pam-aspnet

20/230

11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. } 43. }

} protected void Session_Start(object sender, EventArgs e) { } protected void Application_BeginRequest(object sender, EventArgs e) { } protected void Application_AuthenticateRequest(object sender, EventArgs e) { } protected void Application_Error(object sender, EventArgs e) { } protected void Session_End(object sender, EventArgs e) { } protected void Application_End(object sender, EventArgs e) { }

ligne 5 : la classe globale d'application drive de la classe HttpApplication

La classe est gnre avec des squelettes de gestionnaires d'vnements de l'application :

lignes 8, 38 : grent les vnements Application_Start (dmarrage de l'application) et Application_End (fin de l'application lorsque le serveur web s'arrte ou lorsque l'administrateur dcharge l'application) lignes 13, 33 : grent les vnements Session_Start (dmarrage d'une nouvelle session client l'arrive d'un nouveau client ou l'expiration d'une session existante) et Session_End (fin d'une session client soit explicitement par programmation soit implicitement par dpassement de la dure autorise pour une session). ligne 28 : gre l'vnement Application_Error (apparition d'une exception non gre par le code de l'application et remonte jusqu'au serveur) ligne 18 : gre l'vnement Application_BeginRequest (arrive d'une nouvelle requte). ligne 23 : gre l'vnement Application_AuhenticateRequest (se produit lorsqu'un utilisateur s'est authentifi).

La mthode [Application_Start] est souvent utilise pour initialiser l'application partir d'informations contenues dans [Web.Config]. Celui gnr la cration initiale d'un projet a l'allure suivante : ... ... ....

http://tahe.developpez.com/dotnet/pam-aspnet

21/230

... ....

Pour notre application actuelle, ce fichier est inutile. Si on le supprime ou le renomme, l'application continue fonctionner normalement. Nous allons nous intresser aux balises des lignes 8 et 9 :

permet de dfinir un dictionnaire d'informations permet de dfinir des chanes de connexion des bases de donnes

Considrons le fichier [Web.config] suivant :1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. ... ...

Ce fichier peut tre exploit par la classe globale d'application suivante :1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. using System; using System.Configuration; namespace Intro { public class Global : System.Web.HttpApplication { public static string Param1 { get; set; } public static string Param2 { get; set; } public static string ConnString1 { get; set; } public static string Erreur { get; set; } protected void Application_Start(object sender, EventArgs e) { try { Param1 = ConfigurationManager.AppSettings["cle1"]; Param2 = ConfigurationManager.AppSettings["cle2"]; ConnString1 = ConfigurationManager.ConnectionStrings["conn1"].ConnectionString; } catch (Exception ex) { Erreur = string.Format("Erreur de configuration : {0}", ex.Message); } } protected void Session_Start(object sender, EventArgs e) { } } }

lignes 8-11 : quatre proprits statiques P. Comme la dure de vie de la classe Global est celle de l'application, toute requte faite l'application aura accs ces proprits P via la syntaxe Global.P.

http://tahe.developpez.com/dotnet/pam-aspnet

22/230

lignes 17-19 : le fichier [Web.config] est accessible via la classe [System.Configuration.ConfigurationManager] lignes 17-18 : rcupre les lments de la balise du fichier [Web.config] via l'attribut key. ligne 19 : rcupre les lments de la balise du fichier [Web.config] via l'attribut name.

Les attributs statiques des lignes 8-11 sont accessibles de n'importe quel gestionnaire d'vnement des pages ASPX charges. Nous les utilisons dans le gestionnaire [Page_Load] de la page [Default.aspx] :1. 2. 3. 4. 5. 6. 7. protected void Page_Load(object sender, EventArgs e) { // on note l'vnement ListBoxEvts.Items.Insert(0, string.Format("{0}: Page_Load", DateTime.Now.ToString("hh:mm:ss"))); // on rcupre les informations de la classe globale d'application LabelGlobal.Text = string.Format("Param1={0},Param2={1},ConnString1={2},Erreur={3}", Global.Param1, Global.Param2, Global.ConnString1, Global.Erreur); }

ligne 6 : les quatre attributs statiques de la classe globale d'application sont utiliss pour alimenter un nouveau label de la page [Default.aspx]

A l'excution, nous obtenons le rsultat suivant :

http://tahe.developpez.com/dotnet/pam-aspnet

23/230

Ci-dessus, nous voyons que les paramtres de [web.config] ont t correctement rcuprs. La classe globale d'application est le bon endroit pour stocker des informations partages par tous les utilisateurs.

2.5 Gestion des donnes de porte SessionNous nous intressons ici la faon de mmoriser des informations au fil des requtes d'un utilisateur donn :

Navigateur1

Serveur web

Mmoire Application Mmoire Utilisateur 1 Mmoire Utilisateur 2

Html2

Page ASPX

Chaque utilisateur a sa propre mmoire qu'on appelle sa session. Nous avons vu que la classe d'application globale disposait de deux gestionnaires pour grer les vnements :

Session_Start : dbut d'une session Session_end : fin d'une session

Le mcanisme de la session est mis en oeuvre de la faon suivante :

lors de la premire requte d'un utilisateur, le serveur web cre un jeton de session qu'il attribue l'utilisateur. Ce jeton est une suite de caractres unique pour chaque utilisateur. Il est envoy par le serveur dans la rponse faite la premire requte de l'utilisateur. lors des requtes suivantes, l'utilisateur (le navigateur web) inclut dans sa requte le jeton de session qu'on lui a attribu. Aussi le serveur web est-il capable de le reconnatre. une session a une dure de vie. Lorsque le serveur web reoit une requte d'un utilisateur, il calcule le temps qui s'est coul depuis la requte prcdente. Si ce temps dpasse la dure de vie de la session, une nouvelle session est cre pour l'utilisateur. Les donnes de la prcdente session sont perdues. Avec le serveur web IIS (Internet Information Server) de Microsoft, les sessions ont par dfaut une dure de vie de 20 mn. Cette valeur peut tre change par l'administrateur du serveur web. le serveur web sait qu'il a affaire la premire requte d'un utilisateur parce que cette requte ne comporte pas de jeton de session. C'est la seule.

http://tahe.developpez.com/dotnet/pam-aspnet

24/230

Toute page ASP.NET a accs la session de l'utilisateur via la proprit Session de la page, de type [System.Web.SessionState.HttpSessionState]. Nous utiliserons les proprits P et mthodes M suivantes de la classe HttpSessionState : Nom Item[String cl] Clear Abandon P M M Type Rle La session peut tre construite comme un dictionnaire. Item[cl] est l'lment de la session identifi par cl. Au lieu d'crire [HttpSessionState].Item[cl], on peut galement crire [HttpSessionState].[cl]. vide le dictionnaire de la session termine la session. La session n'est alors plus valide. Une nouvelle session dmarrera avec la prochaine requte de l'utilisateur.

Comme exemple de mmoire utilisateur, nous allons compter le nombre de fois qu'un utilisateur clique sur le bouton [Valider]. Pour obtenir ce rsultat, il faut maintenir un compteur dans la session de l'utilisateur. La page [Default.aspx] volue comme suit :

La classe globale d'application [Global.asax.cs] volue comme suit :1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. using System; using System.Configuration; namespace Intro { public class Global : System.Web.HttpApplication { public static string Param1 { get; set; } ... protected void Application_Start(object sender, EventArgs e) { } protected void Session_Start(object sender, EventArgs e) { // compteur de requtes Session["nbRequtes"] = 0; }

...

http://tahe.developpez.com/dotnet/pam-aspnet

25/230

22. } 23. }

Ligne 19, on utilise la session de l'utilisateur pour y stocker un compteur de requtes identifi par la cl "nbRequtes". Ce compteur est mis jour par le gestionnaire [ButtonValider_Click] de la page [Default.aspx] :1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. using System; namespace Intro { public partial class _Default : System.Web.UI.Page { .... protected void ButtonValider_Click(object sender, EventArgs e) { // on note l'vnement ListBoxEvts.Items.Insert(0, string.Format("{0}: ButtonValider_Click", DateTime.Now.ToString("hh:mm:ss"))); // on affiche le nom et l'ge posts LabelPost.Text = string.Format("nom={0}, age={1}", TextBoxNom.Text.Trim(), TextBoxAge.Text.Trim()); // nombre de requtes Session["nbRequtes"] = (int)Session["nbRequtes"] + 1; LabelNbRequetes.Text = Session["nbRequtes"].ToString(); // la page est-elle valide ? Page.Validate(); if (!Page.IsValid) { ... } ... } } }

ligne 16 : on incrmente le compteur de requtes ligne 17 : le compteur est affich sur la page

Voici un exemple d'excution :

http://tahe.developpez.com/dotnet/pam-aspnet

26/230

2.6 Gestion du GET / POST dans le chargement d'une pageNous avons dit qu'il y avait deux types de requtes vers une page ASPX : la requte initiale du navigateur faite avec une commande HTTP GET. Le serveur rpond en envoyant la page demande. Nous supposerons que cette page est un formulaire, c.a.d. que dans la page ASPX envoye, il y a une balise . les requtes suivantes faites par le navigateur en raction certaines actions de l'utilisateur sur le formulaire. Le navigateur fait alors une requte HTTP POST. Que ce soit sur une demande GET ou une demande POST, la mthode [Page_Load] est excute. Lors du GET, cette mthode est habituellement utilise pour initialiser la page envoye au navigateur client. Ensuite, par le mcanisme du VIEWSTATE, la page reste initialise et n'est modifie que par les gestionnaires des vnements qui provoquent les POST. Il n'y a pas lieu de rinitialiser la page dans Page_Load. D'o le besoin pour cette mthode de savoir si la requte du client est un GET ou un POST. Examinons l'exemple suivant. On ajoute une liste droulante la page [Default.aspx]. Le contenu de cette liste sera dfini dans le gestionnaire Page_Load de la requte GET :

La liste droulante est dclare dans [Default.aspx.designer.cs] de la faon suivante :protected global::System.Web.UI.WebControls.DropDownList DropDownListNoms;

Nous utiliserons les mthodes M et proprits P suivantes de la classe [DropDownList] : Nom Items SelectedItem Type P P Rle la collection de type ListItemCollection des lments de type ListItem de la liste droulante l'index, partant de 0, de l'lment slectionn dans la liste droulante lorsque le formulaire est post l'lment de type ListItem slectionn dans la liste droulante lorsque le formulaire est post la valeur de type string de l'lment de type ListItem slectionn dans la liste droulante lorsque le formulaire est post. Nous allons dfinir prochainement cette notion de valeur.

SelectedIndex P SelectedValue P

La classe ListItem des lments d'une liste droulante sert gnrer les balises de la balise Html :1. 2. texte1 3. texte2 4. .... 5.

Dans la balise textei est le texte affich dans la liste droulante vali est la valeur poste par le navigateur si textei est le texte slectionn dans la liste droulante Chaque option peut tre gnre par un objet LisItem construit l'aide du constructeur ListItem(string texte, string valeur). Dans [Default.aspx.cs], le code du gestionnaire [Page_Load] volue comme suit :1. 2. 3. protected void Page_Load(object sender, EventArgs e) { // on note l'vnement

http://tahe.developpez.com/dotnet/pam-aspnet

27/230

4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. }

... // on rcupre les informations de la classe globale d'application ... // initialisation du combo des noms uniquement lors du GET initial if (!IsPostBack) { for (int i = 0; i < 3; i++) { DropDownListNoms.Items.Add(new ListItem("nom"+i,i.ToString())); } }

ligne 8 : la classe Page a un attribut IsPostBack de type boolen. A vrai, il signifie que la requte de l'utilisateur est un POST. Les lignes 10-13 ne sont donc excutes que sur le GET initial du client. ligne 12 : on ajoute la liste [DropDownListNoms], un lment de type ListItem(string texte, string value). Le texte affich pour le (i+1)me lment sera nomi et la valeur poste pour cet lment s'il est slectionn sera i.

Le gestionnaire [ButtonValider_Click] est modifi afin d'afficher la valeur poste par la liste droulante :1. protected void ButtonValider_Click(object sender, EventArgs e) 2. { 3. // on note l'vnement 4. ... 5. // on affiche les valeurs postes 6. LabelPost.Text = string.Format("nom={0}, age={1}, combo={2}", TextBoxNom.Text.Trim(), TextBoxAge.Text.Trim(), DropDownListNoms.SelectedValue); 7. // nombre de requtes 8. ... 9. }

Ligne 6, la valeur poste pour la liste [DropDownListNoms] est obtenue avec la proprit SelectedValue de la liste. Voici un exemple d'excution :

1 2

4 3

en [1], le contenu de la liste droulante aprs le GET initial et juste avant le 1er POST en [2], la page aprs le 1er POST. en [3], la valeur poste pour la liste droulante. Correspond l'attribut value du ListItem slectionn dans la liste.

http://tahe.developpez.com/dotnet/pam-aspnet

28/230

en [4], la liste droulante. Elle contient les mmes lments qu'aprs le GET initial. C'est le mcanisme du VIEWSTATE qui explique cela.

Pour comprendre l'interaction entre le VIEWSTATE de la liste DropDownListNoms et le test if (! IsPostBack) du gestionnaire Page_Load de [Default.aspx], le lecteur est invit refaire le test prcdent avec les configurations suivantes : Cas DropDownListNoms.EnableViewState test if(! IsPostBack) dans Page_Load de [Default.aspx]1 2 3 4 true false true false prsent prsent absent absent

Les diffrents tests donnent les rsultats suivants : 1. 2. 3. 4. c'est le cas prsent plus haut la liste est remplie lors du GET initial mais pas lors des POST qui suivent. Comme EnableViewState est faux, la liste est vide aprs chaque POST la liste est remplie aussi bien aprs le GET initial que lors des POST qui suivent. Comme EnableViewState est vrai, on a 3 noms aprs le GET initial, 6 noms aprs le 1er POST, 9 noms aprs le 2ime POST, ... la liste est remplie aussi bien aprs le GET initial que lors des POST qui suivent. Comme EnableViewState est faux, la liste est remplie avec seulement 3 noms chaque requte que celle-ci soit le GET initial ou les POST qui suivent. On retrouve le comportement du cas 1. Il y a donc deux faons d'obtenir le mme rsultat.

2.7 Gestion du VIEWSTATE des lments d'une page ASPXPar dfaut, tous les lments d'une page ASPX ont leur proprit EnableViewState True. A chaque fois que la page ASPX est envoye au navigateur client, elle contient le champ cach __VIEWSTATE qui a pour valeur une chane de caractres codant l'ensemble des valeurs des composants ayant leur proprit EnableViewState True. Pour minimiser la taille de cette chane, on peut chercher rduire le nombre de composants ayant leur proprit EnableViewState True. Rappelons comment les composants d'une page ASPX obtiennent leurs valeurs l'issue d'un POST : 1. 2. 3. 4. la page ASPX est instancie. Les composants sont initialiss avec leurs valeurs de conception. la valeur __VIEWSTATE poste par le navigateur est utilise pour donner aux composants la valeur qu'ils avaient lorsque la page ASPX a t envoye au navigateur la fois prcdente. les valeurs postes par le navigateur sont affectes aux composants les gestionnaires d'vnements sont excuts. Ils peuvent modifier la valeur de certains composants.

De cette squence, on dduit que les composants qui :

ont leur valeur poste ont leur valeur modifie par un gestionnaire d'vnement

peuvent avoir leur proprit EnableViewState Faux puisque leur valeur de VIEWSTATE (tape 2) va tre modifie par l'une des tapes 3 ou 4. La liste des composants de notre page est disponible dans [Default.aspx.designer.cs] :1. namespace Intro { 2. public partial class _Default { 3. protected global::System.Web.UI.HtmlControls.HtmlForm form1; 4. protected global::System.Web.UI.WebControls.TextBox TextBoxNom; 5. protected global::System.Web.UI.WebControls.RequiredFieldValidator RequiredFieldValidatorNom; 6. protected global::System.Web.UI.WebControls.TextBox TextBoxAge; 7. protected global::System.Web.UI.WebControls.RequiredFieldValidator RequiredFieldValidatorAge; 8. protected global::System.Web.UI.WebControls.RangeValidator RangeValidatorAge; 9. protected global::System.Web.UI.WebControls.DropDownList DropDownListNoms; 10. protected global::System.Web.UI.WebControls.Button ButtonValider; 11. protected global::System.Web.UI.WebControls.ListBox ListBoxEvts; 12. protected global::System.Web.UI.WebControls.Label LabelPost; 13. protected global::System.Web.UI.WebControls.Label LabelValidation; 14. protected global::System.Web.UI.WebControls.Label LabelErreursSaisie; 15. protected global::System.Web.UI.WebControls.Label LabelGlobal; 16. protected global::System.Web.UI.WebControls.Label LabelNbRequetes;

http://tahe.developpez.com/dotnet/pam-aspnet

29/230

17. 18. }

}

La valeur de la proprit EnableViewState de ces composants pourrait tre la suivante : Composant TextBoxNom TextBoxAge RequiredFieldValidatorNom RequiredFieldValidatorAge RangeValidatorAge LabelPost LabelValidation LabelErreursSaisie LabelGlobal LabelNbRequetes DropDownListNoms ListBoxEvts ButtonValider idem aucune idem idem aucune idem idem idem idem "value" de l'lment slectionn True "value" de l'lment slectionn False libell du bouton False on veut garder le contenu de la liste au fil des requtes sans avoir la rgnrer le contenu de la liste est gnr par un gestionnaire d'vnement le composant garde sa valeur de conception False obtient sa valeur par un gestionnaire d'vnement False absence de notion de valeur du composant Valeur poste valeur saisie dans le TextBox EnableViewState False Pourquoi la valeur du composant est poste

2.8 Forward d'une page vers une autreJusqu' maintenant, les oprations GET et POST retournaient toujours la mme page [Default.aspx]. Nous allons considrer le cas o une requte est traite par deux pages ASPX successives, [Default.aspx] et [Page1.aspx] et o c'est cette dernire qui est retourne au client. Par ailleurs, nous verrons comment la page [Default.aspx] peut transmettre des informations la page [Page1.aspx] via une mmoire qu'on appellera mmoire de la requte.

Navigateur1

Serveur web [Default.aspx] [Page1.aspx]

Html2

Mmoire de la requte

Nous construisons la page [Page1.aspx] :

http://tahe.developpez.com/dotnet/pam-aspnet

30/230

2

1

3

en [1], on ajoute un nouvel lment au projet en [2], on ajoute un lment [Web Form] nomm [Page1.aspx] [3]

5

4

en [4], la page ajoute en [5], la page une fois construite

Le code source de [Page1.aspx] est le suivant :1. 2. 3. 4. 5. 6. Page1 7. 8. 9. 10. 11. 12. Page 1 13. 14.
15. Retour 16. vers page [Default] 17. 18. 19. 20.

ligne 13 : un label qui servira afficher une information transmise par la page [Default.aspx] ligne 15 : un lien Html vers la page [Default.aspx]. Lorsque l'utilisateur clique sur ce lien, le navigateur demande la page [Default.aspx] avec une opration GET. La page [Default.aspx] est alors charge comme si l'utilisateur avait tap directement son Url dans son navigateur.

http://tahe.developpez.com/dotnet/pam-aspnet

31/230

La page [Default.aspx] s'enrichit d'un nouveau composant de type LinkButton :

1

Le code source de ce nouveau composant est le suivant :Forward vers Page1

CausesValidation="False" : le clic sur le lien va provoquer un POST vers [Defaul.aspx]. Le composant [LinkButton] se comporte comme le composant [Button]. Ici, on ne veut pas que le clic sur le lien dclenche l'excution des validateurs. EnableViewState="False" : il n'y a pas lieu de conserver l'tat du lien au fil des requtes. Il garde ses valeurs de conception. onclick="LinkButtonToPage1_Click" : nom de la mthode qui, dans [Defaul.aspx.cs], gre l'vnement Click sur le composant LinkButtonToPage1.

Le code du gestionnaire LinkButtonToPage1_Click est le suivant :1. // vers Page1 2. protected void LinkButtonToPage1_Click(object sender, EventArgs e) 3. { 4. // on met des infos dans le contexte 5. Context.Items["msg1"] = "Message de Default.aspx pour Page1"; 6. // on passe la requte Page1 7. Server.Transfer("Page1.aspx",true); 8. }

Ligne 7, la requte est passe la page [Page1.aspx] au moyen de la mthode [Server.Transfer]. Le deuxime paramtre de la mthode qui est true indique qu'il faut passer [Page1.aspx] toute l'information qui a t envoye [Default.aspx] lors du POST. Cela permet par exemple [Page1.aspx] d'avoir accs aux valeurs postes via une collection appele Request.Form. La ligne 5 utilise ce qu'on appelle le contexte de la requte. On y a accs via la proprit Context de la classe Page. Ce contexte peut servir de mmoire entre les diffrentes pages qui traitent la mme requte, ici [Default.aspx] et [Page1.aspx]. On utilise pour cela le dictionnaire Items. Lorsque [Page1.aspx] est charge par l'opration Server.Transfer("Page1.aspx",true), tout se passe comme si [Page1.aspx] avait t appele par un GET d'un navigateur. Le gestionnaire Page_Load de [Page1.aspx] est excut normalement. Nous l'utiliserons pour afficher le message mis par [Default.aspx] dans le contexte de la requte :1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. using System; namespace Intro { public partial class Page1 : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { Label1.Text = Context.Items["msg1"] as string; } } }

Ligne 9, le message mis par [Default.aspx] dans le contexte de la requte, est affich dans Label1. Voici un exemple d'excution :

http://tahe.developpez.com/dotnet/pam-aspnet

32/230

1

5 3 4

2

dans la page [Default.aspx] [1], on clique sur le lien [2] qui nous mne vers la page Page1 en [3], la page Page1 est affiche en [4], le message cr dans [Default.aspx] et affich par [Page1.aspx] en [5], l'Url affiche dans le navigateur est celle de la page [Default.aspx]

2.9 Redirection d'une page vers une autreNous prsentons ici une autre technique fonctionnellement proche de la prcdente : lorsque l'utilisateur demande la page [Default.aspx] par un POST, il reoit en rponse une autre page [Page2.aspx]. Dans la mthode prcdente, la requte de l'utilisateur tait traite successivement par deux pages : [Default.aspx] et [Page1.aspx]. Dans la mthode de la redirection de page que nous prsentons maintenant, il y a deux requtes distinctes du navigateur :

Navigateur Html

1

Serveur web [Default.aspx] Session Utilisateur

2

Html

[Page2.aspx]

en [1], le navigateur fait une requte POST la page [Default.aspx]. Celle-ci traite la requte et envoie une rponse dite de redirection au navigateur. Cette rponse est un simple flux HTTP (des lignes de texte) demandant au navigateur de se rediriger vers une autre Url [Page2.aspx]. [Default.aspx] n'envoie pas de flux Html dans cette premire rponse. en [2], le navigateur fait une requte GET la page [Page2.aspx]. Celle-ci est alors envoye en rponse au navigateur. si la page [Default.aspx] souhaite transmettre des informations la page [Page2.aspx], elle peut le faire via la session de l'utilisateur. Contrairement la mthode prcdente, le contexte de la requte n'est pas utilisable ici, car il y a ici deux requtes distinctes donc deux contextes distincts. Il faut alors utiliser la session de l'utilisateur pour faire communiquer les pages ensemble.

Comme il a t fait pour [Page1.aspx], nous ajoutons au projet la page [Page2.aspx] :

http://tahe.developpez.com/dotnet/pam-aspnet

33/230

2

3

4 1

en [1], [Page2.aspx] a t ajoute au projet en [2], l'aspect visuel de [Page2.aspx] en [3], nous ajoutons la page [Default.aspx] un composant LinkButton [4] qui va rediriger l'utilisateur vers [Page2.aspx].

Le code source de [Page2.aspx] est analogue celui de [Page1.aspx] :1. 2. 3. 4. 5. 6. Page2 7. 8. 9. 10. 11. 12. Page 2 13. 14.
15. Retour 16. vers page [Default] 17. 18. 19. 20.

Dans [Default.aspx], l'ajout du composant LinkButton a gnr le code source suivant :Redirection vers Page2

C'est le gestionnaire [LinkButtonToPage2_Click] qui assure la redirection vers [Page2.aspx]. Son code dans [Defaul.aspx.cs] est le suivant :1. 2. 3. 4. 5. 6. 7. } protected void LinkButtonToPage2_Click(object sender, EventArgs e) { // on met un msg dans la session Session["msg2"] = "Message de [Default.aspx] pour [Page2.aspx]"; // on redirige le client vers [Page2.aspx] Response.Redirect("Page2.aspx");

ligne 4 : on met un message dans la session de l'utilisateur ligne 5 : l'objet Response est une proprit de toute page ASPX. Elle reprsente la rponse faite au client. Elle possde une mthode Redirect qui fait que la rponse faite au client va tre un ordre HTTP de redirection.

http://tahe.developpez.com/dotnet/pam-aspnet

34/230

Lorsque le navigateur va recevoir l'ordre de redirection vers [Page2.aspx], il va faire un GET sur cette page. Dans celle-ci, la mthode [Page_Load] va s'excuter. On va l'utiliser pour rcuprer le message mis par [Default.aspx] dans la session et afficher celui-ci. Le code [Page2.aspx.cs] est le suivant :1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. using System; namespace Intro { public partial class Page2 : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { // on affiche le msg mis dans la session par [Default.aspx] Label1.Text = Session["msg2"] as string; } } }

A l'excution, on obtient les rsultats suivants :

2

3

1

en [1], on clique sur le lien de redirection de [Default.aspx]. Un POST est fait vers la page [Default.aspx] en [2], le navigateur a t redirig vers [Page2.aspx]. Cela se voit l'Url affiche par le navigateur. Dans la mthode prcdente, cette Url tait celle de [Default.aspx] car l'unique requte faite par le navigateur l'tait vers cette Url. Ici il y a un premier POST vers [Default.aspx], puis l'insu de l'utilisateur un second GET vers [Page2.aspx]. en [3], on voit que [Page2.aspx] a correctement rcupr le message mis par [Default.aspx] dans la session.

2.10 ConclusionNous avons introduit, l'aide de quelques exemples, les concepts d'ASP.NET qui nous seront utiles dans la suite du document. Cette introduction ne permet pas de comprendre les subtilits des changes client / serveur d'une application web. Pour cela, on pourra lire :

Programmation ASP.NET [http://tahe.developpez.com/dotnet/aspnet/vol1] et [http://tahe.developpez.com/dotnet/ aspnet/vol2]

http://tahe.developpez.com/dotnet/pam-aspnet

35/230

3

L'tude de cas

Nous souhaitons crire une application .NET permettant un utilisateur de faire des simulations de calcul de la paie des assistantes maternelles de l'association " Maison de la petite enfance " d'une commune. Nous nous intresserons autant l'organisation du code DotNet de l'application qu'au code lui-mme.

3.1 La base de donnesLes donnes statiques utiles pour construire la fiche de paie sont places dans une base de donnes SQL Server Express nomme dbpam (pam=Paie Assistante Maternelle). Cette base a un administrateur appel sa ayant le mot de passe msde.

La base a trois tables, EMPLOYES, COTISATIONS et INDEMNITES, dont la structure est la suivante : Table EMPLOYES : rassemble des informations sur les diffrentes assistantes maternelles Structure :SS NOM PRENOM ADRESSE VILLE CODEPOSTAL INDICE

numro de scurit sociale de l'employ - cl primaire nom de l'employ son prnom son adresse sa ville son code postal son indice de traitement - cl trangre sur le champ [INDICE] de la table [INDEMNITES]

Son contenu pourrait tre le suivant :

Table COTISATIONS : rassemble les taux des cotisations sociales prleves sur le salaire Structure :

http://tahe.developpez.com/dotnet/pam-aspnet

36/230

CSGRDS: Son contenu pourrait tre le suivant CSGD SECU RETRAITE

pourcentage : contribution sociale gnralise + contribution au remboursement de la dette sociale pourcentage : contribution sociale gnralise dductible pourcentage : scurit sociale pourcentage : retraite complmentaire + assurance chmage

Les taux des cotisations sociales sont indpendants du salari. La table prcdente n'a qu'une ligne. Table INDEMNITES : rassemble les diffrentes indemnits dpendant de l'indice de l'employINDICE BASEHEURE ENTRETIENJOUR REPASJOUR INDEMNITESCP

indice de traitement - cl primaire prix net en euro dune heure de garde indemnit dentretien en euro par jour de garde indemnit de repas en euro par jour de garde indemnit de congs pays. C'est un pourcentage appliquer au salaire de base.

Son contenu pourrait tre le suivant :

On notera que les indemnits peuvent varier d'une assistante maternelle une autre. Elles sont en effet associes une assistante maternelle prcise via l'indice de traitement de celle-ci. Ainsi Mme Marie Jouveinal qui a un indice de traitement de 2 (table EMPLOYES) a un salaire horaire de 2,1 euros (table INDEMNITES). Les relations entre les trois tables sont les suivantes :COTISATIONSCSGRDS CSGD SECU RETRAITE

EMPLOYESSS NOM PRENOM ADRESSE VILLE CODEPOSTAL INDICE

INDEMNITESINDICE BASEHEURE ENTRETIENJOUR REPASJOUR INDEMNITESCP

FK_EMPLOYES_INDEMNITES

Il y a une relation de cl trangre entre la colonne EMPLOYES(INDICE) et la colonne INDEMNITES(INDICE). La base de donnes [dbpam] ainsi cre donne naissance deux fichiers dans le dossier de SQL Server Express :

http://tahe.developpez.com/dotnet/pam-aspnet

37/230

Les fichiers [dbpam.mdf, dbpam_log.ldf] peuvent tre transports sur une autre machine et tre rattachs au SGBD SQL Server Express de cette machine. Voici comment procder :

les fichiers de la BD [dbpam] sont dupliqus dans un dossier

on lance SQL Server Express avec le client SQL Server Management Studio Express, on attache le fichier [dbpam.mdf] au SGBD :

2

1

3 4

1. 2. 3. 4.

clic droit sur [Databases] / Attach choix du fichier [dbpam.mdf] via un bouton [Add] non reprsent le fichier attach va donner naissance une BD qui ne doit pas dj exister. Ici, dans le champ [Attach As] on a donn le nom [dbpam2] la nouvelle BD. on voit la nouvelle BD et ses tables

http://tahe.developpez.com/dotnet/pam-aspnet

38/230

Cette technique de l'attachement d'une BD est utile pour transporter une BD d'un poste un autre et nous l'utiliserons ici.

3.2 Mode de calcul du salaire d'une assistante maternelleNous prsentons maintenant le mode de calcul du salaire mensuel d'une assistante maternelle. Nous prenons pour exemple, le salaire de Mme Marie Jouveinal qui a travaill 150 h sur 20 jours pendant le mois payer. Les lments suivants sont pris en compte :[TOTALHEURES]: total des heures travailles dans le mois [TOTALJOURS]: total des jours travaills dans le mois [TOTALHEURES]=150 [TOTALJOURS]= 20

Le salaire de base de l'assistante maternelle est donn par la formule suivante : Un certain nombre de cotisations sociales doivent tre prleves sur ce salaire de base :

[SALAIREBASE]=([TOTALHEURES]*[BAS EHEURE])*(1+[INDEMNITESCP]/100)

[SALAIREBASE]=(150*[2.1])*(1+0.15 )= 362,25

Contribution sociale gnralise et contribution au remboursement de la dette sociale : [SALAIREBASE]*[CSGRDS/100] Contribution sociale gnralise dductible : [SALAIREBASE]*[CSGD/ 100] Scurit sociale, veuvage, vieillesse : [SALAIREBASE]*[SECU/ 100] Retraite Complmentaire + AGPF + Assurance Chmage : [SALAIREBASE]*[RETRAITE/100]

CSGRDS : 12,64 CSGD : 22,28 Scurit sociale : 34,02 Retraite : 28,55

Total des cotisations sociales : Par ailleurs, l'assistante maternelle a droit, chaque jour travaill, une indemnit d'entretien ainsi qu' une indemnit de repas. A ce titre elle reoit les indemnits suivantes : Au final, le salaire net payer l'assistante maternelle est le suivant :

[COTISATIONSSOCIALES]=[SALAIREBAS E]*(CSGRDS+CSGD+SECU+RETRAITE)/10 0 [INDEMNITS]=[TOTALJOURS]*(ENTRET IENJOUR+REPASJOUR)

[COTISATIONSSOCIALES]=97,48

[INDEMNITES]=104

[SALAIREBASE][COTISATIONSSOCIALES]+ [INDEMNITS]

[salaire NET]=368,77

3.3 Rappels ADO.NETL'application de calcul de paie a besoin des informations de la base de donnes [dbpam]. Son architecture sera la suivante :

Application [simupaie] 1 Utilisateur 5 2 3

ADO.NET 4 SGBD

5

BD DBPAM

en [1], l'utilisateur fait une demande en [2], l'application de paie la traite.

http://tahe.developpez.com/dotnet/pam-aspnet

39/230

elle peut alors avoir besoin des donnes de la base de donnes. Elle fait alors une requte au fournisseur (provider) ADO.NET du SGBD utilis [4]. celui-ci exploite la base de donnes [5] et rend ses rsultats au fournisseur ADO.NET qui lui-mme les remonte l'application celle ci exploite ces rsultats et labore une rponse [5] pour l'utilisateur

Nous rappelons maintenant les principales interfaces prsentes par un fournisseur ADO.NET ses clients [3]. En mode connect, l'application : 1. ouvre une connexion avec la source de donnes 2. travaille avec la source de donnes en lecture/criture 3. ferme la connexion Trois interfaces ADO.NET sont principalement concernes par ces oprations :

IDbConnection qui encapsule les proprits et mthodes de la connexion. IDbCommand qui encapsule les proprits et mthodes de la commande SQL excute. IDataReader qui encapsule les proprits et mthodes du rsultat d'un ordre SQL Select.

L'interface IDbConnection Sert grer la connexion avec la base de donnes. Parmi les mthodes M et proprits P de cette interface on trouve les suivantes : NomConnectionString Open Close BeginTransaction State

Type P M M M P

Rle chane de connexion la base. Elle prcise tous les paramtres ncessaires l'tablissement de la connexion avec une base prcise. ouvre la connexion avec la base dfinie par ConnectionString ferme la connexion dmarre une transaction. tat de la connexion : ConnectionState.Closed, ConnectionState.Open, ConnectionState.Executing, ConnectionState.Fetching, ConnectionState.Broken ConnectionState.Connecting,

Si Connection est une classe implmentant l'interface IDbConnection, l'ouverture de la connexion peut se faire comme suit :1. 2. 3. IDbConnection connexion=new Connection(); connexion.ConnectionString=...; connexion.Open();

L'interface IDbCommand Sert excuter un ordre SQL ou une procdure stocke. Parmi les mthodes M et proprits P de cette interface on trouve les suivantes : NomCommandType

Type P

Rle indique ce qu'il faut excuter - prend ses valeurs dans une numration : - CommandType.Text : excute l'ordre SQL dfini dans la proprit CommandText. C'est la valeur par dfaut. - CommandType.StoredProcedure : excute une procdure stocke dans la base - le texte de l'ordre SQL excuter si CommandType= CommandType.Text - le nom de la procdure stocke excuter si CommandType= CommandType.StoredProcedure la connexion IDbConnection utiliser pour excuter l'ordre SQL la transaction IDbTransaction dans laquelle excuter l'ordre SQL la liste des paramtres d'un ordre SQL paramtr. L'ordre update articles set prix=prix*1.1 where id=@id a le paramtre @id. pour excuter un ordre SQL Select. On obtient un objet IDataReader reprsentant le rsultat du Select. pour excuter un ordre SQL Update, Insert, Delete. On obtient le nombre de lignes affectes par l'opration (mises jour, insres, dtruites). pour excuter un ordre SQL Select ne rendant qu'un unique rsultat comme dans : select count(*) from articles.

CommandText Connection Transaction Parameters ExecuteReader ExecuteNonQuery ExecuteScalar

P P P P M M M

http://tahe.developpez.com/dotnet/pam-aspnet

40/230

NomCreateParameter Prepare

Type M M

Rle pour crer les paramtres IDbParameter d'un ordre SQL paramtr. permet d'optimiser l'excution d'une requte paramtre lorsqu'elle est excute de multiples fois avec des paramtres diffrents.

Si Command est une classe implmentant l'interface IDbCommand, l'excution d'un ordre SQL sans transaction aura la forme suivante :1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. // ouverture connexion IDbConnection connexion=... connexion.Open(); // prparation commande IDbCommand commande=new Command(); commande.Connection=connexion; // excution ordre select commande.CommandText="select ..."; IDbDataReader reader=commande.ExecuteReader(); ... // excution ordre update, insert, delete commande.CommandText="insert ..."; int nbLignesInsres=commande.ExecuteNonQuery(); ... // fermeture connexion connexion.Close();

L'interface IDataReader Sert encapsuler les rsultats d'un ordre SQL Select. Un objet IDataReader reprsente une table avec des lignes et des colonnes, qu'on exploite squentiellement : d'abord la 1re ligne, puis la seconde, .... Parmi les mthodes M et proprits P de cette interface on trouve les suivantes : NomFieldCount GetName Item Read Close GetBoolean

Type P M P M M M M M le nombre de colonnes de la table IDataReader

Rle GetName(i) rend le nom de la colonne n i de la table IDataReader. Item[i] reprsente la colonne n i de la ligne courante de la table IDataReader. passe la ligne suivante de la table IDataReader. Rend le boolen True si la lecture a pu se faire, False sinon. ferme la table IDataReader. GetBoolean(i) : rend la valeur boolenne de la colonne n i de la ligne courante de la table IDataReader. Les autres mthodes analogues sont les suivantes : GetDateTime, GetDecimal, GetDouble, GetFloat, GetInt16, GetInt32, GetInt64, GetString. Getvalue(i) : rend la valeur de la colonne n i de la ligne courante de la table IDataReader en tant que type object. IsDBNull(i) rend True si la colonne n i de la ligne courante de la table IDataReader n'a pas de valeur ce qui est symbolis par la valeur SQL NULL.

Getvalue IsDBNull

L'exploitation d'un objet IDataReader ressemble souvent ce qui suit :1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. // ouverture connexion IDbConnection connexion=... connexion.Open(); // prparation commande IDbCommand commande=new Command(); commande.Connection=connexion; // excution ordre select commande.CommandText="select ..."; IDataReader reader=commande.ExecuteReader(); // exploitation rsultats while(reader.Read()){ // exploiter ligne courante ... } // fermeture reader reader.Close(); // fermeture connexion connexion.Close();

http://tahe.developpez.com/dotnet/pam-aspnet

41/230

http://tahe.developpez.com/dotnet/pam-aspnet

42/230

4

L'application [SimuPaie] version 1 ASP.NET

4.1 IntroductionNous souhaitons crire une application .NET permettant un utilisateur de faire des simulations de calcul de la paie des assistantes maternelles de l'association " Maison de la petite enfance " d'une commune. Le formulaire ASP.NET de calcul du salaire aura l'allure suivante :

L'application ASP.NET aura l'architecture suivante :

Application [simupaie] 1 Utilisateur Default.aspx 4 2 Global.asax

3 0

Donnes

lors de la premire requte faite l'application, un objet de type [Global] driv du type [System.Web.HttpApplication] est instanci. C'est lui qui va exploiter le fichier de configuration [web.config] de l'application web et mettre en cache certaines donnes de la base de donnes (opration 0 ci-dessus).

http://tahe.developpez.com/dotnet/pam-aspnet

43/230

lors de la premire requte (opration 1) faite la page [Default.aspx] qui est l'unique page de l'application, l'vnement [Load] est trait. On y traite le remplissage du combo des employs. Les donnes ncessaires au combo sont demandes l'objet [Global] qui les a mises en cache. C'est l'opration 2 ci-dessus. L'opration 4 envoie la page ainsi initialise l'utilisateur. lors de la demande du calcul du salaire (opration 1) faite la page [Default.aspx], l'vnement [Load] est de nouveau trait. Rien n'est fait car il s'agit d'une demande de type POST, et le gestionnaire [Pam_Load] a t crit pour ne rien faire dans ce cas (utilisation du boolen IsPostBack). L'vnement [Load] trait, c'est l'vnement [Click] sur le bouton [Salaire] qui l'est ensuite. Celui-ci a besoin de donnes qui n'ont pas t mises en cache dans [Global]. Aussi le gestionnaire de l'vnement les demande-t-il la base de donnes. C'est l'opration 3 ci-dessus. Le calcul du salaire est ensuite fait et l'opration 4 envoie les rsultats l'utilisateur.

4.2 Le projet Visual Web Developer 2008

3 4 1 2

en [1], on cre un nouveau projet en [2], de type [Web / Application Web ASP.NET] en [3], on donne un nom au projet en [4], on prcise son nom et en [5] son emplacement. Un dossier [c:\temp\pam-aspnet\pam-v1-adonet] va tre cr pour le projet.

7

8

5

en [5], le projet Visual Web Developer en [6], les proprits du projet (clic droit sur projet / Proprits / Application). en [7], le nom de l'assembly qui sera produit par la gnration du projet en [8], l'espace de noms par dfaut que nous souhaitons avoir pour les classes du projet. La classe [_Default] dfinie dans les fichiers [Default.aspx.cs] et [Default.aspx.designer.cs] a elle t cre dans l'espace de noms [pam_v1_adonet] driv du nom du projet. On peut changer cet espace de noms directement dans le code de ces deux fichiers :

[Default.aspx.cs]using System; .... namespace pam_v1 { public partial class _Default : System.Web.UI.Page {

http://tahe.developpez.com/dotnet/pam-aspnet

44/230

[Default.aspx.designer.cs]//-----------------------------------------------------------------------------// // Ce code a t gnr par un outil. // Version du runtime :2.0.50727.3603 // // Les modifications apportes ce fichier peuvent provoquer un comportement incorrect et seront perdues si // le code est rgnr. // //-----------------------------------------------------------------------------namespace pam_v1 { public partial class _Default { .........

Le balisage du fichier [Default.aspx] doit tre galement modifi :

...

L'attribut Inherits ci-dessus dsigne la classe dfinie dans les fichiers [Default.aspx.cs] et [Default.aspx.designer.cs]. On y utilise l'espace de noms pam_v1.

4.2.1

Le formulaire [Default.aspx]

L'aspect visuel du formulaire [Default.aspx] est le suivant :

http://tahe.developpez.com/dotnet/pam-aspnet

45/230

1 5

2

3

4

6 9

7 10 11

8

12

13

14

15

16

17

18

19

20

21 24

22

23

Les composants sont les suivants : N1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

Type TextBox TextBox Button TextBox Label Label Label Label Label Label Label Label Label Label Label Label Label Label

Nom TextBoxHeures TextBoxJours ButtonSalaire TextBoxErreur LabelNom LabelPrnom LabelAdresse LabelVille LabelCP LabelIndice LabelCSGRDS LabelCSGD LabelRetraite LabelSS LabelSH LabelEJ LabelRJ LabelCongs

Rle Nombre d'heures travailles nombre rel Nombre de jours travaills nombre entier Demande le calcul du salaire Message d'information destination de l'utilisateur ReadOnly=true, TextMode=MultiLine Nom de l'employ slectionn en (1) Prnom de l'employ slectionn en (1) Adresse Ville Code postal Indice Taux de cotisation CSGRDS Taux de cotisation CSGD Taux de cotisation Retraite Taux de cotisation Scurit Sociale Salaire horaire de base pour l'indice indiqu en (11) Indemnit journalire d'entretien pour l'indice indiqu en (11) Indemnit journalire de repas pour l'indice indiqu en (11) Taux d'indemnits de congs pays appliquer au salaire de base

DropDownList ComboBoxEmployes Contient la liste des noms des employs

http://tahe.developpez.com/dotnet/pam-aspnet

46/230

N20 21 22 23 24

Type Label Label Label Label Label

Nom LabelSB LabelCS LabelIE LabelIR LabelSN Montant du salaire de base

Rle Montant des cotisations sociales verser Montant des indemnits d'entretien de l'enfant gard Montant des indemnits de repas de l'enfant gard Salaire net payer l'employ(e)

Le formulaire contient en outre deux conteneurs de type [Panel] :PanelErreurs PanelSalaire

contient le composant (5) TextBoxErreur contient les composants (6) (24)

Un composant de type [Panel] peut tre rendu visible ou non par programmation grce sa proprit boolenne [Panel].Visible.

4.2.2

La vrification des saisies

Pour calculer un salaire, l'utilisateur : slectionne un employ en [1] saisit le nombre d'heures travailles en [2]. Ce nombre peut tre dcimal, comme 2,5 pour 2 h 30 mn. saisit le nombre de jours travaills en [3]. Ce nombre est entier. demande le salaire avec le bouton [4]

1

2

3 4

Lorsque l'utilisateur entre des donnes errones dans [2] et [3], celles-ci sont vrifies ds que l'utilisateur change de champ de saisie. Ainsi, la copie d'cran ci-dessous a t obtenue avant mme que l'utilisateur ne clique sur le bouton [Salaire] :

2 25, 26

3 27, 28

Il faut deux conditions pour avoir le comportement prcdent : les composants de validation doivent avoir leur proprit EnableClientScript vrai :

http://tahe.developpez.com/dotnet/pam-aspnet

47/230

le navigateur affichant la page doit tre capable d'excuter le code Javascript embarqu dans une page HTML.

Si le navigateur client ne vrifie pas lui-mme la validit des donnes, celles-ci ne seront vrifies que lorsque le navigateur postera les saisies du formulaire au serveur. C'est alors le code situ sur ce dernier et qui traite la demande du navigateur qui vrifiera la validit des donnes. On rappelle que cette vrification doit tre toujours faite mme si la page affiche dans le navigateur client embarque du code javascript faisant cette mme vrification. En effet, le serveur ne peut tre assur que la demande POST qui lui est faite vient rellement de cette page et que donc la vrification des donnes a t faite. La liste des validateurs est la suivante : N25 26 27 28

Type RangeValidator

Nom RangeValidatorHeures

Rle vrifie que le champ [2] [TextBoxHeures] est un nombre rel dans l'intervalle [0, 200] vrifie que le champ [3] [TextBoxJours] n'est pas vide vrifie que le champ [3] [TextBoxJours] est un nombre entier dans l'intervalle [0,31]

RequiredFieldValidator RequiredFieldValidatorHeures vrifie que le champ [2] [TextBoxHeures] n'est pas vide

RequiredFieldValidator RequiredFieldValidatorJours RangeValidator RangeValidatorJours

Travail faire : construire la page [Default.aspx]. On placera d'abord les deux conteneurs [PanelErreurs] et [PanelSalaire] pour pouvoir ensuite y placer les composants qu'ils doivent contenir.

4.2.3

Les entits de l'application

Une fois lues, les lignes des tables [cotisations], [employes], [indemnites] seront mises dans des objets de type [Cotisations], [Employe] et [Indemnites] dfinis comme suit :1. namespace Pam.Entites 2. { 3. public class Cotisations 4. { 5. // proprits automatiques 6. public double CsgRds { get; set; } 7. public double Csgd { get; set; } 8. public double Secu { get; set; } 9. public double Retraite { get; set; } 10. 11. // constructeurs 12. public Cotisations() 13. { 14. } 15. 16. public Cotisations(double csgRds, double csgd, double secu, double retraite) 17. { 18. CsgRds = csgRds; 19. Csgd = csgd; 20. Secu = secu;

http://tahe.developpez.com/dotnet/pam-aspnet

48/230

21. 22. 23. 24. 25. 26. 27. 28. 29. } 30. }

Retraite = retraite; } // ToString public override string ToString() { return string.Format("[{0},{1},{2},{3}]", CsgRds, Csgd, Secu, Retraite); }

1. namespace Pam.Entites 2. { 3. public class Employe 4. { 5. // proprits automatiques 6. public string SS { get; set; } 7. public string Nom { get; set; } 8. public string Prenom { get; set; } 9. public string Adresse { get; set; } 10. private string Ville { get; set; } 11. private string CodePostal { get; set; } 12. private int Indice { get; set; } 13. 14. // constructeurs 15. public Employe() 16. { 17. 18. } 19. 20. public Employe(string ss, string nom, string prenom, string adresse, string codePostal, string ville, int indice) 21. { 22. SS = ss; 23. Nom = nom; 24. Prenom = prenom; 25. Adresse = adresse; 26. CodePostal = codePostal; 27. Ville = ville; 28. Indice = indice; 29. } 30. 31. // ToString 32. public override string ToString() 33. { 34. return string.Format("[{0},{1},{2},{3},{4},{5},{6}]", SS, Nom, Prenom, Adresse, Ville, CodePostal, Indice); 35. } 36. } 37. }

1. namespace Pam.Entites 2. { 3. public class Indemnites 4. { 5. 6. // proprits automatiques 7. public int Indice { get; set; } 8. public double BaseHeure { get; set; } 9. public double EntretienJour { get; set; } 10. public double RepasJour { get; set; } 11. public double IndemnitesCP { get; set; } 12. 13. // constructeurs 14. public Indemnites() 15. { 16. 17. } 18. 19. public Indemnites(int indice, double baseHeure, double entretienJour, double repasJour, double indemnitesCP) 20. { 21. Indice = indice; 22. BaseHeure = baseHeure; 23. EntretienJour = entretienJour;

http://tahe.developpez.com/dotnet/pam-aspnet

49/230

24. 25. 26. 27. 28. 29. 30. 31.

}

RepasJour = repasJour; IndemnitesCP = indemnitesCP;

// identit public override string ToString() { return string.Format("[{0}, {1}, {2}, {3}, {4}]", Indice, BaseHeure, EntretienJour, RepasJour, IndemnitesCP); 32. } 33. 34. } 35. }

4.2.4

Configuration de l'application

Le fichier [Web.config] qui configure l'application sera le suivant :1. 2. 3. 4. 5. ... 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 26. 27. ... 28.

ligne 9 : dfinit la chane de connexion la base SQL Server prcdente lignes 13-16 : dfinissent des requtes SQL utilises par l'application afin d'viter de les mettre en dur dans le code. ligne 13 : la requte SQL est paramtre. La notation du paramtre est propre SQL Server.

Travail faire : introduire ces paramtres dans le fichier [Web.config]. La ligne 9 sera adapte au chemin rel de la base de donnes [dbpam.mdf].

4.2.5

Initialisation de l'application

L'initialisation d'une application ASP.NET est faite par le fichier [Global.asax.cs]. Celui-ci est construit de la faon suivante :

http://tahe.developpez.com/dotnet/pam-aspnet

50/230

2 1

3

en [1], on ajoute un nouvel lment au projet en [2], on ajoute la classe d'application globale qui s'appelle par dfaut [Global.asax] [3]

5

4

en [4], le fichier [Global.asax] et la classe associe [Global.asax.cs] en [5], on fait afficher le balisage de [Global.asax]

La classe [pam_v1.Global] est dfinie dans le fichier [Global.asax.cs]. Pour notre problme, elle sera dfinie comme suit :1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. using using using using using System; System.Collections.Generic; System.Configuration; System.Data.SqlClient; Pam.Entites;

namespace pam_v1 { public class Global : System.Web.HttpApplication { // --- donnes statiques de l'application --public static Employe[] Employes; public static Cotisations Cotisations; public static Dictionary Indemnites = new Dictionary(); public static string Msg = string.Empty; public static bool Erreur = false; public static string ConnectionString = null; // dmarrage de l'application public void Application_Start(object sender, EventArgs e) {

http://tahe.developpez.com/dotnet/pam-aspnet

51/230

22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43.

... try { // connexion ConnectionString = ... using (SqlConnection connexion = new SqlConnection(ConnectionString)) { connexion.Open(); // on rcupre la liste des emp