I’ve been using ASP.NET MVC Release 1 for a bit now, and while it’s definitely not for every application, I happen to like it quite a bit.  There has been a lot of activity on MS-centric blogs regarding MVC, but there are still some really mundane tasks that there could be more information on.  So, this series of posts isn’t going to be anything crazy; it will, however, illustrate what options you have to do centralized error-handling using MVC 1.

We’ll start at the beginning…

The System.Web.Mvc.dll comes with the HandleErrorAttribute class, which contains..wait for it…the HandleError attribute.   This information won’t be important until later in this series, but the HandleErrorAttribute class inherits from the FilterAttribute class, and implements the IExceptionFilter interface – the interface requires a method with the following signature. 

public virtual void OnException(ExceptionContext filterContext);

This method is really where the brunt of the work is done when you use the provided [HandleError] attribute.  In case you’ve never taken a look using Reflector, this HandleErrorAttribute’s implementation of OnException looks like this:

public virtual void OnException(ExceptionContext filterContext)
  {
      if (filterContext == null)
      {
          throw new ArgumentNullException("filterContext");
      }
      if (!filterContext.ExceptionHandled && filterContext.HttpContext.IsCustomErrorEnabled)
      {
          Exception innerException = filterContext.Exception;
          if ((new HttpException(null, innerException).GetHttpCode() == 500) && this.ExceptionType.IsInstanceOfType(innerException))
          {
              string controllerName = (string) filterContext.RouteData.Values["controller"];
              string actionName = (string) filterContext.RouteData.Values["action"];
              HandleErrorInfo model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);
              ViewResult result = new ViewResult();
              result.ViewName = this.View;
              result.MasterName = this.Master;
              result.ViewData = new ViewDataDictionary<HandleErrorInfo>(model);
              result.TempData = filterContext.Controller.TempData;
              filterContext.Result = result;
              filterContext.ExceptionHandled = true;
              filterContext.HttpContext.Response.Clear();
              filterContext.HttpContext.Response.StatusCode = 500;
              filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
          }
      }
  }

Essentially, you’re grabbing some information from the ExceptionContext, and you’re using the HandleErrorInfo class to pass this information back to your view.

Using [HandleError] is really as easy as using any other attribute.  You simply decorate your method or class with the attribute and your errors will be pushed to the default view for errors (Views/Shared/Error.aspx)

Sample usage of [HandleError]:

namespace MvcErrorHandling.Controllers
{
    [HandleError]
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            if (true)
            { 
                throw new ApplicationException("Some error...");
            }
            return View();
        }
        //removed...

Alternatively, you can provide the HandleError attribute with some arguments to specify a view other than the default error-view, or specify a specific view based on the exception type.  Here’s an example of the usage for that…

[HandleError(ExceptionType = typeof(ApplicationException), View = "AppErrorPage")]
public class HomeController : Controller
{
    public ActionResult Index()
    {
        if (true)
        { 
            throw new ApplicationException("Some error...");
        }
        return View();
    }
    //removed...

The only other thing you’ll want to make sure you do is ensure your web.config <customErrors> section is configured appropriately.  That is, you’ll want to make sure customErrors mode=”On” to test this out.

Hope this helps somebody; the next part in this series will demonstrate how to add functionality to the existing OnException method that the HandleErrorAttribute class implements, such as logging.

kick it on DotNetKicks.com

Share this post :

Technorati Tags: ,