Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Neater handling of exceptions

0.00/5 (No votes)
9 Sep 2009 1  
ASP.net provides facilities in web.config for specifying error pages when an exception occurs, for example:            <customErrors

This articles was originally at wiki.asp.net but has now been given a new home on CodeProject. Editing rights for this article has been set at Bronze or above, so please go in and edit and update this article to keep it fresh and relevant.

ASP.net provides facilities in web.config for specifying error pages when an exception occurs, for example:

    <system.web>
        <customErrors mode="RemoteOnly" defaultRedirect="~/error-generic.aspx">
            <error statusCode="403" redirect="~/error-403.aspx" />
            <error statusCode="404" redirect="~/error-404.aspx" />
        </customErrors>
    </system.web>
 

This example redirects error 403 & 404 to specific pages, and all other errors to a generic page. This works great for the most part, but there are a couple of problems with it:

1. It doesn't allow for custom logging, and

2. Because of how the page is served, it returns with a HTTP status of 200 instead of 500 (or something useful).

However, both of these problems can be overcome fairly easily, using a custom HttpModule to handle your errors. First, create a new class:

public class ErrorModule : IHttpModule
{
    public void Dispose() { }

    public void Init(HttpApplication context)
    {
        context.Error += new EventHandler(Context_Error);
    }

    public void Context_Error(object sender, EventArgs e)
    {
        HttpApplication application = (HttpApplication)sender;
        HttpContext context = application.Context;
        System.Configuration.Configuration configuration = WebConfigurationManager.OpenWebConfiguration("~");
        SystemWebSectionGroup systemWeb = (SystemWebSectionGroup)configuration.GetSectionGroup("system.web");
        CustomErrorsSection customErrorsSection = systemWeb.CustomErrors;

        // If customerrors mode == off, then just let IIS handle it
        if (customErrorsSection.Mode != CustomErrorsMode.Off)
        {
            // If mode == on or its a remote request, we want to get the pretty page
            if (customErrorsSection.Mode == CustomErrorsMode.On || !context.Request.IsLocal)
            {
                Exception ex = context.Error;
                HttpException httpException = (HttpException)ex;

                string sURL = customErrorsSection.DefaultRedirect;
                if (httpException != null)
                {
                    context.Response.StatusCode = httpException.GetHttpCode();
                    CustomErrorCollection customErrorsCollection = customErrorsSection.Errors;
                    CustomError customError = customErrorsCollection[context.Response.StatusCode.ToString()];
                    if (customError != null)
                        sURL = customError.Redirect;

                    // Log the actual cause
                    ex = httpException.GetBaseException();
                }
                else
                {
                    context.Response.StatusCode = 500;
                }


/*

Put custom logging here!
*/

                context.ClearError();
                context.Server.Transfer(sURL);
            }
        }
    }
}
 

Then, in web.config, add the following:

    <system.web>
        <httpModules>
            <add name="ErrorModule" type="ErrorModule" />
        </httpModules>
    </system.web>
 

When ISS loads the application, it loads the ErrorModule class and execute it's Init() method, which adds a custom handler for the Application.Error event. The handler is where the magic happens.

First, it reads the customErrors section of web.config, so it can use your settings. Next it checks the error mode, so that when you don't want to bypass the default error page, it just returns without doing anything.

After setting the default error URL, it checks if the error is a HttpException, if so it sets the response HTTP status to the code returned by the exception, and checks the code against the any custom pages you've defined in the customErrors section. If it finds a match, it updates the URL with the one from web.config. If it is not a HttpException, it sets the HTTP status to 500 (Internal server error). At this point you can add custom error logging. It then clears the error, so IIS won't do it's thing, and redirects to the selected page.

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