Reputation: 1293
Why RegularExpressionAttribute
validation doesn't compare the input string with the value of all matches concatenated?
I asked a question here about the scenario below, but I found a solution the next day and found it better to raise the issue here.
[Required(
AllowEmptyStrings = false,
ErrorMessage = "Required")]
[RegularExpression(
"^[^0]{1}|..+",
ErrorMessage = "Expressao Regular")]
public string EncryptedValue { get; set; }
Except by empty string or "0", the property should be valid in ModelState, but:
You can test HERE the expression and value.
Expression
^[^0]{1}|..+
Value
+iCMEBYZQtWbnU2RPX/MmqrDPuVJzSGGWhkFd+9/zpMbHVoOlZFuF9ND1xAxsQy3YFCPIsUBEgg2RJNkPefrmQ==
You will notice that the expression match, but with two matches. The first match itself are not equals to the input string, you need to concatenate both match value to reach that.
But apparently this is not done in the validation of ModelState, even with jquery.validate.unobtrusive this happens (with jquery, I need to click in submit button two times to see this, but it's happens).
Solution
You need to build an expression that match input string completelly in the first match.
When you build a expression to validate a field, every OR in your expression must match all the input string.
So whenever you mount an expression with OR operators, always mount from largest input to smallest input.
In this case:
From ^[^0]{1}|..+
to ..+|^[^0]{1}
Upvotes: 0
Views: 715
Reputation: 4075
So, if your regex is ^[^0]{1}|..+
And you value is : +iCMEBYZQt...
One match it will be +
, and the other: iCMEBY0ZQt...
.
The thing is, in the first part ^[^0]{1}
, your regex try to match any character that is not 0
, once (at the beginning of the line/string).
So, the regex looks the string and say something like:
Voilah!! I have something that is not zero, at the beginning and is one character, the character is :
+
, Thanks, thanks, where is my cookie?!
Also, the or instruction (|
) tells the regex to be more flexible about the patterns and is something like, If you don't find the first expression, don't feel bad, you also can look for this another thing. But once the regex has the first cookie doesn't make sense to go back and try to look again for the second expression (..+
) because already found a solution for the first expression, and the regex knows that there will not be extra cookies for the same work. So, life continues and we have to move on.
Here you can see that the first and the second expressions are independent ways to satisfy the regex.
https://regex101.com/r/UWtcF8/3
..+|^[^0]{1}
:
https://regex101.com/r/la3wDa/1
Where the order of the expressions are swapped. This is the same but the first expression that the regex will try to satisfy is ..+
which basically is give anything that involves 2 or more characters. So for example if you have 00
, the regex will say:
Yumm, cookies !
And that can be fine or not, it will depend on what you want to solve.
Now another option is:
^(?!0$).+
https://regex101.com/r/gxJdch/1
Where we are going to look for anything but a single zero
.
regex debugger
to learn more things about regex!)
https://regexper.com/
Upvotes: 0
Reputation: 1603
let's take a look at class System.ComponentModel.DataAnnotations.RegularExpressionAttribute . we are interested in the following method :
[__DynamicallyInvokable]
public override bool IsValid(object value)
{
this.SetupRegex();
string input = Convert.ToString(value, (IFormatProvider) CultureInfo.CurrentCulture);
if (string.IsNullOrEmpty(input))
return true;
Match match = this.Regex.Match(input);
if (match.Success && match.Index == 0)
return match.Length == input.Length;
return false;
}
In our case we have regex expression "^[^0]{1}|..+" and input string +iCMEBYZQtWbnU2RPX/MmqrDPuVJzSGGWhkFd+9/zpMbHVoOlZFuF9ND1xAxsQy3YFCPIsUBEgg2RJNkPefrmQ== . Regex validation return two matches, the first + (first symbol) and the second is the rest part. the first match length less then input string, that is why IsValid return false.
Why RegularExpressionAttribute validation doesn't compare the input string with the value of all matches concatenated? because it works with the first match
Upvotes: 2