PRESENTATION D'ASP.NET WEB PAGES

Notions de base sur les formulaires HTML

Mike Pope, Tom fitzMacken

Traducteur

Hervé Taraveau

Ce tutoriel vous montre les bases de la création d'un formulaire de saisie et comment gérer les saisies des utilisateurs lorsque vous utilisez ASP.NET Web Pages (Razor).

Commentez

- Titre : PRESENTATION D'ASP.NET WEB PAGES

- Auteur : Mike Pope, Tom fitzMacken

- Traducteur : Hervé Taraveau

- Parution : 10 décembre 2018

- Public visé :

- Licence : Copyright ® 2014 Hervé Taraveau. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Préface

- I-A. Qu'allez-vous apprendre ?

- I-B. Fonctionnalités/technologies abordées :

- II. Qu'allez-vous construire ?

- III. À propos des formulaires HTML

- III-A. Sécurité des verbes HTTP, GET, POST

- III-B. HTML5 et les formulaires de saisie.

- IV. Création du formulaire

- V. Lecture des valeurs d'un formulaire

- V-A. L'objet Request

- VI. Création dune requête en utilisant un critère de recherche

- VI-A. Passer le critère de recherche en paramètre

- VII. Mise à jour de la page avec le code de la recherche

- VIII. Tester la fonctionnalité Search-by-Genre

- VIII-A. « Se souvenir » de ce que l'utilisateur a saisi

- IX. Recherche d'un mot quelconque dans le titre

- X. Test de la fonctionnalité de recherche dans le titre

- XI. Combiner les requêtes

- XII. Prochainement

- XIII. Listing complet de Movies Page (mise à jour de la page avec la fonctionnalité de recherche)

- XIV. Ressources supplémentaires

- XV. Information sur les auteurs

- XVI. Postface

- XVI-A. Remerciements

- XVI-B. Sources

I - Préface

Ce tutoriel vous montre les bases de la création d'un formulaire de saisie et de la gestion des saisies des utilisateurs lorsque vous utilisez ASP.NET Web Pages (Razor). Maintenant que vous avez une base de données, vous allez utiliser vos compétences sur les formulaires pour permettre aux utilisateurs de trouver des films spécifiques dans la base de données. Cela suppose que vous avez terminé la lecture de Présentation d'ASP.NET Web Page — Affichage des données.

Note de la rédaction Développez.com :
- ce tutoriel est basé sur la technologie ASP.NET Web Pages. Si elle est toujours d’actualité et peut continuer d’être utilisée sans aucun souci pour des projets existants, Microsoft recommande l’usage d’ASP.NET Core Razor Pages pour de nouveaux projets ;
- de plus, ce tutoriel est basé sur l’utilisation de WebMatrix comme environnement de développement. Aujourd’hui, cet environnement est considéré comme obsolète et il est préférable d’utiliser un environnement de développement récent comme Visual Studio ou Visual Studio Code. Néanmoins, cela ne devrait pas gêner la lecture de ce tutoriel ;
- précision vis-à-vis de la version anglaise : les liens invalides ont été retirés de la traduction.

I-A - Qu'allez-vous apprendre ?

- comment créer un formulaire utilisant les éléments HTML standards ;

- comment lire les saisies utilisateurs dans un formulaire ;

- comment créer une requête SQL qui obtient des données sélectionnées en fonction d'un critère que l'utilisateur fournit ;

- comment utiliser les champs que l'utilisateur a saisi dans la page « remember ».

I-B - Fonctionnalités/technologies abordées :

- l'objet Request ;

- la clause SQL Where.

II - Qu'allez-vous construire ?

Dans le tutoriel précédant, vous avez créé une base de données, ajouté des données et utilisé le WebGrid helper pour les afficher. Dans ce tutoriel, vous allez ajouter une boîte de dialogue « rechercher » qui vous permettra de trouver des films pour un genre spécifique ou dont le titre contient n'importe quel mot que vous entrez (par exemple, vous serez capable de trouver tous les films dont le genre est « action » ou dont le titre contient « Harry » ou « Adventure »).

Lorsque vous aurez fini ce tutoriel, vous aurez une page comme ceci :

La partie "liste" de la page est identique à celle du tutoriel précédant — une grille. La différence sera que la grille affichera seulement les films que vous aurez recherchés.

III - À propos des formulaires HTML

Si vous avez une expérience dans la création de formulaire HTML et connaissez la différence entre GET et POST, vous pouvez sauter cette section.

Un formulaire a des éléments de saisie pour les utilisateurs, zones de textes, boutons, boutons radio, cases à cocher, listes déroulantes, et d'autres encore. Les utilisateurs remplissent ces contrôles ou effectuent des sélections et ensuite envoient le formulaire en cliquant sur un bouton.

La syntaxe HTML de base d'un formulaire est illustrée dans cet exemple :

