다음을 통해 공유


반복 #3 - 양식 유효성 검사 추가(VB)

작성자: Microsoft

코드 다운로드

세 번째 반복에서는 기본 양식 유효성 검사를 추가합니다. 사용자가 필요한 양식 필드를 완료하지 않고 양식을 제출하지 못하도록 합니다. 또한 전자 메일 주소 및 전화 번호의 유효성을 검사합니다.

VB(연락처 관리 ASP.NET MVC 애플리케이션) 빌드

이 자습서 시리즈에서는 처음부터 끝까지 전체 연락처 관리 애플리케이션을 빌드합니다. 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="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에 오류 메시지를 추가합니다. 예를 들어 DateTime 값을 허용하는 BirthDate 속성에 문자열 "apple"을 할당하려고 하면 UpdateModel() 메서드가 ModelState에 오류를 추가합니다.

목록 2의 수정된 Create() 메서드에는 새 연락처가 데이터베이스에 삽입되기 전에 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

유효성 검사 섹션에서는 네 가지 고유한 유효성 검사 규칙을 적용합니다.

  • 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.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

요약

이 반복에서는 Contact Manager 애플리케이션에 기본 양식 유효성 검사를 추가했습니다. 유효성 검사 논리를 사용하면 사용자가 FirstName 및 LastName 속성에 대한 값을 제공하지 않고 새 연락처를 제출하거나 기존 연락처를 편집할 수 없습니다. 또한 사용자는 유효한 전화 번호와 이메일 주소를 제공해야 합니다.

이 반복에서는 가능한 가장 쉬운 방법으로 Contact Manager 애플리케이션에 유효성 검사 논리를 추가했습니다. 그러나 유효성 검사 논리를 컨트롤러 논리에 혼합하면 장기적으로 문제가 발생합니다. 애플리케이션은 시간이 지남에 따라 유지 관리 및 수정하기가 더 어려울 것입니다.

다음 반복에서는 컨트롤러에서 유효성 검사 논리 및 데이터베이스 액세스 논리를 리팩터링합니다. 몇 가지 소프트웨어 디자인 원칙을 활용하여 보다 느슨하게 결합되고 유지 관리가 가능한 애플리케이션을 만들 수 있습니다.