views:

4204

answers:

5

I have some basic code to determine errors in my MVC application. Currently In the project I have a controller called Error with action methods "HTTPError404", "HTTPError500", and "General". They all accept a string "error." Using or modifying the code I am working on below, what is the best/proper way to pass the data to the Error controller for processing? I want this solution to be as robust as possible.

        protected void Application_Error(object sender, EventArgs e)
    {
        Exception exception = Server.GetLastError();
        Response.Clear();

        HttpException httpException = exception as HttpException;

        if (httpException != null)
        {
            RouteData routeData = new RouteData();
            routeData.Values.Add("controller", "Error");

            switch (httpException.GetHttpCode())
            {
                case 404:
                    // page not found
                    routeData.Values.Add("action", "HttpError404");
                    break;
                case 500:
                    // server error
                    routeData.Values.Add("action", "HttpError500");
                    break;
                default:
                    routeData.Values.Add("action", "General");
                    break;
            }

            routeData.Values.Add("error", exception);

            // clear error on server
            Server.ClearError();

            // at this point how to properly pass routedata to error controller?
        }
    }
+5  A: 

Instead of creating a new route for that, you could just redirect to your controller/action and pass the information via querystring. For instance:

protected void Application_Error(object sender, EventArgs e) {
  Exception exception = Server.GetLastError();
  Response.Clear();

  HttpException httpException = exception as HttpException;

  if (httpException != null) {
    string action;

    switch (httpException.GetHttpCode()) {
      case 404:
        // page not found
        action = "HttpError404";
        break;
      case 500:
        // server error
        action = "HttpError500";
        break;
      default:
        action = "General";
        break;
      }

      // clear error on server
      Server.ClearError();

      Response.Redirect(String.Format("~/Error/{0}/?message={1}", action, exception.Message));
    }

Then your controller will receive whatever you want:

// GET: /Error/HttpError404
public ActionResult HttpError404(string message) {
   return View("SomeView", message);
}

There are some tradeoffs with your approach. Be very very careful with looping in this kind of error handling. Other thing is that since you are going through the asp.net pipeline to handle a 404, you will create a session object for all those hits. This can be an issue (performance) for heavly used systems.

Cheers,

André Carlucci

andrecarlucci
When you say "be careful of looping" what exactly do you mean? Is there a better way to handle this type of error redirect (assuming it WAS a heavily used system) ?
aherrick
By looping I mean when you have an error in your error page, then you would be redirected to your error page again and again... (for instance, you want to log your error in a database and it is down).
andrecarlucci
Redirecting on errors goes against the architecture of the web. The URI should remain the same when the server responds the correct HTTP status code so the client knows the exact context of the failure.Implementing HandleErrorAttribute.OnException or Controller.OnException is a better solution. And if those fail, do a Server.Transfer("~/Error") in Global.asax.
asbjornu
A: 

Perhaps a better way of handling errors in MVC is to apply the HandleError attribute to your controller or action and update the Shared/Error.aspx file to do what you want. The Model object on that page includes an Exception property as well as ControllerName and ActionName.

Brian
A: 

Application_Error having issue with Ajax requests. If error handled in Action which called by Ajax - it will display your Error View inside the resulting container.

Lion_cl
+1  A: 
+2  A: 

Hi aherrick,

I struggled with the idea of centralizing a global error handling routine in an MVC app before. Please take a look at my post at http://forums.asp.net/t/1505777.aspx. It basically handles all your application errors in the global.asax without the need for an error controller, decorating with the [HandlerError] attribute, or fiddling with the customErrors node in the web.config.

I hope it helps.

Cheers!

Jack Hsu