Apresentando Páginas da Web do ASP.NET – Excluindo dados de banco de dados

por Tom FitzMacken

Este tutorial mostra como excluir uma entrada de banco de dados individual. Ele pressupõe que você tenha concluído a série por meio da Atualização de Dados do Banco de Dados no Páginas da Web do ASP.NET.

O que você aprenderá:

  • Como selecionar um registro individual de uma listagem de registros.
  • Como excluir um único registro de um banco de dados.
  • Como marcar que um botão específico foi clicado em um formulário.

Recursos/tecnologias discutidos:

  • O WebGrid auxiliar.
  • O comando SQL Delete .
  • O Database.Execute método para executar um comando SQL Delete .

O que você vai construir

No tutorial anterior, você aprendeu a atualizar um registro de banco de dados existente. Este tutorial é semelhante, exceto que, em vez de atualizar o registro, você o excluirá. Os processos são muito iguais, exceto que a exclusão é mais simples, portanto, este tutorial será curto.

Na página Filmes , você atualizará o WebGrid auxiliar para que ele exiba um link Excluir ao lado de cada filme para acompanhar o link Editar adicionado anteriormente.

Página de filmes mostrando um link Excluir para cada filme

Assim como acontece com a edição, quando você clica no link Excluir , ele leva você a uma página diferente, em que as informações do filme já estão em um formulário:

Página Excluir Filme com um filme exibido

Em seguida, você pode clicar no botão para excluir o registro permanentemente.

Você começará adicionando um link Excluir ao WebGrid auxiliar. Esse link é semelhante ao link Editar que você adicionou em um tutorial anterior.

Abra o arquivo Movies.cshtml .

Altere a WebGrid marcação no corpo da página adicionando uma coluna. Esta é a marcação modificada:

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

A nova coluna é esta:

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

Da maneira como a grade é configurada, a coluna Editar é mais à esquerda na grade e a coluna Excluir é a mais à direita. (Há uma vírgula após a Year coluna agora, caso você não tenha notado isso.) Não há nada de especial sobre onde essas colunas de link vão, e você poderia facilmente colocá-las ao lado umas das outras. Nesse caso, eles são separados para torná-los mais difíceis de misturar.

Página de filmes com links Editar e Detalhes marcados para mostrar que eles não estão próximos uns dos outros

A nova coluna mostra um link (<a> elemento) cujo texto diz "Excluir". O destino do link (seu href atributo) é o código que, em última análise, é resolvido para algo como essa URL, com o id valor diferente para cada filme:

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

Esse link invocará uma página chamada DeleteMovie e passará a ID do filme selecionado.

Este tutorial não entrará em detalhes sobre como esse link é construído, pois ele é quase idêntico ao link Editar do tutorial anterior (Atualizando dados de banco de dados no Páginas da Web do ASP.NET).

Criando a página Excluir

Agora você pode criar a página que será o destino do link Excluir na grade.

Observação

Importante A técnica de selecionar primeiro um registro a ser excluído e, em seguida, usar uma página e um botão separados para confirmar que o processo é extremamente importante para a segurança. Como você leu em tutoriais anteriores, fazer qualquer tipo de alteração em seu site sempre deve ser feito usando um formulário , ou seja, usando uma operação HTTP POST. Se você possibilitou alterar o site apenas clicando em um link (ou seja, usando uma operação GET), as pessoas poderiam fazer solicitações simples para seu site e excluir seus dados. Até mesmo um rastreador de mecanismo de pesquisa que está indexando seu site poderia inadvertidamente excluir dados apenas seguindo links.

Quando seu aplicativo permite que as pessoas alterem um registro, você precisa apresentar o registro ao usuário para edição mesmo assim. Mas você pode estar tentado a ignorar esta etapa para excluir um registro. No entanto, não pule essa etapa. (Também é útil que os usuários vejam o registro e confirmem que estão excluindo o registro pretendido.)

Em um conjunto de tutoriais subsequente, você verá como adicionar a funcionalidade de logon para que um usuário precise fazer logon antes de excluir um registro.

Crie uma página chamada DeleteMovie.cshtml e substitua o que está no arquivo pela seguinte marcação:

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

Essa marcação é como as páginas EditMovie , exceto que, em vez de usar caixas de texto (<input type="text">), a marcação inclui <span> elementos. Não há nada aqui para editar. Tudo o que você precisa fazer é exibir os detalhes do filme para que os usuários possam ter certeza de que estão excluindo o filme certo.

