ASP.NET Custom 404 Возврат 200 OK вместо 404 не найден
После попытки настроить мой сайт для Инструментов Google для веб-мастеров, я обнаружил, что моя пользовательская страница ASP.NET 404 не возвращала код статуса 404. Он отобразил правильную страницу и сказал браузеру, что все в порядке. Это считается мягким 404 или ложным 404. Google не нравится это. Поэтому я нашел много статей по этой проблеме, но решение, которое я хочу, похоже, не работает.
Решение, которое я хочу использовать, заключается в добавлении следующих двух строк в код, стоящий за методом Page_Load на пользовательской странице 404.
Response.Status = "404 Not Found";
Response.StatusCode = 404;
Это не работает. Страница все еще возвращает 200 OK. Однако я обнаружил, что если я буду жестко закодировать следующий код в код проекта, он будет работать правильно.
<asp:Content ID="ContentMain" ContentPlaceHolderID="ContentPlaceHolderMaster" runat="server">
<%
Response.Status = "404 Not Found";
Response.StatusCode = 404;
%>
... Much more code ...
</asp:content>
Страница использует мастер-страницу. И я настраиваю страницы пользовательских ошибок в моем web.config. Я бы предпочел использовать код позади опции, но я не могу заставить его работать, не вставляя строчный код взлома в дизайн/макет.
Ответы
Ответ 1
Решение:
Проблема, оказалось, заключалась в использовании главной страницы. Я получил его для работы, установив код состояния позже в жизненном цикле страниц, очевидно, что рендеринг главной страницы сбрасывал его, поэтому я переопределил метод рендеринга и установил его после завершения рендеринга.
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 и не существует, в моем журнале fiddler явно отображается 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
Ответ 2
У меня была аналогичная проблема: я хочу показать пользовательскую страницу как 404 (это ASPX), и она отлично работала на localhost, но как только удаленный посетитель подключился, они получат общий IIS 404.
Решением этого было добавить
Response.TrySkipIisCustomErrors = true;
Перед изменением кода Response.StatusCode.
Найдено через Рик Страл http://www.west-wind.com/weblog/posts/745738.aspx
Ответ 3
Решение 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>
http://forums.asp.net/t/1563128.aspx/1
Ответ 4
Попробуйте вызвать Response.End(), чтобы пропустить рендеринг...
Response.Status = "404 Not Found";
Response.StatusCode = 404;
Response.End();
return;
Ответ 5
После долгих испытаний и устранения неполадок выясняется, что некоторые хостинг-провайдеры могут помешать обратному коду. Я смог обойти это, применив "хак" в контенте.
<%
// This code is required for host that do special 404 handling...
Response.Status = "404 Not Found";
Response.StatusCode = 404;
%>
Это позволит странице вернуть правильный код возврата независимо от того, что.
Ответ 6
Мне удалось обойти эту проблему, используя следующую настройку в веб-форматах asp.net с помощью .NET 3.5.
Образец, который я реализовал, обходит .NET custom redirect solution в web.config, поскольку я написал свой собственный, чтобы обрабатывать все сценарии с правильным кодом статуса HTTP в заголовке.
Сначала раздел customErrors web.config выглядит следующим образом:
<customErrors mode="RemoteOnly" defaultRedirect="~/error.htm" />
Эта настройка гарантирует, что режим CustomErrors включен, параметр, который нам понадобится позже, и предоставит параметр all-else-fail для 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 включен, это означает, что у нас есть случай, когда мы работаем, и как-то ошибка не была обработана. Мы очистим его здесь, чтобы пользователь не мог его видеть, но запишите его в Эльма, чтобы мы знали, что происходит.
Класс 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() на этом уровне, потому что почти каждая ошибка будет обернута в исключение более высокого уровня. Например, выполнение "throw new System.Exception()" с любой страницы 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();
}
В конце концов, у меня есть расширяемая схема обработки ошибок. В каждом из определенных "вариантов поведения" у меня есть специальная реализация для типа ошибки. Например, исключение Http будет проверяться для кода состояния и обрабатываться соответствующим образом. Код статуса 404 потребует Server.Transfer вместо Request.Redirect вместе с соответствующим кодом состояния, записанным в заголовке.
Надеюсь, что это поможет.
Ответ 7
Вы можете использовать следующий код:
Response.TrySkipIisCustomErrors = True
Response.Status = "404 Not Found"
Response.AddHeader("Location", "{your-path-to-your-404-page}")