Compartilhar via


Apresentando Páginas da Web do ASP.NET – Inserindo dados de banco de dados usando formulários

por Tom FitzMacken

Este tutorial mostra como criar um formulário de entrada e inserir os dados obtidos do formulário em uma tabela de banco de dados quando você usa Páginas da Web do ASP.NET (Razor). Ele pressupõe que você concluiu a série por meio de Noções básicas de formulários HTML em Páginas da Web do ASP.NET.

O que você aprenderá:

  • Mais sobre como processar formulários de entrada.
  • Como adicionar (inserir) dados em um banco de dados.
  • Como verificar se os usuários inseriram um valor necessário em um formulário (como validar a entrada do usuário).
  • Como exibir erros de validação.
  • Como ir para outra página da página atual.

Recursos/tecnologias discutidos:

  • O método Database.Execute.
  • A instrução SQL Insert Into
  • O Validation auxiliar.
  • O método Response.Redirect.

O que você vai construir

No tutorial anterior que mostrava como criar um banco de dados, você inseriu dados de banco de dados editando o banco de dados diretamente no WebMatrix, trabalhando no workspace Banco de Dados. Na maioria dos aplicativos, essa não é uma maneira prática de colocar dados no banco de dados. Portanto, neste tutorial, você criará uma interface baseada na Web que permite que você ou qualquer pessoa insira dados e salve-os no banco de dados.

Você criará uma página na qual poderá inserir novos filmes. A página conterá um formulário de entrada que tem campos (caixas de texto) em que você pode inserir um título de filme, gênero e ano. A página será semelhante a esta página:

Página 'Adicionar Filme' no navegador

As caixas de texto serão elementos HTML <input> que se parecerão com esta marcação:

<input type="text" name="genre" value="" />

Criando o formulário de entrada básico

Crie uma página chamada AddMovie.cshtml.

Substitua o que está no arquivo pela marcação a seguir. Substituir tudo; você adicionará um bloco de código na parte superior em breve.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Add a Movie</title>
</head>
<body>
  <h1>Add a Movie</h1>
  <form method="post">
    <fieldset>
      <legend>Movie Information</legend>
      <p><label for="title">Title:</label>
         <input type="text" name="title" value="@Request.Form["title"]" />
      </p>

      <p><label for="genre">Genre:</label>
         <input type="text" name="genre" value="@Request.Form["genre"]" />
      </p>

      <p><label for="year">Year:</label>
         <input type="text" name="year" value="@Request.Form["year"]" />
      </p>

      <p><input type="submit" name="buttonSubmit" value="Add Movie" /></p>
    </fieldset>
  </form>
</body>
</html>

Este exemplo mostra HTML típico para criar um formulário. Ele usa elementos para as caixas <input> de texto e para o botão enviar. As legendas das caixas de texto são criadas usando elementos padrão <label> . Os <fieldset> elementos e <legend> colocam uma caixa agradável ao redor do formulário.

Observe que, nesta página, o <form> elemento usa post como o valor do method atributo. No tutorial anterior, você criou um formulário que usava o get método . Isso estava correto porque, embora o formulário tenha enviado valores para o servidor, a solicitação não fez nenhuma alteração. Tudo o que ele fez foi buscar dados de maneiras diferentes. No entanto, nesta página, você fará alterações. Você adicionará novos registros de banco de dados. Portanto, esse formulário deve usar o post método . (Para obter mais informações sobre a diferença entre GET as operações e POST , consulte a barra lateralGET, POST e HTTP Verb Safety no tutorial anterior.)

Observe que cada caixa de texto tem um name elemento (title, genre, year). Como você viu no tutorial anterior, esses nomes são importantes porque você deve ter esses nomes para que possa obter a entrada do usuário mais tarde. Você pode usar qualquer nome. É útil usar nomes significativos que ajudam você a lembrar com quais dados você está trabalhando.

O value atributo de cada <input> elemento contém um pouco de código Razor (por exemplo, Request.Form["title"]). Você aprendeu uma versão desse truque no tutorial anterior para preservar o valor inserido na caixa de texto (se houver) após o envio do formulário.

Obtendo os valores de formulário

