5,427,303 members and growing! (18,861 online)
Email Password   helpLost your password?
Web Development » Ajax and Atlas » General     Intermediate

Logging Client Side JavaScript Errors to the Server

By Adrian K

How to log client side JavaScript errors to the server using AJAX, XML and C#.
Javascript, XML, C#, HTML, Windows, .NET, Visual Studio, ASP.NET, Ajax, Dev

Posted: 12 Dec 2005
Updated: 12 Dec 2005
Views: 49,533
Bookmarked: 48 times
Announcements
Want a new Job?



Search    
Advanced Search
Sitemap
8 votes for this Article.
Popularity: 3.42 Rating: 3.79 out of 5
1 vote, 12.5%
1
0 votes, 0.0%
2
1 vote, 12.5%
3
3 votes, 37.5%
4
3 votes, 37.5%
5

Introduction

It's kind of scary realising that should your JavaScript fail, the only way you'll know is if some kind user lets you know. We've all seen "object x is undefined" errors and so on, how many times have you reported the error to the webmaster? It's easy for these problems to go unnoticed for prolonged periods of time.

I have recently been getting to grips with 'AJAX' techniques, and had a magic light-bulb moment when I realised that by using a combination of AJAX and C#, we can do away with reliance on users, and log the errors automatically ourselves.

The basic plan of attack is as follows:

Overview.

Background

The whole concept hinges on catching the errors in the first place, then using XMLHttpRequests to send the error data back to the server via a .NET HTTP handler which finally invokes a method of some kind that does something useful with the error information.

Check out MSDN for more info on catching errors on the client side.

If you haven't used AJAX before, I suggest the following helpful resources:

If you're new to HttpHandlers in .NET, go no further than:

Using the code

