私は、xVal のサーバー側検証とデータ注釈を使用するアプリケーションに取り組んできました。最近、フィールドが空の場合に失敗する可能性のある複数の検証があるフィールドに対して、検証メッセージが予測できないというエラーが発生しました (たとえば、電子メール アドレスが必要ですが、有効性チェックにも失敗するなど)。
最初の検証エラーを返すだけでよいと仮定して、その目標を達成するために検証ランナーにメソッドを追加しました ( UPDATE : 正確なメソッドについては、下部の編集を参照してください)。
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"));
}
問題は、このテストの出力が非常に予測不可能であることです。成功する場合もあれば、エラーが 1 つまたは 2 つしか返されない場合もあれば、まったくエラーが返されない場合もあります。問題は、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);
}