Em seguida, adicione o código que processa o formulário. Na estrutura de tópicos, você fará o seguinte:

  1. Verifique se a página está sendo postada (foi enviada). Você deseja que seu código seja executado somente quando os usuários clicarem no botão, não quando a página for executada pela primeira vez.
  2. Obtenha os valores que o usuário inseriu nas caixas de texto. Nesse caso, como o formulário está usando o POST verbo, você obtém os valores de formulário da Request.Form coleção.
  3. Insira os valores como um novo registro na tabela de banco de dados Filmes .

Na parte superior do arquivo, adicione o seguinte código:

@{
    var title = "";
    var genre = "";
    var year = "";

    if(IsPost){
        title = Request.Form["title"];
        genre = Request.Form["genre"];
        year = Request.Form["year"];
    }
}

As primeiras linhas criam variáveis (title, genree year) para manter os valores das caixas de texto. A linha if(IsPost) garante que as variáveis sejam definidas somente quando os usuários clicarem no botão Adicionar Filme , ou seja, quando o formulário tiver sido postado.

Como você viu em um tutorial anterior, você obtém o valor de uma caixa de texto usando uma expressão como Request.Form["name"], em que name é o nome do <input> elemento.

Os nomes das variáveis (title, genree year) são arbitrários. Como os nomes que você atribui aos <input> elementos, você pode chamá-los de qualquer coisa que desejar. (Os nomes das variáveis não precisam corresponder aos atributos de nome dos <input> elementos no formulário.) Mas, assim como acontece com os <input> elementos, é uma boa ideia usar nomes de variáveis que refletem os dados que eles contêm. Quando você escreve código, nomes consistentes facilitam a lembrar com quais dados você está trabalhando.

Adicionando dados ao banco de dados

No bloco de código que você acabou de adicionar, logo dentro da chave de fechamento ( } ) do if bloco (não apenas dentro do bloco de código), adicione o seguinte código:

var db = Database.Open("WebPagesMovies");
var insertCommand = "INSERT INTO Movies (Title, Genre, Year) VALUES(@0, @1, @2)";
db.Execute(insertCommand, title, genre, year);

Este exemplo é semelhante ao código usado em um tutorial anterior para buscar e exibir dados. A linha que começa com db = abre o banco de dados, como antes, e a próxima linha define uma instrução SQL, novamente como você viu antes. No entanto, desta vez, ele define uma instrução SQL Insert Into . O exemplo a seguir mostra a sintaxe geral da instrução Insert Into :

INSERT INTO table (column1, column2, column3, ...) VALUES (value1, value2, value3, ...)

Em outras palavras, especifique a tabela na qual inserir, liste as colunas nas quais inserir e liste os valores a serem inseridos. (Conforme observado anteriormente, o SQL não diferencia maiúsculas de minúsculas, mas algumas pessoas capitalizam as palavras-chave para facilitar a leitura do comando.)

As colunas que você está inserindo no já estão listadas no comando — (Title, Genre, Year). A parte interessante é como você obtém os valores das caixas de texto para a VALUES parte do comando. Em vez de valores reais, você vê @0, @1e @2, que são, naturalmente, espaços reservados. Ao executar o comando (na db.Execute linha), você passa os valores que obteve das caixas de texto.

Importante: Lembre-se de que a única maneira de incluir dados inseridos online por um usuário em uma instrução SQL é usar espaços reservados, como você vê aqui (VALUES(@0, @1, @2)). Se você concatenar a entrada do usuário em uma instrução SQL, você se abrirá para um ataque de injeção de SQL, conforme explicado no Form Basics em Páginas da Web do ASP.NET (o tutorial anterior).

Ainda dentro do if bloco, adicione a seguinte linha após a db.Execute linha:

Response.Redirect("~/Movies");

Depois que o novo filme tiver sido inserido no banco de dados, essa linha saltará você (redireciona) para a página Filmes para que você possa ver o filme que acabou de inserir. O ~ operador significa "raiz do site". (O ~ operador funciona apenas em páginas ASP.NET, não em HTML em geral.)

O bloco de código completo é semelhante a este exemplo:

