In a previous post, I shared my
ArgumentValidator class as well as an overview of
Regular Expressions. I want to revisit this topic because of the fact that I hadn't really optimized it for ASP.NET 2.0. There are some features now offered in .NET 2.0 that help the process of keeping your messages standard. Also, I'd like to re-address some of the regular expression things as well.
Let's go ahead and create a new ASP.NET 2.0 Web Site. From here, we have the basic Default.aspx/cs. From this page we will add two controls to validate. They would look something similar to this:
<asp:TextBox ID="txtEmployeeID" runat="server" />
<asp:RegularExpressionValidator ID="valEmployeeID" ControlToValidate="txtEmployeeID" runat="server" />
<asp:TextBox ID="txtZipCode" runat="server" />
<asp:RegularExpressionValidator ID="valZipCode" ControlToValidate="txtZipCode" runat="server" />
Now that we have the web page, let's go ahead and initialize the validator controls with some of the more constant data. I would rather not hard code certain validations in the UI as they can change. I also do not want to hard code the actual error message displayed should the validations fail. This is especially important in globalized applications.
private void InitializeControls()
{
this.valEmployeeID.Text = ResourceMessageManager.EmployeeIDInvalidMessage;
this.valEmployeeID.ValidationExpression = ArgumentValidator.EmployeeIDExpression;
this.valZipCode.Text = ResourceMessageManager.ZipCodeExceptionMessage;
this.valZipCode.ValidationExpression = ArgumentValidator.ZipCodeExpression;
} // method - InitializeControls
Now what I did here is I set the validator text to constants that I am reading in from my Strings.resx file. Visual Studio automatically creates a Resources.Strings hard class for you to use. The reason why I still use ResourceMessageManager is that some of the messages may require some additional data in order to become really useful. An example of this would be a max length violation with a dynamic input as to the maximum length. You would certainly like to know in an error message what the string cannot exceed. Remember, useful error messages are always nice!
Now that we covered that part, let's look at how the code changed from one version to this one. Refer to the previous post for the code listed.
public static class ResourceMessageManager
{
private static string FormatString(string message, params object[] args)
{
return string.Format(CultureInfo.InvariantCulture, message, args);
} // method - FormatString(string, params string[])
public static string ArgumentNullExceptionMessage
{
get { return Strings.ArgumentNullExceptionMessage; }
} // property - ArgumentNullExceptionMessage
public static string StringEmptyNullExceptionMessage
{
get { return Strings.StringEmptyNullExceptionMessage; }
} // property - StringEmptyNullExceptionMessage
public static string StringTooLongExceptionMessage(int maxLength)
{
return FormatString(Strings.StringTooLongExceptionMessage, maxLength);
} // property - StringTooLongExceptionMessage
public static string UnexpectedTypeExceptionMessage
{
get { return Strings.UnexpectedTypeExceptionMessage; }
} // property - UnexpectedTypeExceptionMessage
public static string IntOutOfRangeExceptionMessage
{
get { return Strings.IntOutOfRangeExceptionMessage; }
} // property - IntOutOfRangeExceptionMessage
public static string ZipCodeExceptionMessage
{
get { return Strings.ZipCodeExceptionMessage; }
} // property - ZipCodeExceptionMessage
public static string EmployeeIDInvalidMessage
{
get { return Strings.EmployeeIDInvalidMessage; }
} // property - EmployeeIDInvalidMessage
} // class - ResourceMessageManager
See, what you can see, it has been greatly simplified. Now, let's take a look at what has been changed with ArgumentValidatior. What I did here was add some constant regular expression validations as well as some other functions that would be useful going forward. Let's take a look at that:
public static class ArgumentValidator
{
public const string EmployeeIDExpression = @"^\d{8}";
public const string ZipCodeExpression = @"^(\d{5}-\d{4}|\d{5}|\d{9})$|^([a-zA-Z]\d[a-zA-Z] \d[a-zA-Z]\d)$";
public const string SocialSecurityNumberExpression = @"^\d{3}-\d{2}-\d{4}$";
public const string UrlExpression = @"^(ht|f)tp(s?)\:\/\/[0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*(:(0-9)*)*(\/?)([a-zA-Z0-9\-\.\?\,\'\/\\\+&%\$#_]*)?$";
public const string PasswordExpression = @"(?!^[0-9]*$)(?!^[a-zA-Z]*$)^([a-zA-Z0-9]{8,10})$";
public static bool IsMatch(string input, string pattern)
{
CheckForNullReference(pattern, "pattern");
CheckForNullReference(input, "input");
return Regex.IsMatch(input, pattern);
} // method - IsMatch
} // class - ArgumentValidator
There are many regular expressions out there and many good resources to make rock solid expressions. I'd rather learn these myself instead of relying on the tools already out there because they are always handy in the future. Should you need to search for some pre-existing ones,
Regular Expression Library is not a bad resource.
So, in conclusion, I fixed a few things to make things more ASP.NET 2.0 friendly. Once you have the validation pattern down, it's quite easy to keep going.