Friday, October 21, 2011

Custom Http Error Module in C#


(this post is displayed correctly in Chrome and IE but not in Firefox)

During the implementation of a very large website I had to find a way to redirect http errors to custom error pages, the technologies used on the front end were Windows 2008 Server, IIS 7 and ASP .Net (C#). After doing some research I shortly found a few different approaches to handle http errors, below are details of all these approaches and limitations of some of them.


IIS GUI
From IIS GUI, go to your site and then click on Error Pages. Then add a new Status Code or edit an existing one accordingly to your needs.

IIS configuration File

In the IIS configuration file under C:\Windows\System32\inetsrv\config\ applicationHost.config. See below the section you need to edit to configure the custom error pages from the applicationHost.config.
    <location path="staging.dev.tridion.local">
       <system.webServer>
           <httpErrors errorMode="Custom" defaultResponseMode="Redirect">
               <remove statusCode="412" subStatusCode="-1" />
               <remove statusCode="406" subStatusCode="-1" />
               <remove statusCode="405" subStatusCode="-1" />
               <remove statusCode="503" subStatusCode="-1" />
               <remove statusCode="502" subStatusCode="-1" />
               <remove statusCode="501" subStatusCode="-1" />
               <remove statusCode="500" subStatusCode="-1" />
               <remove statusCode="403" subStatusCode="-1" />
               <remove statusCode="401" subStatusCode="-1" />
               <remove statusCode="404" subStatusCode="-1" />
           </httpErrors>
       </system.webServer>
   </location>

Web Application's Web.config

In the web application’s Web.config. Below there is an example about how to redirect 404 errors to 404.aspx, additionally any other http error would be send to the default page which in this case is DefaultErrorPage.aspx.
   <customErrors defaultRedirect="/en/resources/errorpages/DefaultErrorPage.aspx" mode="On">
        <error statusCode="404" redirect="/en/resources/errorpages/404.aspx" />
   </customErrors>


Global.asax


It is an optional file used to declare and handle application and session-level events and objects for an ASP.NET web site running on an IIS Web Server. The file contains ASP.NET program code, and is the .NET counterpart of the Global.asa file used for ASP. The Global.asax file resides in the IIS virtual root of an ASP.NET application.

Below I show how to handle HTTP errors from the Global.asax, note that it would need keys to be added to the web.config exactly in the same way as is shown in the next point Creating a Http Module.
   protected void Application_Error()
   {
       string errorPage = "";        
       Exception unhandledException = Server.GetLastError();
       HttpException httpException = unhandledException as HttpException;
       if (httpException == null)
       {
           Exception innerException = unhandledException.InnerException;
           httpException = innerException as HttpException;
       }
       if (httpException != null)
       {
           int httpCode = httpException.GetHttpCode();
           if (ConfigurationManager.AppSettings[(Convert.ToString(httpCode))] != null)
               errorPage = ConfigurationManager.AppSettings[Convert.ToString(httpCode)].ToString();
           if (string.IsNullOrEmpty(errorPage))            {
               if (ConfigurationManager.AppSettings["DefaultHttpErrorPage"] != null)
               errorPage = ConfigurationManager.AppSettings["DefaultHttpErrorPage"].ToString();
           }
           if (!string.IsNullOrEmpty(errorPage))
           {
               Response.Redirect(errorPage);
           }
       }
   }

Creating a Http Module

This requires registering the new HTTP module in the web.config, It needs to be added in two different places inside the web.config. Find more details on how to do it on this link 
My first approach was to capture the event as follows
  public void Init(HttpApplication application)
  {
     application.Error += new System.EventHandler(HandleHttpErrrors);       
  }
  public void HandleHttpErrrors(object sender, System.EventArgs args)
  {
  …
The downside of the approach above is that application.error event is triggered just when the request ends with .aspx.
One of the requirements for this project was to remove all the extensions from the requests, to be able to handle this scenario I implemented the HTTP module as shown here. See the first lines of the class below.


For every HTTP error that needs to be redirected to its own custom error page, a new key needs to be added to the web.config as sown below. For those HTTP errors that don’t have a key in the web.config the DefaultHttpErrorPage will be rendered.
  <appSettings>        
   <add key="it-404" value="/en/resources/errorpages/404.aspx"/>
   <add key="en-404" value="/en/resources/errorpages/404.aspx"/>
   <add key="DefaultHttpErrorPage" value="/en/resources/errorpages/404.aspx"/>
  </appSettings>

No comments:

Post a Comment