Simone has a great post (as usual) on 12 ASP.NET MVC Best Practices:
1 – Delete the AccountController
2 – Isolate controllers from the outside world
3 – Use an IoC Container
4 – So NO to “magic strings”
5 – Build your own personal conventions
6 – Pay attention to the verbs
7 – Domain Model != ViewModel
8 – Use ActionFilters for “shared” data
9 – NEVER use code-behind
10 – Write HTML each time you can
11 – If there is an if, write an HtmlHelper extension
12 – Choose your ViewEngine carefully
This is a fantastic list, and of course I have my own additions/suggestions First, I’m not a fan of action filters for shared data. If we’re doing strongly-typed views, using action filters for shared data puts us back into the magic string land, where we have to either use inheritance in our ViewModels, or the dictionary part of ViewData. I don’t like either approach, I’d rather go with something like RenderAction to truly enforce SRP in my ViewModels. Not everyone appreciates the elegance of this approach, but I’m sure they’ll agree eventually.
I also don’t like writing an HtmlHelper extension just because I have logic in the view. For a half-decent view engine, it shouldn’t be that problematic to have view logic in the view. HtmlHelper extensions enforce the Helper object anti-pattern – a bunch of procedural logic hanging off one static class. Instead, we went the route of building intelligent input builders for input elements, and only really using HtmlHelper when we want to eliminate duplication between multiple views. I see these constructs:
- Master Pages
All as means of eliminating duplication in our views, but not much more. If there’s logic in a view, that’s fine by me as long as it’s not duplicated. It’s not my fault that C# looks downright bizarre mixed in with HTML markup, but that’s what other view engines are for.
Finally, if there was an award for How Not to Design a Controller, the AccountController would be the runaway champ. I still can’t imagine why it’s necessary, and the idea of portable areas would be a better fit for its functionality than the Thing We Always Delete with Extreme Prejudice.