Geeks With Blogs
Blog Moved to http://podwysocki.codebetter.com/ Blog Moved to http://podwysocki.codebetter.com/
In previous posts, I talked about one of the major pillars of security is to never trust user input.  We need to verify at every level the data that is in our system.  One way of doing this is to implement a validation class that does the heavy lifting for you.
 
I have written a common class that follows the pattern introduced in the Common library from the Enterprises Library to do just this task.  This class validates the parameters and throws the appropriate exception type based upon the values given.
 
Let's go through the code to see what it does:
 
public static class ArgumentValidator
{
     public static void CheckForNullReference(object value, string name)
     {
          if(name == null)
               throw new ArgumentNullException(name, ResourceMessageManager.ArgumentNullExceptionMessage);
 
          if(value == null)
               throw new ArgumentNullException(name, ResourceMessageManager.ArgumentNullExceptionMessage);
     } // method - CheckForNullReference
 
     public static void CheckForEmptyOrNullString(string value, string name)
     {
          CheckForNullReference(name, "name");
 
          if(value == null || value.Length == 0)
               throw new ArgumentException(ResourceMessageManager.StringEmptyNullExceptionMessage, name);
     } // method - CheckForEmptyOrNullString
 
     public static void CheckForStringLength(int maxLength, string value, string name)
     {
          CheckForNullReference(name, "name");
          CheckForNullReference(value, name);
          CheckForIntRange(0, int.MaxValue, maxLength, "maxLength");
 
          if(value.Length > maxLength)
               throw new ArgumentException(ResourceMessageManager.StringTooLongExceptionMessage, name);
     } // method - CheckForStringLength
 
     public static void CheckForExpectedType(Type type, object value, string name)
     {
          CheckForNullReference(name, "name");
          CheckForNullReference(type, "type");
          CheckForNullReference(value, "value");
 
          if(!type.IsAssignableFrom(value.GetType()))
               throw new ArgumentException(ResourceMessageManager.UnexpectedTypeExceptionMessage, name);
     } // method - CheckForExpectedType
 
     public static void CheckForIntRange(int min, int max, int value, string name)
     {
          CheckForNullReference(name, "name");
 
          if(value < min || value > max)
               throw new ArgumentException(ResourceMessageManager.IntOutOfRangeExceptionMessage, name);
     } // method - CheckForIntRange
 
     public static void CheckForInvalidEnum(Type type, object value, string name)
     {
          CheckForNullReference(name, "name");
          CheckForNullReference(value, "value");
          CheckForNullReference(type, "type");
 
          if(!Enum.IsDefined(type, value))
               throw new InvalidEnumArgumentException(name, (int)value, type);
     } // method - CheckForInvalidEnum
} // class - ArgumentValidator
 
As each method is called, this class would be used to validate all incoming data for type, length, etc to check for violations.  I've used this class and argument validation pattern for some time now and has saved me a ton of coding. 
 
I've used a class called ResourceMessageManager.  This class uses a file called strings.resx that contains the constants for my error messages and formats the values appropriately.  As you will note that the Podwysocki.strings is made up from Podwysocki which is my default namespace and strings is the name of the file.  Let's go over some of that code:
 
internal static class ResourceMessageManager
{
     private static ResourceManager manager = new ResourceManager("Podwysocki.strings", typeof(ResourceMessageManager).Module.Assembly);
 
     private static string GetString(string logicalName)
     {
          return manager.GetString(logicalName, CultureInfo.CurrentCulture);
     } // method - GetString(string)
 
     private static string GetString(string logicalName, params string[] args)
     {
          return string.Format(CultureInfo.InvariantCulture, manager.GetString(logicalName, CultureInfo.CurrentCulture), args);
     } // method - GetString(string, params string[])
 
     internal static string ArgumentNullExceptionMessage
     {
          get { return GetString("ArgumentNullExceptionMessage"); }
     } // property - ArgumentNullExceptionMessage
} // class - ResourceMessageManager
 
Also, you will notice that the ArgumentNullException property looks up the ArgumentNullException string literal in the strings.resx file.  I always include these files in my projects as ways to localize my resources.  I haven't used the built-in capabilities in Visual Studio 2005 just yet, but I hope to utilize some of that functionality for my localized resources.
Posted on Friday, June 2, 2006 2:53 PM .NET , C# | Back to top


Comments on this post: .NET Best Practices - Constrain User Input

No comments posted yet.
Your comment:
 (will show your gravatar)


Copyright © Matthew Podwysocki | Powered by: GeeksWithBlogs.net