Real world error hadnling in ASP.NET MVC RC2.

6 במרץ 2009

13 תגובות

I would like to share with You my ASP.NET MVC Error Handling solution after reading this question in stackoverflow.com 

Goal:

To catch every error that occures on server include HttpExeptions like 404 (Page not found).

The ability to choose a specific View (error Template) for some errors and a generic View/Behaviour if nor specific has been specified.
Scenario 1:
anonymus user typed a wrong url.
Actions:
display a user friendly message like: "OOPS, The page is missing… back to home"
Log the error to .log file on server.
Send email to admin.

Senario 2:
same as scenario 1 but one difference : user is anonymus but his IP is from our company office.
Actions:
show the detailed error.

Let's see some code:

 

Add this method to Global.asax:

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

 // Log the exception.
 ILogger logger = Container.Resolve<ILogger>();
 logger.Error(exception);
 
 Response.Clear();
 
 
 HttpException httpException = exception as HttpException;
 RouteData routeData = new RouteData();
 routeData.Values.Add("controller", "Error");
 
 if (httpException == null)
 {
      routeData.Values.Add("action", "Index");
 }
 else //It's an Http Exception, Let's handle it.
 {
 
  switch (httpException.GetHttpCode())
  {
    case 404:
      // Page not found.
      routeData.Values.Add("action", "HttpError404");
      break;
     case 500:
     // Server error.
       routeData.Values.Add("action", "HttpError500");
       break;
       // Here you can handle Views to other error codes.
        // I choose a General error template  
        default:
        routeData.Values.Add("action", "General");
        break;
     }
  }
 
 // Pass exception details to the target error View.
 routeData.Values.Add("error", exception);
 
 // Clear the error on server.
 Server.ClearError();
 
// Call target Controller and pass the routeData.
 IController errorController = new ErrorController();
 errorController.Execute(new RequestContext(
new HttpContextWrapper(Context), routeData));
 
}

Created a new controller called ErrorController:
You can specify some more behaviors to another eception types, I breated a view just for error: 404, 500.

 

    public ActionResult HttpError404(string error)
        {
            ViewData["Title"] = "Sorry, an error occurred while processing your request. (404)";
            ViewData["Description"] = error;
            return View("Index");
        }
 
        public ActionResult HttpError500(string error)
        {
            ViewData["Title"] = "Sorry, an error occurred while processing your request. (500)";
            ViewData["Description"] = error;
            return View("Index");
        }
 
 
        public ActionResult General(string error)
        {
            ViewData["Title"] = "Sorry, an error occurred while processing your request.";
            ViewData["Description"] = error;
            return View("Index");
        }

 

I attached an example project to this post.

 

הוסף תגובה
facebook linkedin twitter email

כתיבת תגובה

האימייל לא יוצג באתר. (*) שדות חובה מסומנים

13 תגובות

  1. Mose2 באפריל 2009 ב 11:28

    2 remarks :

    1) the HandleError attribute is of no use anymore (in Home & Error controller) as you are using a custom error handling.

    2) in your sample the Application_Error method is called twice (breakpoint told me so).

    Whatever : good sample.

    להגיב
  2. Patrick8 באפריל 2009 ב 13:53

    It looks like this works only on GET requests. If I have an exception which is caused after an POST then this ain't working.

    There seems to be an innerexception in the Context, "This operation requires IIS integrated pipeline mode."

    Has somebody else noticed this also?

    להגיב
  3. Eduardo16 ביולי 2009 ב 1:56

    Do you know why if the error is a security error (try posting

    להגיב
  4. Andrew23 ביולי 2009 ב 12:51

    Thanks for the code. However it appears to break if I type in a URL for example "/foo/foo/foo/foo"

    "The SessionStateTempDataProvider requires SessionState to be enabled."

    להגיב
  5. Sam Shawn15 באוקטובר 2009 ב 17:28

    Thanks your codes, but InvalidOperationException with message "Session state disabled" at
    errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));

    להגיב
  6. Palantir23 באוקטובר 2009 ב 11:17

    Great code. You have a typo in the page title, though :)

    להגיב
  7. Nimesh23 באוקטובר 2009 ב 12:34

    i am getting errror:
    The SessionStateTempDataProvider requires SessionState to be enabled.

    להגיב
  8. joedirt7 בדצמבר 2009 ב 17:12

    I've tried to implement this into my project and I get a blank screen back. The response is empty and the URL doesn't change to my error view. I've stepped through the code in the debugger and I see the HttpError404 controller method being called and returning the View, but then I don't get anything on the screen. Any suggestions?

    להגיב
  9. שי יעקובי9 בדצמבר 2009 ב 21:15

    Please check with the debugger

    להגיב
  10. Scott Findlater2 בינואר 2010 ב 16:48

    i am also getting the error:

    The SessionStateTempDataProvider requires SessionState to be enabled.

    Any ideas?

    להגיב
  11. Jared12 בפברואר 2010 ב 19:43

    From what I see, and I could be wrong, the 'SessionStateTempDataProvider requires SessionState' error is caused from a resource request such as an image or file. No session state is provided with such requests, therefor the SessionState is null. To handle this, I do this:

    try
    {
    IController errorController = new ClientPortal.Controllers.ErrorController();
    errorController.Execute( new RequestContext(
    new HttpContextWrapper( Context ), routeData ) );
    }
    catch ( Exception ex )
    {
    //Do Nothing… 9 times out of 10 it's a missing resouce that doesn't contain state
    }

    Hope this helps… please post if I am wrong.

    להגיב
  12. Sam Delaney15 באפריל 2010 ב 18:32

    I've run the sample project, with a network analyser running, and at no point do we get a 404 or 500 response code back, just 200s.

    להגיב
  13. Matt Kocaj16 במאי 2010 ב 8:50

    @Jared:

    That fix of swallowing the exception does not work even with the "/foo/foo/foo/foo" example. I suspect that the Session State is required a little more than 10% of the time.

    להגיב