@{
    var title = "";
    var genre = "";
    var year = "";

    if(IsPost){
        title = Request.Form["title"];
        genre = Request.Form["genre"];
        year = Request.Form["year"];

        var db = Database.Open("WebPagesMovies");
        var insertCommand = "INSERT INTO Movies (Title, Genre, Year) Values(@0, @1, @2)";
        db.Execute(insertCommand, title, genre, year);
        Response.Redirect("~/Movies");
    }
}

Testando o comando Insert (até agora)

Você ainda não terminou, mas agora é uma boa hora para testar.

Na exibição de árvore de arquivos no WebMatrix, clique com o botão direito do mouse na página AddMovie.cshtml e clique em Iniciar no navegador.

A captura de tela mostra a página 'Adicionar Filme' no navegador.

(Se você acabar com uma página diferente no navegador, verifique se a URL é http://localhost:nnnnn/AddMovie), em que nnnnn é o número da porta que você está usando.)

Você teve uma página de erro? Nesse caso, leia-o com cuidado e verifique se o código tem a aparência exata do que foi listado anteriormente.

Insira um filme no formato – por exemplo, use "Cidadão Kane", "Drama" e "1941". (Ou seja lá o que for).) Em seguida, clique em Adicionar Filme.

Se tudo correr bem, você será redirecionado para a página Filmes . Verifique se o novo filme está listado.

Página de filmes mostrando o filme recém-adicionado

Validando entradas de usuário

Voltar à página AddMovie ou execute-a novamente. Insira outro filme, mas desta vez, insira apenas o título , por exemplo, insira "Singin' in the Rain". Em seguida, clique em Adicionar Filme.

Você será redirecionado para a página Filmes novamente. Você pode encontrar o novo filme, mas está incompleto.

Página de filmes mostrando um novo filme que não tem alguns valores

Ao criar a tabela Filmes , você disse explicitamente que nenhum dos campos poderia ser nulo. Aqui você tem um formulário de entrada para novos filmes e está deixando os campos em branco. Isso é um erro.

Nesse caso, o banco de dados não gerou (ou gerou) um erro. Você não forneceu um gênero ou ano, portanto, o código na página AddMovie tratou esses valores como as chamadas cadeias de caracteres vazias. Quando o comando SQL Insert Into foi executado, os campos de gênero e ano não tinham dados úteis, mas não eram nulos.

Obviamente, você não deseja permitir que os usuários insiram informações de filme meio vazias no banco de dados. A solução é validar a entrada do usuário. Inicialmente, a validação simplesmente garantirá que o usuário inseriu um valor para todos os campos (ou seja, que nenhum deles contém uma cadeia de caracteres vazia).

Dica

Cadeias de caracteres nulas e vazias

Na programação, há uma distinção entre diferentes noções de "sem valor". Em geral, um valor será nulo se nunca tiver sido definido ou inicializado de alguma forma. Por outro lado, uma variável que espera dados de caractere (cadeias de caracteres) pode ser definida como uma cadeia de caracteres vazia. Nesse caso, o valor não é nulo; ele foi definido explicitamente como uma cadeia de caracteres cujo comprimento é zero. Essas duas instruções mostram a diferença:

var firstName;       // Not set, so its value is null
var firstName = "";  // Explicitly set to an empty string -- not null

É um pouco mais complicado do que isso, mas o ponto importante é que null representa uma espécie de estado indeterminado.

Agora e depois é importante entender exatamente quando um valor é nulo e quando é apenas uma cadeia de caracteres vazia. No código da página AddMovie , você obtém os valores das caixas de texto usando Request.Form["title"] e assim por diante. Quando a página é executada pela primeira vez (antes de clicar no botão), o valor de Request.Form["title"] é nulo. Mas quando você envia o formulário, Request.Form["title"] obtém o valor da caixa de title texto. Não é óbvio, mas uma caixa de texto vazia não é nula; ele só tem uma cadeia de caracteres vazia. Portanto, quando o código é executado em resposta ao clique do botão, Request.Form["title"] tem uma cadeia de caracteres vazia.

