N-Layered Web Applications with ASP.NET 3.5 Part 2: Introducing the Validation Framework


NOTE: the concepts presented in this article are now considered obsolete possibly because better alternatives are available.

Update!! - I have written a new series on N-Layer design targeting ASP.NET 4.5 and Entity Framework 5. You can check out the new series here.

Update 02/03/2009: There is now a VB.NET version of the application available thanks to Sven Huijbrechts from ClearMedia bvba. Check it out at the Downloads section at the end of this article

Note: this is part two in a series of six. If you rather read this entire series off-line, you can buy the series as a convenient PDF document that comes with the full source. Besides the convenience, buying the PDF will also make you feel good as it shows your appreciation for the articles and helps me pay the bills for my server and hosting so I can keep running imar.spaanjaars.com and continue to provide you with great content. For more details, check out this post that shows you how you can buy the entire series right now.

This is part 2 of a six-part series of articles on N-Layer design using ASP.NET 3.5. This article series builds on top of my article series on N-Layer design that I released in early 2007. If you haven’t already done so, be sure to check out these articles first, as a lot of code and concepts used in this new series is explained in detail in the older series.

This installment and the next one deal with validation and show you how to implement a Validation Framework into your application in order to stop unwanted data from getting into your database.

After you’ve read the previous series, be sure to check out part 1 of this new series first, as it gives you an overview of the design of the new application, what’s new compared to the previous version, and what you can expect from this entire article series. Here’s a complete list of all the articles in both series that are currently available:

Quick Links to All Articles

Previous Series
Building Layered Web Applications with Microsoft ASP.NET 2.0 - Part 1
Building Layered Web Applications with Microsoft ASP.NET 2.0 - Part 2
Building Layered Web Applications with Microsoft ASP.NET 2.0 - Part 3
Custom Sorting with N-Layer Design Classes and the GridView

Current Series
N-Layered Web Applications with ASP.NET 3.5 Part 1: General Introduction
N-Layered Web Applications with ASP.NET 3.5 Part 2: Introducing the Validation Framework
N-Layered Web Applications with ASP.NET 3.5 Part 3: Advanced Validation Topics
N-Layered Web Applications with ASP.NET 3.5 Part 4: Sorting, Paging and Filtering
N-Layered Web Applications with ASP.NET 3.5 Part 5: Dealing with Concurrency
N-Layered Web Applications with ASP.NET 3.5 Part 6: Security

Remember: you can buy the full set of articles right now if you want to say "thanks" in return for these articles or you just want to have the whole set as a single, convenient PDF.

Part 2, which you are reading now, deals with Validation. Validation is at the core of most business applications. Without any form of validation you’re pretty much lost and you’ll find your database flooded with invalid data, ranging from simple typos to complete viruses injected using SQL injection. So, the necessity of validation is beyond dispute, but how do you implement it? As always, you have many different options.

Introducing Validation

It’s probably no surprise that in a multi layer application you can add validation code to all of your layers. In case of the Contact Manager Application it means you can add it to the UI Layer, the Business Layer and to the Data Access Layer. In order to understand the benefits and possibilities of each of these options, it’s important to look at them in some detail.

Validation in the Presentation Layer

One common technique for validation in the Presentation Layer is using the ASP.NET Validation Controls. When they were introduced in ASP.NET 1.0 they really meant a boost in developers’ productivity and site security as they removed the need for a lot of custom (and often forgotten) validation code. (They didn’t work on browsers other than Internet Explorer but that has been fixed a long time ago). The Validation Controls are simple to use, provide validation services at both the client (for a good user experience) and at the server (to protect your data) and provide enough features to enable most of your validation needs in the Presentation Layer. I emphasize the Presentation Layer for a reason, as you’ll see in a bit. In its simplest form, validation using the ASP.NET controls only requires a few lines of code. In the following example you see a simple TextBox, a RequiredFieldValidator and a Button. The RequiredFieldValidator ensures at the client that the user has entered a value before the form can be submitted.

	<asp:TextBox ID="TextBox1" runat="server" />
<asp:RequiredFieldValidator ID="reqVal" runat="server" 
       ErrorMessage="Please enter a value" ControlToValidate="TextBox1" />
<asp:Button ID="Button1" runat="server" Text="Button" />

Whether JavaScript is turned on or off at the client, you can check the validity of the page on the server using the IsValid property of the Page class:

	protected void Button1_Click(object sender, EventArgs e) 
{ 
  if (Page.IsValid) 
  { 
    // TextBox1 has a value so we can proceed.
  } 
}

So, you may ask, if this is all so easy to implement, why not use it for all your sites and applications? The answer is: it validates on the Presentation Layer, and on the Presentation Layer only. While this is nice for some simpler sites as the original Contact Manager Application, it won’t cut it in larger applications where the Bll or Business Entities projects are shared by other front ends. For example, what happens when you have a Command Line tool for bulk importing contacts from a text file? What happens when you allow your users to submit changes or get the latest details of your contacts through web services? Or how would you ensure proper validation when you decide to build a simple Win Forms data entry application to allow your users to enter data on a desk top application?

In all of these cases, you would need to rewrite your validation mechanism. While in itself this is not so bad (you need a way to overcome the differences in presentation between a Web Application and a Win Forms Application anyways) it poses a bigger issue than just more work: developers may — deliberately or not — forget to implement validation in the presentation or front end layer. So, your cool Web Service or Command Line Import Tool may work today, but may (and probably will) fail miserably tomorrow, possibly because the contact records file you’re trying to import has changed or contains invalid data. So, you’ll need to look into validation in deeper layers - like the business and data layer - to better protect your data and its integrity. I’ll show you the possibilities of validation in the data layer first, and then show you how I would have coded the business layer before I started using the Validation Framework.

Validation in the Database

I love validation at the data layer. It’s like a big, aggressive pit-bull guarding your house, not allowing anyone in except for his boss. It’s your last line of defense. In fact, it’s your last opportunity to sanitize or reject invalid data, before it hits your main database, possibly corrupting your important business data, leading to losses, bankruptcies, or other unforeseen disasters.

Validation in the database is pretty easy to implement. For example, for a required field whose value comes from a different table, all you need to do is connect a few tables to create a relationship between a primary key and a foreign key. Likewise, adding a business rule like “this field must have a value between 0 and 100” is as simple as adding a Check Constraint, either through the SQL Server Management Studio interface or through some custom T-SQL code:

	ALTER TABLE  dbo.Category ADD CONSTRAINT
CK_Category CHECK (SortOrder >= 0  AND SortOrder <= 100)
GO      

With this constraint, SQL Server will check the value of SortOrder any time it’s set (with INSERT and UPDATE statements) and reject the value if it’s not between 0 and 100.

This is just a simple example, but you could easily apply these kinds of rules to many other columns or relationships, protecting your data at the “deepest” level in your application architecture. So, judging from this, it seems that validating your data at the database level is a smart thing to do.

In many ways, it is. Except it has this huge issue: it doesn’t lend itself very well to be displayed in the Presentation Layer. Typically, when you violate a database rule, you get a nerdy looking error message like this one:

Msg 515, Level 16, State 2, Line 1
Cannot insert the value NULL into column 'ContentTypeId', table 'Test.dbo.Category'; column does not allow nulls. INSERT fails.
The statement has been terminated.


Useful as this may be to us, web and database developers, I am sure you agree your users typically expect something else. Something along the lines of “You forget to choose a type of content for this article. Please choose an option from the Type drop down and try again. And if you forget it again, it’s *you* who gets terminated. Make no mistake about it”. Whatever your house style of communicating with users, you need a way to translate these database errors into some stuff that users can understand. While you could catch these messages from your .NET Connection objects, convert them into something your user understands and then display them in the Presentation Layer, this is not an easy or straightforward thing to do.

Another downside is the moment where this validation takes places. Ideally, you want to validate the data before you start hitting the database, minimizing network overhead and processor time on the database server. When you validate data in the database, you’re incurring too much unnecessary overhead.

So, while database validation is great and should always be used no matter where else you’re validating your data, there’s another, more user friendly way to approach data validation. I am sure you saw this one coming, but if not, the answer is: Validation in the Business Layer.

Validation in the Business Layer

In my opinion, validation in the Business Layer is a very natural thing to do. It feels like slipping into a pair of your favorite sneakers: you just know beforehand that they’ll fit exactly right. The Business Layer is where you work with your data, where you accept it from the UI before you move it on to the database, it’s where you determine who can see what or make what changes and so on. Basically, the Business Layer is where all your data comes together in order to represent something useful. So, it makes a lot of sense to implement validation logic in there as well.

