ASP.NET MVC Global Error Handling Step by step Implementation and Top 10 Questions and Answers
 Last Update: April 01, 2025      11 mins read      Difficulty-Level: beginner

ASP.NET MVC Global Error Handling: A Detailed Guide for Beginners

Handling errors gracefully in a web application is crucial to ensure user satisfaction and maintain system integrity. ASP.NET MVC offers several mechanisms to handle errors both within a single controller or action and globally across the entire application, regardless of the specific controller or action being invoked. This guide will delve into the nuances of setting up global error handling in ASP.NET MVC, helping you to build more robust applications.

1. Understanding Error Types

Before delving into the specifics of global error handling, it’s vital to understand the types of errors that may occur in an ASP.NET MVC application.

  • Unhandled Exceptions: These occur when an exception is thrown and not caught by any try-catch block.
  • HTTP Errors: These errors are caused by HTTP request failures, such as 404 (Not Found), 405 (Method Not Allowed), and 500 (Internal Server Error) etc.
  • Custom Errors: These are application-specific errors that arise from logic or data handling issues.

2. Basic Configuration: Web.config

The web.config file serves as a global configuration center for your application, including settings for error handling.

a. Custom Errors Configuration

You can configure the application to show a custom error page by modifying the <customErrors> section within the web.config:

<system.web>
    <customErrors mode="On" defaultRedirect="~/Error/GenericError">
        <error statusCode="404" redirect="~/Error/NotFound"/>
        <error statusCode="500" redirect="~/Error/ServerError"/>
    </customErrors>
</system.web>
  • mode="On": Shows custom errors to all users.
  • mode="RemoteOnly": Shows custom errors to remote users and detailed errors to local administrators (default).
  • mode="Off": Shows detailed errors to all users.

b. HTTP Errors Configuration

For HTTP-level errors, the httpErrors section in the web.config can be utilized:

<system.webServer>
    <httpErrors errorMode="Custom" existingResponse="Replace">
        <remove statusCode="404" />
        <remove statusCode="500" />
        <error statusCode="404" path="/Error/NotFound" responseMode="ExecuteURL" />
        <error statusCode="500" path="/Error/ServerError" responseMode="ExecuteURL" />
    </httpErrors>
</system.webServer>
  • errorMode="Custom": Specifies that custom responses are provided for errors.
  • responseMode="ExecuteURL": The specified path is executed as a URL; for ASP.NET MVC, this is commonly used.

3. Using Filters

ASP.NET MVC uses action filters, result filters, and exception filters to handle errors at the controller level. Global error handling can also be achieved by registering these filters globally in the Global.asax file.

a. Registering Filters Globally

In the Global.asax file, use the RegisterGlobalFilters method to add an exception filter globally:

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
    }
}

public static class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
        filters.Add(new CustomHandleErrorAttribute());
    }
}

b. Custom Exception Filter

You can create a custom exception filter that inherits from HandleErrorAttribute to handle errors globally:

public class CustomHandleErrorAttribute : HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        Exception exception = filterContext.Exception;

        // Log the exception
        LogException(exception);

        filterContext.ExceptionHandled = true; // Marks the exception as handled

        // Redirect to error view
        if (exception != null)
        {
            filterContext.Result = new ViewResult()
            {
                ViewName = "GenericError"
            };
        }

        base.OnException(filterContext);
    }

    private void LogException(Exception ex)
    {
        // Implement your logging logic here
        // For example: writing to a file, database, or external logging service
        File.AppendAllText("ErrorLog.txt", DateTime.Now.ToString() + " - " + ex.Message + Environment.NewLine);
    }
}
  • HandleErrorAttribute: A built-in filter to handle exceptions.
  • CustomHandleErrorAttribute: A custom implementation that logs exceptions and redirects users to an error page.

4. Application-Level Error Handling

The Application_Error method in the Global.asax file acts as a global handler for unhandled exceptions.

protected void Application_Error(object sender, EventArgs e)
{
    Exception exception = Server.GetLastError();

    if (exception != null)
    {
        // Log the exception
        LogException(exception);

        // Clear the error from server
        Server.ClearError();

        // Redirect to error page
        Response.Redirect("/Error/GenericError");
    }
}

private void LogException(Exception ex)
{
    // Implement your logging logic here
    File.AppendAllText("ErrorLog.txt", DateTime.Now.ToString() + " - " + ex.Message + Environment.NewLine);
}
  • Server.GetLastError(): Retrieves the last unhandled exception.
  • Server.ClearError(): Clears the exception from the server, preventing ASP.NET from bubbling it up to the browser.
  • Response.Redirect(): Redirects to a custom error page.

