IIS7 anula customErrors al configurar Response.StatusCode?

98

Tengo un problema extraño aquí. Todo el mundo sabe que si usa la customErrorssección de web.config para crear una página de error personalizada, debe configurarla Response.StatusCodeen lo que sea apropiado. Por ejemplo, si hago una página 404 personalizada y la nombro 404.aspx, podría poner <% Response.StatusCode = 404 %>el contenido para que tenga un verdadero encabezado de estado 404.

¿Me sigues tan lejos? Bueno. Ahora intente hacer esto en IIS7. No puedo hacer que funcione, punto. Si Response.StatusCodese establece en la página de error personalizada, IIS7 parece anular la página de error personalizada por completo y muestra su propia página de estado (si tiene una configurada).

¿Alguien más ha visto este comportamiento y quizás también sepa cómo solucionarlo? Funcionaba bajo IIS6, así que no sé por qué cambiaron las cosas.

Nota: Esto no es lo mismo que el problema en ASP.NET Custom 404 Devuelve 200 OK en lugar de 404 Not Found

Nicolás
fuente
Bobby, encontré esa pregunta y la intenté, pero no solucionó el problema. Pero gracias.
Nicholas
Me gustaría comentar que este problema también ocurre cuando se cambia de tubería clásica a integrada. Usé la solución @PavelChuchuva (la solución @RickStrahl también funciona). Supongo que el "paso a través" en Classic es automático, en Integrated toma el manejo de la página de error global del servidor ..
sonjz

Respuestas:

116

Establezca existingResponse en PassThrough en la sección system.webServer / httpErrors:

  <system.webServer>
    <httpErrors existingResponse="PassThrough" />
  </system.webServer>

El valor predeterminado de la propiedad existingResponse es Auto:

Auto le dice al módulo de error personalizado que haga lo correcto . El texto de error real visto por los clientes se verá afectado según el valor de fTrySkipCustomErrors devuelto en la IHttpResponse::GetStatusllamada. Cuando f TrySkipCustomErrors se establece en verdadero, el módulo de error personalizado dejará pasar la respuesta, pero si se establece en falso, el módulo de errores personalizados reemplaza el texto con su propio texto.

Más información: Qué esperar del módulo de error personalizado IIS7

Pavel Chuchuva
fuente
3
Tenga en cuenta que la configuración de existingResponse en PassThrough puede provocar algún efecto secundario. Domina el enlace proporcionado por Pavel antes de realizar cualquier cambio.
Lex Li
¿Es <httpErrors existingResponse="PassThrough" />equivalente Response.TrySkipIisCustomErrorso se comportan de manera diferente?
Asbjørn Ulsberg
1
@sbjornu Logran lo mismo pero con Response.TrySkipIisCustomErrorsusted obtienen un mejor control sobre cuándo mostrar los errores personalizados de IIS.
Pavel Chuchuva
Gracias, he visto mucha información sobre response.tryskipiiscustomerrors pero no tanto sobre la respuesta existente.
HBCondo
Resolví un problema con páginas de error personalizadas que no funcionaban en mi servidor web que ejecuta IIS7 simplemente configurando existingResponse = "Auto", lo cual fue muy sorprendente ya que el artículo hacía referencia a afirmaciones que son las predeterminadas. Claramente no lo es ... o mi empresa de alojamiento estableció el valor predeterminado incorrecto en otro lugar, supongo. De cualquier manera espero que alguien le ahorre unas horas: \
Eric Sassaman
80

La forma más sencilla de hacer que el comportamiento sea coherente es borrar el error y usar Response.TrySkipIisCustomErrors y establecerlo en true. Esto anulará el manejo de la página de error global de IIS desde dentro de su página o el controlador de error global en Application_Error.

Server.ClearError();
Response.TrySkipIisCustomErrors = true;

Por lo general, debe hacer esto en su controlador Application_Error que maneja todos los errores que los controladores de errores de su aplicación no detectan.