<form method="post">
<input type="text" name="name" value="" />
<br/>
<input type="submit" name="submit" value="Submit" />
</form>

Lorsque ce balisage s'exécute dans une page, il crée un simple formulaire qui ressemble à cette illustration :

L'élément <form> inclut les éléments HTML devant être soumis (une méprise facile à faire est d'ajouter des éléments à la page, mais d'oublier de les positionner à l'intérieur de l'élément <form>. Dans ce cas, rien n'est soumis). L'attribut method indique au navigateur comment soumettre l'entrée utilisateur. La méthode indique seulement comment sont passés les paramètres :

- GET : via l’URL ;

- POST : via le corps de la requête,

III-A - Sécurité des verbes HTTP, GET, POST

HTTP, le protocole utilisé par les navigateurs et les serveurs pour échanger des informations,

est remarquablement simple dans ces opérations de base. Les navigateurs utilisent seulement quelques verbes pour effectuer des requêtes aux serveurs. Lorsque vous écrivez du code pour le web(1), il est utile de comprendre ces verbes et de savoir comment le navigateur et le serveur les utilisent. De loin, les verbes les plus couramment utilisés sont :

- GET. le navigateur utilise ce verbe pour aller chercher quelque chose sur le serveur. Par exemple, lorsque vous saisissez une URL dans votre navigateur, il exécute une opération GET pour demander la page que vous souhaitez. Si la page inclut des graphiques, le navigateur exécute plusieurs opération GET supplémentaires pour obtenir les images. Si l'opération GET a besoin de transmettre des informations au serveur, celles-ci sont passées comme une partie de l'URL dans la chaîne de requête ;

- POST. le navigateur envoie une requête POST afin de soumettre des données pour l'ajout ou la modification sur le serveur. Par exemple, le verbe POST est utilisé pour créer des enregistrements dans une base de données ou modifier ceux existant. La plupart du temps, lorsque vous remplissez un formulaire et cliquez sur le bouton soumettre, le navigateur exécute une opération POST. Dans l'opération POST, les données devant être passées au serveur sont dans le corps de la requête.

Une distinction importante entre ces verbes est que l'opération GET n'est pas supposée changer quelque chose sur le serveur — ou d'une façon un peu plus abstraite, une opération GET ne doit pas entraîner un changement d'état sur le serveur. Vous pouvez exécuter une opération GET sur la même ressource autant de fois que vous le souhaitez, et ces ressources ne changent pas (une opération GET est souvent considérée comme « safe », ou pour utiliser un terme technique, est idempotent). En revanche, bien sûr, une requête POST change quelque chose sur le serveur chaque fois que vous soumettez cette opération.

Deux exemples nous aiderons à illustrer cette différence. Lorsque vous exécutez une recherche en utilisant un moteur comme Bing ou Google, cela consiste à remplir une TextBox dans un formulaire, puis à cliquer sur le bouton « search ». Le navigateur exécute une opération GET, avec la valeur que vous avez saisie dans la TextBox passée comme une partie de l'URL. C'est bien d'utiliser une opération GET pour ce type de formulaire, parce qu'une opération de recherche ne change aucune ressource sur le serveur, elle prélève juste des informations.

Maintenant considérez le processus de commande de quelque chose en ligne. Vous saisissez les détails de la commande et cliquez sur le bouton soumettre. Cette opération effectuera une requête POST, parce que de cette opération résultera des changements sur le serveur, comme un nouvel enregistrement commande, un changement dans les informations de votre compte, et peut-être de nombreuses autres modifications. Contrairement à une opération GET, vous ne pouvez pas répéter votre requête POST — si vous l'avez fait, chaque fois que vous soumettez la requête, vous générez une nouvelle commande sur le serveur (dans ce cas, souvent les sites web vous avertissent que vous ne devez pas cliquer plus d'une fois sur le bouton "soumettre", ou ils rendent le bouton "soumettre" inactif, ainsi vous ne pouvez plus l'activer accidentellement).

Dans le cadre de ce tutoriel, vous utiliserez chacune des opération GET et POST pour travailler avec les formulaires HTML. Nous expliquerons pour chaque cas pourquoi le verbe utilisé est le plus approprié.

Pour apprendre plus sur les verbes HTTP, regardez l'article Method Definitions sur le site W3C.

La plupart des éléments de saisie utilisateur sont des éléments HTML <input>. Ils ressemblent à <input type="type" name="name">, où type indique le genre de contrôle de saisie que vous souhaitez. Les éléments les plus fréquents sont :

- Text box: <input type="text"> ;

- Check box: <input type="check"> ;

- Radio button: <input type="radio"> ;

- Button: <input type="button"> ;

- Submit button: <input type="submit">.

Vous pouvez aussi utiliser l'élément <textarea> pour créer une « textbox » multiligne et l'élément <select> pour créer une « dropdown list » ou une « scrollable list » (pour en savoir plus sur les éléments HTML, regardez HTML Forms and Input sur le site W3Schools).

