Before We Start
This post is based on the nightly builds of the ASP.NET Web API. The Web API team is constantly making improvements to the framework, and publishing them with nightly builds on NuGet. Click here for more information on getting setup with the nightly builds, there is a lot of exciting things in them.
I would also like to extend a giant thank you, to Youssef Moussaoui over at Microsoft for fixing the following defect. Without this fix, the IValidatableObject support outlined in this post would be much more difficult. So thanks Youssef!
And finally, to get the source code for the sample application ‘ResIt’ outlined in this post, click here. And as always no warranty for you!
Background
If you ask me what the most difficult aspect of Business Application Development is, I will say, quickly and confidently, validation! Add to the mix a distributed architecture like Http, and you have the makings for a real bugger of a problem. With rules on the server, rules on the client, and a pile of plumbing code in between, there is a plenty of opportunity for things to get mucked up. Yet, despite all of this complexity, we still need to provide the user a reasonable validation experience.
So all together now…Validation is hard!
With the ASP.NET MVC Framework we were given lots of fancy tools to help support the validation story. Of course, we got all kinds of DataAnnotation support, and with MVC 3 we were given another option with the added support for the IValidatableObject interface. But what does this have to do with the ASP.NET Web API? Well, as it turns out it has a lot to do with it. Because the ASP.NET Web API is build on top of the MVC framework the Web API can take advantage of many of the features that we all know and love in the MVC stack. Things like Action Filters, Routing, and of course all of the goodness that is Model Binding.
Model Binding Review
For a detailed description of Model Binding please look here. For now, here are the Cliff Notes. Model Binding is how form, querystring, and any other type of data coming in via the Http Request gets converted into the CLR types defined as the input parameters to our action methods. This magic allows us to work with typed .Net objects in our actions, as opposed to developers having to interrogate the HTTP Request directly. And this is my friend is a marvellous thing! Oh, but there’s more! Not only does Model Binding handle the nasty right to left mapping between the incoming HTTP Request and our .Net types. Model Binding validates our model using Model Validation, and it’s this part of the MVC stack that we are interested in, at least for this post.
Model Validation is the process where the framework takes our objects already created by Model Binding and inspects their properties for any DataAnnotations. If found, the Validate method of the each DataAnnotation is executed. This process then invalidates any objects that don’t meet the business rules as defined by the supplied DataAnnotation. So why is this relevant to the Web API? Simply put, because the Web API has complete Model Binding and Model Validation support, any of the techniques we use for validation in MVC is fair game. This includes both DataAnnotations and the IValidatableObject interface.
Boo To You Mr. Data Annotation
Generally speaking, I am not a fan of the ever so popular attribution method of validation. First of all they tend to break down as soon as something difficult arises. Secondly, they are not terribly explicit, and out of sight out of mind, right? Thirdly, and most importantly, I have never been able to figure out how to use the hooks for client validation when creating custom validators (Just can’t find the energy to do it). I will admit that in the context of ASP.NET MVC DataAnnotations do have one tantalizing benefit with the added JavaScript support (sometimes). However, with the ASP.NET Web API that benefit does not actually exist, after all we are not returning markup and JavaScript to the client, we are returning resources formatted in JSON or XML. With the absence of the JavaScript benefit, I assert that DataAnnotations make validation harder when working with the Web API, and as such, I avoid them as a rule.
One More Better Validation
The technique I am going to outline here is one that I have used successfully in several projects. It leverages one of my favorite open source frameworks, Fluent Validation, coupled with the WEB API’s support for the IValidatableObject interface. Using Fluent Validation, we will make individual validators for each our domain objects. These validators are both explicit and testable, both traits that get two thumbs up from me. Combing these validators with the Web API support for the IValidableObject interface, we will create what I consider a pretty slick solution to the validation problem.
How It Works
Before we get into the dirty details, let’s talk about the sequence events we are going to look at.
- Using JQuery, we send an invalid HTTP Post Request to our Web API
- Model Binding does its thing, converting the request into a Reservation object
- Model Validation honors the IValidatableObject contract, calling the Validate method of our Reservation object
- The Validate method delegates to our Fluent Validator, invalidating the Reservation object
- Our WEB API returns an HTTP Response, with a Status Code 400 (bad request) back to the client, along with a list of error messages
- jQuery unobtrusive will then render these errors to the screen
This image below illustrates the sequence of events using a super slick tool.

Basic Validation Sequence
Our Sample Application
Before we get into the meat of this example, I want to introduce to you our sample application. Our sample application is a fictional Reservation web site called ‘Resit’. Resit is a simple application, it consists of a single screen, that allows users to add reservations. In addition to the screen, we also have a Web API that will be responsible for the validation of our models and any data access required. Finally, we have a single domain object named Reservation. The Reservaion object implements the IValidatableObject interface and leverages Fluent Validation to execute any validation rules that may be needed.
The View
Our view is nothing more than a simple Html form with the following fields.
- First Name
- Last Name
- Reservation Date
It looks a little something like this (yeah I know it is not real purty!)

