I am using view model for start and end date and use validation using data annotation. Validation Rule are:
Following View Model consist of startdate and enddate properties. The confusion is that How can I pass value of EndDate value in StartEndDateRange data-annotation and StartDate value in data-annotation of EndDate in below code:
public class StartEndDate
{
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
[StartEndDateRange("2000/01/01", "value of end date properties")]
public DateTime StartDate { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
[StartEndDateRange("value of startdate properties", DateTime.Now.ToString("yyyy/MM/dd"))]
public DateTime EndDate { get; set; }
}
public class StartEndDateRangeAttribute : ValidationAttribute
{
private const string DateFormat = "yyyy/MM/dd";
private const string DefaultErrorMessage =
"'{0}' must be a date between {1:d} and {2:d}.";
public DateTime MinDate { get; set; }
public DateTime MaxDate { get; set; }
public StartEndDateRangeAttribute(string minDate, string maxDate)
: base(DefaultErrorMessage)
{
MinDate = ParseDate(minDate);
MaxDate = ParseDate(maxDate);
}
public override bool IsValid(object value)
{
if (value == null || !(value is DateTime))
{
return true;
}
DateTime dateValue = (DateTime)value;
return MinDate <= dateValue && dateValue <= MaxDate;
}
public override string FormatErrorMessage(string name)
{
return String.Format(CultureInfo.CurrentCulture,
ErrorMessageString,
name, MinDate, MaxDate);
}
private static DateTime ParseDate(string dateValue)
{
return DateTime.ParseExact(dateValue, DateFormat,
CultureInfo.InvariantCulture);
}
}
Create two different Validation Attributes. One DateBefore and Another DataAfter
You can get the the properties of the model under validation from validationContext.
In the DateBefore do
protected override ValidationResult IsValid(object value, ValidationContext validationContext) {
PropertyInfo endDateProperty= validationContext.ObjectType.GetProperty("EndDate");
...
}
Get the value by
var endDate = endDateProperty.GetValue(validationContext.ObjectInstance, null);
Now compare value and endDate.
A little more code
public class BeforeEndDateAttribute : ValidationAttribute{
public string EndDatePropertyName { get; set; }
public string StartDate { get; set; }
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
PropertyInfo endDateProperty = validationContext.ObjectType.GetProperty(EndDatePropertyName);
DateTime endDate = (DateTime) endDateProperty.GetValue(validationContext.ObjectInstance, null);
var startDate = DateTime.Parse(StartDate);
// Do comparison
// return ValidationResult.Success; // if success
return new ValidationResult("Error"); // if fail
}
}
And use like:
public class MyModel
{
[BeforeEndDate(EndDatePropertyName = "EndDate", StartDate = "2000/01/01")]
public DateTime StartDate { get; set; }
// [AfterStartDate(StartDatePropertyName = "StartDate", EndDate = "2020/01/01")]
public DateTime EndDate { get; set; }
}
It's easier to implement this in one validation attribute DateRange.
But if you don't want to, you'll have to override IsValid(Object, ValidationContext), extract object type being validated from ValidationContext.ObjectType, get its property being validated by ValidationContext.MemberName and then read values from attributes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With