2

I have read articles on exception handling in ASP.NET MVC. I want to make sure I am doing right by presenting it briefly. Could anyone please comment.

  1. Catch the exceptions in controller actions, if necessary.

    [HttpPost]
    public ActionResult Insert()
    {
        try
        {
    
        }
        catch
        {
            //ModelState.Error -> display error msg to the user.
        }
    }
    
  2. Override the "OnException" method of controller in basecontroller and "log" the exceptions raised in step 1 and other MVC exceptions

  3. Logged the global exceptions in application_onerror.

Alastair Pitts
  • 19,423
  • 9
  • 68
  • 97
Sunny
  • 4,765
  • 5
  • 37
  • 72
  • 2
    take a look at something like ELMAH – Daniel Powell Aug 31 '12 at 04:03
  • Yeah, I am planning to use log4net but not decided though. – Sunny Aug 31 '12 at 04:12
  • 1
    why reinvent the wheel? I admit its good to know how it works but after you understand that no real point in writing it yourself unless it doesnt do what you want, also log4net is targeted at slightly different logging then elmah, i see elmah as more unexpected exception logging and log4net to log application events/known errors – Daniel Powell Aug 31 '12 at 04:57

3 Answers3

2

If you want handle exceptions in your Actions you can override "OnException" in your Controller like so:

protected override void OnException(ExceptionContext filterContext)
{
  logging or user notification code here
}

You can put it in your BaseController class to prevent duplication

Dima
  • 6,721
  • 4
  • 24
  • 43
2

I would definitely recommend ELMaH instead of writing this code yourself, and also over Log4Net for your MVC apps. I personally avoid any exception handling, unless I have a specific functional response to it. In this way, I don't "eat" any of the errors that an application-wide tool such as ELMaH will handle gracefully for me.

ELMaH also has nice built-in web reporting, and there are third-party tools specifically for ELMaH that can give you statistics, e.g. the most frequent errors.

You might start with a custom error redirect...

<customErrors defaultRedirect="~/site/error" mode="RemoteOnly">
  <error statusCode="404" redirect="~/site/notfound" />
</customErrors>

...to a controller that is aware you are using ELMaH...

public virtual ActionResult Error() {
    System.Collections.IList errorList = new System.Collections.ArrayList();
    ErrorLog.GetDefault(System.Web.HttpContext.Current).GetErrors(0, 1, errorList);
    ErrorLogEntry entry = null;
    if (errorList.Count > 0) {
        entry = errorList[0] as Elmah.ErrorLogEntry;
    }
    return View(entry);
}

...backed by a view that helps the visitor get the specific error ID to you:

@model Elmah.ErrorLogEntry

@if (Context.User.Identity.IsAuthenticated) {
    <p>Since you are signed in, we've noted your contact information,
    and may follow up regarding this to help improve our product.</p>
} else {
    <p>Since you aren't signed in, we won't contact you regarding this.</p> 
}
<p>Error ID: @Model.Id</p>

I also notice this is an HttpPost in this example. If you are doing AJAX, then you'll want to handle errors for those in a unique way. Pick a standard response you can send to browsers that all of your AJAX code handles gracefully. Perhaps by displaying the ELMaH error ID in a javascript alert (as a simple example).

I also handle a few special types of AJAX errors via Global.asax:

protected void Application_EndRequest()
{
    if (Context.Response.StatusCode == 302 &&
        Context.Request.Headers["X-Requested-With"] == "XMLHttpRequest")

HandleErrorAttribute is a nice feature, but it is well-known that there is extra work to use it in conjunction with ELMaH. How to get ELMAH to work with ASP.NET MVC [HandleError] attribute?

Community
  • 1
  • 1
shannon
  • 8,664
  • 5
  • 44
  • 74
0

try and catch are for expected exceptions ie your user has entered a file name and it might not exist so you want to catch the FileNotFoundException.

For unexpected exceptions use either the Error event in the MvcApplication object e.g.

public class MvcApplication : HttpApplication
{
    protected void Application_Start()
    {
        this.Error += MvcApplication_Error;
        // Other code
    }

    private void MvcApplication_Error(object sender, EventArgs e)
    {
        Exception exception = this.Server.GetLastError();
        // Do logging here.
    }
}

or as Dima suggested you have controller level execption handling using

protected override void OnException(ExceptionContext filterContext)
{
   // Do logging here.
}

Keep the trys and catches on code where you want to catch something expected and can handle. "Generic" error handling just obfuscates the underlying problem, which you will have to dig for later.

Mark Broadhurst
  • 2,675
  • 23
  • 45