使用数据注解验证嵌套模型无效,如何让TryValidateObject验证内部模型?
如何让TryValidateObject递归验证嵌套模型
你遇到的问题很典型——默认情况下Validator.TryValidateObject并不会自动递归验证嵌套的复杂类型属性,这就是为什么Card类里的Cv2字段超长错误没被检测到的原因。不过别担心,我们有几种方法可以解决这个问题:
原因分析
TryValidateObject的默认行为只会校验当前对象的直接属性(比如CardPayment里的Description),对于像CardDetail这种嵌套的自定义类对象,它不会自动深入去验证其内部的[Required]、[MaxLength]这些注解。
解决方案1:手动验证嵌套对象
最简单的方式就是在验证完主对象后,手动对嵌套的CardDetail调用验证方法,并将结果合并到总验证结果中:
var context = new ValidationContext(cardPayment); var results = new List<ValidationResult>(); // 先验证CardPayment主对象 var isMainValid = Validator.TryValidateObject(cardPayment, context, results, true); // 单独验证嵌套的Card对象(注意先判断是否为null,避免空引用) if (cardPayment.CardDetail != null) { var cardValidationContext = new ValidationContext(cardPayment.CardDetail); var cardValidationResults = new List<ValidationResult>(); var isCardValid = Validator.TryValidateObject(cardPayment.CardDetail, cardValidationContext, cardValidationResults, true); // 把Card的验证错误合并到总结果里 results.AddRange(cardValidationResults); } // 最终判断所有验证是否通过 var isAllValid = isMainValid && !results.Any();
解决方案2:编写通用递归验证方法
如果你的项目里有很多嵌套模型需要验证,写一个通用的递归验证方法会更高效,不用每次都手动处理每个嵌套对象:
public static class ValidatorExtensions { public static bool TryValidateObjectRecursive<T>(T obj, List<ValidationResult> validationResults) { if (obj == null) throw new ArgumentNullException(nameof(obj)); var context = new ValidationContext(obj); var isValid = Validator.TryValidateObject(obj, context, validationResults, true); // 遍历当前对象的所有属性,递归验证复杂类型(排除string,因为string是特殊的引用类型) foreach (var property in obj.GetType().GetProperties()) { if (property.PropertyType.IsClass && property.PropertyType != typeof(string)) { var nestedObject = property.GetValue(obj); if (nestedObject != null) { isValid &= TryValidateObjectRecursive(nestedObject, validationResults); } } } return isValid; } }
然后调用这个扩展方法就可以一键验证所有嵌套层级:
var results = new List<ValidationResult>(); var isValid = ValidatorExtensions.TryValidateObjectRecursive(cardPayment, results);
额外说明
如果是在ASP.NET Core项目中使用模型绑定(比如接口参数自动绑定),框架默认会自动递归验证所有嵌套模型的注解,不需要手动处理。只有当你像这样手动调用Validator.TryValidateObject时,才需要自己处理递归逻辑。
内容的提问来源于stack exchange,提问作者Neil Gilbert
相关产品推荐
相关产品推荐

