E-commerce App 1
The Goals for this Example
Here we intend to create a web app that displays in a drop-down list the names of available products as
read in from a database. When the user clicks on a product name in the list, a new page of information
on that product is shown. The other main feature is that a consistent user interface is provided, with
the same header, footer, and navigation buttons on each page.
The Overall Design
- Look at the following picture and comments to get an overall view of the design.
Notice that this e-commerce app is for a fictitious software company called Br. David's Software.
The products are thus programs. You can, of course, substitute your own company with a different
line of products. Be sure that your proposed company can fit the simplifying
assumptions shown below. Also, each product needs to have a name, a brief description, a
price (which can be zero), a URL for where to download the product, and an optional URL for a
small image of the product.
- Default page
- The default (home) page gives a quick overview of the company and web site.
- Products page
- The user selects a product by clicking on it in the drop-down list.
- This brings up a results page showing
the information on this product as retrieved from the database.
- Search page
- This page is just a place-holder. We will implement the search functionality
in a later example.
- Privacy page
- The company's privacy policy is provided here. For this simple web app, there is
hardly a need for this, but if we should grow this into a more complicated app that
collects user data, a good privacy policy would be expected.
- Contact page
- This provides an email address and phone number.
- We make some simplifying assumptions
to keep this web app relatively easy
to make. In later examples we will add some of the functionality that we omit at this point.
- Although prices may be listed for the products,
no attempt will be made to arrange for payment.
- Users will obtain one product at a time so that no shopping cart is needed.
- Users will simply download each desired product. No mailing address or other user information
is thus needed.
- The number of products is small, and there is no need to group them by type, department, or
something similar. Also, the products have no variable attributes (such as size of a shirt,
color, etc.)
|
Creating the Web App
Make a New Web App
- For this web app, detailed directions will not be given for features covered in previous
examples. New features will be covered in greater detail.
- As usual, make a new ASP .NET web app using VB, and save it to a good location, such as
your M drive.
- We assume from here on that the name of the folder for the web app is e1.
- Use Layout, Position, Auto-position Options to change to statically positioned.
Absolute positioning would place each item in an exact location on the page, but in this
web app we are going to place items inside of a cell of a table, thus using tables
to arrange the items.
- Begin with Default.aspx, the first web form.
- Change the title to "Home, Br. David's Software".
- Save your work so far by using File, Save All.
- As shown in this screen shot, all you put on this form are a few labels.
If you wish, you can copy the text for these labels from the following box:
|
Welcome!
Br. David's software provides a number of interesting software items for Linux and
for Windows. Begin by clicking on the Products link.
Br. David Carlson, Associate Professor of Computing at Saint Vincent College,
creates this software as a hobby and so as to provide tools that assist in learning
certain areas of computing.
|
- So where are the other items that appear on the home page? These are the items that all of the
pages have in common. These are put into separate files which are then included into each
web form. Here is how all of that is done:
- The main idea is to use a couple of tables to hold the common items to be displayed.
The table format helps to keep these items in a fixed spot on the screen.
- A simple table, created with HTML tags, can be set up as in this example:
|
<TABLE BORDER=1>
<TR>
<TH>Column Name</TH>
<TH>Data Type</TH>
<TH>Length</TH>
<TH>Allow Nulls</TH>
</TR>
<TR>
<TD>Username</TD>
<TD>char</TD>
<TD>8</TD>
<TD>no</TD>
</TR>
<TR>
<TD>Salary</TD>
<TD>money</TD>
<TD>8</TD>
<TD>no</TD>
</TR>
<TR>
<TD>Title</TD>
<TD>char</TD>
<TD>24</TD>
<TD>no</TD>
</TR>
</TABLE>
|
- When a browser renders this table, the result is a 2-dimensional grid
that looks something like this:
|
Column Name |
Data Type |
Length |
Allow Nulls |
Username |
char |
8 |
no |
Salary |
money |
8 |
no |
Title |
char |
24 |
no |
- Even if you do not know HTML, you can easily figure out what the tags for a table mean.
TR is for a table row, TH is for a table header, and TD is for a table data item. Note
that closing tags begin with a /.
- Add a new file called header.txt to your project by right clicking your project name
in Solution Explorer, selecting Add and then New Item, and clicking on Text File.
Use the filename header.txt. Copy the following into your text file and save it:
|
<br/>
<table width="680" border = "0">
<tr>
<td width="5"> </td> <!-- blank column for spacing purposes -->
<td><font size="7" color="blue"><b>Br. David's Software<b></font></td>
<td align="right" valign="center"><img src="earth3.gif"></td>
</tr>
<tr>
<td width="5"> </td> <!-- blank column for spacing purposes -->
<td colspan="2" width="675">
<br/>
<hr>
<br/>
</td>
</tr>
</table>
<table width="680" border="0">
<tr>
<td width="5"> </td> <!-- blank column for spacing purposes -->
<td width="130" valign="top"> <!-- column with navigation links -->
<a href="Default.aspx">
<img src="http://cis.stvincent.edu/icons/comp.gray.gif" border="0" align="center"></a>
<font color="blue" size="4">
<a href="Default.aspx">Home</a></font>
<br/><br/>
<a href="Products.aspx">
<img src="http://cis.stvincent.edu/icons/comp.gray.gif" border="0" align="center"></a>
<font color="blue" size="4">
<a href="Products.aspx">Products</a></font>
<br/><br/>
<a href="Search.aspx">
<img src="http://cis.stvincent.edu/icons/comp.gray.gif" border="0" align="center"></a>
<font color="blue" size="4">
<a href="Search.aspx">Search</a></font>
<br/><br/>
<a href="Privacy.aspx">
<img src="http://cis.stvincent.edu/icons/comp.gray.gif" border="0" align="center"></a>
<font color="blue" size="4">
<a href="Privacy.aspx">Privacy</a></font>
<br/><br/>
<a href="Contact.aspx">
<img src="http://cis.stvincent.edu/icons/comp.gray.gif" border="0" align="center"></a>
<font color="blue" size="4">
<a href="Contact.aspx">Contact Us</a></font>
<br/<br/>
</td>
<td width="10"> </td> <!-- blank column for spacing purposes -->
<td valign="top" width="535"> <!-- column for primary page content -->
|
- Note: A better way to do this would be to use the Master Page facility in Visual Studio
and to put the desired tables and items that stay fixed on all of the pages into that.
The varying items are then placed on content pages. We do not show the details of
that approach here.
- We will look at the overall effect of this HTML below. For the moment, let's look at
some of the details of what the tags mean.
- Some of the HTML tags used here include:
- <br/> which is the break tag. This is used to go to skip to a new line.
- <hr> which is the horizontal rule tag. It puts a horizontal line across the web page.
- <img ...> tag. This is used to place an image on a web page. The image can be
specified by a filename or pathname on the server or by a URL to an image on another server.
The first of these is used like this
<img src="earth3.gif">
to display the picture of
the earth that you see on each page of this web app. (Here is a
link to this earth3.gif image, but feel free to choose your favorite
image instead. You should add this image to your Visual Studio project.)
The second of these img tags is used like this
<img src="http://cis.stvincent.edu/icons/comp.gray.gif" border="0" align="center">
to show an icon of a computer. That URL should get you the desired image.
- <font ...> tag. This is used to specify properties of the font to use. One
example is
<font color="blue" size="4">
to specify blue and size 4 for the font to use up until the closing </font> tag.
- <a ...> anchor tag. There's more than one possible use for an anchor tag, but here
we use it to provide a clickable link to another web page (form) as in the example
<a href="Search.aspx">Search</a>
where the text of the link is Search and the web page
the user is sent to is Search.aspx.
- Also note that gives a space one pixel wide.
- Add a new file called footer.txt to your project by right clicking your project name
in Solution Explorer, selecting Add and then New Item, and clicking on Text File.
Copy the following into your text file and save it:
|
</td>
</tr>
<tr>
<td width="5"> </td> <!-- blank column for spacing purposes -->
<td colspan="3" width="675">
<hr>
<br/>
<font size="2">
© Copyright 2008 Saint Vincent College
<br/><br/>
Last updated: 10/26/2008
</font>
<br/><br/>
<font color="red" size="2">
Warning: This is a demo, not a real e-commerce site!
</font>
</td>
</tr>
</table>
|
- There are no new HTML tags here.
- However, note the use of colspan="3" in the one td (table data) tag. This indicates that
this data item should span 3 columns. Contained in this data item are a horizontal rule,
the copyright notice, the date, and a warning note.
- The © produces the copyright symbol.
- Now we need to include the header and footer in the HTML for your web form.
- Begin by clicking the Source button at the bottom of your Default.aspx web form.
- The header is included by changing the section of HTML from the body tag to the form tag
so that it looks like the following:
|
<body>
<!-- #Include File="header.txt" -->
<form id="Form1" runat="server">
|
- You can also check this picture.
- In a similar way, include your footer.txt file between the closing form tag and the closing
body tag like this:
|
</form>
<!-- #Include File="footer.txt" -->
</body>
|
- Save your work so far by using File, Save All.
- Build your application.
- Examine your application in a web browser to check that the home page displays properly.
- What is the overall plan that these include files have given us?
- If you look at the HTML for the Default.aspx form and the HTML in the 2 include files,
you will see that overall we get a web page enclosed in an opening <html> and
closing </html> tags.
- Near the top there is a section enclosed in <head> and </head> tags. This
contains the title and a few other items.
- Thanks to the header.txt include file, the body section of the web form starts
out with a table of width 680. The table is used to get items placed where we want
them on the page and to do so consistently across all of the pages of this web app -- just
by using the same 2 include files.
- This first table contains 2 rows. Each row begins with a table data item containing 5 spaces.
This is used so that the visible items do not begin crammed up against the left margin.
- The first row has 2 other table items: Br. David's Software and an image of the earth.
- The second row has the same table data item of 5 spaces. This is followed by one table data
item that spans 2 columns. It contains a horizontal line (rule).
- Thus the first table gives the layout for the top of each web page in the application.
- The second table has the same width and also has 2 rows.
- The first row begins with a table data item of 5 spaces. This is followed by a table
data item of width 130 pixels that contains the navigation buttons and links. That is,
this item contains the 5 images and links. The <br/> tag is used several times to
skip to a new line so that these navigation items are separated by some vertical spacing.
- The next table data item in the first row contains 10 spaces. It is used to separate the
navigation items from the primary page content which is to follow.
- The next table data item is an empty one of width 535 pixels (the remaining amount for the
given table width). This is just a place holder. We will put our page content in this location.
- Note that this table item has its opening tag in header.txt, but its closing tag is
found in footer.txt.
- By looking at footer.txt, we see that the second (and last) row of the second table
starts with a table data item of 5 spaces and ends with a table data item that spans the
remaining 3 columns.
- This wide data item contains a horizontal line (rule) which begins the bottom of each web page.
- Following this are the copyright line, the "last updated" line, and the warning line that
says that this is not a real e-commerce site.
- As we see in the HTML view of the web form, after footer.txt we simply have the closing tags
for the body of the web page and for the web page itself.
- Using tables to get consistent spacing is a common technique. Putting them into
a Visual Basic Master Page would be a somewhat better way to do this here.
|
SQL Server Stuff
- Next, let's set up the data for our e-commerce site.
- We assume that you still have a logon for SQL Server and have access to the database
you used in the previous examples.
In our example here the name used for the database is CS305, but use the name of
your particular database.
- Copy the connection information from the Web.config file of one of your previous database-related
web apps and paste it into the Web.config file for this current project. You might browse to the
old app's folder with My Computer and open the file with Notepad or Wordpad in order to copy this
information. Replace any existing connection information in your new project's Web.config file
with the copied information. It should look something like this:
|
<connectionStrings>
<add name="PartsConnectionString" connectionString="Data Source=CIS-W2K8SERVER\SQL_CIS;Initial Catalog=CS305;Integrated Security=True"/>
</connectionStrings>
|
- In Server Explorer, under this connection string, create a new table called Software.
- You can refer to the directions in this
previous web app on how to create a new table.
- Set up the new table's fields as in this screen shot and as
shown below.
|
Column Name |
Data Type |
Allow Nulls |
Number |
int |
no |
Name |
varchar(50) |
no |
Description |
varchar(960) |
no |
ImageURL |
varchar(80) |
yes |
Price |
money |
no |
DownloadURL |
varchar(80) |
yes |
- Right click at the front of the Number field and choose the item that sets this field
as the the primary key field.
- As seen in the above screen shot,
under Properties, also change Identity to yes for the Number field,
with seed 1 and increment 1. This is so that each time you add a new row of data,
the Number value will automatically go up by 1.
- The meaning of each field is fairly obvious. The ImageURL is used to supply a link
to a small image of the product. The DownloadURL is a link to the software to download
or to the page from which the software can be downloaded.
- Add to this table the data contained in the text file software.txt.
Note that the primary key values are not included in this file, as they will be generated
automatically. The values for each field of a record are on one line after another, with a
blank line separating records.
- You can check this screen shot
of the data. Note that the primary key values in this screen shot do not start at 1 and
sometimes skip a number. That is because some records were deleted and others added
when this table was under construction.
- You can also refer back to how we added data to a table in this
previous web app.
You can, of course, use your own data instead of that shown here.
- Note that we use "none" for the ImageURL if we have no image.
|
Easy Pages
- Let's do the 3 easy web pages next.
- Add a web form called Search.aspx to your web project.
- Change the title to "Search, Br. David's Software".
- Place a single label on it containing the text
"Sorry! The search feature has not yet been implemented."
- Position this label close to the upper left corner of the form. With static positioning,
this should put it close to the upper left corner of the appropriate table cell
that holds the page content.
- Go to HTML view for this web form and include the header.txt and footer.txt in the exact
same locations we used before for the Default.aspx page.
- Next, add a web form called Privacy.aspx to your web project.
- Change the title to "Privacy, Br. David's Software".
- Place 2 labels on this form.
The first should contain the text "Privacy Policy" in large, bold.
- The other label should be placed below the first and contain the text)
"Our policy is never to sell or give to others data that you provide."
- Position these labels close to the upper left corner of the form.
- Go to HTML view for this web form and include the header.txt and footer.txt in the exact
same locations we used for the last 2 web forms.
- Now add a web form called Contact.aspx to your web project.
- Change the title to "Contact, Br. David's Software".
- Place 4 labels on this form starting in the upper left corner.
- We want the results to look like this.
- The first label contains the text "For further information, contact:" in extra large, bold.
- The next label contains "Br. David Carlson" in large, bold.
- The third label contains "Phone: 724-805-2416" in bold.
- The last label contains
"Email: <A HREF="mailto:carlsond@stvincent.edu">carlsond@stvincent.edu</A>
in bold.
- Go to HTML view for this web form and include the header.txt and footer.txt in the exact
same locations we used for the other web forms.
- In Visual Studio do File, Save All.
- Build your web app.
- Then test it locally (Start Without Debugging) to see that
the pages created thus far work reasonably.
|
Products Page
- Add a web form called Products.aspx.
- Change its title to "Products, Br. David's Software".
- We want to set up this form as shown in this screen shot of the
products page or in this view of the Products.aspx form
in Visual Studio.
- The content area begins with a label showing "Select a product from the pull-down:"
in extra large, bold.
- Below this add a drop-down list and change its ID to ProductList.
- Set the AutoPostBack property of ProductList to True so that a postback will happen when the user
selects an item from the list.
- Below this place a label that says "Error in accessing database" in red.
- Change the ID of this label to ErrorLabel and set the Visible property to False.
- Go to HTML view for this web form and include the header.txt and footer.txt in the exact
same locations we used for the other web forms.
|
The Stored Procedure for the Products Page
- As usual, we use a stored procedure to obtain from the database
the list of products to display in the drop-down list.
- Since you have created similar stored procedures before, we do not give detailed directions
here.
- Place the following code into your stored procedure:
|
CREATE PROCEDURE db_datareader.SelectNames
AS
SET NOCOUNT ON
SELECT DISTINCT Name
FROM Software
ORDER BY Name
RETURN
|
- Note that the stored procedure is named SelectNames and that it
selects the Name column of the Software table that we created above.
DISTINCT is used to be sure that we have no duplicate names, but we do not expect any. Also the
data is placed in ascending order by Name.
- Save your stored procedure.
- Then execute the stored procedure and see that the correct data is returned
as shown at the bottom of this screen shot.
|
The Products.aspx.vb Code-Behind File
- Adjust the Page_Load procedure so that it matches the following code.
- However, change "PartsConnectionString" to whatever name is used in your Web.config file.
|
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
Dim myDatabaseConnection As SqlClient.SqlConnection = Nothing
Dim myCommand As SqlClient.SqlCommand = Nothing
Dim myReader As SqlClient.SqlDataReader = Nothing
Try
Dim connectionString As String = _
ConfigurationManager.ConnectionStrings("PartsConnectionString").ConnectionString
myDatabaseConnection = New SqlClient.SqlConnection(connectionString)
myCommand = New SqlClient.SqlCommand()
'Set up to use a stored procedure:
myCommand.CommandType = CommandType.StoredProcedure
myCommand.Connection = myDatabaseConnection
myCommand.CommandText = "SelectNames"
'Use an SqlDataReader to execute the stored procedure and
'get the results into the drop down list:
ProductList.Items.Add("*** Make a choice ***")
myDatabaseConnection.Open()
myReader = myCommand.ExecuteReader()
While (myReader.Read())
ProductList.Items.Add(myReader.GetString(0))
End While
myDatabaseConnection.Close()
myDatabaseConnection.Dispose()
Catch exception As System.Data.SqlClient.SqlException
ErrorLabel.Visible = True
Catch exception As Exception
ErrorLabel.Visible = True
Finally 'Do cleanup tasks here:
myCommand = Nothing
If Not myReader Is Nothing AndAlso _
Not myReader.IsClosed Then
myReader.Close()
End If
myReader = Nothing
If Not myDatabaseConnection Is Nothing AndAlso _
myDatabaseConnection.State = ConnectionState.Open Then
myDatabaseConnection.Close()
myDatabaseConnection.Dispose()
End If
myDatabaseConnection = Nothing
End Try
Else ' We have a postback.
Page.Validate()
If Page.IsValid Then
Session.Add("ProductSelected", ProductList.SelectedItem.Text)
Response.Redirect("Results.aspx")
End If
End If
End Sub
|
- As you can see, the above code uses a data reader to populate the drop-down list with the
names of the products read (by our stored procedure) from the database.
- However, we manually added "*** Make a choice ***" as the first item in the list.
- If a user clicks on a product in the drop-down list, a postback happens. In this case
we use session state to keep track of the name of the product and redirect to another page,
the Results.aspx form.
- Save all of your files before going on.
|
The Results Page
- Add a new web form to your project and name it Results.aspx.
- Change its title to "Selected Product, 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.
- There should be a label containing "Information on Selected Product" in large, bold.
- Underneath this put a label in large size, but no bold, with nothing in its Text field. We will
fill this in with the name of a product in the code-behind file.
- Also set its Visible property to False and its ID to ProductNameLabel.
- Underneath this put a hyperlink. Change the ID of this hyperlink to DownloadHyperLink,
Text "Download", and Visible set to False.
- Below this put a label with ID PriceLabel. Set Visible to False.
- To the right of the DownloadHyperLink place an Image control from the Toolbox. Be sure
to get an Image and not an ImageButton.
- Change the ID of this Image to ProductImage.
Also set the Visible property to False. The code-behind file will fill in the ImageURL if we
have an image for the given product.
- Below all of these items put a TextBox and change its ID to ProductDescriptionBox.
Change the ReadOnly property to True to prevent the user from trying
to change what appears in this box.
- Also change the Visible property for this box to False and the TextMode property to Multiline (so
that the description will not show up as one long line).
- Finally, put a label below this containing the text "Error in accessing database" in red.
Change the ID to ErrorLabel and set the Visible property to False.
- Go to HTML view for this web form and include the header.txt and footer.txt in the exact
same locations we used for the other web forms.
- Save all of your files before proceeding further.
|
The Stored Procedure for the Results Page
- We use a stored procedure to look up the data for the product selected by the user.
- Place the following code into your stored procedure:
|
CREATE PROCEDURE db_datareader.SelectByName
(
@TargetName varchar(50)
)
AS
SET NOCOUNT ON
SELECT Name, Description, ImageURL, Price, DownloadURL
FROM Software WHERE (Name = @TargetName)
RETURN
|
- The stored procedure is named SelectByName, and it
selects all of the fields except the primary key Number
from the Software table's row that has the Name
- Save the stored procedure and then execute it to see that it works properly.
For example, if you use ted when asked for the value of the @TargetName parameter,
you should get the information on the ted product, as shown at the
bottom of this screen shot.
|
The Results.aspx.vb Code-Behind File
- Adjust the Page_Load procedure so that it looks as follows.
- However, again adjust "PartsConnectionString" to match the actual name used in your
Web.config file.
|
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim Temp As String
Dim Price As Decimal
Dim myDatabaseConnection As SqlClient.SqlConnection = Nothing
Dim myCommand As SqlClient.SqlCommand = Nothing
Dim myReader As SqlClient.SqlDataReader = Nothing
If Session.Count = 0 Then ' No session items were supplied.
ErrorLabel.Visible = True
Else
Try
Dim connectionString As String = _
ConfigurationManager.ConnectionStrings("PartsConnectionString").ConnectionString
myDatabaseConnection = New SqlClient.SqlConnection(connectionString)
myCommand = New SqlClient.SqlCommand()
'Set up to use a stored procedure:
myCommand.CommandType = CommandType.StoredProcedure
myCommand.Connection = myDatabaseConnection
myCommand.CommandText = "SelectByName"
myCommand.Parameters.AddWithValue("@TargetName", Session("ProductSelected"))
'Use an SqlDataReader to execute the stored procedure:
myDatabaseConnection.Open()
myReader = myCommand.ExecuteReader()
If myReader.HasRows Then
myReader.Read()
ProductNameLabel.Text = myReader.GetValue(0)
ProductNameLabel.Visible = True
ProductDescriptionBox.Text = myReader.GetValue(1)
ProductDescriptionBox.Visible = True
Temp = myReader.GetValue(2)
If Not Equals(Temp, "none") Then
ProductImage.ImageUrl = Temp
ProductImage.Visible = True
End If
Price = myReader.GetValue(3)
PriceLabel.Text = "Price: " & String.Format("{0:C}", Price)
PriceLabel.Visible = True
DownloadHyperLink.NavigateUrl = myReader.GetValue(4)
DownloadHyperLink.Visible = True
Else
ErrorLabel.Visible = True
End If
myDatabaseConnection.Close()
myDatabaseConnection.Dispose()
Catch exception As System.Data.SqlClient.SqlException
ErrorLabel.Visible = True
Catch exception As Exception
ErrorLabel.Visible = True
Finally 'Do cleanup tasks here:
myCommand = Nothing
If Not myReader Is Nothing AndAlso _
Not myReader.IsClosed Then
myReader.Close()
End If
myReader = Nothing
If Not myDatabaseConnection Is Nothing AndAlso _
myDatabaseConnection.State = ConnectionState.Open Then
myDatabaseConnection.Close()
myDatabaseConnection.Dispose()
End If
myDatabaseConnection = Nothing
End Try
End If
End Sub
|
- The main goal of this code is to use the stored procedure created above
so as to get the data on the selected product. This data is read using a data reader. Instead
of displaying this data in a data grid, we display it in the various labels, the text
box, image, etc. on the Results.aspx web form.
- Note that the value of ProductSelected is obtained from the session state object.
It is used as the value for the @TargetName parameter to the stored procedure.
- If the data reader has no rows of data, then the error label is displayed.
- The
myReader.Read() command is important. That gets one row of data.
Of course, in our case the stored procedure only returns one row of data.
- We then get at the column 0, column 1, etc. values for this row by using
myReader.GetValue(0) , myReader.GetValue(1) , etc.
- Of course, we know that our stored procedure returns the Name field value as the first
item (column 0), the Description as column 1, etc.
- Notice how an IF is used to skip filling in the ImageUrl field of ProductImage when the
ImageURL value returned by the stored procedure is the string "none". Recall that
we placed this string in the database table when we had no image for a given product.
- The PriceLabel is used to display the string "Price: " with the appropriate number concatenated onto
it. This number is formatted using String.Format, and the {0:C} indicates that parameter 0 (the only
parameter) will be formatted using currency format.
- Save all of your files again.
|
Testing Your Web Application
- Build your project.
- Start Without Debugging in order to test your web app locally.
- Once you have that working, publish your app to your live web server, have the web server
admin make it an IIS Web App, and view it in a browser to be sure it works.
- You have your first (simple) e-commerce app!
|
Back to the main page for ASP .NET Web Apps
|