2010-02-15 5 views
2

저는 데이터 주석이있는 xVal의 서버 측 유효성 검사를 사용하는 응용 프로그램에서 작업했습니다. 최근 필드가 비어있는 경우 실패 할 수있는 여러 유효성 검사가있는 입력란 (예 : 이메일 주소가 필요하지만 유효성 검사에도 실패한)에 대해 유효성 확인 메시지를 예측할 수없는 오류가 발생했습니다.예측할 수없는 LINQ 쿼리 결과의 원본을 어떻게 결정합니까?

public static IEnumerable<ErrorInfo> GetFirstErrors<T>(object instance) where T : ValidationAttribute 
    { 
     return from prop in TypeDescriptor.GetProperties(instance).Cast<PropertyDescriptor>() 
       from attribute in prop.Attributes.OfType<T>().Take(1) 
       where !attribute.IsValid(prop.GetValue(instance)) 
       select new ErrorInfo(prop.Name, attribute.FormatErrorMessage(string.Empty), instance); 
    } 
:

난 그냥 첫 번째 유효성 검사 오류를 반환 할 필요가 있다고 가정하면, 그 목표 (: 정확한 방법의 하단에있는 편집을 참조 UPDATE)를 달성하기 위해 우리의 검증 주자에 메서드를 추가

또한 NUnit과에 확인하는 간단한 테스트 방법을 설정 :

private class FirstErrorValidationTest 
    { 
     [RequiredValueValidator(ErrorMessage = "This field is required"), StringLength(50)] 
     public string FirstName { get; set; } 

     [RequiredValueValidator(ErrorMessage = "This field is required"), StringLength(50)] 
     public string LastName { get; set; } 

     [RequiredValueValidator(ErrorMessage = "This field is required"), EmailAddressValidator, StringLength(50)] 
     public string EmailAddress { get; set; } 
    } 

    [Test] 
    public void Assert_GetFirstErrors_Gets_First_Listed_Validation_Attribute_Error_Messages() 
    { 
     FirstErrorValidationTest test = new FirstErrorValidationTest() 
     { 
      FirstName = "", 
      LastName = "", 
      EmailAddress = "" 
     }; 

     var errors = DataAnnotationsValidationRunner.GetFirstErrors(test); 

     Assert.AreEqual(3, errors.Count()); 

     foreach (var error in errors) 
      Assert.IsTrue(error.ErrorMessage.Contains("required")); 
    } 

문제는이 테스트의 출력은 매우 예측할 수없는 것입니다. 때로는 통과하고, 때로는 오류 중 하나 또는 두 개를 반환하고 때로는 전혀 반환하지 않습니다. LINQ 쿼리, 테스트 또는 둘 다에서 문제가 발생합니까?

편집 : 약간 다른 방법으로 붙여 넣기에 좋은 점; 여기에 실제로 명중 하나는 다음과 같습니다

public static IEnumerable<ErrorInfo> GetFirstErrors(object instance) 
    { 
     return from prop in TypeDescriptor.GetProperties(instance).Cast<PropertyDescriptor>() 
       from attribute in prop.Attributes.OfType<ValidationAttribute>().Take(1) 
       where !attribute.IsValid(prop.GetValue(instance)) 
       select new ErrorInfo(prop.Name, attribute.FormatErrorMessage(string.Empty), instance); 
    } 
+0

어떻게 컴파일합니까? 'GetFirstErrors'는 명시 적으로 또는 암시 적으로 지정하지 않는 타입 매개 변수 'T'를 요구합니다. –

+0

죄송합니다! 나는 적절한 방법으로 붙여 넣었다. –

답변

2

Take(1) 없애 사용할 수 있습니다. 빈 문자열이 Required 테스트를 통과 한 것 같습니다. 이 길이 유효성 검사기 대신에이되면 테스트가 통과합니다.

+0

Take (1) 호출은 분명히 범인입니다. 속성 선택에서 묵시적인 순서 또는 우선 순위를 가질 수있는 방법이 없습니까? 즉, 다른 속성 위에 필수 입력란 속성을 확인하십시오. –

+0

단위 테스트이므로 가능한 이유는 무엇입니까? 테스트 데이터의 모든 속성을 확인하지 않아야합니까? –

+0

필자는 분명 동의합니다. 그러나 필드 당 하나의 유효성 검증 오류를 표시하는 글로벌 규칙을 적용하는 더 좋은 방법은 무엇입니까 (필수 필드 실패에 유리합니까?). 어쨌든 모델 상태 오류가 사전에 롤업되어보기가 사용되는 것처럼 보입니다. 따라서 선택이 임의적이면 어떤 오류가 먼저 표시 될지 예측할 수없는 것처럼 보입니다. –

0

시도가

var errors = DataAnnotationsValidationRunner.GetFirstErrors(test).ToArray(); 
+0

나는 그것을 시도했지만 여전히 예측할 수없는 결과를 얻는다. NUnit을 떠날 때 clean/recompile 한 다음 다시 실행하는 것이 가장 바뀌기 쉽다는 것을 알았습니다. –

관련 문제