Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этом руководстве показано, как обновить (изменить) существующую запись базы данных при использовании ASP.NET веб-страниц (Razor). Предполагается, что вы завершили серию путем ввода данных с помощью форм с помощью ASP.NET веб-страниц.
Что вы узнаете:
- Как выбрать отдельную запись в вспомогательном
WebGridприложении.- Чтение одной записи из базы данных.
- Как предварительно загрузить форму со значениями из записи базы данных.
- Как обновить существующую запись в базе данных.
- Как хранить сведения на странице без отображения.
- Как использовать скрытое поле для хранения информации.
Рассматриваются функции и технологии:
- Помощник
WebGrid.- Команда SQL
Update.- Метод
Database.Execute.- Скрытые поля (
<input type="hidden">).
Что вы будете создавать
В предыдущем руководстве вы узнали, как добавить запись в базу данных. Здесь вы узнаете, как отобразить запись для редактирования. На странице "Фильмы" вы обновите WebGrid вспомогательный элемент, чтобы он отображал ссылку "Изменить " рядом с каждым фильмом:
Щелкнув ссылку "Изменить ", вы перейдете на другую страницу, где информация о фильме уже находится в форме:
Вы можете изменить любое из значений. При отправке изменений код на странице обновляет базу данных и возвращает вас в список фильмов.
Эта часть процесса работает почти точно так же, как страница AddMovie.cshtml , созданная в предыдущем руководстве, поэтому большая часть этого руководства будет знакома.
Существует несколько способов реализации способа редактирования отдельного фильма. Был выбран данный подход, поскольку он прост в реализации и легко понимается.
Добавление ссылки на изменение в список фильмов
Чтобы начать, вы обновите страницу "Фильмы ", чтобы каждый список фильмов также содержал ссылку "Изменить ".
Откройте файл Movies.cshtml .
В тексте страницы измените разметку WebGrid , добавив столбец. Ниже приведена измененная разметка:
@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="~/EditMovie?id=@item.ID)">Edit</a>)
Цель этого столбца заключается в том, чтобы отобразить ссылку (<a> элемент) с текстом "Изменить". Мы намерены создать ссылку, которая будет выглядеть следующим образом при запуске страницы, с разным значением id для каждого фильма.
http://localhost:43097/EditMovie?id=7
Эта ссылка вызывает страницу с именем EditMovie, и она передает строку ?id=7 запроса этой странице.
Синтаксис нового столбца может выглядеть немного сложно, но это только потому, что он объединяет несколько элементов. Каждый отдельный элемент прост. Если сосредоточиться только на элементе <a>, вы увидите следующую разметку:
<a href="~/EditMovie?id=@item.ID)">Edit</a>
Некоторые фоновые сведения о том, как работает сетка: сетка отображает строки, по одному для каждой записи базы данных и отображает столбцы для каждого поля в записи базы данных. При создании каждой строки сетки объект item содержит запись базы данных (элемента) для этой строки. Это соглашение предоставляет вам способ в коде получить доступ к данным для этой строки. Вот что вы видите здесь: выражение item.ID получает значение идентификатора текущего элемента базы данных. Вы можете получить любое из значений базы данных (заголовок, жанр или год) таким же образом, используя item.Titleили item.Genreitem.Year.
Выражение "~/EditMovie?id=@item.ID объединяет жестко закодированную часть целевого URL-адреса (~/EditMovie?id=) с этим динамически производным идентификатором. (Вы видели ~ оператор в предыдущем уроке; это оператор ASP.NET, представляющий корневой каталог текущего веб-сайта.)
Результатом является то, что эта часть разметки в столбце просто создает примерно следующую разметку во время выполнения:
href="/EditMovie?id=2"
Естественно, фактическое значение будет отличаться для каждой id строки.
Создание настраиваемого отображения для столбца сетки
Теперь вернитесь к столбцу сетки. Три столбца, которые вы изначально имели в сетке, отображали только значения данных (название, жанр и год). Вы указали это отображение, передав имя столбца базы данных — например, grid.Column("Title").
Этот новый столбец ссылки "Изменить" отличается. Вместо указания имени столбца передайте format параметр. Этот параметр позволяет определить разметку, которую помощник WebGrid будет визуализировать вместе со значением item для отображения данных столбца полужирным, зеленым или в любом формате, который вам нужен. Например, если вы хотите, чтобы название отображалось полужирным шрифтом, можно создать столбец, как в следующем примере:
grid.Column(format:@<strong>@item.Title</strong>)
(Различные @ символы, которые отображаются в свойстве format , помечают переход между разметкой и значением кода.)
После того как вы знаете о format свойстве, проще понять, как формируется столбец «Изменить»:
grid.Column(format: @<a href="~/EditMovie?id=@item.ID">Edit</a>),
Столбец состоит только из разметки, отображающей ссылку, плюс некоторая информация (идентификатор), извлеченная из записи базы данных для строки.
Подсказка
Именованные параметры и позиционные параметры для метода
Во многих случаях при вызове метода и передаче параметров в него вы просто перечислили значения параметров, разделенные запятыми. Ниже приведено несколько примеров.
db.Execute(insertCommand, title, genre, year)
Validation.RequireField("title", "You must enter a title")
Мы не упомянули проблему, когда вы впервые видели этот код, но в каждом случае вы передаете параметры методам в определенном порядке, а именно порядок определения параметров в этом методе.
db.Execute и Validation.RequireFields, если вы перепутаете порядок передаваемых значений, вы получите сообщение об ошибке при запуске страницы или, по крайней мере, столкнетесь с некоторыми странными результатами. Очевидно, что вам нужно знать порядок передачи параметров. (В WebMatrix IntelliSense поможет узнать имя, тип и порядок параметров.)
В качестве альтернативы передаче значений в порядке можно использовать именованные параметры. (Передача параметров в порядке называется использованием позиционных параметров.) Для именованных параметров вы явно включаете имя параметра при передаче его значения. Вы уже использовали именованные параметры несколько раз в этих руководствах. Рассмотрим пример.
var grid = new WebGrid(source: selectedData, defaultSort: "Genre", rowsPerPage:3)
и
@grid.GetHtml(
tableStyle: "grid",
headerStyle: "head",
alternatingRowStyle: "alt",
columns: grid.Columns(
grid.Column("Title"),
grid.Column("Genre"),
grid.Column("Year")
)
)
Именованные параметры удобны для нескольких ситуаций, особенно если метод принимает множество параметров. Один из них заключается в том, что вы хотите передать только один или два параметра, но значения, которые необходимо передать, не являются первыми позициями в списке параметров. Другая ситуация заключается в том, что вы хотите сделать код более читаемым путем передачи параметров в порядке, который имеет наибольшее значение для вас.
Очевидно, что для использования именованных параметров необходимо знать имена параметров. WebMatrix IntelliSense может показать вам имена, но в настоящее время не может автоматически заполнить их для вас.
Создание страницы редактирования
Теперь вы можете создать страницу EditMovie . Когда пользователи щелкают ссылку "Изменить ", они будут в конечном итоге на этой странице.
Создайте страницу под именем EditMovie.cshtml и замените её содержимое следующей разметкой:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Edit a Movie</title>
<style>
.validation-summary-errors{
border:2px dashed red;
color:red;
font-weight:bold;
margin:12px;
}
</style>
</head>
<body>
<h1>Edit 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="@title" /></p>
<p><label for="genre">Genre:</label>
<input type="text" name="genre" value="@genre" /></p>
<p><label for="year">Year:</label>
<input type="text" name="year" value="@year" /></p>
<input type="hidden" name="movieid" value="@movieId" />
<p><input type="submit" name="buttonSubmit" value="Submit Changes" /></p>
</fieldset>
</form>
</body>
</html>
Эта разметка и код похожи на то, что у вас есть на странице AddMovie . Существует небольшое различие в тексте для кнопки отправки. Как и на странице AddMovie, есть Html.ValidationSummary вызов, который будет отображать ошибки проверки, если они возникнут. В этот раз мы не используем вызовы Validation.Message, так как ошибки будут отображаться в итоговой сводке проверки. Как отмечалось в предыдущем руководстве, можно использовать сводку проверки и отдельные сообщения об ошибках в различных сочетаниях.
Обратите внимание, что method для атрибута <form> элемента задано postзначение . Как и на странице AddMovie.cshtml , эта страница вносит изменения в базу данных. Поэтому эта форма должна выполнять POST операцию. (Дополнительные сведения о различиях между GETPOST операциями см. в боковой панели GET, POST и HTTP Verb Safety в руководстве по формам HTML.)
Как вы видели в предыдущем руководстве, value атрибуты текстовых полей устанавливаются с помощью кода Razor, чтобы предварительно загрузить их. Однако на этот раз вы используете такие переменные, как title и genre для этой задачи, а не Request.Form["title"]:
<input type="text" name="title" value="@title" />
Как и раньше, эта разметка будет предварительно загружать значения текстового поля со значениями фильма. Вы увидите, почему это удобно использовать переменные на этот раз вместо использования Request объекта.
На этой странице также есть элемент <input type="hidden">. Этот элемент сохраняет идентификатор фильма, не делая его видимым на странице. Идентификатор изначально передается на страницу с помощью значения строки запроса (?id=7 или аналогичного в URL-адресе). Поместив значение идентификатора в скрытое поле, вы можете убедиться, что он доступен при отправке формы, даже если у вас больше нет доступа к исходному URL-адресу, с которым была вызвана страница.
В отличие от страницы AddMovie код страницы EditMovie имеет две разные функции. Первая функция заключается в том, что при первом отображении страницы (и только тогда) код получает идентификатор фильма из строки запроса. Затем код использует идентификатор для чтения соответствующего фильма из базы данных и отображения (предварительной загрузки) в текстовых полях.
Вторая функция заключается в том, что когда пользователь нажимает кнопку "Отправить изменения ", код должен считывать значения текстовых полей и проверять их. Код также должен обновить элемент базы данных новыми значениями. Этот метод аналогичен добавлению записи, как вы видели в AddMovie.
Добавление кода для чтения одного фильма
Чтобы выполнить первую функцию, добавьте этот код в начало страницы:
@{
var title = "";
var genre = "";
var year = "";
var movieId = "";
if(!IsPost){
if(!Request.QueryString["ID"].IsEmpty()){
movieId = Request.QueryString["ID"];
var db = Database.Open("WebPagesMovies");
var dbCommand = "SELECT * FROM Movies WHERE ID = @0";
var row = db.QuerySingle(dbCommand, movieId);
title = row.Title;
genre = row.Genre;
year = row.Year;
}
else{
Validation.AddFormError("No movie was selected.");
}
}
}
Большая часть этого кода находится в блоке, который начинается if(!IsPost). Оператор ! означает "не", поэтому выражение значит, если этот запрос не является отправкой данных, что является косвенным способом сказать, если этот запрос является первым запуском этой страницы. Как отмечалось ранее, этот код должен выполняться только при первом запуске страницы. Если код не заключен в if(!IsPost), он будет выполняться каждый раз при вызове страницы, будь то в первый раз или после нажатия кнопки.
Обратите внимание, что на этот раз код включает блок else. Как мы сказали, когда мы ввели if блоки, иногда вы хотите запустить альтернативный код, если условие, которое вы тестируете, не верно. Вот так. Если условие выполняется (то есть, если переданный на страницу идентификатор корректен), вы считываете строку из базы данных. Однако если условие не выполняется, блок else запускается, и код устанавливает сообщение об ошибке.
Проверка значения, переданного на страницу
Код использует Request.QueryString["id"] для получения идентификатора, переданного на страницу. Код гарантирует, что значение действительно передано для ID. Если значение не было передано, код задает ошибку проверки.
Этот код показывает другой способ проверки информации. В предыдущем руководстве вы работали с вспомогательным помощником Validation . Вы зарегистрировали поля для проверки, и ASP.NET автоматически проверял и отображал ошибки с помощью Html.ValidationMessage и Html.ValidationSummary. Однако в этом случае вы действительно не проверяете входные данные пользователя. Вместо этого вы проверяете значение, переданное на страницу из другого места. Помощник Validation не делает это за вас сам.
Таким образом, вы проверяете значение самостоятельно, протестировав его с помощью if(!Request.QueryString["ID"].IsEmpty(). Если возникла проблема, можно отобразить ошибку с помощью Html.ValidationSummary, как вы сделали с Validation. Для этого вы вызываете Validation.AddFormError и передаете сообщение для отображения.
Validation.AddFormError — это встроенный метод, который позволяет вам задавать настраиваемые сообщения, связанные с уже известной вам системой проверки. (Далее в этом руководстве мы поговорим о том, как сделать этот процесс проверки более надежным.)
Убедившись, что для фильма есть идентификатор, код считывает базу данных, ищет только один элемент базы данных. (Вероятно, вы заметили общий шаблон для операций с базами данных: откройте базу данных, определите инструкцию SQL и выполните инструкцию.) На этот раз инструкция SQL Select включает WHERE ID = @0. Так как идентификатор является уникальным, можно вернуть только одну запись.
Запрос выполняется с помощью db.QuerySingle (не db.Queryтак, как используется для описания фильма), а код помещает результат в row переменную. Имя row является произвольным. Вы можете указать переменные, которые вам нравится. Затем переменные, инициализированные вверху, заполняются сведениями о фильме, чтобы эти значения отображались в текстовых полях.
Тестирование страницы редактирования (до сих пор)
Если вы хотите протестировать страницу, запустите страницу "Фильмы " и щелкните ссылку "Изменить " рядом с любым фильмом. Вы увидите страницу EditMovie со сведениями, заполненными для выбранного фильма:
Обратите внимание, что URL-адрес страницы содержит что-то подобное ?id=10 (или другое число). До сих пор вы проверили, что ссылки на редактирование на странице "Фильм " работают, что страница считывает идентификатор из строки запроса, и что запрос базы данных для получения одной записи фильма работает.
Вы можете изменить сведения о фильме, но ничего не происходит при нажатии кнопки "Отправить изменения".
Добавление кода для обновления кинофильма с учетом изменений, внесенных пользователем
В файле EditMovie.cshtml для реализации второй функции (сохранения изменений) добавьте следующий код непосредственно в закрывающую скобку @ блока. (Если вы не знаете, куда поместить код, вы можете просмотреть полный список кода на странице "Изменить фильм ", которая отображается в конце этого руководства.)
if(IsPost){
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("movieid", "No movie ID was submitted!");
title = Request.Form["title"];
genre = Request.Form["genre"];
year = Request.Form["year"];
movieId = Request.Form["movieId"];
if(Validation.IsValid()){
var db = Database.Open("WebPagesMovies");
var updateCommand = "UPDATE Movies SET Title=@0, Genre=@1, Year=@2 WHERE Id=@3";
db.Execute(updateCommand, title, genre, year, movieId);
Response.Redirect("~/Movies");
}
}
Опять же, эта разметка и код похожи на код в AddMovie. Код находится в блоке if(IsPost) , так как этот код запускается, только если пользователь нажимает кнопку "Отправить изменения ", то есть когда (и только когда) была размещена форма. В этом случае вы не используете такой тест if(IsPost && Validation.IsValid()), т. е. вы не объединяете оба теста с помощью AND. На этой странице сначала определяется, существует ли отправка формы (if(IsPost)), а затем регистрируются поля для проверки. Затем можно проверить результаты проверки (if(Validation.IsValid()). Поток немного отличается от на странице AddMovie.cshtml , но эффект тот же.
Вы получаете значения текстовых полей с помощью Request.Form["title"] и аналогичного кода для других <input> элементов. Обратите внимание, что на этот раз код получает идентификатор фильма из скрытого поля (<input type="hidden">). При первом запуске страницы код получил идентификатор из строки запроса. Вы извлекаете значение из скрытого поля, чтобы удостовериться, что получаете идентификатор фильма, который первоначально отображался, если строка запроса была, возможно, изменена.
Действительно важное различие между кодом AddMovie и этим кодом заключается в том, что в этом коде вместо инструкции Update используется инструкция SQLInsert Into. В следующем примере показан синтаксис инструкции SQL Update :
UPDATE table SET col1="value", col2="value", col3="value" ... WHERE ID = value
Вы можете указать любые столбцы в любом порядке, и вам не обязательно нужно обновлять каждый столбец во время Update операции. (Не удается обновить идентификатор, так как это в действительности сохранит запись в качестве новой записи, и это не разрешено для Update операции.)
Замечание
Важно Предложение Where с идентификатором очень важно, так как база данных знает, какая запись базы данных требуется обновить. Если вы пропустите Where , база данных обновит каждую запись в базе данных. В большинстве случаев это будет катастрофой.
В коде значения для обновления передаются инструкции SQL с помощью плейсхолдеров. Чтобы повторить то, что мы сказали ранее: по соображениям безопасности используйте заполнители только для передачи значений в инструкцию SQL.
После того как код использует db.Execute для выполнения оператора Update, он перенаправляется обратно на страницу списка, где можно увидеть изменения.
Подсказка
Различные инструкции SQL, различные методы
Возможно, вы заметили, что для выполнения различных инструкций SQL используются немного разные методы. Чтобы запустить Select запрос, который потенциально возвращает несколько записей, используйте метод Query. Чтобы выполнить запрос Select, который, как вы знаете, возвращает только один элемент базы данных, используйте метод QuerySingle. Чтобы выполнить команды, которые вносят изменения, но не возвращают элементы базы данных, используйте Execute этот метод.
У вас должны быть разные методы, так как каждый из них возвращает разные результаты, как вы уже видели в разнице между Query и QuerySingle. (Метод Execute фактически возвращает значение , а именно , количество строк базы данных, затронутых командой, но вы игнорируете это до сих пор.)
Конечно, Query метод может возвращать только одну строку базы данных. Однако ASP.NET всегда рассматривают результаты Query метода как коллекцию. Даже если метод возвращает только одну строку, необходимо извлечь одну строку из коллекции. Поэтому в ситуациях, когда вы знаете , что вы вернетесь только одну строку, это немного удобнее использовать QuerySingle.
Существует несколько других методов, которые выполняют определенные типы операций базы данных. Список методов базы данных можно найти в кратком справочнике по API веб-страниц ASP.NET.
Повышение надежности проверки идентификатора
При первом запуске страницы вы получите идентификатор фильма из строки запроса, чтобы получить этот фильм из базы данных. Вы убедились, что действительно есть значение, которое можно найти, используя этот код:
if(!IsPost){
if(!Request.QueryString["ID"].IsEmpty()){
// Etc.
}
}
Этот код использовался, чтобы убедиться, что если пользователь попадает на страницу EditMovies без первого выбора фильма на странице "Фильмы ", страница будет отображать понятное сообщение об ошибке. (В противном случае пользователи увидят ошибку, которая, вероятно, просто запутает их.)
Однако эта проверка не очень надежна. Страница также может вызываться с этими ошибками:
- Идентификатор не является числом. Например, страницу можно вызвать с URL-адресом, например
http://localhost:nnnnn/EditMovie?id=abc. - Идентификатор является числом, но ссылается на фильм, который не существует (например,
http://localhost:nnnnn/EditMovie?id=100934).
Если вам интересно увидеть ошибки, которые возникают из-за этих URL-адресов, откройте страницу "Фильмы". Выберите фильм для редактирования и измените URL-адрес страницы EditMovie на URL-адрес, содержащий алфавитный идентификатор или идентификатор несуществующего фильма.
Так что делать? Первое исправление заключается в том, чтобы убедиться, что на страницу передан не только идентификатор, но и что он является целым числом. Измените код !IsPost для теста, чтобы выглядеть следующим образом:
if(!IsPost){
if(!Request.QueryString["ID"].IsEmpty() && Request.QueryString["ID"].IsInt()) {
// Etc.
Вы добавили в тест второе условие IsEmpty, связанное с && (логическим И):
Request.QueryString["ID"].IsInt()
Вы можете вспомнить из руководства Введение в программирование веб-страниц ASP.NET, что такие методы, как AsBool и AsInt, преобразуют символьную строку в другой тип данных. Метод IsInt (и другие, как IsBool и IsDateTime) похожи. Однако они проверяют, можно ли преобразовать строку, не выполняя преобразование. Поэтому здесь вы говорите, что если строковое значение запроса можно преобразовать в целое число ....
Другой потенциальной проблемой является поиск фильма, который не существует. Код для получения фильма выглядит следующим образом:
var row = db.QuerySingle(dbCommand, movieId);
Если вы передаете movieId значение методу QuerySingle, которое не соответствует существующему фильму, ничего не возвращается, и следующие операторы (например, title=row.Title) приводят к ошибкам.
Опять же, есть простое исправление.
db.QuerySingle Если метод не возвращает результатов, row переменная будет иметь значение NULL. Таким образом, можно проверить, имеет ли row переменная значение NULL, прежде чем пытаться получить значения из него. Следующий код добавляет if блок вокруг инструкций, которые получают значения из row объекта:
if(row != null) {
title = row.Title;
genre = row.Genre;
year = row.Year;
}
else{
Validation.AddFormError("No movie was found for that ID.");
}
С помощью этих двух дополнительных тестов страница становится более надёжной. Полный !IsPost код ветви теперь выглядит следующим образом:
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 selected.");
}
}
Мы еще раз заметим, что данная задача является хорошим применением блока else. Если тесты не проходят, else блоки задают сообщения об ошибках.
Добавление ссылки для возврата на страницу "Фильмы"
Последняя и полезная информация заключается в добавлении ссылки обратно на страницу "Фильмы ". В обычном потоке событий пользователи начнут на странице Фильмы и нажмут ссылку Изменить. Это приводит их к странице EditMovie , где они могут изменить фильм и нажать кнопку. После обработки изменения код перенаправляется обратно на страницу "Фильмы ".
Однако:
- Пользователь может не изменить ничего.
- Возможно, пользователь перейдет на эту страницу, не щелкнув ссылку "Изменить " на странице "Фильмы ".
Вы хотите сделать для них возврат к основному списку простым в любом случае. Это простое исправление— добавьте следующую разметку сразу после закрывающего </form> тега в разметке:
<p><a href="~/Movies">Return to movie listing</a></p>
Эта разметка использует тот же синтаксис для <a> элемента, который вы видели в другом месте. URL включает в себя ~, что обозначает "корень веб-сайта".
Тестирование процесса обновления фильма
Теперь можно протестировать. Запустите страницу "Фильмы " и нажмите кнопку "Изменить рядом с фильмом". Когда появится страница EditMovie , внесите изменения в фильм и нажмите кнопку "Отправить изменения". Когда появится список фильмов, убедитесь, что изменения отображаются.
Чтобы убедиться, что проверка работает, нажмите кнопку "Изменить " для другого фильма. Когда вы перейдёте на страницу EditMovie, очистите поле Жанр (или поле Год, или оба) и попробуйте отправить ваши изменения. Вы увидите ошибку, как вы ожидаете:
Щелкните ссылку "Вернуться к списку фильмов", чтобы отказаться от изменений и вернуться на страницу "Фильмы ".
Далее
В следующем руководстве вы узнаете, как удалить запись фильма.
Полный список для страницы фильма (обновлено с добавлением ссылок для редактирования)
@{
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")
)
)
</div>
<p>
<a href="~/AddMovie">Add a movie</a>
</p>
</body>
</html>
Полный список страниц для редактирования страницы фильма
@{
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 selected.");
}
}
else{
Validation.AddFormError("No movie was selected.");
}
}
if(IsPost){
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("movieid", "No movie ID was submitted!");
title = Request.Form["title"];
genre = Request.Form["genre"];
year = Request.Form["year"];
movieId = Request.Form["movieId"];
if(Validation.IsValid()){
var db = Database.Open("WebPagesMovies");
var updateCommand = "UPDATE Movies SET Title=@0, Genre=@1, Year=@2 WHERE Id=@3";
db.Execute(updateCommand, title, genre, year, movieId);
Response.Redirect("~/Movies");
}
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Edit a Movie</title>
<style>
.validation-summary-errors{
border:2px dashed red;
color:red;
font-weight:bold;
margin:12px;
}
</style>
</head>
<body>
<h1>Edit 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="@title" /></p>
<p><label for="genre">Genre:</label>
<input type="text" name="genre" value="@genre" /></p>
<p><label for="year">Year:</label>
<input type="text" name="year" value="@year" /></p>
<input type="hidden" name="movieid" value="@movieId" />
<p><input type="submit" name="buttonSubmit" value="Submit Changes" /></p>
</fieldset>
</form>
<p><a href="~/Movies">Return to movie listing</a></p>
</body>
</html>