Por que essa distinção é importante? Ao criar a tabela Filmes , você disse explicitamente que nenhum dos campos poderia ser nulo. Mas aqui você tem um formulário de entrada para novos filmes, e você está deixando campos em branco. Você esperaria razoavelmente que o banco de dados reclamasse quando tentasse salvar novos filmes que não tinham valores para gênero ou ano. Mas esse é o ponto , mesmo que você deixe essas caixas de texto em branco, os valores não são nulos; são cadeias de caracteres vazias. Como resultado, você pode salvar novos filmes no banco de dados com essas colunas vazias, mas não nulas! — valores. Portanto, você precisa garantir que os usuários não enviem uma cadeia de caracteres vazia, o que você pode fazer validando a entrada do usuário.

O auxiliar de validação

Páginas da Web do ASP.NET inclui um auxiliar — o Validation auxiliar — que você pode usar para garantir que os usuários insiram dados que atendam aos seus requisitos. O Validation auxiliar é um dos auxiliares integrados ao Páginas da Web do ASP.NET, portanto, você não precisa instalá-lo como um pacote usando o NuGet, a maneira como você instalou o auxiliar gravatar em um tutorial anterior.

Para validar a entrada do usuário, você fará o seguinte:

  • Use o código para especificar que você deseja exigir valores nas caixas de texto na página.
  • Coloque um teste no código para que as informações do filme sejam adicionadas ao banco de dados somente se tudo for validado corretamente.
  • Adicione código à marcação para exibir mensagens de erro.

No bloco de código na página AddMovie , logo na parte superior antes das declarações de variável, adicione o seguinte código:

Validation.RequireField("title", "You must enter a title");
Validation.RequireField("genre", "Genre is required");
Validation.RequireField("year", "You haven't entered a year");

Você chama Validation.RequireField uma vez para cada campo (<input> elemento) em que deseja exigir uma entrada. Você também pode adicionar uma mensagem de erro personalizada para cada chamada, como você vê aqui. (Variamos as mensagens apenas para mostrar que você pode colocar qualquer coisa que quiser lá.)

Se houver um problema, você deseja impedir que as novas informações de filme sejam inseridas no banco de dados. if(IsPost) No bloco , use && (AND lógico) para adicionar outra condição que testa Validation.IsValid(). Quando você terminar, o bloco inteiro if(IsPost) será semelhante a este código:

if(IsPost && Validation.IsValid()){
    title = Request.Form["title"];
    genre = Request.Form["genre"];
    year = Request.Form["year"];

    var db = Database.Open("WebPagesMovies");
    var insertCommand = "INSERT INTO Movies (Title, Genre, Year) Values(@0, @1, @2)";
    db.Execute(insertCommand, title, genre, year);
    Response.Redirect("~/Movies");
}

Se houver um erro de validação com qualquer um dos campos registrados usando o Validation auxiliar , o Validation.IsValid método retornará false. Nesse caso, nenhum código nesse bloco será executado, portanto, nenhuma entrada de filme inválida será inserida no banco de dados. E, claro, você não será redirecionado para a página Filmes .

O bloco de código completo, incluindo o código de validação, agora se parece com este exemplo:

@{
    Validation.RequireField("title", "You must enter a title");
    Validation.RequireField("genre", "Genre is required");
    Validation.RequireField("year", "You haven't entered a year");

    var title = "";
    var genre = "";
    var year = "";

    if(IsPost && Validation.IsValid()){
       title = Request.Form["title"];
       genre = Request.Form["genre"];
       year = Request.Form["year"];

       var db = Database.Open("WebPagesMovies");
       var insertCommand = "INSERT INTO Movies (Title, Genre, Year) Values(@0, @1, @2)";
       db.Execute(insertCommand, title, genre, year);
       Response.Redirect("~/Movies");
    }
}

Exibindo erros de validação

A última etapa é exibir mensagens de erro. Você pode exibir mensagens individuais para cada erro de validação ou exibir um resumo ou ambos. Para este tutorial, você fará as duas coisas para que possa ver como ela funciona.

Ao lado de cada <input> elemento que você está validando, chame o Html.ValidationMessage método e passe o nome do <input> elemento que você está validando. Você coloca o Html.ValidationMessage método exatamente onde deseja que a mensagem de erro apareça. Quando a página é executada, o Html.ValidationMessage método renderiza um <span> elemento para o qual o erro de validação irá. (Se não houver erro, o <span> elemento será renderizado, mas não há texto nele.)

