Overview of MVC Model Binding
Model Binding is nothing more than mapping HTTP request data back to your Model’s properties or the parameters on an Action in your controller. If you follow the standard framework convention and use the standard editor templates, this will just work on its own with limited intervention on your part.
That being said, it is still good to understand what happens behind the scenes so that you can take advantage of everything that framework has to offer and won’t be fighting it. Also eventually you will encounter a scenario where the basic conventions won’t cover what you need.
ASP.NET MVC Model Binding – Part 1 [The Code Project]
Here the author gives a gentle introduction to what is going on behind the scenes. He distills everything down to a single Model a couple of views and a controller. In this simple example he works through a couple of different ways of posting the data back to the controller. The most intuitive way is explicitly listing out each field from the view as a parameter to the action. Then he shows an example using a method that expects an instance of the Model.
Finally he works through a couple of examples using the BindAttribute to influence the binding. He also touches on an interesting security issue here. You can use the BindAttribute to explicitly exclude individual properties from being mapped. This could potentially close the door on an attacker trying to inject values through the binding process.
This article dates back to the early days before the initial release of MVC. Some of the solutions offered are speculative and off base, but he does give a good explanation of the security concerns that I mentioned earlier. The more common solution in practice today is the ViewModel.
Using Model Binding to Receive File Uploads
A Back To Basics Case Study: Implementing HTTP File Upload with ASP.NET MVC including Tests and Mocks [Blog]
Scott Hanselman always is a treasure trove of information. This blog dates back to the early days of MVC,so some of the information may be a little dated and we will see a bit later easier ways to go about this, but sometimes you need to understand what is happening behind the scenes.
Scott gives a guided tour through the weeds of what is actually involved in HTTP. He also gives good guidance that is still relevant on mocking the unmockable.
Phill Haack is inspired by Scott’s blog that we just saw and two years later he makes this post to topple Scott in the search rankings. Not only did he succeed in supplanting this staple from the top of the search rankings, Phill shows off a very elegant solution by showcasing how much progress was made in MVC 2.0. This common task of uploading a file is made almost trivial with the introduction of Custom Value Providers. We will look at these marvels next.
Creating a Custom Value Provider
It turns out that it is really rather easy to create your own custom Value Provider. At the same time with the rich array natively provided by the MVC framework, you are not likely to need to. Out of the box you get:
- • FormValueProvider: Provides value from posted form parameters.
- • QueryStringValueProvider: Provides value from querystring.
- • HttpFileCollectionValueProvider: Provides value from posted files.
- • RouteDataValueProvider: Provides value from route parameters.
This is a pretty comprehensive list places where you might be interested in getting values.
Here, Artëm Smirnov found a missing built in Value Provider. In this article he steps through creating a custom Value Provider to pull values from the HTTP Headers.
Creating a Custom Model Binder
We now return to Mr. Hanselman as he steps through not just the mechanics of creating a custom binder but also some of the reasoning why. In this case, it is to improve testability. This is important because one of the main driving factors for MVC period is testability.
Not only do you get to see how to create a simple binder, Scott also shows you two ways to register your new binder. Unless you know for certain that you are going to use a binder in only one location, I prefer registering it in the global.asax.
A better Model BinderC [Los Techies]
Here Jimmy Bogard turns the idea of binder registration on its head. As Scott pointed out in the last article, when we register a binder, it is an exact match to an individual type.Jimmy wanted more flexibility such as specifying a binder for a base class and all derived classes, or every class in a namespace, or a binder for anything implementing a specific interface. To make this magic work, he starts with an interface:
public interface IFilteredModelBinder : IModelBinder
bool IsMatch(Type modelType);
This makes each binder responsible for determining whether or not it can handle binding the specified type using whatever test it wants.
The matching algorithm to find the appropriate binder becomes fairly straight forward:
public override object BindModel(ControllerContext controllerContext,
foreach (var filteredModelBinder in _filteredModelBinders)
return filteredModelBinder.BindModel(controllerContext, bindingContext);
return base.BindModel(controllerContext, bindingContext);
Since he derives from the DefaultModelBinder, if no one steps up to the plate, the default is still available as a fallback.
You may not need this level of flexibility, but this is an interesting case study in just how much customization is possible.