ASP.NET MVC 自定义多字段验证

2023-11-21

我正在开发一个 ASP.NET MVC 5.2.3 自定义数据注释,用于在 Visual Studio 2015 中进行验证。它需要采用任意数量的字段,并确保如果一个字段有值,则它们都必须有值;如果它们都是空/空白,那就应该没问题。

一些例子有帮助:

  • ASP.NET MVC使用IClientValidatable实现自定义验证器
  • 多个字段的 MVC 表单验证
  • http://www.macaalay.com/2014/02/24/unobtrusive-client-and-server-side-age-validation-in-mvc-using-custom-data-annotations/

但是,我不确定如何在要验证的字段数量未知的情况下进行客户端验证。

如何使用以下实现将其传递给客户端GetClientValidationRules()的方法IClientValidatable界面?

另外,如何将这个新的数据注释应用到视图模型上的属性?会是这个样子吗?

[MultipleRequired("AppNumber", "UserId", /* more fields */), ErrorMessage = "Something..."]
[DisplayName("App #")]
public int AppNumber { get; set; }

[DisplayName("User ID")]
public int UserId { get; set; }

这是我所能得到的MultipleRequiredAttribute自定义数据注释类:

public class MultipleRequiredAttribute : ValidationAttribute, IClientValidatable
{
    private readonly string[] _fields;
    public MultipleRequiredAttribute(params string[] fields)
    {
        _fields = fields;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        // If any field has value, then all must have value
        var anyHasValue = _fields.Any(f => !string.IsNullOrEmpty(f));

        if (!anyHasValue) return null;

        foreach (var field in _fields)
        {
            var property = validationContext.ObjectType.GetProperty(field);
            if (property == null)
                return new ValidationResult($"Property '{field}' is undefined.");

            var fieldValue = property.GetValue(validationContext.ObjectInstance, null);

            if (string.IsNullOrEmpty(fieldValue?.ToString()))
                return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
        }

        return null;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        yield return new ModelClientValidationRule
        {
            ErrorMessage = ErrorMessage,
            ValidationType = "multiplerequired"
        };
    }
}

谢谢。


为了获得客户端验证,您需要传递“其他属性”的值ModelClientValidationRule通过使用.Add()规则方法ValidationParameters属性,然后编写客户端脚本以将规则添加到$.validator.

但首先,您的属性还需要解决一些其他问题。首先你应该执行你的foreach仅当您应用该属性的属性值为null。其次,返回一个ValidationResult如果“其他属性”之一不存在,对用户来说会令人困惑且毫无意义,您应该忽略它。

属性代码应该是(注意我更改了属性的名称)

public class RequiredIfAnyAttribute : ValidationAttribute, IClientValidatable
{
    private readonly string[] _otherProperties;
    private const string _DefaultErrorMessage = "The {0} field is required";

    public RequiredIfAnyAttribute(params string[] otherProperties)
    {
        if (otherProperties.Length == 0) // would not make sense
        {
            throw new ArgumentException("At least one other property name must be provided");
        }
        _otherProperties = otherProperties;
        ErrorMessage = _DefaultErrorMessage;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value == null) // no point checking if it has a value
        {
            foreach (string property in _otherProperties)
            {
                var propertyName = validationContext.ObjectType.GetProperty(property);
                if (propertyName == null)
                {
                    continue;
                }
                var propertyValue = propertyName.GetValue(validationContext.ObjectInstance, null);
                if (propertyValue != null)
                {
                    return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
                }
            }
        }
        return ValidationResult.Success;
    }
    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientValidationRule
        {
            ValidationType = "requiredifany",
            ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
        };
        / pass a comma separated list of the other propeties
        rule.ValidationParameters.Add("otherproperties", string.Join(",", _otherProperties));
        yield return rule;
    }
}

然后脚本将是

sandtrapValidation = {
    getDependentElement: function (validationElement, dependentProperty) {
        var dependentElement = $('#' + dependentProperty);
        if (dependentElement.length === 1) {
            return dependentElement;
        }
        var name = validationElement.name;
        var index = name.lastIndexOf(".") + 1;
        var id = (name.substr(0, index) + dependentProperty).replace(/[\.\[\]]/g, "_");
        dependentElement = $('#' + id);
        if (dependentElement.length === 1) {
            return dependentElement;
        }
        // Try using the name attribute
        name = (name.substr(0, index) + dependentProperty);
        dependentElement = $('[name="' + name + '"]');
        if (dependentElement.length > 0) {
            return dependentElement.first();
        }
        return null;
    }
}

