In the last posts I’ve talked about the use of Moq framework when writing ASP.NET MVC unit tests. Today, I will be talking about ASP.NET MVC Model Binding mechanism and how to extend it to make your life easier when writing testable web applications. [I have written a similar post on SharpShooters blog, but it is in portuguese]
Basically, Model Binding is the mechanism that ASP.NET MVC framework uses for mapping HTTP Request variables into Actions’ parameters. In other words, every time you submit a form to a Controller, the Model Binding mechanism passes through all variables submitted trying to match them with Actions’ parameters using a very specific standard. The standard is “parameterName.PropertyName”. To illustrate how things happen, let’s use a small example. Imagine that we want to implement a blog platform which allows the creation of posts with title and content. Model, View and Controller for creating it are illustrated below:
As you already know, the Create Action receives newPost parameter with all the information submitted in the form. However, if the ASP.NET MVC Team hadn’t implemented Model Binding, we would need to type something like this:
In short, Model Binding is responsible for binding values passed in HTTP Requests to Actions’ parameters.
Now that we already know what Model Binding is about, we can extend it to bind any parameter we want. Imagine that we want to add a User to a Post. Class and Controller would have to change to something similar to this:
Although this code works, it is very difficult to test since I need to mock User.Identity.Name. I can mock it using a technique presented by Michael Feathers in his excellent book Working Effectively With Legacy Code which basically involves two steps:
1. Extract the piece of code in a protected virtual function;
2. Create a mock which inherit from PostController and overrides the protected function by returning a specific username;
PostController class would result in the code below.
And here is the test for the controller class.
Now, the test pass
However, every time that a User is referenced by other class, this approach is needed. Imagine we have another entity, for example Comments, which has a reference to User as well. The same solution would be used to test CommentsController class. It would be great if we could pass the User as a parameter in PostController.Create action, wouldn’t be? Something like this:
To do that, we need to extend ModelBinding mechanism so it can bind the value of a User type. This is really simple. All we have to do is implement IModelBinder interface and register it in the Global.asax. The code below shows the extension.
Everything is now configured and we don’t need to worry about retrieving the logged user anymore.
In adittion to that, it’s much more easy to test PostController class. We can create a new user and pass it as parameter, as shown below.
To conclude, Model Binding is a very importante feature of ASP.NET MVC framework, saving us a lot of work. It is also extensible and allows us to create our own bindings and testable applications.
Hope it’s usefull for you someday