ASP.NET MVC 5数据注解验证:能否继承父类[Required]属性?
我来给你捋清楚这个问题:
首先直接给结论:默认情况下,数据注解里的[Required]属性不会自动从父类继承到子类。ASP.NET MVC的默认验证机制只会扫描当前类(以及它的元数据类)上的注解,不会主动去查找父类的验证属性。不过别担心,有几个实用的办法能帮你实现类似“继承”验证规则的效果:
1. 最直接:手动在子类上重复标注[Required]
这是最简单的方案,如果你的子类需要和父类一样的验证规则,直接在子类对应的属性或者类上加上[Required]注解就行。比如如果ReasonViewModel有个子类SpecialReasonViewModel,你直接在子类的相关属性上贴[Required],就能触发同样的验证。
2. 自定义验证属性实现继承逻辑
如果你不想重复写注解,可以自己封装一个支持继承的Required属性。思路是重写RequiredAttribute的验证逻辑,让它检查父类是否存在[Required]注解,如果有就执行验证。示例代码如下:
public class InheritedRequiredAttribute : RequiredAttribute { protected override ValidationResult IsValid(object value, ValidationContext validationContext) { // 获取当前属性的父类定义 var parentType = validationContext.ObjectType.BaseType; var targetProperty = parentType?.GetProperty(validationContext.MemberName); // 如果父类属性有[Required],就执行默认验证逻辑 if (targetProperty != null && Attribute.IsDefined(targetProperty, typeof(RequiredAttribute))) { return base.IsValid(value, validationContext); } return ValidationResult.Success; } }
之后在子类的属性上用[InheritedRequired]代替[Required],就能自动继承父类的验证规则了。
3. 用MetadataType共享验证规则
如果你的父类和子类需要共享大量验证规则,推荐把验证注解抽离到一个单独的元数据类里,然后让父类和子类都通过[MetadataType]特性引用这个元数据类。示例:
// 单独的验证规则类 public class ReasonValidationRules { [Required] public string SelectedReason { get; set; } // 其他验证规则... } // 父类引用元数据 [MetadataType(typeof(ReasonValidationRules))] public class ReasonViewModel { public string SelectedReason { get; set; } // 其他属性... } // 子类同样引用元数据,自动继承所有验证规则 [MetadataType(typeof(ReasonValidationRules))] public class ChildReasonViewModel : ReasonViewModel { // 子类特有的属性... }
这种方式不仅能实现“继承”验证规则,还能让代码更整洁,避免重复注解。
另外补充一句:在你的场景里,TaskViewModel里的Reasons属性加了[Required],这是验证Reasons对象本身不能为null。如果是ReasonViewModel的子类需要继承它内部属性的验证规则,上面的方案就适用;如果是想让TaskViewModel里的Reasons属性不管是父类还是子类实例都触发[Required],那原来的注解就已经生效了,因为它验证的是对象是否为null,和子类无关。
内容的提问来源于stack exchange,提问作者Junior

