Two step MVC 3 Error Handling using Custom Error Controller and HandleErrorAttribute

I am using a combination of HandleErrorAttribute and a Custom Error Controller in the Custom Errors section for error handling in a MVC3 application. The logic is to handle any Ajax request errors via the OnException handler in the HandleErrorAttribute and rest of the errors via the ErrorController. Below is the code -

// Handle any ajax error via HandleErrorAttribute 
public class HandleAjaxErrorAttribute : System.Web.Mvc.HandleErrorAttribute
 {
    public override void OnException(System.Web.Mvc.ExceptionContext filterContext)
    {



        filterContext.HttpContext.Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;
        var exception = filterContext.Exception;

        if (filterContext.HttpContext.Request.IsAjaxRequest())
        {
            //some logic
            filterContext.ExceptionHandled = true;
        }

    }
}

//Handle remaining errors in the Error Controller

public class ErrorController : Controller
{

    protected override void HandleUnknownAction(string actionName)
    {
        var exception = Server.GetLastError(); //Can't get the exception object here.
        //some logic
    }



}

The Web.config settings:

<customErrors mode="On" defaultRedirect="~/Error">
</customErrors>

When any non-ajax exception occurs the control flows from the OnException block to the HandleUnknownAction in the Error Controller. However I am unable to get the Exception object. How can I get the Exception object in the Error Controller ?

Also, do you think this two step approach is a proper way to handle errors in MVC3 ? I thought of handling error in a centralized location using the Application_Error event handler but as per my research this is not the recommed approach for MVC applications.

Answers


Regarding my comment above, I'm pasting my code here in order to clarify what I did.

This code goes inside a BaseController (highly recommended to make one, see this article: http://weblogs.asp.net/rashid/archive/2009/04/01/asp-net-mvc-best-practices-part-1.aspx)

and I've overridden the OnException method (My main goal here was to differentiate between Ajax calls and regular calls):

protected override void OnException(ExceptionContext filterContext)
    {
        // Set to true or else it'll still propagate
        filterContext.ExceptionHandled = true;

        string message;



        // Check if it's an Ajax request
        if (filterContext.HttpContext.Request.IsAjaxRequest())
        {
            // Here I check if the custom error is on, if it isn't I'll paste the
            // stacktrace and the error
            if (!filterContext.HttpContext.IsCustomErrorEnabled)
            {
                message = filterContext.Exception.Message + filterContext.Exception.StackTrace;
            }
            else
            {
                message = "Something went wrong";
            }

            // TODO: Decide what to do if ajax
            filterContext.HttpContext.Response.StatusCode = 401;
            var json = new JsonResult {Data = message};
            json.ExecuteResult(this.ControllerContext);
        }
        else
        {
            // This is basically the same conditional, but instead of sending a JSON
            // I'll redirect to a view and give it the exception
            if (!filterContext.HttpContext.IsCustomErrorEnabled)
            {
                ViewData.Model = filterContext.Exception;
                this.View("Error").ExecuteResult(this.ControllerContext);
            }
            else
            {
               this.View("../Error/ServerError").ExecuteResult(this.ControllerContext);
            }

        }
    }
}

Important to notice about my comment above is that I'm not saying not to use CustomError, but think of it only when errors that are, indeed, outside the pipeline occur (401 for example).


I might be wrong but I believe that you do not need to worry about error info in your controller because MVC automatically wires it up in the View. So if you make your (Razor) view like this, it should work:

@model System.Web.Mvc.HandleErrorInfo

Any logging can be done in your attribute but if you need to do it in the error controller, create a LogError action on your Error controller that takes a HandleErrorInfo argument and call it something like:

@Html.RenderAction("LogError", Model)

PS I haven't tested this but it should work.


My Error message was not getting displayed and ErrorController was not kicking in till I did following setting

<customErrors mode="On" defaultRedirect="~/Error">
</customErrors>

Need Your Help

How to show content without html tags in feed of wordpress?

php regex wordpress feed atom-feed

I want to remove all html tags from my custom wordpress feed. Is it possible? How to do it? I tried to use str.replace(/&lt;\/?[^&gt;]+&gt;/gi, '') but it doesn't help me at all. Here is the code ...