views:

45

answers:

2

I found the answer to this, but it's a bit of a gotcha so I wanted to share it here.

I have a regular expression that validates passwords. They should be 7 to 60 characters with at least one numeric and one alpha character. Pretty standard. I used positive lookaheads (the (?= operator) to implement it:

(?=^.{7,60}$)(?=.*[0-9].*)(?=.*[a-zA-Z].*)

I checked this expression in my unit tests using Regex.IsMatch(), and it worked fine. However, when I use it in a RegularExpressionValidator, it always fails. Why?

+1  A: 

Have you tried

(?=^.{7,60}$)(?=.*[0-9].*)(?=.*[a-zA-Z].*).+
//                                        ^^

? The regex should need something to consume.

KennyTM
Right that's the problem. Just wanted to write up what I found as an answer. Thanks!
Jerph
A: 

It's strange that I've never run into this before, but it turns out that the RegularExpressionValidator doesn't use Regex.IsMatch or JavaScript's Regex.test() -- it checks for a capturing match that exactly equals the full tested value. Here's the relevant JS code:

var rx = new RegExp(val.validationexpression);
var matches = rx.exec(value);
return (matches != null && value == matches[0]);

So if the expression is all lookaheads (which match positions, not the actual text), it will fail. This is clearer with the example of an expression that only partially matches, e.g. with \d{5}, the value "123456" would fail. It's not just that it adds "^$" around your expression and does an IsMatch. Your expression actually has to capture.

The fix in my case is this expression:

(?=^.{7,60}$)(?=.*[0-9].*).*[a-zA-Z].*
Jerph