Я работал над приложением, которое использует проверку на стороне сервера xVal с аннотациями данных. Недавно мы столкнулись с ошибками, когда сообщения проверки были непредсказуемыми для полей, которые имеют несколько проверок, которые могут завершиться ошибкой, если поле пустое (например, требуется адрес электронной почты, но также не проходит проверку достоверности).
Предполагая, что мне нужно было просто вернуть первую ошибку проверки, я добавил метод к нашему исполнителю проверки для достижения этой цели ( ОБНОВЛЕНИЕ : точный метод см. В правке внизу):
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);
}
Я также настроил простой метод тестирования для проверки в 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);
}