A marcação já contém um link que permite que o usuário retorne à página de listagem de filmes.

Como na página EditMovie , a ID do filme selecionado é armazenada em um campo oculto. (Ele é passado para a página em primeiro lugar como um valor de cadeia de caracteres de consulta.) Há uma Html.ValidationSummary chamada que exibirá erros de validação. Nesse caso, o erro pode ser que nenhuma ID de filme foi passada para a página ou que a ID do filme é inválida. Essa situação pode ocorrer se alguém executou esta página sem primeiro selecionar um filme na página Filmes .

O botão legenda é Excluir Filme e seu atributo de nome é definido buttonDeletecomo . O name atributo será usado no código para identificar o botão que enviou o formulário.

Você precisará escrever código para 1) ler os detalhes do filme quando a página for exibida pela primeira vez e 2) realmente excluir o filme quando o usuário clicar no botão.

Adicionando código para ler um único filme

Na parte superior da página DeleteMovie.cshtml , adicione o seguinte bloco de código:

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

Essa marcação é a mesma que o código correspondente na página EditMovie . Ele obtém a ID do filme da cadeia de caracteres de consulta e usa a ID para ler um registro do banco de dados. O código inclui o teste de validação (IsInt() e row != null) para garantir que a ID do filme que está sendo passada para a página seja válida.

Lembre-se de que esse código só deve ser executado na primeira vez que a página for executada. Você não deseja ler novamente o registro de filme do banco de dados quando o usuário clica no botão Excluir Filme . Portanto, o código para ler o filme está dentro de um teste que diz if(!IsPost) — ou seja, se a solicitação não for uma operação pós-operação (envio de formulário).

Adicionando código para excluir o filme selecionado

Para excluir o filme quando o usuário clicar no botão, adicione o seguinte código dentro da chave de fechamento do @ bloco:

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

Esse código é semelhante ao código para atualizar um registro existente, mas mais simples. O código basicamente executa uma instrução SQL Delete .

Como na página EditMovie , o código está em um if(IsPost) bloco. Desta vez, a if() condição é um pouco mais complicada:

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

Há duas condições aqui. A primeira é que a página está sendo enviada, como você já viu antes — if(IsPost).

A segunda condição é !Request["buttonDelete"].IsEmpty(), o que significa que a solicitação tem um objeto chamado buttonDelete. É uma maneira indireta de testar qual botão enviou o formulário. Se um formulário contiver vários botões de envio, somente o nome do botão que foi clicado aparecerá na solicitação. Portanto, logicamente, se o nome de um botão específico aparecer na solicitação ou conforme indicado no código, se esse botão não estiver vazio, esse será o botão que enviou o formulário.

O && operador significa "e" (AND lógico). Portanto, toda if a condição é ...

Essa solicitação é uma postagem (não uma solicitação pela primeira vez)

AND

ObuttonDeletefoi o botão que enviou o formulário.

Esse formulário (na verdade, esta página) contém apenas um botão, portanto, o teste adicional para buttonDelete tecnicamente não é necessário. Ainda assim, você está prestes a executar uma operação que removerá permanentemente os dados. Portanto, você deseja ter a maior certeza possível de que está executando a operação somente quando o usuário a solicitou explicitamente. Por exemplo, suponha que você expandiu essa página mais tarde e adicionou outros botões a ela. Mesmo assim, o código que exclui o filme será executado somente se o buttonDelete botão tiver sido clicado.

Como na página EditMovie , você obtém a ID do campo oculto e, em seguida, executa o comando SQL. A sintaxe da instrução Delete é:

DELETE FROM table WHERE ID = value

É vital incluir a WHERE cláusula e a ID. Se você deixar de fora a cláusula WHERE, todos os registros na tabela serão excluídos. Como você viu, passe o valor da ID para o comando SQL usando um espaço reservado.

Testando o processo de exclusão de filme

Agora você pode testar. Execute a página Filmes e clique em Excluir ao lado de um filme. Quando a página DeleteMovie for exibida, clique em Excluir Filme.

Excluir página Filme com o botão Excluir Filme realçado

Quando você clica no botão, o código exclui os filmes e retorna à listagem de filmes. Lá, você pode pesquisar o filme excluído e confirmar se ele foi excluído.

Próximo

O próximo tutorial mostra como dar a todas as páginas do seu site uma aparência e um layout comuns.

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

Lista completa para a página 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>

Recursos adicionais