Validate a Date in a specific format in ASP.NET MVC 3
Solution 1
I have now thrown away the RegularExpression
. It doesn't seem to be suited on a property of type DateTime
. Then I created a new validation attribute for DateTime and nullable DateTime:
[AttributeUsage(AttributeTargets.Property, Inherited = false,
AllowMultiple = false)]
public sealed class DateOnlyAttribute : ValidationAttribute
{
public DateOnlyAttribute() :
base("\"{0}\" must be a date without time portion.")
{
}
public override bool IsValid(object value)
{
if (value != null)
{
if (value.GetType() == typeof(DateTime))
{
DateTime dateTime = (DateTime)value;
return dateTime.TimeOfDay == TimeSpan.Zero;
}
else if (value.GetType() == typeof(Nullable<DateTime>))
{
DateTime? dateTime = (DateTime?)value;
return !dateTime.HasValue
|| dateTime.Value.TimeOfDay == TimeSpan.Zero;
}
}
return true;
}
public override string FormatErrorMessage(string name)
{
return string.Format(CultureInfo.CurrentCulture,
ErrorMessageString, name);
}
}
Usage:
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode=true)]
[DateOnly]
public DateTime MyDate { get; set; }
It doesn't provide client side validation. On server side the validation relies on model binding (to make sure that the entered string is convertable to a DateTime
at all). If the user entered a time part other than midnight the DateOnly
attribute kicks in and she gets a warning that only a date should be entered.
Solution 2
Don't use regular expressions to validate dates, they are simply ignored.
Differences in cultures might be the root of your problem. Client side validation uses the browser's culture in order to validate the date. So for example if it is configured to en-US
the expected format would be MM/dd/yyyy
. If your server is configured to use fr-FR
the expected format would be dd/MM/yyyy
.
You could use the <globalization>
element in web.config to set the server side culture. You could configure it in such a way that it uses the same culture as the client:
<globalization culture="auto" uiCulture="auto"/>
Hanselman has a nice blog post about globalization and localization in ASP.NET MVC.
Slauma
Updated on June 19, 2020Comments
-
Slauma about 4 years
I have a property of type
DateTime MyDate
in my ViewModel. I want to make sure that the user only enters the Date part in a text box in a specific format (dd.mm.yyyy) and tried the following attributes:[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode=true)] [RegularExpression(@"^(([0-2]\d|[3][0-1])\.([0]\d|[1][0-2])\.[2][0]\d{2})$", ErrorMessage="Failed...")] public DateTime MyDate { get; set; }
The controller action signature for a HttpPost looks like this:
[HttpPost] public ActionResult Edit(int id, MyViewModel viewModel) { // MyViewModel contains the MyDate property ... // ... if (ModelState.IsValid) { // ... } // ... }
In the Razor view I tried the following two ways:
@Html.TextBoxFor(model => model.MyDate)
@Html.EditorFor(model => model.MyDate)
It doesn't work as I want. The result is:
- Client side validation works as expected with both Html helpers
- Server side validation always fails for both helpers, even with valid dates like "17.06.2011" which pass the regular expression. The
MyDate
property is filled correctly with the entered date inviewModel
which is passed to the action. So it seems that model binding was working. - The
DisplayFormat
attribute is only respected byEditorFor
but not byTextBoxFor
.TextBoxFor
displays "dd.mm.yyyy hh:mm:ss"
Questions:
Can I apply a
RegularExpressionAttribute
at all on a property which isn't astring
? If it is allowed how is the reg ex evaluated for a non-string property likeDateTime
on server side? Is something likeMyDate.ToString()
compared with the reg ex? (It would explain that the validation fails because ToString will return a string including time part which doesn't pass the regular expression.)Is the
DisplayFormat
attribute generally only respected byEditorFor
and never byTextBoxFor
?How can I do a date validation right?
-
Slauma about 13 yearsThanks for the link, I've bookmarked it for future reference. BUT: I don't think my problem has anything to do with localization. I don't believe that the regular expression is ignored: Client side validation works and server side validation also does something with the reg ex (it fails against this reg ex, as the ModelState says). I test on a dev machine (client and server = same machine), so the locales are the same. But I also believe in the meantime that using a reg ex is wrong (although not ignored). How would you validate that a user only enters a date without time portion?
-
Darin Dimitrov about 13 years@Slauma, the fact that you tried this on the same machine doesn't mean that there aren't differences in the culture settings of the browser and the server. As far as the time portion is concerned, I would simply tell the user the format he needs to enter the date in, and on the server I would simply ignore the time portion if my application doesn't need it. Maybe even provide a jquery date picker to simplify the user entering the date into a correct format.
-
Slauma about 13 yearsYou are right, I'm trying it too complicated. For now as a little additional help for user input I have created a
DateOnly
attribute (see my own answer here). Date picker is a better help for the user! I'll try that as one of the next steps.