Puede encontrar información más detallada en esta publicación de blog: http://www.west-wind.com/weblog/posts/745738.aspx

Rick Strahl
fuente
2
Esto tampoco funciona para mí (IIS8), y el consejo no parece coincidir con el OP (suponiendo que lo esté leyendo correctamente). Yo quiero el customErrorconfigurado en Web.config para gatillo. Con Response.TrySkipIisCustomErrors = trueobtengo el mismo comportamiento: se muestra la fea página de error generada por el servidor. Con él configurado en, falseno sucede nada: una ventana del navegador en blanco.
Shawn South
¡Funcionó bien para mí! Si bien la configuración que menciona Pavel Chuchuva en su respuesta también funcionó, tuvo algunos efectos secundarios que causaron otros problemas. Esta configuración me permitió omitir la anulación de error de IIS en el escenario específico que quería, mientras dejaba el comportamiento intacto para todo lo demás.
Kevin Tighe
Funcionó bien en Azure para mí. Server:Microsoft-IIS/8.5 X-AspNet-Version:4.0.30319 X-AspNetMvc-Version:5.2 X-Powered-By:ASP.NET
Encabezados de
Todavía encuentro que necesito configurarlo customErrors mode="Off"para que esto funcione. Si hago eso, entonces httpErrors existingResponse = "Auto" (predeterminado) funciona correctamente para mí cuando uso el código en esta respuesta.
AaronLS
11

Resuelto: Resulta que "Errores detallados" debe estar activado para que IIS7 "pase a través" de cualquier página de error que pueda tener. Ver http://forums.iis.net/t/1146653.aspx

Nicolás
fuente
1
Aunque esta fue marcada como la respuesta, creo que vale la pena leer otras respuestas para obtener más información sobre el tema.
Lex Li
También podría ser bueno eliminarlo. HandleErrorAttribute en FilterConfig
Por G
4

No estoy seguro de si esto es de naturaleza similar o no, pero resolví un problema que suena similar en la superficie y así es como lo manejé.

En primer lugar, el valor predeterminado para existingResponse (Auto) fue la respuesta correcta en mi caso, ya que tengo un 404, 400 y 500 personalizado (podría crear otros, pero estos tres serán suficientes para lo que estoy haciendo). Aquí están las secciones relevantes que me ayudaron.

Desde web.config:

<customErrors mode="Off" />

Y

<httpErrors errorMode="Custom" existingResponse="Auto" defaultResponseMode="ExecuteURL">
  <clear />
  <error statusCode="404" path="/errors/404.aspx" responseMode="ExecuteURL" />
  <error statusCode="500" path="/errors/500.aspx" responseMode="ExecuteURL" />
  <error statusCode="400" path="/errors/400.aspx" responseMode="ExecuteURL" />
</httpErrors>

A partir de ahí, agregué esto a Application_Error en global.asax:

    Response.TrySkipIisCustomErrors = True

En cada una de mis páginas de error personalizadas, tuve que incluir el código de estado de respuesta correcto. En mi caso, estoy usando un 404 personalizado para enviar usuarios a diferentes secciones de mi sitio, por lo que no quiero que se devuelva un código de estado 404 a menos que en realidad sea una página muerta.

De todos modos, así es como lo hice. Espero que ayude a alguien.

SEFL
fuente
3

Este problema ha sido un gran dolor de cabeza. Ninguna de las sugerencias mencionadas anteriormente me resolvió por sí sola, así que incluyo mi solución. Para el registro, nuestro entorno / plataforma utiliza:

  • .NET Framework 4
  • MVC 3
  • IIS8 (estación de trabajo) e IIS7 (servidor web)

Específicamente, estaba tratando de obtener una respuesta HTTP 404 que redirigiera al usuario a nuestra página personalizada 404 (a través de la configuración de Web.config).

Primero, mi código tenía que lanzar un HttpException. Devolver un NotFoundResultdel controlador no logró los resultados que buscaba.

throw new HttpException(404, "There is no class with that subject");

Luego tuve que configurar tanto el customErrorsy httpErrornodos en el Web.config.

