我可以做服务器端部分。我想如果开始日期不为空,则结束日期必须等于或大于开始日期。服务器端逻辑几乎完成,但我有点混淆如何做客户端逻辑。基本上我想通过IClientValidatable
界面来做。
我的服务器端代码如下
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;
}
}
我关注的是如何将开始日期文本框名称从服务器端传递到客户端,这将在结束日期文本框中添加一些属性。
所以,请帮助我为GetClientValidationRules
函数构建一些服务器端代码,并为客户端不显眼的代码编写一些代码,例如$.validator.unobtrusive.adapters.add and $.validator.addMethod
任何人都可以帮助我了解如何实现它。感谢
我尝试以这种方式解决它但我的客户端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 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;
}
}
$.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如下所示
<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;
}
}
@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>
}
答案 0 :(得分:1)
如果我做对了 - 那么你需要根据开始日期在结束日期添加验证,即依据值。 使用Foolproof.js可以很容易地完成它,其中有各种属性,如RequiredIf,RequiredIfRegexMatch等。您也可以编写自定义代码,以与我们对MVC属性相同的方式覆盖默认属性。 一个例子:
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);
}
}
答案 1 :(得分:0)
对于客户端验证,如果您使用的是jquery ui(datepicker),那么您需要做的就是
<!-- Client form -->
<form>
<?php wp_nonce_field('my_form','_my_token'); ?>
<!-- Additional form fields -->
</form>