jQuery MVC 自定义验证:比较两个日期
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7025198/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
MVC custom validation: compare two dates
提问by ShaneKm
I've created a custom ValidationAttribute that compares 2 dates and makes sure that the second date is greater than the first:
我创建了一个自定义 ValidationAttribute 来比较 2 个日期并确保第二个日期大于第一个日期:
public sealed class IsDateAfter : ValidationAttribute, IClientValidatable
{
private readonly string testedPropertyName;
private readonly bool allowEqualDates;
public IsDateAfter(string testedPropertyName, bool allowEqualDates = false)
{
this.testedPropertyName = testedPropertyName;
this.allowEqualDates = allowEqualDates;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var propertyTestedInfo = validationContext.ObjectType.GetProperty(this.testedPropertyName);
if (propertyTestedInfo == null)
{
return new ValidationResult(string.Format("unknown property {0}", this.testedPropertyName));
}
var propertyTestedValue = propertyTestedInfo.GetValue(validationContext.ObjectInstance, null);
if (value == null || !(value is DateTime))
{
return ValidationResult.Success;
}
if (propertyTestedValue == null || !(propertyTestedValue is DateTime))
{
return ValidationResult.Success;
}
// Compare values
if ((DateTime)value >= (DateTime)propertyTestedValue)
{
if (this.allowEqualDates)
{
return ValidationResult.Success;
}
if ((DateTime)value > (DateTime)propertyTestedValue)
{
return ValidationResult.Success;
}
}
return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule
{
ErrorMessage = this.ErrorMessageString,
ValidationType = "isdateafter"
};
rule.ValidationParameters["propertytested"] = this.testedPropertyName;
rule.ValidationParameters["allowequaldates"] = this.allowEqualDates;
yield return rule;
}
CalendarEntry class: ...
CalendarEntry 类:...
public virtual DateTime StartDate { get; set; }
[IsDateAfter("StartDate", true, ErrorMessage="End date needs to be after start date")]
public virtual DateTime EndDate { get; set; }
VIEW:
看法:
$.validator.unobtrusive.adapters.add(
'isdateafter', ['propertytested', 'allowequaldates'], function (options) {
options.rules['isdateafter'] = options.params;
options.messages['isdateafter'] = options.message;
});
$.validator.addMethod("isdateafter", function(value, element, params) {
alert(params.propertytested);
var startdatevalue = $('input[name="' + params.propertytested + '"]').val();
if (!value || !startdatevalue) return true;
return (params.allowequaldates) ? Date.parse(startdatevalue) <= Date.parse(value) : Date.parse(startdatevalue) < Date.parse(value);
}, '');
This works fine when the CalendarEntryis not wrapped inside another class. HOWEVER, when I use a view model like so:
当CalendarEntry没有包含在另一个类中时,这可以正常工作。但是,当我使用这样的视图模型时:
public class TrainingDateEditViewModel
{
#region Properties
/// <summary>
/// Gets or sets CalendarEntry.
/// </summary>
public CalendarEntry CalendarEntry { get; set; }
....
The client validation no longer works because the html output produced is this:
客户端验证不再有效,因为生成的 html 输出是这样的:
<input type="text" value="" name="CalendarEntry.EndDate" id="CalendarEntry_EndDate" data-val-isdateafter-propertytested="StartDate" data-val-isdateafter-allowequaldates="True" data-val-isdateafter="End date needs to be after start date" data-val="true">
And the
而
data-val-isdateafter-propertytested="StartDate" and IT SHOULD BE: "CalendarEntry.StartDate".
How would I make it so that it would know to bind to "CalendarEntry.StartDate" rule.ValidationParameters["propertytested"] = this.testedPropertyName; // HERE IT SHOULD BE FULL NAME??? HOW??
我将如何使它知道绑定到“CalendarEntry.StartDate” rule.ValidationParameters[“propertytested”] = this.testedPropertyName; // 这里应该是全名???如何??
thanks
谢谢
采纳答案by counsellorben
You need to modify your client-side script to check for the tested element's prefix, and add the prefix (if any) to your selector, as follows:
您需要修改客户端脚本以检查测试元素的前缀,并将前缀(如果有)添加到您的选择器中,如下所示:
$.validator.addMethod("isdateafter", function(value, element, params) {
var parts = element.name.split(".");
var prefix = "";
if (parts.length > 1)
prefix = parts[0] + ".";
var startdatevalue = $('input[name="' + prefix + params.propertytested + '"]').val();
if (!value || !startdatevalue)
return true;
return (params.allowequaldates) ? Date.parse(startdatevalue) <= Date.parse(value) :
Date.parse(startdatevalue) < Date.parse(value);
});
回答by MrFlo
Do not forget to include the client side inside this code. It tooks me hours to find that this was missing!
不要忘记在此代码中包含客户端。我花了几个小时才发现它不见了!
(function ($) {
// your code here..
})(jQuery);
回答by gerard789
Just to fix a small error in counsellorben's javascript: the "(params.allowequaldates)" will be interpreted as a string (which will have a value of "False" or "True"), but that string will always be evaluated to true, thus always allowing equal dates. If you also want to allow for more levels of nesting of your objects than just 1, then you will get:
只是为了修复顾问的 javascript 中的一个小错误:“(params.allowequaldates)”将被解释为一个字符串(其值为“False”或“True”),但该字符串将始终被评估为真,因此总是允许相同的日期。如果您还希望允许对象的嵌套级别超过 1 级,那么您将获得:
$.validator.addMethod("isdateafter", function(value, element, params) {
var parts = element.name.split(".");
var prefix = "";
for (var i = 0; i < parts.length - 1; i++)
prefix = parts[i] + ".";
var startdatevalue = $('input[name="' + prefix + params.propertytested + '"]').val();
if (!value || !startdatevalue)
return true;
var allowequal = params.allowequaldates.toLowerCase === "true";
return allowequal ? Date.parse(startdatevalue) <= Date.parse(value) :
Date.parse(startdatevalue) < Date.parse(value);
});
回答by Dan Pettersson
In the last answer there were some missing parenthesis on the call to toLowerCase, here is an updated version with document ready and the $.validator.unobtrusive...-part:
在最后一个答案中,调用 toLowerCase 时缺少一些括号,这是一个更新版本,文档准备就绪,$.validator.unobtrusive...-part:
$(function () {
$.validator.addMethod("isdateafter", function(value, element, params) {
var parts = element.name.split(".");
var prefix = "";
for (var i = 0; i < parts.length - 1; i++) {
prefix = parts[i] + ".";
}
var startdatevalue = $('input[name="' + prefix + params.propertytested + '"]').val();
if (!value || !startdatevalue) return true;
var allowequal = params.allowequaldates.toLowerCase() === "true";
return allowequal ? Date.parse(startdatevalue) <= Date.parse(value) :
Date.parse(startdatevalue) < Date.parse(value);
});
$.validator.unobtrusive.adapters.add('isdateafter',
['propertytested', 'allowequaldates'],
function (options) {
options.rules['isdateafter'] = options.params;
options.messages['isdateafter'] = options.message;
});
});