Заметка
Доступ к этой странице требует авторизации. Вы можете попробовать войти в систему или изменить каталог.
Доступ к этой странице требует авторизации. Вы можете попробовать сменить директорию.
от Майкрософт
В третьей итерации мы добавим базовую проверку формы. Мы запрещаем пользователям отправлять форму без заполнения обязательных полей формы. Мы также проверяем адреса электронной почты и номера телефонов.
Создание приложения управления контактами ASP.NET MVC (VB)
В этой серии учебников мы создадим все приложение управления контактами от начала до конца. Приложение Диспетчер контактов позволяет хранить контактные данные ( имена, номера телефонов и адреса электронной почты) для списка людей.
Мы создаем приложение с помощью нескольких итераций. С каждой итерацией мы постепенно улучшаем приложение. Цель этого подхода с несколькими итерациями — дать возможность понять причину каждого изменения.
Итерация 1. Создание приложения. В первой итерации мы создадим диспетчер контактов самым простым способом. Добавлена поддержка базовых операций с базами данных: создание, чтение, обновление и удаление (CRUD).
Итерация 2. Сделайте приложение красивым. В этой итерации мы улучшаем внешний вид приложения, изменив ASP.NET по умолчанию представление MVC master страницу и каскадную таблицу стилей.
Итерация 3. Добавление проверки формы. В третьей итерации мы добавим базовую проверку формы. Мы запрещаем пользователям отправлять форму без заполнения обязательных полей формы. Мы также проверяем адреса электронной почты и номера телефонов.
Итерация 4. Сделайте приложение слабосвязанным. В этой четвертой итерации мы воспользуемся преимуществами нескольких шаблонов проектирования программного обеспечения, чтобы упростить обслуживание и изменение приложения Диспетчера контактов. Например, мы рефакторинг приложения для использования шаблона репозитория и шаблона внедрения зависимостей.
Итерация 5. Создание модульных тестов. В пятой итерации мы упростим обслуживание и изменение приложения, добавив модульные тесты. Мы имитируем классы модели данных и создаем модульные тесты для наших контроллеров и логики проверки.
Итерация 6. Использование разработки на основе тестирования. В этой шестой итерации мы добавим новые функции в приложение, сначала написав модульные тесты и написав код для модульных тестов. В этой итерации мы добавим группы контактов.
Итерация 7. Добавление функциональных возможностей Ajax. В седьмой итерации мы повышаем скорость реагирования и производительность приложения, добавляя поддержку Ajax.
Эта итерация
Во второй итерации приложения Диспетчера контактов мы добавим базовую проверку формы. Мы запрещаем пользователям отправлять контакт, не вводя значения для обязательных полей формы. Мы также проверяем номера телефонов и адреса электронной почты (см. рис. 1).
Рис. 01. Форма с проверкой (щелкните для просмотра полноразмерного изображения)
В этой итерации мы добавим логику проверки непосредственно в действия контроллера. Как правило, это не рекомендуемый способ добавления проверки в приложение ASP.NET MVC. Лучший подход заключается в том, чтобы разместить логику проверки приложения в отдельном уровне служб. В следующей итерации мы рефакторинг приложения Диспетчера контактов, чтобы сделать приложение более пригодным для обслуживания.
В этой итерации, чтобы упростить процесс, мы напишем весь код проверки вручную. Вместо того, чтобы самостоятельно писать код проверки, мы могли бы воспользоваться преимуществами платформы проверки. Например, можно использовать блок приложения проверки корпоративной библиотеки Майкрософт (VAB) для реализации логики проверки для приложения ASP.NET MVC. Дополнительные сведения о блоке приложения проверки см. в следующих разделах:
http://msdn.microsoft.com/library/dd203099.aspx
Добавление проверки в представление создания
Начнем с добавления логики проверки в представление Создание. К счастью, так как мы создали представление "Создать" с помощью Visual Studio, представление "Создание" уже содержит всю необходимую логику пользовательского интерфейса для отображения сообщений проверки. Представление Создание содержится в листинге 1.
Листинг 1. \Views\Contact\Create.aspx
<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of ContactManager.Contact)" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
<title>Create</title>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<%= Html.ValidationSummary() %>
<% Using Html.BeginForm()%>
<fieldset>
<legend>Create New Contact</legend>
<p>
<label for="FirstName">First Name:</label>
<%= Html.TextBox("FirstName") %>
<%= Html.ValidationMessage("FirstName", "*") %>
</p>
<p>
<label for="LastName">Last Name:</label>
<%= Html.TextBox("LastName") %>
<%= Html.ValidationMessage("LastName", "*") %>
</p>
<p>
<label for="Phone">Phone:</label>
<%= Html.TextBox("Phone") %>
<%= Html.ValidationMessage("Phone", "*") %>
</p>
<p>
<label for="Email">Email:</label>
<%= Html.TextBox("Email") %>
<%= Html.ValidationMessage("Email", "*") %>
</p>
<p class="submit">
<input type="submit" value="Create" />
</p>
</fieldset>
<% End Using %>
</asp:Content>
Класс field-validation-error используется для оформления выходных данных, отображаемых вспомогательным методом Html.ValidationMessage(). Класс input-validation-error используется для оформления текстового поля (входных данных), отображаемого вспомогательным элементом Html.TextBox(). Класс validation-summary-errors используется для оформления неупорядоченного списка, отображаемого вспомогательным элементом Html.ValidationSummary().
Примечание
Вы можете изменить классы таблиц стилей, описанные в этом разделе, чтобы настроить внешний вид сообщений об ошибках проверки.
Добавление логики проверки в действие создания
Сейчас в представлении Создание никогда не отображаются сообщения об ошибках проверки, так как мы не написали логику для создания сообщений. Чтобы отобразить сообщения об ошибках проверки, необходимо добавить сообщения об ошибках в ModelState.
Примечание
Метод UpdateModel() автоматически добавляет сообщения об ошибках в ModelState при возникновении ошибки при присвоении значения поля формы свойству. Например, при попытке назначить строку apple свойству BirthDate, которое принимает значения DateTime, метод UpdateModel() добавляет ошибку в ModelState.
Измененный метод Create() в листинге 2 содержит новый раздел, который проверяет свойства класса Contact перед вставкой нового контакта в базу данных.
Листинг 2. Controllers\ContactController.vb (создание с проверкой)
<AcceptVerbs(HttpVerbs.Post)> _
Function Create(<Bind(Exclude:="Id")> ByVal contactToCreate As Contact) As ActionResult
' Validation logic
If contactToCreate.FirstName.Trim().Length = 0 Then
ModelState.AddModelError("FirstName", "First name is required.")
End If
If contactToCreate.LastName.Trim().Length = 0 Then
ModelState.AddModelError("LastName", "Last name is required.")
End If
If (contactToCreate.Phone.Length > 0 AndAlso Not Regex.IsMatch(contactToCreate.Phone, "((\(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4}"))
ModelState.AddModelError("Phone", "Invalid phone number.")
End If
If (contactToCreate.Email.Length > 0 AndAlso Not Regex.IsMatch(contactToCreate.Email, "^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$"))
ModelState.AddModelError("Email", "Invalid email address.")
End If
If Not ModelState.IsValid Then
Return View()
End If
' Database logic
Try
_entities.AddToContactSet(contactToCreate)
_entities.SaveChanges()
Return RedirectToAction("Index")
Catch
Return View()
End Try
End Function
В разделе validate применяются четыре отдельных правила проверки:
- Свойство FirstName должно иметь длину больше нуля (и оно не может состоять исключительно из пробелов).
- Свойство LastName должно иметь длину больше нуля (и оно не может состоять исключительно из пробелов).
- Если свойство Phone имеет значение (имеет длину больше 0), то свойство Phone должно соответствовать регулярному выражению.
- Если свойство Email имеет значение (имеет длину больше 0), то свойство Email должно соответствовать регулярному выражению.
При нарушении правила проверки в ModelState с помощью метода AddModelError() добавляется сообщение об ошибке. При добавлении сообщения в ModelState укажите имя свойства и текст сообщения об ошибке проверки. Это сообщение об ошибке отображается в представлении вспомогательными методами Html.ValidationSummary() и Html.ValidationMessage().
После выполнения правил проверки проверяется свойство IsValid объекта ModelState. Свойство IsValid возвращает значение false при добавлении сообщений об ошибках проверки в ModelState. Если проверка завершается сбоем, форма создания повторно отображается с сообщениями об ошибках.
Примечание
Я получил регулярные выражения для проверки номера телефона и адреса электронной почты из репозитория регулярных выражений по адресу http://regexlib.com
Добавление логики проверки в действие "Изменить"
Действие Edit() обновляет объект Contact. Действие Edit() должно выполнять ту же проверку, что и действие Create(). Вместо того, чтобы дублировать один и тот же код проверки, следует выполнить рефакторинг контроллера Contact, чтобы действия Create() и Edit() вызывали один и тот же метод проверки.
Измененный класс контроллера Contact содержится в листинге 3. Этот класс имеет новый метод ValidateContact(), который вызывается в действиях Create() и Edit().
Листинг 3. Controllers\ContactController.vb
Public Class ContactController
Inherits System.Web.Mvc.Controller
Private _entities As New ContactManagerDBEntities()
Protected Sub ValidateContact(contactToValidate As Contact)
If contactToValidate.FirstName.Trim().Length = 0 Then
ModelState.AddModelError("FirstName", "First name is required.")
End If
If contactToValidate.LastName.Trim().Length = 0 Then
ModelState.AddModelError("LastName", "Last name is required.")
End If
If (contactToValidate.Phone.Length > 0 AndAlso Not Regex.IsMatch(contactToValidate.Phone, "((\(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4}"))
ModelState.AddModelError("Phone", "Invalid phone number.")
End If
If (contactToValidate.Email.Length > 0 AndAlso Not Regex.IsMatch(contactToValidate.Email, "^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$"))
ModelState.AddModelError("Email", "Invalid email address.")
End If
End Sub
'
' GET: /Contact
Function Index() As ActionResult
Return View(_entities.ContactSet.ToList())
End Function
'
' GET: /Contact/Create
Function Create() As ActionResult
Return View()
End Function
'
' POST: /Contact/Create
<AcceptVerbs(HttpVerbs.Post)> _
Function Create(<Bind(Exclude:="Id")> ByVal contactToCreate As Contact) As ActionResult
' Validation logic
ValidateContact(contactToCreate)
If Not ModelState.IsValid Then
Return View()
End If
' Database logic
Try
_entities.AddToContactSet(contactToCreate)
_entities.SaveChanges()
Return RedirectToAction("Index")
Catch
Return View()
End Try
End Function
'
' GET: /Contact/Edit/5
Function Edit(ByVal id As Integer) As ActionResult
Dim contactToEdit = (from c in _entities.ContactSet _
where c.Id = id _
select c).FirstOrDefault()
Return View(contactToEdit)
End Function
'
' POST: /Contact/Edit/5
<AcceptVerbs(HttpVerbs.Post)> _
Function Edit(ByVal contactToEdit As Contact) As ActionResult
' Validation logic
ValidateContact(contactToEdit)
If Not ModelState.IsValid Then
Return View()
End If
' Database logic
Try
Dim originalContact = (from c in _entities.ContactSet _
where c.Id = contactToEdit.Id _
select c).FirstOrDefault()
_entities.ApplyPropertyChanges(originalContact.EntityKey.EntitySetName, contactToEdit)
_entities.SaveChanges()
Return RedirectToAction("Index")
Catch
Return View()
End Try
End Function
'
' GET: /Contact/Delete/5
Function Delete(ByVal id As Integer) As ActionResult
Dim contactToDelete = (from c in _entities.ContactSet _
where c.Id = id _
select c).FirstOrDefault()
Return View(contactToDelete)
End Function
'
' POST: /Contact/Delete/5
<AcceptVerbs(HttpVerbs.Post)> _
Function Delete(ByVal contactToDelete As Contact) As ActionResult
Try
Dim originalContact = (from c in _entities.ContactSet _
where c.Id = contactToDelete.Id _
select c).FirstOrDefault()
_entities.DeleteObject(originalContact)
_entities.SaveChanges()
Return RedirectToAction("Index")
Catch
Return View()
End Try
End Function
End Class
Итоги
В этой итерации мы добавили базовую проверку формы в приложение Диспетчера контактов. Наша логика проверки запрещает пользователям отправлять новый контакт или редактировать существующий контакт, не предоставляя значения для свойств FirstName и LastName. Кроме того, пользователи должны указать допустимые номера телефонов и адреса электронной почты.
В этой итерации мы добавили логику проверки в приложение Диспетчера контактов самым простым способом. Однако смешивание логики проверки с логикой контроллера создаст проблемы в долгосрочной перспективе. Наше приложение будет сложнее поддерживать и изменять со временем.
В следующей итерации мы будем выполнять рефакторинг логики проверки и логики доступа к базе данных из контроллеров. Мы воспользуемся преимуществами нескольких принципов проектирования программного обеспечения, чтобы создать более слабо связанное и более доступное для обслуживания приложение.