In previous article I shown you how to use log4net to log errors and redirect to custom error page. The problem in this approach is redirection. It’s not good for SEO to make redirection to custom error page.

I found better way to handle and log errors with custom error pages. It’s simple and elegant, and what is more important works perfect for MVC.
First we should switch off custom error pages in <system.web> section:

<system.web>
	…
	<customErrors mode="Off" />
	…
</system.web>

And then enable it <system.webServer> section:

<system.webServer>
	…
	<!-- Custom Error Pages -->
	<httpErrors errorMode="Detailed" existingResponse="Replace">
	  <remove statusCode="404" subStatusCode="-1" />
	  <remove statusCode="500" subStatusCode="-1" />
	  <error statusCode="404" path="/Error/404" responseMode="ExecuteURL" />
	  <error statusCode="500" path="/Error" responseMode="ExecuteURL" />
	</httpErrors>
</system.webServer>

Here we are telling IIS replace all responses with status code 404 with page /Error/404. All other responses with application errors replace with page /Error.

And yes, that’s it. IIS will show our custom error pages (will not change URL and show appropriate status code), log it to server AND still trigger Application_Error function where we can log the error.

Few important notes:

  1. To able to overwrite global settings in global IIS settings (file: C:\Windows\System32\inetsrv\config \applicationHost.config) should be: <section name="httpErrors" overrideModeDefault="Allow" />
  2. In Application_Error function do not erase error from server: Server.ClearError();
  3. For high performance and safety I would recommend static files for custom error pages: Example:
<system.webServer>
	…
	<!-- Custom Error Pages -->
	<httpErrors errorMode="Detailed" existingResponse="Replace">
	  <remove statusCode="404" subStatusCode="-1" />
	  <remove statusCode="500" subStatusCode="-1" />
	  <error statusCode="404" path="Error404.htm" responseMode="File" />
	  <error statusCode="500" path="Error.htm" responseMode="File" />
	</httpErrors>
</system.webServer>
  1. If you want to show error page – use HttpException method. Example:
public ActionResult Index(string URL) {
	Article article = db.Articles.FirstOrDefault(a => a.URL.Equals(URL, StringComparison.CurrentCultureIgnoreCase));
	if (article != null)
		return View(article);
	else
		throw new HttpException(404, "Article not found");
	}