Meditating Upon the ASP.NET Code-Behind Model
At the highest level of abstraction, an ASP.NET page is made of two components—page layout information and procedural code that ties controls and literals up together. The code can be injected in the same .aspx file through the server-side <script> tag or placed in an externally bound class file. Just the possibility of keeping code and layout separate was initially welcomed as one of the coolest features of the whole ASP.NET platform. It was seen as the herald of an incoming pure object-oriented approach to Web programming—so unusual, but so desirable, in the Microsoft's land.
Three years after the first public beta of ASP.NET 1.0, and with the first alpha of ASP.NET 2.0 just around the corner, the debate about the effective goodness of code-behind seems to be close to its end. Is it good stuff? Should you use it? How do you feel about using it?
The first two questions have a foregone answer—by all means, use code-behind because it is really good stuff. The third question, though, is not there by chance; and it is not just a rhetorical question. There are a lot of good points in the code-behind model, but the real point is, how comfortable do you feel when using it to build ASP.NET applications? This leads us to carefully review the architecture of the ASP.NET page designer embedded in Visual Studio .NET 2002 and 2003. If code-behind in itself a really good thing, the same is not necessarily true for its Visual Studio .NET implementation.
Code-Behind and Inline Code
When writing ASP.NET applications, there's just one possible alternative to code-behind—using inline code. Using inline code means that you inject all the page-specific code in the same .aspx file with the rest of the page. Although insulated in a distinct tag—the <script runat=server> tag—the server-side code (postback and page event handlers, helper routines, code blocks) is merged with the markup. Especially for pages rich in content and functionality, this is not good news. The page loses in readability and maintainance. In addition, all inline code must be written in the same language declared for the page. The contents of the <script> tag are copied verbatim in the source code of the dynamically generated class that represents the .aspx resource in execution. This explains why the language must match.
The code-behind model entails that a separate class file is used to hold all the code bound to the page. This class inherits from Page and constitutes the effective base class for the aforementioned dynamically generated class that represents the .aspx resource in execution. In other words, if you use code inline, the page is represented by an object derived from Page; otherwise, it will be represented by an instance of a class derived from the code-behind class.
The binding between the page and the class file is indissolubly set at the page level using an attribute on the @Page directive. The runtime detects the link and builds the dynamic page representation using the code in the external file or assembly.
The advantages brought by the code-behind model are clear and to a large extent also unquestionable. You deal with classes and integrate your own classes with the existing framework. The code and layout physical separation enable graphic designers and page developers to work on the same resource at the same time. The code is more readable, and easy to maintain. When the code-behind class is linked in a precompiled form, no language barrier hinders the development of the project and different languages can be used.
Code-Behind in ASP.NET
The key point about the code-behind model is that you can bind a class to a page in two forms—source code and compiled assembly. If you specify the class as a source file, the ASP.NET runtime takes care of compiling it on demand and makes the resulting assembly available to the application. No significant performance hit is reported because the compilation occurs only once—the first time the page is requested. The following code shows how to bind a page to a source class file.
<%@ Page Language="C#" Src="MyBasePage.cs" %>
You must deploy the C# (or Visual Basic .NET) source file to the Web server, but any update will be detected promptly and automatically handled without restarting the application. If you mind having a source file over the Web, you can precompile the class and bind it to the page by using the Inherits attribute instead.
<%@ Page Language="C#" Inherits="Samples.MyBasePage" Assembly="Foo"%>
In this case, no source code is deployed; but in case of changes, the developer is responsible for deploying the updated assembly. Not too bad, one might think. The rub is that the assemblies used by an ASP.NET application normally go to the Bin subdirectory of the root. When this directory is updated—its last access timestamp changes—the Web application is automatically restarted. You understand that this perspective is not very enticing as long as large Web applications are involved.
So, you have two good reasons for choosing the source-based implementation of the code-behind model. What tool do you use for building your Web applications?
Code-Behind in Visual Studio .NET
If you use Microsoft Visual Studio .NET to build your Web applications, you can't just use the most effective implementation of code-behind. Visual Studio .NET doesn't recognize and support the Src attribute. Even worse, it doesn't let you add pages to the project containing inline code. To get along with Visual Studio .NET, you have to play by its rules. You have to store any server code for a page to a code-behind class. This class is bound to the .aspx page using the Inherits attribute and Visual Studio .NET takes care of building any necessary assembly at compile time.
This fact creates in you as a developer a sort of dependency from Visual Studio .NET. Furthermore, for editing purposes only Visual Studio .NET needs to track the source file bound to a particular page. The name of the source file is stored in a custom attribute named Codebehind.
<%@ Page Language="C#" Inherits="Samples.MyBasePage" Assembly="Foo" Codebehind="default.aspx.cs" %>
The Codebehind attribute means little (not nothing!) to the ASP.NET runtime. If you add a custom attribute to the @Page directive, the best that you can get is an exception. This doesn't happen for the Codebehind attribute. (Read, the attribute is recognized but blissfully ignored.)
Why doesn't Visual Studio .NET support inline code? Because as it is architected in version 2002 and 2003, it couldn't otherwise provide Intellisense functionality. For Visual Studio to support inline code, or acting as a standalone editor for .aspx file, a complete reenginering is required—just what is announced for the next version!
Web Development Issues Today
Many developers love ASP.NET but dislike the way in which ASP.NET applications are built in Visual Studio .NET. On the other hand, the same developers can't just abandon Visual Studio .NET for, say, Web Matrix because of the other features that a true IDE can provide—from syntax coloring to debugging, from profiling to Intellisense and source code management. Third-party tools are a certainly a feasible, sometimes good, answer.
Back to Visual Studio .NET, there's a long list of issues with Web development today. The list includes at least the following:
- The code-behind model is mandatory
- Visual Studio .NET compiles down to a single DLL and causes the application to restart when updates are deployed
- Lack of compile-on-demand features. It requires an explicit compile step to deploy and run
- Inability to open single .aspx page without a project file
- Missing support for direct (local) IIS access or FTP access to files
- IIS must be installed on the development machine and administrative privileges are required to edit files
- Debugging different scenarios is quite hard and moving projects to another machine can be a nightmare
The above shortcomings belong to two distinct categories—IDE features and code model. As long as the code model is concerned, the code-behind model is under charge. All in all, code-behind is an abstract concept that in Visual Studio .NET 2002 and 2003 is implemented using inheritance and precompiled assemblies. This proved not the right approach.
In the next version of ASP.NET (the alpha is coming up at PDC, a few weeks away), expect to see several changes both at the IDE level and in the code model. Not something really different from code-behind is needed, but a form of code-behind that doesn't require preliminary compilation and doesn't force you to have a project file. Looking forward to the alpha!
About the Author...
Dino Esposito is Wintellect's ADO.NET expert and a trainer and consultant based in Rome, Italy. Dino is a full-time author, a full-time consultant and a full-time trainer. Prior to this, Dino was a full-time employee and worked day and night for Andersen Consulting focusing on the very first real-world implementations of DNA systems. Dino also has extensive experience developing commercial Windows-based software, especially for the photography world, and was part of the team who designed and realized one of the first European image online databanks. You can also check out Dino's newest book, Building Web Solutions with ASP.NET and ADO.NET.
# # #