0

Trying to make use of Fluent Validation to ensure that a date range is always filled and that the end date does not occur before the beginning date.

I have the first part done correctly, and it fires correctly, but the second part seems to be unimplementable.

My code:

public class Report1ToExcelValidator : AbstractValidator<Report1ToExcelViewModel> {
  public Report1ToExcelValidator() {
    RuleFor(x => x.Report1ToExcelDateFrom)
      .NotEmpty().WithMessage("Please provide a valid beginning date for the range.");
    RuleFor(x => x.Report1ToExcelDateTo)
      .NotEmpty().WithMessage("Please provide a valid end date for the range.")
      .GreaterThan(x => x.Report1ToExcelDateFrom.Value).WithMessage("The Date To must be after the Date From");
  }
}

Where everything gets tripped up is with the .GreaterThan, which reports an error:

'DateTime' does not contain a definition for 'Value' and no extension method 'Value' accepting a first argument of type 'DateTime' could be found

My DateTime is not nullable, both DateTimes require content. When I allow Intellisense to bring up possible options, anything after the field name is restricted to things like .Date and .Hour, which also do not work. .Value does not exist in that list of options, neither does .HasValue.

Really confused on this one.


Also, another question: how do I do separate validations on multiple forms that exist on a single page? Right now I have only the one form, but the form's model is being brought in directly. I cannot seem to figure out how to abstract away the form's model so that I can have more than one model on a page. No data is being brought in.

Right now I have just tried to alter the models to:

public class ReportViewModel {
    public Report1ToExcelViewModel Report1ToExcelViewModel { get; set; } 
}

[Validator(typeof(Report1ToExcelValidator))]
public class Report1ToExcelViewModel {
  public Guid? Report1ToExcelRegion { get; set; }
  public DateTime Report1ToExcelDateFrom { get; set; }
  public DateTime Report1ToExcelDateTo { get; set; }
}

with the page referencing @model CCS.Models.ReportViewModel instead of @model CCS.Models.Report1ToExcelViewModel but I cannot seem to get the page to pull in the Report1ToExcelViewModel so that the form fields get recognized. Right now they error out because 'ReportViewModel' does not contain a definition for [fieldname] even though I am bringing the Report1ToExcelViewModel directly into ReportViewModel as above.

René Kåbis
  • 842
  • 2
  • 9
  • 28
  • Just use `.GreaterThan(x => x.Report1ToExcelDateFrom)` –  Mar 21 '16 at 23:06
  • It doesn't validate properly. If I have an DateTo that is less than the DateFrom, it doesn't get caught. Which is why I am asking the question of why it doesn't work. Besides, all google sources I have found clear up to late 2015 and referencing MVC 5 make use of the `.Value` and `.HasValue` attributes. – René Kåbis Mar 21 '16 at 23:07
  • Can't see anything wrong with you code assuming you remove `.Value` –  Mar 21 '16 at 23:17
  • And yet, it fails to validate. Or at the very least, it fails to prevent the form from being executed and fails to provide an error message. Unlike leaving null (empty) values, which do prevent the form from firing and do return error messages. This is an excel file generation routine, so I just cannot do a `ModelState.IsValid` and `else {return View("Index")}` because the method is a `FileContentResult` and not an `ActionResult`. If this is to be caught on the server side, I need to return a file without actually returning a file. Which is impossible. – René Kåbis Mar 21 '16 at 23:19
  • What happens if you do make the property nullable and leave in `.Value`? –  Mar 21 '16 at 23:22
  • The `.Value` becomes available but this still doesn't validate on the client side. I cannot have a file returned because it will make no sense, so this cannot be done on the server side. – René Kåbis Mar 21 '16 at 23:24
  • 2
    According to the [docs](https://github.com/JeremySkinner/FluentValidation/wiki/h.-MVC), it appears `.GreaterThan` may not be supported for client side validation (at least its not included in the list of client side supported validators). An alternative would be to try a [foolproof](http://foolproof.codeplex.com/) `[GreaterThan]` or similar validation attribute –  Mar 21 '16 at 23:31
  • Will look into this, thank you very much! – René Kåbis Mar 22 '16 at 01:06

1 Answers1

1

Use

.GreaterThan(x => x.Report1ToExcelDateFrom)

in place of

.GreaterThan(x => x.Report1ToExcelDateFrom.Value)

since your model Report1ToExcelDateFrom is not a nullable Datetime

public DateTime ? Report1ToExcelDateFrom { get; set; }

would have worked out perfectly

Sudipto Sarkar
  • 346
  • 2
  • 11