Condividi tramite


Introduzione Pagine Web ASP.NET - Eliminazione dei dati del database

di Tom FitzMacken

Questa esercitazione illustra come eliminare una singola voce di database. Si presuppone che la serie sia stata completata tramite l'aggiornamento dei dati del database in Pagine Web ASP.NET.

Contenuto dell'esercitazione:

  • Come selezionare un singolo record da un elenco di record.
  • Come eliminare un singolo record da un database.
  • Come verificare che sia stato fatto clic su un pulsante specifico in un modulo.

Funzionalità/tecnologie descritte:

  • Helper WebGrid .
  • Comando SQL Delete .
  • Metodo Database.Execute per eseguire un comando SQL Delete .

Scopo dell'esercitazione

Nell'esercitazione precedente si è appreso come aggiornare un record di database esistente. Questa esercitazione è simile, ad eccezione del fatto che invece di aggiornare il record, verrà eliminato. I processi sono molto uguali, ad eccezione del fatto che l'eliminazione è più semplice, quindi questa esercitazione sarà breve.

Nella pagina Film aggiornerai l'helper WebGrid in modo che visualizzi un collegamento Elimina accanto a ogni filmato per accompagnare il collegamento Modifica aggiunto in precedenza.

Pagina Film che mostra un collegamento Elimina per ogni film

Come per la modifica, quando si fa clic sul collegamento Elimina , si passa a una pagina diversa, in cui le informazioni sui film sono già in un modulo:

Elimina pagina Film con un filmato visualizzato

È quindi possibile fare clic sul pulsante per eliminare definitivamente il record.

Si inizierà aggiungendo un collegamento Elimina all'helper WebGrid . Questo collegamento è simile al collegamento Modifica aggiunto in un'esercitazione precedente.

Aprire il file Movies.cshtml .

Modificare il WebGrid markup nel corpo della pagina aggiungendo una colonna. Ecco il markup modificato:

@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 nuova colonna è la seguente:

grid.Column(format: @<a href="~/DeleteMovie?id=@item.ID">Delete</a>)

La modalità di configurazione della griglia, la colonna Modifica è all'estrema sinistra nella griglia e la colonna Elimina è all'estrema destra. Dopo la Year colonna è presente una virgola, nel caso in cui non sia stato notato. Non c'è niente di speciale su dove vanno queste colonne di collegamento, e si potrebbe facilmente inserirle l'una accanto all'altra. In questo caso, sono separati per renderli più difficili da mescolare.

Pagina Film con collegamenti Modifica e Dettagli contrassegnati per mostrare che non si trovano l'uno accanto all'altro

La nuova colonna mostra un collegamento (<a> elemento) il cui testo indica "Delete". La destinazione del collegamento (attributo) href è il codice che alla fine si risolve in un valore simile a questo URL, con il id valore diverso per ogni filmato:

http://localhost:43097/DeleteMovie?id=7

Questo collegamento richiamerà una pagina denominata DeleteMovie e passerà l'ID del film selezionato.

Questa esercitazione non illustra in dettaglio il modo in cui viene costruito questo collegamento, perché è quasi identico al collegamento Modifica dell'esercitazione precedente (aggiornamento dei dati del database in Pagine Web ASP.NET).

Creazione della pagina Elimina

È ora possibile creare la pagina che sarà la destinazione per il collegamento Elimina nella griglia.

Nota

Importante La tecnica di selezionare prima un record da eliminare e quindi usare una pagina e un pulsante separati per verificare che il processo sia estremamente importante per la sicurezza. Come hai letto nelle esercitazioni precedenti, apportare qualsiasi tipo di modifica al tuo sito Web dovrebbe sempre essere fatto usando un modulo, ovvero usando un'operazione HTTP POST. Se è stato possibile modificare il sito semplicemente facendo clic su un collegamento (ovvero usando un'operazione GET), le persone potrebbero effettuare richieste semplici al sito ed eliminare i dati. Anche un crawler del motore di ricerca che indicizza il sito potrebbe inavvertitamente eliminare i dati seguendo i collegamenti seguenti.

Quando l'app consente agli utenti di modificare un record, è necessario presentare comunque il record all'utente per la modifica. Ma si potrebbe essere tentati di ignorare questo passaggio per l'eliminazione di un record. Tuttavia, non ignorare questo passaggio. È anche utile per gli utenti visualizzare il record e verificare che stia eliminando il record previsto.

In un set di esercitazioni successivo verrà illustrato come aggiungere funzionalità di accesso in modo che un utente dovrà accedere prima di eliminare un record.

Creare una pagina denominata DeleteMovie.cshtml e sostituire il contenuto del file con il markup seguente:

<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>

Questo markup è simile alle pagine EditMovie , ad eccezione del fatto che invece di usare caselle di testo (<input type="text">), il markup include <span> elementi. Non c'è niente da modificare. Tutto quello che devi fare è visualizzare i dettagli del film in modo che gli utenti possano assicurarsi che eliminino il film corretto.