In my original article series I left out validation as I wanted to keep things simple — at an entry level that anyone could follow. But I did get a lot of requests for it; where to implement it, how to do it exactly and so on. Usually, I recommended implementing a private Validate method that would throw an exception when any of your business rules was invalid. For example, you could call the following Validate method from the Save method of the EmailAddress class:

	private static void Validate (EmailAddress myEmailAddress) 
{ 
  if (myEmailAddress.ContactPersonId <= 0) 
  { 
    throw new InvalidOperationException("Can't save an EmailAddress 
              without a valid ContactPersonId."); 
  } 

  if (string.IsNullOrEmpty(myEmailAddress.Email))
  { 
    throw new InvalidOperationException("Can't save an EmailAddress 
              without an e-mail address."); 
  } 

  if (!IsValidEmailAddress(myEmailAddress.Email)) 
  { 
    throw new InvalidOperationException("Can't save an EmailAddress 
              without a valid e-mail address."); 
  } 
} 

public static int Save(EmailAddress myEmailAddress) 
{ 
  Validate (myEmailAddress);
  myEmailAddress.Id = EmailAddressDB.Save(myEmailAddress);
  return myEmailAddress.Id; 
} 

While this approach certainly works, it has a few drawbacks. First of all, it means writing lots of repetitive and boring code. Since it’s so boring to write, it’s easy to forget to validate one or more business rules. Secondly, it uses an annoying “one by one” pattern, where the error conditions are fixed one at a time. You get an error about the contact person ID, fix it and try again, only to be greeted by an error stating that the e-mail address is invalid. Finally, it uses exception based validation which means you need to use try/catch blocks whenever you’re calling methods that trigger the validation.
Obviously, it would be a lot easier if you could present a complete list with broken business rules in the user interface (or wherever you need it).

Wouldn’t it be great if you could do something like this in the code behind of your pages (assuming you have a ContactPerson instance stored in myContactPerson:

	if (myContactPerson.Validate()) 
{ 
  ContactPersonManager.Save(myContactPerson);
} 
else
{ 
  lstErrors.DataSource = myContactPerson.BrokenRules;
  lstErrors.DataBind();
} 

And wouldn’t it be great if all you need to do to display a list of errors is to drop a data-bound control like a BulletedList on your page (lstErrors in the example above) that would take care of displaying the errors like this (or any other way you prefer of course):

  • Enter your first name.
  • Enter your last name.
  • Enter your date of birth.

And finally, I am sure you agree it would be very useful if that list of errors would automatically adapt to the language the user has chosen.

Read on to see how you can accomplish this with a relatively small amount of code.

Introduction to the Validation Framework

As I mentioned in the first part of this series, the Validation Framework used in the Contact Manager Application is inspired by the work by AzamSharp in his article “Creating a Domain Object Validation Framework”. (Or maybe by Jan Tielens; see here for more information). Before I read AzamSharp’s article on validation, I had been working on various flavors of validation myself, including some using custom attributes on properties (I am a big fan of attributes as you can find out here and here).

My earlier solutions typically required a lot more code than the one presented by AzamSharp. But even though I like this framework, it has a few shortcomings that I wanted to address (lack of built-in localization behavior, no Validate() method on the business entity but on a separate ValidationEngine instead, generics List<T> types in the public API and a BusinessBase class which in reality was more like a ValidationBase. Over the next couple of sections I’ll show you how I fixed these issues.

Design of the Validation Framework

Figure 15 shows a class diagram of a typical ContactPerson class that inherits from the ValidationBase class. (Later you’ll see another intermediate class between these two called BusinessBase providing translation services and other shared behavior; for now, just focus on the main ValidationBase class). This ValidationBase contains one property (BrokenRules which is described later) and two important methods: GetValidationMessage and Validate.

The ContactPerson Class Inherits from ValidationBase
Figure 15 – The ContactPerson Class Inherits from ValidationBase

It’s this latter method that you saw at work when I showed you a quick example of the Validation Framework:

	if (myContactPerson.Validate()) 
{ 
  ContactPersonManager.Save(myContactPerson);
} 

So, how does the Validate method know whether the ContactPerson is valid? Simple: it asks all of its properties if they are valid or not. Normally, properties are not able to express whether they contain a valid value or not. However with the use of the Attribute class this is easy to implement. I’ll show you a quick example first, then dig deeper into the architecture later, explaining how things work together.

If you look in the code for the ContactPerson class in the BusinessEntities namespace you’ll find the following property for the contact’s FirstName:
 

	/// <summary>
/// Gets or sets the first name of the contact person.
/// </summary>
[NotNullOrEmpty(Key = "FirstNameNotEmpty")] 
public string FirstName { get; set; }

Notice the NotNullOrEmpty attribute on top of the property. Basically this says: when you try to validate me, I’ll be valid when I contain a value that is not null and not an empty string. Likewise, the Email property looks like this:

	/// <summary>
/// Gets or sets the actual e-mail address text of the e-mail address.
/// </summary>
[NotNullOrEmpty(Key = "EmailNotEmpty")] 
[ValidEmail(Key = "EmailNotValid")] 
public string Email { get; set; }

These two attributes require you to enter a value for the e-mail address that is not null or empty. On top of that, you have to make sure that the Email property contains a valid e-mail address as well (that is, it must contain an @ symbol, a period, contain a user and a domain name or IP address and so on).

The Key property of the attribute is used as the localization key for multi-lingual web sites. If you don’t have a localized site, you can add the validation message to the Message property instead:

	[NotNullOrEmpty(Message = "Enter your first name.")] 
public string FirstName { get; set; }

You add these attributes to your code at development time, simply by typing their code on top of a property. You’ll see more examples of these attributes, how to create and apply your own and an explanation of the Key property later. For now, I’ll give you an overview of how this validation process works first.

From the Attributes Class to the Validate() Method to the BrokenRules Class

Imagine you have a simple class with a single property with a single validation attribute that marks the field as required. Something like the following User class will do:

	public class User : ValidationBase
{  
  [NotNullOrEmpty(Message = "Please enter a user name.")] 
  public string UserName { get; set; } 
}

Also imagine that you have a new instance of this class without the UserName set. That means that the class should be considered invalid and that its BrokenRules collection should contain a BrokenRule instance indicating the reason why the rule is broken.

You could write a quick unit test to check whether this is the case or not:

	[TestMethod] 
public void NewUserIsInvalid() 
{ 
  User myUser = new User(); 
  Assert.IsFalse(myUser.Validate());
  Assert.IsTrue(myUser.BrokenRules.FindByPropertyName("UserName").Count > 0);
}

Straight forward as the example may be from a code perspective, a lot is going on under the hood to make it work. Here’s a run-down of the numerous steps involved:

  1. A new user is instantiated. Because the UserName property is defined as an automatic property, it will simply default to null.
  2. The Validate method is accessed (more later on why this is a method and not a property).
  3. If Validate() is overridden in the child class, that version is called. Since that’s not the case here, the version of Validate in ValidationBase is called.
  4. This method first gets rid of any existing BrokenRule instances by calling Clear on the BrokenRules collection.
  5. Then Validate uses reflection to get a list of all properties that require validation and tries to validate them:
    1. First, it gets a list of all the public and instance properties of the class.
    2. It then loops through each of these properties and for each property it loops through its validation attributes.
    3. For each attribute it checks if it’s valid by calling IsValid on the attribute.
    4. The specific attribute checks the value of the property it’s attached to and determines if it meets the criteria set for the property.
    5. When the attribute determines the value is not valid, a new BrokenRule instance is filled with the error message that is retrieved from the attribute and the property name retrieved from the property. This BrokenRule instance is then added to the BrokenRules collection of the User instance.
  6. Eventually, Validate returns false because the UserName rule is broken. This causes the Assert to succeed.
  7. The BrokenRules collection should now contain a BrokenRule for the UserName property. Calling FindByPropertyName gives you a new BrokenRules collection containing all the broken rules for the requested property. (Notice that the unit test is the only piece of code that uses a string literal to refer to a property name. All other code in the Validation Framework uses strongly typed objects and members.).

Obviously, this is just a high-level overview of the process. The next couple of sections dig deeper in the actual code for the classes that make up this Validation Framework.

The ValidationBase Class and the Validate Method

The ValidationBase class is the base class for all classes that want to implement validation. Figure 16 shows its class diagram:

The ValidationBase Class
Figure 16 – The ValidationBase Class

This class is marked as abstract which means you can’t create instances of it. This makes perfect sense as there is no point in having ValidationBase instances in your application, It’s only purpose (and a good one at that) is to serve as a base class for other classes in your application, like a ContactPerson or an EmailAddress.

Besides the BrokenRules property, ValidationBase contains two methods: Validate() and GetValidationMessage.

The Validate method is responsible for checking the validity of all the properties on a business entity (a class that ultimately inherits from ValidationBase). It does this by executing LINQ queries to find all public properties and their validation attributes. The method has two overloads which are implemented as follows:

	public virtual bool Validate() 
{ 
  return Validate(true); 
} 


public virtual bool Validate(bool clearBrokenRules) 
{ 
  if (clearBrokenRules) 
  { 
    this.BrokenRules.Clear();
  } 
  PropertyInfo[] properties = this.GetType().GetProperties(
          BindingFlags.Public | BindingFlags.Instance);
  var valProps = from PropertyInfo property in properties 
                 where property.GetCustomAttributes(
                    typeof(ValidationAttribute), true).Length > 0 
                 select new
                 { 
                   Property = property, 
                   ValidationAttibutes = property.GetCustomAttributes(
                     typeof(ValidationAttribute), true) 
                 }; 

  foreach (var item in valProps) 
  { 
    foreach (ValidationAttribute attribute in item.ValidationAttibutes) 
    { 
      if (!attribute.IsValid(item.Property.GetValue(this, null))) 
      { 
        string message = string.Empty;
        if (attribute.Key != string.Empty)
        { 
          message = GetValidationMessage(attribute.Key); 
        } 
        else
        { 
          message = attribute.Message; 
        } 
        this.BrokenRules.Add(new BrokenRule(item.Property.Name, message ));
      } 
    } 
  } 
  return (this.BrokenRules.Count == 0);
}

(Note: I’ll discuss the parameterless overload and the use of the clearBrokenRules parameter in part 3 of this article series.)

First, an array of all the public instance properties is retrieved using the GetProperties method of the Type class. A LINQ query then gets all the properties that have at least one ValidationAttribute (a custom Attribute defined in the Spaanjaars.Validation namespace) applied. The query returns an anonymous type with two properties: the property itself and an object array of the validation attributes.

The foreach code block then loops through each of the attributes and calls its IsValid method and passes that method the value of the property. If the underlying is not valid according to the IsValid method, a new BrokenRule instance is added the BrokenRules collection. If the attribute’s Key property is set, GetValidationMessage is called to translate the key into an error message. If the Key is not set, the Message property of the attribute is used. The GetValidation method is useful if you want to localize your application or if you want to store all your validation messages in a central location. Localization is discussed later in this article.

To see how this works, take another look at the User class:

	public class User : ValidationBase
{ 
  [NotNullOrEmpty(Message = "Please enter a user name.")] 
  public string UserName { get; set; } 
}

When Validate is called on an instance of User, the collection of properties will contain only one item: the UserName property. The collection of validation attributes on this property will be one as well: the NotNullOrEmpty validation attribute. This attribute returns false from its IsValid method when the property’s underlying value is null or an empty string. It also adds a BrokenRule with the error message “Please enter a user name.” to the BrokenRules collection.

To understand how the Validate method is able to determine the validity of the properties, you need to look at the ValidationAttribute base class.

The ValidationAttribute base class

The ValidationAttribute class is an abstract class with one method and two properties, depicted in Figure 17:

The ValidationAttribute Class
Figure 17 – The ValidationAttribute Class, the Base Class for all Custom Validation Attributes

The code for the class looks like this:

	public abstract class ValidationAttribute : System.Attribute
{
  private string _key; 
  private string _message; 
  
  public abstract bool IsValid(object item); 
  
  public string Message 
  { 
    get { return _message; } 
    set
    { 
      if (!string.IsNullOrEmpty(_key))
      { 
        throw new ArgumentException(
            "Can't set Message when Key has already been set."); 
      } 
      _message = value;
    } 
  } 

  public string Key 
  { 
    get { return _key; } 
    set
    { 
      if (!string.IsNullOrEmpty(_message))
      { 
        throw new ArgumentException(
            "Can't set Key when Message has already been set."); 
      } 
      _key = value;
    } 
  } 
}

The Message and Key properties are mutually exclusive and are used to determine the actual validation message or a key defined in a resource file that holds the (localized) validation message. Classes that inherit from ValidationBase need to set either the Key or the Message property using named parameters (or through a constructor) when applying the relevant attributes to the properties.

Since IsValid is defined as abstract, it has no behavior of its own in the ValidationAttribute base class. However, custom attributes inheriting from ValidationAttribute are required to implement the method as you’ll see next.

Creating Custom Validation attributes

The ValidationAttribute is an abstract class and as such cannot be instantiated or used as an attribute on a property in a business entity. It serves as a base class for your own validation attributes that do provide specific validation behavior. Consider for example the NotNullOrEmpty attribute. This attribute can be used to check whether the property that the attribute is attached to contains a value that is not null or empty. The code for this attribute looks like this:

	[AttributeUsage(AttributeTargets.Property)]
public sealed class NotNullOrEmptyAttribute : ValidationAttribute
{ 
  public override bool IsValid(object item) 
  { 
    if (item is string) 
    { 
      return !string.IsNullOrEmpty(item as string);
    } 
    return item != null; 
  } 
}

The first line with the AttributeUsage attribute tells the compiler to make sure the NotNullOrEmpty attribute can only be applied to properties. You’ll get a compile error if you try to apply it to another class member like a method.

The only method in this class is an override of IsValid. As a parameter it accepts an object that contains the underlying value of the property being validated. In the case of the earlier example with the User class, this is the value of the UserName property (null, an empty string or a valid value). Inside the method you can write whatever behavior you need for validation. In the case of the NotNullOrEmpty attribute, the code checks to see if the item is a string and then delegates responsibility of the check to the IsNullOrEmpty methods. If the item is not a string, it’s simply compared with null.

The cool thing of this framework is that you can pretty much validate anything you want (as long as the rules are related to a single property). For example, a ValidEmailAddress attribute that validates whether a property’s value represents an e-mail address could look like this:

	[AttributeUsage(AttributeTargets.Property)]
public sealed class ValidEmailAttribute : ValidationAttribute
{ 
  public override bool IsValid (object item) 
  { 
    string tempValue = item as string; 
    if (string.IsNullOrEmpty(tempValue))
    { 
      return true; 
    } 
    return (tempValue).Contains("@"); 
  } 
}

Obviously, this is a simplified example as the code only checks whether the value contains an @ symbol, but I am sure you get the idea. You could easliy enhance this method by using a strong regular expression that checks the true validity of an e-mail address (syntactically, not whether it exists or not). Notice how this method returns true when the item contains null or an empty string. While that certainly doesn’t represent a valid value, I decided to implement it like this because it allows me to make fields optional. So, the e-mail address can be empty, but *if* it’s filled in, it has to be valid. To define a required e-mail address, you simply add a NotNullOrEmpty attribute to the property:

	[NotNullOrEmpty(Message = "Please enter an e-mail address.")] 
[ValidEmail(Message = "This is not a valid e-mail address.")] 
public string Email { get; set; } 

When the Email property is left empty, the first attribute will flag a business rule violation. If a value is entered that doesn’t look like an e-mail address, the second attribute flags an error. Only when the Email property contains a valid e-mail address is the property considered to be valid. If you don't want this behavior and want a single validation attribute instead, you can change the ValidEmail attribute and give it a Required property that you can set to true or false as a named parameter when you apply the attribute.

You’re not limited to simple string comparisons. By adding public properties to your validation attributes you can for example create range validators. The following class shows how to implement a simple ValidRange validator that ensures the property’s value is between the Min and Max values:

	[AttributeUsage(AttributeTargets.Property)]
public sealed class ValidRange : ValidationAttribute
{ 
  public double Min { get; set; } 
  public double Max { get; set; } 
  
  public override bool IsValid(object item) 
  { 
    double tempValue = Convert.ToDouble(item);
    return tempValue >= Min && tempValue <= Max; 
  } 
} 

Because attributes on members support named parameters there’s no need to create special overloads of the ValidRange’s constructor; you simply specify the necessary values by prefixing them with the property’s name. The following example shows you how to make sure a property called Priority has a value that falls between 0 and 10 (inclusive):

	[ValidRange(Message=@"This is not a valid priority. 
           Valid values are between 0 and 10", Min=0, Max=10)] 
public int Priority { get; set; }

Notice how the Min and Max values are set using the PropertyName=Value syntax. This makes it easy to assign one or more properties of the class without the need to create specialized overloads.

From here, you can pretty much create any attribute you like. The following possible attributes come to mind:

  • RegularExpressionAttribute – validates a value given a regular expression.
  • DateTimeNotEmpty – Ensures that a DateTime instance does not equal DateTime.MinValue or DateTime.MaxValue.
  • ValidSsn – Validates a social security number.
  • ValidCreditCardNumber – this class could validate a credit card number.
  • MaxLengthAttribute – Ensures that a string is not longer than a given maximum length.
  • MinLengthAttribute – Ensures that a string is not shorter than a given minimum length.
  • ExactLengthAttribute - Ensures that a string has a specific length.

Many of these attributes could inherit from the RegularExpression attribute which would make implementing them as simple as overriding the regular expression property of the class. With the base classes in the Validation Framework you have a very flexible set of tools. Adding new validation attributes or tweaking the behavior of others by overriding a few methods or properties is now very easy, while you still maintain the same usage experience: apply the attribute and set a few named arguments.

When I discussed the ValidationBase and its Validate method to validate the properties through their attributes, I also mentioned the BrokenRule and BrokenRules classes. You’ll see how they fit in in the next section.

The BrokenRule and BrokenRules Classes

The BrokenRule and BrokenRules classes are used to communicate the broken validation rules back to the calling code. The BrokenRule class is a simple data container that has two properties: Message and PropertyName. Both are visible in Figure 18.

The BrokenRule Class
Figure 18 – The BrokenRule Class

The Message property always contains the expanded error message associated with the broken rule, whether the message was applied to the property directly, or retrieved from a localization resource. The PropertyName contains the name of the property that broke the rules. For example, this property could contain a value of Email when you assigned an invalid value to an Email property. The PropertyName is used to get a collection of all broken rules for a specific property which in turn is useful for unit testing. This is explained later when I discuss the FindByPropertyName method of the BrokenRules collection.

As you saw earlier, each class that inherits from ValidationBase has a BrokenRules property that you can check for the rules that are broken by your business object.
The BrokenRules collection inherits from Collection<BrokenRule> and has two constructors and a useful method to find specific broken rules by the name of the property that triggered the rule.

The BrokenRulesCollection Class
Figure 19 – The BrokenRulesCollection Class

The two constructors of this class allow you to create a brand new collection and one based on an existing IList<BrokenRule>. This overload is used in the FindByPropertyName that filters the inner list and returns all the broken rules that belong to a certain property:

	public BrokenRulesCollection FindByPropertyName(string propertyName) 
{ 
  return new BrokenRulesCollection(
               (from rule in this
                where rule.PropertyName.ToUpperInvariant() ==
                       propertyName.ToUpperInvariant() 
                select rule).ToList<BrokenRule>());
}

This simple LINQ query selects all the BrokenRule instances with a matching (case insensitive) property name. The LINQ query result is converted to an IList which is then fed into the constructor of the BrokenRules collection. This method, and the FindByMessage method are mostly useful for Unit Tests that need to check the validity of a ValidationBase instance and check for specific properties, But you can also use it to get the relevant broken rules in the UI and display them next to their respective UI controls.

To see how all of this works together, the next section introduces a simple Person class with a few properties. The Person class inherits ValidationBase and implements the Validation Framework. A number of Unit Tests and screen shots from the debugger will then show you how everything fits together.

Putting it all together: a very simple Person class and a Bunch of Unit Tests

To test out framework code like the validation code I’ve shown you so far, it’s always a good idea to write unit tests to validate your assumptions and code implementation. As of Visual Studio 2008, the Unit Testing framework is now included in the Professional edition and up (it used to be in the more expensive Team Editions only), so integrated unit testing is now available to more developers than ever. I am a big fan of unit testing, so I use it in many of the projects I code or design.

In order to test some of the validation principles found in the Validation Framework with Unit Tests, I created a simple Person class with the following properties:

	public class Person
{ 
  public string FirstName { get; set; } 
  public string LastName { get; set; } 
  public string EmailAddress { get; set; } 
  public int Age { get; set; } 
}       

As you can see, this is a very simple, yet typical class with a few auto-implemented properties. It looks quite a bit like the ContactPerson class introduced in my previous article series.

To ensure you only store valid people in your data store, let’s say you want to enforce the following business rules on this Person class :

  1. The first name is required
  2. The last name is required
  3. The email address is required and must contain a value that represents an e-mail address.
  4. The age should be between 0 and 150. (Notice that normally a DateTime for the date of birth would be a better option for the Age property).

To change the Person class to implement this validation behavior, you need to carry out two steps:

  1. Make Person inherit from ValidationBase
  2. Implement the necessary attributes to enforce the validation rules.

The Person class could end up like this:

	public class Person : ValidationBase
{ 
  [NotNullOrEmpty(Message="First name is required.")] 
  public string FirstName { get; set; } 

  [NotNullOrEmpty(Message = "Last name is required.")] 
  public string LastName { get; set; } 

  [NotNullOrEmpty(Message = "Email address is required.")] 
  [ValidEmail(Message="A valid e-mail address is required.")] 
  public string EmailAddress { get; set; } 

  [ValidRange(Message="Age must be between 0 and 150.", Min=0, Max=150)] 
  public int Age { get; set; } 
}

In order to test this class and see if the right validation rules are applied, you can write a number of Unit Tests. For example, you could write a simple test that asserts that a brand new Person without any properties set on it is invalid:

	[TestMethod] 
public void NewPersonIsNotValid() 
{ 
  Person myPerson = new Person(); 
  Assert.IsFalse(myPerson.Validate());
}

If you debug this code and put a watch on the Person instance, you can see how the BrokenRules collection is filled with a broken rule for each invalid attribute:

Watching the BrokenRules Property in the Watch Window
Figure 20 – Watching the BrokenRules Property in the Watch Window

In Figure 20 you can see four broken rules; one for each property in the Person class. The ToString method on the BrokenRule class is responsible for prefixing the validation message with the property that caused the rule to be broken. When presenting the broken rules in the UI you typically use the Message property instead that doesn’t contain the property name.

Obviously, in a real world application you could use the BrokenRules collection for something more useful, like binding it to a data bound control, returning it from a Web Service call, or logging it somewhere.

You could (and should) write other tests to validate individual properties; often you want to write a separate test for all possible edge cases. For example, when testing a property with the NotNullOrEmpty attribute applied, you want to test for null, string.Emtpy and a valid value like this:

	[TestMethod] 
public void NullIsNotAValidFirstName() 
{ 
  Person myPerson = new Person { FirstName = null }; 
  Assert.IsFalse(myPerson.Validate());
  Assert.IsTrue(myPerson.BrokenRules.FindByPropertyName(
                  "FirstName").Count > 0);
} 

[TestMethod] 
public void EmptyIsNotAValidFirstName() 
{ 
  Person myPerson = new Person { FirstName = string.Empty };
  Assert.IsFalse(myPerson.Validate());
  Assert.IsTrue(myPerson.BrokenRules.FindByPropertyName(
                   "FirstName").Count > 0);
} 

[TestMethod] 
public void ImarIsAValidFirstName() 
{ 
  Person myPerson = new Person { FirstName = "Imar" }; 
  myPerson.Validate();
  Assert.IsTrue(myPerson.BrokenRules.FindByPropertyName(
                   "FirstName").Count == 0);
} 

Notice that with invalid cases I can be sure that Validate must return false, so I can assert myPerson.Validate(). With a valid example, I cannot be sure the entire instance is valid because other properties could be broken as well. In that case, I am not using Assert.IsTrue(myPerson.Validate()) but simply myPerson.Validate() instead. Also note that in tests where I expect the validation to fail I check the Count property of the filtered broken rule collection to be at least 1.

You could write similar tests for other properties, like the Age attribute. For example, with a ValidRange attribute as applied on the Age property, you likely want to ensure that the lower and upper bounds are valid, and values outside the range aren’t. The following code snippet shows the implementation of a number of tests for the Age property:

	[TestMethod] 
public void AgeCannotBeMinusOne() 
{ 
  Person myPerson = new Person { Age = -1 }; 
  Assert.IsFalse(myPerson.Validate());
  Assert.IsTrue(myPerson.BrokenRules.FindByPropertyName("Age").Count > 0);
} 

[TestMethod] 
public void AgeCannotBeLargeNegative() 
{ 
  Person myPerson = new Person { Age = int.MinValue };
  Assert.IsFalse(myPerson.Validate());
  Assert.IsTrue(myPerson.BrokenRules.FindByPropertyName("Age").Count > 0);
} 

[TestMethod] 
public void AgeCannotMoreThan150() 
{ 
  Person myPerson = new Person { Age = 151 }; 
  Assert.IsFalse(myPerson.Validate());
  Assert.IsTrue(myPerson.BrokenRules.FindByPropertyName("Age").Count > 0);
} 

[TestMethod] 
public void AgeCannotBeLargePositive() 
{ 
  Person myPerson = new Person { Age = int.MaxValue };
  Assert.IsFalse(myPerson.Validate());
  Assert.IsTrue(myPerson.BrokenRules.FindByPropertyName("Age").Count > 0);
} 

[TestMethod] 
public void AgeCanBeLowerbound() 
{ 
  Person myPerson = new Person { Age = 0 }; 
  myPerson.Validate();
  Assert.IsTrue(myPerson.BrokenRules.FindByPropertyName("Age").Count == 0);
} 

[TestMethod] 
public void AgeCanBeUpperbound() 
{ 
  Person myPerson = new Person { Age = 150 }; 
  myPerson.Validate();
  Assert.IsTrue(myPerson.BrokenRules.FindByPropertyName("Age").Count == 0);
} 

[TestMethod] 
public void AgeCanBeBetweenLowerAndUpperbounds() 
{ 
  Person myPerson = new Person { Age = 130 }; 
  myPerson.Validate();
  Assert.IsTrue(myPerson.BrokenRules.FindByPropertyName("Age").Count == 0);
}

By having this set of tests, you can be sure you’re notified of problems if someone changes the rules. For example if the lower bound of the Age validation attribute is changed from 0 to 1, the AgeCanBeLowerbound test will fail. Likewise, other tests will fail as well as other settings are changed.

Implementing the Validation Framework the way I have shown you here gives you a lot of flexibility, without requiring a lot of hand written code. However, it may seem to you that the Validation Framework only works on single instance properties. That is, you can only validate a single property’s value at a time, without the ability to relate it to the value of another. Fortunately, validating related properties is easy as well, as you’ll learn in the next article in this series. Stay tuned!

Summary

Validation is a very important concept in most day to day business applications. You can implement validation in different layers, including the UI, the Business Layer and the database. By implementing validation in the UI, you get responsive applications, but as a down side you’ll need to rewrite rules every time you present data in the UI. Database validation works at the lowest possible level: right before the data gets stored in the database. Although this ensures a great integrity of your data, it isn’t always the most practical solution as you’ll need to deal with low-level exceptions which are difficult to transform and translate into the user interface.

By implementing validation in the Business Layer with the Validation Framework I’ve shown you in this article, you can circumvent the problems typically associated with UI and database validation and get the following benefits:

  1. Your validation rules are easy to write and implement.
  2. It’s easy to reuse your validation rules across your business entities.
  3. You can ensure that the rules are applied regardless of the user interface used.
  4. You can localize your validation messages so they are easy to understand for end users.
  5. You have a centralized validation mechanism, making it easy to get a full list of broken rules or invalid properties from a single location.

In the next part in this article series I’ll show you some advanced validation topics. You’ll see how to write your own validation code in your business entities to enforce complex business rules and you’ll learn how to localize the entire Validation Framework so it can be used in multi-lingual web sites.

Downloads

 


 


Where to Next?

Wonder where to go next? You can read existing comments below or you can post a comment yourself on this article .


Consider making a donation
Please consider making a donation using PayPal. Your donation helps me to pay the bills so I can keep running Imar.Spaanjaars.Com, providing fresh content as often as possible.



Feedback by Other Visitors of Imar.Spaanjaars.Com

On Friday, December 19, 2008 8:54:39 AM Maarten van der Lee said:
I really like this approach to validation! But isn't there a problem when using inheritance?

Let’s say, we have got an abstract base class Person with a couple of standard properties like FirstName and LastName. Normally these properties may not be null or empty. We can accomplish this by using the custom validation attributes. But, We also have got a class Employee which derives from Person. For this class we want to be able to let the LastName be empty (i know this isn't obvious). Can this be accomplished?
On Saturday, December 20, 2008 5:52:20 PM Imar Spaanjaars said:
Hi Maarten,

The first question that comes to mind is: why don't you try it out?

Try this:

- Make Street in the original Address class virtual
- Create a class that inherits from Address
- Override Street in the child class
- Don't supply an attribute for this new overriden property.
- Instantiate and validate the child object

You'll notice that Street is not validated. That is, the code in ValidationBase is able to find properties with attributes only at the latest level they are defined. Overriding a property doesn't inherit its attributes, but as long as you don't override a property, the validation rules from the base class are applied.

Cheers,

Imar
On Sunday, December 21, 2008 10:47:34 PM Jaams Adams said:
Hi, I am just wondering if this framework should be extended to support Parameter Validation for direct function calls too. Like validation for parameter(s) being passed for a function such as PersonID as int etc. This might result in a better foolproof business layer to work with. What do you think about?
On Monday, December 22, 2008 11:52:10 AM Maarten van der Lee said:
Imar, I have to agree your code should do the trick.

But although your code looks brilliant, I prefer an abstract validate method which I have to include in every class that derives from ValidationBase and some validate-functions inside ValidationBase.

This way you can do your validation like this:

public override bool Validate()
{
    this.ValidateIsNotNullOrEmpty(this.Firstname);
    this.ValidateMaxLength(this.Firstname, 200);
    this.ValidateMatchRegex(this.EmailAddress, "regex goes here")
    etc...
}

Because the Validate function is an abstract function, you are forced to think about your validation rules, which I think is a good thing to do. It also decreases the number of validation classes you have to write (custom attributes) and there is no need for reflection.

It doesn't look a sexy as your solution, but in my opinion it's cleaner and probably faster/safer (no reflection) way for the validation.

By the way, don't take this post as criticism, I just wanted to share my thoughts.
On Monday, December 22, 2008 12:38:19 PM Iker said:
Sorry if I was not able o make out but how to take the validation back and display in label UI? Like if user leav UserName empty then how display on the label that "Please enter a user name".

One example please.
On Monday, December 22, 2008 7:48:41 PM Imar Spaanjaars said:
Hi Iker,

You find that example at the top of this article. Also, the code download shows a number of good examples.

Cheers,

Imar
On Monday, December 22, 2008 7:53:18 PM Imar Spaanjaars said:
Hi Maarten,

I definitely see your point. It would be easy to implement in this model though. Just mark Validate as virtual and add a bunch of validation methods.

Not sure if I like methods over attributes though. I don't think it minimizes the amount of code (it surely does minimize the number of classes) and I think it's more difficult to reuse them. With attributes you can have many different attributes - even in separate assemblies - and only choose the ones you like. With a base class with validation methods you have all of them available which might be confusing.

Still an interesting solution though....

Imar
On Monday, December 22, 2008 8:06:55 PM Imar Spaanjaars said:
Hi Jaams,

Yes, that's how I typically implement it as well: through "design by contract" and "fail fast" mechanisms. For example, GetItem could look like this:

public Person GetItem (int id)
{
  if (id <= 0)
  {
    throw new Exception ("Id must be larger than zero");
}
}

Instead of a generic Exception I throw a Pre- or PostConditionException. You can do the same at the end of the method and throw an exception if the item is null (not found in the database; although it could perfectly be acceptable in most cases if it was null, in which case you don't throw an exception of course).

For more info:

http://www.martinfowler.com/ieeeSoftware/failFast.pdf
http://www.codeproject.com/KB/cs/designbycontract.aspx

Cheers,

Imar
On Tuesday, December 23, 2008 3:16:52 AM iker said:
Thanks so much you answer all posts :)

You said code download. Where is code for this article? Cannot find out.
On Tuesday, December 23, 2008 6:23:20 AM Iker said:
I need sppecs :) I found code.
On Tuesday, December 23, 2008 9:41:09 AM Imar Spaanjaars said:
Hi Iker,

Yeah, I was just going to suggest getting a copy of "Beginning Reading" from Wrox or "Reading for Dummies".... ;-)

Imar
On Tuesday, December 23, 2008 7:30:54 PM Mike said:
Excellent article, thanks for writing this!

Attributes are the best way to declare validation rule, because they can be read using reflection. Why is that so important? Because you will want to generate javascript code for UI validation in web applications. Did you try that Imar? Do you know of any validation frameworks that can do this?

On Tuesday, December 23, 2008 9:16:09 PM khurram said:
Hi,
I just wonder why dont you use validation application block of enterprise library which provides a pretty good frawework for validation.
On Tuesday, December 23, 2008 10:22:13 PM Imar Spaanjaars said:
Hi Mike,

Sorry, no, don't know any framework that can do that.

Cheers,

Imar
On Tuesday, December 23, 2008 10:28:50 PM Imar Spaanjaars said:
Hi khurram,

You can certainly use the Validation Application Block as well for your own validation if you're confortable using it.

I often use my approach instead as it's often a little easier to understand / implement and configure. Also, because the underlying code model is so simple and small, it's easy to add your own behavior, or change the existing code. But, the VAB is certainly a viable alternative.

Cheers,

Imar
On Wednesday, December 24, 2008 5:17:38 PM Mark said:
First of all very interesting article. Although i do have some questions.

In your article you are talking about validation in de BLL. But I downloaded the solution. When you update or insert a contactperson, you validating in the bussiness layer but also in the presentation layer. What is the reason for this? Or are you going to write about that in the next articles?

And why don't you use LINQ in the DAL?

Keep up the good work!

Kind Regards,

Mark
On Wednesday, December 24, 2008 5:28:20 PM Imar Spaanjaars said:
Hi Mark,

I call Validate on the business entity to let it handle validation and then present the rules in the UI. The Validation controls in the presentation layer are just to give the user a fast repsonse to any erorrs they make, but the Bll is always in control.

Regarding Linq: check out Blogo.NET:

http://s3maphor3.org/blogo.net/
http://ferdychristant.com/blog/articles/DOMM-7DDFWT

It's a Linq to SQL implementation of my design.

I chose not to implement LINQ as a) a lot has already been written on LINQ and B) LINQ is not always the answer in every architecture, so it's important to understand how to manually program the underlying data layer for full control.

But, as you'll see in the Blogo article, it's pretty easy to implement LTS (or better yet, the ADO.NET Entities Framework) using my design.

Cheers,

Imar
On Wednesday, December 24, 2008 5:58:36 PM Jaams Adams said:
Hi...again here...your suggestion above regarding to parameter base validation for methods as "design by contract" and "fail fast" routes away from your localizeable architecture. Other day I came across at CodePlex a validation framework for methods too, have a look here http://www.codeplex.com/ValidationFramework.
They also offer to tweak with your validation rules without bothering with your code altogather, seems bit flexible. How is about having best of the both worlds togather? just wondering what's your thinking about.
On Thursday, December 25, 2008 10:03:58 AM Imar Spaanjaars said:
Hi Jaams,

Why would design by contract break my localizeable architecture?

And yes, you could easily mix other frameworks into my design. My design is not "the solution"; it's a starting point that you can enhance or alter however you see fit, depending on your own knowledge and experience....

Cheers,

Imar
On Saturday, December 27, 2008 10:39:23 PM Gon said:
Hi Imar,

I was wondering how would you implement with this validation framework a validator that needed the value of two properties to validate the bussiness rules, let's say for example "The length of the FullName (FirstName + LastName) cannot exceed 50 characters" without implementing the FullName property

Thnx
On Saturday, December 27, 2008 11:11:44 PM Imar Spaanjaars said:
Hi Gon,

This is discusssed in part three which is yet to be published. You can wait for it to come on-line, or you can buy the full set of articles right now:

http://imar.spaanjaars.com/QuickDocId.aspx?quickdoc=482

Cheers,

Imar
On Sunday, December 28, 2008 9:26:05 PM Nice.Developer said:
Hi Imar
i have gone through your first 3 articles for N layer written in asp.net 2.0
i have some comments.
let me explain it with an example
we have a form on UI in which many files are displayed to the user and these fields are need to be saved in the DataBase in different tables.
according to your framework at UI layer we have to call individual BL classes in transaction scope.
i think ui just call only one  method and then all things save in a transaction
ui just need only one call to save all the form.
is there any lack of one more layer of frame work.
thanks
On Sunday, December 28, 2008 9:50:46 PM Imar Spaanjaars said:
Hi tjere,

I don't understand what you're asking....

Imar
On Monday, December 29, 2008 11:13:03 AM Nice.Developer said:
Hi ,
UI layer calls the BL methods , if there any to call more than one BL functions then UI layer call these in code behind of a page. ?
if yes then whether this is a good solution ?
On Monday, December 29, 2008 11:28:03 AM Imar Spaanjaars said:
I still don't get it. The UI layer calls methods on the Bll, either through an ObjectDataSource, or in Code Behind. You call as much as you need to....

Typically, a Save method on a class like ContactPerson can (internally) call other methods as well, so all the UI needs to do is call a single method. However, what exactly needs to be called depends on the actual design and implementation.

Cheers,

Imar
On Tuesday, December 30, 2008 6:46:51 AM Nice.Developer said:
we have a UI Form on follwoing fileds are displayd


DropDownList : list of p repopulate Subject
DropDownList : list of Topic based on subjectid
user can have option to add new subject and new topic as well , and both drop down list are editable.
user select a subject from our list and then did not select a topic based on subject id , and add new topic in the drop down list as ddl is editable.
then according to you UI will call one method of Subject class(save method) and the logic to add new topic will be in the subject class save method?

Subject is a seperate Class and Topic is seperate a BL Class .
Both have their own save methods
On Tuesday, December 30, 2008 9:09:12 AM Imar Spaanjaars said:
Hi there,

You misunderstood me. Yes, there might only be the need for a single Save method. However, you also need a way to add items to the collection of the "outer" type. Take a look at part 2 of the original series (QuickDoc ID: 419) under the heading "Wrapping it Up". You'll see an example of addresses being added to the Addresses collection of a contact person like this:

ContactPerson myContactPerson = new ContactPerson();
...
Address myAdress = new Address();
myAdress.Street = "Some Street";
...
myContactPerson.Addresses.Add(myAdress);

ContactPersonManager.Save(myContactPerson);

Here the Add method is used to add items to the ContactPerson's Addresses collection. Once Save is called, it saves the ContactPerson instance and its Addresses.

Cheers,

Imar
On Friday, January 02, 2009 2:17:59 AM Bec said:
Hi Imar,

Assume I want to control user authorization (what users can do on different pages) using an xml file. One example would be to only allow Administrators to delete things. Would all 3 layers check that the user is an Administrator before allowing the Delete function? I ask this because the layers are separated into independent assemblies. Also the Presentation layer would want to do something like disable the Delete button whereas the Bll and Dal may want to throw exceptions, so each layer would need to be able to do this validation.

Cheers!
On Friday, January 02, 2009 9:11:19 AM Imar Spaanjaars said:
Hi Bec,

You're more or less answering your own question by saying the type of validation is different in the various layers. I use validation in the Bll to enforce business logic rules, and I use it in the UI to provide a better, more usable interface. That is, show quick responses to validation errors, hide or disable irrelevant controls and so on.

So, you'd need to validate at least in the UI and Bll to make sure only authorized users can see and access specific data / functionality. I don't do validation in the Dal that much; at the most I check technical validity of data to see if it can be saved in the database.

Hope this helps,

Imar
On Wednesday, January 07, 2009 4:39:11 AM asp2go said:
Imar,
This series (so far) and the original are absolutely awesome. Other than Rocky Lhotka's books this is one of the only truly informative and practical approaches I've seen on implementing and designing with OOP in .NET apps. You also provide us with some great Web control use tips. I've also gone through the majority of your Comment posts and it's truly impressive how much time you spend considering and responsing to questions. A truly great information share for the ASP.NET community!

Question: Do you intend to also release source in VB as in the previous series or will you stick solely to C#?

Thanks and Keep On Teaching Us!
On Wednesday, January 07, 2009 5:04:24 AM asp2go said:
Imar,
One question that may benefit others that perhaps is covered but I don't see it anywhere in this or the earlier series. Is it possible to create a full object from a web form at once and then Save the whole thing? In many cases for instance I may want to create the Order and Order Details records all on a page at once and not commit anything to the database until 'Submit Order' is clicked. It seems in the sample app you first save the Contact and then subsequently save each Collection item.
So perhaps we're populating a Formview with Order Header information and a Gridview with Order detail information and then 'Submit Order' creates a full object with its associated collection. Or in your sample app maybe our rule is that we don't want to store Contacts that don't have at least 1 Address entry and 1 Email entry, etc.

Any advice on how this could be accomplished would be appreciated.
Thanks
On Wednesday, January 07, 2009 7:33:14 AM Imar Spaanjaars said:
Hi asp2go,

Yes, the source is currently being translated by a reader of my site. It's about 95 percent done. Will post on my site when it's fully done.

Regarding saving: yes, you can certainly do that. Simply instantiate a ContactPerson, add stuff to the collection and save it:

ContactPerson myPerson = new ContactPerson();
myPerson.Addresses.Add(new Address(...));
myPerson.Addresses.Add(new Address(...));
myPerson.EmailAddresses.Add(new EmailAddress(...));
myPerson.Save();

Cheers,

Imar
On Tuesday, January 20, 2009 2:26:49 PM Martin Van de Moortel said:
Hi Imar,
Thanks for sharing this great article.
My question is if it's also possible to validate a regular expression such as the example below (validates a valid € currency input).
How should this be implemented if possible.

ValidationExpression='^\s*-?((\d{1,3}(\.(\d){3})*)|\d*)(,\d{1,2})?\s?(\u20AC)?\s*$'

Thank you in advance
On Tuesday, January 20, 2009 8:26:28 PM Imar Spaanjaars said:
Hi Martin,

Here's what I would do:

1. Create a class called RegularExpressionAttribute that inherits ValidationAttribute.

2. Give it a public property called RegularExpression of type string.

3. In the override of Validate, get the value, cast it to a string, and when it's not null, use a RegEx to match the value against the expression. This should return true or false.

4. Apply the attribute by setting the expression

... RegularExpressionAttribute("^\s*-?((\d{1,3}(\.(\d){3})*)|\d*)(,\d{1,2})?\s?(\u20AC)?\s*$", "InvalidCurrency") ...
public string Currency { ... } // or whatever the type needs to be

You can extend the attribute with options for the RegEx like IgnoreCase, MultiLine and so on.

Does that help?

Imar
On Wednesday, January 21, 2009 7:40:12 AM Martin Van de Moortel said:
Thanks Imar for your fast reply.
I will give it a try. I intend to convert my webapp using your method in stead of the validations at webpage level.
Looking forward for more.

Best regards

Martin
On Thursday, January 22, 2009 12:08:56 PM Imar Spaanjaars said:
Hi Martin,

Good luck.

Or should I say "Veel geluk"? ;-)

Imar
On Friday, January 23, 2009 3:33:24 PM Gufran Sheikh said:
Hi Imar,
Very impressive article, thanks for contributing to the community.
I read all the comments in this article and I came up with two suggestions.

Please dont take it much serious just want to express the idea, I know with flexibility lots of complicacy comes.

1. whether the validation is applicable or not in Business Logic Layer.
some times we want to validate one field in the one form and same field in the other form we dont want, say

in form1.aspx
person myperson= new person();
person.FirstName.ValidationRequired= True;
or
person.FirstName.NotNull.ValidationRequired=True;
person.FirstName.ValidRange.ValidationRequired=False;

in form2.aspx
person myperson= new person();
person.FirstName.NotNull.ValidationRequired=False;

2) User Roles in Attributes
say only certain roles is required to put the data in certain feild

in form1.aspx
person myperson= new person();
person.FirstName.Roles= "Admin";

in form2.aspx
person myperson= new person();
person.FirstName.Roles= "Member";

and every time we dont have to pass these parameters just only in some condition we want otherwise the default will apply.

Thanks
Gufran Sheikh
www.gufran.info
On Friday, January 23, 2009 11:11:05 PM Imar Spaanjaars said:
Hi Gufran,

Yeah, that's another way to approach things: change all simple types to domain classes.

The biggest drawback I see with this approach is state and databinding. When everything is kept in memory this is reasonably simple to implement. However, as soon as you need to flatten stuff, for example to be displayed in an ASP.NET GridView, and need to get the data back when editing you'll run into problems, as databinding really only works well with simple properties....

Cheers,

Imar
On Saturday, January 24, 2009 7:10:41 AM Gufran Sheikh said:
Hi Imar,
Thanks for reply, so what do you suggest to achieve that approach ? I am sure there should be some good approach to achieve that functionality. If you have any refrence link then it would be helpful.

And another question is can I use this validation framework with SubSonic ORM ?
because I am going to use it for my project, so just wanted your suggestion.

Thanks
Gufran Sheikh
www.gufran.info
On Saturday, January 24, 2009 8:34:17 AM Imar Spaanjaars said:
Hi Gufran,

Sorry, no direct links or detailed explanations. You came up with that idea, so I thought you were going to tell us... ;-)

I am not familiar with SubSonic, so I can't recommend anything on that either.

Cheers,

Imar

On Tuesday, February 03, 2009 7:19:33 PM Imar Spaanjaars said:
Hi asp2go and others interested in the VB.NET version of the application,

I just uploaded the source to my site so you can download it right now. You can read more about it here: http://imar.spaanjaars.com/QuickDocId.aspx?quickdoc=485

Cheers,

Imar
On Wednesday, February 04, 2009 9:14:14 AM Martin Van de Moortel said:
Hi Imar,
I started with some tests to implement your validation strategy in my webapp. I like to keep as much as possible the same behavior as with the validation  controls in the website's.
I have the following problem and don't know yet how to solve it.
1. Behavior using a RequiredFieldValidator
I have a gridview allowing edit/update of some fields. When the user tries to save an empty field the RequiredFieldValidator takes care of it and leaves the  row being edited in edit mode, so the user can correct his mistake.
2. Using the new validation strategy:
I'm handling the Validation in the objectdatasource updating eventhandler. This works fine, the empty field is checked and the error is returned, but due to the e.cancel=true to cancel the event, the gridview row returns to its normal state. Is there a way at this stage to keep the edited row in edit mode so that the user can correct his mistake immediately?

Any suggestion is highly appreciated.

Alvast bedankt.

Martin
On Wednesday, February 04, 2009 11:03:55 AM Martin Van de Moortel said:
Hi Imar,

My problem is solved. I treat the validation in the gridview RowUpdating event handler, this works fine.

Best regards.

Martin
On Wednesday, February 11, 2009 6:20:46 PM MG said:
Hi,

Is there reason why you didn't give an attribute to ContactPersonId property, something like NotNullOrEmpty in bussiness entities. It is a foreign key and it have to be controlled whether null or empty?

Thanks.
On Wednesday, February 11, 2009 9:19:30 PM Imar Spaanjaars said:
Hi MG,

Yeah, you could do that. However, I usually set validation attributes on properties that can be set by users. The Id is something that is controlled intenally, so IMO it's better so simply throw an exception if it doesn't have the value you expect.

Cheers,

Imar
On Friday, February 13, 2009 1:16:58 PM kurt schroeder said:
and again thank you
On Tuesday, February 17, 2009 2:11:29 PM Bliek said:
I see it is possible able to check whether one date is less or equal compared to another date. But what if the user inputs these two dates in the UI and the dates he enters aren't dates at all, but i.e. silly character strings? The same question for money type input. You can't just get an invalid input string in a decimal...? How would you perform such a validation (which is normally done thru one of the validator controls), even concerning the local input language? (for the decimal point, thousand separatores and so on)
On Tuesday, February 17, 2009 5:57:19 PM Imar Spaanjaars said:
Hi Bliek,

You still need to use UI validation controls for that. Because you can't assign an invalid string to a DateTime property (or any string for that matter), the validation code will never be hit to do its work.

The standard ASP.NET validation controls can do what you want, and are culture aware.

Cheers,

Imar
On Wednesday, February 18, 2009 6:42:27 PM Vladimir Kelman said:
It's a matter of taste, but I think that this looks more elegant:

public sealed class NotNullOrEmptyAttribute : ValidationAttribute {
  public override bool Validate(object item)   {
    return (item is string)?
           !string.IsNullOrEmpty(item as string) :  (item != null);
  }
}
On Wednesday, February 18, 2009 11:12:16 PM Vladimir Kelman said:
As it was for a first series of articles too, reading comments is almost as interesting and helpful as reading the main article.
Thinking about author's discussion with Maarten van der Lee above, I decided that using attributes *probably* is a more structural approach: it places validation attributes next to properties to be validated instead of putting all of them into the big bag of the overridden Validate() method. By the way, is it allowed to use
   public virtual override bool Validate() {}
when you predict that classes derived from this concrete class will reuse the same validate?  
On Wednesday, February 18, 2009 11:16:49 PM Vladimir Kelman said:
Design by contract will be incorporated into .NET 4.0: http://iridescence.no/post/Design-by-Contract-with-NET-40.aspx
On Thursday, February 19, 2009 7:03:11 AM Imar Spaanjaars said:
Hi Vladimir,

Not sure what you're asking....Why wouldn't it be allowed?

Imar
On Saturday, February 21, 2009 9:05:00 AM mohamad said:
hi
i want to use ur article for write a book.
can i do this?
On Saturday, February 21, 2009 9:49:33 AM Imar Spaanjaars said:
Hi mohamad,

The answer is probably: No. These are my articles, my code and my ideas so you cannot just copy and paste them in your book and claim they're yours. However, it depends of course on what the book is about. If you get inspired by these articles, then write up your own ideas based on them, then it's probably OK.

Just don't bluntly copy and paste or I'll sue you..... ;-)

