ASP.NET OnError not catching ConfigurationErrorsException

A ConfigurationErrorsException was being thrown from within a class library linked to an ASP.NET site. The site logs all errors using the Global.ASAX error event and by overridding the ASP.NET page OnError() protected method. Neither of which handled the ConfigurationErrorsException when it was thrown.

When the type of exception in the class library was changed from ConfigurationErrorsException to ApplicationException, the page OnError method handles the exception.

Why does the type of the Exception thrown change the way ASP.NET handles the exception? If you want all errors to be handled in the ASP.NET OnError and/or Global.asax page Error event which Exceptions are safe to throw?

The following code demonstrates what I’ve described. A breakpoint in the OnError will get hit when you click the App Exception button but not when you click the Configurations Exception button…

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="OnErrorTest.WebForm1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
</head>
<body>
    <form id="form1" runat="server">
    <div>
    <asp:Button ID="btnInvalidOpEx" runat="server" Text="Invalid OP Exception" OnClick="btnInvalidOpEx_OnClick" />
    <asp:Button ID="btnAppEx" runat="server" Text="Application Exception" OnClick="bthnAppEx_OnClick" />
    <asp:Button ID="btnConfigEx" runat="server" Text="Configurations Exception" OnClick="btnConfigEx_OnClick" />    
    </div>
    </form>
</body>
</html>

Code behind

using System;
using System.Configuration;
using System.Web;

namespace OnErrorTest
{
    public partial class WebForm1 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected override void OnError(EventArgs e)
        {
            HttpContext ctx = HttpContext.Current;

            System.Exception exception = ctx.Server.GetLastError();
        }

        protected void bthnAppEx_OnClick(object sender, EventArgs e)
        {
            throw new ApplicationException("Application Error");
        }

        protected void btnConfigEx_OnClick(object sender, EventArgs e)
        {
            throw new ConfigurationErrorsException("Configurations Error");
        }

        protected void btnInvalidOpEx_OnClick(object sender, EventArgs e)
        {
            throw new InvalidOperationException("Configurations Error");
        }
    }
}

EDIT: It was suggested that ConfigurationErrorsException is a system exception and it’s meant to be thrown by the .NET Framework and not an application. It does indeed derive from SystemException, however so does InvalidOperationException. OnError catches InvalidOperationException

CONCLUSION: Don’t throw anything derived from ConfigurationException unless your intent is that it’s not to be processed in either the OnError method of an ASP.NET Page or global exception handlers. I’ve tested MVC and no Controller.OnException has no such discrimination against ConfigurationException.

Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

Solution 1

I peeked into the source code for ProcessRequestMain. There is a try...catch block in this method which catches any ConfigurationException and throws it again (look into line 4680). All other Exceptions are handed over to HandleError method which will call OnError. (Also ThreadAbortException is handled separately which is not your concern here.)

This is why you can’t capture ConfigurationException (and ConfigurationErrorsException which is inherited from ConfigurationException) using either OnError method or Error event in an ASP.NET page.

Solution 2

I think it’s because a configurationerror essentially blocks the app from running properly and the configurationerrorsexception also, according to the docs, is not meant to be thrown by us but by the framework itself. Since most configurations lead to the app not functioning it wouldn’t be able to catch the configuration error anyways with a logging tool since it can’t configure the environment to run the logging tool when it gets to that error.

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply