Skip to content
RhysC edited this page Dec 16, 2014 · 6 revisions

#Handling errors in Asp.net

NOTE this article refers to MVC 4.5.x which is still using Sytem.Web

The first thing to be aware of is where the error handling is happening and what is the order of execution.


OWIN -> System.Web/Asp.Net -> MVC pipleine -> your app code


##OWIN Errors Catching an exception in an OWIN handler will not really do anything if you are using System.Web as it will not let the exception bubble out of the stack. This conforms to the OWIN spec 6.1 . What this basically means is trying to write a middleware that is just for exception handling in OWIN in this scenario is pointless

##MVC Error handling MVC currently runs within Asp.Net. If you handle an error in MVC infrastructure then it wont bubble up to any of the standard system.web infrastructure. This means you may have to end up writing 2 error handlers!! Of specific note is the common code : filters.Add(new HandleErrorAttribute()); Using this attribute will mean Asp.Net exception handling will not fire eg IHttpModule.Error or Application_Error will not fire. By using [HandleError] you have handled the exception - I recommend you do not use this attribute except for Demo code.

##Old Skool Asp.Net The safest way to handle exceptions is still the old school way.
You should either use a HTTP module that handles errors ( eg CodeConverters.Mvc.Diagnostics.ErrorLoggingHttpModule) or handle it directly in your gloabl.asax.cs as below. You can also use a tool like ELMAH.
You will however still have to correctly handle error pages from within your web.config. You should be using ResponseRewrite in your system.web -> customErrors to show the page but keep the HTTP response code when throwing from within Asp.net.
For IIS issued errors you should also be handling known errors and serve up a custom page if possible (eg when it thinks its looking for a static file). See system.webServer -> httpErrors

//GLOBAL.ASAX.CS
public class Global : System.Web.HttpApplication
    {
        //log4net
        private static readonly ILog Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

        protected void Application_Error(object sender, EventArgs e)
        {
            var ex = Server.GetLastError();
            //Note you should always include a message AND the exception object when logging errors in Log4Net
            Logger.Error(ex.Message, ex);
        }
    }
//WEB.CONFIG
...
<system.web>
  <!-- you will need to have publicly accessible path that follow the paths below -->
  <customErrors mode="On" redirectMode="ResponseRewrite" defaultRedirect="/Error">
    <error statusCode="403" redirect="Forbidden" />
    <error statusCode="404" redirect="NotFound" />
    <error statusCode="500" redirect="Error" />
  </customErrors>
  <!-- other directive here -->  
</system.web>
<system.webServer>
  <httpErrors errorMode="Custom" existingResponse="Replace">
    <remove statusCode="404" />
    <error statusCode="404" responseMode="ExecuteURL" path="/NotFound" />
    <remove statusCode="403" />
    <error statusCode="403" responseMode="ExecuteURL" path="/Forbidden" />
    <remove statusCode="500" />
    <error statusCode="500" responseMode="ExecuteURL" path="/Error" />
  </httpErrors>
  <!-- other directives here -->
<system.webServer>

Note IIS will intercept requests it thinks it can handle independently of Asp.Net, such as static files. This does mean your error handling in thing like http modules may not be hit. One way around this is to tell IIS to just send everything to Asp.Net:

<system.webServer>
    <modules runAllManagedModulesForAllRequests="true" >
      <!-- other stuff here -->
<!-- NOTE for fully explanation of what this will do see http://weblog.west-wind.com/posts/2012/Oct/25/Caveats-with-the-runAllManagedModulesForAllRequests-in-IIS-78 -->
    </modules>
    <!-- other stuff here -->
</system.webServer>

For an excellent article describing much of the fluffing around see : http://benfoster.io/blog/aspnet-mvc-custom-error-pages

Clone this wiki locally