CIS Logo SVC Logo

   Computing & Information Systems
   Department

 

Schoology Facebook        Search CIS Site      Tutorials

E-commerce App 2



The Goals for this Example


The main goal is to add a search capability to the previous e-commerce app 1. In the process we try out a data list for displaying the results of the search, though we ultimately decide that it is not the best choice for this particular application.

Copying the Previous Project and Making Small Changes

  • Open the previous project, e-commerce app 1, in Visual Studio.
  • Make a copy of this project and name the new project ecommerce2.
  • Close the old solution and open the new ecommerce2 project.
  • Let's fix an annoying aspect of the product lookup. If you try out your working version of ecommerce1, you may notice that if you look up a product, use the browser's backspace button, and then click on "*** Make a choice ***" in the drop down list, the code redirects to the results page where an error is displayed because no product matching the name "*** Make a choice ***" can be found.
  • Note that since the AutoPostBack property is True for the drop down list, a postback happens each time the user selects an item in the list that is different from the previous one selected. Thus a postback happens when a change of selection is made.
  • Our annoyance can be fixed by not redirecting to the results page when the selected item is "*** Make a choice ***".
  • You can do this by changing the Page_Load procedure for the products page to look like this:

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _
    Handles MyBase.Load
	
    'Put user code to initialize the page here
    Dim TargetProduct As String

    If Not IsPostBack Then
        Try
            ProductList.Items.Add("*** Make a choice ***")
            SqlConnection1.Open()
            dReader = SqlDataAdapter1.SelectCommand.ExecuteReader
            While (dReader.Read())
                ProductList.Items.Add(dReader.GetString(0))
            End While
        Catch exception As System.Data.SqlClient.SqlException
            ErrorLabel.Visible = True
        Catch exception As Exception
            ErrorLabel.Visible = True
        Finally
            SqlConnection1.Close()
        End Try
    Else   ' Postback case:
        TargetProduct = ProductList.SelectedItem.Text
        If Not Equals(TargetProduct, "*** Make a choice ***") Then
            Session.Add("ProductSelected", TargetProduct)
            Response.Redirect("Results.aspx")
        End If
    End If
End Sub

  • This is the same as the code used before except for the added TargetProduct variable and the code for the postback case.
  • Note the use of an IF to skip adding the selected product name to the session state and to skip redirecting to the results page in the case when the selected item is "*** Make a choice ***".

Adding Search Functionality



Search Page

  • You already have a search page named search.aspx.
  • We want to change this page so that it contains 3 labels, a text box, and a button as shown in this screen shot As before, these items begin several inches from the top and a couple of inches from the left edge. If you wish, you can copy the text for these labels from the following box:

You  can search for products whose name or description
contains a desired term or substring.
Search for:

  • Note that all 3 labels use medium font and that the last one is in bold.
  • Change the ID of the text box to SubstringBox.
  • Change the ID of the button to SearchButton and its Text field to "Search".
  • Since we included the header.txt and footer.txt files in each web form of ecommerce1, the search.aspx web form should still contain this.
  • Go to HTML view and check that these 2 files are included as in the ecommerce1 web app.
  • Save your work so far by using File, Save All.

The search.aspx.vb Code-Behind File

  • Adjust the Page_Load procedure so that it looks as follows:

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _
    Handles MyBase.Load
	
   'Put user code to initialize the page here
    Dim Target As String
    If IsPostBack Then   'Search button was clicked
        Page.Validate()
        If Page.IsValid Then
            Target = SubstringBox.Text.ToString()
            Session.Add("TargetSubstring", Target)
            Response.Redirect("SearchResults.aspx")
        End If
    End If
End Sub

  • The Page.Validate is present because we hope to add validators to the search web form in a later version of this project. We should, for example, use a required field validator for the text box. We skip the validators for the moment so as to keep this example short.
  • If a user clicks on the search button, a postback happens. In this case we use session state to keep track of the string to search for and redirect to another page, the SearchResults.aspx form.
  • Save all of your files before going on.

