ONDotNet.com    
 Published on ONDotNet.com (http://www.ondotnet.com/)
 See this if you're having trouble printing code examples


Learning ASP.NET for the ASP Developer, Part 1

by Neel Mehta
09/20/2004

The combination of the .com boom of the '90s and the success of Microsoft's ASP technologies created a huge number of ASP programmers. The weaknesses of ASP are now well known, and the ability to translate ASP knowledge into a new platform is often the desire of many of these ASP programmers. This is the goal of this article.

This article is presented in three parts. In this first part, we give an introduction to ASP.NET and provide a motivation for the framework. In the second part, we will delve deeper into ASP.NET, showing how the basic concepts in part one can be extended. Finally, in the third part, we will illustrate how you can scale up to larger web sites by sharing code across multiple pages of a site (similar to the server-side includes of classic ASP). We will also demonstrate how coding in ASP.NET can make a cumbersome task in classic ASP relatively straightforward.

This article will show how you can leverage your knowledge of classic ASP to master ASP.NET. Our goal of this article is to cover the major aspects of building large-scale ASP.NET web sites without overwhelming you with a steep learning curve. The aim is to get you to think like an ASP.NET developer. As a result, you will be able rapidly tap into the power of the ASP.NET framework. Furthermore, coding in ASP.NET will offer you several opportunities to dramatically simplify your program logic.

(Our intent is not to show you how you can take ASP code and, line by line, convert it to work in the .NET framework. Since ASP.NET is backward-compatible with classic ASP, there is not much to do if you are copying your code to a server running ASP.NET. So even though you may end up having to revamp your web site code completely, the effort will be well worth your while.)

Throughout this article, we borrow heavily from the "right-brain" learning paradigm together with your existing classic ASP skill set to explore and understand how to code in ASP.NET. This technique allows us to focus on concepts without getting bogged down in details that you as a classic ASP developer are already familiar with. Consequently, in this first part we generally restrict ourselves to partial code listings. Once the main ideas have been fixed, then in the subsequent parts of this series, we will illustrate how to then write a complete ASP.NET web page.

Let's Start with HTML

Say we want to display a list of books and their prices in a table like the one shown below:

ID Book Price ($)
1 ASP.NET in a Nutshell 44.95
2 ASP.NET Cookbook 39.95

The HTML code for this table is:

<table border=1> 
  <tr> 
    <td> ID</td> 
    <td> Book</td>
    <td> Price ($)</td> 
  </tr> 
      <!-- TABLE ROW for First Book --> 
  <tr>
      <td> 1</td> 
      <td> ASP.NET in a Nutshell</td> 
      <td> 44.95</td> 
  </tr> 
      <!-- TABLE ROW for First Book Ends --> 

  <!-- TABLE ROW for Second Book --> 
      <tr> 
      <td> 2</td> 
      <td> ASP Cookbook</td>
      <td> 39.95 </td> 
    </tr> 
  <!-- TABLE ROW for Second Book Ends --> 

</table> 

Every time we need to remove or add books, we have to manually add rows to the table. This can be very tedious and a nightmare to maintain. With classic ASP, we can use a do-loop to go through the records extracted from the database and build the rows:

Listing 2: Table in ASP

  <% 
    '################# Server Side Code Block ##############
    ' Connect to DB ' create the connection and recordset objects
    Dim objConn 
    ' create the connection and recordset objects
    set objConn = Server.CreateObject("ADODB.Connection") 
    ' Open the connection to the DB
    ' SQL Server DB connection 
    objConn.open _
      "Provider=SQLOLEDB;Server=(LOCAL);" + _
      "Integrated Security=SSPI;Initial Catalog=MySite.COM;" 
    dim objRS set objRS = Server.CreateObject("ADODB.Recordset") 
    objRS.ActiveConnection = objConn 
    set objRS = objConn.Execute("select * from Books") ' Extract records from database
    dim outputstring 
    ' format the header of the table 
    outputstring = outputstring & "<tr><td>ID" + _
      "</td><td>Title</td><td>Price</td>" 
    ' ############# DO LOOP for the TABLE ROWS for the BOOKS ##### 
    do until objRS.EOF
      outputstring = outputstring & "<tr>" 
      outputstring = outputstring & "<td>" & _ 
              objRS.Fields("ID").value & "</td>" 
      outputstring = outputstring & "<td>" & _ 
              objRS.Fields("Title").value & "</td>" 
      outputstring = outputstring & "<td>" & _
              objRS.Fields("Price").value & "</td>" 
      outputstring = outputstring & "</tr>"
      objRS.MoveNext 
    loop 
    ' ########### End of DO LOOP for the BOOKS ###################

    ' Clean up 
    set objRS = Nothing
    set objConn = Nothing 
    '################# Server Side Code Block Ends ########
  %>
  <!-- -------------Presentation HTML Block-------------- --> 
  <html>
  <head>   
  </head> 
  <body>
  <table border="1">
  <%= outputstring %> <!-- Mixing server side code with HTML --> 
  </table>
  </body>
  </html>
  <!-- ------------- Presentation HTML Block Ends -------- --> 
    

Related Reading

ASP.NET in a Nutshell
By G. Andrew Duthie, Matthew MacDonald

Notice, however, that VBScript is intermingled with pure or straight HTML. While this mixing may not look so bad in the toy example above, it can get intricate quite rapidly in fairly large web site implementations. Maintaining this type of code is no easy feat. Thus, in one sense, we have come back full circle with code that is hard to maintain.

Can we do even better and totally separate the server-side script code from the presentation code? Can the presentation code consist only of content markup tags and not have any "inline" shortcuts (<%= ...%>) for the ASP Response.Write method? Can we go even further and not even bother to write any HTML (such as table rows and other tags) in the server-side-script part of the page? If we are able to achieve this separation, then in our server-side code we need only focus on the business logic, while in the lower presentation block, we limit ourselves to markup-type issues.

In other words, we want a tag that is "intelligent" enough to know how to render the records extracted from the database assigned to it without us having to explicitly write the markup HTML in our code. By simply associating the recordset en masse to this "intelligent" tag, it should "know" that each record should be rendered as a HTML table row, and that each field forms the HTML table column. Writing a recordset to a table is very common; there already is such a tag defined: <asp:DataGrid> ... </asp:DataGrid>.

These "intelligent" presentation tags or elements allow us to neatly structure our code as follows:

The <asp:DataGrid> ... </asp:DataGrid> presentation tag is itself defined in the markup section with the rest of the HTML for the page. The new tag is accessed programmatically in the script block to associate the records using its ID attribute. Conceptually, programmatically accessing an element is similar to the way we do it in JavaScript/DHTML. The primary difference is that in JavaScript/DHTML, the code is executed on the client side. In ASP.NET, the code is executed by the server before delivering the HTML stream to the browser.

We place the <asp:DataGrid> ... </asp:DataGrid> element within a <form runat="server"> ... </form> container and specify a runat="server" attribute on the <asp:DataGrid> ... </asp:DataGrid> element. The runat="server" makes the corresponding elements "available," or accessible in the script block.

Now, here is where the magic of ASP.NET comes in. When assigning data records to a datagrid in ASP.NET, we do not write any HTML. Instead, all we do is specify that the datagrid is populated from the records we pulled from the database. Then, ASP.NET produces the appropriate HTML to display the records.

Technically speaking, in ASP.NET we set the source of the data of this tag (referred to as the DataSource) to the records that were pulled from the database. (The records themselves are pulled into a table, which can be accessed as a whole by referring to the DefaultView of the zeroth table, Table(0), as RecordSet.Table(0).DefaultView.) Once we have set the DataSource for all relevant tags, we next tell ASP.NET to actually start the population process to write the appropriate HTML for displaying the multiple records using a method for binding the data or recordset to the datagrid. This binding operation is known as the DataBind method.

This process can be summarized in four steps:

  1. Define <asp:datagrid> ... </asp:datagrid> in the presentation block and assign it an ID.
  2. Extract the relevant records from the database.
  3. Set the DataSource of the DataGrid to the records extracted.
  4. Use the DataBind method to populate the grid with the appropriate HTML (each record is displayed as a row in the table, and each field as a table column).

To fix ideas, we first consider the same HTML table to display our books that is devoid of any special layout--a plain vanilla table. The table is bare-bones but allows you to see the essential program flow. The following is a complete code listing; however, for now, please focus on the highlighted code in the script block. (We'll discuss the rest of the code structure in the subsequent part of this series.)


<%@ Page Language="vb" Debug="True" Trace="True" %>
<%@ import Namespace="System.Data" %>
<%@ import Namespace="System.Data.SqlClient" %>
<script runat="server">
'System.Web.UI.Controls namespace for the DataGrid control
  'System.Data namespace for the Dataset class
  'System.Data.SqlClient namespace for SQL server classes
  Sub Page_Load()
  
  'Set up the SQL Server database connection
  Dim ConnStr As String = "server='(local)'; trusted_connection=true; database='Demo'"
  Dim RecordSet As DataSet
  RecordSet = new DataSet()
  'Now, pull the records from the database
  Dim SQL As String = "Select * from Books"
  Dim RecordSetAdpt As new SqlDataAdapter(SQL, ConnStr)
  RecordSetAdpt.Fill(RecordSet) 
  
  'Set the data grid's source of data to this recordset
  DataGrid1.DataSource = RecordSet.Tables(0).DefaultView
  'Finally, bind this data to the control
  DataGrid1.DataBind()
  
  End Sub ' end of Page_Load
</script>
<!-- -------------Presentation/Markup Block Below -------------------------------- -->
  <html>
    <head>
    </head>
    <body>
        <form runat="server">
     <asp:DataGrid id="DataGrid1" runat="server">
     </asp:DataGrid>
       </form>
  </body>
  </html>

You will notice right away that the entire code seems to be eerily lacking in HTML tags. This lack of pure HTML is typical of ASP.NET pages; very often you will find yourself with pages that have barely any HTML, yet display rich content.

Finally, the following graphic makes a side-by-side comparison of classic ASP code versus ASP.NET code. The graphic shows the similarity of ASP.NET and classic ASP, as well the differences. Specifically, it illustrates how ASP.NET is better able to keep presentation separate from script than classic ASP.


(click for full-size image)

Improving Table Presentation

While the simple table being discussed so far is fine for introducing ASP.NET, the tables that we are likely to encounter in practice are going to have more formatting. So, now, let's add some color to the table headers to demonstrate how we can still add markup attributes to presentational elements yet maintain the separation of server-side-script code from the presentation elements. More specifically, notice that the headers in the vanilla table are simply the names of the corresponding fields in the database. But the field names may not always be in the form we'd like to display on a web page. So, this time, we will define a table in which we will change the heading of the Title field to a more descriptive one, Title of Book.

Since the data records that appear in the table do not change--the changes we want to make are purely for display--we can expect to make all of our modifications in the presentation block with absolutely no changes in the server-side-script block. All specifications will be made within the <asp:DataGrid> ... </asp:DataGrid> tags, as shown below:


<asp:DataGrid id="DataGrid1" runat="server">
<!-- Presentation Specification -->
</asp:DataGrid> 

First, we'll describe how to specify background colors for the table headers. Table headers, footers, and presentational elements can be specified using <HeaderStyle> ... </HeaderStyle>, <FooterStyle> ... </FooterStyle>, and <ItemStyle> ... </ItemStyle>, respectively. (Note that all tags are case-sensitive.) On each style element tag, specify the forecolor and backcolor attributes. In the following snippet, we specify the table headers:


<asp:DataGrid id="DataGrid1" runat="server" AutoGenerateColumns="False">
<HeaderStyle forecolor="White" backcolor="#006699"></HeaderStyle>
</asp:DataGrid> 

The datagrid element automatically builds a plain table. So if we want to modify the default column titles, we need to suppress the defaults. This suppression is accomplished by setting the AutoGenerateColumns attribute on the DataGrid element to False. Once we suppress the automatic generation of the columns, we then specify the column presentation information within the <columns> ... </columns> tags within the DataGrid tags.


<asp:DataGrid id="DataGrid1" runat="server" AutoGenerateColumns="False">
<HeaderStyle forecolor="White" backcolor="#006699"></HeaderStyle>
<Columns>
<!-- Columns Specification -->
</Columns>
</asp:DataGrid> 

Each column can be independently controlled using the <asp:BoundColumn> ... </asp:BoundColumn> tags. The name of this tag is not as unusual as it first looks. Recall that the data that is extracted from the database is bound to the DataGrid using the DataBind( ) method. Thus, the BoundColumn refers to a column that is bound to a specific field in a database table. Specifically, we can control the titles that appear on the header columns. The DataField attribute specifies the database field that the table column is associated with, and the HeaderText attribute specifies the title that appears in the header for this column. (While we haven't shown it in this example, you can also specify styles individually for each column within the <asp:BoundColumn> ... </asp:BoundColumn> tags, thus giving you complete flexibility in the presentation of a table. In addition, we can also modify the order of the columns by rearranging the order of the <asp:BoundColumn> ... </asp:BoundColumn> tags for each column within the <Columns> ... </Columns> tags.) Here is the code listing for our Books example, in which we do not show the ID column and display the price before the book's title:


<asp:DataGrid id="DataGrid1" runat="server" AutoGenerateColumns="False">
  <HeaderStyle forecolor="White" backcolor="#006699"></HeaderStyle>
  <Columns>
    <asp:BoundColumn DataField="Price ($)" HeaderText="Price (US$)">
      <ItemStyle horizontalalign="Center"></ItemStyle>
    </asp:BoundColumn>
    <asp:BoundColumn DataField="Title" HeaderText="Book Title">
      <ItemStyle horizontalalign="Left"></ItemStyle>
    </asp:BoundColumn>
  </Columns>
</asp:DataGrid>

This code produces the following table when viewed in a browser:

Price (US$) Book Title
45 ASP.NET in a Nutshell
40 ASP.NET Cookbook

While the specification for table styles seem simple enough to understand, you might feel that there seems to be a lot of things to memorize. However, as we will discuss later, Microsoft has an application that simplifies the development of ASP.NET code. In fact, all of the presentation code described in this section was created by "click and drag," using the application without any manual coding.

Related Reading

ASP.NET Cookbook
The Ultimate ASP.NET Code Sourcebook
By Michael A. Kittel, Geoffrey T. LeBlond

The resulting code is a lot easier to maintain than its classic ASP counterpart. After pulling the data records from the database, there are no further string concatenations that clutter up the code. All layout instructions are written in "almost-English" notation in the presentation block. Even a person not fully familiar with HTML can understand the layout specifications.

Summary

In this first introduction to ASP.NET, we have seen that ASP.NET can be thought of as a scalpel that cleanly separates the script-code block from the presentation markup elements. It provides us with a framework to structure our code along the lines of the way we "think" about the logic flow in our minds. In the example considered above, we may think of the logic flow as simply:

In classic ASP, on the other hand, the last two items are intertwined; the assignment of the records to the presentation elements is done together, making it tedious to later modify. Hence, I deliberately elected to approach ASP.NET using the <asp:datagrid> ... </asp:datagrid> presentation element since I believe it helps to rapidly motivate and get across the main ideas.

In the next article, we will continue the development of ASP.NET and learn how to write a complete ASP.NET page. We will also study a few more presentation elements, including some that can dramatically simplify writing JavaScript for HTML form validation.

Related Links and References

  1. ASP.NET in a Nutshell, G. Andrew Duthie, Matthew MacDonald, O'Reilly, June 2002
  2. ASP.NET Cookbook, Michael A. Kittel, Geoffrey T. LeBlond, O'Reilly, August 2004

Neel Mehta has a doctorate from the University of Pennsylvania and is an ardent fan of .NET and sees it as one of the few technologies that will be around for some time.


Return to ONDotnet.com

Copyright © 2009 O'Reilly Media, Inc.