.Net Core中如何实现基于条件判断的Range数据注解校验
结论
原生Range数据注解不支持你提到的动态判断写法,也无法实现你写的if逻辑切换注解的效果。C#中的特性(Attribute)属于编译期确定的元数据,所有传入的参数必须是编译期常量,无法在运行时根据其他字段的值动态修改特性配置。
可行实现方案
方案1:自定义校验特性(推荐,复用性强)
你可以继承ValidationAttribute自定义符合需求的动态范围校验特性,用法和原生数据注解基本一致,适合需要在多个模型中复用该规则的场景。
自定义特性代码示例:
public class RangeByTypeAttribute : ValidationAttribute { private readonly double _fixedMin = 0.5; private readonly double _maxWhenTypeChecked = 20; private readonly double _maxWhenTypeUnchecked = 100; private readonly string _typeFieldName; public RangeByTypeAttribute(string typeFieldName) { _typeFieldName = typeFieldName; } protected override ValidationResult IsValid(object value, ValidationContext validationContext) { // 获取关联的Type复选框值 var typeProperty = validationContext.ObjectType.GetProperty(_typeFieldName); if (typeProperty == null || typeProperty.PropertyType != typeof(bool)) { return new ValidationResult($"关联字段{_typeFieldName}不存在或不是布尔类型"); } bool isTypeChecked = (bool)typeProperty.GetValue(validationContext.ObjectInstance); // 校验输入值格式 if (value is not double inputValue) { return new ValidationResult("待校验字段必须为数值类型"); } // 执行范围校验 if (inputValue < _fixedMin) { return new ValidationResult($"数值不能小于{_fixedMin}"); } double currentMax = isTypeChecked ? _maxWhenTypeChecked : _maxWhenTypeUnchecked; if (inputValue > currentMax) { ErrorMessage = isTypeChecked ? "<20" : "<100"; return new ValidationResult(ErrorMessage); } return ValidationResult.Success; } }
在模型中使用:
public class YourRequestModel { // 对应你页面上的Type复选框 public bool Type { get; set; } [RangeByType(nameof(Type))] public double TargetNum { get; set; } }
如果需要同时支持客户端校验,额外实现IClientModelValidator接口添加客户端验证规则即可。
方案2:实现IValidatableObject接口(适合单模型用的复杂校验)
如果该规则只在当前一个模型中使用,不需要复用,可以直接让模型类实现IValidatableObject接口,直接在模型内部编写校验逻辑,不需要单独定义特性类:
public class YourRequestModel : IValidatableObject { public bool Type { get; set; } public double TargetNum { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { if (TargetNum < 0.5) { yield return new ValidationResult("数值不能小于0.5", new[] { nameof(TargetNum) }); } double max = Type ? 20 : 100; if (TargetNum > max) { string errorMsg = Type ? "<20" : "<100"; yield return new ValidationResult(errorMsg, new[] { nameof(TargetNum) }); } } }
内容的提问来源于stack exchange,提问作者Micky
相关产品推荐
相关产品推荐