Imar
On Saturday, February 21, 2009 11:06:18 AM mohamad said:
i want write this book in the farsi
On Saturday, February 21, 2009 12:06:19 PM Imar Spaanjaars said:
Hi mohamad,

Nope, you can't do that. Using my articles for translated versions without a (paid) license agreement between you and me would break my copyright rights. So, please don't do this.

Cheers,

Imar
On Monday, March 02, 2009 5:50:31 AM Yaroslav said:
Hi, Imar!

Again a very interesting article! I think I`ll sure implement this approach in my projects, but here goes question: what if you need to validate 1 class in 2 different ways? Like customer can be of different types. for one type of customers I need one validation logic and for other type - another. In this case I see I`ll need to inherit from customer class and override properties and set other validation attribute on them.

And the second question: what if I need to validate fields as a single amount of data? Like one field can be empty, but then other should be filled or vice versa?

Really thanks again for the article!

Best regards,
Yaroslav Yakovlev.
On Thursday, March 12, 2009 9:29:24 PM luisa said:
very very interesting article! i gave got every your suggest for my web application, thank you!
I need a little help again(if it is possible!):i have the same problem described On Wednesday 2/4/2009 10:14:14 AM by Martin Van de Moortel but i use the listview (not gridview), i tried to use  ListView_itemupdating but I don't know how abtain myBusinessBase...can you help me? thank you in advance
Luisa
Ps. sorry for my english!
greetings from Italy
On Friday, March 13, 2009 8:00:45 PM Imar Spaanjaars said:
Hi Yaroslav,

