title: Custom Error Handling in web.config / Global.asax not handling non-existant directory
body: <p>Question is:  Why is custom Error handling not working for non-existing paths/directories?</p>
  
  <p>Updated with fixed code (thanks to everyone for you input):</p>
  
  <p><em><strong></em>* Updated code for web.config and global.asax <em>*</em></strong></p>
  
  <pre><code>&lt;httpErrors errorMode="Custom"&gt;
          &lt;remove statusCode="500" subStatusCode="-1" /&gt;
          &lt;remove statusCode="404" subStatusCode="-1" /&gt;
          &lt;error statusCode="404" subStatusCode="-1" prefixLanguageFilePath="" path="/*****.aspx" responseMode="ExecuteURL" /&gt;
          &lt;error statusCode="500" subStatusCode="-1"  prefixLanguageFilePath="" path="/*****.aspx"  responseMode="ExecuteURL"/&gt;
      &lt;/httpErrors&gt;
  
      added this to the global.asax to stop IIS from handling my 500 errors
      after @Kev's suggestions IIS handled my 500's these lines fixed that
      HttpApplication myApplication = new HttpApplication();
      myApplication.Response.TrySkipIisCustomErrors = true;
  </code></pre>
  
  <p>We have a site setup with custom error handling in <code>web.config</code> and <code>global.asax</code> (the setup is shown below).  We are able to handle all 404's and 500's with no problems.  The errors are caught in the <code>Application_Error</code> in the <code>global.asax</code>, logged to a DB then using <code>HttpContext</code> we set the status code and use <code>Server.Transfer()</code> to move the user to the appropriate error page (redirects cause a 302, and hurts SEO).</p>
  
  <p>The problem is when the user types in <code>http://www.example.com/whatever</code> a blank page is shown in Firefox and in IE it shows the IE 404 page.  Firebug shows no status codes being fired, and when I debug the solution, no breakpoints I have set are hit in the <code>global.asax</code>.  The odd thing is that a user can enter <code>http://www.example.com/whatever/hmm.aspx</code> and an error will be hit.  It seems it's only working on non-existing pages and not paths/directories that don't exist. </p>
  
  <p>Below is my <code>web.config</code> code for the Errors and my <code>global.asax</code> code for Application error.</p>
  
  <p>I've added the <em>*</em>* to hide info, they have valid <code>.aspx</code> pages in them:</p>
  
  <p>Web config:</p>
  
  <pre><code>&lt;customErrors defaultRedirect="~/******.aspx" mode="On" 
                redirectMode="ResponseRewrite"&gt;
      &lt;error statusCode="500" redirect="~/*****.aspx" /&gt;
      &lt;error statusCode="404" redirect="~/*****.aspx" /&gt;
  &lt;/customErrors&gt;
  
      &lt;httpErrors errorMode="Custom"&gt;
          &lt;remove statusCode="500" subStatusCode="-1" /&gt;
          &lt;remove statusCode="404" subStatusCode="-1" /&gt;
          &lt;error statusCode="404" subStatusCode="-1" prefixLanguageFilePath="" path="/*****.aspx" responseMode="ExecuteURL" /&gt;
          &lt;error statusCode="500" subStatusCode="-1"  prefixLanguageFilePath="" path="/*****.aspx"  responseMode="ExecuteURL"/&gt;
      &lt;/httpErrors&gt;
  </code></pre>
  
  <p>Code:</p>
  
  <pre><code>protected void Application_Error(Object sender, EventArgs e)
  {
      // At this point we have information about the error
      HttpContext ctx = HttpContext.Current;
  
      // set the exception to the Context 
      Exception exception = ctx.Server.GetLastError();
  
      // get the status code of the Error
      int httpCode = ((HttpException)exception).GetHttpCode();
  
      // get the IP Address
      String strHostName = string.Empty;
      String ipAddress_s = string.Empty;
      strHostName = System.Net.Dns.GetHostName();
  
      System.Net.IPHostEntry ipEntry = System.Net.Dns.GetHostByName(strHostName);
      System.Net.IPAddress[] addr = ipEntry.AddressList;
  
      for (int i = 0; i &lt; addr.Length; i++)
      {
          ipAddress_s += "IP Address {" + (i + 1) + "} " + 
                              addr[i].ToString() + Environment.NewLine;
      }
  
      // setup the error info one for user display and one for the DB Insert
      string errorInfo =
         "&lt;br /&gt;&lt;b&gt;Error Location:&lt;/b&gt; " + ctx.Request.Url.ToString() +
         "&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Error Source:&lt;/b&gt; " + exception.Source +
         "&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Error Try/Catch:&lt;/b&gt; " + exception.InnerException +
         "&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Error Info:&lt;/b&gt; " + exception.Message +
         "&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Status Code:&lt;/b&gt; " + httpCode +
         "&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Stack trace:&lt;/b&gt; " + exception.StackTrace;
      string errorInfoDB =
         "||Error Location: " + ctx.Request.Url.ToString() +
         "||Error Source: " + exception.Source +
         "||Error Try/Catch: " + exception.InnerException +
         "||Error Info: " + exception.Message +
         "||HttpErrorCode: " + httpCode +
         "||Stack trace: " + exception.StackTrace +
         "||IP Address: " + ipAddress_s;
  
      // clean the input befor you put it in the DB
      char quote = (char)34;
      char filler = (char)124;
      char tick = (char)39;
      char greaterThan = (char)60;
      char lessThan = (char)62;
      errorInfo = errorInfo.Replace(quote, filler);
      errorInfo = errorInfo.Replace(tick, filler);
      errorInfo = errorInfo.Replace(greaterThan, filler);
      errorInfo = errorInfo.Replace(lessThan, filler);
  
      errorInfoDB = errorInfoDB.Replace(quote, filler);
      errorInfoDB = errorInfoDB.Replace(tick, filler);
      errorInfoDB = errorInfoDB.Replace(greaterThan, filler);
      errorInfoDB = errorInfoDB.Replace(lessThan, filler);
  
      string pattern = string.Empty;
      string replacement = "sQueEl";
      pattern = "/cookie|SELECT|UPDATE|INSERT|INTO|DELETE|FROM|NOT IN|WHERE|TABLE|DROP|script*/ig";
      errorInfoDB = Regex.Replace(errorInfoDB, pattern, replacement);
  
      pattern = "/cookie|select|update|insert|into|delete|from|not in|where|table|drop|script*/ig";
      errorInfoDB = Regex.Replace(errorInfoDB, pattern, replacement);
  
  
      if (httpCode == 404)
      {
          InSert_To_DB_Class(*****, *****, *****, *****, *****, errorInfoDB);
      }
      else
      {
          InSert_To_DB_Class(*****, *****, *****, *****, *****, errorInfoDB);
      }
  
      // set the error info to the session variable to display to the allowed users
      Application["AppError"] = errorInfo;
  
      // clear the error now that is has been stored to a session
      ctx.Server.ClearError();
      ctx.Response.ClearHeaders();
      // set the status code so we can return it for SEO
      ctx.Response.StatusCode = httpCode;
      ctx.Response.TrySkipIisCustomErrors = true;
      HttpApplication myApplication = new HttpApplication();
      myApplication.Response.TrySkipIisCustomErrors = true;
      try
      {
          if (ctx.Request.RawUrl.Contains("/*****"))
          {
              // redirect to the error page
              ctx.Server.Transfer("~/*****.aspx", false);
          }
          else if(ctx.Request.RawUrl.Contains("/*****"))
          {
              ctx.Server.Transfer("~/*****/*****.aspx", false);
          }
          else
          {
              // check the httpCode
              if (httpCode == 404)
              {
                  // set the page name they were trying to find to a session variable
                  // this will be cleared in the ****** page
                  Application["404_page"] = exception.Message; 
                  // redirect to the 404 page
                  ctx.Server.Transfer("~/*****", false);
              }
              else
              {
                  // redirect to the error page
                  ctx.Server.Transfer("~/*****", false);
              }
          }
      }
  }
  </code></pre>