Say I have an object that gets some data from HttpPost and some from the database. I think I want to allow the ModelBinder to go to the database/repository for the that data missing from the post. In practice, is this a good or bad idea?
I would say, no.
Here's why: It would create a dependency on your database for testing your controller actions that would not be easy to abstract out.
I would say a bad idea. The idea of the model binder is that it takes the parameters from the request and creates your model from those. If your model binder, behind the scenes, fills in some of the details from the database this breaks the paradigm. I'd much rather expose the database call in my controller by explicitly fetching the required extra data from the database directly. Note that this could be refactored into a method if used frequently.
I think this is perfectly fine and use this technique all the time.
The only arguments against are very pedantic and amount to arguing over philosophy. IMHO you can put "fill in missing posted data" code into you MVC app as a method in your base controller vs. method in you ActionFilter vs method in you ModelBinder. It all depends on who get what responsibility. To me the model binder can do a lot more than simply wire up some properties from posted values.
The reason I love doing database calls in my modelbinder is because it helps clean up your action methods.
//logic not in modelbinder
public ActionResult Edit( KittyCat cat )
{
DoSomeOrthagonalDatabaseCall( cat );
return View( new MODEL() );
}
vs.
//logic in model binder
public ActionResult Add( KittyCat cat )
{
return View( new MODEL() );
}
It violates the way MVC is supposed to work. ModelBinder is for binging Models from the data that comes from the view. Populating missing info from the database is something that is supposed to be handled by the controller. Ideally, it would have same data layer/repository class that it uses to do this.
The reason it should be in the controller is because this code is business logic. The business rules dictate that some data may be missing and thus it must be handled by the brains of the operation, the controller.
Take it a step further, say you want to log in the DB what info the user isn't posting, or catch an exception when getting the missing data and email admins about it. You have to put these in your model binder this way and it gets more and more ugly with the ModelBinder becoming more and more warped from its original purpose.
Basically you want everything but the controller to be as dumb and as specialized as possible, only knowing out how to carry out its specific area of expertise which is purely to assist the controller.
Upon encountering Model Binders for the first time, my first instinct was that they shouldn't be used to do anything beyond populating a complex type with user input. This thinking may have been the result of some indirect conditioning I picked up from the book I was working through, or from the fact that that's how I'd always done things with previous MVC-based frameworks as well as MVP implementations in the past, but it only took me a few days to consider that I really didn't have any good justification for this thinking.
Model Binders are about translating a user request into a more object-oriented request for the controller to operate upon. If the request data represents a persisted entity, why shouldn't it be passed directly to the controller? Is it because one person says it couples the model binder to the database? Uh, that's just if you're using some 1990's approach to database access. So that isn't a good reason. Is it because another thinks it breaks some paradigm or that they would just rather do it from the controller? Well, that's not really a reason either now is it. Is it because the framework designers didn't mean for you to use them that way? Well, I haven't actually come across anything that indicates this, but even if they did say they didn't mean for us to use them that way, is that a good enough reason?
I'm not saying there isn't necessarily a reason, but thus far I can't think of one. It doesn't violate any principles I'm aware of and upon further reflection it actually seems more object-oriented IMO, so for now I'm gonna keep and open mind on how this new (to me) construct can be leveraged.