Separating
User
Interface from Business Logic
In the ASP.NET pages created so far, you likely noted that the C# code is interspersed between the HTML code. Mixing both HTML and ASP.NET code makes the Web pages difficult to understand, maintain, and debug. HTML code represents the user interface (UI) of the application, whereas the ASP.NET code defines the business logic for that page. These are two diverse ideas that usually need to be handled differently.
ASP.NET provides a mechanism to separate the UI portion of a Web page from the business logic. This mechanism is known as
code-behind
. To implement code-behind, you write all the UI-
related
code in one file (
.aspx
) and the business logic in another file (
.cs
for C#) and then link these two files using the
Page
directive in the ASPX page. The linking is provided in the ASPX page instead of the CS file because the user
requests
the ASPX page. When ASP.NET compiles the ASPX page, it examines the
Page
directive to locate the business logic associated with the UI in the ASPX page. You can use the
Page
directive in different ways to link the code to the UI.
Using Code-behind Without Precompilation
When you write both the UI and business logic in separate files, one way to link them is via the
Src
and
Inherits
attributes of the
Page
directive. The following example uses the code of the
Example2_1.aspx
file and converts it into the code-behind version. The UI is stored in
Example2_6.aspx
, and the code is stored in
TemperatureCB.cs
. Do the following:
-
Add a new text file to Web project
315C02
, and
name
it
Example2_6.aspx
. Switch to its HTML view and add the following code to the Web page:
<!--Example2_6.aspx -->
<%@ Page Language="C#"
Inherits="Temperature.TemperatureCB"
src="TemperatureCB.cs"%>
<html>
<body>
<h2>Fahrenheit to Celsius Conversion Chart</h2>
<table border="2">
<tr>
<th>° Fahrenheit</th>
<th>° Celsius</th>
</tr>
<%CreateTemperatureTable();%>
</table>
</body>
</html>
-
Right-click the project in the Solution Explorer, and then select Add, Add New Item. This opens the Add New Item dialog box. Select the Code File template and name the file
TemperatureCB.cs
.
-
Add the following code to the
TemperatureCB.cs
file:
//TemperatureCB.cs
namespace Temperature
{
// Define TemperatureCB class
public class TemperatureCB : System.Web.UI.Page
{
double ToCelsius(double f)
{
// Calculate the temperature in Celsius
return (5.0/9.0)*(f-32.0);
}
public void CreateTemperatureTable()
{
for (double f = 50.0; f<=100.0; f++)
Response.Output.Write("<tr><td>{0}</td><td>" +
"{1:f}</td></tr>", f, ToCelsius(f));
}
}
}
-
Access the Properties Window for the
TemperatureCB.cs
file. Set the
Build Action
property to
None
; this restricts Visual Studio .NET from automatically compiling this file.
-
Select Debug, Run to view the
Example2_6.aspx
file in your browser.
The
Page
directive in the
Example2_6.aspx
file provides the linking mechanism for the UI and code-behind. The
Inherits
attribute specifies that when the ASPX page is dynamically compiled, it inherits its functionality (such as
methods
and properties) from the
TemperatureCB
class of the
Temperature
namespace. In addition, the
Src
attribute specifies that the source code for the
TemperatureCB
class is stored in the
TemperatureCB.cs
file.
Using Code-behind with Visual Studio .NET Web Forms
Web forms are the preferred way of creating ASP.NET pages using Visual Studio .NET. They provide three distinct benefits over simple ASP.NET pages:
-
Support code-behind by separating UI from business logic
-
Provide an
event-based
programming model for designing Web pages
-
Support RAD tools, such as Visual Studio .NET
The following example
demonstrates
how to create a Web form using Visual Studio .NET for displaying a temperature-conversion chart:
-
Open
the Solution Explorer window for project
315C02
; right-click the project name and select Add, Add Web Form. In the Add New Item dialog box, name the file
Example2_7.aspx
.
-
The Web form is in Design view. In the background of the form, you see a message asking you to select between grid layout mode and flow layout mode. Open the Properties window by selecting View, Property Pages. Then, change the Page Layout property of Document to FlowLayout.
-
In the flow layout mode, type
Fahrenheit to Celsius Conversion Chart
. Then, select the text and change its block format to Heading 2 using the Block Format combo box on the formatting toolbar.
-
Select Table, Insert, Table. In the Insert Table dialog box, select options to make a table of size 1 row and 2
columns
. Set the Width attribute to 200 pixels.
-
Switch to the HTML view of the
Example2_7.aspx
file, and modify the code in the
<TABLE>
tag as shown here:
<TABLE id="Table1" cellSpacing="1" cellPadding="1"
width="200" border="1">
<TR>
<TD>° Fahrenheit</TD>
<TD>° Celsius</TD>
</TR>
<%CreateTemperatureTable();%>
</TABLE>
-
Invoke the Solution Explorer, right-click
Example2_7.aspx
, and select View Code. This opens the code-behind file
Example2_7.aspx.cs
. Add the following code just above the Web Form Designergenerated code region:
double ToCelsius(double f)
{
// Calculate and return the temperature in Celsius
return (5.0/9.0)*(f-32.0);
}
public void CreateTemperatureTable()
{
for (double f = 50.0; f<=100.0; f++)
Response.Output.Write("<tr><td>{0}</td><td>" +
"{1:f}</td></tr>", f, ToCelsius(f));
}
-
In the Solution Explorer, right-click
Example2_7.aspx
and select Set As Start Page.
-
Compile the page by selecting Build, Build 315C02; then run the page by selecting Debug, Start Without Debugging. You should see that the temperature table is created just as in the case of earlier examples.
An ASP.NET Web form is made up of two distinct pieces:
Analyzing the User Interface Piece of a Web Form
In the
Example2_7.aspx
file, the
Page
directive is written as
follows
:
<%@ Page language="c#"
Codebehind="Example2_7.aspx.cs"
AutoEventWireup="false"
Inherits="_315C02.Example2_7" %>
This usage of the
Page
directive has two new attributes
AutoEventWireup
and
Codebehind
.
AutoEventWireup
is used for event handling. Visual Studio .NET, by default, sets the
AutoEventWireup
attribute to
false
. The
Codebehind
attribute, on the other hand, is used by Visual Studio .NET to track the location of the source code of the code-behind file. ASP.NET does not understand the
Codebehind
attribute and therefore ignores it. This attribute does not play any role in the execution of the ASP.NET page.
|
In the
Page
directive, when the name of the source code file is specified using the
Src
attribute, the source code file is dynamically compiled at runtime. However, the same does not hold true for the
Codebehind
attribute, which is necessary only for design-time support in Visual Studio .NET. The
Codebehind
attribute plays no role at runtime because it is not recognized by ASP.NET.
|
|
If you are handling events in your program by attaching delegates, set the
AutoEventWireup
attribute of the
Page
directive to
false
. If you keep it
true
, as the page runs, some of the event handlers might be called twice.
To understand why, assume that you want to handle the
Load
event for the
Page
object, so you create a method named
Page_Load()
and attach it to the
Load
event of the
Page
using a delegate object. Now, because the
AutoEventWireup
attribute is
true
, based on the name of the method, the ASP.NET page framework will automatically attach
Page_Load()
as an event handler for the
Load
event of the
Page
. This results in the registration of the same event handler twicehence, the event handler will also be invoked twice when the event is raised.
It is for this reason that Visual Studio .NET by default always sets
AutoEventWireup
to
false
.
|
Analyzing the Business Logic Piece of a Web Form
When you analyze the file storing the business logic piece,
Example2_7.aspx.cs
.
The class definition for the
Example2_7
class looks like this:
public class Example2_7 : System.Web.UI.Page
{
...
}
In the
Example2_7.aspx.cs
file, you can also write this definition as
public class Example2_7 : Page
{
...
}
How does the compiler locate a class if its full namespace-qualified name is not provided?
Inclusion of these
using
directives directs the C# compiler to search for each class used in the code in the namespaces specified by the
using
directives. The compiler looks up each namespace one by one, and when it finds the given class in one of the namespaces, it internally
replaces
the reference of the class with
NamespaceName.ClassName
in the code.
|