October 2017 : Online course in ASP.NET MVC / Core. Conducted by Bipin Joshi. Read more...
Registration for October 2017 batch of ASP.NET MVC / Core online course has already started. Conducted by Bipin Joshi. Book your seat today ! Click here for more details.

Validating Multiple Data Model Properties

In my previous article I wrote about displaying model state errors inside databound controls such as GridView. In that example we used data annotation validators to perform the validations. While data annotation validators do their job quite well they are inherently applied to only one data model property at a time. For example, the [StringLength] or [Required] attributes validate only one property under consideration. However, sometimes your validation rule involves multiple data model properties. In such cases data annotation validators won't be of much use. Luckily there are other validation techniques that can come to your rescue. This article is doing to discuss two of them:

  • Validating using ModelState dictionary
  • Validating using IValidatableObject interface

In the first technique you use ModelState dictionary to access the model properties, check their values and then flag errors if necessary. Let's understand how this technique is used with an example. The example mentioned here uses the same Employee data model class that was used in my previous article. So, if you haven't created the Entity Framework data model yet take a moment to generate it from Northwind database by referring this article.

Now, consider the following code that shows the GridView_UpdateItem method:

public void GridView1_UpdateItem(int employeeid)
{
  NorthwindEntities db = new NorthwindEntities();
  Employee item = db.Employees.Find(employeeid);
  if (item == null)
  {
    ModelState.AddModelError("", String.Format("Item with id {0} was not found", employeeid));
  }
  else
  {
    TryUpdateModel(item);
    if (item.FirstName.Length > 10 && item.LastName.Length > 10)
    {
      ModelState.AddModelError("", "First Name and Last Name are invalid!");
    }
    if (ModelState.IsValid)
    {
      db.SaveChanges();
    }
  }
}

Notice the code shown in bold letters. The code checks the length of FirstName and LastName model properties. Accordingly an error message is added in the ModelState dictionary using AddModelError() method. Supplying the first parameter as an empty string indicates that this is a model level error rather than a property level error. If you want to associate the error under consideration to a specific model property you can specify the name of the property as the first parameter of the AddModelError() method. The second parameter of the AddModelError() method specifies the error message that will be displayed in the ValidationSummary control.

Ok. Now let's see the other technique - IValidatableObject interface. In this technique you need to implement IValidatableObject interface on the data model class. The IValidatableObject interface contains Validate() method that should return a collection of ValidationResult objects. Each ValidationResult represents an error condition with the underlying data model. Since Employee model class is an EF designer generated class the best place to implement the IValidatableObject interface is the Employee partial class you created for the sake of associating metadata class with the model class. The following code shows how the Validate() method can be implemented on the data model.

[MetadataType(typeof(EmployeeMetadata))]
public partial class Employee:IValidatableObject
{
  public IEnumerable Validate(ValidationContext validationContext)
  {
    List errors = new List();
    if (FirstName.Length>10 && LastName.Length>10)
    {
      ValidationResult err = new ValidationResult("Invalid First Name and Last Name");
      errors.Add(err);
    }
    return errors;
  }
}

Notice the code shown in bold letters. The Validate() method receives ValidationContext as a parameter and returns IEnumerable of ValidationResult objects. Inside, it creates a generic List of ValidationResult objects. It then checks for the same validation rule as before and if the validation rule is being violated adds a new ValidationResult to the generic list. The ValidationResult constructor accepts an error message that flags the error. Finally the generic List is returned from the Validate() method.

Which of the two techniques you use depends on your requirement. The ModelState technique puts the validation code in the web form since ModelState is a property of the Page base class. That means your validation logic gets coupled with the rest of the web form code. This may be alright if the validation rule is to be checked for that form alone. However, if the validation rule is applicable inside all the web forms (or wherever Employee data model class is being used) then IValidatableObject technique would be more useful. Using IValidatableObject technique allows you to put the validation rule under consideration in the model class itself. So, depending on your requirement you should pick the appropriate technique.

While the above example illustrates both of these techniques for a web forms application they can be used with ASP.NET MVC application also in the same fashion. If you are using ASP.NET MVC the ModelState dictionary technique will go inside an action method whereas the IValidatableObject technique remains unchanged.

That's it for now! Keep coding.


Bipin Joshi is a software consultant, an author and a yoga mentor having 22+ years of experience in software development. He also conducts online courses in ASP.NET MVC / Core and Design Patterns. He is a published author and has authored or co-authored books for Apress and Wrox press. Having embraced the Yoga way of life he also teaches Meditation and Mindfulness to interested individuals. To know more about him click here.

Get connected : Twitter  Facebook  Google+  LinkedIn

Posted On : 14 August 2013


Tags : ASP.NET ADO.NET Data Access Web Forms MVC