Question

Let me first describe how my error handling is set up as there are several ways to do this in ASP.NET MVC. I have configured httpErrors in web.config, overridden HandleUnknownAction in the controller base and set up a route to handle anything undefined and this works fine (e.g. displaying my 404 error page when anything is not found and displaying my 500 error page when something has gone wrong in the code).

Web.config:

  <system.webServer>
    <httpErrors errorMode="Custom" existingResponse="Replace">
      <clear />
      <error statusCode="400" path="/error/400" responseMode="ExecuteURL" />
      <error statusCode="401" path="/error/401" responseMode="ExecuteURL" />
      <error statusCode="402" path="/error/402" responseMode="ExecuteURL" />
      <error statusCode="403" path="/error/403" responseMode="ExecuteURL" />
      <error statusCode="404" path="/error/404" responseMode="ExecuteURL" />
      <error statusCode="405" path="/error/405" responseMode="ExecuteURL" />
      <error statusCode="406" path="/error/406" responseMode="ExecuteURL" />
      <error statusCode="407" path="/error/407" responseMode="ExecuteURL" />
      <error statusCode="408" path="/error/408" responseMode="ExecuteURL" />
      <error statusCode="409" path="/error/409" responseMode="ExecuteURL" />
      <error statusCode="410" path="/error/410" responseMode="ExecuteURL" />
      <error statusCode="411" path="/error/411" responseMode="ExecuteURL" />
      <error statusCode="412" path="/error/412" responseMode="ExecuteURL" />
      <error statusCode="413" path="/error/413" responseMode="ExecuteURL" />
      <error statusCode="414" path="/error/414" responseMode="ExecuteURL" />
      <error statusCode="415" path="/error/415" responseMode="ExecuteURL" />
      <error statusCode="416" path="/error/416" responseMode="ExecuteURL" />
      <error statusCode="417" path="/error/417" responseMode="ExecuteURL" />
      <error statusCode="429" path="/error/429" responseMode="ExecuteURL" />
      <error statusCode="500" path="/error/500" responseMode="ExecuteURL" />
      <error statusCode="501" path="/error/501" responseMode="ExecuteURL" />
      <error statusCode="502" path="/error/502" responseMode="ExecuteURL" />
      <error statusCode="503" path="/error/503" responseMode="ExecuteURL" />
      <error statusCode="504" path="/error/504" responseMode="ExecuteURL" />
      <error statusCode="505" path="/error/505" responseMode="ExecuteURL" />
    </httpErrors>
  </system.webServer>

(my custom error page is a view with the route "error/{code}")

Controller base:

protected override void HandleUnknownAction(string actionName)
{
    throw new HttpException(404, null);
}

RouteConfig:

routes.MapRoute("Undefined", "{*url}", new { controller = "Undefined", action = "Index" });

UndefinedController:

public class UndefinedController : Controller
{
    public ActionResult Index()
    {
        throw new HttpException(404, null);
    }
}

I also have a HttpErrorResult (ActionResult) class which works fine to return any error:

public class HttpErrorResult : ActionResult
{
    private int _code = 0;

    public HttpErrorResult(int code)
    {
        _code = code;
    }

    public override void ExecuteResult(ControllerContext context)
    {
        throw new HttpException(_code, null);
    }
}

Ok that should be all the code involved in my error handling.

The problem I have encountered is that when I return the HttpErrorResult from an Attribute it does not display my custom error page but instead the standard yellow error page saying "Server Error in '/' Application" "Exception of type 'System.Web.HttpException' was thrown."

Specifically I get this problem when I try to return a 429 error (too many requests) in my EnforceRequestLimitAttribute (AuthorizeAttribute) class:

public override void OnAuthorization(AuthorizationContext filterContext)
{
    if (!AuthorizeCore(filterContext.HttpContext))
        filterContext.Result = new HttpErrorResult(429);
    else
        base.OnAuthorization(filterContext);
}

I cannot understand the reason for this as it works perfectly fine to throw an HttpException in the HandleUnknownAction method and in the UndefinedController and to use the HttpErrorResult in any other controller to get the custom error page but in an Attribute it behaves differently.

Why is this and what can be done to get around it?

Was it helpful?

Solution

I haven't figured out why but simply setting the Response.StatusCode instead of returning a Result that is throwing a HttpException has the desired effect i.e. the custom error page is displayed.

filterContext.HttpContext.Response.StatusCode = 429;

OTHER TIPS

For me the issue was in Global.asax.cs. When I hit the exception in Debug mode, I pressed F10 to step over it and see what else was going on. Turns out I was doing a

Server.ClearError();

which stopped the Custom Error page from showing. Removing this line fixed the issue.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top