Model Validation in Web API

In this article we will understand a very important concept of MVC architecture called “Model validation”.

In our previous article we learned some important concepts of the Web API. You can read them here.

This article explains a very important concept of MVC architecture called “Model validation”. As we know MVC is on top of ASP.NET and the Web API is a data supply mechanism built on top of the MVC architecture. We know that many concepts of MVC are inherited by the Web API and Model Binding is one of them.

If you are very new in Model validation then the following paragraph is for you and Model validation in MVC and Web API are very similar, once you understand the concept you can implement it anywhere. We know that the MVC architecture provides the idea of a Model, View and Controller and a complete separation of concerns.

If we compare the traditional three-tier architecture with MVC then we will find that the DTO layer is replicated into the Model part of MVC that is nothing but our well-known class definition. We know that class contains many property and data members that are again mapped with some persistent storage area, very often a column of a Database table.

Ok, fine. I understood but why do we need to validate a model? Let me ask the reverse question, why not validate a model? Because, we know that the data that an entity of a model will be saved in a database. Now, what mess will happen if we save a model object in our persistent storage without validating it?

Now, you may ask, there are many ways to validate input data and we can adopt one of them in our application. Yes, you have made a good observation of the application lifecycle and phases. Now, let me answer the question.

For example, there is a form in your application where the front-end developer is working. It's his responsibility to validate input fields, but if a mistake by the front end developer fails to validate any field then the reult can affect the model validation stage. You may even implement input validation at the DB level too to be confirm that no garbage data is saved in the DB, anyway this is not our area of interest in this article.

We will see Model validation using Data Annotation with an example. To implement this example, please create one demo application of the Web API and add one API controller to the application. In our example we have implemented the following controller.

  1. public class PersonController : ApiController  
  2. {  
  3.     public bool Post([FromBody] person p)  
  4.     {  
  5.         if (ModelState.IsValid)  
  6.         {  
  7.            return true;  
  8.         }  
  9.         return false;  
  10.     }  
  11. }  

 

Please note that the Person controller is inherited from ApiController, not the normal MVC controller. The advantage of the Web API controller is that we can return a HTTP message from the controller.

There is only one method within the controller that is taking an object of the person model (we will create it very soon). Within the if condition we are checking whether the model state is valid or not. If the model state is valid then we will return “true” otherwise “false” , though it's not a good practice to return true/false from an API controller, we will correct it in the next example.

Fine, we will now implement the Model and will decorate the property with the validation attribute.
  1. public class person  
  2. {  
  3.     [StringLength(7), Required]  
  4.     public string Name { getset; }  
  5.   
  6.     public string surname { getset; }  
  7.     [Range(0, 99)]  
  8.     public Int16 age { getset; }  
  9.   
  10.     [RegularExpression("^[0-9]*$")]  
  11.     public string PhoneNo { getset; }  
  12.   
  13.     [RegularExpression(@"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$")]  
  14.     public string Email { getset; }  
    }  
This is the model implementation with 5 properties. The attribute over each property is very descriptive and easy to understand. Don't forget to add the following:

using System.ComponentModel.DataAnnotations;

attribute to enable data annotation in the application. Fine, we have finished our setup; now we can run the application.

Here is a format of JSON data that we will pass from the request body.

{"name":"sourav","surname":"kayal","age":26,"PhoneNo":"123456789","Email":"sourav.kayal@yahoo.com"}

In Fiddler we are attaching the message with a HTTP message body and the point to make is, it's valid data and the application should return a true message from the controller. Here is the data in Fiddler.



Now, we are seeing that the same data has come into the controller as in the following:



And if we analyze the HTTP response message , we will see that it has returned a “true” value.



Fine, so the validation is true for that data, now try to pass some invalid data to the controller. Here is one sample of invalid data that should fail in the validation.
  1. {  
  2.    "name":"souravkayal",  
  3.    "surname":"kayal",  
  4.    "age":200,  
  5.    "PhoneNo":"123456789!@#",  
  6.    "Email":"sourav.kayal@@yahoo.com"  
Once we run the application, we will see that the same data has come in controller.



And the controller has returned false, which means the model is not validated.



Ok, we now know how to validate our model, but how will we know what's wrong in our data and why the validation fails? The solution is very simple. We will just return the Model state with the response message and it will provide us a complete validation message. Then we are able to understand easily why the validation failed.

For that, we must change our controller implementation, a little. Now we are returning a HTTP response message rather than “true” or “false” as in the previous example.
  1. public class PersonController : ApiController  
  2. {  
  3.    public IHttpActionResult Post([FromBody] person p)  
  4.    {  
  5.       if (ModelState.IsValid)  
  6.       {  
  7.          return Ok();  
  8.       }  
  9.       return BadRequest(ModelState);  
  10.    }  
    }  
Once we run the application, we will get this message in Fiddler.



It's a lengthy message , so it's not possible to view in the screen entirely, I have provided the same message in the following.
  1. {  
  2.    "Message":"The request is invalid.",  
  3.    "ModelState":{  
  4.    "p.Name":["The field Name must be a string with a maximum length of 7."],  
  5.    "p.age":["The field age must be between 0 and 99."],  
  6.    "p.PhoneNo":["The field PhoneNo must match the regular expression '^[0-9]*$'."],  
  7.    "p.Email":["The field Email must match the regular expression '^([\\w\\.\\-]+)@([\\w\\-]+)((\\.(\\w){2,3})+)$'."]  
  8. }  
Conclusion

In this example we learned how to implement Model validation using the data annotation technique in the Web API. I think many of you understand the concept in MVC but may not know that the same is applicable in the Web API too.