$.validator.unobtrusive.adapters.add("requiredifany", ["otherproperties"], function (options) {
    var element = options.element;
    var otherNames = options.params.otherproperties.split(',');
    var otherProperties = [];
    $.each(otherNames, function (index, item) {
        otherProperties.push(sandtrapValidation.getDependentElement(element, item))
    });
    options.rules['requiredifany'] = {
        otherproperties: otherProperties
    };
    options.messages['requiredifany'] = options.message;
});

$.validator.addMethod("requiredifany", function (value, element, params) {
    if ($(element).val() != '') {
        // The element has a value so its OK
        return true;
    }
    var isValid = true;
    $.each(params.otherproperties, function (index, item) {
        if ($(this).val() != '') {
            isValid = false;
        }
    });
    return isValid;
});
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ASP.NET MVC 自定义多字段验证 的相关文章

  • CSharpRepl emacs 集成?

    我碰巧知道莫诺CSharpRepl http www mono project com CsharpRepl 是否有 emacs csharp 模式使用它在一个窗口中运行 REPL 并像 python 模式一样在另一个窗口中编译 运行 C
  • 在开关中使用“goto”?

    我看到了一个建议的编码标准 内容如下Never use goto unless in a switch statement fall through 我不跟 这个 例外 案例到底是什么样的 这证明了goto 此构造在 C 中是非法的 swi
  • 如何制作可启动程序?

    所以 这个问题可能看起来很奇怪 但假设我编译了 int main void int x 3 int y 4 int z x y 是否可以让CPU这样运行 如何 例如 这允许我写入监视器吗 如果我没记错的话 内存中有些地方可以写入要显示的内容
  • C# 开源 NMEA 解析器 [已关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找 C 开源 NMEA 解析器 嗯 我自己也不熟悉 但是一些快速搜索显示了一个代码项目 htt
  • 将表(行)与 OpenXML SDK 2.5 保持在一起

    我想在 Word 文档中生成多个表 每行 2 行 但我想将这两行保留在一起 如果可能的话 new KeepNext 第一行不起作用 new KeepNext 第一行的最后一段不起作用 new CantSplit 放在桌子上不起作用 在所有情
  • 增强精神、递归和堆栈溢出

    为什么下面的代码在运行时崩溃 它会给出堆栈溢出错误 include
  • 如何对 NServiceBus.Configure.WithWeb() 进行单元测试?

    我正在构建一个 WCF 服务 该服务接收外部 IP 上的请求并将其转换为通过 NServiceBus 发送的消息 我的单元测试之一调用Global Application Start 它执行应用程序的配置 然后尝试将 Web 服务解析为 验
  • 如何在三个 IEnumerable 上使用 Zip [重复]

    这个问题在这里已经有答案了 可能的重复 使用 Linq 从 3 个集合创建项目 https stackoverflow com questions 5284315 create items from 3 collections using
  • C#6 中的长字符串插值行

    我发现 虽然字符串插值在应用于现有代码库的字符串 Format 调用时非常好 但考虑到通常首选的列限制 字符串对于单行来说很快就会变得太长 特别是当被插值的表达式很复杂时 使用格式字符串 您将获得一个可以拆分为多行的变量列表 var str
  • 析构函数中的异步操作

    尝试在类析构函数中运行异步操作失败 这是代码 public class Executor public static void Main var c1 new Class1 c1 DoSomething public class Class
  • 搜索实体的所有字段

    我正在尝试在客户数据库上实现 多功能框 类型的搜索 其中单个查询应尝试匹配客户的任何属性 这是一些示例数据来说明我想要实现的目标 FirstName LastName PhoneNumber ZipCode Mary Jane 12345
  • 您如何填充/验证您的 ViewModel?

    我很好奇人们构建 ViewModel 的各种方式以及他们为什么选择该方法 我在这里可以想到几种方法 1 注入存储库 控制器加载模型并映射到 ViewModel 这里 ViewModel 构造函数可以采用各种集合来进行内部设置 在选择列表中
  • 从浏览器访问本地文件?

    您好 我想从浏览器访问系统的本地文件 由于涉及大量安全检查 是否可以通过某种方式实现这一目标 或使用 ActiveX 或 Java Applet 的任何其他工作环境 请帮帮我 要通过浏览器访问本地文件 您可以使用签名的 Java Apple
  • .NET 4 的条件编译[重复]

    这个问题在这里已经有答案了 可能的重复 条件编译和框架目标 https stackoverflow com questions 2923210 c sharp conditional compilation and framework ta
  • 选择查询不适用于使用Parameters.AddWithValue 的参数

    C 中的以下查询不起作用 但我看不出问题所在 string Getquery select from user tbl where emp id emp id and birthdate birthdate cmdR Parameters
  • 需要提取字符串中点后的最后一个数字,如“7.8.9.1.5.1.100”

    我需要提取 C 字符串中最后一个点后面的最后一个数字 例如 7 8 9 1 5 1 100 并将其存储在整数中 Added 该字符串也可以是 7 8 9 1 5 1 1 或 7 8 9 1 5 1 0 我还想验证它在最后一个点之前恰好是 7
  • LINQ 中的“from..where”或“FirstOrDefault”

    传统上 当我尝试从数据库中获取用户的数据时 我使用了以下方法 在某种程度上 DbUsers curUser context DbUsers FirstOrDefault x gt x u LoginName id string name c
  • 使用 using 声明时,非限定名称查找如何工作?

    根据 C 标准 这是格式错误还是格式良好 namespace M struct i namespace N static int i 1 using M i using N i int main sizeof i Clang 拒绝它 GCC
  • DataContractSerializer 事件/委托字段问题

    在我的 WPF 应用程序中 我正在使用DataContractSerializer序列化对象 我发现它无法序列化具有事件或委托声明的类型 考虑以下失败的代码 Serializable public abstract class BaseCl
  • 如何使用placement new重新初始化该字段?

    我的课程包含字段 private OrderUpdate curOrderUpdate 我一遍又一遍地使用它 经常需要重新初始化 for int i 0 i lt entries size i auto entry entries i ne

