Я понимаю, что IValidatableObject
это используется для проверки объекта таким способом, который позволяет сравнивать свойства друг с другом.
Я все еще хотел бы иметь атрибуты для проверки отдельных свойств, но в некоторых случаях я хочу игнорировать сбои некоторых свойств.
Я пытаюсь использовать это неправильно в случае ниже? Если нет, то как мне это реализовать?
public class ValidateMe : IValidatableObject
{
[Required]
public bool Enable { get; set; }
[Range(1, 5)]
public int Prop1 { get; set; }
[Range(1, 5)]
public int Prop2 { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (!this.Enable)
{
/* Return valid result here.
* I don't care if Prop1 and Prop2 are out of range
* if the whole object is not "enabled"
*/
}
else
{
/* Check if Prop1 and Prop2 meet their range requirements here
* and return accordingly.
*/
}
}
}
Цитата из сообщения Джеффа Хэндли в блоге об объектах и свойствах проверки с помощью Validator :
Это означает, что то, что вы пытаетесь сделать, не будет работать «из коробки», поскольку проверка будет прервана на шаге № 2. Вы можете попытаться создать атрибуты, которые наследуются от встроенных, и, в частности, проверить наличие включенного свойства (через интерфейс) перед выполнением их обычной проверки. В качестве альтернативы, вы можете поместить всю логику для проверки сущности в
Validate
методе.источник
Просто добавлю пару пунктов:
Поскольку
Validate()
возвращается сигнатура методаIEnumerable<>
, этоyield return
может использоваться для ленивой генерации результатов - это полезно, если некоторые из проверочных проверок требуют интенсивного ввода-вывода или загрузки ЦП.Кроме того, если вы используете
MVC ModelState
, вы можете преобразовать ошибки результата проверки вModelState
записи следующим образом (это может быть полезно, если вы выполняете проверку в привязке пользовательской модели ):источник
Я реализовал абстрактный класс общего использования для проверки
источник
Проблема с принятым ответом состоит в том, что теперь от вызывающей стороны зависит правильность проверки объекта. Я бы либо удалил RangeAttribute и выполнил валидацию диапазона внутри метода Validate, либо я бы создал собственный атрибут подкласса RangeAttribute, который принимает имя требуемого свойства в качестве аргумента в конструкторе.
Например:
источник
Мне понравился ответ cocogza за исключением того, что вызов base.IsValid привел к исключению переполнения стека, так как он будет снова и снова вводить метод IsValid. Поэтому я изменил его, чтобы он соответствовал определенному типу проверки, в моем случае это был адрес электронной почты.
Это работает намного лучше! Он не падает и выдает хорошее сообщение об ошибке. Надеюсь, это поможет кому-то!
источник
Что мне не нравится в iValidate, так это то, что он запускается только ПОСЛЕ всех других проверок.
Кроме того, по крайней мере, на нашем сайте, он будет работать снова во время попытки сохранения. Я бы посоветовал вам просто создать функцию и поместить в нее весь код проверки. В качестве альтернативы для веб-сайтов, у вас может быть «специальная» проверка в контроллере после создания модели. Пример:
источник