Wednesday, January 1, 2014

Step By Step How to add Model Data Validation (Database First) to an ASP.NET MVC 4 application

         By Carmel Schvartzman

In this tutorial we'll learn how  to add Model Data Validation to an ASP.NET MVC4 application, while using the Database First approach of the Entity Framework

Concerning the Model in a MVC application, there are two kinds of errors that can happen: data type errors and bussiness logic errors. The later are usually handled in special classes which extend the DAL of the application. Remember that when you use the Entity Framework as the DAL (Data Access Layer) of your MVC, every time you update the conceptual data model to reflect changes made to the data store, the Model classes are regenerates by a tool, meaning that everything that's in it is erased and rewriten. Therefore the Bussiness Rules are coded in partial classes which extends the Model classes.

For that reason, decorating entities's fields with Data Annotations will not work while using the Database First approach of the Entity Framework. Every time you refresh the conceptual Model, your annotations will be overriden. In this tutorial we'll use Data Annotations with the  the Database First approach.

The MVC Data Model created automatically by the Entity Framework captures the data type errors caused by incompatibility between data types, and throws exceptions notificating the user about the problems.

This kind of errors can be easily handled using Data Annotations, by decorating the entity's fields with attributes. That way, custom validation rules will be enforced not only while persisting data to the store, but whenever MODEL-BINDING OPERATIONS are performed by MVC.
The  following validator attributes are supported:
   Range – checks if the value of a property is between a specified range.
   ReqularExpression – checks whether the value matches a specified regular expression.
   Required – sets a property as required.
   StringLength –  checks whether a maximum length for a string property is legal.
There is also the option of inheriting from the base class "Validation" in order to enforce custom validation.

Let's say we have an entity named "Comment" mapped to the database table Comment with the following properties:

Notice that the "Title" column holds strings up to 100 characters. We'll try to enter comments with a title longer than that, to check the Data Validation.
In order to check it, create a new test class in the Model folder:

This static class contain a method which just creates a new Comment, add it to the context, and tries to persist it to the database. The Data Model Validation of the Entity Framework will automatically refuse to do that and will throw an DbEntityValidationException:

The exception, however, doesn't reveal us which field caused it:

We' want to catch this exception in a friendly user way and inform what is causing the problem.
To do that, we'll create a MetaData class with the necessary Data Annotations, and extend the partial class Comment created by the Entity Framework to link it to the metadata file.

Therefore we'll extend the Comments class taking care to copy exactly the name of the class:

Copy this to a new file named CommentMetaData.cs, containing the following two classes:

First think we must do is adding the System.ComponentModel.DataAnnotations namespace to the entity class we want to validate:

Add an attribute setting the MetaData Class for the Comment class:

Now copy the properties you want to add validation to, from the original class Comment:

And paste them, adding the necessary validation attributes, specifying the maximal lenght of the Title:

Next, we'll add a View to create Comments, to see how it works:

Add the corresponding Action to the Home Controller:

And the ActionLink to the Menu in the _Layout.cshtml file:

Finally, add the Action to cope with Comments creation, on the Home Controller:

Rebuild the MVC project (F6) and browse to the Comments Page:

In it, type some valid data to check if it's saved correctly:

Check the data in the database. Yes, it was persisted:

Now type some invalid input, and try to save it:

The Message error that you wrote on the MetaData class is presented to the User to inform her/him that the length of the Title was illegal, and the Comment is not saved:

That's all!! 
Happy programming.....

כתב: כרמל שוורצמן