Понимание ValidationContext в DataAnnotations - PullRequest
19 голосов
/ 30 ноября 2010

Я хочу использовать Validator.TryValidateValue(), но не понимаю механику.Скажем, у меня есть следующее:

public class User {
    [Required(AllowEmptyStrings = false)]
    [StringLength(6)]
    public string Name { get; set; }
}

и метод:

public void CreateUser(string name) {...}

Мой код проверки:

ValidationAttribute[] attrs = bit of reflection here to populate from User class
var ctx = new ValidationContext(name, null, null);
var errors = new List<ValidationResult>();
bool valid = Validator.TryValidateValue(name, ctx, errors, attrs);

Работает нормально до значения name - это null.Я получаю ArgumentNullException при создании экземпляра ValidationContext и не понимаю почему.TryValidateValue() также требует ненулевого контекста.У меня есть значение и список атрибутов для проверки.Для чего это ValidationContext?

1 Ответ

18 голосов
/ 10 декабря 2010

Единственное, что не так в вашем коде, это объект экземпляра для вашего контекста проверки.Экземпляр не обязательно должен быть проверяемым значением.Для Validator.ValidateProperty, да, это должен быть объект, которому принадлежит свойство, но для Validator.ValidateValue достаточно «this».

Я написал вспомогательный класс проверки для выполнения настройки;это позволяет мне передавать произвольные значения из любого места.

public class ValidationHelper
{
    private List<ValidationResult> m_validationResults = new List<ValidationResult>();
    private List<ValidationAttribute> m_validationAttributes = new List<ValidationAttribute>();

    public Tuple<bool, List<string>> ValidateDOB(DateTime? dob)
    {
        m_validationAttributes.Add(new CustomValidationAttribute(typeof(DateOfBirthValidator), "ValidateDateOfBirth"));
        bool result = Validator.TryValidateValue(dob, 
                             new ValidationContext(this, null, null), 
                             m_validationResults, 
                             m_validationAttributes);
        if (result)
        {
            return Tuple.Create(true, new List<string>());
        }
        List<string> errors = m_validationResults.Select(vr => vr.ErrorMessage).ToList();
        return Tuple.Create(false, errors);
    }
}

Если вы проверяете свойства, которые имеют атрибуты проверки для свойства, это намного проще:

internal void Validate(T value)
{
    if (!m_Initializing && TrackChanges && !Entity.IsImmutable)
    {
        Validator.ValidateProperty(value, new ValidationContext(Entity, null, null) { MemberName = PropertyName ?? ModelName });
    }
}

"Entity"это свойство текущего класса, которое ссылается на объект, который я хочу проверить.Это позволяет мне проверять свойства других объектов.Если вы уже внутри объекта, «этого» снова будет достаточно.

...