I. Préface▲
Ce tutoriel vous montre comment supprimer une ligne d'une base de données. Cela présume que vous avez étudié les tutoriels précédant de la série jusqu'à mise à jour de la base de données avec ASP.NET Web Page.
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 sélectionner une ligne dans une liste ;
- comment supprimer un enregistrement dans une base de données ;
- comment vérifier qu'un bouton spécifique a été cliqué dans un formulaire.
I-B. Fonctionnalités/technologie abordées :▲
- le WebGrid helper ;
- la commande SQL Delete ;
- la méthode Database.Execute pour exécuter une commande Delete.
II. Qu'allez-vous construire ?▲
Dans le tutoriel précédant, vous avez appris comment mettre à jour un enregistrement existant dans la base de données. Ce tutoriel est similaire, sauf qu'au lieu de mettre à jour l'enregistrement, vous allez le supprimer. Les processus sont les mêmes, sauf que la suppression est simple, aussi ce tutoriel sera court.
Dans la page Movies, vous devez mettre à jour le WebGrid helper afin qu'il affiche un lien Delete à coté de chaque film en parallèle au lien Edit que vous avez ajouté auparavant.
Comme avec la modification, lorsque que vous cliquez sur le lien Delete, il vous envoie sur une page différente, où les informations concernant le film seront présentées dans un formulaire :
Maintenant, vous pouvez cliquer sur le bouton pour supprimer l'enregistrement définitivement.
III. Ajouter un bouton Delete à la liste des films▲
Vous allez commencer par ajouter un lien Delete au WebGrid helper. Ce lien est similaire au lien Edit que vous avez ajouté dans un tutoriel précédant.
Ouvrez le fichier Movies.cshtml.
Changez le balisage WebGrid dans le corps (body) de la page en ajoutant une colonne. Voici le balisage modifié :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
@grid.GetHtml(
tableStyle:
"grid"
,
headerStyle:
"head"
,
alternatingRowStyle:
"alt"
,
columns:
grid.
Columns(
grid.
Column(format:
@<
a href=
"~/EditMovie?id=@item.ID"
>
Edit</
a>
),
grid.
Column("Title"
),
grid.
Column("Genre"
),
grid.
Column("Year"
),
grid.
Column(format:
@<
a href=
"~/DeleteMovie?id=@item.ID"
>
Delete</
a>
)
)
)
La nouvelle colonne est celle-ci :
grid.Column(format: @<a
href
=
"~/DeleteMovie?id=@item.ID"
>
Delete</a>
)
La grille est configurée de cette façon, la colonne Edit est le plus à gauche, et la colonne Delete le plus à droite (au cas où vous ne l'auriez pas remarqué, maintenant, il y a une virgule après la colonne Year). Il n'y a rien de spécial pour ces colonnes de lien, et vous pourriez très bien les mettre l'une à coté de l'autre. Ici, elles sont séparées pour ne pas les confondre.
La nouvelle colonne montre un lien (l'élément <a>) où le texte affiche « Delete ». La cible du lien (son attribut href) est un code qui finalement résout (construit) une URL semblable à celle-ci, avec une valeur d'id différente pour chaque film :
http://localhost:43097/DeleteMovie?id=7
Ce lien invoquera une page nommée DeleteMovie et lui passera l'ID du film que vous avez sélectionné.
Ce tutoriel ne va pas entrer en détail sur la construction de ce lien, parce que c'est presque identique au lien Edit du tutoriel précédant .
IV. Création de la page Delete▲
Maintenant vous pouvez créer la page qui sera la cible du lien Delete dans la grille.
Important : la technique de commencer par sélectionner un enregistrement pour le supprimer, puis d'utiliser une page séparée et un bouton pour confirmer le processus est extrêmement importante pour la sécurité. Comme vous avez lu dans les tutoriels précédents, faites en sorte que tout changement au sein de votre site se fasse sur un formulaire — et pour cela utiliser une opération HTTP POST. Si vous laissez la possibilité de changer votre site juste en cliquant sur un lien (ce qui correspnd à l'utilisation d'une opération GET), les gens pourrons faire de simples requêtes sur votre site et détruire des données(1). Même un robot de recherche indexant votre site pourrait, par inadvertance, supprimer des données juste en suivant les liens.
Lorsque votre application permet aux utilisateurs de mettre à jour un enregistrement, vous devrez de toute façon l'afficher pour le modifier. Mais pour la suppression d'un enregistrement, vous pourriez être tenté de sauter cette étape. Cependant, ne le faite pas (il est également utile pour les utilisateurs de voir cet enregistrement et de confirmer leur intention de le supprimer).
Dans une série de tutoriels ultérieure, vous verrez comment ajouter une fonctionnalité de login de sorte qu'un utilisateur devra se connecter avant de supprimer un enregistrement.
Créez une page nommée DeleteMovie.cshtml et remplacez le contenu du fichier par le balisage suivant :
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.
<html>
<head>
<title>Delete a Movie</title>
</head>
<body>
<h1>Delete a Movie</h1>
@Html.ValidationSummary()
<p><a href
=
"~/Movies"
>
Return to movie listing</a></p>
<form method
=
"post"
>
<fieldset>
<legend>Movie Information</legend>
<p><span>Title:</span>
<span>@title</span></p>
<p><span>Genre:</span>
<span>@genre</span></p>
<p><span>Year:</span>
<span>@year</span></p>
<input type
=
"hidden"
name
=
"movieid"
value
=
"@movieId"
/>
<p><input type
=
"submit"
name
=
"buttonDelete"
value
=
"Delete Movie"
/></p>
</fieldset>
</form>
</body>
</html>
Ce balisage est comme celui de la page EditMovie, sauf qu'au lieu d'utiliser des zones de texte (<input type="text">), le balisage inclut des éléments <span>. Ici il n'y a rien a modifier. Tout ce que vous avez à faire est d'afficher les détails du film, ainsi les utilisateurs peuvent être sûrs qu'il supprimeront le bon.
Le balisage contient toujours un lien qui permet à l'utilisateur de retourner sur la page de liste des films.
Comme dans la page EditMovie, l'ID du film sélectionné est stocké dans un champ caché (il est passé à la page en première position comme une valeur de la chaîne de requête de l'URL). Il y a un appel à Html.ValidationSummary qui affichera les messages d'erreurs. Dans ce cas, l'erreur peut être qu'aucun ID de film n'est passé à la page, ou l'ID du film est invalide. Cette situation apparaît si quelqu'un exécute cette page sans sélectionner un film dans la page Movies.
Les attributs du bouton sont Delete Movie pour la légende et buttonDelete pour son nom. L'attribut name sera utilisé dans le code pour identifier le bouton qui soumettra le formulaire.
Vous devez écrire le code 1) pour lire les détails du film lorsque la page est affichée la première fois, et 2) pour réellement supprimer le film lorsque l'utilisateur clique sur le bouton.
V. Ajout de code pour lire un film▲
En haut de la page DeleteMovie.cshtml, ajoutez le bloc de code suivant :
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.
@{
var
title =
""
;
var
genre =
""
;
var
year =
""
;
var
movieId =
""
;
if
(!
IsPost){
if
(!
Request.
QueryString[
"ID"
].
IsEmpty
(
) &&
Request.
QueryString[
"ID"
].
IsInt
(
)){
movieId =
Request.
QueryString[
"ID"
];
var
db =
Database.
Open
(
"WebPagesMovies"
);
var
dbCommand =
"SELECT * FROM Movies WHERE ID = @0"
;
var
row =
db.
QuerySingle
(
dbCommand,
movieId);
if
(
row !=
null
) {
title =
row.
Title;
genre =
row.
Genre;
year =
row.
Year;
}
else
{
Validation.
AddFormError
(
"No movie was found for that ID."
);
}
}
else
{
Validation.
AddFormError
(
"No movie was found for that ID."
);
}
}
}
Ce balisage est le même que le code correspondant dans la page EditMovie. Il obtient l'ID du film dans la chaîne de requête de l'URL et l'utilise pour lire un enregistrement de la base de données. Le code inclut le test de validation (IsInt() et row != null) afin d'être sûr que l'ID de film transmis à la page est valide.
Rappelez-vous que ce code s'exécute seulement la première fois que la page s'exécute. Vous ne voulez pas relire l'enregistrement depuis la base de données lorsque l'utilisateur clique le bouton Delete Movie. Par conséquent, le code pour lire le film est à l'intérieur d'un test qui est if(!IsPost) — qui se traduit par, si la requête n'est pas une opération Post (soumettre le formulaire).
VI. Ajout du code pour supprimer le film sélectionné▲
Pour supprimer le film lorsqu'un utilisateur clique le bouton, ajouter le code suivant juste à l'intérieur l'accolade de fermeture du bloc @ :
2.
3.
4.
5.
6.
7.
if
(
IsPost &&
!
Request[
"buttonDelete"
].
IsEmpty
(
)){
movieId =
Request.
Form[
"movieId"
];
var
db =
Database.
Open
(
"WebPagesMovies"
);
var
deleteCommand =
"DELETE FROM Movies WHERE ID = @0"
;
db.
Execute
(
deleteCommand,
movieId);
Response.
Redirect
(
"~/Movies"
);
}
Ce code est similaire au code utilisé pour mettre à jour un enregistrement, mais plus simple. Le code fonctionne principalement autour d'une instruction SQL Delete.
Comme dans la page EditMovie, le code est dans un bloc if(IsPost). Cette fois-ci, la condition if() est un petit peu plus compliquée :
if
(
IsPost &&
!
Request[
"buttonDelete"
].
IsEmpty
(
))
Il y a deux conditions ici. La première est que la page doit être soumise, comme vous l'avez vu auparavant — if(IsPost).
La deuxième condition est !Request["buttonDelete"].IsEmpty(), ce qui signifie que la requête a un objet nommé buttonDelete. Il faut reconnaître que c'est une façon indirecte de tester quel bouton a soumis le formulaire. Si un formulaire contient plusieurs boutons "soumettre", seul le nom du bouton qui a été cliqué apparaît dans la requête. Par conséquent, et logiquement, si le nom d'un bouton particulier apparaît dans une requête — ou comme indiqué dans le code, si ce bouton n'est pas vide — c'est le bouton qui a soumis le formulaire.
L'opérateur && signifie « ET » (ET logique). Par conséquent la condition if entière est…
Cette requête est un post (pas un premier affichage)
ET
le bouton buttonDelete était celui qui a soumis le formulaire.
Ce formulaire (en fait, cette page) contient seulement un bouton, aussi le test additionnel pour buttonDelete n'est techniquement pas nécessaire. Pourtant, vous êtes sur le point d'effectuer une opération qui va supprimer les données définitivement. Aussi vous voulez être sûr qu'il n'est possible d'effectuer cette opération que lorsque l'utilisateur l'a explicitement demandé. Par exemple, supposons que plus tard vous complétiez cette page avec de nouveaux boutons. Même dans ce cas, le code qui supprime le film ne s'exécutera que si le bouton buttonDelete a été cliqué.
Comme dans la page EditMovie, vous obtenez l'ID du champ caché et ensuite exécutez la commande SQL. La syntaxe pour l'instruction Delete est :
DELETE
FROM
table
WHERE
ID =
value
Il est vital d'inclure la clause WHERE et l'ID. Si vous oubliez la clause WHERE, tous les enregistrements de la table seront supprimés. Comme vous l'avez vu, vous passez la valeur de l'ID à la commande SQL en utilisant les paramètres de substitution. (NdT : requête paramétrée.)
VII. Tester le processus de suppression▲
Maintenant vous pouvez tester. Exécutez la page Movies, et cliquez sur le bouton Delete à côté d'un film. Lorsque la page DeleteMovie apparaît, cliquez sur delete Movie.
Lorsque vous cliquez le bouton, le code supprime le film et vous renvoie vers la liste des films. Là, vous pouvez rechercher le film supprimé et constater qu'il n'est plus présent.
VIII. Prochainement▲
Le prochain tutoriel vous montre comment publier votre site.
IX. Listing complet pour la page Movie (mise à jour avec lien Delete)▲
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.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
@{
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"
];
}
if
(!
Request.
QueryString[
"searchTitle"
].
IsEmpty() ) {
selectCommand =
"SELECT * FROM Movies WHERE Title LIKE @0"
;
searchTerm =
"%"
+
Request.
QueryString[
"searchTitle"
]
+
"%"
;
}
var
selectedData =
db.
Query(selectCommand,
searchTerm);
var
grid =
new
WebGrid(source:
selectedData,
defaultSort:
"Genre"
,
rowsPerPage:
3);
}
<!
DOCTYPE html
>
<html
lang
=
"en"
>
<head>
<meta
charset
=
"utf-8"
/>
<title>
Movies</title>
<style
type
=
"text/css"
>
.grid
{
margin:
4
px;
border-collapse:
collapse
;
width:
600
px;
}
.grid
th,
.grid
td {
border:
1
px solid
#C0C0C0
;
padding:
5
px;
}
.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(format:
@<
a href=
"~/EditMovie?id=@item.ID"
>
Edit</
a>
),
grid.
Column("Title"
),
grid.
Column("Genre"
),
grid.
Column("Year"
),
grid.
Column(format:
@<
a href=
"~/DeleteMovie?id=@item.ID"
>
Delete</
a>
)
)
)
</div>
<p>
<a
href
=
"~/AddMovie"
>
Add a movie</a>
</p>
</body>
</html>
X. Listing complet pour la page DeleteMovie▲
@{
var
title =
""
;
var
genre =
""
;
var
year =
""
;
var
movieId =
""
;
if
(!
IsPost){
if
(!
Request.
QueryString[
"ID"
].
IsEmpty() &&
Request.
QueryString[
"ID"
].
IsInt()){
movieId =
Request.
QueryString[
"ID"
];
var
db =
Database.
Open("WebPagesMovies"
);
var
dbCommand =
"SELECT * FROM Movies WHERE ID = @0"
;
var
row =
db.
QuerySingle(dbCommand,
movieId);
if
(row !=
null
) {
title =
row.
Title;
genre =
row.
Genre;
year =
row.
Year;
}
else
{
Validation.
AddFormError("No movie was found for that ID."
);
}
}
else
{
Validation.
AddFormError("No movie was found for that ID."
);
}
}
if
(IsPost &&
!
Request[
"buttonDelete"
].
IsEmpty()){
movieId =
Request.
Form[
"movieId"
];
var
db =
Database.
Open("WebPagesMovies"
);
var
deleteCommand =
"DELETE FROM Movies WHERE ID = @0"
;
db.
Execute(deleteCommand,
movieId);
Response.
Redirect("~/Movies"
);
}
}
<html>
<head>
<title>
Delete a Movie</title>
</head>
<body>
<h1>
Delete a Movie</h1>
@Html.ValidationSummary()
<p><a
href
=
"~/Movies"
>
Return to movie listing</a></p>
<form
method
=
"post"
>
<fieldset>
<legend>
Movie Information</legend>
<p><span>
Title:</span>
<span>
@title
</span></p>
<p><span>
Genre:</span>
<span>
@genre
</span></p>
<p><span>
Year:</span>
<span>
@year
</span></p>
<input
type
=
"hidden"
name
=
"movieid"
value
=
"@movieId"
/>
<p><input
type
=
"submit"
name
=
"buttonDelete"
value
=
"Delete Movie"
/></p>
</fieldset>
<p><a
href
=
"~/Movies"
>
Return to movie listing</a></p>
</form>
</body>
</html>
XI. Ressources supplémentaires▲
- Introduction to ASP.NET Web Programming by Using the Razor Syntax.
- SQL UPDATE Statement sur le site W3Schools.
XII. Information sur les auteurs▲
Tom FitzMacken — Tom FitzMacken est un auteur senior dans la programmation de l'équipe suivi du contenu sur la plateforme Web et Outils.
XIII. Postface▲
XIII-A. Remerciements▲
Nous remercions François DORIN pour la relecture et la validation technique et Jacques-jean pour la relecture orthographique.
XIII-B. Sources▲
Traduction de l'article de l'équipe de Microsoft ASP.NET — Introducing ASP.NET Web Pages - Deleting Database Data.