I was sure I provided an answer to your post some days ago, but somehow it never ended up on-line.

Ayway, you could have a base class with overridable properties. The base class provides the default validation while a child class can override some properties and add new attribute.s

With regards to the second question: take another look at the Validate method of BusinessBase in part three of this series.

Cheers,

Imar
On Friday, March 13, 2009 8:14:08 PM Imar Spaanjaars said:
Hi luisa,

Take a look at the Updating event of the ObjectDataSource. It provides access to the InputParameters collection. The first item is actually your business object. For example

Address myAddress = e.InputParameters[0] as Address;

should give you a reference to the object being updated.

Hope this helps,

Imar
On Saturday, March 14, 2009 11:03:14 AM Luisa said:
Hi Imaar thank you for you answer,  i'm able to use but i don't want use Updating event of the ObjectDataSource because i have to use the Listview_itemupdating event for not loosing the edit/insert itemtemplate (i suppose...).
So my question is: how can i acced to my businness object (and convert it to businessbase) in Listview_itemupdating: how can i reference to the object being updated in Listview_itemupdating event?  
Sorry but it is diffucult for me explain my needs, i tryed this but doesn't works:
Protected Sub LVFormatSingleItem_ItemUpdating(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ListViewUpdateEventArgs) Handles LVFormatSingleItem.ItemUpdating
        Dim IIndex As Integer = Integer.Parse(LVFormatSingleItem.DataKeys(e.ItemIndex).Value.ToString())
        'my businessobject:
        Dim myformat As Format = FormatManager.GetItem(IIndex)
        Dim myBusinessBase As BusinessBase = TryCast(myformat, BusinessBase)
        If Not myBusinessBase.Validate Then
            ErrorList1.BrokenRules = myBusinessBase.BrokenRules
        End If
    End Sub
