ASPX Pages

I l @ ve RuBoard

Now that there exists two UserControls , it is time to create some aspx pages to host those controls. The first page to implement is the EmployeeEdit page. This allows the EmployeeViewPaglet control to navigate to an edit page. The edit page should allow for changes to the name , department, and to upload a photograph. ASP.NET makes client-side file transfer a snap.

EmployeeEdit

One of the requirements for the EmployeeBrowser site was the ability to edit employee information and the associated photograph. Rather than build another UserControl , this functionality will be implemented within the context of an aspx page. The only reason for doing so is to poke around ASP.NET. The EmployeeEdit page would be a good candidate for a UserControl ; I'll leave that to you.

There's no real magic to the layout, so the markup will be omitted from the text. Only new or interesting markup will be shown. The full code is contained on the CD-ROM included with this book, and you should refer to it if needed. Figure 4.3.4 shows the EmployeeEdit page with a record ready to edit.

Figure 4.3.4. EmployeeEdit page.

graphics/0403fig04.gif

The first control to look at is the drop-down list used to hold the names of the various departments. In standard HTML, it was necessary to hard-code the values for list boxes or drop-down menus . You could use script woven in to produce some type of data dependant list, but this fails in comparison to ASP.NET and databinding. Listing 4.3.6 shows the declaration for an asp:dropdownlist which will be bound to a variable within the EmployeeEdit.cs source code.

Listing 4.3.6 dropdownlist Snipit from EmployeEdit.aspx
 1: <tr> 2:   <td>Department</td> 3:   <td> 4:       <asp:dropdownlist runat="Server" id="Departments" /> 5:   </td> 6: </tr> 

Listing 4.3.6 comes from the EmployeeEdit.aspx page. Although there seems to be nothing worth noting, don't overlook the fact that the dropdownlist does not define any listitems . Instead of declaring the listitems within the aspx page, each ASP.NET WebControl supports databinding similar to the Windows Forms controls. In the code supporting the EmployeeEdit aspx page, there will exist the code to set up the databinding for the control. As with any databinding source, the container must implement GetEnumerator() or the IEnumerable interface. The departments will be held within an array list, so the general code looks something like the following:

 ArrayList Depts = new ArrayList( ); FillDepts( Depts ); Departments.DataSource = Depts; Departments.DataBind( ); 

Setting a databound control really doesn't require a lot of effort on the developer's part. Of course, like any WebControl, pragmatic access is always an option. If the default databinding doesn't fit the bill, there is the ability to write C# code and take full control.

The next control of interest is the input control that has its type set to file. This allows for the user to browse for a new photograph and upload it to the Web server.

 <input type="file" id="EmpImageFile" name="EmpImageFile" runat="server"> 

Wait, this is not an asp:* type control, so how can it be accessed behind the scenes? It just so happens that ASP.NET supports binding of HTML controls just like WebControls. When the input tag is specified with type="file" , the designer will create a variable of the following type:

 System.Web.UI.HtmlControls.HtmlInputFile 

This allows the code page to again access the HTML element. Listing 4.3.7 shows the C# code for EmployeeEdit.aspx.cs .