L'attribut name est très important, car il permet plus tard de retrouver la valeur de l'élément, comme vous le verrez bientôt.

Ce qui est intéressant, est ce que vous, développeur de pages, faites avec les saisies utilisateurs. Il n'y a aucun comportement intégré associé à ces éléments. Au lieu de cela, vous devez récupérer ou sélectionner les valeurs saisies et faire quelque chose avec. C'est ce que vous apprendrez dans ce tutoriel.

III-B - HTML5 et les formulaires de saisie.

Comme vous le savez peut-être, HTML est en transition et la dernière version (HTML5) inclut de nouvelles façons pour la saisie d'informations, qui sont plus intuitives pour les utilisateurs. Par exemple, en HTML5, vous (développeur de pages) pouvez préciser que vous voulez que l'utilisateur saisisse une date. Le navigateur peut alors automatiquement afficher un calendrier plutôt que de demander à l'utilisateur de saisir une date manuellement. Cependant, HTML5 est nouveau et il n'est pas encore supporté par tous les navigateurs.(2)

ASP.NET Web Pages supporte les entrées HTML5 dans la mesure où le navigateur de l'utilisateur le peut. Pour avoir une idée des éléments <input> dans HTML5, regardez HTML <input> type attribute sur le site W3Schools.

IV - Création du formulaire

Dans WebMatrix, dans l'espace de travail File, ouvrez la page Movies.chtml.

Après la balise de fermeture </h1> et avant la balise d'ouverture <div> de l'appel grid.GetHtml, ajoutez le balisage suivant :

<form method="get">
<div>
<label for="searchGenre">Genre to look for:</label>
<input type="text" name="searchGenre" value="" />
<input type="Submit" value="Search Genre" /><br/>
(Leave blank to list all movies.)<br/>
</div>
</form>

Ce balisage crée un formulaire qui a une « textbox » nommée SearchGenre et un bouton soumettre. La « textbox » et le bouton soumettre sont inclus dans l'élément <form> dont l'attribut method est get (rappelez-vous que si vous ne placez pas la « textbox » et le bouton soumettre à l'intérieur de l'élément <form>, rien ne sera soumis lorsque vous cliquerez sur le bouton). Ici, vous utilisez le verbe GET parce que vous créez un formulaire qui n'effectuera aucun changement sur le serveur — il en résultera juste une recherche (dans le tutoriel précédant, vous avez utilisé une méthode POST, avec laquelle vous soumettiez des changements sur le serveur. Vous verrez de nouveau cela dans le tutoriel suivant).

Exécutez la page. Même si vous n'avez pas défini de comportement pour le formulaire, vous pouvez voir à quoi il ressemble :

Saisissez une valeur dans la « textbox », comme « Comedy ». Maintenant cliquez sur Search Genre.

Prenez note de l'URL de la page. Parce que vous avez placé l'attribut de method à get dans l'élément <form>, la valeur saisie fait maintenant partie de la chaîne de requête de l'URL, comme ceci :

http://localhost:45661/Movies.cshtml?searchGenre=Comedy

V - Lecture des valeurs d'un formulaire

La page contient déjà du code qui prend des données dans la base de données et les affiche dans une grille. Maintenant vous devez ajouter du code qui lit la valeur d'une « textbox » et qui pourra aussi exécuter une requête SQL qui inclut le critère de recherche.

Parce que vous avez placé l'attribut method du formulaire à get, vous pouvez lire la valeur saisie dans la « textbox » en utilisant le code de la façon suivante :

var searchTerm = Request.QueryString["searchGenre"];

L'objet Request.QueryString (la propriété QueryString de l'objet Request) inclut les valeurs des éléments qui sont soumis dans une partie de l'opération GET. La propriété Request.QueryString contient une collection (une liste) des valeurs qui sont soumises dans le formulaire. Pour prendre chaque valeur individuellement, vous spécifiez le nom de l'élément que vous souhaitez. C'est pourquoi vous devez avoir un attribut name dans l'élément <input> (searchTerm) qui crée la « textbox » (pour plus d'information sur l'objet Request, regardez le paragraphe Objet Request plus bas).

Il est assez simple de lire la valeur de la « textbox ». Mais si l'utilisateur ne saisit rien dans celle-ci et clique sur Search quand même, vous pouvez ignorer ce clic, puisqu'il n'y a rien à chercher.

