IIS обслуживает страницу пользовательской ошибки как обычный текст, без заголовка содержимого

UPD: вот полное решение для обработки ошибок

У меня есть простой веб-проект vanilla MVC4. Ничего не добавлено, ничего не удалено, просто создал новый проект в Visual Studio.

В web.config Я добавил пользовательский обработчик страницы ошибок:

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

а файл ~/Content/Error.htm:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>OOPS! Error Occurred. Sorry about this.</title>
</head>
<body>
    <h2>OOPS! Error Occurred</h2>
</body>
</html>

Всякий раз, когда я получаю ошибку 404 на сайте, Error.htm используется как открытый текст в Firefox и Chrome:

HTML is displayed as plain text

Fiddler говорит, что страница с ошибкой подается без заголовка content-type, который заставляет браузеры отображать страницу как обычный текст:

No Content-type header

Есть ли способ заставить страницы ошибок сервера IIS с заголовком content-type

p.s. фактическая проблема заключается в сложном проекте MVC4, который имеет собственную обработку ошибок в Global.asax. Но я обнаружил, что некоторые ошибки не проходят через ASP-канал и обрабатываются только IIS. Как точка в конце URL. Решение с < httpErrors/" > выполняет корректные ответы, но наша настраиваемая обработка ошибок в Global.asax, Application_Error() не вызвана таким образом.

UPD Кажется, я не могу победить в этой войне. IE показывает, что html правильно отображается, Firefox и Chrome отображаются как обычный текст. Когда я переключаюсь на обычный текст, Firefox и IE корректно показывают пустое пространство, IE поглощает пустое пространство и пытается отобразить html. Если я попробую показать изображение как страницу с ошибкой, Firefox и Chrome покажут изображение. IE показывает это: IE9 is on crack! Facepalm!

Ответ 1

Используйте .aspx вместо .htm для страниц ошибок (переименуйте htm в aspx).

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

Ответ 2

По-видимому, <customErrors> - беспорядок, чтобы работать. Если вы полны решимости использовать его, Бен Фостер отлично разбирается в этой теме: http://benfoster.io/blog/aspnet-mvc-custom-error-pages

Если вы хотите использовать страницы .cshtml, лучший выбор - это, возможно, вырезать <customErrors> и обрабатывать ошибки в 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));
    }
}

Конечно, вам также необходимо добавить ErrorController с соответствующими методами и представлениями .cshtml.

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

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

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

Ответ 3

Это известная ошибка, очевидно, и предложение Microsoft соответствует идее spiatrax о переименовании htm/html в aspx. В моем случае я также должен был включить

<% Response.StatusCode = 400 %>

на странице .aspx.

Для дополнительной информации: http://connect.microsoft.com/VisualStudio/feedback/details/507171/

Ответ 4

Я добавил заголовок типа контента в пользовательский заголовок в разделе system.webServer/httpprotocol, и это исправило его.

<customHeaders><remove name="Content-Type" /><add name="ContentType"value="text/html" /></customHeaders>