Walkthrough: Using Tracing in Visual Web Developer to Help Find Web Page Errors
There are several ways to find errors in an ASP.NET Web page. This includes using the debugger and tracing. Tracing displays messages about the actions that occur during page processing, and can include information that you choose to display. Tracing also gives you information about the data that is being exchanged by the server and browser. The data exchange includes control details, server variables, user name, cookies, and so on. This walkthrough illustrates how to use tracing.
Tracing is useful when it is impractical or not good to use the debugger. For example, the debugger might not be available because your pages are on a remote server. Tracing also makes it easier for you to view information, such as the HTTP header, that is not explicitly available in the debugger. For information about debugging, see Walkthrough: Debugging Web Pages in Visual Web Developer.
In this walkthrough, you will work with tracing. You will create a Web page that prompts the user for a name, and then displays the name. The page also stores the name in a cookie so that the user does not have to re-enter the name.
Note
In a production application, a better technique for storing personal information is to use ASP.NET profile properties. For detailed information, see ASP.NET Profile Properties Overview. However, using a cookie in this walkthrough simplifies the code, which lets you focus on tracing.
In this walkthrough, you will deliberately introduce some errors. Then, you will use tracing to see the status of page processing, which will help you diagnose the errors.
Tasks illustrated in this walkthrough include the following:
Enabling tracing for a single page.
Reading trace output.
Displaying custom trace information.
Viewing tracing information in a separate trace window.
Creating custom trace output.
Prerequisites
In order to complete this walkthrough, you will need the following:
Microsoft Visual Web Developer Web development tool.
The .NET Framework.
This walkthrough assumes that you have a general understanding of working in Visual Web Developer. For an introduction to Visual Web Developer, see Walkthrough: Creating a Basic Web Page in Visual Web Developer.
Creating the Web Site
If you have already created a Web site in Visual Web Developer by completing Walkthrough: Creating a Basic Web Page in Visual Web Developer, you can use that Web site and go to "Adding Controls," later in this walkthrough. Otherwise, create a new Web site and page by following these steps.
Note
This walkthrough assumes that you are working with an ASP.NET page that uses a code-behind file for its code.
To create a file system Web site
Open Visual Web Developer.
On the File menu, click NewWeb Site.
The New Web Site dialog box appears.
Under Visual Studio installed templates, click ASP.NET Web Site.
In the right-most Location box, enter the name of the folder where you want to keep the pages of the Web site.
For example, type the folder name C:\WebSites.
In the Language list, click the programming language that you prefer to work in.
Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Adding a Page
If you are using an existing Web site, you can create a new page. If you already have a page you can use for this walkthrough, go to the next section.
To create a new page
In Solution Explorer, right-click the Web site name, and then click Add New Item.
In the Add New Item <Path> dialog box, under Visual Studio installed templates, click Web Form.
In the Name box, type FirstWebPage.aspx.
In the Language list, click the programming language that you prefer to work in.
If you are creating a page in Visual Basic or C#, select the Place code in separate file check box.
Click Add.
Adding Controls
After you create a Web site and open a page, the next step is to add some controls to the page.
To add controls and code for debugging
Switch to Design view, and then from the Standard group in the Toolbox, drag the following controls onto the page and set their properties as indicated in the table.
Control
Properties
TextBox
ID: textName
Text: (empty)
Button
ID: buttonDisplayName
Text: Submit
Label
ID: labelName
Text: (empty)
Note
For this walkthrough, the layout of the page is not important.
Adding Code
The next step is to add code to the page. When the page is running correctly, the user can enter a name, and then click Submit, which displays the name in the Label control. If the user closes the browser, and then returns to the page, the page will already have the user's name, because it is stored in a cookie.
The following steps guide you through adding the code. Neither the procedure here for adding the code nor the code itself is completely correct. This is deliberate, so that you will be able to use tracing to find the errors on the page.
To add code
In Solution Explorer, right-click FirstWebPage.aspx, and then click View Code.
Note
Do not double-click the button in Design view.
Inside the class definition, enter the following code.
Note
If you are working with a single-file page, paste the code into the <script> block.
Protected Sub buttonDisplayName_Click(ByVal sender As Object, _ ByVal e As EventArgs) labelName.Text = Server.HtmlEncode(textName.Text) Response.Cookies("username").Value = labelName.Text End Sub
protected void buttonDisplayName_Click(Object sender, EventArgs e) { labelName.Text = Server.HtmlEncode(textName.Text); Response.Cookies["username"].Value = labelName.Text; }
The code performs the following tasks:
It reads the value of the TextBox control, and then displays the value in the Label control. As part of this logic, the code calls the HtmlEncode method, which turns potentially executable HTML characters, such as right angle bracket (<), into their display equivalents. This is a security measure to prevent scripting exploits. For detailed information, see Script Exploits.
It creates a cookie named username that stores the value that the user has entered.
Add the following method, either above or under the Click handler that you created in the preceding step.
Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) _ Handles Me.Load If Not Request.Cookies("username") Is Nothing Then labelName.Text = Request.Cookies("username").Value End If End Sub
void Page_Load(Object sender, EventArgs e) { if(Request.Cookies["username"] != null) { labelName.Text = Request.Cookies["username"].Value; } }
Testing the Page
You can now test the page. If you have followed the deliberately incomplete steps from the procedure in the preceding section, the page will not yet work as designed.
To test the page
Press CTRL+F5 to run the page.
When the page appears, in the text box, type your name, and then click Submit.
Notice that even though clicking Submit caused the page to be posted back to the server, your name is not displayed.
Close the browser.
You can now use tracing to help you find the errors in the page.
Using Tracing to Find Errors
In this section, you will enable tracing for the page. You will examine tracing output, and then include custom tracing messages that will help you pinpoint page errors.
To enable tracing for the page
Open the FirstWebPage.aspx page and switch to Design view.
In Properties, in the list, click DOCUMENT.
This displays properties for the page.
Set Trace to true.
The trace setting is actually made as part of the @ Page directive. You can see this by switching to Source view and looking at the first line in the page. The @ Page directive will look similar to the following:
<%@ Page language="VB" Trace="true" %>
<%@ Page language="C#" Trace="true" %>
Press CTRL+F5 to run the page.
The page is displayed in the browser. At the top, you see the text and controls that you put on the page. Under the text and controls, you see the tracing output, which displays many details about page processing and includes the following information:
The sequence of page events that occurred while the page ran.
The types, names, and sizes of the controls on the page.
The cookies and their contents.
The server variables, which is a collection of all information that the browser sends to the server.
Notice that under Request Details (the first block of tracing information), the Request Type is GET. This indicates that it is the first time the page has run; that is, it is not a postback.
In the box, type a name, and then click Submit.
Request Type is now POST. This indicates that this is a postback for the page. Clicking Submit does not cause the name to be displayed.
Close the browser.
You can use custom tracing output to help you follow the logic of the page.
To add custom trace output
Add the following highlighted lines to the buttonDisplayName_Click handler that you created in "Adding Code," earlier in this walkthrough:
Protected Sub buttonDisplayName_Click(ByVal sender As Object, _ ByVal e As EventArgs) Trace.Warn("debugging", "Start buttonDisplayName Click handler") labelName.Text = Server.HtmlEncode(textName.Text) Response.Cookies("username").Value = labelName.Text Trace.Warn("debugging", "End buttonDisplayName Click handler") End Sub
protected void buttonDisplayName_Click(Object sender, EventArgs e) { Trace.Warn("debugging", "Start buttonDisplayName Click handler"); labelName.Text = Server.HtmlEncode(textName.Text); Response.Cookies["username"].Value = labelName.Text; Trace.Warn("debugging", "End buttonDisplayName Click handler"); }
The Warn method adds your custom messages to the trace output. Although the TraceContext class also provides a Write method, the Warn method is more useful because the output is displayed in color.
Press CTRL+F5 to run the page.
Click Submit.
When you examine the trace output, you will notice that the output contains no red text. You can conclude from this that the Click handler for Submit is not being called.
The most common reason that a handler is not called is that the control has not been correctly bound to the event handler. That is true in this case — although you added the event-handling code, you did not bind the Click event for Submit to the handler. Typically, Visual Web Developer binds the event to the control when you double-click the control in Design view.
Close the browser.
In Source view, add the following highlighted attribute to the <asp:button> element:
<asp:button id="buttonDisplayName" runat="server" text="Submit" onclick="buttonDisplayName_Click" />
Press CTRL+F5 to run the page.
In the box, enter a name, and then click Submit.
Your custom trace output appears in red in the Trace Information section, which lists the processing steps that the page goes through.
The output in this section shows the messages in the order that the messages occurred during page processing. You added your messages in the Click event handler, which is processed between the Begin Raise PostBackEvent and End Raise PostBackEvent lines. Including custom messages lets you know not only that your handler was called but also where in the page processing cycle the code is executed.
The category next to your custom messages is debugging, which is the category that you specified when you called the Warn method. You can specify any category you want, and if it is useful, you can set the TraceMode property for the page to the SortByCategory value to make it easier to find the category in the trace output.
Additionally, notice that the name that you entered is displayed in the label.
Now that the Click handler for Submit is working correctly, you can test the rest of the code in the page, including the cookie.
To test the cookie
Close the browser.
Press CTRL+F5 to run the page.
The behavior that you expect is for the name that you have entered to appear automatically in the label, because the Click handler for Submit sets a cookie and the Page_Load handler reads it during the next postback. However, the label is never set from the cookie.
If you are writing a cookie but it is not being persisted, the error is frequently that you are not setting an explicit expiration date for the cookie. A cookie without an expiration date is a session cookie. A session cookie is maintained in server memory only until the browser is closed. In other words, the cookie is not written to the browser. In the following steps you will correct this problem.
Close the browser.
In Source view, add the following highlighted line to the buttonDisplayName_Click handler:
Protected Sub buttonDisplayName_Click(ByVal sender As Object, _ ByVal e As EventArgs) Trace.Warn("debugging", "Start buttonDisplayName Click handler") labelName.Text = Server.HtmlEncode(textName.Text) Response.Cookies("username").Value = labelName.Text Response.Cookies("username").Expires= _ DateTime.Now.AddMinutes(30) Trace.Warn("debugging", "End buttonDisplayName Click handler") End Sub
protected void buttonDisplayName_Click(Object sender, EventArgs e) { Trace.Warn("debugging", "Start buttonDisplayName Click handler"); labelName.Text = Server.HtmlEncode(textName.Text); Response.Cookies["username"].Value = labelName.Text; Response.Cookies["username"].Expires= DateTime.Now.AddMinutes(30); Trace.Warn("debugging", "End buttonDisplayName Click handler"); }
The new line explicitly sets the cookie to expire in 30 minutes.
Press CTRL+F5 to run the page.
In the box, enter a name, and then click Submit.
The name is displayed in the browser. In the Response Cookies Collection trace output, you can see that the cookie is being set.
Close the browser.
Press CTRL+F5 to run the page.
This time, the name is automatically filled in. In the Request Cookies Collection trace output, now you can see that the browser is passing the cookie to your page.
Displaying Trace Information in a Trace Viewer Window
Setting the page to display tracing output is useful when you are working with only a single page. However, if you are working with many pages in your application, it can be inconvenient to set tracing on and off for each page. Moreover, displaying tracing output information in the page as the page is running can be distracting. Regardless, you would not want the page to show tracing output to users of your application.
You can configure tracing not just at the page level but also at the application level. Setting application-level tracing has two advantages:
You can enable and disable tracing for all pages at the same time.
You can display tracing output in a separate browser window — the trace viewer — instead of displaying it as part of the output for the page.
When application-level tracing is enabled, ASP.NET maintains trace output from all pages in a cache. You can set options to specify how many pages of trace output to cache and whether you want to keep the most recent or the oldest entries. You can then invoke the trace viewer in the browser and select the trace output to examine.
In this section of the walkthrough, you will enable application-level tracing and use the trace viewer to examine the trace output.
To enable application-level tracing
Switch to Source view, and then in the @ Page directive at the top of the page, delete Trace="true".
Note
Remove the attribute; do not just set it to false. Otherwise, the subsequent steps in this walkthrough will not work correctly.
On the Website menu, click ASP.NET Configuration.
The ASP.NET Web Site Administration tool appears.
Click Application Configuration.
Under Debugging and Tracing, click Configure debugging and tracing, and then select the Capture tracing information check box.
This setting enables application-level tracing.
For this walkthrough, you can leave the remaining settings at their default values. ASP.NET will cache up to 10 entries of trace output (either 10 postbacks of a single page or fewer postbacks each for multiple pages), and cache the most recent entries.
Close the ASP.NET Web Site Administration Tool.
Remove the Trace attribute for the page.
Now you can run the original page and work with it in the way that a user will see it. However, at the same time, you can view the tracing output when you have to in a separate browser window.
To view tracing output in a separate browser window
Press CTRL+F5 to run the page.
Notice that the page no longer displays trace output. The page looks the way a user would see it.
In the box, enter a name, and then click Submit to confirm that the page works correctly.
Open a new browser window.
In the browser, in the Address box, type the URL of your site, substituting trace.axd for the name of the page that you are working with.
For example, if the URL for the page is the following:
https://localhost:8081/WebSite/Default.aspx
Type the following:
https://localhost:8081/WebSite/trace.axd
Note
A quick way to perform this task it to copy the URL from the original page, and then change just the page name.
The browser displays the current cache of trace entries.
Click View Details for the last (most recent) trace entry.
The browser displays trace output that is similar to what you saw earlier in the walkthrough, except that it is not appended to the end of the page.
Switch to the browser instance that contains the original page.
In the box, type a new name, and then click Submit.
This action generates a new trace log entry.
Switch to the browser instance that contains the information.
In the browser, click Back to return to the list trace entries, and then click Refresh to update the list of entries.
A new entry appears to represent the trace output that you created in step 7.
Close both browser windows.
Creating Custom Trace Output
As you have seen, trace output contains lots of information, sometimes more than you need. For example, you might want to limit trace output to only the trace output that you create yourself. Tracing lets you read the contents of the trace buffer and selectively display the information that you need.
To create custom trace output, handle the TraceFinished event for the Trace object. In the event handler, you can read the trace buffer.
To create custom trace output
In the page that you have been working with, add the following highlighted code to the Page_Load handler:
Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) _ Handles Me.Load If Not Request.Cookies("username") Is Nothing Then labelName.Text = Request.Cookies("username").Value End If AddHandler Trace.TraceFinished, AddressOf Me.TraceFinished If IsPostBack Then Trace.Write("debugging", "Page_Load (Postback)") Else Trace.Write("debugging", "Page_Load (First Time)") End If End Sub
void Page_Load(object sender, EventArgs e) { if(Request.Cookies["username"].Value != null) { labelName.Text = Request.Cookies["username"].Value; } Trace.TraceFinished += new TraceContextEventHandler(this.TraceFinished); if (Page.IsPostBack) { Trace.Write("debugging", "Page load (postback)"); } else { Trace.Write("debugging", "Page load (first time)"); } }
The code performs the following two functions:
It binds a method in the page to the TraceFinished event for the Trace object, which is raised when the trace output is complete for the page. You will write the method in the next step.
It writes some trace information.
Create the following method to handle the TraceFinished event:
Sub TraceFinished(ByVal sender As Object, _ ByVal e As TraceContextEventArgs) Dim traceRecord As TraceContextRecord For Each traceRecord In e.TraceRecords If traceRecord.Category = "debugging" Then Response.Write("<BR>" & traceRecord.Message) End If Next End Sub
void TraceFinished(object sender, TraceContextEventArgs e) { foreach(TraceContextRecord traceRecord in e.TraceRecords) { if(traceRecord.Category == "debugging") { Response.Write("<br>" + traceRecord.Message); } } }
This code is executed when the trace output is finished. The trace buffer is available as a collection in the TraceRecords property of the e event argument. The code loops through the collection and displays the value of any trace record that has debugging as its category; in this walkthrough, you have set the category of all custom trace output to debugging.
At this point in the walkthrough, the Web site is configured to enable tracing for all pages, but trace output is directed to a trace viewer instead of to the page. If the Web site is configured differently — for example, if trace output is displayed in the page — follow the steps in the procedure named To enable application-level tracing, in "Displaying Trace Information in a Trace Viewer Window," earlier in the walkthrough.
You can now test the custom trace output.
To test custom trace output
Press CTRL+F5 to run the page.
When the page is displayed in the browser, the message Page load (first time) appear, but no other trace output appears.
Click Submit.
The messages Page load (postback), Start buttonDisplayName Click handler, and End buttonDisplayName Click handler appear.
Note
If you exceed the number of cached request that is specified in the requestLimit attribute of the trace Element (ASP.NET Settings Schema), the TraceFinished event will not be raised and you will not see the messages on the Web page.
Next Steps
This walkthrough has illustrated the basic functionality of tracing in ASP.NET. Besides using tracing to display information within the Web application, you can integrate ASP.NET tracing with other instrumentation. For example, you might want to do the following:
Display system diagnostics messages as part of your ASP.NET tracing.
For more information, see Walkthrough: Integrating ASP.NET Tracing with System.Diagnostics Tracing.
Send ASP.NET trace information to the .NET Framework tracing mechanism, which uses classes in the System.Diagnostics namespace.
Forward information to registered instrumentation listeners as part of the health monitoring for the Web site.
For more information about registering listeners, see <listeners> Element for <trace>.