세 번째 반복에서는 기본 양식 유효성 검사를 추가합니다. 사용자가 필요한 양식 필드를 완료하지 않고 양식을 제출하지 못하도록 합니다. 또한 전자 메일 주소 및 전화 번호의 유효성을 검사합니다.
MVC 애플리케이션을 ASP.NET 연락처 관리 빌드(C#)
이 자습서 시리즈에서는 처음부터 끝까지 전체 연락처 관리 애플리케이션을 빌드합니다. Contact Manager 애플리케이션을 사용하면 사용자 목록에 대한 연락처 정보(이름, 전화 번호 및 전자 메일 주소)를 저장할 수 있습니다.
여러 반복을 통해 애플리케이션을 빌드합니다. 반복할 때마다 애플리케이션을 점진적으로 개선합니다. 이 여러 반복 방법의 목표는 각 변경의 이유를 이해할 수 있도록 하는 것입니다.
반복 #1 - 애플리케이션을 만듭니다. 첫 번째 반복에서는 가능한 가장 간단한 방법으로 연락처 관리자를 만듭니다. CRUD(만들기, 읽기, 업데이트 및 삭제)의 기본 데이터베이스 작업에 대한 지원을 추가합니다.
반복 #2 - 애플리케이션을 멋지게 만듭니다. 이 반복에서는 기본 ASP.NET MVC 보기 master 페이지 및 계단식 스타일시트를 수정하여 애플리케이션의 모양을 개선합니다.
반복 #3 - 양식 유효성 검사를 추가합니다. 세 번째 반복에서는 기본 양식 유효성 검사를 추가합니다. 사용자가 필요한 양식 필드를 완료하지 않고 양식을 제출하지 못하도록 합니다. 또한 전자 메일 주소 및 전화 번호의 유효성을 검사합니다.
반복 #4 - 애플리케이션을 느슨하게 결합합니다. 이 네 번째 반복에서는 여러 소프트웨어 디자인 패턴을 활용하여 Contact Manager 애플리케이션을 더 쉽게 유지 관리하고 수정할 수 있습니다. 예를 들어 리포지토리 패턴 및 종속성 주입 패턴을 사용하도록 애플리케이션을 리팩터링합니다.
반복 #5 - 단위 테스트 만들기 다섯 번째 반복에서는 단위 테스트를 추가하여 애플리케이션을 더 쉽게 유지 관리하고 수정할 수 있습니다. 데이터 모델 클래스를 모의하고 컨트롤러 및 유효성 검사 논리에 대한 단위 테스트를 빌드합니다.
반복 #6 - 테스트 기반 개발을 사용합니다. 이 여섯 번째 반복에서는 먼저 단위 테스트를 작성하고 단위 테스트에 대한 코드를 작성하여 애플리케이션에 새로운 기능을 추가합니다. 이 반복에서는 연락처 그룹을 추가합니다.
반복 #7 - Ajax 기능 추가 일곱 번째 반복에서는 Ajax에 대한 지원을 추가하여 애플리케이션의 응답성과 성능을 향상시킵니다.
이 반복
Contact Manager 애플리케이션의 이 두 번째 반복에서는 기본 양식 유효성 검사를 추가합니다. 필요한 양식 필드에 대한 값을 입력하지 않고 연락처를 제출하지 못하도록 합니다. 또한 전화 번호 및 전자 메일 주소의 유효성을 검사합니다(그림 1 참조).
그림 01: 유효성 검사가 있는 양식(전체 크기 이미지를 보려면 클릭)
이 반복에서는 유효성 검사 논리를 컨트롤러 작업에 직접 추가합니다. 일반적으로 이 방법은 ASP.NET MVC 애플리케이션에 유효성 검사를 추가하는 데 권장되지 않습니다. 더 나은 방법은 애플리케이션의 유효성 검사 논리를 별도의 서비스 계층에 배치하는 것입니다. 다음 반복에서는 애플리케이션을 더 쉽게 유지 관리할 수 있도록 Contact Manager 애플리케이션을 리팩터링합니다.
이 반복에서는 작업을 간단하게 유지하기 위해 모든 유효성 검사 코드를 직접 작성합니다. 유효성 검사 코드를 직접 작성하는 대신 유효성 검사 프레임워크를 활용할 수 있습니다. 예를 들어 Microsoft VAB(엔터프라이즈 라이브러리 유효성 검사 애플리케이션 블록)를 사용하여 ASP.NET MVC 애플리케이션에 대한 유효성 검사 논리를 구현할 수 있습니다. 유효성 검사 애플리케이션 블록에 대한 자세한 내용은 다음을 참조하세요.
http://msdn.microsoft.com/library/dd203099.aspx
만들기 뷰에 유효성 검사 추가
먼저 만들기 보기에 유효성 검사 논리를 추가해 보겠습니다. 다행히 Visual Studio를 사용하여 만들기 뷰를 생성했기 때문에 만들기 보기에는 유효성 검사 메시지를 표시하는 데 필요한 모든 사용자 인터페이스 논리가 이미 포함되어 있습니다. 만들기 보기는 목록 1에 포함되어 있습니다.
목록 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>
HTML 양식 바로 위에 나타나는 Html.ValidationSummary() 도우미 메서드를 호출합니다. 유효성 검사 오류 메시지가 있는 경우 이 메서드는 글머리 기호 목록에 유효성 검사 메시지를 표시합니다.
또한 각 양식 필드 옆에 표시되는 Html.ValidationMessage()를 호출합니다. ValidationMessage() 도우미는 개별 유효성 검사 오류 메시지를 표시합니다. 목록 1의 경우 유효성 검사 오류가 있을 때 별표가 표시됩니다.
마지막으로 Html.TextBox() 도우미는 도우미가 표시하는 속성과 관련된 유효성 검사 오류가 있는 경우 Cascading Style Sheet 클래스를 자동으로 렌더링합니다. Html.TextBox() 도우미는 input-validation-error라는 클래스를 렌더링합니다.
새 ASP.NET MVC 애플리케이션을 만들면 Content 폴더에 Site.css라는 스타일시트가 자동으로 만들어집니다. 이 스타일시트에는 유효성 검사 오류 메시지의 모양과 관련된 CSS 클래스에 대한 다음 정의가 포함되어 있습니다.
.field-validation-error
{
color: #ff0000;
}
.input-validation-error
{
border: 1px solid #ff0000;
background-color: #ffeeee;
}
.validation-summary-errors
{
font-weight: bold;
color: #ff0000;
}
field-validation-error 클래스는 Html.ValidationMessage() 도우미가 렌더링한 출력의 스타일을 지정하는 데 사용됩니다. input-validation-error 클래스는 Html.TextBox() 도우미가 렌더링한 텍스트 상자(입력)의 스타일을 지정하는 데 사용됩니다. validation-summary-errors 클래스는 Html.ValidationSummary() 도우미가 렌더링한 순서가 지정되지 않은 목록의 스타일을 지정하는 데 사용됩니다.
참고
이 섹션에 설명된 스타일시트 클래스를 수정하여 유효성 검사 오류 메시지의 모양을 사용자 지정할 수 있습니다.
만들기 작업에 유효성 검사 논리 추가
현재 만들기 보기에는 메시지를 생성하는 논리를 작성하지 않았기 때문에 유효성 검사 오류 메시지가 표시되지 않습니다. 유효성 검사 오류 메시지를 표시하려면 ModelState에 오류 메시지를 추가해야 합니다.
참고
UpdateModel() 메서드는 양식 필드의 값을 속성에 할당하는 동안 오류가 발생하면 자동으로 ModelState에 오류 메시지를 추가합니다. 예를 들어 DateTime 값을 허용하는 BirthDate 속성에 문자열 "apple"을 할당하려고 하면 UpdateModel() 메서드가 ModelState에 오류를 추가합니다.
목록 2의 수정된 Create() 메서드에는 새 연락처가 데이터베이스에 삽입되기 전에 Contact 클래스의 속성의 유효성을 검사하는 새 섹션이 포함되어 있습니다.
목록 2 - Controllers\ContactController.cs(유효성 검사를 사용하여 만들기)
//
// 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();
}
}
유효성 검사 섹션에서는 네 가지 고유한 유효성 검사 규칙을 적용합니다.
- FirstName 속성의 길이가 0보다 커야 하며 공백으로만 구성될 수 없습니다.
- LastName 속성의 길이가 0보다 커야 하며 공백으로만 구성될 수 없습니다.
- Phone 속성에 값이 있으면(길이가 0보다 큼) Phone 속성이 정규식과 일치해야 합니다.
- Email 속성에 값(길이가 0보다 큼)이 있는 경우 Email 속성은 정규식과 일치해야 합니다.
유효성 검사 규칙 위반이 있는 경우 AddModelError() 메서드의 도움을 받아 ModelState에 오류 메시지가 추가됩니다. ModelState에 메시지를 추가할 때 속성의 이름과 유효성 검사 오류 메시지의 텍스트를 제공합니다. 이 오류 메시지는 Html.ValidationSummary() 및 Html.ValidationMessage() 도우미 메서드를 통해 보기에 표시됩니다.
유효성 검사 규칙이 실행되면 ModelState의 IsValid 속성이 선택됩니다. 유효성 검사 오류 메시지가 ModelState에 추가된 경우 IsValid 속성은 false를 반환합니다. 유효성 검사에 실패하면 만들기 양식이 오류 메시지와 함께 다시 표시됩니다.
참고
에서 정규식 리포지토리에서 전화 번호 및 이메일 주소의 유효성을 검사하기 위한 정규식을 받았습니다. http://regexlib.com
편집 작업에 유효성 검사 논리 추가
편집() 작업은 연락처를 업데이트합니다. Edit() 작업은 Create() 작업과 정확히 동일한 유효성 검사를 수행해야 합니다. 동일한 유효성 검사 코드를 복제하는 대신 Create() 및 Edit() 작업이 동일한 유효성 검사 메서드를 호출하도록 Contact 컨트롤러를 리팩터링해야 합니다.
수정된 Contact 컨트롤러 클래스는 목록 3에 포함되어 있습니다. 이 클래스에는 Create() 및 Edit() 작업 내에서 호출되는 새 ValidateContact() 메서드가 있습니다.
목록 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();
}
}
}
}
요약
이 반복에서는 Contact Manager 애플리케이션에 기본 양식 유효성 검사를 추가했습니다. 유효성 검사 논리를 사용하면 사용자가 FirstName 및 LastName 속성에 대한 값을 제공하지 않고 새 연락처를 제출하거나 기존 연락처를 편집할 수 없습니다. 또한 사용자는 유효한 전화 번호와 이메일 주소를 제공해야 합니다.
이 반복에서는 가능한 가장 쉬운 방법으로 Contact Manager 애플리케이션에 유효성 검사 논리를 추가했습니다. 그러나 유효성 검사 논리를 컨트롤러 논리에 혼합하면 장기적으로 문제가 발생합니다. 애플리케이션은 시간이 지남에 따라 유지 관리 및 수정하기가 더 어려울 것입니다.
다음 반복에서는 컨트롤러에서 유효성 검사 논리 및 데이터베이스 액세스 논리를 리팩터링합니다. 몇 가지 소프트웨어 디자인 원칙을 활용하여 보다 느슨하게 결합되고 유지 관리가 가능한 애플리케이션을 만들 수 있습니다.