Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 返回多个ValidationException_C#_Validation_Error Handling_Data Annotations - Fatal编程技术网

C# 返回多个ValidationException

C# 返回多个ValidationException,c#,validation,error-handling,data-annotations,C#,Validation,Error Handling,Data Annotations,我一直在尝试将服务器端DataAnnotation验证合并到我的项目中,我发现DataAnnotations有它自己的错误类型,ValidationException。但我的问题是,它一次只返回一个验证错误,因此,如果3个属性验证失败,则只会抛出第一个属性。我正在寻找一种将所有错误作为异常抛出的方法,因此它不会通知用户/开发人员验证失败,而是会一次性声明哪些属性/字段未通过验证 我找到了Validator.TryValidateObject(…)方法,但它只是填充ValidationResult

我一直在尝试将服务器端DataAnnotation验证合并到我的项目中,我发现DataAnnotations有它自己的错误类型,ValidationException。但我的问题是,它一次只返回一个验证错误,因此,如果3个属性验证失败,则只会抛出第一个属性。我正在寻找一种将所有错误作为异常抛出的方法,因此它不会通知用户/开发人员验证失败,而是会一次性声明哪些属性/字段未通过验证

我找到了Validator.TryValidateObject(…)方法,但它只是填充ValidationResults,让开发人员可以选择是否抛出和异常。我当前实现的是迭代ValidationResults以创建一个ValidationException列表,将该列表包装到AggregateException中,然后在其InnerException中抛出另一个ValidationException和AggregateException

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));
}
ValidationContext ValidationContext=新的ValidationContext(实体,null,null);
列表验证结果=新列表();
bool isValid=Validator.TryValidateObject(实体,validationContext,validationResults,true);
如果(!isValid)
{
列表验证错误=新建列表();
foreach(ValidationResult ValidationResult in validationResults)
{    
添加(新的ValidationException(validationResult.ErrorMessage);
}
抛出新的ValidationException(“实体验证失败”)、新的AggregateException(validationErrors);
}
所以基本上,我的问题是:

  • 有没有一个原因可以解释为什么没有内置的方法可以同时抛出多个错误?也就是说,我是否缺少一些DataAnnotation验证的最佳实践
  • 有没有更好的方法来实现我想要实现的目标
  • 另外…在将ValidationResult包装到ValidationException中时,如何包含成员名称

  • 关于你的第一个问题,“为什么语言不支持X”的标准答案这只是成本与收益的对比,我相信这也适用于这里。人们并不经常遇到需要抛出多个错误的场景……因此设计和实现C#的人认为C#团队设计和实现“抛出多个异常”所需的时间该功能将更好地用于为更多人提供更多好处的功能

    并且考虑语言用户的成本——在你当前的任何地方都有“catch(异常e)”,你必须做“catch(iQualaby Exchange)”,而后面是一个前缀,以防你调用的API抛出多个异常。

    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));
    }
    
    关于你的第二个问题,我认为将ValidationException与AggregateException结合起来,并将聚合设置为顶级ValidationException的内部异常,是解决问题的一种相当简单的方法……但这不是标准的,所以希望“捕获”的人异常层次结构的另一面是与您密切沟通的人

    您还可以考虑将验证结果集合存储在验证异常的数据属性中。这有点简单。数据属性没有被广泛使用,但它对于像这样的非标准场景是存在的。

    很难说这两种方法中哪一种更好,但我倾向于第一种。它更复杂,但我认为,如果你建立在InnerException和AggregateException的基础上,任意编码者发现你所做的事情的可能性会更高。我的意思是,你最后一次在运行时转储Exception.Data的内容是什么时候我们在调试什么东西吗?是的,我也是。:-)


    关于你的第三个问题,我想我应该根据ValidationResult的内容构建ValidationException的消息。例如,“成员{0}无效:{1}”。

    回答第一个问题: 因为每个验证属性都有自己的
    IsValid
    属性,并返回
    公共验证结果(string errorMessage,IEnumerable MemberName)验证结果,您可以从成员名称列表中获取成员名称。因此,属性返回的每个验证都是有效的。您在实体的属性上应用的实体具有验证不是一个好主意

    回答第二个问题: 您可以创建自己的
    ValidationAttribute
    列表来验证实体:

    var validationResults = new List<ValidationResult>();
    var validationAttributes = new List<ValidationAttribute>();
    validationAttributes.Add(new CustomValidationAttribute(typeof(ClaimValidator), "ValidateClaim"));
    var result = Validator.TryValidateValue(claimObject,
                                            new ValidationContext(claimObject, null, null),
                                            validationResults,
                                            validationAttributes);
    

    我的情况与您类似,我想您已经实施了一个可扩展的体面解决方案?