iam*_*ody 9 c# validation error-handling data-annotations
一直试图将服务器端DataAnnotation验证合并到我的项目中,我发现DataAnnotations有自己的错误类型ValidationException.但是,我的问题在于,它一次只返回一个验证错误,所以如果3个属性验证失败,则只抛出第一个.我正在寻找一种方法将所有错误作为异常抛出,因此它不会通知用户/开发人员验证失败,而是会一次性说明哪些属性/字段验证失败.
我找到了Validator.TryValidateObject(...)方法,但它只是填充ValidationResults并让开发人员选择是否抛出异常.我目前正在实现的是迭代ValidationResults以从中创建ValidationExceptions列表,将列表包装到AggregateException中,然后在其InnerExceptions中抛出另一个带有AggregateException的ValidationException.
ValidationContext validationContext = new ValidationContext(entity, null, null);
List<ValidationResult> validationResults = new List<ValidationResult>();
bool isValid = Validator.TryValidateObject(entity, validationContext, validationResults, true);
if (!isValid)
{
List<ValidationException> validationErrors = new List<ValidationException>();
foreach (ValidationResult validationResult in validationResults)
{
validationErrors.Add(new ValidationException(validationResult.ErrorMessage);
}
throw new ValidationException("Entity validation failed.", new AggregateException(validationErrors));
}
Run Code Online (Sandbox Code Playgroud)
所以基本上,我的问题是:
关于你的第一个问题,“为什么语言不支持X”的标准答案只是成本与收益的比较,我确信这也适用于这里。人们并不经常遇到需要抛出多个错误的情况...因此,设计和实现 C# 的人们认为,C# 团队花在设计和实现“抛出多个异常”功能上的时间最好花在为更多人带来更多好处的功能。
并考虑语言用户的成本- 在当前有“catch (Exception e)”的任何地方,您都必须执行“catch (IEnumerable例外)”,然后是 foreach,以防您调用的 API 引发多个异常。
关于你的第二个问题,我认为将 ValidationExceptions 与 AggregateException 结合起来并将聚合设置为顶级 ValidationException 的 InnerException 是解决问题的一种相当优雅的方法......但这不是标准的,所以希望人们异常层次结构的“捕获”一侧是与您密切沟通的人。
您还可以考虑将 ValidationResult 集合存储在 ValidationException 的 Data 属性中。这有点简单。Data 属性并未广泛使用,但它存在于像这样的非标准场景中。
很难说这两种方法哪个更好,但我倾向于第一种。它更复杂,但我认为如果您基于 InnerException 和 AggregateException 构建,任意编码器发现您所做的事情的可能性会更高一些。我的意思是,您最后一次在调试某些内容时转储 Exception.Data 的内容是什么时候?是的,我也一样。:-)
关于你的第三个问题,我想我只是根据 ValidationResult 的内容构建 ValidationException 的消息。例如,“成员 {0} 无效:{1}”。