Handling exceptions globally at Application_Error event in Global.asax

Global.asax Application_Error event handle exceptions globally in Asp,Net MVC

 

Posted: May 13, 2017. | By: mustafa

In the previous article we have seen how to handle exception in MVC using HandleError filter and customErrors. Now we will see how to handle exception globally using  Application_Error event in global.asax. It is not limited to the MVC scope and implemented in the Global.asax.cs file.

 
However, developer like to manage errors from single location. This allows for a single point of error logging and handling exceptions.
Application_Error method is the final chance to handle all unhandled exceptions either occurred in MVC context or out of MVC context.
 
Steps to follow -
 
  • Get the last server error. 
  • Get the http error code. 
  • Log the error. 
  • Clear the response stream. 
  • Clear the server error. 
  • Rendering the ErrorController.
 protected void Application_Error(object sender, EventArgs e)
        {
            var httpContext = ((MvcApplication)sender).Context;
            var currentController = " ";
            var currentAction = " ";
            var currentRouteData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));


            if (currentRouteData != null)
            {
                if (currentRouteData.Values["controller"] != null && !String.IsNullOrEmpty(currentRouteData.Values["controller"].ToString()))
                {
                    currentController = currentRouteData.Values["controller"].ToString();
                }
                if (currentRouteData.Values["action"] != null && !String.IsNullOrEmpty(currentRouteData.Values["action"].ToString()))
                {
                    currentAction = currentRouteData.Values["action"].ToString();
                }
            }

            var ex = Server.GetLastError();
            var controller = new ErrorController();
            var routeData = new RouteData();
            var action = "Index";

            httpContext.ClearError();
            httpContext.Response.Clear();
            httpContext.Response.StatusCode = ex is HttpException ? ((HttpException)ex).GetHttpCode() : 500;
            httpContext.Response.TrySkipIisCustomErrors = true;

            routeData.Values["controller"] = "Error";
            routeData.Values["action"] = action;

            controller.ViewData.Model = new HandleErrorInfo(ex, currentController, currentAction);
            ((IController)controller).Execute(new RequestContext(new HttpContextWrapper(httpContext), routeData));
            
        }


 
We have set TrySkipIisCustomErrors = true for that it will skip any redirect from IIS based on http code.
 
Invoking ErrorController by calling Execute() passing HandleErrorInfo model. Within the view we can use GetRouteData method of RouteTable.Routes to access controller name and action name.
 
Response.Clear() should be called to ensure that any content written to the response stream before the error occurred is removed. And httpContext.ClearError() must be called to stop ASP.NET from serving the yellow screen of death.

 

Defining ErrorController to return error view while any exception occurs and custom error view for NotFound exception.
 
public class ErrorController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
 
    public ActionResult NotFound()
    {
        return View();
    }
}
 
Note in the pervious article using cutomErrors we can define error view and also custom error views for other http error code like 500, 404. Similarly we can apply in Aplication_Error hence complete our objective.
 
if (ex is HttpException)
    {
        var httpEx = ex as HttpException;
 
        switch (httpEx.GetHttpCode())
        {
            case 404:
                action = "NotFound";
                break;
 
            // others if any
        }
    }
 
The Application_Error event within the global.asax is the perfect place to catch and log all exceptions occured in application, but it has some limitations.
 
Advantages and disadvantages of using Application_Error to catch global exception.
 
Exception filters are not global means it handle error at mvc context only and this is an important reason why we still use Application_Error event.
 
The important problem in the Application_Error event is, once the program execution reaches this point then we are out of MVC context and because of that we can miss some context information related to the exception.

Note: if we are using mvc controllers in our application we can use to get Mvc Controller Context.
 
((MvcApplication)sender).Context
 
Using exception filter we can return custom error views for different type of exceptions raised, by defining type of exception and relevant error view.
 
All other http errors handled by Asp.Net are passed through Application_Error event. Errors like http 500 & 404 not found etc. Also http errors are handled using customError section in web.config but it has its limitations as it gives http 302 Redirect Response.
 
When we need a controller or action level exception handling then we can use the HandleError filter along with the Application_Error event else we can simply ignore the HandleError filter.


While using the application_error event we can set Response StatusCode using httpException error code, result shown in fiddler response.
 
FiddlerHttpResult.png, Exception Loging, Asp.Net, Exception,  
 

related posts

Back to top