The HandleError Attribute
The HandleError attribute (which appears on the default controllers in an MVC project) tells the framework that if an unhandled exception occurs in your controller that rather than showing the default Yellow Screen of Death it should instead serve up a view called Error. The controller-specific View folder will be checked first (eg. Views/Home/Error.aspx) and if it's not found, the Shared folder (Views/Home/Error.aspx) will be used.
But How Do I Log Exceptions?
You might've spotted the problem with HandleError. It just outputs a view, and doesn't let you run any code. This might be fine if you don't want users to see errors but don't really care for fixing them. Hopefully you think this isn't acceptable and you want to investigate all exceptions!
The OnException Method
The System.Web.Mvc.Controller class contains a method called OnException which is called whenever an exception occuts within an action. This does not rely on the HandleError attribute being set. If you're being a good coder and have your own base Controller class you can override this method in one place to handle/log all errors for your site. You might choose to send emails and/or detect duplicate exceptions and discard them. For now, I'm just going to write them all to a text file in my App_Data folder.
protected override void OnException(ExceptionContext filterContext)
{
WriteLog(Settings.LogErrorFile, filterContext.Exception.ToString());
}
///
/// Logs a message to the given log file
///
///
The filename to log to///
The message to logstatic void WriteLog(string logFile, string text)
{
//TODO: Format nicer
StringBuilder message = new StringBuilder();
message.AppendLine(DateTime.Now.ToString());
message.AppendLine(text);
message.AppendLine("===========================");
System.IO.File.AppendAllText(logFile, message.ToString());
}
This works great, but it still shows our user an unhandled exception message, even if we use the HandleError attribute. This makes the HandleError attribute look rather useless, so I've removed it. We can easily show the friendly error ourselves with the following code:
filterContext.ExceptionHandled = true;
this.View("Error").ExecuteResult(this.ControllerContext);
It's important to set ExceptionHandled to true, otherwise you'll still see the default unhandled exception message. The OnException method returns void so we must Execute the view and pass in the ControllerContext ourselves.
How Do I see my own Errors During Development?
It's a little inconvenient to open log files or keep commenting out your error handling code while developing to see exceptions and stack traces. You might remember ASP.NET has a nice web.config setting that configures custom errors. This property is exposed via MVC, so we can set up our config to show friendly errors to remote users only:
<customErrors mode="RemoteOnly" />
protected override void OnException(ExceptionContext filterContext)
{
WriteLog(Settings.LogErrorFile, filterContext.Exception.ToString());
// Output a nice error page
if (filterContext.HttpContext.IsCustomErrorEnabled)
{
filterContext.ExceptionHandled = true;
this.View("Error").ExecuteResult(this.ControllerContext);
}
}



Original Source: