V. L'application [SimuPaie] - version 1 - ASP.NET▲
V-A. 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.
Le formulaire ASP.NET de calcul du salaire aura l'allure suivante :
L'application ASP.NET aura l'architecture suivante :
- lors de la première requête faite à l'application, un objet de type [Global] dérivé 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 données de la base de données (opération 0 ci-dessus).
- lors de la première requête (opération 1) faite à la page [Default.aspx] qui est l'unique page de l'application, l'événement [Load] est traité. On y traite le remplissage du combo des employés. Les données nécessaires au combo sont demandées à l'objet [Global] qui les a mises en cache. C'est l'opération 2 ci-dessus. L'opération 4 envoie la page ainsi initialisée à l'utilisateur.
- lors de la demande du calcul du salaire (opération 1) faite à la page [Default.aspx], l'événement [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 booléen IsPostBack). L'événement [Load] traité, c'est l'événement [Click] sur le bouton [Salaire] qui l'est ensuite. Celui-ci a besoin de données qui n'ont pas été mises en cache dans [Global]. Aussi le gestionnaire de l'événement les demande-t-il à la base de données. C'est l'opération 3 ci-dessus. Le calcul du salaire est ensuite fait et l'opération 4 envoie les résultats à l'utilisateur.
V-B. Le projet Visual Web Developer 2008▲
- en [1], on crée un nouveau projet
- en [2], de type [Web / Application Web ASP.NET]
- en [3], on donne un nom au projet
- en [4], on précise son nom et en [5] son emplacement. Un dossier [c:\temp\pam-aspnet\pam-v1-adonet] va être créé pour le projet.
- en [5], le projet Visual Web Developer
- en [6], les propriétés du projet (clic droit sur projet / Propriétés / Application).
- en [7], le nom de l'assembly qui sera produit par la génération du projet
- en [8], l'espace de noms par défaut que nous souhaitons avoir pour les classes du projet. La classe [_Default] définie dans les fichiers [Default.aspx.cs] et [Default.aspx.designer.cs] a elle été créée dans l'espace de noms [pam_v1_adonet] dérivé du nom du projet. On peut changer cet espace de noms directement dans le code de ces deux fichiers :
[Default.aspx.cs]
[Default.aspx.designer.cs]
Le balisage du fichier [Default.aspx] doit être également modifié :
L'attribut Inherits ci-dessus désigne la classe définie dans les fichiers [Default.aspx.cs] et [Default.aspx.designer.cs]. On y utilise l'espace de noms pam_v1.
V-B-1. Le formulaire [ Default.aspx ] ▲
L'aspect visuel du formulaire [Default.aspx] est le suivant :
Les composants sont les suivants :
N° | Type | Nom | Rôle |
1 | DropDownList | ComboBoxEmployes | Contient la liste des noms des employés |
2 | TextBox | TextBoxHeures | Nombre d'heures travaillées - nombre réel |
3 | TextBox | TextBoxJours | Nombre de jours travaillés - nombre entier |
4 | Button | ButtonSalaire | Demande le calcul du salaire |
5 | TextBox | TextBoxErreur | Message d'information à destination de l'utilisateur ReadOnly=true, TextMode=MultiLine |
6 | Label | LabelNom | Nom de l'employé sélectionné en (1) |
7 | Label | LabelPrénom | Prénom de l'employé sélectionné en (1) |
8 | Label | LabelAdresse | Adresse |
9 | Label | LabelVille | Ville |
10 | Label | LabelCP | Code postal |
11 | Label | LabelIndice | Indice |
12 | Label | LabelCSGRDS | Taux de cotisation CSGRDS |
13 | Label | LabelCSGD | Taux de cotisation CSGD |
14 | Label | LabelRetraite | Taux de cotisation Retraite |
15 | Label | LabelSS | Taux de cotisation Sécurité Sociale |
16 | Label | LabelSH | Salaire horaire de base pour l'indice indiqué en (11) |
17 | Label | LabelEJ | Indemnité journalière d'entretien pour l'indice indiqué en (11) |
18 | Label | LabelRJ | Indemnité journalière de repas pour l'indice indiqué en (11) |
19 | Label | LabelCongés | Taux d'indemnités de congés payés à appliquer au salaire de base |
20 | Label | LabelSB | Montant du salaire de base |
21 | Label | LabelCS | Montant des cotisations sociales à verser |
22 | Label | LabelIE | Montant des indemnités d'entretien de l'enfant gardé |
23 | Label | LabelIR | Montant des indemnités de repas de l'enfant gardé |
24 | Label | LabelSN | Salaire net à payer à l'employé(e) |
Le formulaire contient en outre deux conteneurs de type [Panel] :
PanelErreurs | contient le composant (5) TextBoxErreur |
PanelSalaire | contient les composants (6) à (24) |
Un composant de type [Panel] peut être rendu visible ou non par programmation grâce à sa propriété booléenne [Panel].Visible.
V-B-2. La vérification des saisies▲
Pour calculer un salaire, l'utilisateur :
- sélectionne un employé en [1]
- saisit le nombre d'heures travaillées en [2]. Ce nombre peut être décimal, comme 2,5 pour 2 h 30 mn.
- saisit le nombre de jours travaillés en [3]. Ce nombre est entier.
- demande le salaire avec le bouton [4]
Lorsque l'utilisateur entre des données erronées dans [2] et [3], celles-ci sont vérifiées dès que l'utilisateur change de champ de saisie. Ainsi, la copie d'écran ci-dessous a été obtenue avant même que l'utilisateur ne clique sur le bouton [Salaire] :
Il faut deux conditions pour avoir le comportement précédent :
- les composants de validation doivent avoir leur propriété EnableClientScript à vrai :
- le navigateur affichant la page doit être capable d'exécuter le code Javascript embarqué dans une page HTML.
Si le navigateur client ne vérifie pas lui-même la validité des données, celles-ci ne seront vérifiées 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 vérifiera la validité des données. On rappelle que cette vérification doit être toujours faite même si la page affichée dans le navigateur client embarque du code javascript faisant cette même vérification. En effet, le serveur ne peut être assuré que la demande POST qui lui est faite vient réellement de cette page et que donc la vérification des données a été faite.
La liste des validateurs est la suivante :
N° | Type | Nom | Rôle |
25 | RequiredFieldValidator | RequiredFieldValidatorHeures | vérifie que le champ [2] [TextBoxHeures] n'est pas vide |
26 | RangeValidator | RangeValidatorHeures | vérifie que le champ [2] [TextBoxHeures] est un nombre réel dans l'intervalle [0, 200] |
27 | RequiredFieldValidator | RequiredFieldValidatorJours | vérifie que le champ [3] [TextBoxJours] n'est pas vide |
28 | RangeValidator | RangeValidatorJours | vérifie que le champ [3] [TextBoxJours] est un nombre entier dans l'intervalle [0,31] |
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.
V-B-3. Les entités de l'application▲
Une fois lues, les lignes des tables [cotisations], [employes], [indemnites] seront mises dans des objets de type [Cotisations], [Employe] et [Indemnites] définis comme suit :
V-B-4. Configuration de l'application▲
Le fichier [Web.config] qui configure l'application sera le suivant :
- ligne 9 : définit la chaîne de connexion à la base SQL Server précédente
- lignes 13-16 : définissent des requêtes SQL utilisées par l'application afin d'éviter de les mettre en dur dans le code.
- ligne 13 : la requête SQL est paramétrée. La notation du paramètre est propre à SQL Server.
Travail à faire : introduire ces paramètres dans le fichier [Web.config]. La ligne 9 sera adaptée au chemin réel de la base de données [dbpam.mdf].
V-B-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 façon suivante :
- en [1], on ajoute un nouvel élément au projet
- en [2], on ajoute la classe d'application globale qui s'appelle par défaut [Global.asax] [3]
- en [4], le fichier [Global.asax] et la classe associée [Global.asax.cs]
- en [5], on fait afficher le balisage de [Global.asax]
La classe [pam_v1.Global] est définie dans le fichier [Global.asax.cs]. Pour notre problème, elle sera définie comme suit :
- lignes 20: la méthode [Application_Start] est exécutée au démarrage de l'application web. Elle n'est exécutée qu'une fois.
- lignes 12-17 : champs publics et statiques de la classe. Un champ statique est partagé par toutes les instances de la classe. Ainsi, si plusieurs instances de la classe [Global] sont créées, elles partagent toutes le même champ statique [Employes], accessible via la référence [Global.Employes], c.a.d. [NomDeClasse].ChampStatique. [Global] est le nom d'une classe. C'est donc un type de donnée. Ce nom est arbitraire. La classe dérive toujours de [System.Web.HttpApplication].
Revenons à notre classe [Global]. On peut se demander s'il est nécessaire de déclarer statiques ses champs. En fait, il semble que dans certains cas, on puisse avoir plusieurs exemplaires de la classe [Global], ce qui justifie le fait de rendre statiques les champs qui ont à être partagés par toutes ces instances.
Il existe une autre façon de partager des données de portée " application " entre les différentes pages d'une application web. Ainsi le tableau Employes des employés pourrait être mémorisé dans la procédure Application_Start de la façon suivante :
[Application] est par défaut dans toute application ASP.NET une référence sur une instance de la classe définie par [Global.asax.cs]. Application est un conteneur pouvant mémoriser des objets de tout type. Le tableau Employes pourrait ensuite être récupéré dans le code d'une page quelconque de l'application web de la façon suivante :
Parce que le conteneur Application mémorise des objets de tout type, on récupère un type Object qu'il faut ensuite transtyper. Cette méthode est toujours utilisable mais partager des données via des champs statiques typés de l'objet [Global] évite les transtypages et permet au compilateur de faire des vérifications de type qui aident le développeur. C'est la méthode qui sera utilisée ici.
Les données partagées par tous les utilisateurs sont les suivantes :
- ligne 12 : le tableau d'objets de type [Employe] qui mémorisera la liste simplifiée (SS, NOM, PRENOM) de tous les employés
- ligne 13 : l'objet de type [Cotisations] qui mémorisera les taux de cotisations
- ligne 14 : le dictionnaire qui mémorisera les indemnités liés aux différents indices des employés. Il sera indexé par l'indice de l'employé et ses valeurs seront de type [Indemnites]
- ligne 15 : un message indiquant comment s'est terminée l'initialisation (bien ou avec erreur)
- ligne 16 : un booléen indiquant si l'initialisation s'est terminée par une erreur ou non.
- ligne 17 : la chaîne de connexion à la base de données.
Question : compléter le code de la classe [Application_Start].
V-C. Les événements du formulaire [Default.aspx]▲
V-C-1. La procédure [Page_Load]▲
Lorsque le formulaire [Default.aspx] est chargé, il va chercher dans le tableau [Global.Employes] (ligne 12) les noms des employés pour les mettre dans la liste déroulante [1] :
- la liste déroulante [1] a été remplie
- le TextBox [5] indique que la base des données a été lue correctement
S'il s'est produit des erreurs d'initialisation lors du démarrage de l'application, le TextBox [5] l'indique :
Question : écrire la procédure [Page_Load] de la page web [Default.aspx] qui, exécutée au démarrage de l'application, garantit le fonctionnement précédent.
V-C-2. Le calcul du salaire▲
Le clic sur le bouton [4] provoque l'exécution du gestionnaire :
Ce gestionnaire commence par vérifier la validité des saisies faites en [2] et [3]. Si l'une des deux est incorrecte, l'erreur est signalée comme il a été montré précédemment. Une fois les saisies [2] et [3] vérifiées et trouvées valides, l'application doit afficher des données complémentaires sur l'utilisateur sélectionné en [1] ainsi que son salaire (cf copie d'écran page ).
Question : écrire le code de la procédure [ButtonSalaire_Click].