Data Validation in ASP.NET MVC Database First

Every web application requires data validation to ensure that the data remains correct and useful. If you’re working with ASP.NET MVC, the good news is that the framework greatly simplifies this task. In this article, I’ll go over how to handle data validation when using the database first approach.

There are several great articles online on how to add data validation to an MVC project(including one over at the official ASP.NET site), but in general they all focus on the code first approach, which differs from the database first approach.

Database Setup

To start, we need to create a new database and then create an entity model from that database in our MVC project. If you’re unsure how to go about doing that, read this tutorialfirst. To keep is as simple as possible, I’ve created a database with only one table called “Products”.

The Controller

Next, we’ll create a Controller called ProductsController using the template called “MVC controller with read/write actions and views, using Entity Framework”. Select your Data context class in the appropriate field, and set the Model class to be our Product model. This will also generate all the appropriate Views which will contain code to display any validation error messages.

Validation

Now, data validation is done in MVC using data annotation attributes which get added to specific properties in the model class. The reason this doesn’t work for the database first methodology is that any attributes you add to a model class will get removed and overwritten when you update your data model after making a database change. The solution, then, is theMetaDataType attribute.

The MetaDataType attribute allows you to assign a metadata class to an entity partial class. This metadata class can contain all the required data annotations for data validation, but is not contained directly in the generated model class so it doesn’t get overwritten. In order to use this, we’ll create a new partial Product class, a new class strictly for metadata, and then we’ll bind the new metadata class to the partial Product class. This can all be accomplished like so:

namespace MvcApplication1
{
    [MetadataType(typeof(Product.Metadata))]
    public partial class Product
    {
        private sealed class Metadata
        {
            [Required(ErrorMessage = "Product Name is required")]
            public string Name { get; set; }
        }
    }
}

The Metadata class can be placed anywhere, although I’ve placed it inside the partial class because that’s the only place that it will ever be used. Inside the Metadata class, I’ve specified that the Name property inside the Product class should be required.

Other useful validation attributes include StringLength, Range, and RegularExpression. It is also possible to create custom validation attributes by deriving from either ValidationAttributeitself, or any existing attribute(such as RegularExpression, for custom RegEx validation).

Running the Code

Now let’s go see how this all works. Run your application, and navigate to /products/create. Leave the “Name” field blank, and fill in a value for the “Category” field. When you click “Create”, you should get a data validation error.

If you have client-side validation enabled(which it should be by default), you will notice that the page never refreshed, meaning that the server was never hit. All the validation actually happened on the client-side. If you disable client-side validation, you will get the exact same result except the page will refresh first before returning the error message. On the server, validation errors are checked for by using the ModelState.IsValid property, like so:

[HttpPost]
public ActionResult Create(Product product)
{
    if (ModelState.IsValid)
    {
        db.Products.Add(product);
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(product);
}

And that’s all there is to it! The sometimes tedious job of writing metadata classes for all of our model classes still remains, but the MVC framework takes care of everything else, meaning it takes almost no time at all to get both client and server side validation up and running.

Questions? Let me know in the comments below.

You may also like

Leave a comment