Vinzz
Vinzz

Reputation: 4028

.NET ComponentModel.DataAnnotations issue with RegularExpression attribute

I have to validate a string that's supposed to contain an hour number (e.g. 00 to 23).

I hence set an annotation like:

 [RegularExpression("[01]?[0-9]|2[0-3]", ErrorMessage = "Error")]
 public string JobStartHour {...}

Unfortunately, this regex doesn't match the inputs from 20 to 23, as it's supposed to do (IMHO).

Doesn't this RegularExpression attribute use the plain old Regex.IsMatch ?

Regex.IsMatch("22", "[01]?[0-9]|2[0-3]")

returns true...

Edit: I know, using a string isn't the best idea so as to store a number, nevertheless, this regex issue is annoying.

Upvotes: 1

Views: 337

Answers (4)

oberfreak
oberfreak

Reputation: 1807

You have to group the | to work properly.

I successfully tried, which should be exactly your regex but grouped and limited to start & end:

^([01]?[0-9]|2[0-3])$

Your named Regex.IsMatch line returns true on every expression on my machine.

Upvotes: 0

PretzelSteelersFan
PretzelSteelersFan

Reputation: 111

This pattern will work. I ran into the same thing. It has to do with using parens to correctly establish the groupings. If the RegExAttribute can't figure it out, it seems to just quit at the pipe symbol.

Here's a unit test.

    [TestMethod]
    public void CheckHours()
    {
      var pattern = "([0-1][0-9])|(2[0-3])|([0-9])";
      int cnt = 0;

      var hours = new string[]
        { "1","2","3","4","5","6","7","8","9",
          "01","02","03","04","05","06","07","08","09",
          "10","11","12","13","14","15","16","17","18","19",
          "20","21","22","23" };

      var attribute = new RegularExpressionAttribute(pattern);
      bool isMatchOk = false;
      bool isAttrOk = false;

      foreach (var hour in hours)
      {
        isMatchOk = System.Text.RegularExpressions.Regex.IsMatch(hour, pattern);
        isAttrOk = attribute.IsValid(hour);

        if (isMatchOk & isAttrOk)
        { cnt += 1; }
        else
        { Debug.WriteLine(hour + " / " 
          + isMatchOk.ToString() + " / "
          + isAttrOk.ToString()); }
      }

      Assert.AreEqual(32, cnt);
    }

Upvotes: 2

Vinzz
Vinzz

Reputation: 4028

Don't know why this regex isn't correctly interpreted, but a solution is to implement a CustomValidation, which is pretty handy.

   [CustomValidation(typeof(MyCustomValidation), "Validate24Hour")]
     public string JobStartHour {...}

...

  public class MyCustomValidation
    {
        public static ValidationResult Validate24Hour(string candidate)
        {
            bool isValid = false;
         ...
            if (isValid)
            {
                return ValidationResult.Success;
            }
            else
            {
                return new ValidationResult("Error");
            }
        }
   }

Upvotes: 0

Rajeev Shenoy
Rajeev Shenoy

Reputation: 932

Try this:

[RegularExpression("2[0-3]|[01]?[0-9]", ErrorMessage = "Error")]
 public string JobStartHour {...}

Upvotes: 0

Related Questions