OdeToCode IC Logo

Principles, Code-Behind, & View Engines

Monday, June 29, 2009

The July issue of MSDN Magazine is available online with my article “Guiding Principles For Your ASP.NET MVC Applications”. Another MVC article in this issue is Justin Etheredge’s “Building Testable ASP.NET MVC Applications”. Justin’s article is a good one as he shows you how to design for testability, and includes specific examples with xUnit.net, moq, and Ninject.

Something we both touched on was the topic of code-behind files.

Code-Behind and ASP.NET MVC

The conversation between two developers (let’s call them Pushy and Principled), goes like this:I WANT CODE-BEHIND!!

Pushy: Is it OK to use code-behind files with aspx views?

Principled: No.

Pushy: But, I have something that’s really, really specific to this one particular view. That’s OK, right?

Principled: No.

Pushy: Oh, come on! You aren’t being pragmatic here. I don’t want to add a Page_Load, I just need a teeny tiny little instance method. I’ll add a code-behind file and stick it inside. It’s tiny! That’s OK, right?

Principled: No.

Pushy: Really now, what do you expect me to do? Build one of those forsakenly awful HTML helper methods with more overloads than the California power grid in August? Don’t you think it’s better to put the code close to the view that uses it?

Principled: No.

This is one scenario where I’d side with Principled. Sure, the code-behind could be simple. Sure, if you are careful it might even be unit-testable. But, the mere fact that code-behind is possible is a fluke and a byproduct from building on an existing framework. Someone writing an MVC view engine from scratch wouldn’t need to provide such a feature that allows you to put anything resembling intelligence near a view.

All of the problems I’ve seen described where code-behind is a solution could easily be solved with an HTML helper, or by using a more robust presentation model that is passed to the view. Some people worry about a proliferation of HTML helpers, but if you absolutely need a helper scoped to a specific view, you can always put the helper in a different namespace that only that particular view will use.

I know your team is disciplined. I know you wouldn’t do anything wrong. I know you want to be pragmatic and do the simplest thing that works. But, think of the first code-behind file in a project as the first broken window. It’s another degree of freedom where entropy can wiggle into your software and undermine maintainability. It’s making a view smarter, which your principles should suggest is wrong.

Thoughts?