In computer science we've been taught that each method should do one thing and one thing only. I'm a little confused then that we see MVC actions like the following given as examples of good practice:
[AcceptVerbs(HttpVerbs.Post), Authorize]
public ActionResult Edit(int id, FormCollection collection) {
Dinner dinner = dinnerRepository.GetDinner(id);
if (!dinner.IsHostedBy(User.Identity.Name))
return View("InvalidOwner");
try {
UpdateModel(dinner);
dinnerRepository.Save();
return RedirectToAction("Details", new { id=dinner.DinnerID });
}
catch {
ModelState.AddModelErrors(dinner.GetRuleViolations());
return View(new DinnerFormViewModel(dinner));
}
}
Basically this piece of code provides a lot of functionality:
- Defines how to access the Action - Post only
- Defines who can access the Action - Authorize
- Accesses persistence mechanism - dinnerRepository
- Accesses state information - (User.Identity.Name)
- Converts NameValueCollection to strongly typed object - UpdateModel()
- Specifies 3 possible ActionResults and content for each - InvalidOwner/Details/Edit views
To me this seems like too many responsibilities for one method. It is also a fairly simple action ie it doesn't deal with common scenarios like:
- Checking business rules - "Never trust user input"
- Navigation paths - On successful save always returns to "Details"
- Different return types - Someone wants to call "Edit" from a grid and needs a JsonResult?
- Better error handling - YSOD if the database is not accessible during GetDinner(id)
- Constructing additional view data - SelectLists for Drop down lists
Not too mention the amount of testing required around this single method i.e. mocking/faking for FormCollection/UserIdentity/Authorization Provider/Repository/etc.
My question is how do we avoid cramming so much stuff into our controller actions?
I tend to think "opinions" are a great concept, especially the "Thunderdome Principle". While I have great respect for the guys involved with building FubuMVC and their reasons behind doing so, I need something I can use right now.
Edit - Well it seems I was after something like this - Opinionated Controller. I'll need to examine it further as it's for MVC Preview 5 so i may need to update it myself.