ASP.NET Custom 404 возвращает 200 OK вместо 404 Not Found
-
19-08-2019 - |
Вопрос
После попытки настроить свой сайт для Инструментов Google для веб-мастеров я обнаружил, что моя пользовательская страница ASP.NET 404 не возвращает код состояния 404.Он отобразил правильную пользовательскую страницу и сообщил браузеру, что все в порядке.Это считается мягким 404 или ложным 404.Гуглу это не нравится.Итак, я нашел много статей по этой проблеме, но решение, которое мне нужно, похоже, не сработало.
Решение, над которым я хочу работать, — это добавить следующие две строки в код метода Page_Load пользовательской страницы 404.
Response.Status = "404 Not Found";
Response.StatusCode = 404;
Это не работает.Страница по-прежнему возвращает 200 ОК.Однако я обнаружил, что если я жестко закодирую следующий код в коде дизайна, он будет работать правильно.
<asp:Content ID="ContentMain" ContentPlaceHolderID="ContentPlaceHolderMaster" runat="server">
<%
Response.Status = "404 Not Found";
Response.StatusCode = 404;
%>
... Much more code ...
</asp:content>
Страница использует главную страницу.И я настраиваю собственные страницы ошибок в своем web.config.Я бы предпочел использовать опцию «код позади», но, похоже, я не могу заставить ее работать без добавления встроенного кода взлома в дизайн/макет.
Решение
Решение:
Проблема, как оказалось, заключалась в использовании главной страницы.Я заставил его работать, установив код состояния позже в жизненном цикле страницы. Очевидно, что рендеринг главной страницы сбрасывал его, поэтому я переопределил метод рендеринга и установил его после завершения рендеринга.
protected override void Render(HtmlTextWriter writer)
{
base.Render(writer);
Response.StatusCode = 404;
}
Можно было бы проделать дополнительную работу, чтобы выяснить, когда именно главная страница устанавливает статус, но я оставлю это вам.
Исходное сообщение:
Мне удалось заставить тестовое веб-приложение работать нормально, ну, по крайней мере, оно отображало пользовательскую страницу ошибок и возвращало код состояния 404.Я не могу сказать вам, что не так с вашим приложением, но могу сказать, что я сделал:
1) Отредактировал web.config на предмет пользовательских ошибок:
<customErrors mode="On"> <error statusCode="404" redirect="404.aspx"/> </customErrors>
2) Добавлена страница 404.aspx и установлен код состояния 404.
public partial class _04 : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { Response.StatusCode = 404; } }
Вот и все: если я перейду к любому расширению страницы, которое обрабатывается Asp.Net и не существует, мой журнал скрипача четко показывает 404, вот заголовок:
HTTP/1.1 404 Not Found Server: Microsoft-IIS/5.1 Date: Sun, 07 Dec 2008 06:04:13 GMT X-Powered-By: ASP.NET X-AspNet-Version: 2.0.50727 Cache-Control: private Content-Type: text/html; charset=utf-8 Content-Length: 533
Теперь, если я перейду на страницу, которая не обрабатывается Asp.Net, например, файл htm, пользовательская страница не отображается и отображается ошибка 404, настроенная IIS.
Вот сообщение, в котором подробно описываются некоторые подробности, которые могут быть полезны вам и вашей проблеме. Мой тест выполняет перенаправление на новую страницу, поэтому URL-адрес запрошенного файла практически теряется (за исключением его в строке запроса) .
Пользовательские страницы ошибок Google 404 и .NET
Ответ шпиона по заголовку:
HTTP/1.1 404 Not Found
Date: Sun, 07 Dec 2008 06:21:20 GMT
Другие советы
У меня была похожая проблема, я хочу показать пользовательскую страницу как 404 (то есть ASPX), и она работала нормально на localhost, но как только удаленный посетитель подключился, они получили общий IIS 404.
Решением этой проблемы было добавить
Response.TrySkipIisCustomErrors = true;
Перед изменением Response.StatusCode.
Найдено через Рика Стрэла http://www.west-wind.com/ блог / сообщений / 745738.aspx
Решение IIS 7 состоит в том, чтобы просто добавить это в файл web.config:
<system.webServer>
<httpErrors existingResponse="Replace">
<remove statusCode="500" subStatusCode="-1" />
<remove statusCode="404" subStatusCode="-1" />
<error statusCode="404" prefixLanguageFilePath="" path="404.htm" responseMode="File" />
<error statusCode="500" prefixLanguageFilePath="" path="500.htm" responseMode="File" />
</httpErrors>
</system.webServer>
Попробуйте вызвать Response.End (), чтобы пропустить рендеринг ...
Response.Status = "404 Not Found";
Response.StatusCode = 404;
Response.End();
return;
После длительного тестирования и устранения неполадок выясняется, что некоторые хостинг-провайдеры могут вмешиваться в код возврата. Я смог обойти это, применив & Quot; hack & Quot; в содержании.
<%
// This code is required for host that do special 404 handling...
Response.Status = "404 Not Found";
Response.StatusCode = 404;
%>
Это позволит странице возвращать правильный код возврата, несмотря ни на что.
Мне удалось обойти эту проблему с помощью следующей настройки в веб-формах asp.net с использованием .NET 3.5.
Шаблон, который я реализовал, обходит пользовательское решение перенаправления .NET в web.config, так как я написал свой собственный для обработки всех сценариев с правильным кодом состояния HTTP в заголовке.
Во-первых, раздел customErrors в web.config выглядит следующим образом:
<customErrors mode="RemoteOnly" defaultRedirect="~/error.htm" />
Эта настройка гарантирует, что режим CustomErrors включен, этот параметр нам понадобится позже, и предоставляет опцию all-else-fails для defaultRedirect файла error.htm. Это пригодится, когда у меня нет обработчика для конкретной ошибки или что-то вроде разрыва соединения с базой данных.
Во-вторых, вот глобальное событие asax Error:
protected void Application_Error(object sender, EventArgs e)
{
HandleError();
}
private void HandleError()
{
var exception = Server.GetLastError();
if (exception == null) return;
var baseException = exception.GetBaseException();
bool errorHandled = _applicationErrorHandler.HandleError(baseException);
if (!errorHandled) return;
var lastError = Server.GetLastError();
if (null != lastError && HttpContext.Current.IsCustomErrorEnabled)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(lastError.GetBaseException());
Server.ClearError();
}
}
Этот код передает ответственность за обработку ошибки другому классу. Если ошибка не обрабатывается и CustomErrors включен, это означает, что у нас есть случай, когда мы находимся в производстве, и каким-то образом ошибка не была обработана. Мы очистим его здесь, чтобы пользователь не увидел его, но войдите в систему в Elmah, чтобы мы знали, что происходит.
Класс applicationErrorHandler выглядит следующим образом:
public bool HandleError(Exception exception)
{
if (exception == null) return false;
var baseException = exception.GetBaseException();
Elmah.ErrorSignal.FromCurrentContext().Raise(baseException);
if (!HttpContext.Current.IsCustomErrorEnabled) return false;
try
{
var behavior = _responseBehaviorFactory.GetBehavior(exception);
if (behavior != null)
{
behavior.ExecuteRedirect();
return true;
}
}
catch (Exception ex)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}
return false;
}
Этот класс по существу использует шаблон команды, чтобы найти соответствующий обработчик ошибок для типа возникшей ошибки. На этом уровне важно использовать Exception.GetBaseException (), потому что почти каждая ошибка будет заключена в исключение более высокого уровня. Например, выполните & Quot; throw new System.Exception () & Quot; с любой страницы aspx приведет к получению исключения HttpUnhandledException на этом уровне, а не System.Exception.
" factory " код прост и выглядит так:
public ResponseBehaviorFactory()
{
_behaviors = new Dictionary<Type, Func<IResponseBehavior>>
{
{typeof(StoreException), () => new Found302StoreResponseBehavior()},
{typeof(HttpUnhandledException), () => new HttpExceptionResponseBehavior()},
{typeof(HttpException), () => new HttpExceptionResponseBehavior()},
{typeof(Exception), () => new Found302DefaultResponseBehavior()}
};
}
public IResponseBehavior GetBehavior(Exception exception)
{
if (exception == null) throw new ArgumentNullException("exception");
Func<IResponseBehavior> behavior;
bool tryGetValue = _behaviors.TryGetValue(exception.GetType(), out behavior);
//default value here:
if (!tryGetValue)
_behaviors.TryGetValue(typeof(Exception), out behavior);
if (behavior == null)
Elmah.ErrorSignal.FromCurrentContext().Raise(
new Exception(
"Danger! No Behavior defined for this Exception, therefore the user might have received a yellow screen of death!",
exception));
return behavior();
}
В конце концов, у меня есть расширяемая схема обработки ошибок. В каждом из & Quot; поведения & Quot; это определено, у меня есть пользовательская реализация для типа ошибки. Например, исключение Http будет проверено на наличие кода состояния и обработано соответствующим образом. Код состояния 404 потребует Server.Transfer вместо Request.Redirect вместе с соответствующим кодом состояния, записанным в заголовке.
Надеюсь, это поможет.