我使用下面的代码显式验证我的模型,它可以很好地验证父对象,但无法验证子对象。对此有什么建议吗?
if (!Validator.TryValidateObject(entity, context, errorResults, true))
{
}
尝试递归地验证对象:
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!