title: CustomErrors is On, why is IsCustomErrorEnabled still false?
body: <p>I'm trying to get [HandleError] working in an MVC4 app.  I'm throwing exceptions in my controllers, and I'm still seeing the yellow "Server Error in" pages.</p>
  
  <p>To help figure out what is going on, I created my own filter attribute:</p>
  
  <pre><code>public class MyHandleErrorAttribute : HandleErrorAttribute
  {
      public override void OnException(ExceptionContext filterContext)
      {
          bool isHandled = filterContext.ExceptionHandled;
          bool customErrorEnabled = filterContext.HttpContext.IsCustomErrorEnabled;
          bool debuggingErrorEnabled = filterContext.HttpContext.IsDebuggingEnabled;
  
          base.OnException(filterContext);
      }
  }
  </code></pre>
  
  <p>I stick a breakpoint on base.OnException(), and let-er-rip.</p>
  
  <p>When my controller throws an exception, MyHandleErrorAttribute.OnException is called - but customErrorEnabled is false.  I've used Resharper to examine the code in Microsoft's HandleErrorAttribute.OnException(), and it starts with:</p>
  
  <pre><code>public virtual void OnException(ExceptionContext filterContext)
  {
      if (filterContext == null)
          throw new ArgumentNullException("filterContext");
      if (filterContext.IsChildAction || filterContext.ExceptionHandled || 
              !filterContext.HttpContext.IsCustomErrorEnabled)
          return;
  
      // ...
  }
  </code></pre>
  
  <p>In other words, it intentionally does nothing, if filterContext.HttpContext.IsCustomErrorEnabled is false.</p>
  
  <p>So, the question - why is IsCustomErrorEnabled false?</p>
  
  <p>One obvious possibility is that , in the web.config.  But if that is true, I don't know how.  I've searched the entire project for "customErrors", and it appears only once, in the root web.config, and there it is explicitly set to "On":</p>
  
  <pre><code>&lt;system.web&gt;
      &lt;customErrors mode="On" /&gt;
      ...
  &lt;/system.web&gt;
  </code></pre>
  
  <p>How, then, could IsCustomErrorEnabled still false?  What else could be over-riding it?  Where should I be looking?</p>
  
  <p>================ Additional information added ================</p>
  
  <p>One point of confustion - HandleErrorAttribute was being registered as a global filter. To explore how this stuff is working, I created three different custom exception filters:</p>
  
  <pre><code>public class MyGlobalHandleErrorAttribute : HandleErrorAttribute
  {
      public override void OnException(ExceptionContext filterContext)
      {
          bool isHandled = filterContext.ExceptionHandled;
          bool customErrorEnabled = filterContext.HttpContext.IsCustomErrorEnabled;
          bool debuggingErrorEnabled = filterContext.HttpContext.IsDebuggingEnabled;
  
          base.OnException(filterContext);
      }
  }
  
  public class MyControllerHandleErrorAttribute : HandleErrorAttribute
  {
      public override void OnException(ExceptionContext filterContext)
      {
          bool isHandled = filterContext.ExceptionHandled;
          bool customErrorEnabled = filterContext.HttpContext.IsCustomErrorEnabled;
          bool debuggingErrorEnabled = filterContext.HttpContext.IsDebuggingEnabled;
  
          base.OnException(filterContext);
      }
  }
  
  public class MyActionHandleErrorAttribute : HandleErrorAttribute
  {
      public override void OnException(ExceptionContext filterContext)
      {
          bool isHandled = filterContext.ExceptionHandled;
          bool customErrorEnabled = filterContext.HttpContext.IsCustomErrorEnabled;
          bool debuggingErrorEnabled = filterContext.HttpContext.IsDebuggingEnabled;
  
          base.OnException(filterContext);
      }
  }
  </code></pre>
  
  <p>And, of course, one of these I configured on an action, one on its controller, and one globally. That way I can tell which is being called, and in what order.</p>
  
  <p>So, if I set all three of these, all three are called, action, then controller, then global, regardless of whether  is set in the web.config.  (Running VS2012 in local debug, against IIS Express.) But customErrors does change the flags.</p>
  
  <p>So, let's walk through the possibilities:</p>
  
  <ul>
  <li><p>only the global handler installed.  </p>
  
  <ul>
  <li>customErrors Off: the global handler is called with ExceptionHandled false and IsCustomErrorEnabled false, so it does nothing, and we get the yellow Server Error page.  </li>
  <li>customErrors On: the global handler is called with ExceptionHandled false and IsCustomErrorEnabled true, so the HandleErrorAttribute does what it does, and loads ~/Views/Shared/Error.cshtml.</li>
  </ul></li>
  <li><p>global handler installed, and a handler on the action</p>
  
  <ul>
  <li>customErrors Off: the attribute handler is called with ExceptionHandled false and IsCustomErrorEnabled false, so it does nothing, then the global handler is called with with ExceptionHandled false and IsCustomErrorEnabled false, so it also does nothing, and we get the yellow Server Error page.</li>
  <li>customErrors On: the attribute handler is called with ExceptionHandled false and IsCustomErrorEnabled true, so it does what it does, then the global handler is called with with ExceptionHandled true and IsCustomErrorEnabled true, so it does nothing, because the attribute handler has already handled it. And we get ~/Views/Shared/Error.cshtml.</li>
  </ul></li>
  <li><p>global handler installed, and a handler on the action and on the controller: works the same way. All three are called, first action, then controller, then global. Because the handler on the action sets ExceptionHandled true, the later two do nothing, and we get the error page.</p></li>
  </ul>
  
  <p>All of which is entirely inconsistent with the behavior I was seeing yesterday, when I was setting customErrors On, and was still seeing IsCustomErrorEnabled false. I have no explanation for that, other than the possibility that IIS Express got stuck, and was no longer recognizing changes in the web.config.  </p>