MVC5自定义数据注解问题:GetCustomAttributes未找到及组字段必填验证
解决MVC5中"组内至少一个字段必填"自定义验证注解及
GetCustomAttributes找不到的问题 我来帮你搞定这个需求和遇到的问题,结合MVC5的特性,咱们一步步来实现:
一、先实现RequireAtLeastOneOfGroupAttribute自定义验证注解
你的需求是让同一组的字段至少有一个不为空,这个自定义注解需要继承ValidationAttribute,如果需要客户端验证的话,还得实现IClientValidatable接口。
1. 完整的注解类代码
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Reflection; using System.Web.Mvc; public class RequireAtLeastOneOfGroupAttribute : ValidationAttribute, IClientValidatable { private readonly string _groupName; public RequireAtLeastOneOfGroupAttribute(string groupName) { _groupName = groupName; ErrorMessage = $"请至少填写「{_groupName}」组中的一个字段"; } protected override ValidationResult IsValid(object value, ValidationContext validationContext) { // 获取当前模型的所有属性信息 var modelProperties = validationContext.ObjectType.GetProperties(); // 遍历所有属性,找到同组的字段 foreach (var prop in modelProperties) { // 这里就是你用到GetCustomAttributes的地方,注意要引用System.Reflection var attributes = prop.GetCustomAttributes(typeof(RequireAtLeastOneOfGroupAttribute), false); if (attributes.Length == 0) continue; var groupAttr = (RequireAtLeastOneOfGroupAttribute)attributes[0]; if (groupAttr._groupName != _groupName) continue; // 获取该属性的实际值 var propValue = prop.GetValue(validationContext.ObjectInstance); // 判断值是否有效:非null,或者值类型的Nullable有实际值 var hasValidValue = propValue != null && !(propValue is ValueType vt && vt.Equals(Activator.CreateInstance(vt.GetType()))); if (hasValidValue) { // 只要有一个同组字段有值,验证通过 return ValidationResult.Success; } } // 所有同组字段都为空,返回错误信息 return new ValidationResult(ErrorMessage); } // 可选:添加客户端验证支持,让验证在前端也能生效 public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) { var validationRule = new ModelClientValidationRule { ValidationType = "requireatleastoneofgroup", ErrorMessage = ErrorMessage }; validationRule.ValidationParameters.Add("groupname", _groupName); yield return validationRule; } }
2. 在模型中应用注解
你的模型可以补全成这样:
public class Document { [RequireAtLeastOneOfGroupAttribute("group1")] public long? IdPersons { get; set; } [RequireAtLeastOneOfGroupAttribute("group1")] public int? IdComp { get; set; } [RequireAtLeastOneOfGroupAttribute("group1")] public string? AlternativeField { get; set; } // 示例同组字段,你可以换成自己的第三个字段 }
二、解决GetCustomAttributes找不到的问题
你遇到的这个报错,大概率是下面几个原因之一,对应解决就行:
1. 缺少必要的命名空间
GetCustomAttributes是System.Reflection命名空间下的方法,一定要在你的注解类顶部添加引用:
using System.Reflection;
没加这个的话,编译器肯定找不到这个方法。
2. 调用对象不对
要确保你是对PropertyInfo类型的对象调用GetCustomAttributes,就像上面示例里那样,先通过validationContext.ObjectType.GetProperties()拿到所有属性的PropertyInfo实例,再对每个实例调用方法。如果是对其他类型(比如Type或者普通对象)调用,自然会报错。
3. 项目目标框架版本过低
MVC5要求最低是.NET Framework 4.5,如果你的项目目标框架低于这个版本,可能会缺失部分反射API。检查方式:右键项目 → 属性 → 应用程序 → 目标框架,确认是4.5及以上版本。
4. VS编译缓存问题
有时候VS的缓存会搞出奇怪的错误,试试这几步:
- 清理项目(菜单 → 项目 → 清理)
- 重建整个解决方案(菜单 → 生成 → 重建解决方案)
- 关闭VS重新打开,再编译一次
三、可选:添加客户端验证脚本
如果想要前端也能触发这个验证,需要在页面里加一段自定义验证脚本,放在jquery.validate.js和jquery.validate.unobtrusive.js之后:
// 自定义验证方法 $.validator.addMethod("requireatleastoneofgroup", function (value, element, params) { var groupName = params; var hasValidField = false; // 找到所有同组的输入元素 $("input[data-val-requireatleastoneofgroup-groupname='" + groupName + "']").each(function () { var inputVal = $(this).val(); if (inputVal && inputVal.trim() !== "") { hasValidField = true; return false; // 找到一个有效字段就停止遍历 } }); return hasValidField; }); // 适配Unobtrusive验证 $.validator.unobtrusive.adapters.add("requireatleastoneofgroup", ["groupname"], function (options) { options.rules["requireatleastoneofgroup"] = options.params.groupname; options.messages["requireatleastoneofgroup"] = options.message; });
内容的提问来源于stack exchange,提问作者Geo
相关产品推荐
相关产品推荐

