Exception with invalid dates using data annotations

Have a Json API model with a date property defined as:

    [Required]
    [DataType(DataType.Date, ErrorMessage = "Invalid expiry date")]
    public DateTime ExpiryDate { get; set; }

when posting an incorrect value for the ExpiryDate, examples:

   "ExpiryDate":"2020-02-31T00:00:00",
   "ExpiryDate":"2020-01-99T00:00:00",
   "ExpiryDate":"abc",

the ModelState.Values.Errors[0].ErrorMessage is empty. Instead there is Model exception that I can not return to the API consumer, looks ugly.

    ModelState.Values.Errors[0].Exception = {"Could not convert string to DateTime: 2020-02-31T00:00:00. Path 'CardDetails.ExpiryDate', line 13, position 39."}

My question are: how can I make the data annotation generate an error instead of an exception? Why is not the current data annotation giving an error, is not the job of [DataType(DataType.Date...] to do that?

Upvotes: 1

Views: 2508

Answers (2)

Christopher Stevenson
Christopher Stevenson

Reputation: 2861

The main issue here is that a DateTime value in JSON (at least according to the JSON parser) has a specific format, and not following that format is a parsing error, which is what's currently happening.

I think you'll have to take the value in as a string and do a conversion and validation on top of it. There's a couple of options. One is a custom ValidationAttribute like @erikscandola mentioned. Another is to implmenent IValidatableObject interface on your model.

You could also convert the model property to a string and simply do a check in the controller action:

DateTime expiryDate;
if (!DateTime.TryParse(model.ExpiryDate, out expiryDate))
{
    ModelState.AddModelError("", string.Format(
        "The given ExpiryDate '{0}' was not valid", model.ExpiryDate));
} 

The approach depends upon how much reuse you need of the validation logic.

Upvotes: 2

erikscandola
erikscandola

Reputation: 2936

You should create a custom data annotation:

public class RequiredDateTimeAttribute : ValidationAttribute
{
    public override bool IsValid(object value)
    {
        // Here your code to check date in value
    }
}

Upvotes: 0

Related Questions