I wouldn't recommend to use Global.asax, unless you have some custom logic going on. I'd recommend using web.config. Just be aware that, since MVC uses routes instead of physical files you should use something like this in the web.config:
<httpErrors errorMode="Custom">
<remove statusCode="404"/>
<error statusCode="404" path="/error/404" responseMode="ExecuteUrl"/>
<httpErrors>
But in case you want to call some physical file (html, for example) you should use it in this way:
<httpErrors errorMode="Custom">
<remove statusCode="404"/>
<error statusCode="404" path="/erro404.html" responseMode="File"/>
<httpErrors>
Now, going back to the custom logic. If you really need to use Global.asax I'd recommend you to use something like this:
protected void Application_Error(object sender, EventArgs e)
{
Exception exception = Server.GetLastError();
Response.Clear();
HttpException httpException = exception as HttpException;
RouteData routeData = new RouteData();
routeData.Values.Add("controller", "Error");
if (httpException == null)
{
routeData.Values.Add("action", "Index");
}
else //It's an Http Exception, Let's handle it.
{
switch (httpException.GetHttpCode())
{
case 404:
// Page not found.
routeData.Values.Add("action", "HttpError404");
break;
case 500:
// Server error.
routeData.Values.Add("action", "HttpError500");
break;
// Here you can handle Views to other error codes.
// I choose a General error template
default:
routeData.Values.Add("action", "General");
break;
}
}
// Pass exception details to the target error View.
routeData.Values.Add("error", exception);
// Clear the error on server.
Server.ClearError();
// Avoid IIS7 getting in the middle
Response.TrySkipIisCustomErrors = true;
// Call target Controller and pass the routeData.
IController errorController = new ErrorController();
errorController.Execute(new RequestContext(
new HttpContextWrapper(Context), routeData));
}