Monday, November 21, 2011

Diffference Between RegEx.IsMatch and the RegularExpressionAttribute

I was working on some code that stores a month as CCYYMM string. Of course I wanted to validate the string with Regex so I had the pattern

^20[0-2][0-9](0[1-9])|(1[0-2])$

Everything was fine as long as I was using Regex.IsMatch. The problems started when I used the RegularExpressionAttribute. Suddenly, I was getting errors everywhere. I constructed a little test to verify that there was a difference. What I found was that using the same string and pattern, yielded different results.

Here’s my unit test.

[TestMethod]
public void DifferenceBetweenIsMatchAndRegExAttribute()
{
  var pattern = "^20[0-2][0-9](0[1-9])|(1[0-2])$";
  int cnt = 0;
  var months = new string[]
  {
  "201001",
  "201002",
  "201003",
  "201004",
  "201005",
  "201006",
  "201007",
  "201008",
  "201009",
  "201010",
  "201011",
  "201012" };
  var attribute = new RegularExpressionAttribute(pattern);
  bool isMatchOk = false;
  bool isAttrOk = false;
 
  foreach (var month in months)
  {
    isMatchOk = System.Text.RegularExpressions.Regex.IsMatch(month, pattern);
    isAttrOk = attribute.IsValid(month);
 
    if (isMatchOk & isAttrOk)
    { cnt += 1; }
  }
 
  Assert.AreEqual(12, cnt);
}

You would expect the number of matches to be 12 but it’s actually 9. Why? Because the attribute is matching only the first half of our pattern. It stops at the pipe (|). To prove this, I flipped the sides of the pipe and got 3. If I add parens around both sides of the logical or I will get the answer I’m looking for.

^20[0-2][0-9]((0[1-9])|(1[0-2]))$

While it seems logical that the RegularExpressionAttribute would use Regex.IsMatch underneath, it apparently is not the case. I’m betting the reason has to do with JavaScript compatibility. Remember, the attribute must also validate client side.

Cheers!