Поделиться через


Знакомство с веб-страницы ASP.NET. Ввод данных базы данных с помощью форм

; автор — Том ФитцМакен (Tom FitzMacken)

В этом руководстве показано, как создать форму записи, а затем ввести данные, полученные из формы, в таблицу базы данных при использовании веб-страницы ASP.NET (Razor). Предполагается, что вы завершили серию по основам HTML-форм в веб-страницы ASP.NET.

Из этого руководства вы узнаете, как выполнять такие задачи:

  • Дополнительные сведения о том, как обрабатывать формы ввода.
  • Добавление (вставка) данных в базу данных.
  • Как убедиться, что пользователи ввели требуемое значение в форме (как проверить введенные пользователем данные).
  • Отображение ошибок проверки.
  • Переход на другую страницу с текущей страницы.

Обсуждаемые функции и технологии:

  • метод Database.Execute ;
  • Инструкция SQL Insert Into
  • Помощник Validation .
  • метод Response.Redirect ;

Что вы создадите

В предыдущем руководстве, где показано, как создать базу данных, вы ввели данные базы данных, изменив базу данных непосредственно в WebMatrix, работая в рабочей области База данных . Однако в большинстве приложений это не практический способ поместить данные в базу данных. Поэтому в этом руководстве вы создадите веб-интерфейс, который позволяет вводить данные и сохранять их в базе данных.

Вы создадите страницу, на которой можно вводить новые фильмы. Страница будет содержать форму записи с полями (текстовыми полями), где можно ввести название фильма, жанр и год. Страница будет выглядеть следующим образом:

Страница

Текстовые поля будут элементами HTML <input> , которые будут выглядеть следующим образом:

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

Создание базовой формы записи

Создайте страницу с именем AddMovie.cshtml.

Замените содержимое файла следующей разметкой. Перезаписать все; Вскоре вы добавите блок кода в верхней части окна.

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

В этом примере показан типичный HTML-код для создания формы. В нем используются <input> элементы для текстовых полей и для кнопки отправки. Заголовки для текстовых полей создаются с помощью стандартных <label> элементов. Элементы <fieldset> и <legend> помещают вокруг формы хорошую рамку.

Обратите внимание, <form> что на этой странице элемент использует post в качестве значения атрибута method . В предыдущем руководстве вы создали форму, которая использовала get метод . Это было правильно, так как, хотя форма отправила значения на сервер, запрос не внося никаких изменений. Все, что он сделал, это получить данные по-разному. Однако на этой странице вы внесете изменения— вы добавите новые записи базы данных. Поэтому в этой форме следует использовать post метод . (Дополнительные сведения о различиях между GET операциями и POST см. в боковой панелиGET, POST и HTTP Verb Safety в предыдущем руководстве.)

Обратите внимание, что каждое текстовое name поле содержит элемент (title, genre, year). Как вы видели в предыдущем руководстве, эти имена важны, так как они должны быть, чтобы получить входные данные пользователя позже. Можно использовать любые имена. Полезно использовать понятные имена, которые помогут вам запомнить, с какими данными вы работаете.

Атрибут value каждого <input> элемента содержит немного кода Razor (например, Request.Form["title"]). Вы узнали версию этого трюка из предыдущего руководства, чтобы сохранить значение, введенное в текстовое поле (если таковое имеется) после отправки формы.

Получение значений формы

Затем добавьте код, обрабатывающий форму. В структуре вы выполните следующие действия.

  1. Проверьте, размещена ли страница (отправлена). Вы хотите, чтобы код выполнялся только при нажатии кнопки, а не при первом запуске страницы.
  2. Получение значений, введенных пользователем в текстовых полях. В этом случае, так как в форме используется POST глагол, значения формы получаются из Request.Form коллекции.
  3. Вставьте значения в виде новой записи в таблицу базы данных Movies .

В верхней части файла добавьте следующий код:

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

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

Первые несколько строк создают переменные (title, genreи year) для хранения значений из текстовых полей. Строка if(IsPost) гарантирует, что переменные задаются только при нажатии пользователем кнопки Добавить фильм , то есть при публикации формы.

Как вы видели в предыдущем руководстве, значение текстового поля можно получить с помощью выражения, например Request.Form["name"], где name — это имя <input> элемента.