The sample ASP.NET (C#) project is pretty straightforward and easy to use (to get the sample code working, simply web-share the JavaScriptErrorLogger folder so that you make HTTP requests to the web server). Let's take a look at the essentials.

The good news is that it's pretty easy to apply the error catching code to existing JavaScripts. To handle errors, all you need to do is handle the Window.Onerror event:

window.onerror = errorHandler;

errorHandler will, of course, point to a function that does something constructive with the event:

function errorHandler(message, url, line)
{
    // message == text-based error description

    // url     == url which exhibited the script error

    // line    == the line number being executed when the error occurred


    // handle the error here

    alert( message + '\n' + url + '\n' + line );
    
    return true;
}

Obviously, your error handling needs to be very reliable. Alerting the error data is not especially ground breaking, so here is the JavaScript used in the sample code which actually executes the XmlHttpRequest:

function errorHandler(message, url, line)
{
    // message == text-based error description

    // url     == url which exhibited the script error

    // line    == the line number being executed when the error occurred


    // handle the error here

    //alert( message + '\n' + url + '\n' + line );

    
    
    //-------------------------------------------------------------------

    // Log the Error

    //-------------------------------------------------------------------

    
    var xmlHttpRequest;
    // a variable to hold our instance of an XMLHTTP object.


    var bHookTheEventHandler = true;
    // used to switch on/off the handling

    // of any response from the server.


    // Checking if IE-specific document.all collection exists 

    // to see if we are running in IE 

    if (document.all)
    { 
        xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP"); 
    } else { 
        xmlHttpRequest = new XMLHttpRequest(); 
    }
    

    //----------------------------------------------------------------        

    // Roll the error information into an xml string:

    //----------------------------------------------------------------

    var xmlDoc = new ActiveXObject("Msxml2.DOMDocument.3.0");
    xmlDoc.async = false;
    xmlDoc.loadXML("<JavaScriptError line='" + line + "' url='" 
                   + url + "'>" + message + 
                   "</JavaScriptError>");


    //------------------------------------------------------------

    // If you want to see some sort of response to prove (on the 

    // client end) that something has happened,

    // set bHookTheEventHandler = true 

    // otherwise false is probably all we want.

    //------------------------------------------------------------

    if(bHookTheEventHandler)
    {
        xmlHttpRequest.onreadystatechange = 
                sendSomeXml_HandlerOnReadyStateChange;
    }

    //prepare the call, http method=GET, false=asynchronous call

    xmlHttpRequest.open("post", "http://localhost/JavaScript" + 
            "ErrorLogger/logerror.ashx", bHookTheEventHandler);

    //finally send the call

    xmlHttpRequest.send( xmlDoc );  
    
    //------------------------------------------------------------

    // Finished Logging the Error

    //------------------------------------------------------------

                    
    return true;
}

Note that handling the xmlHttpRequest.onreadystatechange event is not necessary if you just want to log errors, but you could use it in this context if you wanted to let the user know that an error has occurred and has been logged.

Before we can catch any incoming requests, we need to tweak the web.config file (see the background links above for more info). The beauty of this approach is that the URL specified when making the XmlHttpRequest doesn't have to actually exist. In this example, the HTTP handler will catch requests for .ashx URLs.

<httpHandlers>
  <!-- Simple Handler -->
  <add verb="*" path="*.ashx" 
        type="JavaScriptErrorLogger.LogErrorHandler, JavaScriptErrorLogger" />
</httpHandlers>

On the server side, we'll catch the incoming XML using an HTTP handler:

using System;
using System.Web;
using System.Xml;

namespace JavaScriptErrorLogger 
{

    public class LogErrorHandler : IHttpHandler 
    {

        public void ProcessRequest( HttpContext httpContext ) 
        {
            XmlDocument xmlDoc = null;
        
            // If XML document was submitted via POST method

            // then load it in the DOM document:

            if (httpContext.Request.InputStream.Length > 0 && 
                httpContext.Request.ContentType.ToLower().IndexOf("/xml") > 0) 
            {
                xmlDoc = new XmlDocument();
                xmlDoc.Load( httpContext.Request.InputStream );
        
                // at this point the XML message is available via xmlDoc.InnerXml: 

                Console.WriteLine( xmlDoc.InnerXml );
            }
        }
    }
}

Most of the examples I have found on the net make the client side XmlRequest using GET. If you want to send data to the server, you'll need to POST it (as in the error handling code provided earlier). Having used POST, we can get the data sent to the server by using httpContext.Request.InputStream (as above). In this example, we are simply outputting the XML to the console, where as in the sample code, we use a method that will log the XML to a file.

Having caught the XML in our HTTP handler, we could send it (or other XML) back out again:

public void ReturnXML( HttpContext httpContext, string rawXml )
{
    if(rawXml == "")
        throw new ApplicationException("The value of rawXml was not defined.");

    // Produce XML response:

    httpContext.Response.ContentType = "application/xml";
    XmlTextWriter xw = new XmlTextWriter( httpContext.Response.OutputStream, 
                                           new System.Text.UTF8Encoding() );
    xw.WriteRaw( rawXml );
    xw.Close();
}

Points of Interest

You will see in the sample code that I use a simple object to pass the error information about (at the C# level). This object has only one property (a string) which contains the XML that describes the error. But being clever, you'll realize that this could be extended to include any other info we want to send with the error, such as the client's browser and so on. You could go further and deserialize the XML straight into a C# object.

Since - in an ideal world - you'll never get any errors, it will be wise to construct a test-harness so you can periodically invoke an error and check that it is processing the errors just as you intend it to. If your system hasn't send you any error logs for a while, it'd be best if that was because there weren't any - not because the error handling is broken.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Adrian K


I mainly focus on GUI's for web-based apps (mainly focused on MSIE - by accident, I guess) using C# with some DHTML and Ajax thrown in for good measure.
Occupation: Web Developer
Location: New Zealand New Zealand

Other popular Ajax and Atlas articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 23 of 23 (Total in Forum: 23) (Refresh)FirstPrevNext
Subject  Author Date 
GeneralHow to get error message from server using AJAX.memberSANDESHDADDI23:30 15 Jan '07  
GeneralURGENT HELP PLSmemberab62842:53 2 Jan '07  
Questionwhere the error javascriptmemberzhaojicheng20:43 21 Jun '06  
AnswerRe: where the error javascriptmemberzhaojicheng21:09 21 Jun '06  
AnswerRe: where the error javascript [modified]memberAdrian K0:06 25 Aug '06  
GeneralRe: where the error javascriptmemberzhaojicheng18:02 27 Aug '06  
QuestionMissing JavaScriptmemberRainyDaysInVancouver20:08 6 Jun '06  
AnswerRe: Missing JavaScript [modified]memberAdrian K0:13 25 Aug '06  
GeneralThis script works for both FireFox and IE just thought it would be helpful!memberdarthtim20049:54 8 May '06  
GeneralURGENT HELP PLSmemberab62842:49 2 Jan '07  
GeneralRe: This script works for both FireFox and IE just thought it would be helpful! - URGENT HELP REQUIREDmemberab628418:58 2 Jan '07  
GeneralRe: This script works for both FireFox and IE just thought it would be helpful!memberab628420:26 2 Jan '07  
GeneralAjax ProjectsmemberHazem Torab12:00 4 Jan '06  
GeneralMissing FilesmemberDrewM5:32 21 Dec '05  
GeneralRe: Missing FilesmemberAdrian K14:09 21 Dec '05  
GeneralRe: Missing FilesmemberRainyDaysInVancouver17:35 4 Jun '06  
QuestionRemarks . . .memberAur3lien3:43 13 Dec '05  
AnswerRe: Remarks . . .memberAdrian K13:16 13 Dec '05  
GeneralNo document.all check please!memberAlbert Weinert2:30 13 Dec '05  
GeneralRe: No document.all check please!memberAdrian K13:19 13 Dec '05  
General500 ErrormemberYazeed hs1:00 13 Dec '05  
GeneralRe: 500 ErrormemberAdrian K13:54 13 Dec '05  
GeneralRe: 500 ErrormemberRaaj J7:47 22 Feb '06