Matthew Jones

Validation is one of the key components in any web app. After all, we should never trust any input to our applications, ever. Up until now, my group has been building MVC-based web apps, in those apps we've been content to use built-in or custom-built validation solutions for any validation-type procedures we needed to write.

Now, though, we've transferred over to building a web service written in ASP.NET Web API, and the old validation structure we had in place just doesn't work very well in that new environment. Consequently we had to hammer out a new validation structure, and I'm particularly proud of how we set that up, so I wanted to share it here. Let me know if it helps you as well. First, though, a little background on how our app was set up.

Architecture of the App

Our app has the following layers:

Clients (ASP.NET MVC, iPhone apps, etc)
|
API (Web API)
|
Database

It's a pretty standard service-based application, at least from the 10,000-foot view.

The problem is that we want our validation to be performed in the API layer, and not make the clients responsible for implementing their own validation. In other words, we need to do the following:

Validate all incoming requests according to a set of rules.

Return any validation error messages to the calling clients.

We can tackle Problem 1 by using one of my favorite NuGet packages, FluentValidation.

In order to set up FluentValidation, we need to create a Validator class which inherits from AbstractValidator, and add a Validate attribute to the User class. Finally, we need to define the validation rules that apply to the properties of User. The final result looks like this:

Validating the Request

Now that we have the validation rules in place, we need a way to validate that all requests submitted to this service are valid. We can do this by using an ActionFilterAttribute. Remember that FluentValidation places validation errors into the ModelState so our ActionFilterAttribute will need to check the ModelState's status.

What this filter does is return a new error response if the submitted Request has validation errors. We know that ModelState.IsValid will represent whether or not the Request has validation errors because FluentValidation automatically inserts its errors into the ModelState.

Now we just need to add this filter to the Web API Pipeline in WebApiConfig.cs, like so:

Wrapping The Response

Now we come to a fundamental problem with this setup: the type of the response could be anything, yet we need to append existing validation errors to the response. To solve this, we created a simple ResponsePackage class:

Step 1: We wait for the response. After all, for this handler, we don't care about the request or anything besides the response.

Step 2: We get the response content. What that content is determines whether or not we need to run Steps 3-5.

Step 3: If the content is an error (of type HttpError), set the returned content to null.

Step 4: Insert the ModelState errors. We do this by reading the response content, deserializing that first to an anonymous object then to a JObject (using Json.Net) and finally extracting the error messages themselves.

Step 5: Create a new response.

Step 6: Add back the response headers (they should be the same in the new response as in the generated response).

In short, this wrapper will wrap all responses in an instance of ResponsePackage, and if there are any errors in the ModelState, those errors get included in the ResponsePackage.

The final step, of course, is to place the handler in the Web API Pipeline. We're done with all the steps, so here's the complete WebApiConfig.cs file:

This is, of course, what we expect. We violated two validation rules, and therefore got back two errors. Success!

Summary

This architecture allows us to do the validation on the Web API side of the app, and automatically include all validation errors in the response. We need two NuGet packages and three major pieces to implement this solution. The NuGet packages are FluentValidation.WebApi and Newtonsoft.Json, and the other pieces are as follows:

A ResponsePackage class which will have properties for both the result and the errors collection.

An ActionFilterAttribute that validates the ModelState and returns an error if it is invalid.

A DelegatingHandler which wraps all responses from the API into the ResponsePackage class.

I've got a sample project over on GitHub, go check it out, and let me know if it helps you with your projects in the comments.