where is the mistake??? thank you in advance
Luisa
On Saturday, March 14, 2009 11:22:00 AM Imar Spaanjaars said:
Hi Luisa,

>> where is the mistake???

The mistake is in the way you write my name. It's Imar, not Imaar ;-)

The mistake is also that you just get a clean copy from the database, effectively ignoring the updates made to the form.

You'll either need to do it in Updating on the ODS as I suggested earlier, or you'll need to copy from field values one by one into a new BusinessBase type.

But why not handle Updating on the ODS and setting e.Cancel to true. Below is a quick example (using C#, but I am sure you get the idea):

BusinessBase myBusinessBase = e.InputParameters[0] as BusinessBase;
if (!myBusinessBase.Validate())
{
  ViewState["Ooops"] = true;
  e.Cancel = true;
  ErrorList1.BrokenRules = myBusinessBase.BrokenRules;
}
else
{
  ViewState["Ooops"] = null;
}

Then in the Updated event of the ListView you can do this:

bool oops = false;
if (ViewState["Ooops"] != null)
{
  oops = (bool)ViewState["Ooops"];
  ViewState["Ooops"] = null;
}
if (oops)
{
  e.KeepInEditMode = true;
}

This keeps the ListView in edit mode when validation failed.

Hope this helps,

Imar
On Saturday, March 14, 2009 1:30:18 PM luisa said:
Hi Imar (i've learned now),
Thanks for reply, your code is great, it works perfectly!!!
Thank you very much, i can proceed for next lessons
Bye
Luisa
On Friday, March 20, 2009 4:49:28 PM Andrew said:
Hi Imar,

Another enjoyable read.

Just a thought on semantics.  
I assume the decision to use NotNullOrEmpty comes from String.IsNullOrEmpty however, the simply changing from Is to Not changes the meaning of the statement and how it should be interpretted.
NotNullOrEmpty should actually read Not(NullOrEmpty) to be accurate.  
Or NotNullAndNotEmpty.  
Or following the Microsoft ASP.NET validation controls naming - RequiredFieldAttribute.

As I said, it's just a thought.  

Andrew
On Friday, March 20, 2009 6:01:27 PM Imar Spaanjaars said:
Hi Andrew,

I completely agree. RequiredFieldAttribute seems like the best option.

Cheers,

Imar
On Monday, March 23, 2009 8:48:16 AM omar said:
Thank you Imar for your great articles.
I build (www.telbana.com) based on your asp.net 2.0 Series. I  learned  too much from you.

Now I want to implement validation framework to my Existing asp.net 2.0 application.

My questions is:
Is there any equivalent asp.net 2.0 implementation for the Validate() method instead of using [Linq]

My hosting company - unfortunately- doesn’t support asp.net 3.5

On Monday, March 23, 2009 7:58:18 PM Imar Spaanjaars said:
Hi omar,

It shouldn't be too hard. The biggest change is inside the Validate method. Instead of a LINQ query you'll need to loop through the collection of properties and check their attributes. Give it a try and let me know if it doesn't work for you. If it doesn't, please don't post your code here but send me an e-mail message instead.

Cheers,

Imar
On Wednesday, March 25, 2009 10:03:47 AM Guru said:
Wonderful article. It explore many concepts in clear.

Thanks
On Wednesday, April 01, 2009 2:53:44 PM Sean said:
Very useful article. But doing validation in the business classes is great but i think doing validation at the business interfaces level is more powerful.
I have tried your implementation by setting properties in interfaces as custom attributes. when my class implements an interface, the custom attributes don't seem to be inherited in my class. Why?

Thank you
On Wednesday, April 01, 2009 9:40:51 PM Imar Spaanjaars said:
Hi Sean,

Difficult to say without seeing your code. I did test this on interfaces some time ago and it seemed to work.

Maybe you can post your code on the Wrox forum: http://p2p.wrox.com/index.php?referrerid=385

Cheers,

Imar
On Thursday, April 02, 2009 4:26:07 PM Sean said:
Imar,

I work it out by using doing myClass.GetType().GetInterfaces(). and parse again to get any custom attribute inside each interface.
So if you can confirm how custom attributes in interfaces can be inherited in implementing classes that will be great.
On Thursday, April 02, 2009 6:42:14 PM Imar Spaanjaars said:
Hi Sean,

Yeah, that's one way to do it. Another that should work is to cast it to an IWhatever and get the attributes. I don't have any working code that I can share with you, nor do I have the time right now to write it. Remind me again in a couple of weeks if you still need it, or please keep us updated if you have working code yourself.

Cheers,

Imar
On Thursday, April 02, 2009 8:18:49 PM Vladimir Kelman said:
Imar and Sean,
Thanks for a good tip! I think it's always a good idea to operate on the level of interface (define method's argument type as interface type) if a class is implementing it. That's an essence of polymorphism, isn't  it? Actual object would be a class... but no GetInterfaces() or casting would be necessary.
Hope, I'm not saying something stupid.
On Thursday, April 02, 2009 8:44:20 PM Sean said:
Vladimir,

I was thinking the same way in the beginning. But by nature interfaces should not contain any implementation or initialization.
We implement an interface and not inherit from it. it's very subtle but it makes sense to me to have GetInterfaces() or casting as Imar has mentioned since these are totally 2 different entities.
On Friday, April 10, 2009 2:41:00 PM Scott Brady said:
Hi Imar,

Another copyright question?

Would I be breaching copyright by using the validation framework as outlined in this article when developing websites for any of my clients?

Kind Regards

Scott
On Saturday, April 11, 2009 10:27:35 AM Imar Spaanjaars said:
Hi Scott,

Absolutely not. The whole idea of these article series is to learn from it, and apply and use the knowledge and code you gain from it in your own projects.

Cheers,

Imar
On Monday, April 20, 2009 3:18:44 PM Andy said:
Imar,

There is a minor error in the following paragraph.  You said "- like the presentation and data layer -", but I think you meant "- like the business and data layer -"


In all of these cases, you would need to rewrite your validation mechanism. While in itself this is not so bad (you need a way to overcome the differences in presentation between a Web Application and a Win Forms Application anyways) it poses a bigger issue than just more work: developers may — deliberately or not — forget to implement validation in the presentation or front end layer. So, your cool Web Service or Command Line Import Tool may work today, but may (and probably will) fail miserably tomorrow, possibly because the contact records file you’re trying to import has changed or contains invalid data. So, you’ll need to look into validation in deeper layers - like the presentation and data layer - to better protect your data and its integrity. I’ll show you the possibilities of validation in the data layer first, and then show you how I would have coded the business layer before I started using the Validation Framework.

Have a great day and thanks for all the hard work you do.
On Monday, April 20, 2009 6:24:24 PM Imar Spaanjaars said:
Hi Andy,

Fixed.... Thank you....

Imar
On Monday, August 17, 2009 2:04:59 PM Tristan said:
How could one write the Validate method of the ValidationBase class without using Linq?  I'd like to investigate your new validation implemention in a 2.0 framework.  Thanks Imar
On Monday, August 17, 2009 2:11:09 PM Imar Spaanjaars said:
Hi Tristan,

Rather than using LINQ you can simply loop through the properties collection and look for:

property.GetCustomAttributes(typeof(ValidationAttribute), true).Length > 0

on each individual property instead.

Hope this helps,

Imar
On Monday, August 17, 2009 2:18:41 PM Tristan said:
As always, you are awesome!  Thanks Imar.
On Tuesday, September 29, 2009 12:53:21 PM Jostein said:
Hi!

I am trying to learn n-layered design by using your example. Problem is when I try to use webservice as the "front". I get this exception "Validation.BrokenRule cannot be serialized because it does not have a parameterless constructor."

Any ideas to a work around?
On Sunday, January 17, 2010 6:35:07 PM Vinay Bohara said:
Hi Imar,

I read your article a few months ago, and I did get to implement the same in our live project.

I have a question:

How to implement validation that is database dependant? I my case, the user email address has to be unique at the system level. How can i implement this validation?

Thanks indeed for such a nice article.

Regards,
Vinay
On Sunday, January 17, 2010 8:12:23 PM Imar Spaanjaars said:
Hi Vinay,

From a client, you can do something like as described here:

http://imar.spaanjaars.com/QuickDocId.aspx?quickdoc=494

From a BLL, you can change the Save method to return a status (such as an enum with different options) and return a correct status based on the data in the database.

Then you can do stuff like:

PersonSaveStatus myStatus = myPerson.Save();
switch (myStatus)
{
  case Success:

  Case UserExists
}

And so on.

Hope this helps,

Imar
On Tuesday, July 20, 2010 2:51:43 PM Martin Johnson said:
Can anyone point me in the direction to combine/merge two BrokenRulesCollections? Currently I have a web control that exposes two collections. I'd like to combine them and just expose the one collection.
On Wednesday, July 21, 2010 9:02:15 PM Imar Spaanjaars said:
Hi Martin,

You can call Add on one collection while looping over the other. Alternatively, you can create an AddRange extension method as explained here: http://tinyurl.com/339u3dl

Cheers,

Imar
On Wednesday, October 06, 2010 11:48:34 AM Priya said:
I would like to know how I can apply compare validation between two properties in a class, using validation framework.
For example I have two properties like
From and To
If From == To invalid

Thanks
Priya
On Wednesday, October 06, 2010 1:25:43 PM Imar Spaanjaars said:
Hi Priya,

You may want to read part three as it deals exactly with this topic.

Cheers,

Imar
On Wednesday, October 06, 2010 1:29:18 PM Imar Spaanjaars said:
Hi Priya,

BTW: it might be useful to learn how to spell your own e-mail address. My message to you just bounced....

Imar
On Wednesday, October 06, 2010 2:39:29 PM Priya said:
Hi,

Sorry, I read the article series. Now looking for Dynamic attributes, for comparison.

Thanks
Priya
On Thursday, November 18, 2010 7:36:39 PM Abhi said:
Imaar,
I am interested to know how you would handle complex business validation. For instance, for an order management system, I want to create an order, but order is let's say dependent on customer's credit. How would you handle validate for these following scenarios?
1) Customer A, whatever the credit is, the order can be processed.
2) Customer B, credit is under certain threshold, then order can not be processed. But order information that customer entered still need to be persisted to db.
3) Customer C, whatever the credit is, the order can not be processed.