Altere a marcação na página para que ela inclua um método para cada um Html.ValidationMessage dos três <input> elementos na página, como neste exemplo:

<p><label for="title">Title:</label>
     <input type="text" name="title" value="@Request.Form["title"]" />
      @Html.ValidationMessage("title")
  </p>

  <p><label for="genre">Genre:</label>
     <input type="text" name="genre" value="@Request.Form["genre"]" />
      @Html.ValidationMessage("genre")
  </p>

  <p><label for="year">Year:</label>
     <input type="text" name="year" value="@Request.Form["year"]" />
      @Html.ValidationMessage("year")
  </p>

Para ver como o resumo funciona, adicione também a seguinte marcação e código logo após o <h1>Add a Movie</h1> elemento na página:

@Html.ValidationSummary()

Por padrão, o Html.ValidationSummary método exibe todas as mensagens de validação em uma lista (um <ul> elemento que está dentro de um <div> elemento). Assim como acontece com o Html.ValidationMessage método , a marcação para o resumo de validação é sempre renderizada; se não houver erros, nenhum item de lista será renderizado.

O resumo pode ser uma maneira alternativa de exibir mensagens de validação em vez de usar o Html.ValidationMessage método para exibir cada erro específico do campo. Ou você pode usar um resumo e os detalhes. Ou você pode usar o Html.ValidationSummary método para exibir um erro genérico e, em seguida, usar chamadas individuais Html.ValidationMessage para exibir detalhes.

A página completa agora se parece com este exemplo:

@{
    Validation.RequireField("title", "You must enter a title");
    Validation.RequireField("genre", "Genre is required");
    Validation.RequireField("year", "You haven't entered a year");

    var title = "";
    var genre = "";
    var year = "";

    if(IsPost && Validation.IsValid()){
       title = Request.Form["title"];
       genre = Request.Form["genre"];
       year = Request.Form["year"];

       var db = Database.Open("WebPagesMovies");
       var insertCommand = "INSERT INTO Movies (Title, Genre, Year) Values(@0, @1, @2)";
       db.Execute(insertCommand, title, genre, year);
       Response.Redirect("~/Movies");
    }
}

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <title>Add a Movie</title>
</head>
<body>
  <h1>Add a Movie</h1>
  @Html.ValidationSummary()
  <form method="post">
    <fieldset>
      <legend>Movie Information</legend>
      <p><label for="title">Title:</label>
         <input type="text" name="title" value="@Request.Form["title"]" />
          @Html.ValidationMessage("title")
      </p>

      <p><label for="genre">Genre:</label>
         <input type="text" name="genre" value="@Request.Form["genre"]" />
          @Html.ValidationMessage("genre")
      </p>

      <p><label for="year">Year:</label>
         <input type="text" name="year" value="@Request.Form["year"]" />
          @Html.ValidationMessage("year")
      </p>

      <p><input type="submit" name="buttonSubmit" value="Add Movie" /></p>
    </fieldset>
  </form>
</body>
</html>

É isso. Agora você pode testar a página adicionando um filme, mas deixando de fora um ou mais dos campos. Ao fazer isso, você verá a seguinte exibição de erro:

Página Adicionar Filme mostrando mensagens de erro de validação

Estilizando as mensagens de erro de validação

Você pode ver que há mensagens de erro, mas elas realmente não se destacam muito bem. No entanto, há uma maneira fácil de estilizar as mensagens de erro.

Para definir o estilo das mensagens de erro individuais exibidas pelo Html.ValidationMessage, crie uma classe de estilo CSS chamada field-validation-error. Para definir a aparência do resumo de validação, crie uma classe de estilo CSS chamada validation-summary-errors.

Para ver como essa técnica funciona, adicione um <style> elemento dentro da <head> seção da página. Em seguida, defina classes de estilo chamadas field-validation-error e validation-summary-errors que contenham as seguintes regras:

