2

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

2 回答 2

2

摆脱Take(1). 我怀疑空字符串正在通过Required测试。如果您碰巧得到它而不是长度验证器,则测试通过。

于 2010-02-15T20:38:51.470 回答
0

尝试使用

var errors = DataAnnotationsValidationRunner.GetFirstErrors(test).ToArray();
于 2010-02-15T14:38:51.557 回答