0

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?

p.campbell
  • 98,673
  • 67
  • 256
  • 322
user1137472
  • 345
  • 2
  • 5
  • 20

4 Answers4

2

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);
MRAB
  • 20,356
  • 6
  • 40
  • 33
  • could you give an example please or could i modify my current expression so it stops 00/00/00 00:00:00 and allow up 31 and minimal 1 and for days and for months minimal 1 and max 12 – user1137472 Jan 15 '12 at 02:12
  • @user1137472: I've added an example. – MRAB Jan 15 '12 at 02:31
  • Thanks to be honest I do not know what that means I tried to implement the answer given by David by creating a class was not successful thank for your efforts – user1137472 Jan 15 '12 at 02:34
  • I do not know where to put it, what it does or where it goes am sorry to have wasted your time but I wanted a simple answer and wanted to stop 00/00/0000 00:00:00 and only allow 1 to 31 for days and 1 to 12 for months by express validation I have seen it before but I cant recall where thanks for all your efforts – user1137472 Jan 15 '12 at 02:37
0

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.

Community
  • 1
  • 1
David Hoerster
  • 28,421
  • 8
  • 67
  • 102
0

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;
        }
    }
Manas
  • 2,534
  • 20
  • 21
0

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?

takepara
  • 10,413
  • 3
  • 34
  • 31
  • I have no idea what u have written and people say regx is bad? look at that code you could never understand what it does. All i wanted was a regx not using server side validation just want a date and time expression I understand your professionals but giving me this code is like giving a baby a gun – user1137472 Jan 15 '12 at 15:20