随机推荐

  • 如何从 LLVM 中的 CallInst 获取间接调用的函数名称

    Function fun call gt getCalledFunction getCalledFunction 如果是间接调用则返回 null 如何获取函数的名称或指针的名称 我发现Stack Overflow中与此问题相关的所有问题都谈
  • 在gradle中使用目标sdk版本23时,ZBAR条码扫描库不工作

    我在我的项目中使用 zbar 扫描仪库 更新到 sdk 23 后 棉花糖扫描仪无法工作 以下是 gradle 文件 扫描仪正在工作 如果我将 targetSdkVersion 设置为 23 以外的任何值 以下是gradle文件 apply
  • 按下按键后防止光标隐藏在浏览器中

    我知道在大多数浏览器 最新一代 中 当您输入 A 或空格等任何键时 鼠标光标会隐藏 这是为了让用户看到他输入的内容 一旦您将鼠标移动一个像素 光标就会恢复可见 现在问题来了 这种情况在浏览器中随处可见 即使我关注的是 div 等非输入元素
  • JavaFX 中需要使用 gradle 来定位

    我越来越 java lang NullPointerException 位置是必需的 当我使用 gradle 和 javafx 插件组装后运行我的程序时 如果我从 IntelliJ Idea 运行它 一切都很好 Java源文件和 fxml位
  • Haskell hoogle 通过 cabal 安装,但未找到 hoogle 命令

    hoogle hoogle 4 2 36 安装过程看起来很成功 除了在命令行输入 hoogle 时 它会抱怨 hoogle 找不到命令 在两台机器上尝试过这个 都运行 MAC OS X Yosemite 它们以完全相同的方式失败 有什么建议
  • 非常大的集合的 SQLAlchemy 集合成员资格

    我的 SQL 查询可以非常简单地写为 result session query Table filter Table my key in key set The my key整数列已建立索引 主键 但是key set确实可能非常大 有数千万
  • Linux (Ubuntu 11.10) 中的 Matlab 在绘图中不显示 Unicode(希伯来语)

    我尝试在 Ubuntu 上的 Matlab 图形图中使用希伯来字符 但没有成功 我试过 text 0 6 0 5 fontname times new roman rotation 180 fontsize 50 color r and t
  • 验证器中的 HTML 开始标记有误?

    我正在尝试验证此 HTML 文档http validator w3 org validate by input但我收到以下错误 第 3 行 第 47 列 杂散开始标记 html 第 4 行 第 47 列 杂散开始标记 html 第 5 行
  • 简短的 IF - ELSE 语句

    我试图使我的代码更具可读性 因此我决定使用一些简短的 IF 语句 这是我的代码 它不起作用 不是声明 jXPanel6 isVisible jXPanel6 setVisible true jXPanel6 setVisible false
  • ElasticSearch:搜索嵌套数组中的字段

    我对 ES 相当陌生 正在将它用于我的一个新项目 首先 我有一个客户的简单映射 其中包含名字和姓氏以及支付信息对象列表 如果我在 SQL 中执行此操作 它将类似于客户表和具有一对多关系的付款信息表 这是我正在尝试做的一个简单示例 https
  • 如何序列化对象以通过网络发送

    我正在尝试仅使用 STL 序列化对象以通过套接字通过网络发送 我没有找到一种方法来保持对象的结构在其他主机中反序列化 我尝试转换为string to char 我花了很长时间在互联网上搜索教程 但到目前为止我什么也没找到 有没有办法只用ST
  • LDA 忽略 n_components?

    当我尝试使用 Scikit Learn 的 LDA 时 它只给我一个组件 尽管我要求更多 gt gt gt from sklearn lda import LDA gt gt gt x np random randn 5 5 gt gt g
  • Python C 扩展 - 为什么使用关键字参数的方法强制转换为 PyCFunction

    我正在学习 Python C 扩展 并且很困惑为什么使用关键字参数的方法必须转换为 PyCFunctions 我对 PyCFunction 的理解是它需要两个指向 PyObjects 的指针并返回一个指向 PyObject 的指针 例如 P
  • 记忆处理程序[重复]

    这个问题在这里已经有答案了 创建一个像下面这样可以为您处理记忆过程的类是 好习惯 吗 记忆化的好处是如此之大 在某些情况下 比如这个 它从我的计算机上的 501003 次函数调用减少到 1507 次函数调用 并将 CPU 时间从 1 409
  • iOS 正则表达式 阿拉伯语

    我来自这个帖子 正则表达式 仅限阿拉伯字符和数字 如何将阿拉伯语单词与正则表达式匹配 没有回答我的问题 我试过了 p Arabic 并收到 解析错误 原因 无效的转义序列 pos 3 p 阿拉伯语 我也尝试过 u0621 u064A s 解
  • 无法读取配置文件,因为它超出了最大文件大小

    无法读取配置文件 因为它超出了最大文件大小 我收到上述错误是因为我的 rewritemap config 文件大小超过 250KB 带有 IIS 7 5 的 Windows 2008 R2 SP1 服务器 如果您有权访问注册表并且确实需要大
  • ionic/cordova 中的 Firebase 离线功能

    有人在 Android iOS 中使用 Firebase 实现了具有完整离线功能的本机应用程序吗 可以通过使用本机 Firebase SDK 的插件在 Cordova Ionic 中完成此操作吗 我们正在构建一个在下载和首次启动时具有连接的
  • 将 NLog 与 MEF 结合使用的最佳方式是什么?

    我想知道将 NLog 与托管可扩展性框架 MEF 结合使用的最佳方法是什么 我有一个支持使用 MEF 架构的插件的应用程序 导入和导出等 我想向我的应用程序添加日志记录功能 作为一个日志组件 我想使用 NLog 你会推荐什么 1 为 NLo
  • 确定最后一行的宽度

    我有一个包含多行的标签 lineBreakMode 设置为 UILineBreakModeWordWrap 如何确定最后一行的宽度 从 iOS 7 0 开始 您可以使用此函数来完成此操作 也许您需要根据您的情况稍微调整文本容器 public
  • ASP.NET MVC 自定义多字段验证

    我正在开发一个 ASP NET MVC 5 2 3 自定义数据注释 用于在 Visual Studio 2015 中进行验证 它需要采用任意数量的字段 并确保如果一个字段有值 则它们都必须有值 如果它们都是空 空白 那就应该没问题 一些例子