Steve Smith's Blog

Musings on Software and the Developer Community

Codebehind Files in ASP.NET MVC are Evil

imageWith the current versions of ASP.NET MVC (Preview 5) that have shipped, the default MVC template sites all include codebehind files for the ASP.NET views.  For example, here's a screenshot of what a new project looks like the one at right.  Further, adding a new ASP.NET MVC View Page will also include a .aspx.cs and a .aspx.designer.cs file by default.

The question is, why is that codebehind file there, and what are the consequences of having it there by default?  If you watch a few screencasts and blog tutorials from Rob, Phil, ScottGu, ScottHa, et al, it's pretty rare that you'll find anybody actually putting any real code into the codebehind files for the views.  In fact, I'm hoping that in addition to negating the need for codebehind files (there is one - wait for it), Microsoft can also take the next available opportunity to use a different file extension for views to make it incredibly, abundantly clear that they are not to be used like traditional ASP.NET web forms.

Why Are They There?

Today, codebehind files are useful if you want to have a strongly typed View<T>.  The easiest way to achieve this is to edit the codebehind file and change:

public partial class Register : ViewPage

to

public partial class Register : ViewPage<Customer>

and voila! Now you can reference Customer in a strongly typed fashion from your View's ASPX file, off of ViewData.Model.  Apart from this, the codebehind file may be a useful place to store some display-only functionality or a property that makes accessing a piece of ViewData simpler.  Both of which could also easily be done inside the ASPX page - it's just a matter of personal preference.

