0

I am looking at validating, so my application will not allow someone to enter an end date that occurs before a start date.

I have been relying on the "built in" validation to date and it has worked, but not sure how to implement for this.

Model:

    [Required]
    [Display(Name = "Assignment Start Date *")]
    [DataType(DataType.Date)]
    public DateTime? AssignmentStart { get; set; } 

    [Required]
    [Display(Name = "Assignment End Date *")]
    [DataType(DataType.Date)]
    public DateTime? AssignmentEnd { get; set; }

View:

        <div class="form-group">
            <label asp-for="AssignmentStart" class="col-md-2 control-label"></label>
            <div class="col-md-4">
                <input asp-for="AssignmentStart" class="form-control" />
                <span asp-validation-for="AssignmentStart" class="text-danger"></span>
            </div>
        </div>
        <div class="form-group">
            <label asp-for="AssignmentEnd" class="col-md-2 control-label"></label>
            <div class="col-md-4">
                <input asp-for="AssignmentEnd" class="form-control" />
                <span asp-validation-for="AssignmentEnd" class="text-danger"></span>
            </div>
        </div>

Controller:

if (ModelState.IsValid)

is surrounding my code

If i try to submit my form without a date, my Model state becomes invalid , i return my view and a built in message appears - The Assignment Start Date field is required - i am really happy with how neat and simple this is.

Is there a simple way like this to look at two dates and ensure one does not exist before the other? If there is not a simple way, what is the recommended way?

1 Answers1

1

You can create custom annotation :)

  public sealed class IsValidEndDate : ValidationAttribute,
 IClientValidatable
    {
        private readonly string StartDatePropertyName;
        //init
        public IsValidEndDate(string StartDatePropertyAttrName)
        {
            this.StartDatePropertyName = StartDatePropertyAttrName;
        }

        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            throw new NotImplementedException();
        }

        //override IsValid
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            var propertyTestedInfo = validationContext.ObjectType.GetProperty(this.StartDatePropertyName);
            /// Get Start Date Value 
            var StartDateValue = propertyTestedInfo.GetValue(validationContext.ObjectInstance, null);
            // init start date 
            DateTime StartDate = DateTime.MinValue;
            DateTime EndDate = DateTime.MinValue;

            if (DateTime.TryParse(StartDateValue.ToString(), out StartDate))
            {
                if (DateTime.TryParse(value.ToString(), out EndDate))
                {
                    // Implement your logic
                    if (EndDate >= StartDate)
                    {
                        return ValidationResult.Success;
                    }
                    else
                    {
                        return new ValidationResult(FormatErrorMessage("End Date Should be after start date"));

                    }

                }

                else
                {
                    return new ValidationResult(FormatErrorMessage("End Date not valid"));

                }
            }
            else
            {
                return new ValidationResult(FormatErrorMessage("Start Date not valid"));
            }
        }
    }

Then in your model you can do call it like this

   [IsValidEndDate ("AssignmentStart")]
   public DateTime AssignmentEnd{get;set;}

Please Note that you can make more advanced one, this is very basic.

Munzer
  • 2,216
  • 2
  • 18
  • 25