Tracking down bugs in ASP.NET code

One of the trickier aspects of Web development is debugging. In this article we'll look at some of the new ways you can debug your ASP.NET code.

In the days of ASP or simple JavaScript, developers would track down code problems bugs using print statements. Microsoft changed this approach with the introduction of ASP.NET because it includes extensive features to more easily debug Web pages with the TraceContext class.

Choose the scope

Tracing activity within an ASP.NET application may be enabled for a single page or an entire Web application. The web.config file is used to enable tracing at the application level. The web.config file's trace element is used:

<trace enabled="false" requestLimit="10" pageOutput="false"
traceMode="SortByTime" localOnly="true" />

Let's take a closer look at its individual attributes:

  • enabled: Used to turn application-level tracing on (true) and off (false).
  • requestLimit: Delineates the number of traces stored in memory.
  • pageOutput: Signals whether tracing information is appended to each page (true) or not (false). If false is selected, the tracing information may be viewed on the special tracing page, trace.axd.
  • traceMode: Determines how the trace information is displayed. By default, it's set to sort by time, but it may be sorted by category (SortByCategory) instead.
  • localOnly: Signals whether remote debugging is available (false) or not (true).

However, say you experience problems with only one page within the application. In this case, you may enable tracing on an individual page by adding the trace attribute to the page directive:

<%@ Page language="c#" trace="true" tracemode="SortByCategory"
Codebehind="WebForm1.aspx.cs" AutoEventWireup="false"
Inherits="WebApplication1.WebForm1" %>

Notice that the trace and tracemode attributes coincide with their counterparts in the web.config file. If you're wondering which setting takes precedence, the page setting overrides the web.config setting, so you could enable tracing for an entire application and disable it for select pages. The choice of page or application level (or a combination) depends upon the situation.

Working with the output

Once you decide about the level of tracing necessary, you'll begin to receive the tracing output. If you're working with the entire application, you may view all traces (depending on the number maintained with the requestLimit attribute) with the trace.axd page. Likewise, an individual trace is created when viewing a single page trace.

The trace output is separated into five sections:

  • Request Details: This includes the session ID, time of request, encoding, request type (get, post, etc), and the status code.
  • Trace Information: Displays the details of the request, which includes the various events, associated with an ASP.NET page.
  • Control Tree: Displays the controls utilised within the page; it includes their size and the amount of associated bytes stored in ViewState.
  • Cookies Collection: The list of cookies utilised by the page.
  • Headers Collection: The HTTP headers associated with the request. This includes the Host, Cookie, and User-Agent.
  • Server Variables: The complete list of server environment variables associated with the request.

As an example, I've included a portion of a trace in the following listing. (It includes the Headers Collection portion of the trace.)

Headers Collection
Name Value
Connection Keep-Alive
Accept */*
Accept-Encoding gzip, deflate
Accept-Language en-us
Cookie ASP.NET_SessionId=vnadwr45jvrfhv55gbdygobs; LastVisited2=3/1/2004
 2:11:35 PM
Host localhost
User-Agent Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR

From this trace, we can see that the requesting client used English and Internet Explorer 6.0 with the .NET 1.1 Framework installed.

Adding custom information

The default trace capabilities may be valuable in many cases, but other situations may require more information about the page. You can add customer information to the trace log with the Write and Warn methods of the TraceContext class:

  • Write: Writes information to the trace log.
  • Warn: Writes information to the trace log, but it appears in red.

Each method is overloaded, with the most basic syntax accepting a simple message to insert into the trace log. These methods allow you to easily add custom information to the trace output by placing Trace.Write and Trace.Warn statements where necessary. Their output is contained in the Trace Information section of the trace output. (I find using the Warn method makes it easier to spot my additions, since they appear in red.)

No need to recompile

Another excellent feature is that you don't have to remove the trace elements once you're finished; you can simply disable tracing, and the trace statements are ignored. This is advantageous when problems may occur in production. Once in production, you may enable tracing on the application level and view tracing via the trace.axd page but not on the individual pages (set pageOutput to false) so users aren't disrupted.

Finally, the tracing feature adds overhead to an application, which can adversely affect performance. For this reason, you should only enable it on a production application when necessary and disable it as soon as possible.