ASP.NET

Page Tracing

The first place to start with debugging is to examine ASP.NET page tracing. The Page class has a property named Trace. When Trace is turned on, it tells the ASP.NET runtime to insert a rendering of the entire context of the request and response at the end of the HTML sent to the client.

We've already seen page tracing to some extent. When we looked at the ASP.NET server-side control architecture, the page trace was invaluable in understanding the structure of the page. Remember, a rendered page is composed of a number of server-side controls collected together as a hierarchical tree. A Page nests several controls, and the controls themselves may nest other controls (they may be nested several levels deep, as a matter of fact). The page trace includes a section displaying the composition of the page in terms of server-side controls.

Turning on Tracing

Turning tracing on is easy. Simply set the Trace property of the page to True. You may turn tracing on either by modifying the ASPX code directly, or by setting the Trace property using the designer. Here's the Trace property being turned on directly within the ASPX code as part of the page directive.

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="TraceMe.aspx.cs"
Inherits="TraceMe" Trace="true" %>

As soon as you turn tracing on and surf to the page, you'll see tracing information appear at the end of the HTML stream. The TraceMe.aspx page builds a table of strings as they're entered on the site. The list of strings is kept in session state and refreshes the table every time a new string is submitted.

Listing 16-1
public partial class TraceMe : System.Web.UI.Page
{
   ArrayList alTableEntries = null;

    protected void Page_Load(object sender, EventArgs e)
    {
      alTableEntries = (ArrayList)this.Session["TableEntries"];
      if (alTableEntries == null)
      {
         alTableEntries = new ArrayList();
      }
      AssembleTable();
    }
   protected void AssembleTable()
   {
      this.Table1.Rows.Clear();
      foreach (String s in alTableEntries)
      {
         TableRow row = new TableRow();
         TableCell cell = new TableCell();
         cell.Text = s;
         row.Cells.Add(cell);
         this.Table1.Rows.Add(row);
      }
   }
   protected void Button1_Click(object sender, EventArgs e)
   {
      alTableEntries.Add(this.TextBox1.Text);
      this.Session["TableEntries"] = alTableEntries;
      AssembleTable();
   }
}

Figure 16-1 shows how the page appears with tracing turned on.

Figure 16-1 Tracing turned on for the application in Listing 16-1.
Figure 16-1 Tracing turned on for the application in Listing 16-1.

A bit further down the tracing output, you'll see the control tree (as we saw in Tutorials 3, 4, and 5). The control tree for this page is shown in Figure 16-2.

Figure 16-2 Tracing turned on for the application in Listing 16-1. Notice the control tree.
Figure 16-2 Tracing turned on for the application in Listing 16-1. Notice the control tree.

Finally, scroll down a teeny bit more, and you start seeing some of the context information associated with the request. Figure 16-3 shows this context information. This application uses session state to save the array of strings. Notice the session state tracing shows the contents of the session state dictionary. You also get to see other context information. For example, the tracing section shows the session ID and the URL used to surf to this page.

Of course, much of this information becomes more useful in cases where there's a problem with your Web site. For example, the table might stop building itself because you somehow removed the session state item holding the list of strings. You could detect that by examining the page trace. If users begin complaining about layout issues with your site, you may look at the user agent coming down with the request and learn that the client is using a browser not accommodated by your application.

Figure 16-3 Tracing turned on for the application in Listing 16-1. Note the detailed information about the context of the request.
Figure 16-3 Tracing turned on for the application in Listing 16-1. Note the detailed information about the context of the request.

Trace Statements

In addition to all the request context information included with the HTML stream, the page trace also includes specific statements printed out during execution. If you scroll to the Trace Information block on the page, you can see these trace statements, shown in Figure 16-4.

The statements appearing in Figure 16-4 were produced by the ASP.NET framework. You can see the execution of the page progressing through the various events such as PreInit, Init, LoadState, and so forth.

Not only do you get tracing information from ASP.NET itself, but you may also insert your own tracing information. The Page class's Trace object provides a means of tracing page execution. Here's an exercise that shows you how to do this.

Figure 16-4 Tracing turned on for the application in Listing 16-1. These Trace statements track the execution of the page.
Figure 16-4 Tracing turned on for the application in Listing 16-1. These Trace statements track the execution of the page.

Adding Tracing Statements

  1. Open the DebugORama Web site.

  2. Open the TraceMe.aspx page and examine the code. Add tracing statements in strategic places through the page's Trace object. For example, you might want to monitor the table as it's being built. Do this by calling either Trace.Write or Trace.Warn within the page. Trace.Write renders the string in black, while Trace.Warn renders the tracing string in red. The first parameter is a category string you may use to help distinguish the statements you write when they finally render. You may add whatever you want to the category string.

    public partial class TraceMe : System.Web.UI.Page
    {
       ArrayList alTableEntries = null;
    
       protected void Page_Load(object sender, EventArgs e)
       {
          alTableEntries = (ArrayList)this.Session["TableEntries"];
          if (alTableEntries == null)
          {
             Trace.Warn("Page_Load",  "alTableEntries is null");
             alTableEntries = new ArrayList();
          }
          AssembleTable();
       }
       protected void AssembleTable()
       {
          this.Table1.Rows.Clear();
    
          foreach (String s in alTableEntries)
          {
             Trace.Write("AssembleTable","String found: " + s);
             TableRow row = new TableRow();
             TableCell cell = new TableCell();
             cell.Text = s;
             row.Cells.Add(cell);
             this.Table1.Rows.Add(row);
          }
       }
       protected void Button1_Click(object sender, EventArgs e)
       {
          Trace.Write("Button1_Click", "Adding string: " + this.TextBox1.Text);
          alTableEntries.Add(this.TextBox1.Text);
          this.Session["TableEntries"] = alTableEntries;
          AssembleTable();
       }
    }
    
  3. Compile the program and run the Web site. You should see your trace statements appearing in the output (as long as tracing is turned on).

    Graphic