Apresentando Páginas da Web do ASP.NET-excluindo dados do banco

por Tom FitzMacken

Este tutorial mostra como excluir uma entrada de banco de dados individual. Ele pressupõe que você concluiu 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 lista de registros.
  • Como excluir um único registro de um banco de dados.
  • Como verificar se um botão específico foi clicado em um formulário.

Recursos/tecnologias abordados:

  • O auxiliar de WebGrid.
  • O comando SQL Delete.
  • O método Database.Execute 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 semelhantes, 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 de exclusão ao lado de cada filme para acompanhar o link de edição adicionado anteriormente.

Página de filmes mostrando um link de exclusão para cada filme

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

Excluir página de filme com um filme exibido

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

Você começará adicionando um link de exclusão ao auxiliar de WebGrid. Esse link é semelhante ao link de edição que você adicionou em um tutorial anterior.

Abra o arquivo Movies. cshtml .

Altere a marcação de WebGrid no corpo da página adicionando uma coluna. Aqui está 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>)

A maneira como a grade é configurada, a coluna de edição fica 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 colocá-las facilmente ao lado umas das outras. Nesse caso, eles são separados para torná-los mais difíceis de serem misturados.

Página de filmes com links de edição 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 atributo href) é o código que, em última instância, é resolvido para algo como essa URL, com o valor de id diferente para cada filme:

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

Esse link invocará uma página chamada DeleteMovie e passará a ID do filme que você selecionou.

Este tutorial não entrará em detalhes sobre como esse link é construído, pois ele é quase idêntico ao link de edição do tutorial anterior (atualizando dados de banco em 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 de exclusão na grade.

Note

Importante A técnica de primeiro selecionar um registro para excluir e, em seguida, usar uma página e um botão separados para confirmar se o processo é extremamente importante para a segurança. Como você leu nos 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ê tornou possível alterar o site apenas clicando em um link (ou seja, usando uma operação GET), as pessoas podem fazer solicitações simples ao seu site e excluir seus dados. Até mesmo um rastreador de mecanismo de pesquisa que está indexando seu site pode excluir dados inadvertidamente apenas pelos links a seguir.

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

Em um conjunto de tutorial 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 elementos <span>. 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 correto.

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 chamada Html.ValidationSummary 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 seja inválida. Essa situação pode ocorrer se alguém executar essa página sem primeiro selecionar um filme na página filmes .

A legenda do botão é excluir filmee seu atributo Name é definido como buttonDelete. O atributo name 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), na verdade, 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 é igual ao 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 em que a página for executada. Você não deseja ler novamente o registro do 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 post (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 apenas dentro da chave de fechamento do bloco de @:

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 bloco de if(IsPost). Desta vez, a condição de if() é 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ê viu antes de — if(IsPost).

A segunda condição é !Request["buttonDelete"].IsEmpty(), o que significa que a solicitação tem um objeto chamado buttonDelete. Reconhecidamente, é 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 for exibido na solicitação — ou conforme indicado no código, se esse botão não estiver vazio — é o botão que enviou o formulário.

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

Esta solicitação é uma postagem (não é uma solicitação de primeira vez)

AND

O botão de buttonDeletefoi o botão que enviou o formulário.

Esse formulário (na verdade, essa 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ê deve ter a certeza de que está executando a operação somente quando o usuário a solicitou explicitamente. Por exemplo, suponha que você expandiu essa página posteriormente e adicionou outros botões a ela. Mesmo assim, o código que exclui o filme será executado somente se o botão de buttonDelete foi clicado.

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

DELETE FROM table WHERE ID = value

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

Testando o processo de exclusão do 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.

Página excluir filme com o botão excluir filme realçado

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

Chegando em seguida

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

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

Listagem completa da 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