Silently Getting Exception Details From Your Users in ASP.NET

Say you have an ASP web site that you’ve deployed and want to be notified when and why your website craps the bed. Since it’s live you probably have something like this in your web.config file:

<customErrors mode="RemoteOnly" defaultRedirect="error.aspx"/>

And while it hides all the exception details from your users, serving them a pretty error page, it has the side effect of returning the generic and completely useless System.Web.HttpUnhandledException. So the question is how do you, the developer, recieve the full stack trace and exception details when a user happens to come upon an error using your application? You might feel tempted to use the Application_Error event in Global.asax to catch the exception, parse out all the exception details and email them to yourself. Unfortunately that won’t work because ASP will still hide the stack trace from you. Instead of wasting your time writing code from scratch that will do this, you can accomplish the same thing by adding a few lines to your web.config file.

<system.net>
        <mailSettings>
            <smtp deliveryMethod="Network">
                <network host="yoursmtpserver"/>
            </smtp>
        </mailSettings>
    </system.net>
    <system.web>
        <healthMonitoring enabled="true" heartbeatInterval="0">
            <providers>
                <add name="ErrorEmailProvider" type="System.Web.Management.SimpleMailWebEventProvider" to="you@email.com" from="donotreply@you.com" buffer="false" subjectPrefix="[APP ERROR]"/>
            </providers>
            <rules>
                <add name="EmailErrors" eventName="All Errors" provider="ErrorEmailProvider" profile="Default" minInstances="1" maxLimit="Infinite" minInterval="00:01:00" custom=""/>
            </rules>
        </healthMonitoring>

With those blocks in your web.config file you will recieve an email containing all the information you need to track down which section of code failed. And at the same time your user recieves a friendly error page and is none the wiser. Here’s a sample of a simple IndexOutOfRangeException.

** Application Information **
---------------
Application domain: /LM/W3SVC/1/Root/HSR-1-128402415931345878
Trust level: Full
Application Virtual Path: /HSR
Application Path: C:\Inetpub\wwwroot\HSR\ Machine name: myserver


** Events **
---------------
Event code: 3005
Event message: An unhandled exception has occurred.
Event time: 11/22/2007 2:47:40 PM
Event time (UTC): 11/22/2007 9:47:40 PM
Event ID: 051ece02de474c8ea153eb0ffc058f25 Event sequence: 6 Event occurrence: 1 Event detail code: 0

Process information:
    Process ID: 4092
    Process name: w3wp.exe
    Account name: NT AUTHORITY\NETWORK SERVICE

Exception information:
    Exception type: System.IndexOutOfRangeException
    Exception message: Index 0 is either negative or above rows count.

Request information:
    Request URL: http://myserver/HSR/requeststatus.aspx?request=22
    Request path: /HSR/requeststatus.aspx
    User host address: 000.000.000.000
    User: someuser
    Is authenticated: True
    Authentication Type: Negotiate
    Thread account name: NT AUTHORITY\NETWORK SERVICE

Thread information:
    Thread ID: 1
    Thread account name: NT AUTHORITY\NETWORK SERVICE
    Is impersonating: False
    Stack trace:    at System.Data.DataView.GetElement(Int32 index)
   at System.Data.DataView.get_Item(Int32 recordIndex)
   at requeststatus.Page_Load(Object sender, EventArgs e) in c:\Inetpub\wwwroot\HSR\requeststatus.aspx.cs:line 27
   at System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e)
   at System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e)
   at System.Web.UI.Control.OnLoad(EventArgs e)
   at System.Web.UI.Control.LoadRecursive()
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

Leave a Reply