2010-08-18 8 views
9

Estoy usando una página de error genérico usando la directiva <customErrors> de ASP.NET.¿Cómo se envía el código de estado "500" para la página de error genérico en IIS?

<customErrors mode="On" defaultRedirect="500.html" redirectMode="ResponseRewrite"> 
</customErrors> 

Problema: cuando se produce un error, esta página no devuelve el estado HTTP "500". Viene como 200. Por lo tanto, los verificadores de enlaces y las arañas no ven que haya ningún problema.

¿Cómo puedo enviar el estado HTTP 500 junto con la página estática 500.html?

Requisitos:

  • que deben utilizar redirectMode = "ResponseRewrite"
  • no puedo usar una página dinámica, estática única .html.

Respuesta

7

La documentación de MSDN para el elemento customErrors indica que está implementado por System.Web.Configuration.CustomErrorsSection. Si usamos el Reflector .NET de Red Gate para analizar esa clase, podemos ver dónde se usa esa configuración en el Marco.

Es utilizado por System.Web.UI.Page.HandleError y System.Web.HttpResponse.ReportRuntimeError.

Ambos terminan llamando a System.Web.HttpResponse.RedirectToErrorPage.(El nombre de este método es confuso: es importante tener en cuenta que RedirectToErrorPage toma la configuración redirectMode como parámetro, por lo que se llama incluso si está utilizando ResponseRewrite y no ocurre ninguna redirección.)

La parte relevante del RedirectToErrorPage método es:

if (redirectMode == CustomErrorsRedirectMode.ResponseRewrite) 
    { 
     this.Context.Server.Execute(url); 
    } 

no parece haber ninguna manera de establecer el código de respuesta en el manejo de errores: al final del día es sólo una Server.Execute llanura. Por lo tanto, parece inevitable que necesite escribir código para lograr la respuesta HTTP que desea.

¿Puede volver a examinar por qué quiere utilizar un archivo .html simple? Esta parece una opción sensata para el manejo de errores, porque no desea pasar por todos los gastos generales de una página .aspx cuando eso podría causar otro error.

¿Pero quizás hay algún terreno intermedio que será tan robusto como un archivo .html?

Por ejemplo, puede hacer un HttpHandler precompilado, registrarlo en la URL /500.error, y luego hacer que 500.error sea su página predeterminada de Redirección. (Esto sería similar a cómo funciona ScriptResource.axd.) Si precompila su módulo en una DLL (a diferencia de la compilación sobre la marcha de un simple archivo .axd antiguo), puede encontrar que es igual de robusto en el cara de las condiciones de error. Si encuentra un error donde ni siquiera esto funcionará, entonces un archivo .html estático probablemente tampoco funcionará: tenga en cuenta que la directiva customErrors todavía se basa en .NET ejecutándose bajo el capó, y aún usa el StaticFileHandler para servir su archivo .html.

Como alternativa, podría considerar un proxy inverso en frente de su aplicación IIS, que serviría una página amigable de 500 incluso ante una falla catastrófica del grupo de aplicaciones. Esto sería más trabajo de configurar, pero sería incluso más sólido que customErrors, p. Ej. si su web.config se daña, incluso customErrors no funcionará.

+1

Usted plantea un buen punto que depende de ASP.NET. Estaba usando 500.html para evitar la dependencia de ASP.NET, pero es discutible si ASP.NET no responde. Creo que mi mejor opción es usar 500.aspx en y tener una copia de seguridad 500.html de la página de error configurada en el nivel de IIS en caso de que ASP.NET no funcione. – frankadelic

1

Pruebe la configuración de su sección de errores personalizados así:

<customErrors mode="On" redirectMode="ResponseRewrite"> 
    <error statusCode="500" redirect="500.aspx"> 
</customErrors> 

En el archivo 500.aspx, cambie el código de respuesta en el Page_Load;

Response.StatusCode = 500; 
Response.StatusDescription = "Internal Server Error"; 
+0

Necesito usar redirectMode = "ResponseRewrite", así que esta no es una opción para mí. – frankadelic