Il markup contiene già un collegamento che consente all'utente di tornare alla pagina di presentazione dei film.

Come nella pagina EditMovie , l'ID del film selezionato viene archiviato in un campo nascosto. Viene passato nella pagina al primo posto come valore della stringa di query. È presente una Html.ValidationSummary chiamata che visualizzerà gli errori di convalida. In questo caso, l'errore potrebbe essere che non è stato passato alcun ID filmato alla pagina o che l'ID filmato non sia valido. Questa situazione può verificarsi se qualcuno ha eseguito questa pagina senza prima selezionare un film nella pagina Film .

La didascalia del pulsante è Delete Movie e il relativo attributo name è impostato su buttonDelete. L'attributo name verrà usato nel codice per identificare il pulsante che ha inviato il modulo.

Dovrai scrivere codice su 1) leggere i dettagli del film quando la pagina viene visualizzata per la prima volta e 2) eliminare effettivamente il filmato quando l'utente fa clic sul pulsante.

Aggiunta di codice per la lettura di un singolo film

Nella parte superiore della pagina DeleteMovie.cshtml aggiungere il blocco di codice seguente:

@{
    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.");
        }
    }
}

Questo markup è uguale al codice corrispondente nella pagina EditMovie . Ottiene l'ID filmato dalla stringa di query e usa l'ID per leggere un record dal database. Il codice include il test di convalida (IsInt() e row != null) per assicurarsi che l'ID filmato passato alla pagina sia valido.

Tenere presente che questo codice deve essere eseguito solo la prima volta che viene eseguita la pagina. Non vuoi rileggere il record del film dal database quando l'utente fa clic sul pulsante Elimina film . Pertanto, il codice per leggere il film è all'interno di un test che dice if(!IsPost) , ovvero se la richiesta non è un'operazione post (invio modulo).

Aggiunta di codice per eliminare il filmato selezionato

Per eliminare il filmato quando l'utente fa clic sul pulsante, aggiungere il codice seguente all'interno della parentesi graffa di chiusura del @ blocco:

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");
}

Questo codice è simile al codice per l'aggiornamento di un record esistente, ma più semplice. Il codice esegue fondamentalmente un'istruzione SQL Delete .

Come nella pagina EditMovie , il codice si trova in un if(IsPost) blocco. Questa volta, la if() condizione è un po'più complicata:

if(IsPost && !Request["buttonDelete"].IsEmpty())

Ci sono due condizioni qui. Il primo è che la pagina viene inviata, come si è visto in precedenza : if(IsPost).

La seconda condizione è !Request["buttonDelete"].IsEmpty(), vale a dire che la richiesta ha un oggetto denominato buttonDelete. È un modo indiretto per testare il pulsante che ha inviato il modulo. Se un modulo contiene più pulsanti di invio, nella richiesta viene visualizzato solo il nome del pulsante su cui è stato fatto clic. Pertanto, logicamente, se il nome di un particolare pulsante viene visualizzato nella richiesta , o come indicato nel codice, se tale pulsante non è vuoto, è il pulsante che ha inviato il modulo.

L'operatore && indica "and" (AND logico). Pertanto l'intera if condizione è ...

Questa richiesta è un post (non una richiesta per la prima volta)

E

Il buttonDeletepulsante era il pulsante che ha inviato il modulo.

Questo modulo (in effetti, questa pagina) contiene un solo pulsante, quindi il test aggiuntivo per buttonDelete non è tecnicamente obbligatorio. Tuttavia, si sta per eseguire un'operazione che rimuoverà definitivamente i dati. Si vuole quindi essere il più sicuri possibile che si stia eseguendo l'operazione solo quando l'utente l'ha richiesto in modo esplicito. Si supponga, ad esempio, di aver espanso questa pagina in un secondo momento e aggiunto altri pulsanti. Anche allora, il codice che elimina il filmato verrà eseguito solo se è stato fatto clic sul buttonDelete pulsante.

Come nella pagina EditMovie , si ottiene l'ID dal campo nascosto e quindi si esegue il comando SQL. La sintassi per l'istruzione Delete è:

DELETE FROM table WHERE ID = value

È fondamentale includere la WHERE clausola e l'ID. Se si esce dalla clausola WHERE, tutti i record nella tabella verranno eliminati. Come si è visto, si passa il valore ID al comando SQL usando un segnaposto.

Test del processo di eliminazione del filmato

Ora è possibile eseguire il test. Eseguire la pagina Film e fare clic su Elimina accanto a un film. Quando viene visualizzata la pagina DeleteMovie , fare clic su Elimina filmato.

Elimina pagina Film con il pulsante Elimina film evidenziato

Quando si fa clic sul pulsante, il codice elimina i film e torna alla presentazione di film. È possibile cercare il film eliminato e verificare che sia stato eliminato.

Prossimo passaggio

L'esercitazione successiva illustra come assegnare a tutte le pagine del sito un aspetto e un layout comuni.

@{
    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: 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(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>

Elenco completo per la pagina 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>

Risorse aggiuntive