Le code suivant est un exemple qui montre comment implémenter ces conditions (vous n'avez pas à ajouter ce code maintenant, vous le ferez plus tard).

if(!Request.QueryString["searchGenre"].IsEmpty() ) {
// Do something here
}

Le test se décompose ainsi :

- prendre la valeur de Request.QueryString["searchGenre"], à savoir, la valeur qui a été saisie dans l'élément <input> nommé searchGenre ;

- découvrir si elle est vide en utilisant la méthode IsEmpty. Cette méthode est standard pour déterminer si quelque chose (par exemple, un élément form) contient une valeur. Mais réellement, vous ne vous souciez que de savoir si elle n'est pas vide, donc... ;

- ajouter l'opérateur"!" au début du test IsEmpty. (l'opérateur"!" signifie un NON logique — logical NOT).

En bon français, la condition if se traduit ainsi : si l'élément searchGenre du formulaire n'est pas vide alors…

Ceci ouvre la voie à la création d'une requête qui utilise le critère de recherche. Vous allez voir ceci dans la partie suivante.

V-A - L'objet Request

L'objet Request contient toutes les informations que le navigateur envoie quand une page est demandée ou soumise. Cet objet inclut des informations que l'utilisateur fournit, comme les valeurs de « textbox » ou un fichier à télécharger. Il inclut aussi toutes sortes d'informations additionnelles, comme des cookies, les valeurs dans la chaîne de requête URL (s'il y en a), le chemin du fichier de la page qui est en cours d'exécution, le type de navigateur que l'utilisateur utilise, la liste des langues présentes dans le navigateur, et bien plus encore.

L'objet Request est une collection (liste) de valeurs. Vous pouvez accéder à une valeur individuelle de la collection en spécifiant son nom :

var someValue = Request["name"];

L'objet Request expose plusieurs sous-ensembles :

- Request.Form vous donne les valeurs des éléments qui sont dans l'élément <form> soumis si la requête est une requête POST ;

- Request.QueryString vous donne juste les valeurs de la chaîne de requête de l'URL. http://mysite/myapp/page?searchGenre=action&page=2, la section ?searchGenre=action&page=2 de l'URL est la chaîne de requête ;

- La collection Request.Cookies vous donne accès au cookies que le navigateur a envoyé.

Pour obtenir une valeur que vous savez présente dans le formulaire soumis, vous pouvez utiliser Request["name"]. Alternativement, vous pouvez utiliser les versions plus spécifiques Request.Form["name"] (pour les requêtes POST) ou Request.QueryString["name"] (pour les requête GET). Bien sûr, name est le nom de l'élément à obtenir.

Le nom de l'élément que vous souhaitez obtenir doit être unique dans la collection que vous utilisez. C'est pourquoi l'objet Request fournit les sous-ensembles comme Request.Form et Request.QueryString. Supposez que votre page contienne un élément form nommé userName et contienne aussi un cookie nommé userName. Si vous faites Request["userNname"], c'est ambigu selon ce que vous voulez, la valeur de la form ou le cookie. Cependant, si vous faites Request.Form["userName"] ou Request.Cookie["userName"], vous êtes explicite pour chaque valeur que vous voulez obtenir.

C'est une bonne pratique de spécifier et d'utiliser les sous-ensembles de l'objet Request qui vous intéresse, comme Request.Form et Request.QueryString. Pour des pages simples que vous créez dans ce tutoriel, cela ne fait probablement aucune différence. Cependant, lorsque vous créerez des pages plus complexes, utiliser les versions explicites Request.Form et Request.QueryString pourra vous aider à éviter des problèmes qui pourraient survenir lorsque la page contient un ou plusieurs formulaires, des cookies, des valeurs de chaînes de requête, etc.

VI - Création dune requête en utilisant un critère de recherche

Maintenant que vous savez comment obtenir le critère de recherche que l'utilisateur a saisi, vous pouvez créer des requêtes qui l’utilise. Souvenez-vous que pour obtenir tous les films de la base de données, vous avez utilisé une requête SQL qui ressemble à cette déclaration :

SELECT * FROM Movies

Pour obtenir seulement certains films, vous devez utiliser une requête qui contient une clause Where. Cette clause vous permet de définir une condition vérifiée par les lignes renvoyées par la requête. Voici un exemple :

SELECT * FROM Movies WHERE Genre = 'Action'

Le format classique est WHERE column = value. Vous pouvez utiliser différents opérateurs autre que =, comme > (supérieur à), < (inférieur à), <> (différent), <= (inférieur ou égal à), etc., en fonction de ce que vous voulez obtenir.

Dans le cas où vous vous posez la question, les instructions SQL ne sont pas sensibles à la casse — SELECT est identique à Select (ou aussi à select). Cependant, les gens écrivent les mots-clés des instructions SQL en majuscules, comme SELECT et WHERE, pour rendre plus facile la lecture.

VI-A - Passer le critère de recherche en paramètre

La recherche d'un genre spécifique est assez facile (WHERE Genre = 'Action'), mais vous devez être capable d’effectuer une recherche pour n'importe quel genre que l'utilisateur saisira. Pour faire cela, vous créez une requête SQL qui inclut une zone réservée (placeholder) pour la valeur à rechercher. Cela ressemblera à cette commande :

