Iterace č. 3 – přidání ověřovacího formuláře (VB)
od Microsoftu
Ve třetí iteraci přidáme základní ověření formuláře. Bráníme uživatelům v odeslání formuláře bez vyplnění požadovaných polí formuláře. Ověřujeme také e-mailové adresy a telefonní čísla.
Vytvoření aplikace Správy kontaktů ASP.NET MVC (VB)
V této sérii kurzů sestavíme od začátku do konce celou aplikaci Pro správu kontaktů. Aplikace Contact Manager umožňuje ukládat kontaktní informace – jména, telefonní čísla a e-mailové adresy – pro seznam osob.
Aplikaci sestavíme pomocí několika iterací. S každou iterací aplikaci postupně vylepšujeme. Cílem tohoto přístupu s více iteracemi je pochopit důvod každé změny.
Iterace č. 1 – vytvořte aplikaci. V první iteraci vytvoříme Správce kontaktů nejjednodušším možným způsobem. Přidáváme podporu základních databázových operací: vytvoření, čtení, aktualizace a odstranění (CRUD).
Iterace č. 2 – vzhled aplikace V této iteraci vylepšujeme vzhled aplikace úpravou výchozí ASP.NET stránky předlohy zobrazení MVC a šablony stylů CSS.
Iterace č. 3 – přidání ověření formuláře Ve třetí iteraci přidáme základní ověření formuláře. Bráníme uživatelům v odeslání formuláře bez vyplnění požadovaných polí formuláře. Ověřujeme také e-mailové adresy a telefonní čísla.
Iterace č. 4 – Nastavte aplikaci volně na párování. V této čtvrté iteraci využijeme několik vzorů návrhu softwaru, které usnadňují údržbu a úpravy aplikace Contact Manager. Například refaktorujeme aplikaci tak, aby používala vzor úložiště a model injektáže závislostí.
Iterace č. 5 – vytvoření testů jednotek V páté iteraci usnadňujeme údržbu a úpravy naší aplikace přidáním testů jednotek. Vysmíváme si třídy datového modelu a sestavujeme testy jednotek pro naše kontrolery a logiku ověřování.
Iterace č. 6 – použijte vývoj řízený testy. V této šesté iteraci přidáme do naší aplikace nové funkce tím, že nejprve napíšeme testy jednotek a proti testům jednotek napíšeme kód. V této iteraci přidáme skupiny kontaktů.
Iterace č. 7 – přidání funkcí Ajax V sedmé iteraci vylepšujeme rychlost odezvy a výkon naší aplikace přidáním podpory pro Ajax.
Tato iterace
V této druhé iteraci aplikace Contact Manager přidáme základní ověřování formuláře. Bráníme uživatelům v odeslání kontaktu bez zadání hodnot do požadovaných polí formuláře. Ověřujeme také telefonní čísla a e-mailové adresy (viz obrázek 1).
Obrázek 01: Formulář s ověřením (kliknutím zobrazíte obrázek v plné velikosti)
V této iteraci přidáme logiku ověřování přímo do akcí kontroleru. Obecně to není doporučený způsob přidání ověření do aplikace ASP.NET MVC. Lepším přístupem je umístit logiku ověřování aplikace do samostatné vrstvy služby. V další iteraci refaktorujeme aplikaci Contact Manager, aby byla lépe udržovatelná.
Abychom v této iteraci zachovali jednoduchost, napíšeme celý ověřovací kód ručně. Místo toho, abychom ověřovací kód psali sami, mohli bychom využít ověřovací architekturu. K implementaci logiky ověřování pro aplikaci ASP.NET MVC můžete použít například blok aplikace VAB (Microsoft Enterprise Library Validation Application Block). Další informace o bloku ověřovací aplikace najdete tady:
http://msdn.microsoft.com/library/dd203099.aspx
Přidání ověření do zobrazení pro vytvoření
Začněme přidáním logiky ověřování do zobrazení Vytvořit. Protože jsme zobrazení Vytvořit vygenerovali pomocí sady Visual Studio, naštěstí zobrazení Vytvořit už obsahuje veškerou logiku uživatelského rozhraní potřebnou k zobrazení ověřovacích zpráv. Zobrazení Vytvořit je součástí výpisu 1.
Výpis 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>
Třída field-validation-error se používá ke stylu výstupu vykresleného pomocníkem Html.ValidationMessage(). Třída input-validation-error se používá ke stylu textového pole (vstupu) vykresleného pomocníkem Html.TextBox(). Třída validation-summary-errors slouží k vytvoření stylu neuspořádaného seznamu vykresleného pomocnou rutinou Html.ValidationSummary().
Poznámka
Můžete upravit třídy šablon stylů popsané v této části a přizpůsobit tak vzhled chybových zpráv ověření.
Přidání ověřovací logiky do akce vytvoření
V současné chvíli zobrazení Vytvořit nikdy nezobrazuje chybové zprávy ověření, protože jsme nezapsali logiku, která by vygenerovala zprávy. Chcete-li zobrazit chybové zprávy ověřování, musíte přidat chybové zprávy do ModelState.
Poznámka
Metoda UpdateModel() přidá chybové zprávy do ModelState automaticky, pokud dojde k chybě při přiřazování hodnoty pole formuláře k vlastnosti. Pokud se například pokusíte přiřadit řetězec "apple" k Vlastnosti BirthDate, která přijímá hodnoty DateTime, metoda UpdateModel() přidá chybu do ModelState.
Upravená metoda Create() ve výpisu 2 obsahuje nový oddíl, který ověřuje vlastnosti třídy Contact před vložením nového kontaktu do databáze.
Výpis 2 – Controllers\ContactController.vb (vytvoření s ověřením)
<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
Oddíl ověření vynucuje čtyři různá ověřovací pravidla:
- Vlastnost FirstName musí mít délku větší než nula (a nesmí se skládat pouze z mezer).
- Vlastnost LastName musí mít délku větší než nula (a nesmí se skládat pouze z mezer).
- Pokud má vlastnost Phone hodnotu (má délku větší než 0), musí vlastnost Phone odpovídat regulárnímu výrazu.
- Pokud má vlastnost Email hodnotu (má délku větší než 0), musí vlastnost Email odpovídat regulárnímu výrazu.
Pokud dojde k porušení ověřovacího pravidla, přidá se do ModelState chybová zpráva pomocí metody AddModelError(). Při přidávání zprávy do ModelState zadáte název vlastnosti a text ověřovací chybové zprávy. Tuto chybovou zprávu zobrazí pomocné metody Html.ValidationSummary() a Html.ValidationMessage() v zobrazení.
Po spuštění ověřovacích pravidel je zaškrtnutá vlastnost IsValid vlastnosti ModelState. IsValid Vlastnost vrátí false, když byly přidány jakékoli ověřovací chybové zprávy do ModelState. Pokud se ověření nezdaří, formulář Vytvořit se znovu zobrazí s chybovými zprávami.
Poznámka
Regulární výrazy pro ověření telefonního čísla a e-mailové adresy mám z úložiště regulárních výrazů na adrese http://regexlib.com
Přidání logiky ověřování do akce Upravit
Akce Edit() aktualizuje kontakt. Akce Edit() musí provést naprosto stejné ověření jako akce Vytvořit(). Místo duplikování stejného ověřovacího kódu bychom měli refaktorovat kontroler contact tak, aby obě akce Create() a Edit() volaly stejnou metodu ověření.
Upravená třída kontroleru kontaktů je obsažena ve výpisu 3. Tato třída má novou metodu ValidateContact(), která se volá v rámci akcí Create() a Edit().
Výpis 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
Souhrn
V této iteraci jsme do aplikace Contact Manager přidali základní ověřování formuláře. Naše logika ověřování zabraňuje uživatelům v odeslání nového kontaktu nebo úpravě existujícího kontaktu bez zadání hodnot vlastností Jméno a Příjmení. Uživatelé navíc musí zadat platná telefonní čísla a e-mailové adresy.
V této iteraci jsme do naší aplikace Contact Manager přidali logiku ověřování nejjednodušším možným způsobem. Zkombinování logiky ověřování s logikou kontroleru nám ale v dlouhodobém horizontu způsobí problémy. Údržba a úprava naší aplikace bude v průběhu času obtížnější.
V další iteraci refaktorujeme logiku ověřování a logiku přístupu k databázi z našich kontrolerů. Využijeme několik principů návrhu softwaru, které nám umožní vytvořit volněji provázanou a lépe udržovatelnou aplikaci.