aknuds1
aknuds1

Reputation: 68127

In ASP.NET MVC 4, how to validate that a DateTime value is entered on the correct format?

In our ASP.NET MVC 4 application, one of the models has a field of the DateTime type. When editing such model objects via a form, the value for the DateTime field has to be non-empty and on the format yyyy-MM-dd H:mm:ss (e.g., 2012-10-17 10:49:00). How do I ensure this field is correctly validated in the application? I've tried the following annotations:

[System.ComponentModel.DataAnnotations.Required]
[System.ComponentModel.DataAnnotations.DisplayFormat(DataFormatString="yyyy-MM-dd H:mm:ss",
        ApplyFormatInEditMode=true)]

However, validation of form data doesn't require all components of the format to be present. For instance, the value '2012-10-17' is accepted (leaving out the 'H:mm:ss' part). It's just verified that the field contains a valid DateTime string.

How should I ensure that this DateTime field is indeed on my specified format (yyyy-MM-dd H:mm:ss)?

Upvotes: 2

Views: 9628

Answers (2)

Robert Koritnik
Robert Koritnik

Reputation: 105091

Alternative solution - view-only model class

Darin's solution is of course valid, but it's not the only one you can use. And it would require you to write more complex code than with this solution that I'm going to show you here.

So this is an alternative. I'd suggest that instead of creating a custom model binder you rather create a separate view model class that instead of taking DateTime takes a string where you can set as complex validation regular expression as you like. And then have a method on it that would translate it to your application/domain model class instance (and back).

// suppose this app model
public class User
{
    [Required]
    public string Name { get; set; }

    [Required]
    public DateTime DateOfBirth { get; set; }
}

public class ViewUser
{
    [Required]
    public string Name { get; set; }

    [Required]
    [RegularExpression("\d{4}-\d{2}-\d{2}(?:\s\d{1,2}:\d{2}:\d{2})?")]
    public string DateOfBirth { get; set; }

    public ViewUser(User user)
    {
        this.Name = user.Name;
        this.DateOfBirth = user.DateOfBirth.ToString("yyyy-MM-dd H:mm:ss");
    }

    public User ToPoco()
    {
        return new User {
            Name = this.Name,
            DateOfBirth = DateTime.Parse(this.DateOfBirth, "yyyy-MM-dd H:mm:ss")
        };
    }
}

With a bit of tweaking you could inherit ViewUser from User class and use new keyword on DateOfBirth and use base property to store correct typed value. In that case you wouldn't need the ToPoco method.

Note: you will have to use DateTime.TryParseExact method to parse your dates because they may include time or they may not. I didn't include that in my code because it depends on the exact requirements of your date input.

Upvotes: 1

Darin Dimitrov
Darin Dimitrov

Reputation: 1039578

You could write a custom model binder which will use the exact format you have specified in the DisplayFormat attribute. I have shown an example of how this could be achieved in this post.

Also don't be confused into thinking that the DisplayFormat attribute overrides the Required attribute. The DisplayFormat is only used for displaying the field in the input field. It is not a validation attribute. It has strictly nothing to do with validation and when the form is POSTed to the server it is never used.

Upvotes: 0

Related Questions