You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core MVC自定义RequiredIf验证不显示错误且表单仍提交

ASP.NET Core MVC RequiredIf自定义验证客户端不生效问题修复

问题概述

基于ASP.NET Core MVC模型验证实现了RequiredIf自定义验证属性,需求是当指定属性等于特定值时,标记的属性为必填项。调试时服务端验证逻辑正常,但UI不显示错误提示,表单仍能提交。

问题根源

  1. 客户端验证参数缺失:自定义属性的AddValidation方法仅添加了基础验证标记,未传递依赖属性名和目标值,客户端脚本无法获取验证所需的判断条件。
  2. 未注册jQuery验证规则:jQuery Validation默认不识别requiredIf自定义验证类型,需要手动注册验证方法和unobtrusive适配器。
  3. 服务端逻辑错误:原IsValid方法的判断逻辑不符合需求,错误地在依赖属性匹配时只要当前属性有值就返回成功,未处理依赖属性不匹配时的放行逻辑。

修复步骤

1. 修正自定义验证属性代码

修改RequiredIfAttribute的服务端验证逻辑,并完善客户端验证参数传递:

public class RequiredIfAttribute : ValidationAttribute, IClientModelValidator
{
    private readonly string _propertyName;
    private readonly object _desiredValue;
    private readonly string _errorMessage;

    public RequiredIfAttribute(string propertyName, object desiredValue, string errorMessage)
    {
        _propertyName = propertyName ?? throw new ArgumentNullException(nameof(propertyName));
        _desiredValue = desiredValue;
        _errorMessage = errorMessage ?? throw new ArgumentNullException(nameof(errorMessage));
    }

    protected override ValidationResult IsValid(object value, ValidationContext context)
    {
        var instance = context.ObjectInstance;
        var propertyInfo = instance.GetType().GetProperty(_propertyName);
        if (propertyInfo == null)
        {
            return new ValidationResult($"依赖属性 {_propertyName} 不存在");
        }

        var propertyValue = propertyInfo.GetValue(instance, null);

        // 核心逻辑:依赖属性匹配目标值时,当前属性必须非空;否则无需验证
        if (Equals(propertyValue, _desiredValue))
        {
            if (value == null || (value is string str && string.IsNullOrWhiteSpace(str)))
            {
                return new ValidationResult(GetErrorMessage());
            }
        }

        return ValidationResult.Success;
    }

    public string GetErrorMessage() => _errorMessage;

    public void AddValidation(ClientModelValidationContext context)
    {
        if (context == null)
            throw new ArgumentNullException(nameof(context));

        // 启用客户端验证
        MergeAttribute(context.Attributes, "data-val", "true");
        // 设置错误提示
        MergeAttribute(context.Attributes, "data-val-requiredIf", GetErrorMessage());
        // 传递依赖属性名给客户端
        MergeAttribute(context.Attributes, "data-val-requiredIf-property", _propertyName);
        // 传递目标值给客户端
        MergeAttribute(context.Attributes, "data-val-requiredIf-value", _desiredValue.ToString());
    }

    private static bool MergeAttribute(IDictionary<string, string> attributes, string key, string value)
    {
        if (attributes.ContainsKey(key))
        {
            return false;
        }

        attributes.Add(key, value);
        return true;
    }
}

2. 添加客户端自定义验证脚本

在页面中加载完jQuery、jquery.validate和jquery.validate.unobtrusive之后,添加以下脚本,注册自定义验证规则和适配器:

<script>
    // 注册requiredIf验证方法
    $.validator.addMethod("requiredIf", function (value, element, params) {
        const targetElement = $('[name="' + params.property + '"]');
        if (!targetElement.length) return true;

        const currentTargetValue = targetElement.val();
        // 依赖属性匹配目标值时,当前输入框必须非空
        if (currentTargetValue === params.value) {
            return $.trim(value) !== '';
        }
        // 不匹配时直接通过验证
        return true;
    });

    // 注册unobtrusive适配器,关联data属性和验证规则
    $.validator.unobtrusive.adapters.add("requiredIf", ["property", "value"], function (options) {
        options.rules["requiredIf"] = {
            property: options.params.property,
            value: options.params.value
        };
        options.messages["requiredIf"] = options.message;
    });
</script>

3. 验证依赖属性的客户端元素

确保依赖属性(如TransactionType)的客户端元素name属性与视图模型中的属性名一致,比如使用@Html.DropDownListFor(m => m.TransactionType, ...)会自动生成正确的name属性,保证客户端脚本能正确获取其值。

验证效果

修改完成后,当TransactionType等于指定值时,Creditor输入框为空会触发客户端验证,显示错误提示并阻止表单提交;服务端验证逻辑也会正确拦截不符合条件的请求。

内容的提问来源于stack exchange,提问作者Gino Mortillero

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 22:48:35