This article outlines a simple way to validate UK Postcodes with a .NET CustomValidator.
While it is easy enough to use a Regular Expression Validator to validate a postcode the user has input, there is a slight problem with this approach. Because the Regular Expression Validation control by default works only with case-sensitive patterns (certainly client-side), a user who enters their postcode in lower case will be told that it is invalid. This may be technically correct, but I would say from experience that a typical web visitor would miss this distinction and get frustrated. So validation like this may lose your site visitors or customers, and perhaps even result in angry support emails to deal with.
There are a couple of ways to get around this (disabling client-side validation and using the case sensitive off switch in the pattern, or perhaps converting the text to upper case using JavaScript as it is entered), but neither are very elegant.
The cleanest quick way to my mind to get this working smoothly is to use a CustomValidator. A more sophisticated solution would use a proper custom control, but for now, these steps will suffice.
1. TextBox and CustomValidator:
Here we add a TextBox, a CustomValidator control and a submit button to a page.
1: <asp:TextBox ID="PostcodeTextBox" runat="server"></asp:TextBox>
2: <asp:CustomValidator ID="CustomValidator" runat="server"
3: ClientValidationFunction="ValidatePostcode"
4: ControlToValidate="PostcodeTextBox"
5: OnServerValidate="CustomValidator_ServerValidate"
6: ErrorMessage="Invalid" />
7: <br />
8: <asp:Button ID="SubmitButton" runat="server" Text="Submit" />
The Custom Validator has two properties that determine the client and server-side validation functions that will be called.
2. Client validation
Rather than just testing for letters and numbers in the correct place, I use a slightly more sophsticated pattern that tests for all valid postcodes (excluding forces overseas):
(GIR 0AA|[A-PR-UWYZ]([0-9]{1,2}|([A-HK-Y][0-9]|[A-HK-Y][0-9]([0-9]|[ABEHMNPRV-Y]))|[0-9][A-HJKS-UW]) [0-9][ABD-HJLNP-UW-Z]{2})
Source: Wikipedia
So, using JavaScript for our client validation, and the expression above will give us the following function:
1: function ValidatePostcode(sender, args) {
2: args.IsValid = (args.Value.match(/(GIR 0AA|[A-PR-UWYZ]([0-9]{1,2}|([A-HK-Y][0-9]|[A-HK-Y][0-9]([0-9]|[ABEHMNPRV-Y]))|[0-9][A-HJKS-UW]) [0-9][ABD-HJLNP-UW-Z]{2})/i) != null);
3: return args.IsValid;
4: }
The /i modifier as the end of the expression marks it as case-insensitive, as required.
3. Server validation
A similar method performs the same validation on the server, for those visitors who have javascript disabled:
1: protected void CustomValidator_ServerValidate(object source, ServerValidateEventArgs args)
2: {
3: args.IsValid = new Regex("(GIR 0AA|[A-PR-UWYZ]([0-9]{1,2}|([A-HK-Y][0-9]|[A-HK-Y][0-9]([0-9]|[ABEHMNPRV-Y]))|[0-9][A-HJKS-UW]) [0-9][ABD-HJLNP-UW-Z]{2})", RegexOptions.IgnoreCase).IsMatch(args.Value);
4: }
Here, the RegexOptions.IgnoreCase argument marks the test as case-insensitive.
4. Complete test page
Though I prefer using code-behind, we can put all the steps together, resulting in a single test page like this:
1: <%@ Page Language="C#" %>
2: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3: <script runat="server">
4: protected void CustomValidator_ServerValidate(object source, ServerValidateEventArgs args)
5: {
6: args.IsValid = new Regex("(GIR 0AA|[A-PR-UWYZ]([0-9]{1,2}|([A-HK-Y][0-9]|[A-HK-Y][0-9]([0-9]|[ABEHMNPRV-Y]))|[0-9][A-HJKS-UW]) [0-9][ABD-HJLNP-UW-Z]{2})",
7: RegexOptions.IgnoreCase).IsMatch(args.Value);
8: }
9: </script>
10: <html xmlns="http://www.w3.org/1999/xhtml" >
11: <head runat="server">
12: <title>Postcode validation</title>
13: <script type="text/javascript">
14: function ValidatePostcode(sender, args) {
15: args.IsValid = (args.Value.match(/(GIR 0AA|[A-PR-UWYZ]([0-9]{1,2}|([A-HK-Y][0-9]|[A-HK-Y][0-9]([0-9]|[ABEHMNPRV-Y]))|[0-9][A-HJKS-UW]) [0-9][ABD-HJLNP-UW-Z]{2})/i) != null);
16: return args.IsValid;
17: }
18: </script>
19: </head>
20: <body>
21: <form id="form1" runat="server">
22: <div>
23: <asp:TextBox ID="PostcodeTextBox" runat="server"></asp:TextBox>
24: <asp:CustomValidator ID="CustomValidator" runat="server"
25: ClientValidationFunction="ValidatePostcode"
26: ControlToValidate="PostcodeTextBox"
27: ErrorMessage="Invalid" OnServerValidate="CustomValidator_ServerValidate" />
28: <br />
29: <asp:Button ID="SubmitButton" runat="server" Text="Submit" />
30: </div>
31: </form>
32: </body>
33: </html>