Listing 4.3.7 EmployeeEdit.aspx.cs
 1: using System;   2: using System.Collections;   3: using System.ComponentModel;   4: using System.Data;   5: using System.Data.SqlClient;   6: using System.Drawing;   7: using System.Web;   8: using System.Web.SessionState;   9: using System.Web.UI;  10: using System.Web.UI.WebControls;  11: using System.Web.UI.HtmlControls;  12:  13: using Stingray.Data;  14:  15: namespace EmployeeBrowser  16: {  17:     /// <summary>  18:     /// Summary description for EmployeeEdit.  19:     /// </summary>  20:     public class EmployeeEdit : System.Web.UI.Page  21:     {  22:         protected System.Web.UI.WebControls.Image EmployeeImage;  23:         protected System.Web.UI.WebControls.Label EmployeeId;  24:         protected System.Web.UI.WebControls.TextBox FirstName;  25:         protected System.Web.UI.WebControls.TextBox LastName;  26:         protected System.Web.UI.WebControls.DropDownList Departments;  27:         protected System.Web.UI.WebControls.Button btnUpdate;  28:         protected System.Web.UI.HtmlControls.HtmlInputFile EmpImageFile;  29:  30:         public EmployeeEdit()  31:         {  32:             Page.Init += new System.EventHandler(Page_Init);  33:         }  34:  35:         private void Page_Load(object sender, System.EventArgs e)  36:         {  37:            // Put user code to initialize the page here  38:  39:            //Enable Data binding  40:            DataBind( );  41:  42:            if( !IsPostBack )  43:                PopulateForm( );  44:            else  45:                UpdateEmployee( );  46:         }  47:  48:         private void PopulateForm( )  49:         {  50:  51:             string EmpId = this.Request.QueryString["EmpId"].ToString( );  52:             SqlConnection dbCon = DBAccess.AcquireConnection( );  53:             SqlDataAdapter cmd = new SqlDataAdapter(string.Format("SELECT * FROM graphics/ccc.gif EMPLOYEE WHERE EMP_ID = { 0} ", EmpId),dbCon);  54:             DataSet dsResult = new DataSet( );  55:             Employee emp = new Employee( );  56:  57:             cmd.Fill( dsResult, "EMPLOYEE" );  58:             if( dsResult.Tables["EMPLOYEE"] != null)  59:                 emp.FromDataRow( dsResult.Tables["EMPLOYEE"].Rows[0] );  60:  61:             //Set the values for stuff  62:             this.EmployeeId.Text = emp.Id;  63:             this.FirstName.Text = emp.FirstName;  64:             this.LastName.Text  = emp.LastName;  65:             this.EmployeeImage.ImageUrl =  66:             string.Format("~/images/employees/{ 0} .jpg", emp.PictureId.ToString( ));  67:  68:             //Populate the Department list  69:             cmd.SelectCommand.CommandText = "SELECT * FROM DEPARTMENT";  70:             cmd.Fill( dsResult, "DEPARTMENT" );  71:             Hashtable ht = new Hashtable( );  72:  73:             foreach( DataRow row in dsResult.Tables["DEPARTMENT"].Rows)  74:             {  75:                 int nValue = (int)row["DEPT_ID"];  76:                 string Name = (string)row["NAME"];  77:                 ht.Add( Name, nValue );  78:                 this.Departments.Items.Add( Name );  79:             }  80:  81:             this.Session["DEPT_MAPPING"] = ht;  82:             this.Session["CACHE:EMP"] = emp;        //save the employee  83:  84:          }  85:  86:          private void UpdateEmployee( )  87:          {  88:  89:              Employee emp = (Employee)Session["CACHE:EMP"];  90:  91:              emp.FirstName = this.FirstName.Text;  92:              emp.LastName = this.LastName.Text;  93:  94:  95:              //get new department  96:              Hashtable ht = (Hashtable)Session["DEPT_MAPPING"];  97:              int DeptId = (int)ht[ this.Departments.SelectedItem.Text ];  98:              emp.DeptId = DeptId;  99: 100: 101: 102:              //Get the Photo 103:              if( this.EmpImageFile.PostedFile != null && 104:                  this.EmpImageFile.PostedFile.FileName.Length > 0 ) 105:              { 106: 107:                  //Remove the Old Photo 108:                  string strFileName = 109:                             string.Format( 110:         "C:/Inetpub/wwwroot/EmployeeBrowser/images/employees/{ 0} .jpg", 111:         emp.PictureId.ToString( ) 112:                             ); 113: 114:                  System.IO.File.Delete( strFileName ); 115: 116:                  emp.PictureId =  System.Guid.NewGuid( ); 117:                  strFileName = 118:                       string.Format( 119:         "C:/Inetpub/wwwroot/EmployeeBrowser/images/employees/{ 0} .jpg", 120:         emp.PictureId.ToString( ) 121:                                    ); 122: 123:                      this.EmpImageFile.PostedFile.SaveAs( strFileName ); 124:               } 125: 126:               //Update the Employee 127:               DBAccess.Save( DBAccess.AcquireConnection( ), emp ); 128: 129:                  string strUrl = 130:                         string.Format( 131:            "EmployeeListing.aspx?DeptId={ 0} &FirstName={ 1} &LastName={ 2} ", 132:                          emp.DeptId,emp.FirstName,emp.LastName 133:                         ); 134: 135:                  Response.Redirect( strUrl ); 136: 137:            } 138: 139:            private void Page_Init(object sender, EventArgs e) 140:            { 141:                // 142:                // CODEGEN: This call is required by the ASP.NET Web Form Designer. 143:                // 144:                InitializeComponent(); 145:            } 146: 147:            #region Web Form Designer generated code 148:            /// <summary> 149:            /// Required method for Designer support - do not modify 150:            /// the contents of this method with the code editor. 151:            /// </summary> 152:            private void InitializeComponent() 153:            { 154:                this.Load += new System.EventHandler(this.Page_Load); 155: 156:            } 157:            #endregion 158:     } 159: } 

The EmployeeEdit page was designed to accept a query string containing the Employee ID as EmpId ; recall the EmployeeViewPagelet and the code contained within the OnEdit_Click method.

The following lines are from Listing 4.3.5:

 113: protected void OnEdit_Click( object sender, EventArgs e ) 114: { 115:       Response.Redirect( 116:               string.Format( "~/EmployeeEdit.aspx?EmpId={ 0} ", 117:                               btnEdit.CommandArgument ) 118:                ); 119: } 

When the Edit button raises a click event, the CommandArgument property contains the Employee ID. This Employee ID is used to create an HTTP GET request. Line 115 shows the syntax for passing parameters from one page to another.

The PopulateForm method, found in Listing 4.3.7, accesses the QueryString collection found in the Request object. I've omitted error checking and redirection to an error page, but you get the idea. The Employee ID contains all the state information necessary to populate the controls found within the page.

To hold on to information, such as state information or objects, there are two options ” Session or Cache . The EmployeeEdit page makes use of the session to store any necessary data. A Session can survive IIS crashes and work process restarts, but the Cache does not. When deciding where information should be stored, you'll need to examine the uses of the data and the necessity of ensuring that the data exists.

The Session and Cache objects both contain a hash table that maps a key to the object you want to store. The EmployeeEdit page stores both a hash table and the employee within the Session .

When the Update button raises a click event, the page is reloaded with IsPostBack set to true . Page_Load tests for this condition and calls UpdateEmployee rather than PopulateForm .

EmployeeListing

The EmployeeBrowser Web application is starting to come together. With the basic HeaderContol , EmployeeView control, and the EmployeeEdit page complete, it's time to create a Listings page. The Listings page will host one or more EmployeeView controls and allow for paging back and forth through the various employees.

Figure 4.3.5 shows the basic listing control with 2 rows per screen. Also notice the Next >> button at the bottom of the form. When paging takes place, the EmployeeListing.aspx will determine if there are previous records, and display a << Prev button when appropriate, as shown in Figure 4.3.5. The same is true for the Next >> button. If there are additional records, it will be visible; if not, the Next >> button will be hidden.

Figure 4.3.5. EmployeeListing with two rows.

graphics/0403fig05.gif

As you can see, I didn't enforce any type of sizing constraint on the images. The simplest way, of course, is to specify the allowed image size and reject any image that does not fit the sizing criteria.

So how does the EmployeeListing page display the EmployeeViewPagelets ? Easy. The secret is to make use of the asp:repeater control. Remember the repeater control we discussed? The EmployeeListing makes use of the repeater control to display the appropriate number of employees per page. Listing 4.3.8 shows the binding for the EmployeeView control.

Figure 4.3.6. EmployeeListing with two rows and the Prev button enabled.

graphics/0403fig06.gif

Listing 4.3.8 Snippet from EmployeeListing.aspx
 1: <asp:repeater id="EmployeeRepeater" runat="server">  2:   <ItemTemplate>  3:     <tr>  4:       <td>  5:           <EmployeeBrowser:EmployeeViewControl runat="server"  6:               EmployeeId='<%# DataBinder.Eval( Container.DataItem, "Id" )  %>'  7:               FirstName='<%# DataBinder.Eval( Container.DataItem, "FirstName" )  %>'  8:               LastName='<%# DataBinder.Eval( Container.DataItem, "LastName" )  %>'  9:               PictureId='<%# DataBinder.Eval( Container.DataItem,"PictureId" ) %>'> 10:           </EmployeeBrowser:EmployeeViewControl> 11:       </td> 12:     </tr> 13:   </ItemTemplate> 14: </asp:repeater> 

The EmployeeListing makes use of WebControl databinding to set the various properties of the EmployeeViewPagelet control. Notice that each property of the EmployeeViewPagelet control is assigned its value through the use of

 DataBinder.Eval( Container.DataItem,  X  ) 

where X is the name of a field found with the datasource. The source code behind the page creates an ArrayList of Employee objects and binds that list to the repeater control, EmployeeRepeater . Using this technique, binding property values is a breeze ! In fact, the snippet in Listing 4.3.8 is the only real meat of the aspx page. The rest is just HTML markup and the inclusion of the HeaderControl .

As with every aspx page so far, the EmployeeListing page implements the paging logic in a C# source file. After the data is bound to the repeater control, the current index is pushed on a stack and that stack is saved in the Session . When the Next or Prev buttons are pressed, the index is either calculated for the next set or the pervious index is popped of the stack. Listing 4.3.9 presents the source for the EmployeeListing page.

Listing 4.3.9 EmployeeListing.aspx.cs
 1: using System;   2: using System.Collections;   3: using System.ComponentModel;   4: using System.Data;   5: using System.Data.SqlClient;   6: using System.Drawing;   7: using System.Web;   8: using System.Web.SessionState;   9: using System.Web.UI;  10: using System.Web.UI.WebControls;  11: using System.Web.UI.HtmlControls;  12:  13: using Stingray.Data;  14:  15: namespace EmployeeBrowser  16: {  17:  18:     class ViewerState  19:     {  20:         public static string VIEW_STATE_SESSION_KEY = "EMPLOYEE_VIEWER_STATE";  21:         public DataSet       m_EmployeeCache;  22:         public int           m_RowCount = 0;  23:         public int           m_MaxPerPage = 5;  24:         public int           m_CurrentIndex = 0;  25:         public Stack         m_IdxStack = new Stack( );  26:     }  27:  28:     /// <summary>  29:     /// Summary description for EmployeeListing.  30:     /// </summary>  31:     public class EmployeeListing : System.Web.UI.Page  32:     {  33:         protected System.Web.UI.WebControls.Button    btnNext;  34:         protected System.Web.UI.WebControls.Button    btnPrev;  35:         protected System.Web.UI.WebControls.Repeater  EmployeeRepeater;  36:         private ArrayList                             m_EmployeeList;  37:         private ViewerState                           m_ViewerState;  38:  39:  40:  41:         public EmployeeListing()  42:         {  43:             Page.Init += new System.EventHandler(Page_Init);  44:         }  45:  46:         private void Page_Load(object sender, System.EventArgs e)  47:         {  48:             if (!IsPostBack)  49:             {  50:  51:                 int     DeptId = 0;  52:                 string  FirstName;  53:                 string  LastName;  54:  55:  56:                 m_ViewerState = new ViewerState( );  57:                 this.Session.Add(ViewerState.VIEW_STATE_SESSION_KEY ,m_ViewerState);  58:  59:                 GetParams( out FirstName, out LastName, ref DeptId,  ref graphics/ccc.gif m_ViewerState.m_MaxPerPage );  60:  61:                 LoadDataSet( FirstName, LastName, DeptId );  62:  63:  64:                 //save current index  65:                 m_ViewerState.m_IdxStack.Push( 0 );  66:                 int Index = this.CalcNextIndex(  );  67:                 m_ViewerState.m_CurrentIndex = Index;  68:                 this.DisplayData( 0, m_ViewerState.m_CurrentIndex );  69:                 UpdateNavigationButtons( );  70:  71:             }   else {  72:  73:                 m_ViewerState = (ViewerState)this.Session[ graphics/ccc.gif ViewerState.VIEW_STATE_SESSION_KEY];  74:             }  75:  76:         }  77:  78:         private void Page_Init(object sender, EventArgs e)  79:         {  80:            //  81:            // CODEGEN: This call is required by the ASP.NET Web Form Designer.  82:            //  83:            InitializeComponent();  84:         }  85:  86:         protected void GetParams(out string FirstName, out string LastName, ref int graphics/ccc.gif DeptId, ref int MaxPerPage )  87:         {  88:             DeptId     = this.Request.QueryString["DeptId"] == null ?  89:                          -1 : graphics/ccc.gif Int32.Parse(this.Request.QueryString["DeptId"].ToString( ));  90:  91:             FirstName  = this.Request.QueryString["FirstName"] == null ?  92:                          "" : this.Request.QueryString["FirstName"].ToString();  93:  94:             LastName   = this.Request.QueryString["LastName"] == null ?  95:                          "" : this.Request.QueryString["LastName"].ToString();  96:  97:             MaxPerPage = this.Request.QueryString["MaxPerPage"] == null ?  98:                          5 : graphics/ccc.gif Int32.Parse(this.Request.QueryString["MaxPerPage"].ToString( ));  99:         } 100: 101:         protected void LoadDataSet(string FName, string LName, int DeptId) 102:         { 103: 104:             if( DeptId != -1 ) 105:             { 106:                 m_ViewerState.m_EmployeeCache = Search.Find(DBAccess.AcquireConnection( ), DeptId, FName, LName); graphics/ccc.gif 107:             }  else { 108:                 m_ViewerState.m_EmployeeCache = graphics/ccc.gif Search.Find(DBAccess.AcquireConnection( ), FName, LName); 109:             } 110: 111:             m_ViewerState.m_RowCount = graphics/ccc.gif m_ViewerState.m_EmployeeCache.Tables["EMPLOYEE"].Rows.Count; 112:         } 113: 114: 115:         protected void DisplayData( int StartIndex, int StopIndex ) 116:         { 117: 118:             m_EmployeeList = new ArrayList( ); 119: 120:             for(int i = StartIndex; i < StopIndex; i++) 121:             { 122:                 Employee e = new Employee( ); 123:                 e.FromDataRow( graphics/ccc.gif m_ViewerState.m_EmployeeCache.Tables["EMPLOYEE"].Rows[i] ); 124:                 m_EmployeeList.Add( e ); 125:             } 126: 127:             //Bind the data 128:             EmployeeRepeater.DataSource= m_EmployeeList; 129:             EmployeeRepeater.DataBind( ); 130: 131: 132:         } 133: 134:         protected void OnNext_Click( object sender, EventArgs e ) 135:         { 136:              //save current index 137:              int nLast =  m_ViewerState.m_CurrentIndex; 138:              m_ViewerState.m_IdxStack.Push( nLast); 139:              m_ViewerState.m_CurrentIndex = CalcNextIndex( ); 140:              DisplayData( nLast, m_ViewerState.m_CurrentIndex ); 141:              UpdateNavigationButtons( ); 142: 143:          } 144: 145:          protected void OnPrev_Click( object sender, EventArgs e ) 146:          { 147:               int nStop  = (int)m_ViewerState.m_IdxStack.Pop( ); 148:               int nStart = (int)m_ViewerState.m_IdxStack.Peek( ); 149:               DisplayData( nStart, nStop ); 150:               m_ViewerState.m_CurrentIndex = nStop; 151:               UpdateNavigationButtons( ); 152:          } 153: 154:          protected int CalcNextIndex( ) 155:          { 156:              return (m_ViewerState.m_CurrentIndex + m_ViewerState.m_MaxPerPage) > graphics/ccc.gif m_ViewerState.m_RowCount 157:                     ? m_ViewerState.m_RowCount : (m_ViewerState.m_CurrentIndex + graphics/ccc.gif m_ViewerState.m_MaxPerPage); 158: 159:          } 160: 161:          protected void UpdateNavigationButtons( ) 162:          { 163:              this.btnNext.Visible = m_ViewerState.m_CurrentIndex < graphics/ccc.gif m_ViewerState.m_RowCount; 164:              this.btnPrev.Visible = (int)m_ViewerState.m_IdxStack.Peek( ) != 0; 165:          } 166: 167: 168: 169:          #region Web Form Designer generated code 170:          /// <summary> 171:          /// Required method for Designer support - do not modify 172:          /// the contents of this method with the code editor. 173:          /// </summary> 174:          private void InitializeComponent() 175:          { 176:              this.Load += new System.EventHandler(this.Page_Load); 177:          } 178:          #endregion 179:     } 180: } 

To see how data binding is set up, look at the DisplayData method on line 115. An ArrayList is constructed and Employee objects are added based on the StartIndex and StopIndex arguments to the method. After the ArrayList has been filled as specified, the EmployeeRepeater control is bound to the ArrayList . These bindings are evaluated using the <%# DataBinder.Eval( Container.DataItem, X) %> embedded binding statements.

To maintain view state information, a small ViewerState class is created. The ViewerState maintains a DataSet corresponding to the parameters passed into the page. The ViewerState also maintains the current index and a stack object that holds the previous indexes. This stack is used to facilitate paging to previous pages. The remainder of the code for EmployeeListing consists of data loading, index calculation, and the onclick handlers for the bntNext and btnPrev WebControl buttons.

The Search Page: Where It All Begins

With the internals of the EmployeeBrowser Web application in place, an entry point into the application is needed. A simple search page will fit the bill and allow the user to select the department, first/last name, and the number of listings per page. These choices will then be passed as parameters to the EmployeeListing aspx page for processing.

The Search page shown in Figure 4.3.7 will be used to kick off the EmployeeBrowser Web application.

Figure 4.3.7. Search page.

graphics/0403fig07.gif

This is the smallest of all the examples shown so far. Basically, all that is needed is to allow the user to select a department, a first/last name, and the number of listings per page. Again, rather than creating a UserControl -derived pagelet, a small aspx page will be used to gather the input and create the request URL for the EmployeeListing page. Listing 4.3.10 contains the HTML source for the EmployeeSearch.aspx page.

Listing 4.3.10 EmployeeSearch.aspx
 1: <%@ Register TagPrefix="EmployeeBrowser" TagName="HeaderControl" Src="~/Pagelets/ graphics/ccc.gif HeaderPagelet.ascx" %>  2: <%@ Page language="c#" Codebehind="EmployeeSearch.aspx.cs" AutoEventWireup="false" graphics/ccc.gif Inherits="EmployeeBrowser.EmployeeSearch" %>  3: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >  4: <HTML>  5:     <HEAD>  6:         <meta name="GENERATOR" Content="Microsoft Visual Studio 7.0">  7:         <meta name="CODE_LANGUAGE" Content="C#">  8:         <meta name="vs_defaultClientScript" content="JavaScript (ECMAScript)">  9:         <meta name="vs_targetSchema" content="http://schemas.microsoft.com/ graphics/ccc.gif intellisense/ie5"> 10:     </HEAD> 11:     <body MS_POSITIONING="GridLayout"> 12:         <form id="EmployeeSearch" method="post" runat="server"> 13: 14:     <!-- 15:            Insert the custom header control 16:         --> 17:         <EmployeeBrowser:HeaderControl runat="server" Text="Employee Search" graphics/ccc.gif ImageUrl="~/images/logo.jpg" ID="Headercontrol1" NAME="Headercontrol1" /> 18: 19:     <!-- 20:            Begin the Search Page Layout 21:         --> 22:         <table style="BORDER-TOP-STYLE: outset; BORDER-RIGHT-STYLE: outset; graphics/ccc.gif BORDER-LEFT-STYLE: outset; BACKGROUND-COLOR: lightgrey; BORDER-BOTTOM-STYLE: outset"> 23:           <tbody> 24:            <tr> 25:             <td>Department</td> 26:             <td> 27:              <asp:dropdownlist id="Departments" runat="server" /> 28:             </td> 29:            </tr> 30: 31:            <tr> 32:             <td>First Name</td> 33:             <td> 34:              <asp:textbox runat="server" id="FirstName" /> 35:             </td> 36:            </tr> 37: 38:            <tr> 39:             <td>Last Name</td> 40:             <td> 41:              <asp:textbox runat="server" id="LastName" /> 42:             </td> 43:            </tr> 44: 45:            <tr> 46:             <td>Max Per Row</td> 47:             <td> 48:              <asp:textbox runat="server" id="MaxPerRow" /> 49:             </td> 50:            </tr> 51: 52:            <tr> 53:             <td> <!-- Left Blank to push button to second column --></td> 54:             <td align="right"> 55:              <asp:button id="btnGO" onclick="OnSearch_Click" text="GO!" graphics/ccc.gif runat="server" /> 56:             </td> 57:            </tr> 58: 59:          </tbody> 60:         </table> 61:         </form> 62:     </body> 63: </HTML> 

As you can see, the markup is fairly simple. Notice the mixture of standard HTML and ASP.NET. This freedom allows the developer to use the best tool for the job. There is not always a need to require server-side controls, so standard HTML elements fit the bill. The advantage of ASP.NET server-side controls is the ability of the controls to down-level to the client browser.

The code for EmployeeSearch.cs (see Listing 4.3.11 ) employs many of the techniques of the previous pages developed so far. The Session object is used to hold some mapping information, the asp:dropdownbox makes use of data-binding, and when a PostBack is processed , the element data is retrieved to form the HTTP GET request to the EmployeeListing.aspx page.

Listing 4.3.11 EmployeeSearch.cs
 1: using System;   2: using System.Collections;   3: using System.ComponentModel;   4: using System.Data;   5: using System.Data.SqlClient;   6: using System.Drawing;   7: using System.Web;   8: using System.Web.SessionState;   9: using System.Web.UI;  10: using System.Web.UI.WebControls;  11: using System.Web.UI.HtmlControls;  12:  13: using Stingray.Data;  14:  15: namespace EmployeeBrowser  16: {  17:     /// <summary>  18:     /// Summary description for EmployeeSearch.  19:     /// </summary>  20:     public class EmployeeSearch : System.Web.UI.Page  21:     {  22:         protected System.Web.UI.WebControls.DropDownList Departments;  23:         protected System.Web.UI.WebControls.TextBox FirstName;  24:         protected System.Web.UI.WebControls.TextBox LastName;  25:         protected System.Web.UI.WebControls.TextBox MaxPerRow;  26:         protected System.Web.UI.WebControls.Button btnGO;  27:  28:         protected ArrayList    DepartmentList;  29:         protected Hashtable    htDeptMapping;  30:  31:  32:         public EmployeeSearch()  33:         {  34:            Page.Init += new System.EventHandler(Page_Init);  35:         }  36:  37:         private void Page_Load(object sender, System.EventArgs e)  38:         {  39:           if( !this.IsPostBack )  40:           {  41:               htDeptMapping = new Hashtable( );  42:               LoadData( );  43:  44:               this.Session.Add( "SEARCH_HT_MAPPING", htDeptMapping );  45:               Departments.DataSource = DepartmentList;  46:               Departments.DataBind( );  47:           }  48:           else  49:           {  50:               htDeptMapping = (Hashtable)this.Session[" SEARCH_HT_MAPPING"];  51:           }  52:  53:         }  54:  55:         private void Page_Init(object sender, EventArgs e)  56:         {  57:             //  58:             // CODEGEN: This call is required by the ASP.NET Web Form Designer.  59:             //  60:             InitializeComponent();  61:          }  62:  63:          protected void OnSearch_Click( object sender, EventArgs e )  64:          {  65:  66:            //Get the Selected params  67:            if(this.htDeptMapping == null)  68:            {  69:                Response.Redirect( "EmployeeListing.aspx?MaxPerPage=5" );  70:            }  71:            else  72:            {  73:  74:                int    DeptId    = (int)this.htDeptMapping[Departments. graphics/ccc.gif SelectedItem.Text];  75:                string FirstName = this.FirstName.Text;  76:                string LastName  = this.LastName.Text;  77:  78:                int iMaxPerRow    = 5;  79:  80:                if( MaxPerRow.Text != "" )  81:                 {  82:                    iMaxPerRow = Int32.Parse(this.MaxPerRow.Text);  83:                 }  84:  85:  86:                 //build the request URL  87:                 string request;  88:  89:                 if( DeptId != 0)  90:                 {  91:                   object[] args = {  DeptId, FirstName, LastName, iMaxPerRow } ;  92:                   request = string.Format("DeptId={ 0} &FirstName={ 1} & LastName={ graphics/ccc.gif 2} &MaxPerPage={ 3} ", args);  93:                 }  else {  94:                   object[] args = {  FirstName, LastName, iMaxPerRow } ;  95:                   request = string.Format("FirstName={ 0} &LastName={ 1} graphics/ccc.gif &MaxPerPage={ 2} ", args);  96:                 }  97:  98:                 Response.Redirect( string.Format("EmployeeListing.aspx? { 0} ", graphics/ccc.gif request) );  99:             } 100:         } 101: 102:         protected void LoadData( ) 103:         { 104: 105:              SqlConnection dbCon = DBAccess.AcquireConnection( ); 106:              SqlDataAdapter cmd = new SqlDataAdapter( "SELECT * FROM DEPARTMENT", graphics/ccc.gif dbCon ); 107:              DataSet dsResult = new DataSet( ); 108:              cmd.Fill( dsResult, "DEPARTMENT" ); 109: 110:              DepartmentList = new ArrayList( ); 111:              DepartmentList.Add( "All Departments" ); 112:              htDeptMapping.Add( "All Departments", 0 ); 113: 114:              foreach( DataRow row in dsResult.Tables["DEPARTMENT"].Rows ) 115:              { 116:                  Department d = new Department( ); 117:                  d.FromDataRow( row ); 118:                  DepartmentList.Add( d.Name ); 119:                  htDeptMapping.Add( d.Name, d.Id ); 120:              } 121: 122:              dbCon.Close( ); 123:              dbCon.Dispose( ); 124:              dsResult.Dispose( ); 125:         } 126: 127: 128:         #region Web Form Designer generated code 129:          /// <summary> 130:          /// Required method for Designer support - do not modify 131:          /// the contents of this method with the code editor. 132:          /// </summary> 133:          private void InitializeComponent() 134:         { 135:              this.Load += new System.EventHandler(this.Page_Load); 136: 137:           } 138:           #endregion 139:     } 140: } 

With the completion of the EmployeeSearch page, the EmployeeBrowser application is ready. Of course, some layout and design work would go a long way towards improving the overall appearance of the page but, because the focus is on the code, I'll leave the rest to you.

I l @ ve RuBoard


C# and the .NET Framework. The C++ Perspective
C# and the .NET Framework
ISBN: 067232153X
EAN: 2147483647
Year: 2001
Pages: 204

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net