Validator.TryValidateObject() 未验证子对象

问题描述 投票:0回答:1

我使用下面的代码显式验证我的模型,它可以很好地验证父对象,但无法验证子对象。对此有什么建议吗?

if (!Validator.TryValidateObject(entity, context, errorResults, true))
{
    
}
c# asp.net-core validation asp.net-core-webapi
1个回答
0
投票

尝试递归地验证对象:

        public static (bool isValid, ValidationResult[] errors) Validate(object input)
        {
            var context = new ValidationContext(input);
            var results = new List<ValidationResult>();

            // Validate the current object
            bool isValid = Validator.TryValidateObject(input, context, results, true);

            // Use reflection to get properties
            var properties = input.GetType().GetProperties()
                .Where(prop => prop.CanRead
                    && prop.PropertyType.IsClass
                    && prop.PropertyType != typeof(string));

            // Recursively validate nested objects
            foreach (var prop in properties)
            {
                var value = prop.GetValue(input);
                if (value != null)
                {
                    var (nestedIsValid, nestedErrors) = Validate(value);
                    isValid &= nestedIsValid;
                    results.AddRange(nestedErrors);
                }
            }

            return (isValid, results.ToArray());
        }

这是一个完整的示例,您可以直接运行它:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;

namespace LearnModelValidate
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var widget = new Widget
            {
                Price = 1557,
                Name = "test",
                Password = "Invalidpassword",
                SubWidget = new Widget
                {
                    Id = 1,
                    Name = "Sub widget",
                    Price = 100,
                    Password = "Invalid password"
                }
            };

            var (isValid, errors) = Validate(widget);

            Console.WriteLine($"Is valid: {isValid}");

            foreach (var error in errors)
            {
                Console.WriteLine(error.ErrorMessage);
            }
        }

        public static (bool isValid, ValidationResult[] errors) Validate(object input)
        {
            var context = new ValidationContext(input);
            var results = new List<ValidationResult>();

            // Validate the current object
            bool isValid = Validator.TryValidateObject(input, context, results, true);

            // Use reflection to get properties
            var properties = input.GetType().GetProperties()
                .Where(prop => prop.CanRead
                    && prop.PropertyType.IsClass
                    && prop.PropertyType != typeof(string));

            // Recursively validate nested objects
            foreach (var prop in properties)
            {
                var value = prop.GetValue(input);
                if (value != null)
                {
                    var (nestedIsValid, nestedErrors) = Validate(value);
                    isValid &= nestedIsValid;
                    results.AddRange(nestedErrors);
                }
            }

            return (isValid, results.ToArray());
        }
    }

    public class Widget
    {
        [Required(ErrorMessage = "The {0} is required!")]
        public int? Id { get; set; }

        [Required]
        [MinLength(10, ErrorMessage = "The {0} requires min length: {1}")]
        public string Name { get; set; }

        [Range(1, 100)]
        public decimal Price { get; set; }

        [NoSpace]
        public string Password { get; set; }

        public Widget SubWidget { get; set; }
    }

    public class NoSpace : ValidationAttribute
    {
        public override bool IsValid(object value)
        {
            if (value is string val)
            {
                return !val.Contains(" ") && !val.Contains("\r") && !val.Contains("\n");
            }
            return false;
        }

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if (IsValid(value))
            {
                return ValidationResult.Success;
            }
            else
            {
                return new ValidationResult($"The {validationContext.DisplayName} can not contain space!");
            }
        }
    }
}

希望你能得到结果:

Is valid: False
The Id is required!
The Name requires min length: 10
The field Price must be between 1 and 100.
The Password can not contain space!
© www.soinside.com 2019 - 2024. All rights reserved.