The Search Results Page

  • Add a new web form to your project and name it SearchResults.aspx.
  • Change its title to "Search Results, Br. David's Software".
  • We want to set up this form as shown in this screen shot of the results page or in this view of the form in Visual Studio.
  • Drag a data list from the Toolbox and place it on the form in the location shown in the above images. Do not worry about resizing the data list.
  • Leave the ID of the DataList as DataList1. Since it is our only data list, that will be obvious enough.
  • Set the Visible property for DataList1 to False.
  • Place 4 labels for error messages just above the data list. All should use small and red for their text. The Visible property should be False.
  • Change the ID of one label to DatabaseErrorLabel and set its Text field to "A database error happened".
  • Change the ID of another of the 4 labels to SessionErrorLabel and set its Text field to "No data was supplied".
  • Change the ID of another of the labels to NoDataLabel and set its Text field to "No matching data found".
  • Change the ID of the remaining label to ErrorLabel and set its Text field to "An error happened".
  • If security is a concern, it would be better to have only one error label with a very generic message such as "An error happened." There is no sense in giving away clues to attackers who are trying to hack your web application.
  • Now let's start to set up that data list.
  • Go to HTML view for the SearchResults.aspx form.
  • Find the HTML tags that start and end the data list.
  • Just before the closing <asp:datalist> tag, paste in the following HTML:

<HeaderTemplate>
    <table border cellspacing="1">
        <tr>
            <th align="left">Product name</th>
            <th align="left">Description</th>
        </tr>
</HeaderTemplate>
<FooterTemplate>
    </table>
</FooterTemplate>
<ItemTemplate>
    <tr>
        <td><%# DataBinder.Eval(Container.DataItem, "ProductName") %></td>
        <td><%# DataBinder.Eval(Container.DataItem, "ProductDescription") %></td>
    </tr>
</ItemTemplate>

  • The general idea of the above, is that we are setting up 3 templates for the data list. The HeaderTemplate indicates that the data list will display data as a table and that the column headers will be "Product name" and "Description". The FooterTemplate just contains the closing tag for the table. The ItemTemplate is the most important. It indicates the data items to display in each row of the table. As we will see later when we write the code-behind file for this form, we will query the database and place the results in a data set. Actually a data set can contain several data tables. The results of the stored procedure query will be in a data table with the same name as the stored procedure. In the ItemTemplate we use the notation:

<td><%# DataBinder.Eval(Container.DataItem, "fieldname") %></td>


  • Just by filling in the desired field name we indicate what field (column) of the current data table row we wish to put into the data list as a table data item.
  • Note that the <% %> tags are script delimiter tags. They indicate that the commands inside of these tags should be processed on the server, not in the user's browser.
  • The # is used when a data binding expression follows.
  • The DataBinder.Eval function places the current value of the desired fieldname into this location between the opening and closing table data item tags.
  • While in HTML view include header.txt and footer.txt in the exact same locations we used for the other web forms. (If you have forgotten where this is, look at one of the other web forms in HTML view.)
  • What you should now see in HTML view, with the various additions completed, should look like this picture.
  • Although Visual Studio may underline some of the HTML as if there are errors, this will work!
  • Switch to Design view for your SearchResults.aspx form.
  • Click on your data list and in the Properties view, click on the Property Builder link.
  • Click on Borders. Then fill in 2 for "Cell padding", Tan for "Border color", and 1 for "Border width".
  • While still in Proerty Builder, click on Format and then on DataList. Fill in Black as the "Forecolor" and LightGoldenrodYellow as the "Back color".
  • Click OK to get out of Property Builder.
  • You can, of course, experiment with other colors.
  • You should also be able to supply the above settings in Properties and skip the use of Property Builder.
  • You should now be able to drag the edges of the data list to resize it. Make it fairly wide, as seen in this screen shot.
  • For more information it is suggested that you look up DataList in the Visual Studio help system.
  • Save all of your files before proceeding further.

The DataAdapter and Stored Procedure

  • Add an SQLDataAdapter to the SearchResults.aspx web form.
  • We will use this data adapter and an associated stored procedure to look up the data for the product or products that are the results of the search.
  • Since you have created similar stored procedures before, we do not give detailed directions here. Refer to the user input example if you need help.
  • Set up your stored procedure so that it is named SelectProdSearch and so that it selects the ProductName and ProductDescription fields from any Prod5 row that matches the search condition.
  • How do we set up the search condition? By using LIKE to see if the target string occurs as a substring of the ProductName or the ProductDescription. The exact SQL is shown in the box below, but you would probably generate it by using Query Builder as seen in this screen shot.
  • Note that some databases use the * symbol instead of % as the wildcard to indicate zero or more characters.
  • In ProductName LIKE '%' + @Target + '%' we are specifying that the ProductName should be any number of characters, followed by the target string that the user is looking for, followed by any number of characters. The + is used to append the items on either side of it.
  • Also order the results of this query in ascending order, first by ProductName and then by ProductDescription (in the unlikely event that we have 2 products with the same name).
  • Do NOT generate insert, delete, or update stored procedures to go along with this one.
  • When finished, your stored procedure should look like the following:

