ASP.NET MVC 3 使用参数的客户端验证

56

接着这篇文章 Perform client side validation for custom attribute,我试图理解如何在客户端脚本中传递附加参数来实现自定义验证。

迄今为止,我了解到要使用 MVC 3 实现自定义验证需要以下步骤:

创建自定义验证属性

基于 ValidationAttribute 并实现 IClientValidatable 接口。我还看到一些例子是从 ModelValidator 派生而来的,它似乎同时实现了 ValidationAttribute 和 IClientValidatable 的功能。所以我第一个困惑的地方是它们之间的区别是什么,或者 ModelValidator 是用于 MVC 2 的但现已过时了?

必须从 GetClientValidationRules() 方法返回 ModelClientValidationRule 的实例,以指定详细信息,例如错误消息、ValidationType(我理解为执行客户端验证的 JavaScript 函数的名称)以及任何可能存在且需要传递到 JavaScript 验证的附加自定义参数。

我认为运行时(不确定其中的哪个部分)然后使用 ModelClientValidationRule 生成标记元素的 HTML 属性,如下:

data-val="true"  (to indicate that the element requires validation)
data-val-[ValidationType]=[ErrorMessage]
data-val-[ValidationType].[ValidationParameters(n).Key]=[ValidationParameters(n).Value]

实现客户端验证逻辑

必须创建一个Javascript函数并使用jQuery.validators.addmethod()将其添加到jQuery.validators中,以便在需要执行时JQuery知道它的存在。类似以下代码:

jQuery.validator.addMethod(
    'greaterThan', 
    function (value, element, params) {
        /.../
       return /* true or false   */ ; 
    },
    ''
); 

我的问题是,'function (value, element, params)' 这个签名是否是处理验证的方法的标准,并且我假设它会在适当的时间被一些 jQuery 功能调用,比如在表单提交之前、元素失去焦点或按键抬起事件发生时。但我不理解如何控制它,也就是说,如何选择适合自定义验证的事件。

实现一个不显眼的适配器

这个适配器将不显眼的属性转换为一些我不是很清楚的东西,但我认为它是一个 jQuery 规则,但我不清楚它是如何工作的。类似于:

jQuery.validator.unobtrusive.adapters.add(
    'futuredate', 
    { },
    function (options) {
        options.rules['greaterThan'] = true;
        options.messages['greaterThan'] = options.message;
    }
); 

我的问题是关于“function (options)”的。这个函数是在“function (value, element, params)”之前被调用的吗?它负责将不显式标记提取到可以被jQuery.Validation理解的数据结构中。从代码示例来看,似乎options是一个包含属性值(例如options.message)和必须映射到jQuery相关属性的对象(例如options.messages['ClientSideValidationFunctionName'])。如果是这样,如何检索并映射自定义参数。

我希望没有增加任何混淆。


1
不显眼的验证意味着在元素上添加HTML属性,例如data-max-value="5",并且位于正文内容之外的JavaScript查找这些属性并执行验证,而不是直接在HTML元素上添加JavaScript。 - Rich
1个回答

70

您可以使用 ValidationParameters 属性向规则添加自定义参数:

public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
    var rule = new ModelClientValidationRule
    {
        ErrorMessage = this.ErrorMessage,
        ValidationType = "futuredate",
    };
    rule.ValidationParameters.Add("param1", "value1");
    rule.ValidationParameters.Add("param2", "value2");
    yield return rule;
}

可以在适配器中使用:

jQuery.validator.unobtrusive.adapters.add(
    'futuredate', 
    [ 'param1', 'param2' ],
    function (options) {
        var param1 = options.params.param1; // shall equal 'value1'
        var param2 = options.params.param2; // shall equal 'value2'
        // TODO: use those custom parameters to define the client rules
    }
);

更新:

根据评论区的请求,以下是如何将这些参数传递给自定义验证规则函数的方法:

jQuery.validator.unobtrusive.adapters.add(
    'futuredate', 
    [ 'param1', 'param2' ],
    function (options) {
        // simply pass the options.params here
        options.rules['greaterThan'] = options.params;
        options.messages['greaterThan'] = options.message;
    }
);

jQuery.validator.addMethod('greaterThan', function (value, element, params) {
    // params here will equal { param1: 'value1', param2: 'value2' }
    return ...
}, '');

1
@ricardo,关于你的第一个问题,ModelValidator允许你实现与IClientValidatable相同的功能,因为它公开了GetClientValidationRules方法。至于你的第二个问题,那是jQuery验证。 - Darin Dimitrov
1
@ricardo,ValidationAttribute作用于您模型的单个属性,而ModelValidator则作用于整个模型。 - Darin Dimitrov
5
ModelValidator方法是从MVC2中引入的,我认为不应该在MVC3项目中继续使用。MVC3的ValidationAttribute/IClientValidatable方法更加简洁,不需要修改global.asax来注册适配器。 - Paul Hiles
1
天啊,这行注释正是我所需要的。我一直在使用MVC 2网站,现在已经更新到了MVC 3。它有一个自定义的“RequiredIf”ValidationAttribute,使用DataAnnotationsModelValidator和所有在这里描述的东西:http://haacked.com/archive/2009/11/19/aspnetmvc2-custom-validation.aspx。我被旧方法和这些新的MVC3方法搞得很困惑。显然它们实现了同样的功能。感谢Microsoft提供的文档(和提示)!*叹气*感谢Darin、Ricardo和The Flower Guy! - kdawg
@DarinDimitrov,请问一下['greaterThan']是什么意思?它是否像'futuredate'这样是一个方法名,还是其他什么东西? - Glory Raj
显示剩余14条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接