JavaScript Editor Javascript validator     Javascripts

Main Page


Previous Section Next Section

6.1 Code-Behind

In traditional ASP, the interweaving of script with HTML can produce source control nightmares and difficult-to-maintain ASP pages. ASP.NET addresses this problem by giving programmers the ability to separate the executable code from the presentation code. You write the HTML in a page file (with a .aspx extension), and you write the C# or VB.NET code in the code-behind file (with a .cs or .vb extension, depending on its language), which is another way of saying the "code file behind the form."

In the code-behind file, you create a class (which can be any class derived from the Page class) that serves as the base class for the web page you create in the .aspx file. This relationship between your class and the web page is established by a Page directive at the top of the .aspx file:

<%@ Page inherits="CodeBehindDemo" %>

The inherits attribute identifies the class created in the code-behind file from which this .aspx file will derive.

When a web form is compiled, its page is parsed and a new class is generated and compiled. This new class derives from the class identified in the inherits keyword, which in turn derives from System.Web.UI.Page.

Now the only question is, "How does the compiler know where to find this code-behind file class to derive from?" The answer depends on whether or not you are working in the Visual Studio .NET (VS.NET) IDE or using a text editor to work directly with the source files.

If you're working in the VS.NET IDE, then the development environment will automatically pre-compile the class in the code-behind file and use the inherits attribute to point to that class. The .dll file that is created is placed in the \bin subdirectory in the application virtual directory.

You will notice that VS.NET also puts a codebehind attribute in the Page directive, which points to the code-behind file. The codebehind attribute is used to keep track of the code-behind file so that as you make changes to the page, VS.NET can make the appropriate changes to the code-behind file. Using VS.NET will be covered in more detail later in this chapter.

If you are not using a development environment such as VS.NET, but rather editing the files directly in a text editor, then you need to include the src attribute in the Page directive to identify the file containing the class specified in the inherits attribute for the JIT compiler:

<%@ Page inherits="CodeBehindDemo"  src="CodeBehind.cs"  %>

If the src string does not include a fully qualified path, then the compiler assumes that the file is in the same directory as the .aspx file. If the src attribute is missing, then the compiler will look in the \bin subdirectory of the application virtual directory for a .dll that contains the class marked with the inherits attribute.

In order to convert an .aspx file from in-line code to code-behind, you need to make modifications both to the .aspx file as well as to the code-behind file, as follows:

Modifications to the .aspx file

The .aspx file needs to have its Page directive modified to include the inherits attribute.

Optionally, the Page directive must be modified to include the src attribute.

Modifications to the code-behind file

The code-behind file does not automatically inherit the common namespaces used in web forms. The code-behind file itself must tell the compiler which namespaces it needs with the using keyword in C# and the Imports keyword in VB.NET.

The class you create must inherit from the System.Web.UI.Page class.

Every control in the .aspx file referred to by name (id) in the code-behind file must have an accessible variable (declared using either the public or protected access modifier) defined in the code-behind class. The variable type must be the same as the control type, and the variable name must match the control name.

All methods in the code-behind class that are called directly from the .aspx file must be declared as either public or protected methods (that is, using the public or protected access modifiers).

Access Modifiers

