This section shows and explains the code used in the classified application. Table 7.2 is a convenient reference so you can easily find any method that is part of the application, the source code module in which the method resides, the listing number, and a short description of the method. This information will help you as you study the program.
NOTE: There is a link to the Classifieds application from the www.ASPNET-Solutions.com Web site. Follow the links to Chapter Examples, and then choose Chapter 7. Or go directly to http://www.aspnet-solutions.com/chapter_7.htm. You also can download the complete project for both the C# and VB languages from this page.
When the Classifieds application first runs, users get the choice to search for, add, or edit items, as shown in Figure 7.1. Figure 7.1. The Main Classifieds Application Screen Allows Users to Search For, Add, or Edit Items.The first thing I need to point out are the Imports statements (or using statements for C#) that must be in the source code. These statements are shown below, and they include the namespaces for SQL database access, code for retrieving configuration from the Web.Config file, and code that uses the Cache API. C#using System.Data.SqlClient; using System.Configuration; using System.Web.Caching;VB Imports System.Data.SqlClient Imports System.Configuration Imports System.Web.Caching Retrieving the Background ColorWe're going to start off in this application by taking a look at some code that is common to all source code modules in the application. This code enables the application, in a cookie, to keep track of the user's selected background color. Actually, two cookies maintain the background color; one cookie is the actual color name, and the other cookie is the index of the selected color within the drop-down list that can be seen in the user interface in the main page. The code for doing the cookie information retrieval can be seen in Listing 7.1. The code includes two methods: the OutputColor() method and the GetColor method. The OutputColor() method retrieves the cookie that is identified by the key named ClassifiedsColor. The value that the code gets comes directly from the GetColor() method. This method returns a string that contains the named color. The named color is output into the HTML stream with the Response.Write() method. Once output into the HTML stream, this value becomes part of the bgcolor attribute found in the body tag. The GetColor() method first attempts to retrieve the cookie that is identified by the key named ClassifiedsColor. If this key cannot be found, then a cookie with the key ClassifiedsColor is created, and the default values of Cyan and 0 are added. Cyan is the named color, and 0 is the index of the drop down list. The AppendCookie() method is then called with the newly created cookie, and it will then persist. If the cookie was found, then the value is retrieved out of the cookie and returned as a string to the caller. Listing 7.1 Code Common to All Modules That Retrieve and Output the HTML Background ColorPublic Sub OutputColor() Response.Write(GetColor()) End Sub Private Function GetColor() As String If Request.Cookies("ClassifiedsColor") Is Nothing Then Dim Cookie As HttpCookie = _ New HttpCookie("ClassifiedsColor") Cookie.Values.Add("Color", "Cyan") Cookie.Values.Add("Index", "0") Response.AppendCookie(Cookie) Return "Cyan" Else Dim Cookie As HttpCookie = _ Request.Cookies("ClassifiedsColor") Return Convert.ToString(Cookie.Values.Get("Color")) End If End Function Initializing the User InterfaceThe main page is named Default.aspx. A number of items must be initialized in this page's Page_Load() method. It is important to note that no user-interface initialization is required if this method is being called in response to a post back. So before any user interface initialization is done in this method, the IsPostBack property is checked so that the initialization won't be done again unnecessarily. The first thing that happens is that the code checks for the existence of the ClassifiedsColor cookie. If this cookie exists, then the index value is retrieved so that the drop-down list box can be set to the correct color. That is, the drop-down list will correctly reflect whatever color the background is currently set to. The next thing that is done is to get the list of categories. This is done in one of two ways, either retrieving the list from the cache, or querying the database for the list. You will notice that the code acts as if the cached list exists. It assigns the category List.DataSource property from the Cache.Get() method. It then calls the DataBind() method and returns. If, however, the cache data does not exist, an exception will be thrown and the SQL code which is directly below will be executed. The SQL code is fairly straightforward. A new Connection object is created to the database. The Connection object is opened, a new command is created with the simple SQL select that will retrieve all the categories, and then a SQLDataReader object is retrieved by calling the command's ExecuteReader() method. The SqlDataReader object is added to the cache and identified with the key named Categories. A 20-second absolute expiration is specified, so this DataList will expire in 20 seconds. Once the SqlDataReader is retrieved, the CategoryList object (which is part of the user interface) is bound to the data. Listing 7.2 The Page_Load() Method in Default.aspx.cs, in Which the User Interface Is Initialized.Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load If Not IsPostBack And _ (Not Request.Cookies("ClassifiedsColor") Is Nothing) Then Dim Cookie As HttpCookie = _ Request.Cookies("ClassifiedsColor") PageColor.SelectedIndex = _ Convert.ToInt32(Cookie.Values.Get("Index")) End If If Not IsPostBack Then ' Programming for success, guarding against failure. Try CategoryList.DataTextField = "Name" CategoryList.DataValueField = "ID" CategoryList.DataSource = Cache.Get("Categories") CategoryList.DataBind() Return Catch End Try Dim objConnection As New _ SqlConnection(ConfigurationSettings.AppSettings("ConnectString")) Try objConnection.Open() Dim objCommand As New _ SqlCommand("Select * from Categories", objConnection) Dim objReader As SqlDataReader = objCommand.ExecuteReader() Cache.Add("Categories", objReader, Nothing, _ Date.Now.AddSeconds(20), Nothing, _ CacheItemPriority.High, Nothing) CategoryList.DataTextField = "Name" CategoryList.DataValueField = "ID" CategoryList.DataSource = objReader CategoryList.DataBind() ObjReader.Close() Catch ex As Exception ErrorMessage.Text = ex.Message.ToString() Finally If objConnection.State = ConnectionState.Open Then objConnection.Close() End If End Try End If End Sub Responding to Users in the Main PageThree buttons for the main page take the user to different pages. The first page is in response to the Edit Item button, the second page in response to the Search Item button, and the third page in response to the Add Item button. The EditItem_Click() method does two things. First, it sets a session variable name with the key of EditItem to Nothing (or null in C#). This session variable is used to remember which item the user is currently editing. How this session variable is used will become clear in later code, found in listing 7.8. But for now, it will suffice to say that we want to make sure that we start off fresh with nothing in this variable. The Response.Redirect() method is then called, going to the EditItem.aspx page. Before an item can be edited, though, an ID and password must be entered, as shown in Figure 7.2. Figure 7.2. You Must Enter ID and Password Before You Can Edit an Item.The SearchItem_Click() method starts off by creating a session variable and assigning it the value from the selected item in the category list. This value, from the database, will be the actual category ID that corresponds to the selected category name. If no value has been selected, an exception will be thrown; and when the exception is caught, this session variable will be set to 1 so that code later on in the program will know that a category was not selected. Another session variable named SearchCriteria is created and contains any key words that the user typed in. The Response.Redirect() method is called, taking the user to the SearchItem.aspx page. The AddItem_Click() method simply redirects the user to the AddItem.aspx page, as shown in Figure 7.3. Listing 7.3 Button Handlers for the Application's Main PagePrivate Sub EditItem_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles EditItem.Click Session("EditItem") = Nothing Response.Redirect("EditItem.aspx") End Sub Private Sub SearchItem_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles SearchItem.Click Try Session("CategoryID") = _ Convert.ToInt32(CategoryList.SelectedItem.Value) Catch Session("CategoryID") = -1 End Try Session("SearchCriteria") = KeyWords.Text Response.Redirect("SearchItem.aspx") End Sub Private Sub AddItem_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles AddItem.Click Response.Redirect("AddItem.aspx") End Sub Figure 7.3. Adding an Item Is Easy with the Simple User Interface.User Color SelectionThe method that responds to the user's color selection from the main page is PageColor_SelectedIndexChanged(). This method can be seen in Listing 7.4. If the method can already find a cookie named ClassifiedsColor, it retrieves this cookie, asks the color, and then asks the index of the selected item in the drop-down list. The Response.AppendCookie() method is then called to add this cookie to the current page. If the cookie does not exist, then a new cookie is created. The color and index values are added, and the expiration of this cookie is set to DateTime.MaxValue. Setting the expiration to this value in essence means that the cookie will never expire. This means that any time the user comes back to this application, the cookie will persist and be loaded again. The last thing that happens is a call to the Response.AppendCookie() method. Listing 7.4 Code That Responds to User Color SelectionPrivate Sub PageColor_SelectedIndexChanged( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles PageColor.SelectedIndexChanged If Request.Cookies("ClassifiedsColor") Is Nothing Then Dim Cookie As HttpCookie = New HttpCookie("ClassifiedsColor") Cookie.Values.Add("Color", PageColor.SelectedItem.Value) Cookie.Values.Add("Index", _ Convert.ToString(PageColor.SelectedIndex)) Response.AppendCookie(Cookie) Else Dim Cookie As HttpCookie = Request.Cookies("ClassifiedsColor") Cookie.Values.Set("Color", PageColor.SelectedItem.Value) Cookie.Values.Set("Index", _ Convert.ToString(PageColor.SelectedIndex)) Cookie.Expires = DateTime.MaxValue Response.AppendCookie(Cookie) End If End Sub Displaying the Session Start Time and the Application CounterThe code that displays the start time of the user session and the value found in the application-counter variable can be seen in Listing 7.5. Unlike most of the other code in the listings within this chapter, this code is from the .aspx file. It was relatively easy to put this code inline, so that is what was done. Doing this makes the program a little simpler than having the code behind methods. You can see that the Response.Write() method is called to output the start time and the counter directly into the HTML stream. Listing 7.5 Common User Interface Code That Displays the Session Start Time and the Application Counter<p align="center"><FONT color="blue" size="2">You have been using this application since <%Response.Write(Session("StartTime").ToString())%>.<br> There have been <%Response.Write(Application("Counter"))%> users today. </FONT> </p> Retrieving the Database Connection String from Web.ConfigMany of the applications that I create keep the database connection string in the Global.asax file. I had a system with such an application that I delivered to a client in the Atlanta area. When I got to the client's location, I found that the computer had a naming conflict with another computer on his network. I then changed the name of the computer and hooked it up. Unfortunately, the name change in the computer caused the database connection string to stop working. Without a copy of Visual Studio to recompile, I could have been in a big mess because changing the Global.asax.cs file with a text editor did not result in the application picking up the new connect string. Although I would have assumed the application would pick up the string, it didn't, and the application did not work. I was, however, able to recover. I had brought my development box with me, and I simply recompiled the application on the development box and copied it over. This example points out one weakness of keeping information such as database connection strings in the Global.asax file. The strings cannot easily be edited with a text editor so that the application will pick up the changes. For this reason, there are many cases in which similar information should be kept in the Web.Config file, from which the application can retrieve it. The Classifieds application keeps its database connection string in the Web.Config file. The pertinent part of the Web.Config file can be seen in Listing 7.6. The following code shows how to retrieve the string that will contain the configuration data named ConnectString from the Web.Config file. ConfigurationSettings.AppSettings("ConnectString") Listing 7.6 The Web.Config Section That Contains the Connection String[View full width] <?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="ConnectString" value="data source=localhost;initial catalog=Classifieds;persist security info=False;user id=sa;pwd=;packet size=4096" /> </appSettings> ... </configuration> Adding an Item to the Classifieds DatabaseListing 7.7 shows the code that is used that can be found in the AddItem.aspx.cs file. This code is all related to adding items into the Classifieds database. The Page_Load() method simply populates the CategoryList DropDrownList object. If the recordset that contains the list of categories can be found in a cache, then the CategoryList object is populated from this. Otherwise, the code drops down, queries the database, and from the retrieved recordset, populates the CategoryList DropDownList object. The user fills out a large number of user-interface items before submitting the new classified ad. The AddIt_Click() method can be seen just below the Page_Load() method in Listing 7.7. The method starts off by creating a new database connection object. It then creates an ExpirationDate object, which is contained in a DateTime object. It does this by obtaining the current date and time and using the AddDays() method to add however many days have been selected for this classifieds item to expire. The database connection is opened, and a SQL string is created based on all the information that the user has entered in the form's editable fields. At the end of the SQL string, you should notice that a special syntax retrieves the identity value once the record has been created. The ID (which is the identity value) is used below, and this retrieves the value into the stored procedure parameter named @ID. Once the query has been created, a SqlCommandObject is instantiated, the @ID parameter is added, its direction set, and the ExecuteNonQuery() method is called. The ID parameter then is retrieved into an integer, thus remembering the item's ID that was created as an identify field (this happens when a row is inserted into the database). The clean-up work in this method is to simply close the connection and redirect to the Thanks.aspx page. While the method is redirecting to this Thanks.aspx page, for convenience, the item's title, expiration, and ID are sent as command-line parameters. If for some reason the database code throws an exception, then the exception message will be displayed in the ErrorMessageLabel object. The last method in this listing is the Cancel_Click() method. This method simply redirects to the main page and does not save any information. Listing 7.7 The Code Found in AddItem.aspx.cs. This Code Initializes the User Interface, Saves the New Data, and Redirects to the Main Page.[View full width] Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load If Not IsPostBack Then Try CategoryList.DataTextField = "Name" CategoryList.DataValueField = "ID" CategoryList.DataSource = Cache.Get("Categories") CategoryList.DataBind() Return Catch End Try Dim objConnection As New _ SqlConnection(ConfigurationSettings.AppSettings(_ "ConnectString")) Try objConnection.Open() Dim objCommand As New _ SqlCommand("Select * from Categories", objConnection) Dim objReader As SqlDataReader = objCommand.ExecuteReader() CategoryList.DataTextField = "Name" CategoryList.DataValueField = "ID" CategoryList.DataSource = objReader CategoryList.DataBind() Catch ex As Exception ErrorMessage.Text = ex.Message.ToString() Finally If objConnection.State = ConnectionState.Open Then objConnection.Close() End If End Try End If End Sub Private Sub AddIt_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles AddIt.Click Dim objConnection As New _ SqlConnection( _ ConfigurationSettings.AppSettings("ConnectString")) Try Dim objDateExpires As DateTime = _ DateTime.Now.AddDays( _ Convert.ToInt32(Expire.SelectedItem.Value)) objConnection.Open() Dim strSql As String = _ "Insert into Item (Name,Category,Email,URL,Title," + _ "Description,DateExpires,Price,Password) VALUES (" + _ "'" + Name.Text.Replace("'","") + "'," + _ "'" + CategoryList.SelectedItem.Text + "'," + _ "'" + Email.Text.Replace("'","") + "'," + _ "'" + URL.Text.Replace("'","") + "'," + _ "'" + Title.Text.Replace("'","") + "'," + _ "'" + Description.Text.Replace("'","") + "'," + _ "'" + objDateExpires.ToShortDateString() + "'," + _ "'" + Price.Text.Replace("'","") + "'," + _ "'" + Password.Text.Replace("'","") + "'" + _ ") select @ID=@@IDENTITY" Dim objCommand As New SqlCommand(strSql, objConnection) objCommand.Parameters.Add("@ID", SqlDbType.Int) objCommand.Parameters("@ID").Direction = _ ParameterDirection.Output objCommand.ExecuteNonQuery() Dim nItemID As Integer = _ Convert.ToInt32(objCommand.Parameters("@ID").Value) Response.Redirect("Thanks.aspx?Title=" + Chr(34) + _ Title.Text + Chr(34) + "&Expiration=" + _ objDateExpires.ToShortDateString() + "&Item0" width="14" height="9" align="left" src="/books/2/627/1/html/2/files/ccc.gif" alt="graphics/ccc.gif"> Handles Cancel.Click Response.Redirect("Default.aspx") End Sub Editing an Item in the Classifieds DatabaseThe code for editing an item has a lot of similarity to the code for adding an item. That's because the user interface is almost identical for both processes, and the information contained in the user interface objects must be written to the database. Retrieving the Item to Be EditedFirst, the PopulateCategoryList() method takes what's in the cache and populates the CategoryList DropDownList object. If the cache doesn't have anything in it, a new query is made, from which the CategoryList object is populated. A method named RetrieveItem_Click() fires in response to the Retrieve Item button. In general, this method retrieves data from the database and populates the user interface objects. The item that is retrieved is based on the Item ID TextBox field into which users enter an item ID. The RetrieveItem_Click() method creates a database connection and opens it. It then creates a SQL string that selects an item's data based on the item ID that was entered. If the item exists in the database (and this will be true when the SqlDataReader's Read() method is True), the information will be taken from the recordset and placed into the user interface objects. You might notice that a session variable named EditItem is set to a value of 1. This setting is so that the application will know later on whether an item is being edited or added. This value of 1 indicates that an item is being edited. Once the data has been stored in the user interface objects, typical clean-up code follows. The SqlDataReader object is closed, and then the SqlConnection object is closed. Deleting an ItemAlso seen in Listing 7.8 is the Delete_Click() method. In general, this method deletes an item from the database. The Delete_Click() method first creates and opens a database connection. Then, a SQL string is created that will delete the correct item. A SqlCommand object is created and its ExecuteNonQuery() method called, followed by some clean-up code. The clean-up code consists of setting the EditItem session variable to Nothing (or null in C#), clearing the ItemID and Password fields, and closing the database connection. Listing 7.8 This Is the Code That Supports Item Editing Functionality. It Consists of Initializing the User Interface, Retrieving an Item's Data, Saving Updates to an Item, and Deleting an Item.Private Sub PopulateCategoryList() Try CategoryList.DataTextField = "Name" CategoryList.DataValueField = "ID" CategoryList.DataSource = Cache.Get("Categories") CategoryList.DataBind() Return Catch End Try Dim objConnection As New _ SqlConnection(ConfigurationSettings.AppSettings("ConnectString")) Try objConnection.Open() Dim objCommand As New _ SqlCommand("Select * from Categories", objConnection) Dim objReader As SqlDataReader = objCommand.ExecuteReader() CategoryList.DataTextField = "Name" CategoryList.DataValueField = "ID" CategoryList.DataSource = objReader CategoryList.DataBind() Catch ex As Exception ErrorMessage.Text = ex.Message.ToString() Finally If objConnection.State = ConnectionState.Open Then objConnection.Close() End If End Try End Sub Private Sub RetrieveItem_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles RetrieveItem.Click Dim objConnection As New _ SqlConnection(ConfigurationSettings.AppSettings("ConnectString")) Try objConnection.Open() Dim strSql As String = "select * from Item where '","") + " and Password='" + Password.Text.Replace("'","") + "'" Dim objCommand As New SqlCommand(strSql, objConnection) Dim objReader As SqlDataReader = objCommand.ExecuteReader() If objReader.Read() Then Session("EditItem") = 1 PopulateCategoryList() Name.Text = Convert.ToString(objReader("Name")) Dim i As Integer For i = 0 To CategoryList.Items.Count - 1 If CategoryList.Items(i).Text = _ Convert.ToString(objReader("Category")) Then CategoryList.SelectedIndex = i End If Next Email.Text = Convert.ToString(objReader("Email")) URL.Text = Convert.ToString(objReader("URL")) Title.Text = Convert.ToString(objReader("Title")) Description.Text = _ Convert.ToString(objReader("Description")) Expires.Text = Convert.ToString(objReader("DateExpires")) Price.Text = Convert.ToString(objReader("Price")) PW.Text = Convert.ToString(objReader("Price")) End If objReader.Close() Catch ex As Exception ErrorMessage.Text = ex.Message.ToString() Finally If objConnection.State = ConnectionState.Open Then objConnection.Close() End If End Try End Sub Private Sub Delete_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Delete.Click Dim objConnection As New _ SqlConnection(ConfigurationSettings.AppSettings("ConnectString")) Try objConnection.Open() Dim strSql As String = "Delete Item where EditItem") = Nothing ItemID.Text = "" Password.Text = "" Catch ex As Exception ErrorMessage.Text = ex.Message.ToString() Finally If objConnection.State = ConnectionState.Open Then objConnection.Close() End If End Try End Sub Searching for an ItemWhen users search for an item, the application must do a search of the database, and then, if the item is found, display the matches. Listing 7.9 shows the code that does this search. The code performs a query and then binds the data to a DataList object so that the user can easily make a selection, as shown in Figure 7.4. Figure 7.4. When a User Searches for Items, They Are Displayed in the Search Results Screen.The first thing the Page_Load() method in Listing 7.9 does is to instantiate and open a database connection. A SQL string is then created, based on the SearchCriteria session variable. This session variable is used to form a query that looks at the Description field and the Title field. If the search criteria matches any text found in either field, the item will be placed into the result set. Users may also have selected a category from the user interface on the main page. If they did, the value will be contained in a session variable named CategoryID. If this value is positive (>=0), then the SQL query will be adjusted so that the category ID will be a part of the query. The last thing the query must do is take the item expiration date into account. It does this by appending a clause to the SQL query string that makes sure that the expiration date has not occurred. A SqlDataReader object is returned from a SqlCommand Execute Reader() method. The recordset is then databound to the DataList named ResultList. Listing 7.9 This Code Supports the Item Search Functionality. In It Are Methods to Initialize the User Interface (Which Involves a SQL Query), and a Button Handler to Redirect to the Application Main Page.Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load If Not IsPostBack Then Dim objConnection As New _ SqlConnection(_ ConfigurationSettings.AppSettings("ConnectString")) Dim strSql As String = _ "select Title,Name,DateExpires,ID from Item where (" + _ "Description like '%" + _ Convert.ToString(Session("SearchCriteria")) + "%' " + _ "OR Title like '%" + _ Convert.ToString(Session("SearchCriteria")) + "%')" Dim nCategoryID As Integer = _ Convert.ToInt32(Session("CategoryID")) If nCategoryID >= 0 Then strSql += (" and Category in (select Name from " + _ Categories "where )") End If strSql += (" and DateExpires >= '" + _ DateTime.Now.ToShortDateString() + "'") Try objConnection.Open() Dim objCommand As New SqlCommand(strSql, objConnection) Dim objReader As SqlDataReader = objCommand.ExecuteReader() ResultList.DataSource = objReader ResultList.DataBind() Catch Finally If objConnection.State = ConnectionState.Open Then objConnection.Close() End If End Try End If End Sub Private Sub MainPage_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MainPage.Click Response.Redirect("Default.aspx") End Sub Viewing a Classified AdUsers view a classified item within the ViewItem.aspx page. This page displays the item from the Page_Load() method. This method expects an item ID to be contained in a session variable named ItemID. After it queries the database for the item, the database information is placed into the user interface. The Page_Load() method first creates and opens a database connection. A SQL query string is then formed with which a SqlCommand object is created. The ExecuteReader() method returns a SqlDataReader object, which contains all of the necessary item information. Finally, the user-interface objects are populated from the returned DataSet. Links to item URLs and e-mails make it easy for viewers to get more information, as shown in Figure 7.5. Listing 7.10 This Code Allows Users to View a Classified Item. It Consists of a SQL Query to Retrieve the Data, Populate the User Interface, and Respond to a Button That Redirects to the Main Application Page.Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load If Not IsPostBack Then Dim objConnection As New _ SqlConnection(_ ConfigurationSettings.AppSettings("ConnectString")) Try objConnection.Open() Dim objCommand As New SqlCommand("Select * from Item " + _ "where ItemID"), objConnection) Dim objReader As SqlDataReader = objCommand.ExecuteReader() If objReader.Read() Then Title.Text = Convert.ToString(objReader("Title")) Name.Text += Convert.ToString(objReader("Name")) Dim strEmail As String = _ Convert.ToString(objReader("Email")) If strEmail.Length > 0 Then Name.Text += ("<br>Email: <a href=mailto:" + _ strEmail + _ ">" + strEmail + "</a>") End If Dim strURL As String = _ Convert.ToString(objReader("URL")) If strURL.Length > 0 Then Name.Text += ("<br>Website: <a href=" + Chr(34) + _ strURL + Chr(34) + ">" + strURL + "</a>") End If Price.Text += Convert.ToString(objReader("Price")) Description.Text = _ Server.HtmlEncode(_ Convert.ToString(objReader("Description"))) End If objReader.Close() Catch ex As Exception ErrorMessage.Text = ex.Message.ToString() Finally If objConnection.State = ConnectionState.Open Then objConnection.Close() End If End Try End If End Sub Private Sub MainPage_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MainPage.Click Response.Redirect("Default.aspx") End Sub Figure 7.5. Links Are Offered So That Users Can E-mail a Seller or Go to a URL.Giving Feedback After an Item Has Been AddedThe code in Listing 7.11 displays information to the user about the classified add item that she has just added. The code that populates the Label objects that display the information can be found in the Page_Load() method. The MainPage_Click() method simply redirects the user to the Default.aspx page. The AnotherAd_Click() method redirects the user to the AddItem.aspx page. You can see this part of the application in Figure 7.6, in which the user is given information about the item that she just added. Listing 7.11 This Code Thanks the User for Adding an Item.[View full width] Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load Title.Text = Request.QueryString("Title") Expiration.Text = Request.QueryString("Expiration") ItemID.Text = Request.QueryString("ItemID") End Sub Private Sub MainPage_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MainPage.Click Response.Redirect("Default.aspx") End Sub Private Sub AnotherAd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AnotherAd.Click Response.Redirect("AddItem.aspx") End Sub Figure 7.6. Users Will Need to Remember the Item IDs and Their Passwords if They Want to Edit an Item at a Later Time.Maintaining the Counter and Day VariablesThe code that maintains the session start time and the application counter variables can be seen in Listing 7.12. Setting the session StartTime variable is easy. All that must be done is to set the variable equal to DateTime.Now. The application Counter variable, however, is slightly more complicated. The first thing that must be done is to check for its existence. If it doesn't exist, then a value of 0 is assigned to it. And one very important detail, even before this is done, is to use the Application.Lock() method. The Application.Lock() method must be called before any access is made to this application variable. Once you are sure that the application variable exists, then you will able to increment the variable in code that follows. But before you do this, you will also make sure that the application day variable exists. If it doesn't, you simply create it by assigning a DateTime.Now.Day() method to it. The last thing you do in this method is to call the Application.Unlock() method so that other threads will have access to this code. Listing 7.12 This Code, Which Can Be Found in the Global.asax file, Maintains the Counter and Day Variables.Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs) Session("StartTime") = DateTime.Now Application.Lock() If Application("Counter") Is Nothing Then Application("Counter") = 0 End If If Application("Day") Is Nothing Then Application("Day") = DateTime.Now.Day() End If Application("Counter") = Application("Counter") + 1 If DateTime.Now.Day() <> Application("Day") Then Application("Day") = DateTime.Now.Day() Application("Counter") = 1 End If Application.UnLock() End Sub |