Этот шаблон будет работать.Я столкнулся с то же самое .Это связано с использованием паренов, чтобы правильно установить группировки.Если атрибут RegExAttribute не может это выяснить, похоже, он просто завершается при символе канала.
Вот модульный тест.
[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);
}