CREATE PROCEDURE studentc.SelectProdSearch
(
    @Target varchar(50)
)
AS
    SET NOCOUNT ON;
SELECT ProductName, ProductDescription FROM dbo.Prod5
WHERE (ProductName LIKE '%' + @Target + '%') OR (ProductDescription LIKE '%' + @Target + '%')
ORDER BY ProductName, ProductDescription
GO

  • Remember to go to SQL Server Enterprise Manager and give the SQL or IWAM account Exec access to this stored procedure. (Use whatever fits your server configuration.)
  • In the Properties window for your new data adapter, expand the SelectCommand field. Replace what is in the CommandText field with yourid.SelectProdSearch. (Of course, fill in your user ID in place of yourid.) Say Yes and Yes to the questions asked.
  • In the Properties window for the data adapter, try out the Preview Data link to see if your stored procedure is working.
  • In Visual Studio do File, Save All.

The results.aspx.vb Code-Behind File

  • Look at the code inside of the "Web Form Designer Generated Code" region.
  • Add the following line in the usual location:
    Protected dSet As New DataSet
  • Adjust the Page_Load procedure so that it looks as follows:

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _
    Handles MyBase.Load
	
    'Put user code to initialize the page here
    Dim Substring As String
    If Not IsPostBack Then
        If Session.Count = 0 Then   ' No session items were supplied.
            SessionErrorLabel.Visible = True
        Else
            Try
                Substring = Session("TargetSubstring")
                If Substring = "" Then
                    SessionErrorLabel.Visible = True
                Else
                    SqlConnection1.Open()
                    SqlDataAdapter1.SelectCommand.Parameters("@Target").Value = Substring
                    SqlDataAdapter1.Fill(dSet)
                    If dSet.Tables.Item(0).Rows.Count = 0 Then
                        NoDataLabel.Visible = True
                        DataList1.Visible = False
                    Else
                        DataList1.DataSource = dSet
                        DataList1.DataMember = "SelectProdSearch" _ 
                        'Use the name of the stored procedure.
						
                        DataList1.DataBind()
                        DataList1.Visible = True
                    End If
                End If
            Catch exception As System.Data.SqlClient.SqlException
                DatabaseErrorLabel.Visible = True
            Catch exception As Exception
                ErrorLabel.Visible = True
            Finally
                SqlConnection1.Close()
            End Try
        End If
    End If
End Sub

  • The purpose of this code is to use the data adapter and stored procedure just created above to get the data on the selected product into a data set and then to display this data in the data list.
  • The code only tries to get data from the database if there is no postback and if something (hopefully the TargetSubstring) is available in the session state.
  • The TargetName is retrieved from the session state and plugged in as the value of the @Target parameter to the stored procedure.
  • The results of the stored procedure's query are placed into the DataSet named dSet.
  • We check dSet.Tables.Item(0).Rows.Count to see if the number of rows of data is 0. If so, then an error label is displayed. Note that dSet.Tables is a collection of the data tables in dSet. Then Item(0) is used to pick out the first (and only) data table. Rows gives the collection of rows from this data table.
  • Next we use DataList1.DataSource = dSet to indicate that the source of the data for DataList1 should be our data set.
  • Then we use DataList1.DataMember = "SelectProdSearch" to specify which table of the data set should be used. The name of the data table containing the results of the query has the same name as the stored procedure.
  • However, some users report that the name of the data table is the same as the name of the table in the SQL Server database. One user even reported that the line of code to set the DataMember can be skipped. If anyone can explain this, please let the author of these pages know.
  • We then bind the data to the data list.
  • Save all of your files.

Testing Your Web Application

  • Build your project.
  • View your new web app in a browser and check that all pages display correctly and that the database-related code works on the products and results pages as well as the search and search results pages.
  • Note that if you search for a common string such as Windows, you may get so much data in your data list that it does not fit in the empty region on the search results page. This is a problem, as the data and footer information get superimposed.

Conclusions

  • Because of the problem just noted, we decide that a data list is not the best way to display the search resulsts in this web app. If we did not care about having the consistent layout on each web page, we could just abandon this layout (as supplied by header.txt and footer.txt) and let the data list be as long as needed.
  • In our next web app, we will switch to the familiar data grid to display the results of the search. This is because the data grid has an easy way to control how many rows of data display at once. Using this we can fit the data into our fixed page layout.
  • In spite of the fact that we have decided to abandon the data list, it is useful to know how to use it, since it could be helpful in a different application. Also, we learned how to use a data set in the current web app, which is also useful.

Back to the main page for ASP .NET Web Apps



Author: Br. David Carlson
Last updated: September 14, 2008
Disclaimer