2009-09-02 2 views
1

나는 일반적으로 큰 내 ASP.NET MVC 응용 프로그램에서 xVal을 사용하고 있습니다. Steve Sanderson's blog post 다음에 DataAnnotationsValidationRunner를 만들어 속성 ​​객체의 서버 측 유효성 검사를 수행했습니다. 이것은 간단한 수업에 효과적입니다. 예 : 사람 : 나는이 사람에게 주소 속성을 추가하고 DataAnnotation 속성과 주소 클래스를 표시하는 경우xVal 복합 유형의 하위 속성을 어떻게 확인합니까?

public static class DataAnnotationsValidationRunner 
{ 
    public static IEnumerable<ErrorInfo> GetErrors(object o) 
    { 
     return from prop in TypeDescriptor.GetProperties(o).Cast<PropertyDescriptor>() 
       from attribute in prop.Attributes.OfType<ValidationAttribute>() 
       where !attribute.IsValid(prop.GetValue(o)) 
       select new ErrorInfo(prop.Name, attribute.FormatErrorMessage(string.Empty), o); 
    } 
} 

public class Person 
{ 
    [Required(ErrorMessage="Please enter your first name")] 
    public string FirstName { get; set; } 

    [Required(ErrorMessage = "Please enter your last name")] 
    public string LastName { get; set; } 
} 

그러나, 그들은 검증되지 않습니다. 예 :

public class Person 
{ 
    [Required(ErrorMessage="Please enter your first name")] 
    public string FirstName { get; set; } 

    [Required(ErrorMessage = "Please enter your last name")] 
    public string LastName { get; set; } 

    public Address Address { get; set; } 
} 

public class Address 
{ 
    [Required(ErrorMessage="Please enter a street address")] 
    public string Street { get; set; } 

    public string StreetLine2 { get; set; } 

    [Required(ErrorMessage = "Please enter your city")] 
    public string City { get; set; } 

    [Required(ErrorMessage = "Please enter your state")] 
    public string State { get; set; } 

    [Required(ErrorMessage = "Please enter your zip code")] 
    public string Zip { get; set; } 

    public string Country { get; set; } 
} 

하나의 문제는 DataAnnotationValidationRunner가 복잡한 자식 속성을 걸어하지 않습니다. 또한 이러한 오류가 오류 컬렉션에 추가되면 모델 상태에 추가 될 때 여전히 올바르게 접두사를 가져와야합니다. 예를 들어. 사람이 오류는 다음과 같이 추가됩니다

catch (RulesException ex) 
    { 
     ex.AddModelStateErrors(ModelState, "person"); 
    } 

내가 주소 규칙의 예외는 "있는 Person.Address"로 시작 될 필요가있다 생각합니다. xVal을 사용하여 자식 개체 유효성 검사를 처리하는 지원되는 방법이 있습니까? 아니면 단순화 된 데이터 전송 개체를 만드는 것이 유일한 해결책입니까? 모든

답변

2

첫째, 당신은 ("DataAnnotationValidationRunner는 복잡한 자식 속성을 걸어하지 않습니다") 첫 번째 질문에 대해서는 스티브 샌더슨의 DataAnnotationsModelBinder 및

사이에 차이가해야

아마도 당신이 있습니까 Brad Wilson의 DataAnnotationModelBinder? 그렇다면 실제로는 복잡한 ViewModel을 마지막 속성까지 검증해야합니다. 그렇지 않은 경우 사용중인 DataAnnoationsModelRunner 대신 해당 값을 사용해보십시오. Client-Side Validation with xVal에 대한이 블로그 기사 블로그 기사는 방법을 보여줍니다.

DataAnnotationModelBinder의 첫 번째 버전은 복잡한 viewmodels와 함께 사용할 때 충돌이 만들 수있는 버그를했다. 아마도 충돌을 수정하지만 복잡한 모델을 무시하는 새로운 버전이있을 것입니다.

어쨌든 위의 링크 된 블로그 기사의 데모 프로젝트에 사용 된 DataAnnotationModelBinder의 버전을 제공하는 것이 좋습니다. 내 자신의 실제 프로젝트에서 사용하고 있으며 복잡한보기 모델에서 작동합니다.

두 번째 질문 "경우 xval와 자식 개체 유효성 검사를 처리하는 지원 방법이"에 관한 :

당신은 ASPX 양식에있는 코드를 게시하지 않은,하지만 당신은 또한 사실에 참조 될 수있다 < % = Html.ClientSideValidation() %>은 클라이언트 쪽 유효성 검사를 해당 모델 유형의 즉시 속성에만 추가하지만 자식 개체의 속성은 추가하지 않습니다. 다음과 같이 여러 ClientSideValidation 문을 사용하여 문제를 간단히 피할 수 있습니다.

+0

두 번째 대답은 작동하지만 부모 개체에 여러 속성이 있지만 모두 동일한 자식 유형을 연결하지만 속성이 다른 경우 세분화됩니다. 즉. 사용자 BillingAddress ShippingAddress 이 문제를 해결하기 위해 xval.jquery 유효성 검사 유틸리티를 조정할 수있는 것처럼 보입니다. –

1

같은 문제가있었습니다. 다른 객체의 속성으로 나타날 수있는 복잡한 객체의 유효성을 검사해야했습니다. 클라이언트 측 유효성 검사 (아직)에 들어 가지 않았지만 Adrian Grigore가 여러 html에 대한 아이디어를 얻었습니다 .ClientSideValidation()은 티켓이 될 것 같습니다.

필자는 유효성을 검사해야하는 모든 클래스를 표시하는 마커 인터페이스를 만들었습니다. 속성 일 수도 있고 클래스의 모든 속성에 대해이 아이디어를 사용할 수도 있습니다.

기본적으로 위에서 언급 한 DataAnnotationsValidationRunner를 사용하여 개체의 유효성을 검사 한 다음 개체의 속성을 반복하고 검사 할 것이 없을 때까지 모든 개체에 대해 DataAnnotationsValicationRunner를 실행합니다.

는 여기에 내가 무슨 짓을했는지에 대한 의사 코드입니다 :

IEnumarable<ValidationError> GetErrors(object instance) { 
    List<ValidationError> errors = new List<ValidationError>(); 
    errors.AddRange(GetDataAnnotationErrors(instance)); 
    errors.AddRange(GetPropertyErrors(instance)); 
    return errors; 
} 
IEnumerable<ValidationError> GetDataAnnotationErrors(object instance) { 
    // code very similar to what you have above 
} 
IEnumearable<ValidationError> GetPropertyErrors(object instance) 
{ 
    var errors = new List<ValidationError>(); 
    var objectsToValidate = instance.GetType().GetProperties().Where(p => p.PropertyType.GetInterface().Contains(typeof(IMarkerInterface))); 
    // the call above could do any type of reflecting over the properties you want 
    // could just check to make sure it isn't a base type so that all custom 
    // object would be checked 
    if(objectsToValidate == null) return errors; 
    foreach(object obj in objectsToValidate) 
    { 
      errors.AddRange(GetDataAnnotationErrors(obj)); 
      errors.AddRange(GetPropertyErrors(obj)); 
    } 
    return errors; 
} 

나는이 분명하다 바랍니다. 나는 도메인 객체에 대해이 시스템을 테스트 해왔고 지금까지 그렇게 잘 해왔다. 여기저기서 약간의 꼬임을 풀지 만, 그 아이디어는 내가하고있는 것에 대해 검증 된 사운드를 가지고 있습니다.