The built-in server controls in ASP.NET such as RequiredFieldValidator, RegularExpressionValidator, CompareValidator, etc. can greatly help developers to build input validation quickly. However, in some scenarios, those built-in validators are not enough, that is when the CustomValidator comes in. For example, if you are building an eCommerce application that needs to validate user’s credit card number. Instead of passing any number that user enters to payment gateway to validate the card number, your application should perform some preliminary validation check on the number first. This will not only increase the security of your application, but also improve the performance. Here I will show you how to use ASP.NET CustomValidator to check if the credit card number that the user enters is well formatted.
Disclaimer: the credit card number validator I am showing here will only check to see if the number is well-formatted, instead of a randomly generated number. A well-formatted credit card number meets the requirements of most credit card companies, but it does not mean the number is associated with an active account, or with an account with enough fund. Therefore, your application still needs to communicate with your payment gateway to validate the credit card number.
Credit card companies usually use Luhn Algorithm to distinguish well-formatted numbers from randomly generated numbers. Rosetta Code web site has a detailed explanation of how to implement Luhn test in different languages. This post is based on the implementation of Luhn test in JavaScript and C#.
Now let’s get started.
1. Add a CustomValidator to you web form that validates a TextBox server control on the form.
<asp:CustomValidator runat="server" ID="cvCreditCardNumberValidator" ControlToValidate="txtCreditCardNumber" ErrorMessage="Invalid credit card number." CssClass="error" Display="Dynamic" OnServerValidate="ValidateCreditCardNumber" ClientValidationFunction="validateCreditCardNumber" ValidationGroup="Card" ValidateEmptyText="True" > </asp:CustomValidator>
2. Notice ClientValidationFunction points to a client side validation function, here I call it “validateCreditCardNumber“. Let’s add this client side JavaScript function:
<script type="text/javascript"> function validateCreditCardNumber(sender, args) { var patt = new RegExp("[^0-9 -]+"); if (patt.test(args.Value) == true) { args.IsValid = false; } else { var temp = String(args.Value).replace(/[^0-9]/g, ""); if (temp.length < 10) { args.IsValid = false; return; } var s1 = 0; var s2 = 0; var reverse = temp.split("").reverse().join(""); for (var i = 0; i < reverse.length; i++) { var digit = parseInt(reverse.charAt(i), 10); if (i % 2 == 0) { s1 += digit; } else { s2 += 2 * digit; if (digit >= 5) { s2 -= 9; } } } args.IsValid = ((s1 + s2) % 10 == 0); } } </script>
3. Now let’s create a function on the server side, say called “ValidateCreditCardNumber“, and assign this function to OnServerValidate property in the CustomValidator control above.
protected void ValidateCreditCardNumber(object sender, ServerValidateEventArgs args) { if (Regex.IsMatch(args.Value, @"[^0-9 -]+") == true) { args.IsValid = false; } else { string inString = Regex.Replace(args.Value, @"[^0-9]", ""); if (inString.Length < 10) { args.IsValid = false; } else { char[] array = inString.ToCharArray(); Array.Reverse(array); string reverse = new String(array); int s1 = 0, s2 = 0; for (int i = 0; i < reverse.Length; i++) { int digit = 0; if (int.TryParse(reverse[i].ToString(), out digit)) { if (i % 2 == 0) { s1 += digit; } else { s2 += 2 * digit; if (digit >= 5) { s2 -= 9; } } } else { args.IsValid = false; return; } } args.IsValid = ((s1 + s2) % 10 == 0); } } }
4. Add an event handler to handle the button click event.
protected void btnValidateCreditCard_Click(object sender, EventArgs e) { if (Page.IsValid) { this.lblCreditCardValidationResult.Visible = true; this.lblCreditCardValidationResult.Text = "The credit card number is valid.<br />"; this.lblCreditCardValidationResult.CssClass = "valid"; } else { this.lblCreditCardValidationResult.Visible = true; this.lblCreditCardValidationResult.Text = "The credit card number is not valid. <br />"; this.lblCreditCardValidationResult.CssClass = "error"; } }
That is. Here is a live demo to show you how this validator works. If you need to help to understand the source code, please put your question in the comment.