Wednesday, September 19, 2007 3:48 AM Kazi Manzur Rashid

New Project - Asp.net Ajax Exception Logging

In August Ajax column of DotNetSlackers, I have shown an effective exception logging system. In that column, I concluded saying that a lot of enhancement can be done with it which I finally did and created a project in CodePlex - Asp.net Ajax Exception Logging. Here is the list of enhancements:

  • A new Control is introduced - ExceptionManager which is used to register the listeners. No need to manually register those.
  • Automatic Logging of Unhandled and Update Panel Exceptions not need to hook those events manually. Just turn on the HandleUnhandledException and HandleUpdatePanelException which is by default turned on.
  • Encapsulating listeners in its own server side class.
  • An Enhanced version of web service listener which includes dynamic location of web service path/method name and batch submitting of exceptions.
  • A built-in web service to log exceptions - ExceptionLogService.
  • Introducing provider model in server side, so you can roll your provider to log these exceptions.
  • Built-in provider which logs in Asp.net HealthMonitoring/WebEvents.

Let me give a quick tour.

Registering Listeners

Earlier you have to register the listeners like the following:

function applicationLoad(sender, args)
{
    var mgr = Ajax.Logging.ExceptionManager.getInstance();

    mgr.addListener(new Ajax.Logging.WebServiceListener());
    mgr.addListener(new Ajax.Logging.PanelListener($get('pnlExceptions')));
    mgr.addListener(new Ajax.Logging.SysDebugListener());
    mgr.addListener(new Ajax.Logging.AlertListener());
}

Now you will do it in the server side:

<AjaxLogging:ExceptionManager ID="TheExceptionManager" runat="server">
    <Listeners>
        <AjaxLogging:WebServiceListener ServicePath="~/ExceptionLogService.asmx" ServiceMethod="Log" />
        <AjaxLogging:PanelListener Panel="pnlException" />
        <AjaxLogging:SysDebugListener />
        <AjaxLogging:AlertListener />
    </Listeners>
</AjaxLogging:ExceptionManager>

It will automatically inject the earlier JavaScript codes in the client side.

Handling Unhandled and Update Panel Exception

Previously you have to manually hook those events to log exceptions, now it will automatically log those exceptions, just ensure you did not turned off the HandleUnhandledException and HandleUpdatePanelException. You can also set the exception code from the server side .The Control will automatically inject the following code:

window.onerror = function(message, url, lineNumber)
{
    var e = Error.create(message, {description:message, name:'UnhandledError', lineNumber:lineNumber, url:url});
    Ajax.Logging.ExceptionManager.getInstance().publishException(105000, e);
    return true;
}

Sys.WebForms.PageRequestManager.getInstance().add_endRequest(AjaxLoggingHandleUpdatePanelError)
function AjaxLoggingHandleUpdatePanelError(sender, args)
{
    var e = args.get_error();
    if (e != null)
    {
        Ajax.Logging.ExceptionManager.getInstance().publishException(105001, e);
        args.set_errorHandled(true);
    }
}
Encapsulating Listener in Server Side Class

Now each of the listener is encapsulated in its own server side class. You can also roll your own listener from Inheriting the BaseListener class. For example, the following shows the code of AlertListener:

public class AlertListener : BaseListener
{
    [Browsable(false)]
    public override string CreateScript
    {
        [DebuggerStepThrough()]
        get
        {
            string script = string.Format(System.Globalization.CultureInfo.CurrentCulture, "Ajax.Logging.ExceptionManager.getInstance().addListener(new {0}());", this.GetType().FullName);

            return script;
        }
    }

    [Browsable(false)]
    public override IEnumerable<ScriptReference> ScriptReferences
    {
        [DebuggerStepThrough()]
        get
        {
            return new ScriptReference[] { new ScriptReference(Owner.Page.ClientScript.GetWebResourceUrl(this.GetType(), "Ajax.Logging.Scripts.AlertListener.js")) };
        }
    }
}

You have to override the CreateScript and ScriptReferences property which will contain the listener specific code. The client side rule to create listener remains the same.

Enhanced Web Service Listener

In previous version the exceptions were forwarded to a static web service and the web service was called each time the publishException is called, now it supports dynamic web service url as well as method name and it also queue the exceptions in the client side and submits as batch, the default interval is 10 seconds which you can change from the LogInterval property.

Built-in Web Service

Now it has a pre-built web service which you can use to log exceptions. Just add an asmx file and add the following line:

<%@ WebService Language="c#" Class="Ajax.Logging.ExceptionLogService, Ajax.Logging" %>

And in the web service listener set the path and the method name like the following:

<AjaxLogging:WebServiceListener ServicePath="~/ExceptionLogService.asmx" ServiceMethod="Log"  />
Provider Model

To record the exception in server side it uses the Asp.net Provider Model. To create a new provider you have create a class which inherits from ExceptionLogProvider and overriding the Log method.

Built-in Health Monitoring Provider

Now it comes with a Built-in Provider which uses the Asp.net health monitoring system to log the exceptions. It raises a custom event WebClientExceptionEvent to record the exception. Certainly the required settings for health monitoring needs to be present in the configuration file. The following shows a logged exception in the Event Log.

Event Log

You can download the full source and a working sample from codeplex.

A small note about Asp.net Future

The upcoming release of Asp.net known as Asp.net Future also has the support to log client side exceptions. But unfortunately it does not allow to log any other exceptions except the window.onerror, also it is not as much extensible as the above, no support for listeners, not automatic logging etc. You will find the details in this link.

kick it on DotNetKicks.com

Filed under:

Comments

# re: New Project - Asp.net Ajax Exception Logging

Monday, September 24, 2007 10:15 AM by Eran Nachum

Very impressive! Great solution for catching unhandled exception messages that are being thrown to as javascript alert.

# re: New Project - Asp.net Ajax Exception Logging

Wednesday, June 18, 2008 10:21 PM by Jim

Where would be the best place to put logic for sending an email with the error info? Thanks for the great project!

# re: New Project - Asp.net Ajax Exception Logging

Thursday, July 10, 2008 3:34 AM by Rob von Nesselrode

Your demo works well enough, however once I got it all in my project and regardles of WHICH listener, the AJAX validateParameter function has a dummy spit.

The end result is the listeners fail to register and thus don't get called.

I have turned on all exceptions in VS2008 and have stepped all the code - the error is on the line:

(208) if (expectedType && !expectedType.isInstanceOfType(param))

in MicrosoftAjax.js

Also from the debugger:

?typeof(expectedType) = "function"

?typeof(param) = "object"

This leads to:

Object of type 'Object' cannot be converted to type ''.

Parameter name: listener"

Any ideas?

# re: New Project - Asp.net Ajax Exception Logging

Thursday, October 9, 2008 12:27 AM by chandraskhr26

This is Excellent.But I cann't Found How create Logging Evenet for My Project.Please give me clearly.