我一直在开发一个使用 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);
}