2010-06-25 5 views
2

J'ai un DataAnnotationValidator que j'ai créé. J'essaie actuellement de le tester avec un attribut Champ obligatoire et je ne peux pas obtenir la propriété IsValid à échouer lorsque ma propriété est null. Cela fonctionne correctement lorsque je crée un nombre avec un attribut Range qui est en dehors de la plage spécifiée.L'attribut requis dans DataAnnotations ne semble pas fonctionner

public class TestEntityWithDataAnnotations 
{ 
    public Guid Id { get; set; } 

    [Required(ErrorMessage = "Required")] 
    public string Name { get; set; } 
} 

[TestFixture] 
public class DataAnnotationValidatorTest 
{ 
    [Test] 
    public void Validate_ReturnsFailure_WhenPropertyValidationIsNotValid() 
    { 
     var validator = new DataAnnotationValidator(); 
     var invalidEntity = new TestEntityWithDataAnnotations 
     { 
      Id = Guid.NewGuid() 
     }; 
     var validationResult = validator.Validate(invalidEntity); 

     Assert.IsFalse(validationResult.IsValid); 
    } 
} 

public class DataAnnotationValidator 
{ 
    public ValidationResult Validate(object obj) 
    { 
     Type objType = obj.GetType();    
     var typeDescriptor = GetTypeDescriptor(obj, objType); 
     var validationResult = new ValidationResult(); 

     var classValidationResult = CheckClassIsValid(obj, typeDescriptor); 
     if (!classValidationResult.IsValid) 
     { 
      validationResult.AddErrors(classValidationResult.Errors); 
     } 
     foreach (PropertyDescriptor propertyDescriptor in typeDescriptor.GetProperties()) 
     { 
      // Loop over all of the properties on our object that have Validation Attributes 
      var propValidationResult = CheckPropertyIsValid(obj, propertyDescriptor); 
      if(!propValidationResult.IsValid) 
      { 
       validationResult.AddErrors(propValidationResult.Errors); 
      } 
     } 
     return validationResult; 
    } 

    /// <summary> 
    /// Checks to see if there are any class level validation attributes and runs them 
    /// </summary> 
    /// <returns></returns> 
    private static ValidationResult CheckClassIsValid(object obj, ICustomTypeDescriptor typeDescriptor) 
    { 
     var errors = typeDescriptor.GetAttributes().OfType<ValidationAttribute>() 
      .Where(x => !x.IsValid(obj)) 
      .Select(x => new ValidationError(typeDescriptor.GetClassName(), x.ErrorMessage)); 
     return new ValidationResult(errors.ToList()); 
    } 

    /// <summary> 
    /// Checks to see if a property has any DataAnnotations that it has violated 
    /// </summary> 
    private static ValidationResult CheckPropertyIsValid(object obj, PropertyDescriptor propertyDescriptor) 
    { 
     var errors = propertyDescriptor.Attributes.OfType<ValidationAttribute>() 
      .Where(x => !x.IsValid(obj)) 
      .Select(x => new ValidationError(propertyDescriptor.Name, x.ErrorMessage)); 
     return new ValidationResult(errors.ToList()); 
    } 

    /// <summary> 
    /// Gets the model's type descriptor. In order to support the buddy class metadata model 
    /// for LINQ to SQL and Entity Framework, it uses 
    /// <see cref="AssociatedMetadataTypeTypeDescriptionProvider"/>. 
    /// </summary> 
    /// <param name="obj">The model object</param> 
    /// <param name="objType">The type of the model object</param> 
    /// <returns>The model's type descriptor</returns> 
    private static ICustomTypeDescriptor GetTypeDescriptor(object obj, Type objType) 
    { 
     var provider = new AssociatedMetadataTypeTypeDescriptionProvider(objType); 
     return provider.GetTypeDescriptor(objType, obj); 
    } 
} 

Répondre

2

Un peu de bêtise de ma part. J'avais besoin de passer la valeur de la propriété dans IsValid à l'intérieur de CheckPropertyIsValid au lieu de l'objet entier.

private static ValidationResult CheckPropertyIsValid(object obj, PropertyDescriptor propertyDescriptor) 
    { 
     var errors = propertyDescriptor.Attributes.OfType<ValidationAttribute>() 
      .Where(x => !x.IsValid(propertyDescriptor.GetValue(obj))) 
      .Select(x => new ValidationError(propertyDescriptor.Name, x.ErrorMessage)); 
     return new ValidationResult(errors.ToList()); 
    }