10.3.1 Problem You want to identify problems only when an exception occurs. 10.3.2 Solution Dynamically turn on page-level tracing from within the Catch block of your exception handler and write to the trace log. In the code-behind class for the page, use the .NET language of your choice to: -
Set Page.Trace.IsEnabled = true in the Catch block of your exception handler. -
Write to the trace log by using a Trace.Write of the form Trace.Write("Exception", " Message ", exc ) . Figure 10-3 shows the appearance of some exception information in the trace sequence. Example 10-4 through Example 10-6 show the .aspx file and VB and C# code-behind files for the application that produces this result. Figure 10-3. Exception information in the trace sequence 10.3.3 Discussion ASP.NET processes and displays trace statements only when tracing is enabled. However, what if you don't want to see the trace log all the time, but only when an exception occurs? The answer is to turn tracing on dynamically for the page. You can then write the exception information to the trace log and debug the problem from there. Our example that illustrates this solution is rather primitive, in that it simply forces an exception. While this is not something you would normally do in production code, it does allow us to show the infrastructure needed to control tracing at runtime. When the exception occurs, the exception handler enables the trace output by setting Trace.IsEnabled to true . In order for the exception information to appear in the trace sequence, you must use a Trace.Write of the form Trace.Write("Exception" , " Message ", exc ) , where exc is the Exception object defined in the catch statement. Additionally, the code limits who sees the trace sequence, something you might want to consider if you are loathe to show tracing information to remote users when an exception occurs. Before activating tracing, the program checks to see whether the application is being run from the local machine (i.e., the browser making the request is on the machine serving the request). It does so by using the Request object to get the local IP address from the server variables . It then compares this local address to the loopback address , a special IP number (127.0.0.1) that is designated for the software loopback interface of a machine. If it is not equal to the loopback address, a further comparison is then made to see if the local IP address from the server variables is the same as the local IP address that accompanied the request. The results of the comparison are then used to determine whether to enable tracing and display the exception information in the trace sequence. | The URLs for page requests on the local machine can be in the form http://localhost/site/page or http://[server]/site/page (where [server] is the local server name), so it is necessary to check for the loopback IP address as well as the actual IP address. If the page were requested using the server name in the URL, it would not be detected as a local request if the second check were not performed. | | Example 10-4. Pinpointing the cause of an exception (.aspx) <%@ Page Language="vb" AutoEventWireup="false" Codebehind="CH10TestDynamicPageTracingVB.aspx.vb" Inherits="ASPNetCookbook.VBExamples.CH10TestDynamicPageTracingVB"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title>Test Dynamic Page Tracing</title> <link rel="stylesheet" href="css/ASPNetCookbook.css"> </head> <body leftmargin="0" marginheight="0" marginwidth="0" topmargin="0"> <form id="frmTracing" method="post" runat="server"> <table width="100%" cellpadding="0" cellspacing="0" border="0"> <tr> <td align="center"> <img src="images/ASPNETCookbookHeading_blue.gif"> </td> </tr> <tr> <td class="dividerLine"> <img src="images/spacer.gif" height="6" border="0"></td> </tr> </table> <table width="90%" align="center" border="0"> <tr> <td><img src="images/spacer.gif" height="10" border="0"></td> </tr> <tr> <td align="center" class="PageHeading"> Pinpointing the Cause of an Exception (VB) </td> </tr> <tr> <td><img src="images/spacer.gif" height="10" border="0"></td> </tr> <tr> <td align="center" class="LabelText"> <input id="chkOnlyLocal" runat="server" type="checkbox"> Show Only If Request Is Local </td> </tr> <tr> <td><img src="images/spacer.gif" height="10" border="0"></td> </tr> <tr> <td align="center"> <input id="btnCauseException" runat="server" type="button" value="Cause Exception" /> </td> </tr> </table> </form> </body> </html> Example 10-5. Code-behind for pinpointing the cause of an exception (.vb) Option Explicit On Option Strict On '----------------------------------------------------------------------------- ' ' Module Name: CH10TestDynamicPageTracingVB.aspx.vb ' ' Description: This class provides the code behind for ' CH10TestDynamicPageTracingVB ' '******************************************************************************* Imports System Imports System.Collections Imports System.Web Imports System.Web.UI.HtmlControls Imports System.Web.UI.WebControls Imports System.Diagnostics Namespace ASPNetCookbook.VBExamples Public Class CH10TestDynamicPageTracingVB Inherits System.Web.UI.Page 'controls on the form Protected chkOnlyLocal As HtmlInputCheckBox Protected WithEvents btnCauseException As HtmlInputButton '************************************************************************* ' ' ROUTINE: Page_Load ' ' DESCRIPTION: This routine provides the event handler for the page load ' event. It is responsible for initializing the controls on ' the the page. '------------------------------------------------------------------------- Private Sub Page_Load(ByVal Sender As Object, _ ByVal E As EventArgs) Handles MyBase.Load 'Put user code to initialize the page here End Sub 'Page_Load '************************************************************************* ' ' ROUTINE: btnCauseException_ServerClick ' ' DESCRIPTION: This routine provides the event handler for the cause ' exception button click event. It is responsible for ' causing an exception to demonstrate dynamic tracing '------------------------------------------------------------------------- Private Sub btnCauseException_ServerClick(ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles btnCauseException.ServerClick Dim list As ArrayList Try 'force an exception by accessing the list without creating it first list.Add(0) Catch exc As Exception 'enable tracing and output the exception information If ((Not chkOnlyLocal.Checked) OrElse _ ((chkOnlyLocal.Checked) And (requestIsFromLocalMachine( )))) Then Trace.IsEnabled = True Trace.Write("Exception", _ "Demonstration of dynamic tracing", _ exc) End If End Try End Sub 'btnCauseException_ServerClick '************************************************************************* ' ' ROUTINE: requestIsFromLocalMachine ' ' DESCRIPTION: This routine checks to see if the page request came from ' the local machine. ' ' NOTE: Since requests on a local machine can be in the form ' http://localhost/site/page or http://server/site/page, ' two checks are required. The first is for the localhost ' loopback IP address (127.0.0.1) and the second is for the actual ' IP address of the requestor. '------------------------------------------------------------------------- Private Function requestIsFromLocalMachine( ) As Boolean Dim isLocal As Boolean Dim localAddress As String ' Is browser fielding request from localhost? isLocal = Request.UserHostAddress.Equals("127.0.0.1") If (Not isLocal) Then ' Get local IP address from server variables localAddress = Request.ServerVariables.Get("LOCAL_ADDR") ' Compare local IP with IP address that accompanied request isLocal = Request.UserHostAddress.Equals(localAddress) End If Return (isLocal) End Function 'IsRequestFromLocalMachine End Class 'CH10TestDynamicPageTracingVB End Namespace Example 10-6. Code-behind for pinpointing the cause of an exception (.cs) //---------------------------------------------------------------------------- // // Module Name: CH10TestDynamicPageTracingCS.aspx.cs // // Description: This class provides the code behind for // CH10TestDynamicPageTracingCS // //**************************************************************************** using System; using System.Collections; using System.Web; using System.Web.UI.WebControls; using System.Web.UI.HtmlControls; namespace ASPNetCookbook.CSExamples { public class CH10TestDynamicPageTracingCS : System.Web.UI.Page { // controls on form protected HtmlInputCheckBox chkOnlyLocal; protected HtmlInputButton btnCauseException; //************************************************************************ // // ROUTINE: Page_Load // // DESCRIPTION: This routine provides the event handler for the page // load event. It is responsible for initializing the // controls on the page. //------------------------------------------------------------------------ private void Page_Load(object sender, System.EventArgs e) { // wire the "cause exception" button event handler this.btnCauseException.ServerClick += new System.EventHandler(this.btnCauseException_ServerClick); } // Page_Load //************************************************************************ // // ROUTINE: btnCauseException_ServerClick // // DESCRIPTION: This routine provides the event handler for the cause // exception button click event. It is responsible for // causing an exception to demonstrate dynamic tracing //------------------------------------------------------------------------ private void btnCauseException_ServerClick(object sender, System.EventArgs e) { ArrayList list = null; try { // force an exception by accessing the list without creating it first list.Add(0); } // try catch (Exception exc) { // enable tracing and output the exception information if ((!chkOnlyLocal.Checked) ((chkOnlyLocal.Checked) && (requestIsFromLocalMachine( )))) { Trace.IsEnabled = true; Trace.Write("Exception", "Demonstration of dynamic tracing", exc); } } // catch } // btnCauseException_ServerClick //************************************************************************ // // ROUTINE: requestIsFromLocalMachine // // DESCRIPTION: This routine checks to see if the page request came // from the local machine. // // NOTE: Since requests on a local machine can be in the form // http://localhost/site/page or http://server/site/page, // two checks are required. The first is for the localhost // loopback IP address (127.0.0.1) and the second is for the // actual IP address of the requestor. //------------------------------------------------------------------------ private Boolean requestIsFromLocalMachine( ) { Boolean isLocal; string localAddress; // Is browser fielding request from localhost? isLocal = Request.UserHostAddress.Equals("127.0.0.1"); if (!isLocal) { // Get local IP address from server variables localAddress = Request.ServerVariables.Get("LOCAL_ADDR"); // Compare local IP with IP address that accompanied request isLocal = Request.UserHostAddress.Equals(localAddress); } return (isLocal); } // IsRequestFromLocalMachine } // CH10TestDynamicPageTracingCS } |