Имена переменных (title, genreи year) являются произвольными. Как и имена, присваиваемые <input> элементам, их можно называть любым способом. (Имена переменных не обязательно должны соответствовать атрибутам имен элементов <input> в форме.) Но, как и в случае с элементами <input> , рекомендуется использовать имена переменных, отражающие содержащиеся в них данные. При написании кода согласованные имена упрощают запоминать данные, с которыми вы работаете.

Добавление данных в базу данных

В добавленном блоке кода в закрывающей скобке ( } ) if блока (а не внутри блока кода) добавьте следующий код:

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

Этот пример аналогичен коду, который использовался в предыдущем руководстве для получения и отображения данных. Строка, начинающаяся с db = , открывает базу данных, как и раньше, а следующая строка снова определяет инструкцию SQL, как вы видели ранее. Однако на этот раз он определяет инструкцию SQL Insert Into . В следующем примере показан общий Insert Into синтаксис оператора :

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

Другими словами, вы указываете таблицу для вставки, а затем выводите список столбцов для вставки, а затем выводите список значений для вставки. (Как отмечалось ранее, в SQL не учитывается регистр, но некоторые люди заглавные буквы ключевые слова упрощают чтение команды.)

Столбцы, в которые вы вставляете данные, уже перечислены в команде — (Title, Genre, Year). Интересно, как получить значения из текстовых полей в VALUES часть команды. Вместо фактических значений отображаются @0, @1и @2, которые, конечно, являются заполнителями. При выполнении команды (в строке db.Execute ) передаются значения, полученные из текстовых полей.

Важно! Помните, что единственный способ включить данные, введенные пользователем в режиме "в сети" в инструкцию SQL, — использовать заполнители, как показано здесь (VALUES(@0, @1, @2)). Если сцепить введенные пользователем данные в инструкцию SQL, вы откроете для себя атаку путем внедрения кода SQL, как описано в разделе Основные сведения о формах в веб-страницы ASP.NET (предыдущее руководство).

В блоке if добавьте следующую строку после db.Execute строки:

Response.Redirect("~/Movies");

После вставки нового фильма в базу данных эта строка перенаправляет вас на страницу Фильмы , чтобы увидеть только что введенный фильм. Оператор ~ означает "корень веб-сайта". (Оператор ~ работает только на ASP.NET страницах, а не в HTML-коде.)

Полный блок кода выглядит следующим образом:

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

Тестирование команды Insert (Пока)

Вы еще не закончили, но сейчас хорошее время для тестирования.

В древовидном представлении файлов в WebMatrix щелкните правой кнопкой мыши страницу AddMovie.cshtml и выберите команду Запустить в браузере.

Снимок экрана: страница