SELECT * FROM Movies WHERE Genre = @0

La zone réservée est le caractère @ suivi par 0 (zéro). Comme vous pouvez le deviner, une requête peut contenir plusieurs zones réservées, elles sont nommées @0, @1, @2, etc.

Pour définir la requête et passer la valeur, vous utilisez le code suivant :

selectCommand = "SELECT * FROM Movies WHERE Genre = @0";
selectedData = db.Query(selectCommand, Request.QueryString["searchGenre"]);

Ce code est similaire à ce que vous avez déjà fait pour afficher les données dans la grille. Les seules différences sont :

- la requête contient une zone réservée (WHERE Genre = @0) ;

- la requête est placée dans une variable (SelectCommand) ; avant vous aviez passé la requête directement à la méthode db.Query ;

- lorsque vous appelez la méthode db.Query, vous passé la requête et la valeur pour la zone réservée (si la requête a plusieurs zones réservées, vous les passeriez toutes comme valeurs séparées).

Si vous mettez tous ces éléments ensembles, vous obtenez le code suivant :

if(!Request.QueryString["searchGenre"].IsEmpty() ) {
searchTerm = Request.QueryString["searchGenre"];
selectCommand = "SELECT * FROM Movies WHERE Genre = @0";
selectedData = db.Query(selectCommand, searchTerm);
}

Important ! Utiliser les zones réservées (comme @0) pour passer une commande SQL est extrêmement important pour la sécurité. La façon que nous venons de voir, avec les zones réservées pour les variables, est la seule façon de faire pour construire des commandes SQL.

Ne jamais construire une instruction SQL par concaténation de chaînes littérales et de valeurs obtenues de l'utilisateur. Concaténer les valeurs saisies par l'utilisateur dans une instruction SQL ouvre votre site à des attaques par injection SQL, un utilisateur malveillant qui soumet des valeurs à votre page peut pirater votre base de données (vous pouvez en lire plus dans cet article SQL Injection du site web MSDN).

VII - Mise à jour de la page avec le code de la recherche

Maintenant vous pouvez mettre à jour votre code dans le fichier Movies.cshtml. Pour commencer, remplacez le bloc de code en haut de la page par celui-ci :

var db = Database.Open("WebPagesMovies");
var selectCommand = "SELECT * FROM Movies";
var searchTerm = "";

Ici la différence est que vous placez la requête dans la variable SelectCommand, que vous passez plus tard à db.Query. Mettre l'instruction dans une variable vous permet de la changer plus tard, chose que vous allez faire pour réaliser la recherche.

Vous avez aussi enlevé ces deux lignes, que vous replacerez plus tard :

var selectedData = db.Query("SELECT * FROM Movies");
var grid = new WebGrid(source: selectedData, rowsPerPage: 3);