Not a Picasso
Not much going on here, just a simple HTML form taking advantage of the boilerplate MVC look and feel. Oh, and of course, the very ugly HTML 5 control that is rendered for dates automagically. Lets take a look at the code for the view.
@model BetterValidation.Models.Reservation
@{
ViewBag.Title = "ResIt!";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<header>
<div class="content-wrapper">
<div class="float-left">
<p class="site-title">
<a href="~/">ResIt</a>
</p>
</div>
</div>
</header>
<div id="body">
<section class="featured">
<div class="content-wrapper">
<hgroup class="title">
<h1>Welcome To ResIt!</h1>
<h2>A generally useless reservation system</h2>
</hgroup>
<p>
ResIt allows you to create a reservation. Your reservation will not be saved to any kind of database. You will not be
able to edit your reservation. But you will be able to see validation messages. 🙂
</p>
<p>
To learn more about FluentValidation Visit
<a href="http://fluentvalidation.codeplex.com/" title="FluentValidation">FluentValidation</a>.
<br />
<br />
To learn more about Me Visit <a href="http://www.brette.net" title="Brette.Net">Brette.Net Consulting</a>.
</p>
</div>
</section>
<section class="content-wrapper main-content clear-fix">
<h2>Create A New Reservation</h2>
<form id="createReservationForm">
<fieldset>
<legend>Reservation</legend>
<div class="editor-label">
<label class="required" for="FirstName">
First Name</label>
</div>
<div class="editor-field">
<input class="text-box single-line" id="FirstName" name="FirstName" type="text" />
<span class="field-validation-valid" data-valmsg-for="FirstName" data-valmsg-replace="true" />
</div>
<div class="editor-label">
<label class="required" for="LastName">
Last Name</label>
</div>
<div class="editor-field">
<input class="text-box single-line" id="LastName" name="LastName" type="text" />
<span class="field-validation-valid" data-valmsg-for="LastName" data-valmsg-replace="true" />
</div>
<div class="editor-label">
<label class="required" for="Date">
Date</label>
</div>
<div class="editor-field">
<input class="text-box single-line" id="Date" name="Date" type="date" />
<span class="field-validation-valid" data-valmsg-for="Date" data-valmsg-replace="true" />
</div>
<input type="button" id="cancelButton" value="Cancel" />
<input type="submit" id="saveButton" value="Save" />
</fieldset>
</form>
</section>
</div>
@section scripts{
<script type="text/javascript">
$('#createReservationForm').submit(function (submitEvent) {
submitEvent.preventDefault();
var form = $('#createReservationForm');
$.validator.unobtrusive.parse(form);
if (form.valid()) {
$.ajax({
url: "api/Reservation/Create",
data: $("form").serialize(),
type: "POST",
statusCode: {
200: function () {
clearErrors($('#createReservationForm'));
alert("You created a reservation");
},
400: function (response) {
var validationErrors = $.parseJSON(response.responseText);
$.each(validationErrors.ModelState, function (i, ival) {
remoteErrors(form, i, ival);
});
}
}
});
}
});
</script>
}
The Form
The first thing you will notice is the presence of our Html form. A simple little form that contains the inputs for the First Name, Last Name, and Date. Additionally we also have included the data-attributes required to support jQuery validation. Finally, you will see the empty span element that will eventually render our error messages sent back from our Web API.
The JavaScript
Of course, no html form is complete without a bunch of messy JavaScript at the bottom of the screen, and this form is no exception! Looking at the JavaScript, we are really only doing a few things. First, when the form is submitted I use JQuery to make an Ajax HTTP Post Request to our Web API. With it, I send along the serialized form data. If the HTTP Response comes back with a HTTP Status Code 200 (OK), I pop up a very visually pleasing alert dialog, indicating that the reservation has been created. If, however, the HTTP Response from the server has a HTTP Status Code 400 (Bad Request), I do a few additional things. First, I parse the responseText converting the returned JSON into a living and breathing JavaScript object. I then iterate over the errors in the Model State calling the remoteErrors method (more on this later). For now just know that the remoteErrors function is responsible for rendering the error messages to the screen.
Reservation Object
Next lets talk briefly about our Reservation object. This is not very exciting containing only a few properties (FirstName, LastName, Date) however one important thing to notice is that it implements the IValidatableObject interface. And if you remember our conversation about Model Binding you will know that both the the MVC framework and the Web API honor this contract when running through the Model Validation process.
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using BetterValidation.Extensions;
using FluentValidation;
using ValidationContext = System.ComponentModel.DataAnnotations.ValidationContext;
namespace BetterValidation.Models
{
///
/// Simple Domain Object
///
public class Reservation : IValidatableObject
{
#region Private Members
private readonly IValidator _validator;
#endregion
#region Properties
///
/// Gets or sets the date time.
///
///
/// The date time.
///
public DateTime DateTime { get; set; }
///
/// Gets or sets the name.
///
///
/// The name.
///
public string FirstName { get; set; }
///
/// Gets or sets the name.
///
///
/// The name.
///
public string LastName { get; set; }
#endregion
#region Constructor
///
/// Initializes a new instance of the class.
///
public Reservation()
{
_validator = new ReservationValidator();
}
#endregion
#region IValidatableObject
///
/// Determines whether the specified object is valid.
///
///The validation context.
///
/// A collection that holds failed-validation information.
///
///
public IEnumerable Validate(ValidationContext validationContext)
{
return _validator.Validate(this).ToValidationResult();
}
#endregion
}
}
IValidatableObject gives us a single method aptly name Validate. This method takes in a ValidationContext object, and as you can see simply delegates to our ReservationValidator (a Fluent Validator) object. During Model Validation, the Web API will call this method on any object that implements this interface giving us a chance to run any validation rules for each object as its Model Bound.
Reservation Validator
This class represents all of the business rules for our Reservation object. Notice that it derives from the AbstractValidator<T> class. This class is one of the base classes available to us from the Fluent Validation framework. The only other interesting thing here is the rule definitions in the constructor of our validator. Notice I create two rules, the first, requires the FirstName property to be valued, and the second, requires the LastName to be valued.
using FluentValidation;
namespace BetterValidation.Models
{
public class ReservationValidator : AbstractValidator
{
///
/// Initializes a new instance of the class.
///
public ReservationValidator()
{
RuleFor(item => item.FirstName)
.NotEmpty();
RuleFor(item => item.LastName)
.NotEmpty();
}
}
}
The last thing I want to point out here, is a simple extension method I have added to the FluentValidation.Results.ValidationResult type. This extension method simply converts the FluentValidation ValidationResult type to the System.ComponentModel.DataAnnotations.ValidationResult type that both the MVC and the Web API expect. It’s only a few lines of code, but this is required since the types are actually different.
using System.Collections.Generic;
using System.Linq;
using ValidationResult = System.ComponentModel.DataAnnotations.ValidationResult;
namespace BetterValidation.Extensions
{
/// <summary>
/// Extension to the Fluent Validation Types
/// </summary>
public static class FluentValidationExtensions
{
/// <summary>
/// Converts the Fluent Validation result to the type the both mvc and ef expect
/// </summary>
/// <param name="validationResult">The validation result.</param>
/// <returns></returns>
public static IEnumerable<ValidationResult> ToValidationResult(
this FluentValidation.Results.ValidationResult validationResult)
{
var results = validationResult.Errors.Select(item => new ValidationResult(item.ErrorMessage, new List<string> { item.PropertyName }));
return results;
}
}
}
So Far
Just a quick recap. So far we have a Simple view with a Html form, a Reservation domain object that implements IValidatableObject, a single Validator object called ReservationValidator. Based on what we now know about Model Binding and Model Validation, we know that when our form is posted to our Web API, Model Validation will call the Validated method on our Reservation object. That method creates the instance of the ReservationValidator, and all the validation rules are executed. The results are converted into the System.ComponentModel.DataAnnotations.ValidationResult object that is eventually stuffed into Model State and streamed back to our client.
Our Web API
The last major component of our validation solution is our Web API, this is, after all what the post is all about right?
using System.Net;
using System.Net.Http;
using System.Web.Http;
using BetterValidation.ActionFilters;
using BetterValidation.Models;
namespace BetterValidation.Controllers
{
public class ReservationController : ApiController
{
[ValidationResponseFilter]
public HttpResponseMessage Post(Reservation reservation)
{
return Request.CreateResponse(HttpStatusCode.OK, reservation);
}
}
}
Looking at the ReservationController, you know this is our Web API because it derives from ApiController. Our Web API boasts a single Post action; this action takes in an instance of our Reservation domain object, created for us by Model Binding of course. Assuming there are no validation errors, this action simply streams the reservation back to the client with a HTTP Status Code of 200 (OK), and all is well with the world. However, what happens if the incoming HTTP Request is incomplete, or if it’s invalid? How can we communicate this information back to the client? This brings us to the ValidationResponseFilter that decorates our fancy Post action.
Action Filters a Primer
Just a quick refresher on Action Filters. Action Filters are a terrific way to support cross cutting concerns in our applications. As such, they let us execute code just before an action is executed by overriding the OnActionExecuting method. They also let us execute code just after an action executes by overriding the OnActionExecuted method. This gives us a excellent way to add aspect oriented behavior to any action by simply decorating an action method with an attribute. One important thing to note about the OnActionExecuting method is that it executed after the Model Binding process. What this means is, that by the time the OnActionExecuting method is executed, both Model Binding and Model Validation have already run. This results in any validation errors being stuffed into Model State just before our action filter is executed. Using this little tidbit of life cycle knowledge we can do something pretty slick. Enter the ValidationResponseFilter!
ValidationResponseFilter
Looking at the action filter below, notice the implementation of the OnActionExecuting method is checking to see if any validation errors were found. After all, Model Binding has already done its magic, so all errors would be present in Model State at this point. If the Model State is invalid, I ask the HttpRequest object to create for us a special kind of HttpResponse using the CreateErrorResponse method. This overload is special because it actually takes in as an input parameter the Model State information containing all of the validation errors. Using the Model State information, CreateErrorResponse creates an HttpResponseMessage that includes a list of validation messages in such a way that JavaScript frameworks like JQuery can consume them. So by simply annotating a method with this attribute, any validation errors found during the Model Validation process are sent back to the client structure in a JavaScript friendly way.
using System.Net;
using System.Net.Http;
using System.Web.Http.Filters;
namespace BetterValidation.ActionFilters
{
public class ValidationResponseFilter : ActionFilterAttribute
{
///
/// Called when [action executing].
///
///The action context.
public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
{
if (!actionContext.ModelState.IsValid)
{
//actionContext.ModelState.Keys
actionContext.Response = actionContext
.Request
.CreateErrorResponse(HttpStatusCode.BadRequest, actionContext.ModelState);
}
}
}
}
Remote Errors
The last thing I need to touch on, is the JavaScript method remoteErrors. This method is called when our Web API returns a Http Status Code 400 (Bad Request), and it has a few responsibilities. First, it is in charge of inspecting the Model State errors that came back from the server and locating the related input elements. This is done by parsing the dot path information supplied in Model State, and matching it to the data-valmsg-for data attribute of our input controls. Once found, the correct style is applied, and the error message is placed the span element next to the input control. This approach was inspired from a post I found on stack overflow, you can find it here. I have found this to be a pretty straight forward way to deal with the Model State errors that come back from the server. While I am sure there are a million other ways you can do the same thing, I found this to be clean and simple, so I ran with it.
function remoteErrors(jForm, name, errors) {
function inner_ServerErrors(name, elements) {
var ToApply = function () {
for (var i = 0; i < elements.length; i++) {
var currElement = elements[i];
var currDom = $('#' + name.split('.')[1]);
if (currDom.length == 0) continue;
var currForm = currDom.parents('form').first();
if (currForm.length == 0) continue;
if (!currDom.hasClass('input-validation-error'))
currDom.addClass('input-validation-error');
var currDisplay = $(currForm).find("[data-valmsg-for='" + name.split('.')[1] + "']");
if (currDisplay.length > 0) {
currDisplay.removeClass("field-validation-valid").addClass("field-validation-error");
if (currDisplay.attr("data-valmsg-replace") !== false) {
currDisplay.empty();
currDisplay.text(currElement);
}
}
}
};
setTimeout(ToApply, 0);
}
jForm.find('.input-validation-error').removeClass('input-validation-error');
jForm.find('.field-validation-error').removeClass('field-validation-error').addClass('field-validation-valid');
var container = jForm.find("[data-valmsg-summary=true]");
list = container.find("ul");
list.empty();
if (errors && errors.length > 0) {
$.each(errors, function (i, ival) {
$("<li />").html(ival).appendTo(list);
});
container.addClass("validation-summary-errors").removeClass("validation-summary-valid");
inner_ServerErrors(name, errors);
setTimeout(function () { jForm.find('span.input-validation-error[data-element-type]').removeClass('input-validation-error') }, 0);
}
else {
container.addClass("validation-summary-valid").removeClass("validation-summary-errors");
}
}
function clearErrors(jForm) {
remoteErrors(jForm, []);
}
Summary
Validation is hard. In a distributed environment it’s harder. With so many moving parts and so many disparate technologies involved (Html, JavaScript, C#, Http), it can be a challenging thing to do in a testable and maintainable way. While there are many different ways one can approach this problem, the solution I have outlined here has held up to most requirements I have had to deal with when using the ASP.NET Web API. By avoiding DataAnnotations, and plugging into the support IValidatableObject interface, we can create clear, testable Validator objects, and still take full advantage of the Model Binding support of the framework. By leveraging the built in support given to us by CreateErrorResponse, we can send validation information back to the client in ways that are JavaScript friendly. This gives the illusion of client side validation with the power of the server. It also removes the need to write validation rules twice (once on the client, and again on the server), and that is a benefit I think we can all appreciate!
BDN