Because you intend to use a business component in both web and non-web applications, you want to enable tracing within the component without having to reference its current HTTP context.
Create your own trace listener
that inherits
from the TraceListener
class, overrides the
Write
and WriteLine
methods,
and references the current HTTP context to output the message. A
sample trace listener we’ve written to illustrate
this solution is shown in Example 10-12 (VB) and Example 10-13 (C#).
Next, modify web.config
, as
shown in Example 10-14, to add the listener to the
Listeners
collection and make it available to your
application.
In your non-web-specific components, add plain-vanilla
Trace.Write
statements to output any desired
information to the trace log, as shown in our sample component in
Example 10-15 (VB) and Example 10-16
(C#).
A web form and the associated VB and C# code-behind we’ve written to test the tracing in our non-web-specific component are shown in Example 10-17 through Example 10-19.
The .NET Framework uses the
concept of trace
listeners in its handling of trace messages. By default,
the TraceListeners
collection contains a single
listener (DefaultTraceListener
) when you enable
tracing. Additional listeners can be added via the
web.config
file or programmatically. When a
Trace.Write
is executed, all listeners in the
TraceListeners
collection receive and process the
message. It is this mechanism that allows you to add trace statements
to your components without the need to add a reference to the
System.Web
assembly.
The custom TraceListener
in our example overrides
the Write
and WriteLine
methods
to write the passed message to the current HTTP context in the same
manner we did in Recipe 10.4. The
custom TraceListener
is made available by adding
the entry to web.config shown in
Example 10-14.
When adding a TraceListener
to your
web.config
file, it is very important that you
specify the type correctly. The type attribute must be specified as
shown here.
type="namespace
,assembly
"
The namespace must be the fully qualified namespace of the custom
TraceListener
. The assembly must be the name of
the assembly into which the custom TraceListener
is compiled.
Our example business service class is nearly identical to the one we used in Recipe 10.4. Here are the differences:
The imports (or using) statement at the beginning of the class is
changed from System.Web
to
System.Diagnostics
. (The
System.Diagnostics
namespace provides the abstract
base class for the trace listeners.)
The HttpContext.Current.Trace.Write
statements are
changed to Trace.Write
.
Our test web form, like our example business service class, is also nearly identical to our test web form used in Recipe 10.4. The only difference is that it uses our example business service class.
There are two advantages to the approach this recipe takes over the previous recipe:
You can use plain-vanilla Trace.Writes
in your
component; they don’t have to reference the current
HTTP context, thus maintaining the component’s
compatibility for non-web uses.
You can turn tracing on and off via a configuration file.
Example 10-12. The Listener subclass (.vb)
Option Explicit On Option Strict On '----------------------------------------------------------------------------- ' ' Module Name: CH10WebListenerVB.vb ' ' Description: This class provides a trace listener that outputs messages ' that are shown in trace data of an ASPX page. ' '***************************************************************************** Imports System Imports System.Diagnostics Imports System.Web Imports System.IO Namespace ASPNetCookbook.VBExamples Public Class CH10WebListenerVB Inherits TraceListener '************************************************************************* ' ' ROUTINE: Write ' ' DESCRIPTION: This routine writes the passed message to the ' HttpContext Trace object '-------------------------------------------------------------------------Public Overloads Overrides Sub Write(ByVal message As String)
HttpContext.Current.Trace.Write(message)
End Sub 'Write
'************************************************************************* ' ' ROUTINE: Write ' ' DESCRIPTION: This routine writes the passed message to the ' HttpContext Trace object '-------------------------------------------------------------------------Public Overloads Overrides Sub Write(ByVal category As String, _
ByVal message As String)
HttpContext.Current.Trace.Write(category, _
message)
End Sub 'Write
'************************************************************************* ' ' ROUTINE: WriteLine ' ' DESCRIPTION: This routine writes the passed message to the ' HttpContext Trace object with a CR/LF '-------------------------------------------------------------------------Public Overloads Overrides Sub WriteLine(ByVal message As String)
HttpContext.Current.Trace.Write(message)
End Sub 'WriteLine
'************************************************************************* ' ' ROUTINE: Write ' ' DESCRIPTION: This routine writes the passed message to the ' HttpContext Trace object '-------------------------------------------------------------------------Public Overloads Overrides Sub WriteLine(ByVal category As String, _
ByVal message As String)
HttpContext.Current.Trace.Write(category, _
message)
End Sub 'WriteLine
End Class 'CH10WebListenerVB End Namespace
Example 10-13. The Listener subclass (.cs)
//---------------------------------------------------------------------------- // // Module Name: CH10WebListenerCS.cs // // Description: This class provides a trace listener that outputs messages // that are shown in trace data of an ASPX page. // //**************************************************************************** using System; using System.Diagnostics; using System.Web; namespace ASPNetCookbook.CSExamples { public class CH10WebListenerCS : TraceListener { //************************************************************************ // // ROUTINE: Write // // DESCRIPTION: This routine writes the passed message to the // HttpContext Trace object //------------------------------------------------------------------------public override void Write(String message)
{
HttpContext.Current.Trace.Write(message);
} // Write
//************************************************************************ // // ROUTINE: Write // // DESCRIPTION: This routine writes the passed message to the // HttpContext Trace object //------------------------------------------------------------------------public override void Write(String category,
String message)
{
HttpContext.Current.Trace.Write(category,
message);
} // Write
//************************************************************************ // // ROUTINE: WriteLine // // DESCRIPTION: This routine writes the passed message to the // HttpContext Trace object //------------------------------------------------------------------------public override void WriteLine(String message)
{
HttpContext.Current.Trace.Write(message);
} // WriteLine
//************************************************************************ // // ROUTINE: WriteLine // // DESCRIPTION: This routine writes the passed message to the // HttpContext Trace object //------------------------------------------------------------------------public override void WriteLine(String category,
String message)
{
HttpContext.Current.Trace.Write(category,
message);
} // WriteLine
} // CH10WebListenerCS }
Example 10-14. Web.config settings to add the trace listener
<system.diagnostics> <trace autoflush="true" indentsize="0"> <listeners> <add name="CookbookWebListener" type="ASPNetCookbook.VBExamples.CH10WebListenerVB, VBExamples" /> </listeners> </trace> </system.diagnostics>
Example 10-15. Business service class with plain-vanilla Trace.Writes (.vb)
Option Explicit On Option Strict On '----------------------------------------------------------------------------- ' ' Module Name: CH10TestNonWebComponentVB.vb ' ' Description: This class provides a "non-web" component for demonstrating ' outputting trace information from within a class ' '***************************************************************************** Imports SystemImports System.Diagnostics
Namespace ASPNetCookbook.VBExamples Public Class CH10TestNonWebComponentVB Private mStr As String '************************************************************************* ' ' ROUTINE: theString ' ' DESCRIPTION: This property provides the ability to get/set the ' string in the object '------------------------------------------------------------------------- Public Property theString( ) As String Get Return (mStr) End Get Set(ByVal Value As String) mStr = Value End Set End Property 'theString '************************************************************************* ' ' ROUTINE: addToString ' ' DESCRIPTION: This routine provides the ability to add the passed ' string to the private string in this object one or ' more times. '------------------------------------------------------------------------- Public Sub addToString(ByVal stringToAdd As String, _ ByVal numberOfCopies As Integer) Dim counter As Integer Dim startTime As DateTime Dim elapsedTime As TimeSpan Dim averageTime As Double'output trace message indicating the start of the concatenations
Trace.Write("In Non-web Component", _
"Before performing concatenations")
'concatenation the passed string as requested startTime = DateTime.Now( ) For counter = 1 To numberOfCopies mStr &= stringToAdd Next'output trace message indicating the end of the concatenations
Trace.Write("In Non-web Component", _
"After performing concatenations")
'calculate the elapsed time for the string concatenations elapsedTime = DateTime.Now.Subtract(startTime)'Write average time per concatenation in milliseconds to trace sequence
averageTime = elapsedTime.TotalMilliseconds / numberOfCopies
Trace.Write("In Non-web Component", _
"Aver/concat = " & averageTime.ToString("0.0000"))
End Sub 'addToString '************************************************************************* ' ' ROUTINE: New ' ' DESCRIPTION: This constructor creates the object and initializes the ' variables in the object '------------------------------------------------------------------------- Public Sub New( ) 'initialize string in object mStr = "" End Sub 'New End Class 'CH10TestNonWebComponentVB End Namespace
Example 10-16. Business service class with plain-vanilla Trace.Writes (.cs)
//---------------------------------------------------------------------------- // // Module Name: CH10TestNonWebComponentCS.cs // // Description: This class provides a "non-web" component for demonstrating // outputting trace information from within a class // //**************************************************************************** using System;using System.Diagnostics;
namespace ASPNetCookbook.CSExamples { public class CH10TestNonWebComponentCS { private String mStr; //************************************************************************ // // ROUTINE: theString // // DESCRIPTION: This property provides the ability to get/set the // string in the object //------------------------------------------------------------------------ public String theString { get { return(mStr); } set { mStr = value; } } // theString //************************************************************************ // // ROUTINE: addToString // // DESCRIPTION: This routine provides the ability to add the passed // string to the private string in this object one or // more times. //------------------------------------------------------------------------ public void addToString(String stringToAdd, int numberOfCopies) { int counter; DateTime startTime; TimeSpan elapsedTime; Double averageTime;// output trace message indicating the start of the concatenations
Trace.Write("In Non-web Component",
"Before performing concatenations");
// concatenation the passed string as requested startTime = DateTime.Now; for (counter = 1; counter <numberOfCopies; counter++) { mStr += stringToAdd; }// output trace message indicating the end of the concatenations
Trace.Write("In Non-web Component",
"After performing concatenations");
// calculate the elapsed time for the string concatenations elapsedTime = DateTime.Now.Subtract(startTime);// Write average time per concatenation in milliseconds to trace sequence
averageTime = elapsedTime.TotalMilliseconds / numberOfCopies;
Trace.Write("In Non-web Component",
"Aver/concat = " + averageTime.ToString("0.0000"));
} // addToString //************************************************************************ // // ROUTINE: TestNonWebComponentCS // // DESCRIPTION: This constructor creates the object and initializes the // variables in the object //------------------------------------------------------------------------ public CH10TestNonWebComponentCS( ) { // initialize string in object mStr = ""; } // CH10TestNonWebComponentCS } // CH10TestNonWebComponentCS }
Example 10-17. Code to test tracing in the non-web component (.aspx)
<%@ Page Language="vb" AutoEventWireup="false" Trace="true" Codebehind="CH10TestTraceWithinNonWebComponentVB.aspx.vb" Inherits="ASPNetCookbook.VBExamples.CH10TestTraceWithinNonWebComponentVB"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title>Test Trace Within NonWeb Component</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"> Tracing Within Non-Web Components (VB) </td> </tr> </table> </form> </body> </html>
Example 10-18. Code to test tracing in the non-web component code-behind (.vb)
Option Explicit On Option Strict On '----------------------------------------------------------------------------- ' ' Module Name: CH10TestTraceWithinNonWebComponentVB.aspx.vb ' ' Description: This class provides the code behind for ' CH10TestTraceWithinNonWebComponentVB.aspx ' '***************************************************************************** Namespace ASPNetCookbook.VBExamples Public Class CH10TestTraceWithinNonWebComponentVB Inherits System.Web.UI.Page '************************************************************************* ' ' 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 Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.LoadDim webComponent As CH10TestNonWebComponentVB
'create the "web aware" component
webComponent = New CH10TestNonWebComponentVB
'add a string to the string in the component 1000 times
webComponent.addToString("1234567890", _
1000)
End Sub 'Page_Load End Class 'CH10TestTraceWithinNonWebComponentVB End Namespace
Example 10-19. Code to test tracing in the non-web component code-behind (.cs)
//---------------------------------------------------------------------------- // // Module Name: CH10TestTraceWithinNonWebComponentCS.aspx.cs // // Description: This class provides the code behind for // CH10TestTraceWithinNonWebComponentCS.aspx // //**************************************************************************** using System; namespace ASPNetCookbook.CSExamples { public class CH10TestTraceWithinNonWebComponentCS : System.Web.UI.Page { //************************************************************************ // // 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) {CH10TestNonWebComponentCS webComponent = null;
// create the "web aware" component
webComponent = new CH10TestNonWebComponentCS( );
// add a string to the string in the component 1000 times
webComponent.addToString("1234567890",
1000);
} // Page_Load } // CH10TestTraceWithinNonWebComponentCS }