<head>
  <meta charset="utf-8" />
  <title>Add a Movie</title>
  <style type="text/css">
    .field-validation-error {
      font-weight:bold;
      color:red;
      background-color:yellow;
     }
    .validation-summary-errors{
      border:2px dashed red;
      color:red;
      background-color:yellow;
      font-weight:bold;
      margin:12px;
    }
  </style>
</head>

Normalmente, você provavelmente colocaria informações de estilo em um arquivo .css separado, mas para simplificar, você pode colocá-las na página por enquanto. (Posteriormente neste conjunto de tutoriais, você moverá as regras do CSS para um arquivo .css separado.)

Se houver um erro de validação, o Html.ValidationMessage método renderizará um <span> elemento que inclui class="field-validation-error". Ao adicionar uma definição de estilo para essa classe, você pode configurar a aparência da mensagem. Se houver erros, o ValidationSummary método também renderizará dinamicamente o atributo class="validation-summary-errors".

Execute a página novamente e deixe de fora deliberadamente alguns dos campos. Os erros agora são mais perceptíveis. (Na verdade, eles são exagerados, mas isso é apenas para mostrar o que você pode fazer.)

Página Adicionar Filme mostrando erros de validação que foram estilizados

Uma etapa final é tornar conveniente acessar a página AddMovie a partir da listagem de filmes original.

Abra a página Filmes novamente. Após a marca de fechamento </div> que segue o WebGrid auxiliar, adicione a seguinte marcação:

<p>
  <a href="~/AddMovie">Add a movie</a>
</p>

Como você viu antes, ASP.NET interpreta o ~ operador como a raiz do site. Você não precisa usar o ~ operador ; você pode usar a marcação <a href="./AddMovie">Add a movie</a> ou alguma outra maneira de definir o caminho que o HTML entende. Mas o ~ operador é uma boa abordagem geral quando você cria links para páginas razor, pois torna o site mais flexível — se você mover a página atual para uma subpasta, o link ainda irá para a página AddMovie . (Lembre-se de que o ~ operador só funciona em páginas .cshtml . ASP.NET entende, mas não é HTML padrão.)

Quando terminar, execute a página Filmes . Ele será semelhante a esta página:

Página Filmes com link para a página 'Adicionar Filmes'

Clique no link Adicionar um filme para verificar se ele vai para a página AddMovie .

Próximo passo a seguir

No próximo tutorial, você aprenderá a permitir que os usuários editem dados que já estão no banco de dados.

Lista completa para a página AddMovie

@{

    Validation.RequireField("title", "You must enter a title");
    Validation.RequireField("genre", "Genre is required");
    Validation.RequireField("year", "You haven't entered a year");

    var title = "";
    var genre = "";
    var year = "";

    if(IsPost && Validation.IsValid()){
       title = Request.Form["title"];
       genre = Request.Form["genre"];
       year = Request.Form["year"];

       var db = Database.Open("WebPagesMovies");
       var insertCommand = "INSERT INTO Movies (Title, Genre, Year) Values(@0, @1, @2)";
       db.Execute(insertCommand, title, genre, year);
       Response.Redirect("~/Movies");
    }
}

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Add a Movie</title>
      <style type="text/css">
    .field-validation-error {
      font-weight:bold;
      color:red;
      background-color:yellow;
     }
    .validation-summary-errors{
      border:2px dashed red;
      color:red;
      background-color:yellow;
      font-weight:bold;
      margin:12px;
    }
  </style>
</head>
<body>
  <h1>Add a Movie</h1>
  @Html.ValidationSummary()
  <form method="post">
    <fieldset>
      <legend>Movie Information</legend>
      <p><label for="title">Title:</label>
         <input type="text" name="title" value="@Request.Form["title"]" />
          @Html.ValidationMessage("title")
      </p>

      <p><label for="genre">Genre:</label>
         <input type="text" name="genre" value="@Request.Form["genre"]" />
         @Html.ValidationMessage("genre")
      </p>

      <p><label for="year">Year:</label>
         <input type="text" name="year" value="@Request.Form["year"]" />
          @Html.ValidationMessage("year")
      </p>

      <p><input type="submit" name="buttonSubmit" value="Add Movie" /></p>
    </fieldset>
  </form>
</body>
</html>

Recursos adicionais