We use cookies for keeping user sessions alive and for site usage statistics.
Please accept cookies to continue browsing the site.


(You can decline cookies later navigating to page 'Privacy Policy'.)

Global error handling in ASP.NET MVC

To be correct to our visitors and the search engines, we should return meaningful HTTP status codes if errors occur, facing our site. It's not fair to return HTTP status code 200 on error, even if at the same time we return a view, explaining that an error occurred. if the user types in an incorrect address (the most frequent user fault), we should return HTTP status code 404 and not return or redirect to a View, where status code 200 will be returned.

Here we come to the MVC global error handling basic rules considering custom errors settings in Web.config and global error filters in Global.asax.cs:


1. Have HandleErrorAttribute registered in your Global.asax.cs.

public static void RegisterGlobalFilters(GlobalFilterCollection filters) {
    filters.Add(new HandleErrorAttribute());

In fact, it is there by default, called in Application_Start(). Don't remove it. Otherwise the framework will display it's fallback message "Server Error in '/' Application...".

By default above filter captures HTTP errors 500 and displays the /Views/Shared/Error.cshtml view, but you can customize it setting the View property like filters.Add(new HandleErrorAttribute()){View="AnotherView"}.


2. Have the customErrors settings in Web.config.

<customErrors mode="On" defaultRedirect="~/ErrorGeneric.htm" redirectMode="ResponseRewrite">
    <error statusCode="404" redirect="~/Error404.htm" />
    <error statusCode="405" redirect="~/Error405.htm" />

This is required for the filter under (1) to work properly. Besides, this is the way to handle errors outside of controller actions, e.g. incorrect path in the address bar. And, again, to avoid the fallback message "Server error in '/' Application...".

Note that we are having redirectMode="ResponseRewrite", not "ResponseRedirect". Direct error indication is better than redirecting. Besides, redirecting is prone to unsuitable http status codes returned.

Exception: Depending on MVC version you may get .htm content displayed as flat text by browsers, not rendered as HTML. If so, then just rename above .htm files to .aspx, not .cshtml. (This is a workaround for a bug, don't be so astonished. We need a correct 'content-type' header and this is resolved by using .aspx. Hope this changes in the future.)

Special case: Http error 500 is not captured by Application_Error(), but by the HandleError filter as explained in previous topic. Rather leave it as is, it's for the special case of really unexpected, hard to control application errors. But if you yet definitely want error 500 to be handled as a custom error, then

create a custom error handler like this:
public class CustomHandleErrorAttribute : HandleErrorAttribute {
    public override void OnException(ExceptionContext filterContext) {
and invoke it accordingly in RegisterGlobalFilters(), replacing the default handler:
public static void RegisterGlobalFilters(GlobalFilterCollection filters) {
    // ....
    filters.Add(new CustomHandleErrorAttribute());
    // ....
Finally adapt the custom error handling entries in web.config, if desired.

3. Set the HTTP response status code in Global.asax.cs.

protected void Application_Error() {
    var exception = Server.GetLastError();
    if(exception is HttpException) {
        var httpException = (HttpException)exception;
        Response.StatusCode = httpException.GetHttpCode();
This is the most important part - set fair HTTP response status code, not just 200.

Exception to above rules: Where the game is fully under your control, e.g. the user can request an item from a list and enters a wrong identification, you can call a dedicated view from within your code, but setting status code 404 is highly recommended in this case, too.

Fair play is paying off!

Back to List