Iterace č. 3 – přidání ověřovacího formuláře (C#)
od Microsoftu
Ve třetí iteraci přidáme základní ověření formuláře. Bráníme uživatelům v odesílání formuláře bez vyplnění požadovaných polí formuláře. Ověřujeme také e-mailové adresy a telefonní čísla.
Sestavení aplikace Správy kontaktů ASP.NET MVC (C#)
V této sérii kurzů sestavíme celou aplikaci Pro správu kontaktů od začátku do konce. Aplikace Contact Manager umožňuje ukládat kontaktní informace – jména, telefonní čísla a e-mailové adresy – pro seznam lidí.
Aplikaci sestavíme pomocí několika iterací. S každou iterací aplikaci postupně vylepšujeme. Cílem tohoto přístupu k vícenásobné iteraci 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 pro základní databázové operace: vytvoření, čtení, aktualizace a odstranění (CRUD).
Iterace č. 2 – aby aplikace vypadala hezky. V této iteraci vylepšujeme vzhled aplikace úpravou výchozí stránky předlohy zobrazení ASP.NET zobrazení MVC a šablony stylů CSS.
Iterace č. 3 – přidejte ověření formuláře. Ve třetí iteraci přidáme základní ověření formuláře. Bráníme uživatelům v odesílá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ě provázanou. V této čtvrté iteraci využijeme několik vzorů návrhu softwaru, abychom usnadnili údržbu a úpravu aplikace Contact Manager. Například refaktorujeme aplikaci tak, aby používala vzor Úložiště a injektáž 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. Napodobení tříd datového modelu a sestavení testů 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 napíšeme kód proti testům jednotek. 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ěření formuláře. Bráníme uživatelům v odesílání kontaktu bez zadání hodnot 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ěření 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á.
V této iteraci zapisujeme všechny ověřovací kódy ručně, abychom to zjednodušily. Místo toho, abychom ověřovací kód napsali sami, mohli bychom využít ověřovací architekturu. K implementaci logiky ověřování pro aplikaci ASP.NET MVC můžete například použít blok 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 v sadě Visual Studio vygenerovali zobrazení Vytvořit, zobrazení Vytvořit už naštěstí obsahuje veškerou logiku uživatelského rozhraní potřebnou k zobrazení ověřovacích zpráv. Zobrazení Vytvořit je obsaženo ve výpisu 1.
Výpis 1 – \Views\Contact\Create.aspx
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<ContactManager.Models.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 class="fields">
<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>
<% } %>
</asp:Content>
Všimněte si volání pomocné metody Html.ValidationSummary(), která se zobrazí bezprostředně nad formulářem HTML. Pokud existují chybové zprávy ověření, zobrazí tato metoda ověřovací zprávy v seznamu s odrážkami.
Všimněte si také volání Html.ValidationMessage(), která se zobrazí vedle každého pole formuláře. Pomocník ValidationMessage() zobrazí chybovou zprávu jednotlivých ověření. V případě výpisu 1 se hvězdička zobrazí, když dojde k chybě ověření.
Nakonec pomocník Html.TextBox() automaticky vykreslí třídu šablony stylů CSS, pokud je s vlastností zobrazenou pomocnou rutinou přidružena chyba ověření. Pomocník Html.TextBox() vykreslí třídu s názvem input-validation-error.
Když vytvoříte novou aplikaci ASP.NET MVC, automaticky se ve složce Obsah vytvoří šablona stylů Site.css. Tato šablona stylů obsahuje následující definice tříd CSS souvisejících s výskytem chybových zpráv ověřování:
.field-validation-error
{
color: #ff0000;
}
.input-validation-error
{
border: 1px solid #ff0000;
background-color: #ffeeee;
}
.validation-summary-errors
{
font-weight: bold;
color: #ff0000;
}
Třída field-validation-error se používá ke stylu výstupu vykresleného pomocným nástrojem Html.ValidationMessage(). Třída input-validation-error se používá k vytvoření stylu textového pole (vstupu) vykreslovaného pomocníkem Html.TextBox(). Třída validation-summary-errors se používá k vytvoření stylu neuspořádaného seznamu vykresleného pomocníkem Html.ValidationSummary().
Poznámka
Můžete upravit třídy šablon stylů popsané v této části a přizpůsobit tak vzhled ověřovacích chybových zpráv.
Přidání ověřovací logiky do akce vytvořit
V současné chvíli zobrazení Vytvořit nikdy nezobrazuje chybové zprávy ověřování, protože jsme nenapsali logiku pro generování zpráv. Chcete-li zobrazit chybové zprávy ověření, musíte přidat chybové zprávy do ModelState.
Poznámka
Metoda UpdateModel() přidá chybové zprávy do ModeluState 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" vlastnosti BirthDate, která přijímá hodnoty DateTime, pak metoda UpdateModel() přidá chybu do ModelState.
Upravená metoda Create() v výpisu 2 obsahuje novou část, která ověřuje vlastnosti třídy Contact před vložením nového kontaktu do databáze.
Výpis 2 – Controllers\ContactController.cs (vytvoření s ověřením)
//
// POST: /Contact/Create
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create([Bind(Exclude = "Id")] Contact contactToCreate)
{
// Validation logic
if (contactToCreate.FirstName.Trim().Length == 0)
ModelState.AddModelError("FirstName", "First name is required.");
if (contactToCreate.LastName.Trim().Length == 0)
ModelState.AddModelError("LastName", "Last name is required.");
if (contactToCreate.Phone.Length > 0 && !Regex.IsMatch(contactToCreate.Phone, @"((\(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4}"))
ModelState.AddModelError("Phone", "Invalid phone number.");
if (contactToCreate.Email.Length > 0 && !Regex.IsMatch(contactToCreate.Email, @"^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$"))
ModelState.AddModelError("Email", "Invalid email address.");
if (!ModelState.IsValid)
return View();
// Database logic
try
{
_entities.AddToContactSet(contactToCreate);
_entities.SaveChanges();
return RedirectToAction("Index");
}
catch
{
return View();
}
}
Oddíl ověření vynucuje čtyři různá ověřovací pravidla:
- Vlastnost FirstName musí mít délku větší než nulu (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 ModeluState chybová zpráva pomocí metody AddModelError(). Když přidáte zprávu do ModelState, zadáte název vlastnosti a text ověřovací chybové zprávy. Tuto chybovou zprávu zobrazí v zobrazení pomocné metody Html.ValidationSummary() a Html.ValidationMessage().
Po spuštění ověřovacích pravidel je zaškrtnutá vlastnost IsValid ModeluState. Vlastnost IsValid vrátí hodnotu false, pokud byly do ModelState přidány jakékoli ověřovací chybové zprávy. 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í ověřovací logiky do akce Upravit
Akce Upravit() aktualizuje kontakt. Akce Edit() musí provést přesně stejné ověření jako akce Create(). Místo duplikování stejného ověřovacího kódu bychom měli refaktorovat kontroler kontaktu tak, aby obě akce Create() a Edit() volaly stejnou metodu ověřování.
Upravená třída kontroleru kontaktů je obsažena v seznamu 3. Tato třída má novou metodu ValidateContact(), která je volána v rámci akcí Create() a Edit().
Výpis 3 – Controllers\ContactController.cs
using System.Linq;
using System.Text.RegularExpressions;
using System.Web.Mvc;
using ContactManager.Models;
namespace ContactManager.Controllers
{
public class ContactController : Controller
{
private ContactManagerDBEntities _entities = new ContactManagerDBEntities();
protected void ValidateContact(Contact contactToValidate)
{
if (contactToValidate.FirstName.Trim().Length == 0)
ModelState.AddModelError("FirstName", "First name is required.");
if (contactToValidate.LastName.Trim().Length == 0)
ModelState.AddModelError("LastName", "Last name is required.");
if (contactToValidate.Phone.Length > 0 && !Regex.IsMatch(contactToValidate.Phone, @"((\(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4}"))
ModelState.AddModelError("Phone", "Invalid phone number.");
if (contactToValidate.Email.Length > 0 && !Regex.IsMatch(contactToValidate.Email, @"^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$"))
ModelState.AddModelError("Email", "Invalid email address.");
}
public ActionResult Index()
{
return View(_entities.ContactSet.ToList());
}
public ActionResult Create()
{
return View();
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create([Bind(Exclude = "Id")] Contact contactToCreate)
{
// Validation logic
ValidateContact(contactToCreate);
if (!ModelState.IsValid)
return View();
// Database logic
try
{
_entities.AddToContactSet(contactToCreate);
_entities.SaveChanges();
return RedirectToAction("Index");
}
catch
{
return View();
}
}
public ActionResult Edit(int id)
{
var contactToEdit = (from c in _entities.ContactSet
where c.Id == id
select c).FirstOrDefault();
return View(contactToEdit);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Contact contactToEdit)
{
ValidateContact(contactToEdit);
if (!ModelState.IsValid)
return View();
try
{
var 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();
}
}
public ActionResult Delete(int id)
{
var contactToDelete = (from c in _entities.ContactSet
where c.Id == id
select c).FirstOrDefault();
return View(contactToDelete);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Delete(Contact contactToDelete)
{
try
{
var 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();
}
}
}
}
Souhrn
V této iteraci jsme do aplikace Contact Manager přidali základní ověření 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.