+0

Además, su solución no envía un estado de HTTP 500 ... Como está escrito, realiza un redireccionamiento 302 a 500.html. 500.html en sí tiene un estado de HTTP 200. Compruébalo en firebug. – frankadelic

+0

respuesta modificada para la pregunta. –

4

En el archivo gllobal.asax añadir el siguiente código

protected void Application_EndRequest(object sender, EventArgs e) 
    { 
     if (Request.Url.AbsolutePath.EndsWith("500.html")) 
      Response.StatusCode = 500; 
    } 
+0

¿Esto requiere IIS7 + Integrated Pipeline? Las solicitudes de .html de lo contrario no se activaría Application_EndRequest .. – frankadelic

+0

lo siento, no presté atención a la extensión de la página de error que es html, ¿hay algún problema con que sea una página aspx. no tendrías que preocuparte de IIS en ese caso. Además, si no estoy equivocado, iis 6 también debería tener formas de redirigir la solicitud html a los controladores aspnet. no tengo acceso a una máquina con iis 6 instalado ahora –

+0

vea mi segundo punto ... debe ser un archivo html estático. – frankadelic

3

bien, tengo una solución, la única manera en que puedo conseguir que esto funcione es sin pasar por la sección de errores personalizados en la web archivo de configuración.

Así, un ejemplo Default.aspx

public partial class Default : System.Web.UI.Page 
{ 
    protected void Page_Load(object sender, EventArgs e) 
    { 
     throw new Exception("boom"); 
    } 
} 

A continuación, en el archivo Global.asax:

protected void Application_Error(object sender, EventArgs e) 
{ 
    // Clear the error to take control of process 
    Server.ClearError(); 

    Response.WriteFile(Server.MapPath("500.html")); 
    Response.StatusCode = 500; 
    Response.StatusDescription = "Internal Server Error"; 
} 

probablemente usted puede escribir un mejor mecanismo de manejo para la parte 500.html - Creo esto debería hacer lo que estás tratando de lograr.

Solo probado con el servidor web VS Cassini, sin embargo, no veo ninguna razón por la cual esto no debería funcionar en iis6.

-1

Si insistes en cambiar la señalización HTTP central, entonces debes ceder a algunas demandas o estar preparado para escribir tu propio servidor web. Sí, debe ejecutar el AppPool integrado de IIS7 y aún tendrá que aceptar la redirección a la página activa ya que está tratando de simular que su servidor no está funcionando y que el servidor no está diseñado para simular el suicidio. Por lo tanto, si le ofrece una forma sencilla de hacerlo, sus opciones son agradecer o desarrollar su propio servidor que no sea compatible con HTTP, que codificará los códigos de respuesta a voluntad.

+0

Prueba esto: crea una página .asp clásica con división por cero (1/0) y ejecútala. Verá que una página de error estática retorna y el estado de HTTP es de hecho 500 (confirme usando firebug o fiddler2). No es la muerte/suicidio del servidor, solo significa que ocurrió un error. No se modificó la "señalización HTTP central". Puede reconfigurar el contenido de la página de error usando el administrador IIS> Páginas de error ... Mi problema es que esta configuración no se aplica a las páginas .aspx. Puedo poner un redireccionamiento a un archivo .html en en web.config, pero la página resultante devuelve un estado de 200. – frankadelic

+0

¿Está diciendo que para un error interno del servidor (por ejemplo, de una excepción) el código de estado correcto es 302? o 200? está devolviendo un código de estado 302 o 200 NO extremadamente codificado? : -> – Myster

+0

Lo único que está "codificado" es el manejo de ASP.NET de los códigos de error. Lanzar una excepción y regresar y la página de error no debe producir un código de respuesta de 200 o 302. Debe ser 500 para indicar "algo roto". –

0

Esto se puede hacer con un filtro isapi. Debería estar escrito en c, pero puede modificar el estado de respuesta para la solicitud .html para que el navegador obtenga un 500 con su página html personalizada.

Cuestiones relacionadas