如何为Owned类Address的属性设置条件性必填规则
实现Address类的条件性必填验证逻辑
针对你的需求——同一个Address类在Application的不同属性下有不同的必填规则(CorpOffice必填Street/City/State/Zip,Offsite_Facility全可选),可以通过以下两种方式实现,确保Validator.TryValidateObject能捕获缺失的必填属性错误:
方案1:让Application实现IValidatableObject接口
直接在Application类的验证方法中,针对CorpOffice单独做必填字段校验,Offsite_Facility不做强制要求。
修改后的代码
Address类保持原有结构不变,修改Application类:
using System.ComponentModel.DataAnnotations; using System.Collections.Generic; public class Application : IValidatableObject { [Required(ErrorMessage = "公司办公地址不能为空")] public Address CorpOffice { get; set; } public Address Offsite_Facility { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { // 校验CorpOffice的必填字段 if (CorpOffice != null) { if (string.IsNullOrWhiteSpace(CorpOffice.Street)) { yield return new ValidationResult( "公司办公地址的街道不能为空", new[] { $"{nameof(CorpOffice)}.{nameof(CorpOffice.Street)}" }); } if (string.IsNullOrWhiteSpace(CorpOffice.City)) { yield return new ValidationResult( "公司办公地址的城市不能为空", new[] { $"{nameof(CorpOffice)}.{nameof(CorpOffice.City)}" }); } if (CorpOffice.State == null) { yield return new ValidationResult( "公司办公地址的州/省份不能为空", new[] { $"{nameof(CorpOffice)}.{nameof(CorpOffice.State)}" }); } if (!CorpOffice.Zip.HasValue) { yield return new ValidationResult( "公司办公地址的邮编不能为空", new[] { $"{nameof(CorpOffice)}.{nameof(CorpOffice.Zip)}" }); } } // Offsite_Facility 无需强制校验,跳过即可 } }
验证调用示例
// 构造一个CorpOffice缺失必填字段的Application实例 var app = new Application { CorpOffice = new Address() // 仅实例化,未填充必填字段 // Offsite_Facility 可以不赋值 }; var validationResults = new List<ValidationResult>(); var isValid = Validator.TryValidateObject( app, new ValidationContext(app), validationResults, validateAllProperties: true); // 必须设为true,否则不会触发自定义校验 // 输出所有验证错误 foreach (var result in validationResults) { Console.WriteLine($"错误:{result.ErrorMessage},关联字段:{string.Join(", ", result.MemberNames)}"); }
方案2:自定义验证属性
创建一个可复用的RequiredAddressAttribute,标记在需要强制校验的Address属性上(比如CorpOffice),这种方式更灵活,适合多个地方复用同一规则。
自定义验证属性代码
using System.ComponentModel.DataAnnotations; using System.Collections.Generic; public class RequiredAddressAttribute : ValidationAttribute { protected override ValidationResult IsValid(object value, ValidationContext validationContext) { var address = value as Address; if (address == null) { return new ValidationResult("地址不能为空"); } var errorMessages = new List<string>(); if (string.IsNullOrWhiteSpace(address.Street)) errorMessages.Add("街道不能为空"); if (string.IsNullOrWhiteSpace(address.City)) errorMessages.Add("城市不能为空"); if (address.State == null) errorMessages.Add("州/省份不能为空"); if (!address.Zip.HasValue) errorMessages.Add("邮编不能为空"); if (errorMessages.Any()) { return new ValidationResult( $"地址信息不完整:{string.Join(";", errorMessages)}", new[] { validationContext.MemberName }); } return ValidationResult.Success; } }
修改Application类
public class Application { [RequiredAddress(ErrorMessage = "公司办公地址信息不完整")] public Address CorpOffice { get; set; } public Address Offsite_Facility { get; set; } }
验证调用和方案1完全一致,同样能捕获CorpOffice的必填字段缺失错误。
关键注意点
调用Validator.TryValidateObject时,必须设置validateAllProperties: true,否则只会校验顶级的[Required]属性,不会触发自定义验证或IValidatableObject的逻辑。
如果需要实现“Offsite_Facility若赋值则必须填全”的逻辑,只需在方案1的Validate方法中添加判断:当Offsite_Facility不为空时,执行和CorpOffice一样的字段校验即可。
内容的提问来源于stack exchange,提问作者Red_Phoenix
相关产品推荐
相关产品推荐