<customErrors mode="On" defaultRedirect="/classes/Error.aspx">
  <error statusCode="404" redirect="/classes/404.html" />
</customErrors>

...

<httpErrors errorMode="Custom" existingResponse="Auto" defaultResponseMode="ExecuteURL">
  <clear />
  <error statusCode="404" path="/classes/404.aspx" responseMode="ExecuteURL" />
</httpErrors>

Tenga en cuenta que dejé el existingResponseas Auto, que es diferente a la solución que proporcionó @sefl.

La customErrorsconfiguración parecía ser necesaria para manejar mi lanzamiento explícito HttpException, mientras que el httpErrorsnodo manejaba las URL que quedaban fuera de los patrones de ruta especificados en Globals.asax.cs.

PD: Con esta configuración no necesitaba configurar Response.TrySkipIisCustomErrors

Shawn South
fuente
2

TrySkipIisCustomErrorses solo una parte de un rompecabezas. Si usa páginas de error personalizadas pero también desea entregar contenido RESTful basado en estados 4xx, entonces tiene un problema. Configurar httpErrors.existingResponse de web.config en "Auto" no funciona, porque .net parece entregar siempre parte del contenido de la página a IIS, por lo tanto, usar "Auto" hace que no se utilicen todas (o al menos algunas) las páginas de error personalizadas. El uso de "Reemplazar" tampoco funcionará, porque la respuesta contendrá su código de estado http, pero su contenido estará vacío o lleno de una página de error personalizada. Y el "PassThrough" de hecho apaga el CEP, por lo que no se puede usar.

Entonces, si desea omitir CEP en algunos casos (al omitir me refiero a devolver el estado 4xx con algún contenido), necesitará un paso adicional: limpiar el error:

void Application_Error(object sender, EventArgs e)
{
    var httpException = Context.Server.GetLastError() as HttpException;
    var statusCode = httpException != null ? httpException.GetHttpCode() : (int)HttpStatusCode.InternalServerError;

    Context.Server.ClearError();
    Context.Response.StatusCode = statusCode;
}

Entonces, si desea usar la respuesta REST (es decir, 400 - Solicitud incorrecta) y enviar algo de contenido con ella, solo tendrá que establecer TrySkipIisCustomErrorsen algún lugar en acción y establecer existingResponseen "Auto" en la sección httpErrors en web.config. Ahora:

  • cuando no hay error (la acción devuelve 4xx o 5xx) y se devuelve algún contenido, el CEP no se utiliza y el contenido se pasa al cliente;
  • cuando hay un error (se lanza una excepción), el contenido devuelto por los controladores de errores se elimina, por lo que se usa el CEP.

Si desea devolver el estado con contenido vacío de su acción, se tratará como una respuesta vacía y se mostrará CEP, por lo que hay espacio para mejorar este código.

Łukasƨ Fronczyk
fuente
0

De forma predeterminada, IIS 7 utiliza mensajes de error personalizados detallados, por lo que supongo que Response.StatusCode será igual a 404.XX en lugar de solo 404.

Puede configurar IIS7 para usar los códigos de mensaje de error más simples o modificar su código manejando los mensajes de error más detallados que ofrece IIS7.

Más información disponible aquí: http://blogs.iis.net/rakkimk/archive/2008/10/03/iis7-enabling-custom-error-pages.aspx

Investigaciones posteriores revelaron que lo tenía al revés: los mensajes detallados no son predeterminados, pero tal vez se hayan activado en su caja si está viendo los diferentes mensajes de error que ha mencionado.

nulo
fuente
Response.StatusCode es un número entero, por lo que no veo una forma de establecer un código más específico que simplemente "404". Tengo IIS7 configurado para usar / mostrar páginas de error personalizadas, como indica su URL.
Nicholas
Hmmm ... Desafortunadamente, no puedo probar en este momento porque no estoy en mi PC de casa. Si no tiene una solución para entonces, la echaré un vistazo esta noche.
nullnvoid