与ASP.NET MVC 3 client-side validation with parameters
相关我构建了一个自定义验证属性,允许我检查相对日期(例如,模型值小于或等于今天)。
验证程序正确实现了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;
});
日期验证已被破坏。要求似乎工作正常。但每当我在此字段中键入任何值时,Date类型验证器将触发并生成消息“字段日期必须是日期”。输入的任何日期值都会发生这种情况。
我的验证规则有什么问题,它(1)不起作用,(2)破坏日期类型验证?
答案 0 :(得分:2)
与大多数调试经验一样,症状与正在发生的事情无关。必需和日期类型验证都是成功的。失败是在适配器中引起的。
使用浏览器脚本调试程序我发现它在这一行上失败了:
// jQuery.validate.js, line 530
result = $.validator.methods[method].call( this, val, element, rule.parameters );
这是jQuery循环规则及其相关的验证方法的地方。
method
则等于"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垃圾到验证方法的唯一方法。
希望这有助于某人或节省时间。