As mentioned, one weakness of classic ASP was the lack of an easy way to get information about the current request. You should create reusable include files to write out the contents of the various collections of the request object, but there was no simple method of making this information available. ASP.NET provides a solution in the form of tracing, which provides a substantial amount of information about requests that have been executed, either at the page level or the application level, as well as a way to get your own custom debug information without exposing it to the users of your application.
The simplest way to access trace information is through the Trace attribute of the @ Page directive. By adding the Trace attribute to any .aspx page, you can instruct ASP.NET to append the trace output for that page to the rendered content of the page. The following example shows how to enable tracing on a simple ASP.NET page.
Open Visual Studio and create a new ASP.NET Web Application project called Chapter_14. Rename the default Web Page created by Visual Studio from WebPage1.aspx to SimpleTrace.aspx by selecting File, then Save WebForm1.aspx As.
Right-click anywhere on the page, and select Properties from the context menu. In the resulting dialog box (shown in the illustration on the following page), change the Page title to Simple Trace Example. Change Page Layout from GridLayout to FlowLayout. (If you use GridLayout, trace output and rendered page output can end up overlapping. Using FlowLayout prevents this.) Click OK.
Add a label to the page by dragging a label from the toolbox onto the form. In FlowLayout, the label will move to the upper left of the form no matter where you place it. Change the Text property to Trace is enabled for this page.
Click in an empty area of the page to select the DOCUMENT object, locate the trace property in the Properties window, and set its value to True.
Save SimpleTrace.aspx and the project, and then build the project.
Browse SimpleTrace.aspx using Microsoft Internet Explorer. The resulting screen should look similar to the following illustration:
The trace output includes such information as the contents of the cookies, forms, and querystring collections. Therefore, page-level tracing using the Trace attribute of the @ Page directive should be restricted to non-production systems because the output is visible to any client requesting that page. Although you can use one of the configuration options detailed in the next section to configure ASP.NET to provide page-level trace output only for requests from the local system, you’re best off sticking to application-level tracing on publicly available applications.
Tracing has an impact on application performance, and the information that it provides could potentially be used by malicious users to attack your application, so for both performance and security reasons you should use tracing only in development environments; disable tracing before deploying an application to a production (public-facing) environment.
In addition to providing trace output at the page level, ASP.NET can be configured to log trace output for a specified number of requests for later review. The primary advantages of this approach are that it allows you to enable tracing for an entire site at once, and that when configured properly it hides trace output from users of the page, making its use on production or customer-facing systems less likely to allow malicious users access to too much information.
You enable application-level tracing by adding the <trace> configuration element to the Web.config file for the application and then setting its attributes to the desired values. The following example demonstrates modifying the <trace> element to enable application-level tracing and tells ASP.NET to log up to 40 requests. (Logged requests must be cleared manually when the request limit has been reached.) Appendix B details the attributes for the <trace> section.
In Visual Studio, open the Chapter_14 project created in the previous example.
Edit the Web.Config file by double-clicking on it in the Solution Explorer. Then, from the Edit menu, select Find And Replace, and then select Find. In the Find What text box, type <trace and then click Find Next. This will move your cursor to the beginning of the <trace> section. Change the <trace> element so that it looks like this:
Save the changes to Web.config.
To allow access to the logged trace output, ASP.NET provides an HttpHandler that is mapped to a special URL called trace.axd. Appending trace.axd to the base URL for the application will display the list of currently available traces, as shown in the following illustration. Clicking View Details for a particular trace displays its output. Clicking Clear Current Trace clears all current entries from the trace log and allows more requests to be logged.
At one time or another, most developers who have ever tried debugging a classic ASP application have resorted to using Response.Write for outputting the value of variables to the page, or for placing flags within code to determine where the code is breaking by seeing how much of the page gets executed before execution is halted. While this was (and still is) a useful technique for debugging, it is useful only for development machines that are not accessible by users—many of the aforementioned developers have gotten calls from their supervisors when they forgot to take the Response.Write statements out before migrating a page to a production server.
The page-level setting for trace functionality will override the setting in Web.config. So even if you have tracing enabled in Web.config, setting the trace attribute of the @ Page directive to False will still disable tracing for that page. Likewise, even if tracing is disabled at the application level in Web.config (or at the machine level in machine.config), setting the page-level trace attribute to True will still enable tracing for that page. For this reason, if you use page-level tracing you should always double-check your pages before publishing them to a public server to ensure that the trace attribute for each page has been removed or set to False.
ASP.NET’s trace functionality minimizes this problem by allowing developers to write to the trace output instead of writing to the page output. Assuming that page-level trace output has not been enabled, this prevents end-users from seeing the trace statements written by the developer.
As noted earlier, enabling tracing for a page or for an application does carry some performance overhead. Even though the ASP.NET trace functionality allows you to leave tracing enabled without trace output being viewed by end-users, when performance is important, it is a good idea to disable tracing for an application at both the page and application level.
The trace output is exposed to developers via the TraceContext class, which is available from the Page.Trace property (which can be referred to within a page simply as Trace, since the Page object is assumed). There are two methods for writing to the trace output, Trace.Write and Trace.Warn.
To keep developers from wasting time attempting to write to the trace output when tracing is not enabled, the TraceContext class exposes a Boolean property called IsEnabled, which contains the current status of tracing for the page. This is especially helpful if you are performing expensive processing or database lookups as a part of your trace logging.
The Trace.Write method of the TraceContext class is overloaded, and you can call it in one of the following three ways:
Trace.Write(string message) Trace.Write(string category, string message) Trace.Write(string category, string message, Exception errorInfo);
category is a string containing a description of the message (variable, statement, or whatever the developer wants as a category).
errorInfo is an exception object, which allows exceptions to be logged to the trace output.
The category and errorInfo parameters allow developers to set up sophisticated application-wide tracing by defining specific categories of logged information and using them consistently across an application.
The following example shows how to create a page that tests if tracing is enabled for the page, and then writes a simple message to the trace output.
In Visual Studio, open the Chapter_14 project used in the previous examples. Add a new page by right-clicking on the root of the project in the Solution Explorer, selecting Add, and then Add Web Form. Type the name of the form as TraceWrite.aspx.
Right-click anywhere on the page, and select Properties from the context menu. In the resulting dialog box, change Page Layout from GridLayout to FlowLayout, and then click OK.
Add a label to the page.
Change to HTML mode by clicking the HTML button on the bottom of the design window. Add Trace=“true” to the @ Page directive:
<%@ Page Language="c#" AutoEventWireup="false"  Codebehind="TraceWrite.aspx.cs Inherits="Chapter_14.TraceWrite" Trace="true" %>
Change to the code view by pressing F7. Scroll down to the Page_Load event handler and add the following code:
if (Trace.IsEnabled Label1.Text = "Writing 'Hello from Page!' to Trace Log..." Trace.Write("Hello from Page!") }
Save TraceWrite.aspx, its code-behind file, and the project, and then build the project.
Browse TraceWrite.aspx using Internet Explorer. The resulting screen should look similar to the illustration on the nexy page. (Notice the hello message on the first line under the Trace Information heading.)
Another method offered by the TraceContext class for writing to the trace output is Trace.Warn. The primary difference between the two methods is that output written with Trace.Warn appears in the trace output as red text, making it ideal for highlighting important entries such as exceptions.
The trace output for a page contains a great deal of information. Table 14-1 lists the sections of the trace output and describes the information contained in each.
Displays request-specific information such as session ID, request type, request status code, and encoding.
Displays messages relating to stages of page processing, as well as execution times for these stages.
Displays a tree representation of all controls on the page, including LiteralControls for static HTML text within the source file. Also displays the render size and ViewState size of each control.
Displays the name, content, and size of all cookies sent as part of the request.
Displays a list of all HTTP headers sent as a part of the request.
Displays a list of the names and values of all form fields sent as part of a POST request.
Displays a list of the names and values of all querystring values sent as part of a GET request.
Displays a list of the server variables for the request.