5. Implementing a Custom Error Controller

Create an ErrorController to handle specific error views. This approach keeps your error handling logic centralized and organized.

public class ErrorController : Controller
{
    // GET: Error/GenericError
    public ActionResult GenericError()
    {
        return View();
    }

    // GET: Error/NotFound
    public ActionResult NotFound()
    {
        Response.StatusCode = 404;
        return View("NotFound");
    }

    // GET: Error/ServerError
    public ActionResult ServerError()
    {
        Response.StatusCode = 500;
        return View("ServerError");
    }
}
  • GenericError: Handles generic errors.
  • NotFound: Handles 404 errors.
  • ServerError: Handles 500 errors.

6. Creating Error Views

Create corresponding views for each error action in the Error controller. These views will be displayed to users when an error occurs.

GenericError.cshtml

<!DOCTYPE html>
<html>
<head>
    <title>Error</title>
</head>
<body>
    <h1>An error occurred</h1>
    <p>We apologize for the inconvenience. Our team is working to resolve the issue.</p>
    <p>Please try reloading the page or contacting support if the problem persists.</p>
</body>
</html>

NotFound.cshtml

<!DOCTYPE html>
<html>
<head>
    <title>Page Not Found</title>
</head>
<body>
    <h1>404 Error: Page Not Found</h1>
    <p>The page you are looking for does not exist.</p>
    <p>Please check the URL and try again.</p>
</body>
</html>

ServerError.cshtml

<!DOCTYPE html>
<html>
<head>
    <title>Server Error</title>
</head>
<body>
    <h1>500 Error: Server Error</h1>
    <p>An unexpected error has occurred on our server.</p>
    <p>Please try reloading the page or contacting support if the problem persists.</p>
</body>
</html>

7. Testing Error Handling

Testing your error handling setup is crucial to ensure everything is working as expected.

a. Simulate Unhandled Exceptions

You can simulate an unhandled exception in a controller action to test your global exception handling:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        throw new Exception("Simulated Exception");

        return View();
    }
}

Accessing this action should redirect you to the GenericError page, demonstrating that the exception was caught by Application_Error and handled appropriately.

b. Simulate HTTP Errors

To test HTTP errors, you can deliberately call a non-existent route or pass an unsupported method.

public class HomeController : Controller
{
    [HttpGet] // Only handles GET requests
    public ActionResult Detail(string id)
    {
        // Assume the id is required
        if (string.IsNullOrEmpty(id))
        {
            throw new HttpException(400, "Bad Request");
        }

        return View();
    }
}

Accessing this action with a missing id should result in a 400 Bad Request, which is caught by your custom error handling setup, redirecting to a relevant error page.

8. Advanced Considerations

a. Logging

Implement a robust logging mechanism to capture detailed information about exceptions. This can include stack traces, user information, and timestamp. Libraries like NLog, log4net, or Serilog can be used for advanced logging.

b. Email Notifications

Set up email notifications to alert the development team or administrators when critical exceptions occur. This can be achieved by adding email sending logic in your global error handling methods.

c. Error Pages for Different Environments

Consider showing different error messages or levels of detail based on the environment (development, staging, production). This can be controlled via configuration settings.

d. AJAX Error Handling

For AJAX requests, it’s important to handle errors gracefully without redirecting the entire page. The error filter can be adjusted to return JSON responses for AJAX requests:

public class CustomHandleErrorAttribute : HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        Exception exception = filterContext.Exception;

        if (exception != null && filterContext.HttpContext.Request.IsAjaxRequest())
        {
            filterContext.Result = new JsonResult
            {
                JsonRequestBehavior = JsonRequestBehavior.AllowGet,
                Data = new { success = false, message = "An unexpected error occurred" }
            };

            filterContext.ExceptionHandled = true;
        }

        base.OnException(filterContext);
    }
}

e. Custom Response Status Codes

Ensure that appropriate HTTP response status codes are returned for different types of errors to help search engines and clients understand why a request failed.

Conclusion

Implementing global error handling in ASP.NET MVC is essential for creating reliable and user-friendly web applications. By leveraging the web.config, custom filters, and the Application_Error method, you can effectively manage different types of errors across your application. Additionally, creating a dedicated Error controller and implementing detailed logging and notification mechanisms will further enhance your error handling strategy.

By following this guide, you should be well-equipped to handle errors gracefully in your ASP.NET MVC applications, providing a more robust and user-friendly experience.