종류
- Client Validation : javascript로 client쪽에서, 보통 jQuery사용
- Data Annotation : 모델차원에서
- Remote Validation : ajax처럼 client에서 server측 유효성 검사 로직 호출
- Self Validation : ViewModel 자체가 유효성 검사코드 가짐
- plug-in : Castle, Enterprise Library
Data Annotation (모델 기반)
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
[Required(ErrorMessage="이름을 반드시 입력하세욧!")] // 필수
[StringLength(25)] // 문자열 길이제한
public string Username { get; set; }
[Range(1, 120)] // 범위제한
public int Hours { get; set; }
[Compare("Hours")] // Hours와 값이 같아야 한다.
public int ConfirmHours { get; set; }
Custom Validation Attributes (사용자 정의)
- IsValid 를 override하여 정의
- Validation 폴더를 만들고, ValidationAttribute를 상속받아 만들자
- 팁 : "override "까지 입력후 목록이 나오면 선택후에 탭키를 누른다.
- Custom Validation Attributes 생성
using System;
using System.ComponentModel.DataAnnotations;
namespace MvcValidation.Validation
{
public class GreaterThanDateAttribute : ValidationAttribute
{
public string OtherPropertyName { get; set; } // 대상 속성명
public GreaterThanDateAttribute(string otherPropertyName) : base("{0}는 반드시 {1}보다 커야합니다.")
{
this.OtherPropertyName = otherPropertyName;
}
public override string FormatErrorMessage(string name)
{
return string.Format(ErrorMessageString, name, OtherPropertyName);
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
// 현재개체
var thisDate = (DateTime)value; // EndDate
// 대상개체 가져오기
var otherPropertyInfo = validationContext.ObjectType.GetProperty(OtherPropertyName);
var otherDate = (DateTime)otherPropertyInfo.GetValue(validationContext.ObjectInstance, null);
// 유효성 검사 : StartDate < EndDate
if (otherDate >= thisDate)
{
var message = FormatErrorMessage(validationContext.DisplayName);
return new ValidationResult(message);
}
return null;
}
}
}
[GreaterThanDate]
public DateTime EndDate { get; set; }
Self Validation
- IvaliatableObject 인터페이스 구현 (Model 개체에 Validate() 메서드 구현)
- Model차원에서 검사하기 때문에 Custom Validation 와 에러문구 위치가 틀려진다.
public class TimeCard : IValidatableObject
{
...
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (EndDate <= StartDate)
{
yield return new ValidationResult("EndDate는 반드시 StartDate보다 커야 합니다.");
}
}
}
Client Validation
- Unobtrusive(튀지않는) javascript 사용 : jQuery Validation만 사용하면 됨
- jQuery validate plug-in : 서버사이드 유효성 검사도 필수
- web.config 설정
<appSettings>
<add key="ClientValidationEnabled" value="true"/> // 서버까지 안가고..
<add key="UnobtrusiveJavaScriptEnabled" value="true"/> // 튀지않는..
</appSettings>
@{ Html.EnableClientValidation(false); }
@{ Html.EnableUnobtrusiveJavaScript(false); }
Custom Client Validation
- jQuery.validate에 대한 이해가 필요. 어렵다. 힘들면 하지말자
- 보통 기본제공하는 validate가 아닌 경우 서버에 갔다와야 한다. 이걸 Client에서 유효성 검사해보자.
- 아까만든 GreaterThanDateAttribute에 IClientValidatable 상속받게 하여 메소드 구현
// 사용자 정의 클라이언트측 유효성 검사
public System.Collections.Generic.IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule();
rule.ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()); // EndDate
rule.ValidationType = "greater"; // 내가 원하는 이름을 만들어준다.
rule.ValidationParameters.Add("other", OtherPropertyName);
yield return rule; // IEnumerable 로 여러개 리턴할 수 있으니까 yield return 하자.
}
- jQuery validation 메서드를 javascript로 구현
- Script 폴더에 CustomValidation.js 파일 추가
- View에 js를 적용 (솔류션 탐색기에서 js파일을 던진다)
- CustomValidation.js 에 reference 추가 (jquery-1.5.1-vsdoc.js, jquery.validate-vsdoc.js, jquery.validate.unobtrusive.js 파일을 던진다)
/// <reference path="jquery-1.5.1-vsdoc.js" />
/// <reference path="jquery.validate.unobtrusive.js" />
/// <reference path="jquery.validate-vsdoc.js" />
// value : StartDate, param : EndDate
// greater는 GreaterThanDateAttribute 에서 만든 이름
jQuery.validator.addMethod("greater", function (value, element, param) {
return Date.parse(value) > Date.parse($(param).val());
});
jQuery.validator.unobtrusive.adapters.add("greater", ["other"], function (options) {
options.rules["greater"] = "#" + options.params.other;
options.messages["greater"] = options.message;
});
Remote Validation
- ajax와 비슷, 서버측 메서드를 읽어서 실행 (DB를 검사하는 등의 시나리오)
- 모델에 메소드 이름 추가
[Remote("CheckUsername", "Work", ErrorMessage="해당 이름이 없습니다.")]
public string Username { get; set; }
- Work 컨트롤러의 CheckUsername 메소드 실행 (아래의 코드에서 AllowGe t의 공백 없어야함.)
public JsonResult CheckUsername(string username)
{
var result = false;
// 실제 DB값을 뒤져야 한다.
if (username == "kimstar") result = true;
return Json(result, JsonRequestBehavior.AllowGe t);
}