问题描述
我可以做到服务器端部分.我想如果开始日期不为空,则结束日期必须等于或大于开始日期.服务器端逻辑几乎已经完成,但是我有点困惑要为客户端逻辑做些什么.基本上我想通过IClientValidatable
界面来做到这一点.
i could do it server side part. i want if start date is not empty then end date must be equal or greater than start date. server side logic is almost complete but i am bit confuse what to do for client side logic. basically i want to do it by IClientValidatable
interface.
我的服务器端代码如下
public class DateValTest
{
[Display(Name = "Start Date")]
[DataType(DataType.Date), DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
public DateTime? StartDate { get; set; }
[Display(Name = "End Date")]
[DataType(DataType.Date), DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
[DateGreaterThanAttribute(otherPropertyName = "StartDate", ErrorMessage = "End date must be greater than start date")]
public DateTime? EndDate { get; set; }
}
属性代码
public class DateGreaterThanAttribute : ValidationAttribute
{
public string otherPropertyName;
public DateGreaterThanAttribute() { }
public DateGreaterThanAttribute(string otherPropertyName, string errorMessage)
: base(errorMessage)
{
this.otherPropertyName = otherPropertyName;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
ValidationResult validationResult = ValidationResult.Success;
try
{
// Using reflection we can get a reference to the other date property, in this example the project start date
var containerType = validationContext.ObjectInstance.GetType();
var field = containerType.GetProperty(this.otherPropertyName);
var extensionValue = field.GetValue(validationContext.ObjectInstance, null);
var datatype = extensionValue.GetType();
//var otherPropertyInfo = validationContext.ObjectInstance.GetType().GetProperty(this.otherPropertyName);
if (field == null)
return new ValidationResult(String.Format("Unknown property: {0}.", otherPropertyName));
// Let's check that otherProperty is of type DateTime as we expect it to be
if ((field.PropertyType == typeof(DateTime) || (field.PropertyType.IsGenericType && field.PropertyType == typeof(Nullable<DateTime>))))
{
DateTime toValidate = (DateTime)value;
DateTime referenceProperty = (DateTime)field.GetValue(validationContext.ObjectInstance, null);
// if the end date is lower than the start date, than the validationResult will be set to false and return
// a properly formatted error message
if (toValidate.CompareTo(referenceProperty) < 1)
{
validationResult = new ValidationResult(ErrorMessageString);
}
}
else
{
validationResult = new ValidationResult("An error occurred while validating the property. OtherProperty is not of type DateTime");
}
}
catch (Exception ex)
{
// Do stuff, i.e. log the exception
// Let it go through the upper levels, something bad happened
throw ex;
}
return validationResult;
}
}
我关心的是如何将开始日期文本框名称从服务器端传递到客户端,这将为结束日期文本框添加一些属性.
my concern is how to pass start date textbox name from server side to client side which will add some attribute to end date textbox.
所以只需要帮助我为GetClientValidationRules
函数构造一些服务器端代码,以及为客户端非侵入式代码构建一些代码,例如$.validator.unobtrusive.adapters.add and $.validator.addMethod
,任何人都可以帮助我喜欢如何实现它.谢谢
so just help me to construct few server side code for GetClientValidationRules
function and few code for client side unobtrusive code say for example $.validator.unobtrusive.adapters.add and $.validator.addMethod
anyone can help me like how to achieve it. thanks
我尝试以这种方式解决它,但是我的客户端js没有触发.这是我修改后的代码.
i try to solve it this way but my client side js is not triggering. here is my revised code.
public class DateValTest
{
[Display(Name = "Start Date")]
[DataType(DataType.Date), DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
public DateTime? StartDate { get; set; }
[Display(Name = "End Date")]
[DataType(DataType.Date), DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
[MyDate(ErrorMessage = "Back date entry not allowed")]
[DateGreaterThanAttribute(otherPropertyName = "StartDate", ErrorMessage = "End date must be greater than start date")]
public DateTime? EndDate { get; set; }
}
我的属性相关代码
public class DateGreaterThanAttribute : ValidationAttribute, IClientValidatable
{
public string otherPropertyName;
public DateGreaterThanAttribute() { }
public DateGreaterThanAttribute(string otherPropertyName, string errorMessage)
: base(errorMessage)
{
this.otherPropertyName = otherPropertyName;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
ValidationResult validationResult = ValidationResult.Success;
try
{
// Using reflection we can get a reference to the other date property, in this example the project start date
var containerType = validationContext.ObjectInstance.GetType();
var field = containerType.GetProperty(this.otherPropertyName);
var extensionValue = field.GetValue(validationContext.ObjectInstance, null);
var datatype = extensionValue.GetType();
//var otherPropertyInfo = validationContext.ObjectInstance.GetType().GetProperty(this.otherPropertyName);
if (field == null)
return new ValidationResult(String.Format("Unknown property: {0}.", otherPropertyName));
// Let's check that otherProperty is of type DateTime as we expect it to be
if ((field.PropertyType == typeof(DateTime) || (field.PropertyType.IsGenericType && field.PropertyType == typeof(Nullable<DateTime>))))
{
DateTime toValidate = (DateTime)value;
DateTime referenceProperty = (DateTime)field.GetValue(validationContext.ObjectInstance, null);
// if the end date is lower than the start date, than the validationResult will be set to false and return
// a properly formatted error message
if (toValidate.CompareTo(referenceProperty) < 1)
{
validationResult = new ValidationResult(ErrorMessageString);
}
}
else
{
validationResult = new ValidationResult("An error occurred while validating the property. OtherProperty is not of type DateTime");
}
}
catch (Exception ex)
{
// Do stuff, i.e. log the exception
// Let it go through the upper levels, something bad happened
throw ex;
}
return validationResult;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule
{
ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
ValidationType = "isgreater",
};
rule.ValidationParameters.Add("otherproperty", otherPropertyName);
yield return rule;
}
}
我的js代码
$.validator.unobtrusive.adapters.add('isgreater', ['otherproperty'], function (options) {
options.rules['isgreater'] = { isgreater: options.params.otherproperty };
options.messages['isgreater'] = options.message;
});
$.validator.addMethod("isgreater", function (value, element, param) {
alert('pop' + params.otherproperty);
var otherProp = $('#' + params.otherproperty);
var date = new Date(value);
if (otherProp.val() != '')
{
return date >= minDate;
}
return true;
});
我的结束日期文本框html如下
My end date textbox html look like as following
<input type="date"
value="03/16/2016"
name="EndDate"
id="EndDate"
data-val-restrictbackdates-mindate="03/16/2016 00:00:00"
data-val-restrictbackdates="Back date entry not allowed"
data-val-isgreater-otherproperty="StartDate"
data-val-isgreater="End date must be greater than start date"
data-val-date="The field End Date must be a date."
data-val="true"
class="input-validation-error form-control text-box single-line">
问题是我的js代码未触发.....无法捕获该区域js代码中的错误.需要一些提示或帮助.谢谢
public class DateValTest
{
[Display(Name = "Start Date")]
[DataType(DataType.Date), DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
public DateTime? StartDate { get; set; }
[Display(Name = "End Date")]
[DataType(DataType.Date), DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
[MyDate(ErrorMessage = "Back date entry not allowed")]
[DateGreaterThanAttribute(otherPropertyName = "StartDate", ErrorMessage = "End date must be greater than start date")]
public DateTime? EndDate { get; set; }
}
与自定义属性相关的类代码
public class MyDateAttribute : ValidationAttribute, IClientValidatable
{
private DateTime _MinDate;
public MyDateAttribute()
{
_MinDate = DateTime.Today;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
DateTime _EndDat = DateTime.Parse(value.ToString(), CultureInfo.InvariantCulture);
DateTime _CurDate = DateTime.Today;
int cmp = _EndDat.CompareTo(_CurDate);
if (cmp > 0)
{
// date1 is greater means date1 is comes after date2
return ValidationResult.Success;
}
else if (cmp < 0)
{
// date2 is greater means date1 is comes after date1
return new ValidationResult(ErrorMessage);
}
else
{
// date1 is same as date2
return ValidationResult.Success;
}
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule
{
ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
ValidationType = "restrictbackdates",
};
rule.ValidationParameters.Add("mindate", _MinDate);
yield return rule;
}
}
public class DateGreaterThanAttribute : ValidationAttribute, IClientValidatable
{
public string otherPropertyName;
public DateGreaterThanAttribute() { }
public DateGreaterThanAttribute(string otherPropertyName, string errorMessage)
: base(errorMessage)
{
this.otherPropertyName = otherPropertyName;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
ValidationResult validationResult = ValidationResult.Success;
try
{
// Using reflection we can get a reference to the other date property, in this example the project start date
var containerType = validationContext.ObjectInstance.GetType();
var field = containerType.GetProperty(this.otherPropertyName);
var extensionValue = field.GetValue(validationContext.ObjectInstance, null);
if(extensionValue==null)
{
//validationResult = new ValidationResult("Start Date is empty");
return validationResult;
}
var datatype = extensionValue.GetType();
//var otherPropertyInfo = validationContext.ObjectInstance.GetType().GetProperty(this.otherPropertyName);
if (field == null)
return new ValidationResult(String.Format("Unknown property: {0}.", otherPropertyName));
// Let's check that otherProperty is of type DateTime as we expect it to be
if ((field.PropertyType == typeof(DateTime) || (field.PropertyType.IsGenericType && field.PropertyType == typeof(Nullable<DateTime>))))
{
DateTime toValidate = (DateTime)value;
DateTime referenceProperty = (DateTime)field.GetValue(validationContext.ObjectInstance, null);
// if the end date is lower than the start date, than the validationResult will be set to false and return
// a properly formatted error message
if (toValidate.CompareTo(referenceProperty) < 1)
{
validationResult = new ValidationResult(ErrorMessageString);
}
}
else
{
validationResult = new ValidationResult("An error occurred while validating the property. OtherProperty is not of type DateTime");
}
}
catch (Exception ex)
{
// Do stuff, i.e. log the exception
// Let it go through the upper levels, something bad happened
throw ex;
}
return validationResult;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule
{
ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
ValidationType = "isgreater",
};
rule.ValidationParameters.Add("otherproperty", otherPropertyName);
yield return rule;
}
}
使用js查看代码
@model AuthTest.Models.DateValTest
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>DateValTest</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.StartDate, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.StartDate, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.StartDate, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.EndDate, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.EndDate, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.EndDate, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
<script src="https://cdn.jsdelivr.net/momentjs/2.12.0/moment.min.js"></script>
<script type="text/javascript">
$.validator.unobtrusive.adapters.add('restrictbackdates', ['mindate'], function (options) {
options.rules['restrictbackdates'] = { mindate: options.params.mindate };
options.messages['restrictbackdates'] = options.message;
});
$.validator.addMethod("restrictbackdates", function (value, element, param) {
var date = new Date(value);
var minDate = new Date(param.mindate);
return date >= minDate;
});
$.validator.unobtrusive.adapters.add('isgreater', ['otherproperty'], function (options) {
options.rules['isgreater'] = { otherproperty: options.params.otherproperty };
options.messages['isgreater'] = options.message;
});
$.validator.addMethod("isgreater", function (value, element, param) {
var otherProp = $('#' + param.otherproperty);
if (otherProp.val() != '') {
var StartDate = new Date(moment(otherProp.val(), 'MM/DD/YYYY'));
var Enddate = new Date(value);
if (StartDate != '') {
return Enddate >= StartDate;
}
}
return true;
});
</script>
}
推荐答案
如果我做对了-那么您需要根据开始日期"(即取决于值")在结束日期"上添加验证.使用Foolproof.js可以很容易地做到这一点,其中有各种属性,如RequiredIf,RequiredIfRegexMatch等.您还可以像编写MVC属性一样,编写覆盖默认属性的自定义代码.一个例子:
If I am getting it right - then you need to add validation on End Date based on Start Date i.e., Depending value.It can be done very easily using Foolproof.js where there are various attributes like RequiredIf, RequiredIfRegexMatch etc. You can also write you customized code overridding the default attributes in the same manner like we do for MVC attributes.One example:
using Foolproof;
public class MustBeTrueIfAttribute : RequiredIfAttribute
{
static MustBeTrueIfAttribute()
{
Register.Attribute(typeof(MustBeTrueIfAttribute));
}
public MustBeTrueIfAttribute(string dependentProperty, object dependentValue)
: base(dependentProperty, dependentValue)
{
}
public MustBeTrueIfAttribute(string dependentProperty, Operator @operator, object dependentValue)
: base(dependentProperty, @operator, dependentValue)
{
}
public override string ClientTypeName => "mustbetrueif";
public override bool IsValid(object value, object dependentValue, object container)
{
return !this.Metadata.IsValid(dependentValue, this.DependentValue) || (value != null && (bool)value);
}
}
这篇关于ASP.Net MVC条件验证:结束日期必须大于或等于开始日期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!