Separating Code from Content in ASP.NET Pages via Code-Behind...
ASP.NET web forms can be logically divided into two sections: the user interface (UI) components and the code for the page. The user interfaces comprises HTML and ASP.NET controls. The code programmatically interacts with the UI elements.
ASP.NET web forms can be logically divided into two sections: the user interface (UI) components and the code for the page. The user interfaces comprises HTML and ASP.NET controls. The code programmatically interacts with the UI elements.
It is good practice to keep these elements distinct (though not mandated) whether in the same page or via the code behind model. In the same page the code would be placed in a <script> block. With the code behind model the interface elements remain in the .aspx file, whilst the code is placed in a .vb, .cs file or whatever is the appropriate extension for your chosen language.
Why is this code distinction good practice? There are two main arguments for the approach. The split makes code that much more readable and maintainable as well as less error prone. This means resource savings in the short and long term. Further we have the concept that that on larger projects the development workload could be split between UI developers and code developers and as the elements with which they work are distinct the work boundaries are strongly enforced and the possibility is minimised that changes made to one set of page elements leads to errors within the other set, simply because they are physically distinct.
Thus a key idea is that code behind facilitates team based development – developers can focus on implementing the business logic and 'designers' the interface, though the role of the designer has been extended a little from the generally understood definition. Splitting the page content in this way will, perhaps, allow both roles to complete their tasks more effectively. That's the idea. Whether this is true in practice is open to discussion.
As an ASP.NET web form is compiled into an object including a tree structure representing the elements and controls of the web form, the user interface and code logic can exist separately. The logic is a class file, which is also compiled into an object incorporated into the structure of the page class object with its properties, methods and event handlers exposed like any other object in the page. The code behind file is in fact the base class from which the web form inherits.
The primary difference if you move to the code behind model is that you lose the automatic inheritance of classes of the .NET Framework so must explicitly import them. This can at first glance make your code look more complicated and the very fact that you are splitting a single file into two suggests you are adding complexity.
In fact the code behind model is a bone of contention with Microsoft developers. Importantly though the use of the code behind model is the default in Visual Studio .NET and the IDE does make using code behind files much easier when you are familiar with the involved concepts and there are advantages to this approach, as we shall see.
To implement code behind you write all the user interface related code in one file (.aspx) and the page business logic in another file (.vb for VB) and then link the two files using the page directive of the .aspx file. Thus when the user requests the aspx file for the first time the ASP.NET compiler knows where to find the business logic for the page and will compile this additional code (though see options below) into the object which then represents and defines the behaviour of the page as a whole.
At this point let's look at an example page, the first version implemented as a single page and the second version being the same functionality implemented as a .aspx with a codebehind .vb file.
So that the example is sufficiently 'real world' I'm going to use some existing code of mine that reads in a list of articles I've written and presents this data in a simple datagrid. The page uses two other files: article_schema.xsd and articles.xml. The list is a bit out of date but never mind!
The code (UI and business logic) implemented as a single .aspx page is therefore:
|
<%@ Page Language="vb" Debug="false" Trace="false" %> <%@ import Namespace="System.Data" %> <script runat="server"> Sub Page_Load(sender as Object, e as EventArgs) if not page.ispostback then DisplayArticles() end if End Sub Sub DisplayArticles() Dim dsDMS as DataSet = new DataSet() Dim myDataView as DataView dsDMS.ReadXmlSchema(Server.MapPath("articles_schema.xml")) dsDMS.ReadXml(Server.MapPath("articles.xml")) myDataView=dsDMS.tables("article").DefaultView myDataView.Sort = "PubDate DESC" myDatagrid.datasource=myDataView myDatagrid.databind() dsDMS = nothing End Sub </script> <html> <head> </head> <body> <h2>Articles</h2> <p class="para"> The following is a list of links to articles authored by <a href="http://www.cymru-web.net/" target=_new> Cymru-Web</a>'s Technical Director (last updated 18/01/2003): </p> <ASP:DataGrid id="MyDataGrid" runat="server" MaintainState="false" AutoGenerateColumns="False" DataKeyField="name" CellPadding="2"> <Columns> <ASP:TemplateColumn HeaderText="<b>Article name</b>"> <ItemTemplate> <a href="<%# Container.DataItem("url") %>"><%# Container.DataItem("name") %></a> </ItemTemplate> </ASP:TemplateColumn> <ASP:TemplateColumn HeaderText="<b>Publication Date</b>"> <ItemTemplate> <center><%# format("d",Container.DataItem("PubDate")) %></center> </ItemTemplate> </ASP:TemplateColumn> </Columns> </ASP:DataGrid> </body> </html> |
To implement the above in line with the code behind model we need to
A working result of this process for the above page is:
CodeBehind_articles.vb:
|
Imports System Imports System.Data Imports System.Xml Imports System.Web Imports System.Web.UI Imports System.Web.UI.WebControls Imports System.Web.UI.HTMLControls Public Class CodeBehind_Articles Inherits Page Public myDataGrid as DataGrid Sub Page_Load(sender as Object, e as EventArgs) if not page.ispostback then DisplayArticles() end if End Sub Sub DisplayArticles() Dim dsDMS as DataSet = new DataSet() Dim myDataView as DataView dsDMS.ReadXmlSchema(Server.MapPath("articles_schema.xml")) dsDMS.ReadXml(Server.MapPath("articles.xml")) 'create a view of the manipulated table based on the selected category for binding to the datagrid myDataView=dsDMS.tables("article").DefaultView myDataView.Sort = "PubDate DESC" myDatagrid.datasource=myDataView myDatagrid.databind() dsDMS = nothing End Sub End Class |
articles_codebehind.aspx:
|
<%@ Page Inherits="CodeBehind_Articles" Src="CodeBehind_articles.vb" %> <html> <head> </head> <body> <h2>Articles</h2> <p class="para"> The following is a list of links to articles authored by <a href="http://www.cymru-web.net/" target=_new> Cymru-Web</a>'s Technical Director (last updated 18/01/2003): </p> <ASP:DataGrid id="MyDataGrid" runat="server" MaintainState="false" AutoGenerateColumns="False" DataKeyField="name" CellPadding="2"> <Columns> <ASP:TemplateColumn HeaderText="<b>Article name</b>"> <ItemTemplate> <a href="<%# Container.DataItem("url") %>"><%# Container.DataItem("name") %></a> </ItemTemplate> </ASP:TemplateColumn> <ASP:TemplateColumn HeaderText="<b>Publication Date</b>"> <ItemTemplate> <center><%# format("d",Container.DataItem("PubDate")) %></center> </ItemTemplate> </ASP:TemplateColumn> </Columns> </ASP:DataGrid> </body> </html> |
I recommend you review the above and see how the conversion has been implemented based on the 5 point process detailed above.
There are different ways in which you can use the Page directive to link the code to the UI.
You can use the Src and Inherits attributes of the Page directive. Below is an outline example of the involved syntax, and this is the method used in the example above.
filename.aspx
|
<%@ Page language="vb" inherits "[namespace1].[classname]" src="[filename.vb]"%> [HTML+] . . . |
filename.vb:
|
Namespace [namespace1] Public class [classname] Inherits System.Web.UI.Page [CODE] End Class End Namespace |
In the above we use namespaces - good practice to organise classes. All the business logic code associated with the page is written in the codebehind file filename.vb. The page directive of the .aspx file provides the linking mechanism between the two files. The Inherits attribute specifies that when the .aspx is dynamically compiled it inherits the functionality presented in the code behind file within the [classname] class of the [namespace1] namespace with the src attribute specifying the code behind file itself, [filename.vb].
Thus in this instance two files are dynamically compiled – the .aspx and the .vb file.
Finally notice the inclusion of
| Inherits System.Web.UI.Page |
Exposing the base class of the .aspx file for use.
This is an alternate option with the following benefits:
This requires an extra step – compiling the src file and placing it in the bin subdirectory of the web application, as well as removing the src attribute of the Page directive, as follows:
| <%@ page language="vb" inherits "[namespace1].[classname]" %> |
Why does this work? Because when ASP.NET compiles the machine-generated class file corresponding to the .aspx file it includes references to all the DLL files present in the bin sub-directory. In other words it will effectively search the local bin directory for dlls containing namespace code used by the aspx file and include it.
This method is the default option for Visual Studio .NET which also does the necessary compilation so as not to necessitate manual intervention.
I hope this article has served as a useful introduction to how and why to use code behind with ASP.NET and, in particular, that you have a better idea of what Visual Studio .NET is doing with your pages. There are a few further issues that arise when looking at code behind techniques with User Controls that I shall perhaps return to in a subsequent article.
ASP.NET: Tips, Tutorial and Code
Scott Mitchell et al.
Sams
Developing and implementing web applications with VB.Net and VS.Net
Mike Gunderloy
Que