IIS Serves Custom Error page as plain text, no content-type header

This is a known bug apparently and Microsoft's suggestion is in line with spiatrax's idea of renaming htm/html to aspx. In my case I also had to include

<% Response.StatusCode = 400 %>

in the .aspx page.

For more information: http://connect.microsoft.com/VisualStudio/feedback/details/507171/


Apparently, <customErrors> is a mess to get working. If you're determined to use it, Ben Foster has a great write-up on the subject: http://benfoster.io/blog/aspnet-mvc-custom-error-pages

If you want to use .cshtml pages, your best bet is probably to ditch <customErrors> and handle errors in Global.asax.cs:

protected void Application_Error(object sender, EventArgs e)
{
    var exception = Server.GetLastError();
    if (exception != null)
    {
        Response.Clear();
        HttpException httpException = exception as HttpException;
        RouteData routeData = new RouteData();
        routeData.Values.Add("controller", "Error");
        if (httpException == null)
        {
            routeData.Values.Add("action", "Unknown");
        }
        else
        {
            switch (httpException.GetHttpCode())
            {
                case 404:               // Page not found.
                    routeData.Values.Add("action", "NotFound");
                    break;

                default:
                    routeData.Values.Add("action", "Unknown");
                    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;
        // Ensure content-type header is present
        Response.Headers.Add("Content-Type", "text/html");
        // Call target Controller and pass the routeData.
        IController errorController = new ErrorController();
        errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
    }
}

Of course, you would also need to add an ErrorController with the appropriate methods and .cshtml views.

public class ErrorController : Controller
{
    public ActionResult Index()
    {// your implementation
    }

    public ActionResult Unknown(Exception error)
    {// your implementation 
    }

    public ActionResult NotFound(Exception error)
    {// your implementation         
    }
}

Use .aspx instead of .htm for error pages (rename htm to aspx).

<customErrors mode="On" defaultRedirect="~/Content/Error.aspx" redirectMode="ResponseRewrite" />