Vous ne voulez pas déjà exécuter la requête (c'est à dire, appeler db.Query) et vous ne voulez pas non plus initialiser WebbGrid helper. Vous ferez cela après avoir compris quelle instruction SQL s'exécutera.

Après avoir réécrit ce bloc, vous pouvez ajouter la nouvelle logique de gestion de recherche. Le code complet ressemble à ce qui suit. Mettez à jour le code dans votre page pour qu'il corresponde à cette page.

@{
var db = Database.Open("WebPagesMovies") ;
var selectCommand = "SELECT * FROM Movies";
var searchTerm = "";

if(!Request.QueryString["searchGenre"].IsEmpty() ) {
selectCommand = "SELECT * FROM Movies WHERE Genre = @0";
searchTerm = Request.QueryString["searchGenre"];
}

var selectedData = db.Query(selectCommand, searchTerm);
var grid = new WebGrid(source: selectedData, defaultSort: "Genre", rowsPerPage:3);
}

La page fonctionne maintenant ainsi. Chaque fois que la page s'exécute, le code ouvre la base de données et la variable SelectCommand est placé dans l'instruction SQL qui obtient tous les enregistrements de la table Movies. Le code initialise aussi la variable SearchTerm.

Cependant, si la requête courante inclut une valeur pour l'élément SearchGenre, le code définit une requête différente pour SelectCommand — à savoir, une version qui inclut une clause Where pour rechercher un genre. Il définit aussi SearchTerm pour tout ce qui est passé à la « textbox » de recherche (qui pourrait être vide).

Indépendamment de l'instruction SQL dans selectCommand, le code appelle ensuite db.Query pour exécuter la requête, en lui passant tout ce qui est dans SearchTerm. S'il n'y a rien dans SearchTerm , peu importe, car dans ce cas il n'y a aucun paramètre à remplacer dans selectCommand.

Finalement, le code initialise le WebGrid helper en utilisant le résultat de la requête, comme il faisait avant.

Vous pouvez constater qu'en plaçant l'instruction SQL et le critère de recherche dans des variables, vous avez ajouté de la flexibilité à votre code. Comme vous le verrez plus tard dans ce tutoriel, vous pourrez utiliser ce code de base et conserver cette logique d'ajout pour différents types de recherche.

VIII - Tester la fonctionnalité Search-by-Genre

Dans WebMatrix, exécutez la page Movies.cshtml. Vous verrez la page avec la « textbox » pour le genre.

Entrez un genre que vous avez saisi dans un de vos enregistrements de test, et cliquez sur Search. Cette fois, vous verrez juste une liste de films qui correspondent au genre :

Entrez différents genres et cherchez à nouveau. Essayez de saisir le genre en utilisant les lettres minuscules ou majuscules afin de voir que la recherche n'est pas sensible à la casse.(3)

VIII-A - « Se souvenir » de ce que l'utilisateur a saisi

Vous avez peut-être remarqué qu'après avoir saisi un genre et cliqué sur Search genre, vous voyez une liste concernant ce genre. Cependant, la « textBox » de recherche est vide — en d'autres termes, la fonctionn'a pas mémorisé ce que vous avez entré.

Il est important de comprendre ce fonctionnement obscur. Lorsque vous soumettez une page, le navigateur envoie une requête au serveur web. Lorsque ASP.NET reçoit celle-ci, il crée une Une nouvelle instance de cette page, exécute le code qu'elle contient, et renvoie la page au navigateur. Cependant la page envoyée ne sait pas que vous venez juste de travailler avec une version précédente d'elle même. Tout ce qu'elle sait c'est qu'elle a reçu une requête qui a ajouté certaines données.

Chaque fois que vous demandez une page — que ce soit la première fois ou en la soumettant — vous obtenez une nouvelle page. Le serveur web ne mémorise pas pour vous la dernière requête. Pas plus qu’ASP.NET ou le navigateur. La seule connexion entre les différentes instances de la page sont les données que vous transmettez entre elles. Si vous soumettez une page, par exemple, la nouvelle instance de la page peut obtenir des données qui ont été envoyées par l'instance précédente (une autre façon de passer des données entre les pages et d'utiliser les cookies).

Une façon formelle pour décrire cette situation est de dire que les pages sont stateless (sans état). Les serveurs web, les pages elles-mêmes et les éléments de la page ne conservent aucune information de l'état de la page précédente. Le web a été conçu ainsi parce que maintenir l'état des requêtes individuelles épuiserait rapidement les ressources des serveurs web, qui traitent souvent des milliers, voire même des centaines de milliers de requêtes par seconde.

Cela explique pourquoi la « textBox » est vide. Après que vous ayez soumit la page, ASP.NET crée une nouvelle instance de la page et exécute le code et le balisage. Dans ce code rien ne dit à ASP.NET de mettre une valeur dans la « texBox ». Aussi ASP.NET ne fait rien, et la « textBox » à été ré-affichée sans valeur.

Il existe effectivement un moyen facile de contourner ce problème. Le genre que vous avez saisi dans la « textBox » est disponible dans le code — c'est dans Request.QueryString["searchGenre"].

Mettez à jour le balisage pour la « textBox » afin que l'attribut value obtienne sa valeur de searchTerm, comme dans cet exemple :

<input type="text" name="searchGenre" value="@Request.QueryString["searchGenre"]" />

Dans cette page, vous pouvez aussi avoir assigné l'attribut value à la variable searchTerm, puisque cette variable contient aussi le genre que vous avez saisi. Mais la méthode standard est d'utiliser l'objet Request pour assigner l'attribut value, comme illustré ici (en supposant que vous procédez ainsi normalement — dans certains cas, vous pouvez afficher la page sans valeur dans les champs. Cela dépend de ce que vous voulez faire avec votre application).

Note : vous ne devez pas conserver la valeur d'une « textBox » qui est utilisée pour le mot de passe. Ce serait une faille de sécurité qui permettrait à des personnes de remplir le champ du mot de passe en utilisant du code.

Exécutez à nouveau la page, saisissez un genre, et cliquez sur Search Genre. Cette fois non seulement vous voyez le résultat de la recherche, mais la « textBox » se souvient de votre saisie :

IX - Recherche d'un mot quelconque dans le titre

Vous pouvez maintenant rechercher n'importe quel genre, mais vous pouvez aussi rechercher un titre. Il est difficile de saisir exactement un titre entier lorsque vous faites une recherche, aussi vous pouvez rechercher un mot qui apparaît n'importe où dans le titre. Pour faire cela en SQL, vous utilisez l'opérateur LIKE avec la syntaxe suivante :

SELECT * FROM Movies WHERE Title LIKE '%adventure%'