(Если в браузере отображается другая страница, убедитесь, что URL-адрес — http://localhost:nnnnn/AddMovie), где nnnnn — это номер порта, который вы используете.)

Вы получили страницу ошибки? Если да, внимательно прочтите его и убедитесь, что код выглядит точно так, как указано ранее.

Введите фильм в форме, например "Гражданин Кейн", "Драма" и "1941". (Или что-то еще.) Затем нажмите кнопку Добавить фильм.

Если все пойдет хорошо, вы будете перенаправлены на страницу Фильмы . Убедитесь, что новый фильм указан в списке.

Страница

Проверка введенного пользователем

Назад на страницу AddMovie или запустите ее еще раз. Введите другой фильм, но на этот раз введите только заголовок, например "Singin' in the Rain". Затем нажмите кнопку Добавить фильм.

Вы снова будете перенаправлены на страницу Фильмы . Вы можете найти новый фильм, но он неполный.

Страница

При создании таблицы Movies вы явно указали, что ни одно из полей не может иметь значение NULL. Здесь у вас есть форма записи для новых фильмов, и вы оставляете поля пустыми. Это ошибка.

В этом случае база данных не вызвала (или не вызвала) ошибку. Вы не указали жанр или год, поэтому код на странице AddMovie рассматривал эти значения как так называемые пустые строки. При выполнении команды SQL Insert Into в полях жанра и года не было полезных данных, но они не были пустыми.

Очевидно, что вы не хотите, чтобы пользователи вводили в базу данных полупустую информацию о фильмах. Решение заключается в проверке введенных пользователем данных. Изначально проверка будет просто убедиться, что пользователь ввел значение для всех полей (т. е. ни одно из них не содержит пустую строку).

Совет

Пустые и пустые строки

В программировании существует различие между разными понятиями "нет ценности". Как правило, значение равно NULL , если оно никогда не было задано или инициализировано каким-либо образом. Напротив, для переменной, которая ожидает символьные данные (строки), можно задать пустую строку. В этом случае значение не равно NULL; Для нее просто явно задана строка символов, длина которых равна нулю. Эти два оператора показывают разницу:

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

Это немного сложнее, чем это, но важно то, что null представляет своего рода неопределенное состояние.

Время от времени важно точно понимать, когда значение равно NULL, а когда это просто пустая строка. В коде страницы AddMovie значения текстовых полей можно получить с помощью Request.Form["title"] и т. д. При первом запуске страницы (перед нажатием кнопки) значение Request.Form["title"] равно NULL. Но при отправке формы Request.Form["title"] получает значение текстового title поля. Это не очевидно, но пустое текстовое поле не равно NULL; В нем просто есть пустая строка. Поэтому при выполнении кода в ответ на нажатие Request.Form["title"] кнопки в нем есть пустая строка.

Почему это различие важно? При создании таблицы Movies вы явно указали, что ни одно из полей не может иметь значение NULL. Но здесь у вас есть форма записи для новых фильмов, и вы оставляете поля пустыми. Вы разумно ожидаете, что база данных будет жаловаться, когда вы пытаетесь сохранить новые фильмы, у которых не было значений для жанра или года. Но дело в том, что даже если оставить эти текстовые поля пустыми, значения не будут пустыми; они пустые строки. В результате вы сможете сохранять новые фильмы в базе данных с пустыми столбцами, но не со значением NULL! — значения. Поэтому необходимо убедиться, что пользователи не отправят пустую строку, что можно сделать, проверив введенные пользователем данные.

Вспомогатель проверки

веб-страницы ASP.NET включает вспомогающую функцию Validation , которую можно использовать, чтобы убедиться, что пользователи вводят данные, соответствующие вашим требованиям. Вспомогательный Validation компонент является одним из вспомогательных средств, встроенных в веб-страницы ASP.NET, поэтому вам не нужно устанавливать его в качестве пакета с помощью NuGet, как вы установили вспомогатель Gravatar в предыдущем руководстве.

Чтобы проверить введенные пользователем данные, сделайте следующее:

  • Используйте код, чтобы указать, что требуется использовать значения в текстовых полях на странице.
  • Поместите тест в код, чтобы сведения о фильме добавлялись в базу данных только в том случае, если все проверяется правильно.
  • Добавьте код в разметку для отображения сообщений об ошибках.

В блоке кода на странице AddMovie вверху перед объявлениями переменных добавьте следующий код:

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

Вы вызываете Validation.RequireField один раз для каждого поля (<input> элемента), в котором требуется запись. Вы также можете добавить пользовательское сообщение об ошибке для каждого вызова, как показано здесь. (Мы изменяли сообщения только для того, чтобы показать, что вы можете поместить там все, что вам нравится.)

Если возникла проблема, необходимо предотвратить вставку новых сведений о фильме в базу данных. В блоке if(IsPost) используйте && (логическое И), чтобы добавить еще одно условие, которое проверяет Validation.IsValid(). Когда все будет готово, весь if(IsPost) блок будет выглядеть следующим образом:

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

При возникновении ошибки проверки с любым из полей, зарегистрированных с помощью вспомогательного ValidationValidation.IsValid средства, метод возвращает значение false. И в этом случае ни один код в этом блоке не будет выполняться, поэтому недопустимые записи фильмов не будут вставлены в базу данных. И, конечно, вы не будете перенаправлены на страницу Фильмы .

Полный блок кода, включая код проверки, теперь выглядит следующим образом:

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

Отображение ошибок проверки

Последним шагом является отображение сообщений об ошибках. Вы можете отображать отдельные сообщения для каждой ошибки проверки, сводку или и то, и другое. В этом руководстве вы выполните оба действия, чтобы увидеть, как это работает.

Рядом с каждым <input> проверяющим элементом Html.ValidationMessage вызовите метод и передайте ему имя проверяемого <input> элемента. Вы помещаете метод в Html.ValidationMessage нужное место, где будет отображаться сообщение об ошибке. При запуске страницы метод отрисовывает элемент, Html.ValidationMessage в который <span> будет идти ошибка проверки. (Если ошибки нет, <span> элемент отображается, но в нем нет текста.)

Измените разметку на странице таким образом, чтобы она была включена Html.ValidationMessage в метод для каждого из трех <input> элементов на странице, как в следующем примере:

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

Чтобы увидеть, как работает сводка, добавьте следующую разметку и код сразу после <h1>Add a Movie</h1> элемента на странице:

@Html.ValidationSummary()

По умолчанию Html.ValidationSummary метод отображает все сообщения проверки в списке <ul> (элементе, который находится внутри <div> элемента). Как и в случае с методом Html.ValidationMessage , разметка для сводки проверки всегда отображается; если ошибок нет, элементы списка не отображаются.

Сводка может быть альтернативным способом отображения сообщений проверки, а не с помощью Html.ValidationMessage метода для отображения каждой ошибки для конкретного поля. Или можно использовать как сводку, так и сведения. Или можно использовать метод для Html.ValidationSummary отображения общей ошибки, а затем использовать отдельные Html.ValidationMessage вызовы для отображения сведений.

Полная страница теперь выглядит, как в следующем примере:

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

Вот и все. Теперь вы можете протестировать страницу, добавив фильм, но оставив одно или несколько полей. В этом случае отобразится следующее сообщение об ошибке:

Страница

Стилизация сообщений об ошибках проверки

Вы видите, что есть сообщения об ошибках, но они не очень хорошо выделяются. Однако существует простой способ оформления сообщений об ошибках.

Для оформления отдельных сообщений об ошибках, отображаемых в Html.ValidationMessage, создайте класс стилей CSS с именем field-validation-error. Чтобы определить поиск сводки проверки, создайте класс стилей CSS с именем validation-summary-errors.

Чтобы увидеть, как работает этот метод, добавьте <style> элемент в <head> раздел страницы. Затем определите классы стилей с именами field-validation-error и validation-summary-errors , которые содержат следующие правила:

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

Обычно вы, вероятно, помещаете сведения о стиле в отдельный CSS-файл , но для простоты вы можете поместить их на страницу. (Далее в этом наборе учебников вы переместите правила CSS в отдельный CSS-файл .)

При возникновении ошибки Html.ValidationMessage проверки метод отрисовывает <span> элемент, включающий class="field-validation-error". Добавив определение стиля для этого класса, можно настроить внешний вид сообщения. При возникновении ошибок ValidationSummary метод также динамически отрисовывает атрибут class="validation-summary-errors".

Запустите страницу еще раз и намеренно оставьте несколько полей. Ошибки стали более заметными. (На самом деле, они overdone, но это только для того, чтобы показать, что вы можете сделать.)

Страница

Последний шаг — сделать его удобным для доступа к странице AddMovie из исходного списка фильмов.

Снова откройте страницу Фильмы . После закрывающего </div> тега, следующего за вспомогательным WebGrid , добавьте следующую разметку:

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

Как вы видели ранее, ASP.NET интерпретирует ~ оператор как корень веб-сайта. Вам не нужно использовать ~ оператор ; вы можете использовать разметку <a href="./AddMovie">Add a movie</a> или другой способ определения пути, который понимает HTML. ~ Но оператор является хорошим общим подходом при создании ссылок на страницы Razor, так как он делает сайт более гибким. При перемещении текущей страницы во вложенную папку ссылка по-прежнему будет переходить на страницу AddMovie. (Помните, что ~ оператор работает только на страницах .cshtml . ASP.NET понимает его, но не является стандартным HTML.)

Когда все будет готово, запустите страницу Фильмы . Он будет выглядеть следующим образом:

Страница

Щелкните ссылку Добавить фильм , чтобы убедиться, что он перейдет на страницу AddMovie .

Ближайшие к следующему

В следующем руководстве вы узнаете, как разрешить пользователям изменять данные, которые уже находятся в базе данных.

Полный список для страницы 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>

Дополнительные ресурсы