Tracing in ASP

download Tracing in ASP

of 13

Transcript of Tracing in ASP

  • 8/6/2019 Tracing in ASP

    1/13

    Tracing in ASP.NETFuente: http:/ / weblogs.asp.net/ plip/ articles/ 111130.aspx

    This small article will focus on ASP.NETs built in Tracing functionality, this offersthe developer a place to put all the debug information from their program without itmucking up your expertly designed UI (well I can dream!).

    We will discuss the benefits of using Trace, as well as the costs it imposes on youas the developer especially in a team based environment. There is also a specialsection of this article devoted to the classic ASP developers that know and love

    Response.Write, hopefully I can persuade you not to use it any more

    The .NET Documentation describes Tracing as so: -

    ASP.NET introduces new functionality that allows you to write debug statements,directly in your code, without having to remove them from your application when itis deployed to production servers. Called tracing, this feature allows you to writevariables or structures in a page, assert whether a condition is met, or simply tracethrough the execution path of your page or application.

    In order for these messages and other tracing information to be gathered and

    displayed, you must enable tracing for the page or application. When you enabletracing, two things occur:

    ASP.NET appends a series of diagnostic information tables immediately

    following the page's output. The information is also sent to a trace viewerapplication (only if you have enabled tracing for the application).

    ASP.NET displays your custom diagnostic messages in the Trace

    I n f o rma t i o n table of the appended performance data.

    Diagnostic information and tracing messages that you specify are appended to theoutput of the page that is sent to the requesting browser. Optionally, you can viewthis information from a separate trace viewer (trace.axd) that displays traceinformation for every page in a given application. This information can help you to

    clarify errors or undesired results as ASP.NET processes a page request.

    Trace statements are processed and displayed only when tracing is enabled. Youcan control whether tracing is displayed to a page, to the trace viewer, or both.

  • 8/6/2019 Tracing in ASP

    2/13

    Turning it on

    What I shall show you first is simply how to turn tracing on for one of your existingASP.NET pages.

    First find the Page directive on your ASP.NET page (usually the first line in thepage): -

    Now we need to turn on Tracing for your page, we do this by adding the Traceproperty to the directive and setting it to true, like this: -

    Save your page, and open it in a browser. You should see the trace information at

    the bottom of the page looking something like this: -

    If you are not seeing the Trace information then take a quick look through this

    checklist to make sure something isnt overriding your settings.

    Note you can also enable tracing in your application, at an application level.

  • 8/6/2019 Tracing in ASP

    3/13

    Whats in it?

    Request Details

    Trace Information

    Control Tree

    Session Collection

    Cookies Collection

    Forms Collection

    Headers Collection

    Server Variables

  • 8/6/2019 Tracing in ASP

    4/13

    How does it w ork with my page HTML?

    As soon as ASP.NET detects the tag is in the response buffer it adds theTrace information to the end of the page, this is all encapsulated in a with an

    id of __asptrace.

    Talk about absolute positioning

  • 8/6/2019 Tracing in ASP

    5/13

    Lets use it to help us Debug a page

    Visual Studio .NET and ASP.NET offer the developer some really cool debuggingtools, but if you dont have access to them, then you are stuck with the good old

    ways of doing things, writing out your variables until you find the problem.

    Lets just quickly throw together some business logic that has a variable changing

    its value through out the page, in real life this could be anything from the contentof a shopping basket right up to some high level mathematics. For now its just me

    playing around with a number.

    privatevoid Page_Load(object sender, System.EventArgs e)

    {//Some fake business logic

    //Take a variable, any variable

    int i = 0;

    //Perform some addition

    i += 10;

    //Perform some more additioni += 30;

    //Do something slightly more complex than additioni = (i * (i + -2));

    //Pass it to a methodi = DoSomething(i);

    }

    publicint DoSomething(int aNumber){

    //Blow up, just to prove a pointif(aNumber > 0)

    {thrownew Exception("aNumber is more than 0!");

    }else

    {//Set it to 0return 0;

    }

    }

    In the Page_Load event we can see how were changing the value of i quite a bit. Ifsomething is going wrong like this: -Trace Information

    Category MessageFrom

    First(s)From

    Last(s)

    aspx.page Begin Init

    aspx.page End Init 0.001180 0.001180

    UnhandledExecutionError

    aNumber is more than 0!at intranet._default.DoSomething(Int32 aNumber) in

    c:\inetpub\wwwroot\intranet\default.aspx.cs:line 56

    0.002194 0.001014

  • 8/6/2019 Tracing in ASP

    6/13

    at intranet._default.Page_Load(Object sender, EventArgs e)in c:\inetpub\wwwroot\intranet\default.aspx.cs:line 44

    at System.Web.UI.Control.OnLoad(EventArgs e)at System.Web.UI.Control.LoadRecursive()at System.Web.UI.Page.ProcessRequestMain()

    This gives us no information as to where our sums are going wrong, so we can usethe Trace commands to output the variables value throughout its life time.

    So here is the same method above with some Trace calls: -

    privatevoid Page_Load(object sender, System.EventArgs e){

    //Some fake business logic

    //Take a variable, any variableint i = 0;

    Trace.Write("i","Variable after it's been created is " + i.ToString());

    //Perform some additioni += 10;

    Trace.Write("i","Variable after it's been added to is " + i.ToString());

    //Perform some more addition

    i += 30;

    Trace.Write("i","Variable after it's been added to again is " + i.ToString());

    //Do something slightly more complex than additioni = (i * (i + -2));

    Trace.Write("i","Variable after it's been messed around with is " +i.ToString());

    //Pass it to a methodi = DoSomething(i);

    Trace.Write("i","Variable after it's been processed is " + i.ToString());

    }

    publicint DoSomething(int aNumber){

    //Blow up, just to prove a pointif(aNumber > 0){

    thrownew Exception("aNumber is more than 0!");}else{

    //Set it to 0return 0;

    }

    }

  • 8/6/2019 Tracing in ASP

    7/13

    When we run our page with the Trace information included we get it all placed in tothe Trace log: -Trace Information

    Category MessageFrom

    First(s)From

    Last(s)

    aspx.page Begin Init

    aspx.page End Init 0.001043 0.001043

    i Variable after it's been created is 0 0.002366 0.001323

    i Variable after it's been added to is 10 0.002413 0.000047

    i Variable after it's been added to again is 40 0.002442 0.000030

    i Variable after it's been messed around with is 1520 0.002472 0.000030

    UnhandledExecutionError

    aNumber is more than 0!at intranet._default.DoSomething(Int32 aNumber) in

    c:\inetpub\wwwroot\intranet\default.aspx.cs:line 56at intranet._default.Page_Load(Object sender, EventArgs e)

    in c:\inetpub\wwwroot\intranet\default.aspx.cs:line 44at System.Web.UI.Control.OnLoad(EventArgs e)at System.Web.UI.Control.LoadRecursive()at System.Web.UI.Page.ProcessRequestMain()

    0.003193 0.000720

    Now we can see by looking at the trace log, whats happening to the number, andwe can modify our business logic accordingly.

    privatevoid Page_Load(object sender, System.EventArgs e){

    //Some fake business logic

    //Take a variable, any variable

    int i = 0;

    Trace.Write("i","Variable after it's been created is " + i.ToString());

    //Perform some additioni += 10;

    Trace.Write("i","Variable after it's been added to is " + i.ToString());

    //Perform some more additioni += 30;

    Trace.Write("i","Variable after it's been added to again is " + i.ToString());

    //Do something slightly more complex than additioni = (i * -(i + -2));

    Trace.Write("i","Variable after it's been messed around with is " +i.ToString());

    //Pass it to a method

    i = DoSomething(i);

    Trace.Write("i","Variable after it's been processed is " + i.ToString());}

    Now when we look at the page the exception does not occur and we can see whywhen we look at the Trace information: -Trace Information

    Category Message From First(s) From Last(s)aspx.page Begin Initaspx.page End Init 0.003425 0.003425

  • 8/6/2019 Tracing in ASP

    8/13

    i Variable after it's been created is 0 0.006264 0.002838i Variable after it's been added to is 10 0.006327 0.000063i Variable after it's been added to again is 40 0.006370 0.000044i Variable after it's been messed around with is -1520 0.006414 0.000044i Variable after it's been processed is 0 0.007609 0.001195aspx.page Begin PreRender 0.007684 0.000074aspx.page End PreRender 0.009410 0.001727aspx.page Begin SaveViewState 0.034088 0.024677

    aspx.page End SaveViewState 0.085753 0.051665aspx.page Begin Render 0.085834 0.000081aspx.page End Render 0.288975 0.203141

    Now we have fixed our code, we dont need to do anything to the Trace commandsas they do not interfear with the visual side of our page. All we need to do is set theTrace property to false in the page directive Tag.

  • 8/6/2019 Tracing in ASP

    9/13

    Which part of False do you not understand?

    Remember way back to the top of the article, where I showed you an excerpt fromthe .NET SDK Documentation, it said Trace statements are processed and

    displayed only when tracing is enabled.?

    It Lies.

    We can prove this by setting the Trace property on a page to False and then callinga trace command that will cause an exception, for example referencing an objectthat doesnt exist such as a Querystring value: -

    privatevoid Page_Load(object sender, System.EventArgs e)

    {Trace.Write(Request.QueryString["Doesn'tExist"].ToString());

    }

    Calling this when Trace is enabled causes an exception to occur: -

    Server Error in '/intranet' Application.

    Object reference not set to an instance of an object.Description: An unhandled exception occurred during the execution of the current web request. Please reviewthe stack trace for more information about the error and where it originated in the code.

    Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.

    Source Error:

    Line 21: {Line 22: //Some fake business logicLine 23: Trace.Write(Request.QueryString["Doesn'tExist"].ToString());Line 24: }

    Line 25:

    Source File: c:\inetpub\wwwroot\intranet\default.aspx.cs Line: 23

    Stack Trace:

    [NullReferenceException: Object reference not set to an instance of anobject.]

    intranet._default.Page_Load(Object sender, EventArgs e) inc:\inetpub\wwwroot\intranet\default.aspx.cs:23

    System.Web.UI.Control.OnLoad(EventArgs e) +67System.Web.UI.Control.LoadRecursive() +29System.Web.UI.Page.ProcessRequestMain() +718

    Version Information: Microsoft .NET Framework Version:1.0.3705.288; ASP.NET Version:1.0.3705.288

    This means that the statement Trace statements are processed and displayed onlywhen tracing is enabled. is obviously a blatant lie.

    This is also important in terms of costly operations, lets say youve put a large loop

    in to your page and its outputting data to the Trace log so you can debug it whydo we need to call this when Trace is turned off?

    A solution is provided in the form of Trace.IsEnabled(), we can check to see if

    Tracing is enabled before we run the Trace commands, like this: -

  • 8/6/2019 Tracing in ASP

    10/13

    privatevoid Page_Load(object sender, System.EventArgs e){

    if(Trace.IsEnabled)

    {Trace.Write(Request.QueryString["Doesn'tExist"].ToString());

    }}

    Now, that means we now have to write four lines of code for every Trace we haveto write, which is really not an inviting thought Trace is supposed to make thingsEASIER not HARDER!

    Lets also add some error handling to our Trace command to make sure that even

    when we get errors we can handle them properly: -

    privatevoid Page_Load(object sender, System.EventArgs e){

    if(Trace.IsEnabled){

    try{

    Trace.Write(Request.QueryString["Doesn'tExist"].ToString());}catch (Exception ex){

    Trace.Warn("Trace","Exception",ex);}

    }}

    Now, our simple 1 line Trace.Write call is 11 lines long! Messy I hope youll agree.

  • 8/6/2019 Tracing in ASP

    11/13

    Tidy the Mess

    The easiest and quickest way to get around these limitations of Trace is toencapsulate all the functionality so that we can call it in one line. One way to do

    this is to create a class such as so.

    using System;

    namespace My{

    publicclass Trace{

    publicstaticvoid Write(string Message){

    if(System.Web.HttpContext.Current.Trace.IsEnabled){

    try

    {

    System.Web.HttpContext.Current.Trace.Write(Message.ToString());}

    catch(Exception e){

    System.Web.HttpContext.Current.Trace.Warn("Intranet.Web","Write",e);}

    }}publicstaticvoid Write(string Category, string Message){

    if(System.Web.HttpContext.Current.Trace.IsEnabled){

    try{

    System.Web.HttpContext.Current.Trace.Write(Category.ToString(),Message.ToString());

    }catch(Exception e){

    System.Web.HttpContext.Current.Trace.Warn("Intranet.Web","Write",e);}

    }

    }publicstaticvoid Write(string Category, string Message,

    System.Exception exe){

    if(System.Web.HttpContext.Current.Trace.IsEnabled){try{

    System.Web.HttpContext.Current.Trace.Write(Category.ToString(),Message.ToString(),exe);

    }catch(Exception e)

    {

  • 8/6/2019 Tracing in ASP

    12/13

    System.Web.HttpContext.Current.Trace.Warn("Intranet.Web","Write",e);

    }

    }}publicstaticvoid Warn(string Message){

    if(System.Web.HttpContext.Current.Trace.IsEnabled){

    try{

    System.Web.HttpContext.Current.Trace.Warn(Message.ToString());}

    catch(Exception e){

    System.Web.HttpContext.Current.Trace.Warn("Intranet.Web","Write",e);}

    }

    }publicstaticvoid Warn(string Category, string Message){

    if(System.Web.HttpContext.Current.Trace.IsEnabled){

    try{

    System.Web.HttpContext.Current.Trace.Warn(Category.ToString(),Message.

    ToString());}catch(Exception e)

    {

    System.Web.HttpContext.Current.Trace.Warn("Intranet.Web","Write",e);}

    }}publicstaticvoid Warn(string Category, string Message,

    System.Exception exe)

    {if(System.Web.HttpContext.Current.Trace.IsEnabled){

    try{

    System.Web.HttpContext.Current.Trace.Warn(Category.ToString(),Message.

    ToString(),exe);}catch(Exception e){

    System.Web.HttpContext.Current.Trace.Warn("Intranet.Web","Write",e);}

    }}

    }

  • 8/6/2019 Tracing in ASP

    13/13

    }

    If you place the above in to a class file in your project, you can then use it as a 1line replacement for Trace as so: -

    privatevoid Page_Load(object sender, System.EventArgs e){

    if(Request.QueryString["Doesn'tExist"] != null){

    My.Trace.Write(Request.QueryString["Doesn'tExist"].ToString());}

    }

    This is all nice and neat and encapsulated now, and gives you a performanceincrease which scales with your application through debug and in to release, as wellas error handling of your Trace commands, all this with the ease of use of the Trace

    methods them selves.