Web.config customErrors element with ASP.NET explained
Tags: csharp, dotnet, aspnet
Published: 2020-05-06 07:12:34

---
title: Web.config customErrors element with ASP.NET explained
published: true
description: Learn everything you need to know about showing custom error pages in ASP.NET and MVC using the customErrors element in your web.config file.
tags: csharp, dotnet, aspnet
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/39pfi1ph5e7gt5nty19d.png
canonical_url: https://blog.elmah.io/web-config-customerrors-element-with-aspnet-explained/
---

The `CustomErrors` element inside an ASP.NET/MVC/Web API `Web.config` file, is something almost everyone uses somehow, however, many people’s experiences don’t work like they expect. During my years coding primarily ASP.NET MVC, I've used the custom errors element again and again. I have also spent countless hours Googling issues and browsing through StackOverflow. This post is an attempt to put down all of the things I have learned on "paper," so you can avoid having to go through the same pain I did.

Let's start by discussing what we can do with the `customErrors` element. When errors happen on your ASP.NET application, you want to tell the user that an error happened. Out of the box, ASP.NET provides an error page often referred to as the "Yellow Screen of Death" (YSoD):

![](https://blog.elmah.io/content/images/2019/04/ysod.png)

The YSoD is the default fallback when no custom error page has been configured. YSoD works after deploying it to another server, but it looks different:

![](https://blog.elmah.io/content/images/2019/04/ysod-remote.png)

It's the same page, but one is accessed through localhost and the other through a remote name. ASP.NET hides an application’s specific details like the stack trace, file locations, .NET version, etc., as a security feature. While the first example is quite fine when running locally and where you want to track down errors, the second is not very user friendly.

Before we start digging down into custom error pages, let me put a few words in on the possibilities listed in the screenshot above. As mentioned, you can add the following to the `system.web` element:

```xml
<configuration>
  <system.web>
    <customErrors mode="Off"/>
    ...
  </system.web>
  ...
</configuration>
```

Doing so will give you the detailed error message from the first screenshot, even when running in production. This approach is used by some developers while setting up the production environment or if everything fails.

> I discourage you from disabling custom errors on the production environment. Everyone will be able to inspect details about your application that could be potential fuel for hackers. Always use an error logging solution (like ELMAH or [elmah.io](https://elmah.io/?utm_source=devto&utm_medium=social&utm_campaign=devtoposts)) instead, since they will log the details and still only show the generic error message to the user.

Finally, let's talk about some custom errors. So what exactly is a custom error? Actually, it's just an HTML (typically) document like everything else. The page should explain to the user that something went wrong and it's preferable to help the user move on by either proposing alternatives or giving them a way to contact support.

Different versions of ASP.NET come with different features. I'll explain how MVC defines error pages later in this post, and why I'll focus on ASP.NET WebForms first. We have already seen a possible value of the `mode` attribute (`mode="Off"`). To enable an error page, set the value to On and specify an error page in the `defaultRedirect` attribute:

```xml
<configuration>
  <system.web>
    <customErrors mode="On" defaultRedirect="~/Error.aspx"/>
    ...
  </system.web>
  ...
</configuration>
```

When an exception occurs, ASP.NET will automatically redirect the user to `/Error?aspxerrorpath=/default.aspx`.  The `aspxerrorpath` parameter is appended to the URL specified in `defaultRedirect` to help identify the page that caused the error. If you want ASP.NET to keep the user on the failing URL, but still show the error page, you can use the `redirectMode` attribute:

```xml
<configuration>
  <system.web>
    <customErrors mode="On" defaultRedirect="~/Error.aspx" redirectMode="ResponseRewrite"/>
    ...
  </system.web>
  ...
</configuration>
```

When setting `redirectMode` to `ResponseRewrite` the error page is shown, but the URL stays on `/Default.aspx` (which is the page where I'm throwing an exception). If you want to go back to the old behavior, either remove the `redirectMode` attribute or set it to `ResponseRedirect`.

If you are coding along you may have noticed that ASP.NET now shows the custom error page when running localhost. If you are using [elmah.io](https://elmah.io?utm_source=devto&utm_medium=social&utm_campaign=devtoposts) or something similar to inspect your errors, this may not be a problem. But in most cases, having the YSoD when running locally is a huge advantage. To get this behavior, set `mode` to `RemoteOnly`:

```xml
<configuration>
  <system.web>
    <customErrors mode="RemoteOnly" defaultRedirect="~/Error.aspx"/>
    ...
  </system.web>
  ...
</configuration>
```

As expected, ASP.NET now only redirects the user to the error page if the web application is accessed on a remote name other than `localhost`.

Another feature worth mentioning is the option of having multiple error pages. You may have a "funny" 404 page and another page reassuring users who experience a 500 that you are indeed looking at the error. To do just this, use `error` child elements:

```xml
<configuration>
  <system.web>
    <customErrors mode="RemoteOnly" defaultRedirect="~/Error.aspx">
      <error statusCode="404" redirect="~/Notfound.aspx" />
    </customErrors>
    ...
  </system.web>
  ...
</configuration>
```

The added `error` element tells ASP.NET to redirect the user to `/Notfound.aspx` if an exception is thrown and the status code is `404`. You can define multiple `error` elements with each "listening" for an individual status code. If the returned status code doesn't match one already specified in an `error` element, ASP.NET uses the value in `defaultRedirect` as a fallback.

## ASP.NET MVC

ASP.NET MVC introduces new features for custom error pages, but everything is still built on top of the ASP.NET pipeline. When creating a new project using the template available in Visual Studio, you get an error page generated (`Views/Shared/Error.cshtml`) which you can style to meet your needs. The page is triggered using a combination of setting `mode` to On or `RemoteOnly` in `web.config` (as shown multiple times already) and by adding the MVC filter `HandleErrorAttribute` either on individual controllers and/or actions or simply as a global filter in `FilterConfig.cs`:

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

This kind of custom error page can be fine for simple projects. However, in real life you want to look into something more elaborate since the `HandleErrorAttribute` only handles errors that happen within the context of MVC (`500`s basically).

Another downside of using the `HandleErrorAttribute` is that it may end up swallowing exceptions. This means that error logging platforms like ELMAH and [elmah.io](https://elmah.io?utm_source=devto&utm_medium=social&utm_campaign=devtoposts) don't work as intended. To overcome this, people have been specifying their own specialization of the `HandleErrorAttribute` that logs the error to ELMAH as [discussed here](https://stackoverflow.com/questions/766610/how-to-get-elmah-to-work-with-asp-net-mvc-handleerror-attribute). If you MUST use the error attribute available in MVC, I recommend you use Alexander Beletsky's `Elmah.MVC` package, which automatically handles this issue for you. In case you are an [elmah.io](https://elmah.io?utm_source=devto&utm_medium=social&utm_campaign=devtoposts) user, install the `Elmah.Io.Mvc` package. This package installs the `Elmah.MVC` package to make everything run smoothly.

We use ASP.NET MVC on [elmah.io](https://elmah.io?utm_source=devto&utm_medium=social&utm_campaign=devtoposts) for some of our applications (we want to migrate everything to ASP.NET Core eventually, but we are not there yet). In those projects we have settled on a solution very similar to the one shown when discussing ASP.Net WebForms. This means we are not using the `HandleErrorAttribute` anywhere. Instead, we have defined a new controller named `StatusCodeController`:

```csharp
public class StatusCodeController : Controller
{
    public ActionResult NotFound()
    {
        return View();
    }

    public ActionResult InternalServerError()
    {
        return View();
    }
}
```

In the `web.config` file we use the routes given by MVC:

```xml
<configuration>
  <system.web>
    <customErrors mode="RemoteOnly" defaultRedirect="/statuscode/internalservererror">
      <error statusCode="404" redirect="/statuscode/notfound" />
    </customErrors>
    ...
  </system.web>
  ...
</configuration>
```

Setting up custom error pages like this, ensures that any errors thrown in our application are redirecting to the correct error page.

## Would your users appreciate fewer errors?

elmah.io is the easy error logging and uptime monitoring service for .NET. Take back control of your errors with support for all .NET web and logging frameworks.

➡️ [Error Monitoring for .NET Web Applications](https://elmah.io/?utm_source=devto&utm_medium=social&utm_campaign=devtoposts) ⬅️

This article first appeared on the elmah.io blog at https://blog.elmah.io/web-config-customerrors-element-with-aspnet-explained/