我正在MVC5项目中使用FluentValidation,但日期方面没有任何问题。我的目标是让GreaterThanOrEqualTo
客户端验证适用于一些日期字段。我知道当前文档没有将此方法列为受支持的客户端,但是它呈现了正确的jQuery验证数据属性。
在我的模型中,我有一个属性:
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
[Display(Name = "Credit Decision Due Date")]
public DateTime? DueDate { get; set; }
在我看来,我正在使用标准的Razor语法来绘制控制组:
<div class="control-group">
@Html.LabelFor(m => m.DueDate, new { @class = "control-label text-bold" })
@Html.TextBoxFor(m => m.DueDate, "{0:MM/dd/yyyy}", new { @class = "span12 date-picker" })
@Html.ValidationMessageFor(m => m.DueDate)
</div>
在我的验证器中,只有一个简单的规则:
RuleFor(m => m.DueDate).GreaterThanOrEqualTo(DateTime.Today);
注意,我也尝试过InclusiveBetween
(在文档中明确列出为受支持的客户端):
RuleFor(r => r.DueDate).InclusiveBetween(DateTime.Today, DateTime.Today.AddYears(1));
使用GreaterThanOrEqualTo
渲染视图的结果是:
<div class="control-group">
<label class="control-label text-bold" for="DueDate">Credit Decision Due Date <span class="text-error required-asterisk">*</span></label>
<input class="span12 date-picker hasDatepicker" data-val="true" data-val-range="'Credit Decision Due Date' must be greater than or equal to '9/27/2018 12:00:00 AM'." data-val-range-max="" data-val-range-min="09/27/2018 00:00:00" data-val-required="'Credit Decision Due Date' must not be empty." id="DueDate" name="DueDate" type="text" value="">
<span class="field-validation-valid help-block" data-valmsg-for="DueDate" data-valmsg-replace="true"></span>
</div>
到目前为止,我说的一切看起来都不错,除了正在运行客户端的验证工作异常外,几乎就像它将值视为 text 而不是Date
。例如,假阴性:
还有误报:
除了在选择日期后立即强制该字段进行验证之外,我没有在附加到这些字段的jQuery Datepicker中做任何事情:
$('.date-picker').datepicker({
changeMonth: true,
changeYear: true,
onClose: function () {
$(this).valid();
}
});
默认情况下,整个应用程序使用“ en-US”语言环境。所有其他验证都有效。
我正在使用以下库版本:
我知道我可以编写一个自定义验证器,在比较之前将输入和范围值解析为JavaScript Date
对象,但是似乎应该内置一些东西,以使所有内容都将这些字符串识别为日期。
我想念什么?
答案 0 :(得分:2)
问题在于range
中的jquery.validate.js
规则适用于数字值,如果不是数字,则进行字符串比较。
您可以通过添加自己的规则来比较日期来覆盖默认行为。在validate*
脚本之后添加以下脚本,但不要在$(document).ready
$.validator.methods.range = function(value, element, param) {
if ($(element).attr('data-val-date')) {
var min = $(element).attr('data-val-range-min');
var max = $(element).attr('data-val-range-max');
var date = new Date(value).getTime();
var minDate = new Date(min).getTime() || 0;
var maxDate = new Date(max).getTime() || 8640000000000000;
return this.optional(element) || (date >= minDate && date <= maxDate);
}
// use the default method
return this.optional( element ) || ( value >= param[ 0 ] && value <= param[ 1 ] );
};
请注意,您的TextBoxFor()
方法应生成一个data-val-date="The field Credit Decision Due Date must be a date."
属性。我不确定是否只是从显示的结果html中省略了它,还是有其他一些代码省略了它。如果未生成,则需要修改if ($(element).attr('data-val-date')) {
代码行,例如使用类名
if ($(element).hasClass('date-picker')) {
请注意您的
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
如果使用TextBoxFor()
,则不需要属性-仅当使用EditorFor()
时才尊重这些属性,如果您使用EditorFor()
,则格式字符串应为ISO格式-即The specified value does not conform to the required format yyyy-MM-dd中的DataFormatString = "{0:yyyy-MM-dd}"