Cette commande obtient tous les films dont le titre contient « adventure ». Lorsque vous utilisez l'opérateur LIKE, vous incluez un caractère générique « % » comme partie intégrante du critère de recherche. La recherche LIKE 'adventure%' signifie « commençant par adventure » (techniquement, cela signifie « la chaîne adventure suivie de n'importe quoi ».), de façon similaire, la recherche LIKE '%adventure' signifie « quoi que ce soit suivi par la chaîne adventure », qui est une autre façon de dire « se terminant par adventure ».

L'expression de recherche LIKE '%adventure%' signifie donc « avec 'adventure' n'importe où dans le titre ». (Techniquement « n'importe quoi dans le titre, suivi par 'adventure', suivi par n'importe quoi ».)

À l'intérieur de l'élément <form>, ajoutez le balisage suivant au dessus du tag de fermeture </div> pour la recherche du genre (juste avant l'élément de fermeture </form>) :

<div>
<label for="SearchTitle">Movie title contains the following:</label>
<input type="text" name="searchTitle" value="@Request.QueryString["searchTitle"]" />
<input type="Submit" value="Search Title" /><br/>
</div>

Le code permettant de gérer cette recherche est similaire au code de recherche par genre, sauf que vous devez construire la recherche avec LIKE. Dans le bloc de code en haut de la page ajoutez ce bloc if juste après le bloc if pour la recherche par genre :

if(!Request.QueryString["searchTitle"].IsEmpty() ) {
selectCommand = "SELECT * FROM Movies WHERE Title LIKE @0";
searchTerm = "%" + Request["searchTitle"] + "%";
}

Ce code utilise la même logique que vous avez vu auparavant, sauf que la recherche utilise l'opérateur LIKE et le code place « % » avant et après le critère de recherche.

Remarquez comme il est facile d'ajouter un autre type de recherche dans la page. Tout ce que vous aviez à faire est :

- créer un bloc if qui teste si la « textBox » a un critère de recherche ;

- assigner une nouvelle instruction à la variable selectCommand ;

- assigner à la variable searchTerm la valeur à passer à la requête.

Voici le bloc de code complet, qui contient la nouvelle logique de recherche pour un titre :

1. @{

2. var db = Database.Open("WebPagesMovies") ;

3. var selectCommand = "SELECT * FROM Movies";

4. var searchTerm = "";

6. if(!Request.QueryString["searchGenre"].IsEmpty() ) {

7. selectCommand = "SELECT * FROM Movies WHERE Genre = @0";

8. searchTerm = Request.QueryString["searchGenre"];

9. }

11. if(!Request.QueryString["searchTitle"].IsEmpty() ) {

12. selectCommand = "SELECT * FROM Movies WHERE Title LIKE @0";

13. searchTerm = "%" + Request["searchTitle"] + "%";

14. }

16. var selectedData = db.Query(selectCommand, searchTerm);

17. var grid = new WebGrid(source: selectedData, defaultSort: "Genre", rowsPerPage:8);

18. }

Voici un résumé de ce que fait le code :

- les variables searchTerm et selectCommand sont initialisées en haut. Vous définissez ces variables pour le critère de recherche (le cas échéant) et pour la commande SQL en fonction des saisies de l'utilisateur dans la page. La recherche par défaut est le cas simple pour obtenir tous les films de la base de donées ;

- dans les tests pour searchGenre et searchTitle, le code affecte searchTerm à la valeur que vous voulez rechercher. Ces blocs de code affectent aussi selectCommand à une commande SQL appropriée pour cette recherche ;

- la méthode db.Query est appelée une seule fois, peu importe la commande SQL utilisée dans selectCommand et la valeur dans searchTerm. S'il n'y aucun critère de recherche (pas de genre et pas de mot du titre), la valeur de searchTerm est une chaîne vide. Cependant, ça ne fait rien, parce que dans ce cas, la requête ne requiert pas de paramètres.

X - Test de la fonctionnalité de recherche dans le titre

Maintenant vous pouvez tester votre page de recherche complétée. Exécutez Movies.cshtml.

Entrez un genre et cliquez sur Search Genre. La grille affiche les films de ce genre, comme avant.

Entrez un titre et cliquez sur Search Title. La grille affiche les films qui ont ce mot dans le titre.

Laissez les deux zones de textes vides et cliquez sur chaque bouton. La grille affiche tous les films.

XI - Combiner les requêtes

Vous avez peut-être remarqué que les recherches que vous pouvez effectuer sont exclusives. Vous ne pouvez pas rechercher le titre et le genre en même temps. Par exemple, vous ne pouvez pas chercher tous les films d'action qui contiennent dans le titre le mot « Adventure » (telle que la page est codée actuellement, si vous saisissez des valeurs pour le titre et le genre, la priorité est donnée à la recherche sur le titre). Pour créer une recherche qui combine les conditions, vous devez créer une requête SQL dont la syntaxe ressemblent à ce qui suit :

SELECT * FROM Movies WHERE Genre = @0 AND Title LIKE @1

Et vous auriez exécuté la requête en utilisant une instruction comme la suivante (grosso modo) :

var selectedData = db.Query(selectCommand, searchGenre, searchTitle);

Créer une logique afin de permettre de nombreuses permutations de critères de recherche peut devenir compliqué, comme vous pouvez le voir. Donc, nous allons nous arrêter ici.

XII - Prochainement

Dans le prochain tutoriel, vous créerez une page utilisant un formulaire qui permettra aux utilisateurs d'ajouter des films à la base de données.

XIII - Listing complet de Movies Page (mise à jour de la page avec la fonctionnalité de recherche)

1. @{

2. var db = Database.Open("WebPagesMovies") ;

3. var selectCommand = "SELECT * FROM Movies";

4. var searchTerm = "";

6. if(!Request.QueryString["searchGenre"].IsEmpty() ) {

7. selectCommand = "SELECT * FROM Movies WHERE Genre = @0";

8. searchTerm = Request.QueryString["searchGenre"];

9. }

11. if(!Request.QueryString["searchTitle"].IsEmpty() ) {

12. selectCommand = "SELECT * FROM Movies WHERE Title LIKE @0";

13. searchTerm = "%" + Request["searchTitle"] + "%";

14. }

16. var selectedData = db.Query(selectCommand, searchTerm);

17. var grid = new WebGrid(source: selectedData, defaultSort: "Genre", rowsPerPage:3);

18. }

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Movies</title>
<style type="text/css">
.grid { margin: 4px; border-collapse: collapse; width: 600px; }
.grid th, .grid td { border: 1px solid #C0C0C0; padding: 5px; }
.head { background-color: #E8E8E8; font-weight: bold; color: #FFF; }
.alt { background-color: #E8E8E8; color: #000; }
</style>
</head>
<body>
<h1>Movies</h1>
<form method="get">
<div>
<label for="searchGenre">Genre to look for:</label>
<input type="text" name="searchGenre" value="@Request.QueryString["searchGenre"]" />
<input type="Submit" value="Search Genre" /><br/>
(Leave blank to list all movies.)<br/>
</div>

<div>
<label for="SearchTitle">Movie title contains the following:</label>
<input type="text" name="searchTitle" value="@Request.QueryString["searchTitle"]" />
<input type="Submit" value="Search Title" /><br/>
</div>
</form>

<div>
@grid.GetHtml(
tableStyle: "grid",
headerStyle: "head",
alternatingRowStyle: "alt",
columns: grid.Columns(
grid.Column("Title"),
grid.Column("Genre"),
grid.Column("Year")
)
)
</div>
</body>
</html>

XIV - Ressources supplémentaires

- Introduction to ASP.NET Web Programming Using the Razor Syntax ;

- SQL WHERE Clause sur le site W3Schools ;

- l'article Method Definition sur le site W3C.

XV - Information sur les auteurs

Mike Pope — Mike Pope est un programmeur, créateur de l'équipe chargée du suivi du contenu sur la plate-forme Web et Outils Microsoft.

Tom FitzMacken — Tom FitzMacken est un auteur senior dans la programmation, créateur et membre de l'équipe chargée du du contenu sur la plate-forme Web et Outils.

XVI - Postface

XVI-A - Remerciements

Nous remercions rv26t, François DORIN pour la relecture et la validation technique et jacques_jean pour la relecture orthographique.

XVI-B - Sources

Traduction de l'article de l'équipe de Microsoft ASP.NET — Introducing ASP.NET Web Pages - HTML Form Basics.

(1)L'auteur semble confondre ici les verbes définis par le protocole HTTP et les verbes définis par le standard HTML. En HTML, il est possible de préciser si les informations d'un formulaire doivent être transmises par URL (méthode GET) ou dans le corps de la requête (méthode POST). La norme HTTP spécifie plusieurs verbes, dont les plus usités sont GET, POST, DELETE et PUT permettant de réaliser des opérations différentes pour une même URL (par exemple, une requête GET vers l'URL /profil/32 viendrait récupérer les informations sur le profil dont l'id est 32, tandis qu'une requête DELETE vers l'URL /profil/32 viendrait supprimer ce profil). La norme HTTP précise également la sémantique qui devrait être associée à chaque verbe (il ne s'agit pas d'une obligation, mais d'une convention fortement recommandée).

Les différents verbes HTTP sont notamment utilisés dans la réalisation de webservices REST. Le fait que la méthode HTML GET utilise le verbe HTTP GET et que la méthode HTML POST utilise le verbe HTTP POST semble être la source de la confusion.

(2)NdT : c’était effectivement le cas lors de l’écriture de cet article. Aujourd’hui, les navigateurs supportent très bien la norme HTML5.

(3)NdT : en réalité, une recherche peut être sensible à la casse en fonction de la configuration de votre base de données, notamment de sa collation.