Reputation: 345
Consider this code:
[Required]
[RegularExpression(@"\d{2,2}/\d{2,2}/\d{4,4} \d{2,2}:\d{2,2}:\d{2,2}",
ErrorMessage = "Wrong Syntax Entered, Needed:day/Month/Year Hour:Minutes:Seconds")]
public DateTime Posted { get; set; }
When I enter this value, my application crashes: 00/00/0000 00:00:00
Is there a way to stop this and make it more realistic? I'm wanting to allow the date so it only allows max 31 days or less up 1 and allows max months up 12 and min 1?
Upvotes: 0
Views: 494
Reputation: 2542
Validating datatime with Regex will result in complex regex like
^([0][1-9]||[1-2][0-9]||[3][0-1])/([0][1-9]||[1][1-2])/([1][0-9]{3}) ([0][1-9]||[1][0-2]):([0][1-9]||[1-5][0-9]):([0][1-9]||[1-5][0-9])$
But Still i doubt it may miss some edge cases.
If you are using MVC3, then the best way to Use Self validating model like follows,
public class TestModel:IValidatableObject
{
string MyDateTime{get;set;}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
List<ValidationResult> v = new List<ValidationResult>();
DateTime dt = default(DateTime);
DateTime.TryParseExact(MyDateTime, "dd/MM/yyyy HH:mm:ss", CultureInfo.InvariantCulture,DateTimeStyles.None,out dt);
if (dt.Equals(default(DateTime)))
v.Add(new ValidationResult("Invalid Date time"));
return v;
}
}
Upvotes: 0
Reputation: 10433
Yet another, change FormatException message in ModelBinder(but going to far...).
DefaultModelBinder.GetValueInvalidResource is static method.I can not override this method. Because I create CustomModelBinder class and override SetProperty method.
[Required]
[AdditionalMetadata(
"PropertyValueInvalid",
"Wrong Syntax Entered, Needed:day/Month/Year Hour:Minutes:Seconds")]
public DateTime? Posted { get; set; }
And create custom ModelBinder
public class CustomModelBinder : DefaultModelBinder
{
protected override void SetProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor, object value)
{
base.SetProperty(controllerContext, bindingContext, propertyDescriptor, value);
var propertyMetadata = bindingContext.PropertyMetadata[propertyDescriptor.Name];
var invalidMessage = propertyMetadata.AdditionalValues.ContainsKey("PropertyValueInvalid")
? (string)propertyMetadata.AdditionalValues["PropertyValueInvalid"]
: string.Empty;
if (string.IsNullOrEmpty(invalidMessage))
{
return;
}
// code from DefaultModelBinder
string fullPropertyKey = CreateSubPropertyName(bindingContext.ModelName, propertyDescriptor.Name);
if (!bindingContext.ValueProvider.ContainsPrefix(fullPropertyKey))
{
return;
}
ModelState modelState = bindingContext.ModelState[fullPropertyKey];
foreach (ModelError error in modelState.Errors.Where(err => String.IsNullOrEmpty(err.ErrorMessage) && err.Exception != null).ToList())
{
for (Exception exception = error.Exception; exception != null; exception = exception.InnerException)
{
if (exception is FormatException)
{
string displayName = propertyMetadata.GetDisplayName();
string errorMessageTemplate = invalidMessage;
string errorMessage = String.Format(CultureInfo.CurrentCulture, errorMessageTemplate,
modelState.Value.AttemptedValue, displayName);
modelState.Errors.Remove(error);
modelState.Errors.Add(errorMessage);
break;
}
}
}
}
}
How about this?
Upvotes: 0
Reputation: 20654
A regex is the wrong way to validate dates and times. Use DateTime.TryParse
instead.
EDIT:
Here's an example:
using System;
using System.Globalization;
...
bool valid;
DateTime dt;
valid = DateTime.TryParseExact(inputString, "dd/MM/yyyy HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.None, out dt);
Upvotes: 2
Reputation: 28701
I agree with @MRAB that TryParse is probably easier to manage and maintain.
This SO question also tries to do what you're doing and they created a custom attribute (that derives from RegularExpressionAttribute
) that seems to have solved his problem. Maybe it will help you.
Hope this helps.
Upvotes: 0