0

涉及:带有参数的 ASP.NET MVC 3 客户端验证

我构建了一个自定义验证属性,允许我检查相对日期(例如模型值小于或等于今天)。

验证器正确实现了该GetClientValidationRules方法,并且视图中发出的 HTML5对我来说看起来是正确的:

<div class="editor-label">
    <label for="Date">Date</label>
</div>
<div class="editor-field">
    <input class="text-box single-line" data-val="true" data-val-date="The field Date must be a date." data-val-relativedate="Date must be less than or equal to 12/04/2012" data-val-relativedate-referencedate="12/04/2012 00:00:00" data-val-relativedate-relativityoperator="lessThanOrEqual" data-val-required="The Date field is required." id="Date" name="Date" type="date" value="" />
    <span class="field-validation-valid" data-valmsg-for="Date" data-valmsg-replace="true"></span>
</div>

下一步是定义一个自定义的jQuery Unobtrusive Validator适配器和方法:

// Validation Method: Relative Date
// Note: method name value does NOT need to match the HTML5 metadata built by the server model annotation attribute.
$.validator.addMethod("validateRelativeDate", function (value, element, params) {
    // "element" is the actual HTML element we are validating, and is unneeded here.
    // "value" is the value of the HTML element
    var toValidate = DateUtilities.convert(value);
    // "params" is a JSON collection of those values provided by the adapter.
    var referenceDate = params["referencedate"];
    var relativityOperator = params["relativityoperator"];

    if (relativityOperator != "lessThan" && relativityOperator != "lessThanOrEqual" || relativityOperator != "greaterThan" && relativityOperator != "greaterThanOrEqual")
        return false; // "Invalid relativity operator (ex. '<', '<=', '>', or '>=').");

    var toReference = referenceDate == null ? new Date() : referenceDate;

    var relativity = DateUtilities.compare(toValidate, toReference);

    switch(relativityOperator) {
        case "lessThan":
            if (relativity >= 0) return false; //"Date must be lesser than " + toReference);
        break;
        case "lessThanOrEqual":
            if (relativity > 0) return false; //"Date must be less than or equal to " + toReference);
        break;
        case "greaterThan":
            if (relativity <= 0) return false; //"Date must be greater than " + toReference);
        break;
        case "greaterThanOrEqual":
            if (relativity < 0) return false; //"Date must be greater than or equal to " + toReference);
        break;
    }

    return true;

});

// note: adapter name must match HTML metadata built by the server model annotation attribute
$.validator.unobtrusive.adapters.add("relativedate", ["referencedate", "relativityoperator"], function (options) {
    options.rules["relativedate"] = options.params;
    options.messages["relativedate"] = options.message;
});

症状

日期验证已损坏。必需的似乎工作正常。但是,每当我在此字段中键入任何值时,日期类型验证器都会触发并生成消息“日期字段必须是日期”。输入的任何日期值都会发生这种情况。

问题

我的验证规则有什么问题,它 (1) 不起作用,并且 (2) 破坏了 Date 类型验证?

4

1 回答 1

2

与大多数调试经验一样,症状与正在发生的事情无关。必需和日期类型验证均成功。故障是在适配器中引起的。

解释

使用浏览器脚本调试器我发现它在这一行失败:

// jQuery.validate.js, line 530
result = $.validator.methods[method].call( this, val, element, rule.parameters );

这是 jQuery 循环通过规则及其相关方法进行验证的地方。

methodthen 等于"relativedate"(在 HTML5 中吐出的元数据值),因此该call属性引发了异常。我以不同的方式命名了我的方法$.validator.addMethod("validateRelativeDate", /*...*/),并且文档说它不必匹配这个元数据值......那么为什么会发生这种情况?

是适配器。我知道适配器名称必须与 HTML5 元数据相同,这是两者之间的紧密耦合 -"relativedate"如下所示。

// 注意:适配器名称必须匹配服务器模型注释属性构建的 HTML 元数据 $.validator.unobtrusive.adapters.add("relativedate", ["referencedate", "relativityoperator"], function (options) { options.rules[ "relativedate"] = options.params; options.messages["relativedate"] = options.message; });

rules为和添加数组值的两行messages是罪魁祸首。显然,这些值需要是用于验证的方法的名称,而不是适配器/元数据的名称。

解决方案

更改这两行以匹配验证方法名称,解决了所有问题:

options.rules["validateRelativeDate"] = options.params;
options.messages["validateRelativeDate"] = options.message;

借口,借口……

我研究的所有示例,甚至我引用的示例,所有这些值都是相等的,因此从未讨论过这个细节。但最终这意味着我是一个有点缺乏智慧的程序员,没有意识到这是它使 HTML5 废话“适应”验证方法的唯一方法。

希望这可以帮助某人或节省他们的时间。

于 2012-12-04T20:44:45.180 回答