I have a business rule of my page - controls with date should be in ascending order. I.e. entered value to Date1 < entered value to Date2 < Date3
My attribute:
public class CompareDateAttribute : ValidationAttribute, IClientValidatable
{
public CompareDateAttribute(string datesString)
{
_datesString = datesString;
}
private string _datesString;
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule()
{
//ErrorMessage = this.FormatErrorMessage(metadata.DisplayName),
ErrorMessage = String.Format("Invalid date {0}", metadata.PropertyName),
ValidationType = "datecomparer"
};
rule.ValidationParameters.Add("dates", _datesString);
yield return rule;
}
}
client side:
$.validator.addMethod("datecomparer", function (value, element, param) {
//var valid = true;
var arrElements = param.split(',');
var datePreviousStr = null;
$.each(arrElements, function (index, v) {
if (datePreviousStr == null)
{
datePreviousStr = $('#' + v).val();
}
else
{
var dateCurrentStr = $('#' + v).val();
if (dateCurrentStr == '')
{
return false;
}
var dateCurrent = $.datepicker.parseDate("mm/dd/yy", dateCurrentStr);
var datePrevious = $.datepicker.parseDate("mm/dd/yy", datePreviousStr);
if (dateCurrent < datePrevious)
{
return false;
}
else
{
datePreviousStr = dateCurrentStr;
}
}
});
return true;
});
$.validator.unobtrusive.adapters.addSingleVal("datecomparer", "dates");
Model:
public class Valid6
{
[CompareDate("Date1,Date2,Date3")]
public DateTime Date1 { get; set; }
[CompareDate("Date1,Date2,Date3")]
public DateTime Date2 { get; set; }
[CompareDate("Date1,Date2,Date3")]
public DateTime Date3 { get; set; }
}
and view (necessary part):
<div class="form-horizontal">
<h4>Valid6</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.Date1, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Date1, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Date1, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Date2, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Date2, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Date2, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Date3, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Date3, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Date3, "", 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>
also, part of result HTML:
<input class="form-control text-box single-line valid" data-val="true" data-val-date="The field Date3 must be a date." data-val-datecomparer="Invalid date Date3" data-val-datecomparer-dates="Date1,Date2,Date3" data-val-required="The Date3 field is required." id="Date3" name="Date3" type="datetime" value="">
but when I enter Date1='11/11/2010' and Date2='11/11/2009' debugger says, that datecomparer method returns false, but validator message is not appeared. Why and how to solve?
Found the solution - "return false;" inside loop returns only from loop and then find "return true" on the end of method.
should be like :
$.validator.addMethod("datecomparer", function (value, element, param) {
var valid = true;
var arrElements = param.split(',');
var datePreviousStr = null;
$.each(arrElements, function (index, v) {
if (datePreviousStr == null)
{
datePreviousStr = $('#' + v).val();
}
else
{
var dateCurrentStr = $('#' + v).val();
if (dateCurrentStr == '')
{
valid = false;
return;
}
var dateCurrent = $.datepicker.parseDate("mm/dd/yy", dateCurrentStr);
var datePrevious = $.datepicker.parseDate("mm/dd/yy", datePreviousStr);
if (dateCurrent < datePrevious)
{
valid = false;
return;
}
else
{
datePreviousStr = dateCurrentStr;
}
}
});
return valid;
});
$.validator.unobtrusive.adapters.addSingleVal("datecomparer", "dates");