ASP.NET personalizado 404 Retornando 200 OK Em vez de 404 Not Found
-
19-08-2019 - |
Pergunta
Depois de tentar configurar o meu site para o Google Webmaster Tools, descobri que minha página personalizada ASP.NET 404 não estava retornando o código de status 404. É exibida a página personalizada correta e disse o navegador que está tudo OK. Esta é considerar um soft 404 ou falso 404. Google não faz assim. Então, eu encontrei muitos artigos sobre o problema, mas a solução que eu quero não parece trabalho.
A solução que eu quero trabalhar está adicionando as duas linhas a seguir para o código por trás método Page_Load da página 404 personalizada.
Response.Status = "404 Not Found";
Response.StatusCode = 404;
Esta não funciona. A página ainda retorna 200 OK. Eu encontrei no entanto, que se eu codificar o seguinte código para o código de projeto que vai funcionar corretamente.
<asp:Content ID="ContentMain" ContentPlaceHolderID="ContentPlaceHolderMaster" runat="server">
<%
Response.Status = "404 Not Found";
Response.StatusCode = 404;
%>
... Much more code ...
</asp:content>
A página está usando uma página mestra. E eu estou configurar páginas de erro personalizadas no meu web.config. Eu realmente prefiro usar o código por trás opção, mas eu não consigo fazê-lo funcionar sem colocar um código em linha corte no design / layout.
Solução
Solução:
O problema, ele saiu, foi o uso da página mestre. Eu tenho que trabalhar, definindo o código de status mais tarde nas páginas de ciclo de vida, obviamente, o processamento da página mestre foi redefini-lo, então eu cancelou o método render e configurá-lo após a prestar estava completa.
protected override void Render(HtmlTextWriter writer)
{
base.Render(writer);
Response.StatusCode = 404;
}
Mais trabalho poderia ser feito para descobrir exatamente quando a página principal é definir o status, mas vou deixar isso para você.
Original Post:
Eu era capaz de obter um aplicativo de teste da web para funcionar bem, bem, pelo menos exibida a página de erro personalizada e retornou um código de status 404. Eu não posso te dizer o que está errado com seu aplicativo, mas eu posso te dizer o que eu fiz:
1) editou o web.config para erros personalizados:
<customErrors mode="On"> <error statusCode="404" redirect="404.aspx"/> </customErrors>
2) Adicionado uma página 404.aspx e definir o código de status para 404.
public partial class _04 : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { Response.StatusCode = 404; } }
Isso é sobre ele, se eu ir para qualquer extensão de página que é processada por Asp.Net e não existe, meu log violinista mostra claramente a 404, aqui é o cabeçalho:
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
Agora, se eu ir para uma página que não é processado por Asp.Net, como um arquivo htm, a página personalizada não mostra eo 404 que está configurado pelo IIS é exibida.
Aqui está um post que vai para mais alguns detalhes que possam ser de utilidade para você e seu problema, meu teste faz fazer um redirecionamento para a nova página assim que a url do arquivo solicitado está praticamente perdido (excepto o seu no string de consulta).
Google 404 e .NET personalizado páginas de erro
Header Spy resposta:
HTTP/1.1 404 Not Found
Date: Sun, 07 Dec 2008 06:21:20 GMT
Outras dicas
Eu tive um problema semelhante que eu quero mostrar uma página personalizada como um 404 (que é ASPX) e funcionou muito bem em localhost, mas assim que um visitante remoto conectado eles iriam receber o genérico IIS 404.
A solução para isso foi adicionar
Response.TrySkipIisCustomErrors = true;
Antes de mudar o Response.StatusCode.
A via Rick Strahl http://www.west-wind.com/ weblog / posts / 745738.aspx
O IIS 7 solução é apenas adicionar isso ao seu arquivo 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>
Tente chamar Response.End () para pular de renderização ...
Response.Status = "404 Not Found";
Response.StatusCode = 404;
Response.End();
return;
Depois de muitos testes e resolução de problemas, parece que certos provedores de hospedagem pode interferir com o código de retorno. Eu era capaz de contornar este problema através da aplicação de um "hack" no conteúdo.
<%
// This code is required for host that do special 404 handling...
Response.Status = "404 Not Found";
Response.StatusCode = 404;
%>
Isso permitirá que a página para retornar o código de retorno correta não importa o que.
Eu era capaz de contornar esse problema usando a seguinte configuração em asp.net webforms usando .NET 3.5.
O padrão Eu tenho implementado bypasses solução redirecionamento personalizado do .NET no web.config como eu escrevi o meu próprio para lidar com todos os cenários com o código de status HTTP correto no cabeçalho.
Em primeiro lugar, os olhares seção customErrors do web.config assim:
<customErrors mode="RemoteOnly" defaultRedirect="~/error.htm" />
Esta configuração garante que o modo CustomErrors estiver ativada, um cenário que vamos precisar mais tarde, e fornece uma opção para o defaultRedirect de Error.htm tudo-else-falha. Isto virá a calhar quando eu não tenho um manipulador para o erro específico, ou há algo ao longo das linhas de uma conexão com o banco quebrado.
Em segundo lugar, aqui está o evento asax erro global:
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();
}
}
Este código é fazer passar a responsabilidade de lidar com o erro para outra classe. Se o erro não for manuseado e CustomErrors está ligado, isso significa que temos um caso em que estamos na produção e de alguma forma um erro não foi manipulado. Vamos limpá-la aqui, a fim de impedir que o usuário vê-lo, mas registrá-lo em Elmah por isso sabemos o que está acontecendo.
Os olhares classe applicationErrorHandler como este:
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;
}
Esta classe utiliza essencialmente o padrão de comando para localizar o manipulador de erro apropriada para o tipo de erro que é emitido. É importante usar Exception.GetBaseException () a este nível, porque quase todo erro será envolto em uma exceção de nível superior. Por exemplo, fazendo "throw new System.Exception ()" a partir de qualquer página aspx irá resultar em um HttpUnhandledException sendo recebidos a este nível, não um System.Exception.
O código "fábrica" ??é simples e se parece com isto:
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();
}
No final, eu tenho um erro extensível manipulação configuração esquema. Em cada um dos "comportamentos" que é definido, eu tenho uma implementação personalizada para o tipo de erro. Por exemplo, uma excepção HTTP será inspeccionado para o código de estado e tratadas adequadamente. Um código de status 404 vai exigir um Server.Transfer em vez de um Request.Redirect, juntamente com o código de status apropriado escrito no cabeçalho.
Espero que isso ajude.