Would you still have one validate routine that would handle everything or try to break down the validate routine to sub routines? Would you may be create customvalidattion attributes for each customer type or name and depending on customer just call those validation routine?

Really interested to know how you think about those validation scenarios. I struggle with those complex validation rules.

Thanks for the site, it's been a lot of help.
On Thursday, November 18, 2010 7:39:11 PM Imar Spaanjaars said:
Hi Abhi,

I don't think I would handle that directly in all these related classes with attributes. Instead, I would probably create a separate Validation class and dynamically inject that into the process.

Cheers,

Imar
On Monday, August 29, 2011 6:31:34 AM Rajesh said:
Hi,

   I have read your articles. Thanks for sharing the articles.

Talk Back! Comment on Imar.Spaanjaars.Com

I am interested in what you have to say about this article. Feel free to post any comments, remarks or questions you may have about this article. The Talk Back feature is not meant for technical questions that are not directly related to this article. So, a post like "Hey, can you tell me how I can upload files to a MySQL database in PHP?" is likely to be removed. Also spam and unrealistic job offers will be deleted immediately.

When you post a comment, you have to provide your name and the comment. Your e-mail address is optional and you only need to provide it if you want me to contact you. It will not be displayed along with your comment. I got sick and tired of the comment spam I was receiving, so I have protected this page with a simple calculation exercise. This means that if you want to leave a comment, you'll need to complete the calculation before you hit the Post Comment button.

If you want to object to a comment made by another visitor, be sure to contact me and I'll look into it ASAP. Don't forget to mention the page link, or the QuickDocId of the document.

For more information about the Talk Back feature, check out this news item.