Tomorrow (as in, with some future release, I'm guessing), codebehind files may be important for interacting with custom controls.  Today that story just isnt' fleshed out yet.

Getting a View to work without a codebehind is simple provided you don't need a strongly typed view:

<%@ Page Inherits="ViewPage" %>

One could still achieve strongly typed views, if they were important, by using the generic backtick notation like this (if VS supported it, which I'm not able to get working so I'm assuming it does not today):

<%@ Page Inherits="ViewPage`1[Customer]" %>

Why are Codebehind Files in Views Evil?

The problem with having a codebehind file for a View comes down to temptation and habit.  If it's there, anybody who's been using "classic ASP.NET" for the last 8 years or so is accustomed to putting all kinds of things into the ASP.NET codebehind files.  From click handlers to Page_Load to event wireups to changing display settings based on the value of a data item - most web forms apps have a ton of logic in their codebehind files.  And that's great - but not typically how it should be done with ASP.NET MVC.

With ASP.NET MVC, the View should be dumb.  It should be stupidly simple.  It should have no logic in it to speak of, not least of all because it's difficult to test, but also because that's the Controller's whole purpose in life.  If you need to do any kind of business logic, it should happen in the Controller.  Need to format something a particular way if it's outside of a particular range?  Great, do it in the controller and pass the necessary CSS string into the View as ViewData.  Then write a test that proves it works.  Beautiful.

Having a codebehind file is a temptation.  Developers who are new to ASP.NET MVC (and who isn't - it's not even a year old and not released yet) but who have a background with web forms (as most will) are going to have to resist a natural inclination to put code into their codebehind files like they always have.  This will make the logic in the View more difficult to test and at worst might even involve logic in the codebehind making calls directly to a database or web service and thus completely bypassing the separation of Model from View as well.

And of course while we're removing the Codebehind files from the default template, we'll want to remove the .designer.cs/vb files as well!

Fall into the Pit of Success

If having the codebehind file available by default is a temptation to stray from the canonical correct MVC path, then not having it there by default would help most developers do things the right way without thinking about it.  That's what is meant by helping them to fall into a "pit of success" (not sure who came up with that term, but kudos for it).  Sure, some might simply add in a codebehind file (this would still be simple to do) or just write a bunch of complex logic within the ASPX file, but many more would do the right thing and place this logic in their Controller.  New developers joining their first ASP.NET MVC project would immediately realize that Views were not the same as Web Forms because they lack the codebehind files typical of web forms.  And the 95% of Views that don't need a codebehind file for anything would have half as many files cluttering their solutions, without the need for manual deletion of the .aspx.cx / .aspx.vb files.

Some folks really want to have codebehind files included.  I think they're a small minority, and if/when codebehind files are necessary for a View, it will still be simple to Right-Click->Add File to get one.  But in the default case, when a new View is added to an ASP.NET MVC project (or when a new project is created from the default template), it would only include the ASPX file(s) (and perhaps in a later rev of Visual Studio/ASP.NET, an ASVX file), and no codebehind or designer files.

kick it on DotNetKicks.com

kick it on DotNetKicks.com

Wednesday, 17 September 2008

Comments

 avatar

Chris Sutton said on 17 Sep 2008 at 10:40 PM

Steven,

I hope to see the default ASP.NET MVC templates get rid of the code behind as well. They don't serve a good purpose at this point.

Chris


 avatar

evodanh said on 18 Sep 2008 at 6:56 AM

I agree with: "Codebehind Files in ASP.NET MVC are Evil" :D

MVC should be: "fat model, thin controller, stupid view"


 avatar

Matt said on 18 Sep 2008 at 8:51 AM

I never did ASP.NET before MVC, and came from a Rails background. One thing I *do* like about having a code behind, is I can hide view logic in it, and not clutter the markup with large conditional checks that have to check for null, empty, etc. values. I can encapsulate a full conditional check into a single property into the code behind - it's still view logic, because the view is trying to figure out how to handle the data passed by the model, but it keeps my markup/code combinations cleaner.


 avatar

Luke said on 18 Sep 2008 at 9:07 AM

I also never did ASP.NET before MVC, so probably I'm unaware that such thing can be made: If you want to your page to be rendered as XML, how can you simply put it into *.aspx file? I do it in the codebehind like:

protected void Page_Load(object sender, EventArgs e)

{

Response.ContentType = "application/xml";

}

ASP.NET MVC still lacks many features (such as passing data to Master Pages *easily*) and documentation. It is a pity :( However, I'm looking forward to it.

PS. My homepage is written entirely in ASP.NET MVC (unfortunately Polish only :()


 avatar

Keith said on 18 Sep 2008 at 11:37 AM

Why doesn't the "Add Item" dialog ask if you want a codebehind file just like ASP.NET 2 does? Any code can easily be put in the view file. It should be view related and I hate opening 2 files just to deal with one view.

+1 Code behind files are evil.


 avatar

Rob Conery said on 18 Sep 2008 at 2:27 PM

You certainly don't want to put logic back there. The reason they are still included is that, by default, ASP.NET MVC uses the WebFormsViewEngine. Quite simply put, these "pages" are thought of as "classes" and so you have the class file artifact.

It's actually helpful (for people like me) who like to work with typed data and who like compile-time checking. In addition can create properties for partials - which is a nice type-safe way of working with data and minimal code.

For example, I have a partial in the Storefront for displaying Product information. On that partial I have an add to cart button which I only want to show conditionally. This is very specific to this partial, so I created a property for ShowAddToCartButton.

Anyway - I wouldn't say code behind is "Evil", but yes, it's confusing to folks who come from a webforms world :).


 avatar

Brad Wilson said on 18 Sep 2008 at 4:03 PM

@Luke, like this in the .aspx file:

<% Response.ContentType = "application/xml"; %>


 avatar

LaptopHeaven said on 18 Sep 2008 at 5:18 PM

@brad_wilson

Won't doing things like that start us down the path of spaghetti code, like lots of classic asp projects ended up with?

ASP.NET MVC != Classic ASP, but a lot of the examples look just like classic ASP.


 avatar

LaptopHeaven said on 18 Sep 2008 at 5:18 PM

@brad_wilson

Won't doing things like that start us down the path of spaghetti code, like lots of classic asp projects ended up with?

ASP.NET MVC != Classic ASP, but a lot of the examples look just like classic ASP.


 avatar

Steve Smith said on 18 Sep 2008 at 5:55 PM

@laptopheaven,

Not if all you're doing is View stuff. If you start putting in lots of other logic, then yes. But just because you have some logic in your ASPX doesn't make it spaghetti code. That's just a (very understandable) gut reaction based on all the pain we ASP developers endured, but in my opinion it *is* possible to have <%...%> code in a ViewPage's ASPX file without it automatically turning into pasta.


 avatar

Andrei Rinea said on 19 Sep 2008 at 9:12 AM

I propose the .asvx extension for .aspx files with no code-behind files designed as MVC views :D


 avatar

Luis Abreu said on 19 Sep 2008 at 1:44 PM

My thoughts on this topic are here: msmvps.com/.../codebehind-file


 avatar

foobar said on 19 Sep 2008 at 2:37 PM

What's all this bullsh*t about banning codebehind files? If you don't want to use C# code in your codebehind, then don't. Don't demand Microsoft ban codebehind in the next/final release.

Grow up, assume responsibility for your own life, or for the way you develop in MVC, dammit.


 avatar

foobar said on 19 Sep 2008 at 3:13 PM

Fine, what you're saying is no .cs or .designer.cs files by default.

What prevents you from modifying your project template files so that the afore-said files may not be generated? I've customized almost every VS2k8 project/item template extremely.


 avatar

Mike said on 19 Sep 2008 at 3:13 PM

While you're at it, why not remove the knives from your kitchen? They could be used to kill someone.


ssmith avatar

ssmith said on 19 Sep 2008 at 3:27 PM

@mike - poor analogy; knives in the kitchen are useful to me. These extra files are not. A better one might be "why not remove all the crap that comes preinstalled on your new PC - you might not want some of that stuff, either". To which I would answer, "Hell yeah, remove all that crap." (http://www.pcdecrapifier.com/)

I'm talking about decluttering, not overprotecting.


 avatar

Dharminder said on 20 Sep 2008 at 12:44 AM

How to add the Designer file to an aspx file


 avatar

Dan F said on 22 Sep 2008 at 9:50 AM

According to Brad Abrams, it was Rico Mariani who coined the phrase "pit of success" - http://blogs.msdn.com/brada/archive/2003/10/02/50420.aspx. I first read about if via Scott Hanselman. 'Tis a great term.

I'd be happier without the codebehind files myself, but I know a few colleagues would freak out royally.

According to Tim Barcz you can use that funky backtick notation, but it appears you need some extra square brackets - devlicio.us/.../strongly-typed-


 avatar

TimothyP said on 23 Sep 2008 at 4:06 AM

I have one situation where I (think I) need to put code in the codebehind. I'm streaming a fiel from another datasource to the client so in classic ASP.NET I'd have to

Response.ClearContent();

Response.ClearHeaders();

Response.ContentType = ".....";

Response.AppendHeader("Content-Disposition", ...

This is not something I could do in the controller right?

(Although I haven't figured out how to make this kind of download page with MVC yet)

Just saying there are situations where

code behind might be needed.


 avatar

Timothy said on 23 Sep 2008 at 4:21 AM

It would seem having a custom ActionResult class is the way to do it... so you're right... no need to stuff code in the codebehind :-)


 avatar

Marcelo L said on 24 Sep 2008 at 1:37 PM

@foobar: Yes ! I'm not the only one who's annoyed that in all these years, VS hasn't shipped with better, more robust templates "out of the box".


 avatar

Andrey Shchekin said on 26 Sep 2008 at 12:40 PM

One could still achieve strongly typed views, if they were important, by using the generic backtick notation like this (if VS supported it, which I'm not able to get working so I'm assuming it does not today):

<%@ Page Inherits="ViewPage`1[Customer]" %>

That is _the_ reason for me. It is possible, by the way, if you use the full generic argument name:

<%@ Page Inherits="ViewPage`1[X.Y.Customer, X.Y]" %>

but it is much less maintanable.

I do not really see areason to use untyped ViewPages, and the current syntax for typed ones is too complicated without code-behind.


 avatar

Hassan said on 03 Nov 2008 at 6:57 AM

I agree with Matt. I also prefer to put the view logic at code behind not cluttering the markup.It makes the aspx page less readable when you put large conditional checks that have to check for null, empty, etc. values as matt said. It keeps the code/markup cleaner and more readable. Most importantly You CAN NOT resist someone putting bussiness logic on the view only by removing code behind files. the guy would then start writing at aspx page then. a design pattern is a thing to be maintain by the developer.


Leave a Comment

Please join the discussion and share your thoughts.