The keywords public, protected, private, and internal (in C#) or friend (in VB) are access modifiers. An access modifier determines which class methods can see and use a member variable or method. Table 6-1 summarizes the access modifiers.

The default accessibility of members of a class is private. Thus, if there is no access modifier provided for a class member, then it will be a private member. Regardless of this circumstance, it is always a good idea to explicitly specify the access modifier in order to enhance the readability of the code.

Table 6-1. Access modifiers

Access modifier

Restrictions

public

No restrictions. Members marked public are visible to any method of any class.

private

The members in class A that are marked private are accessible only to methods of class A.

protected

The members in class A that are marked protected are accessible to methods of class A and also to methods of classes derived from class A.

internal (C#) Friend (VB)

The members in class A that are marked internal or friend are accessible to methods of any class in A's assembly.

protected internal (C#) Protected friend (VB)

The members in class A that are marked protected internal or protected friend are accessible only to methods of class A and also to methods of classes derived from class A, and also to any class in A's assembly. This is effectively protected or internal.

To better understand code-behind, modify one of the Calendar examples from Chapter 5 (Example 5-43 in C# or Example 5-44 in VB.NET) to use code-behind. These modifications will entail removing the entire script block and changing the Page directive in the .aspx file, and creating a code-behind file that essentially contains the excised script block.

The easiest way to accomplish this is to copy the .aspx file twice: once to the file to use for the new .aspx file and once to the file to use for the code-behind file. Then edit each of those new files. In this example, the original Calendar example .aspx files will be copied and renamed as shown in Table 6-2.

Table 6-2. Example filenames

Original filename

New filename

Purpose

csASPCalendarMoreSelections.aspx

csCodeBehind.aspx

Contains the HTML for the C# version

"

CodeBehind.cs

Contains the C# version of the code-behind class

vbASPCalendarMoreSelections.aspx

vbCodeBehind.aspx

Contains the HTML for the VB.NET version

"

CodeBehind.vb

Contains the VB.NET version of the code-behind class

It is important that the code-behind file have the correct file extension. This tells the framework which compiler to use to compile the code-behind file. Valid file extensions are:

  • .cs for C#

  • .vb for VB.NET

  • .js for JavaScript

Example 6-1 shows the .aspx file modified to use code-behind for C#. Since the HTML is exactly the same in both C# and VB.NET, Example 6-2 shows only the Page directive for the VB.NET version.

Example 6-1. Code-behind page using C#, csCodeBehind.aspx
<%@ Page inherits="CodeBehindDemo"  src="CodeBehind.cs" %>

<html>
   <body>
   <form runat="server">

      <h1>ASP Controls</h1>
      <h2>Calendar Control</h2>
      <h2>More Selections</h2>

      <asp:Calendar
         id="cal"
         SelectionMode="DayWeekMonth"
         ShowGridLines="true"
         ShowNextprevMonth="true"
         CellPadding="7"
         CellSpacing="5"
         DayNameFormat="FirstTwoLetters"
         FirstDayOfWeek="Monday"
         NextPrevFormat="CustomText"
         NextMonthText="Next &gt;"
         PrevMonthText="&lt; Prev"
         onSelectionChanged="SelectionChanged"
         DayHeaderStyle-BackColor="Black"
         DayHeaderStyle-ForeColor="White"
         DayHeaderStyle-Font-Name="Arial Black"
         runat="server" >

         <DayStyle
            BackColor="White"
            ForeColor="Black"
            Font-Name="Arial" />
         <NextPrevStyle
            BackColor="DarkGray"
            ForeColor="Yellow"
            Font-Name="Arial" />
         <OtherMonthDayStyle
            BackColor="LightGray"
            ForeColor="White"
            Font-Name="Arial" />
         <SelectedDayStyle
            BackColor="CornSilk"
            ForeColor="Blue"
            Font-Name="Arial" 
            Font-Bold="true"
            Font-Italic="true"/>
         <SelectorStyle
            BackColor="CornSilk"
            ForeColor="Red"
            Font-Name="Arial" />
         <TitleStyle
            BackColor="Gray"
            ForeColor="White"
            HorizontalAlign="Left"
            Font-Name="Arial Black" />
         <TodayDayStyle
            BackColor="CornSilk"
            ForeColor="Green"
            Font-Name="Arial" 
            Font-Bold="true"
            Font-Italic="false"/>
         <WeekendDayStyle
            BackColor="LavenderBlush"
            ForeColor="Purple"
            Font-Name="Arial" 
            Font-Bold="false"
            Font-Italic="false"/>
      </asp:Calendar>

      <br/>
      <asp:Label id="lblCount" runat="server" />
      <br/>
      <asp:Label id="lblTodaysDate" runat="server" />
      <br/>
      <asp:Label id="lblSelected" runat="server" />
      <br/>
      <table>
         <tr>
            <td>
               Select a month:
            </td>
            <td>
               <asp:DropDownList 
                  id= "ddl"
                  AutoPostBack="true"
                  onSelectedIndexChanged = "ddl_SelectedIndexChanged"
                  runat="server">

                  <asp:ListItem text="January" value="1" />
                  <asp:ListItem text="February" value="2" />
                  <asp:ListItem text="March" value="3" />
                  <asp:ListItem text="April" value="4" />
                  <asp:ListItem text="May" value="5" />
                  <asp:ListItem text="June" value="6" />
                  <asp:ListItem text="July" value="7" />
                  <asp:ListItem text="August" value="8" />
                  <asp:ListItem text="September" value="9" />
                  <asp:ListItem text="October" value="10" />
                  <asp:ListItem text="November" value="11" />
                  <asp:ListItem text="December" value="12" />

               </asp:DropDownList>
            </td>
            <td>
               <asp:Button
                  id="btnTgif"
                  text="TGIF"
                  onClick="btnTgif_Click"
                  runat="server" />
            </td>
         </tr>
      </table>
   </form>
   </body> 
</html>
Example 6-2. Code-behind page directive using VB.NET, vbCodeBehind.aspx
<%@ Page inherits="CodeBehindDemo"  src="CodeBehind.vb" %>

In Example 6-1 and Example 6-2, the only changes necessary from the original .aspx file are to remove the script block entirely and modify the Page directive. The Page directive modifications are intended to:

  1. Remove the Language attribute.

  2. Add an inherits attribute for the code-behind class.

  3. Add the appropriate value to the src attribute that points to the correct code-behind file.

    You remove the Language attribute because there is no longer any code other than HTML in the page file. If you keep script in the page file, the Language attribute would have to remain.

Example 6-3 shows the code-behind file for C#.

Example 6-3. CodeBehind.cs
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public class CodeBehindDemo : Page
{
   protected Calendar cal;
   protected Label lblCount;
   protected Label lblTodaysDate;
   protected Label lblSelected;
   protected DropDownList ddl;

   //  This Page_Load makes the selected days visible first time
   //  the TGIF button is clicked by initializing the VisibleDate
   //  property.
   protected void Page_Load(Object sender, EventArgs e) 
   {
      if (!IsPostBack)
     {
         cal.VisibleDate = cal.TodaysDate;
        ddl.SelectedIndex = cal.VisibleDate.Month - 1;
      }
      lblTodaysDate.Text = "Today's Date is " +  
            cal.TodaysDate.ToShortDateString(  );
   }

   protected void SelectionChanged(Object sender, EventArgs e)
   {
      lblSelectedUpdate(  );
      lblCountUpdate(  );
   }

   protected void ddl_SelectedIndexChanged(Object sender, EventArgs e)
   {
      cal.SelectedDates.Clear(  );
      lblSelectedUpdate(  );
      lblCountUpdate(  );
      cal.VisibleDate = new DateTime(cal.TodaysDate.Year, 
                        Int32.Parse(ddl.SelectedItem.Value), 1);
   }

   protected void btnTgif_Click(Object sender, EventArgs e)
   {
      int currentMonth = cal.VisibleDate.Month;
      int currentYear = cal.VisibleDate.Year;

      cal.SelectedDates.Clear(  );

      for (int i = 1; 
               i <= System.DateTime.DaysInMonth(currentYear,
                                                currentMonth); 
               i++ )
      {
         DateTime date = new DateTime(currentYear, currentMonth, i);
         if (date.DayOfWeek == DayOfWeek.Friday)
            cal.SelectedDates.Add(date);
      }

      lblSelectedUpdate(  );
      lblCountUpdate(  );
   }

   private void lblCountUpdate(  )
   {
      lblCount.Text = "Count of Days Selected:  " + 
            cal.SelectedDates.Count.ToString(  );
   }

   private void lblSelectedUpdate(  )
   {
      if (cal.SelectedDate != DateTime.MinValue)
         lblSelected.Text = "The date selected is " + 
               cal.SelectedDate.ToShortDateString(  );
      else
        lblSelected.Text = "";
   }
}

Example 6-3 shows several changes from the original code in the inline script block:

  • There are several using statements at the beginning of the C# code-behind file to reference the needed namespaces. These were not required in the inline code because they were automatically included by the compiler when it compiled the .aspx file.

  • The class declaration for the CodeBehindDemo class inherits from the base class System.Web.UI.Page. (It is not actually necessary to fully qualify the Page object because you have included the System.Web.UI namespace in a using statement.)

  • Variables are declared for each of the controls referred to in the code-behind file. Note that there is no declaration for the btnTgif control, since that control is not referenced anywhere in the code-behind file, although there is an event handler for the Click event.

  • Remember that the .aspx file is compiled into a class that derives from the code-behind class, CodeBehindDemo. Because these variables must be visible to the .aspx file, they have to be declared as either public or protected. Good object-oriented programming practice recommends using protected to hide data as much as possible.

  • All of the methods that are called directly from the .aspx file have the protected keyword added to their declaration. (These are all the methods except lblCountUpdate and lblSelectedUpdate, which are declared private.)

  • As with the variables, the program will work if the methods use the keyword public, but protected gives better encapsulation.

Example 6-4 shows the code-behind file for VB.NET. It makes the same functional changes as for the C# file, with only syntactic changes.

Example 6-4. CodeBehind.vb
Imports System
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls


public class CodeBehindDemo
Inherits Page

   protected cal as Calendar
   protected lblCount as Label
   protected lblTodaysDate as Label
   protected lblSelected as Label
   protected ddl as DropDownList

   '  This Page_Load makes the selected days visible first time
   '  the TGIF button is clicked by initializing the VisibleDate
   '  property.
   protected sub Page_Load(ByVal Sender as Object, _
                 ByVal e as EventArgs) 
      if not IsPostBack then
         cal.VisibleDate = cal.TodaysDate
       ddl.SelectedIndex = cal.VisibleDate.Month - 1
      end if

      lblTodaysDate.Text = "Today's Date is " & _
            cal.TodaysDate.ToShortDateString(  )
   end sub

   protected sub SelectionChanged(ByVal Sender as Object, _
                        ByVal e as EventArgs)
      lblSelectedUpdate(  )
      lblCountUpdate(  )
   end sub

   protected sub ddl_SelectedIndexChanged(ByVal Sender as Object, _
                                ByVal e as EventArgs)
      cal.SelectedDates.Clear(  )
      lblSelectedUpdate(  )
      lblCountUpdate(  )
      cal.VisibleDate = new DateTime(cal.TodaysDate.Year, _
                        Int32.Parse(ddl.SelectedItem.Value), 1)
   end sub

   protected sub btnTgif_Click(ByVal Sender as Object, _
                     ByVal e as EventArgs)
      dim currentMonth as integer = cal.VisibleDate.Month
      dim currentYear as integer = cal.VisibleDate.Year

      cal.SelectedDates.Clear(  )

      dim i as integer
      for i = 1 to System.DateTime.DaysInMonth(currentYear, currentMonth)
         dim dt as DateTime = new DateTime(currentYear, currentMonth, i)
         if dt.DayOfWeek = DayOfWeek.Friday then
            cal.SelectedDates.Add(dt)
         end if
      next

      lblSelectedUpdate(  )
      lblCountUpdate(  )
   end sub

   private sub lblCountUpdate(  )
      lblCount.Text = "Count of Days Selected:  " & _
            cal.SelectedDates.Count.ToString(  )
   end sub

   private sub lblSelectedUpdate(  )
      if (cal.SelectedDate <> DateTime.MinValue) then
         lblSelected.Text = "The date selected is " & _
               cal.SelectedDate.ToShortDateString(  )
      else
        lblSelected.Text = ""
      end if
   end sub
end class

When either Example 6-1 or Example 6-2 is run, the relevant using the code-behind pages from Example 6-3 or Example 6-4, the result shown in Figure 6-1 is identical to the result produced by the inline code of Example 5-43 and Example 5-44 and shown in Figure 5-24.

Figure 6-1. Code-behind from Example 6-1 or Example 6-2
figs/pan2_0601.gif
    Previous Section Next Section


    JavaScript Editor Javascript validator     Javascripts 




    ©