.net - net - ¿Response.End() es considerado dañino?
asp.net response.end subproceso anulado (8)
TL; DR
Inicialmente, le recomendé que simplemente reemplace todas sus llamadas a [Response.End] con [...] Llamadas CompleteRequest (), pero si desea evitar el procesamiento de devolución de datos y el procesamiento html, deberá agregar [... .] anula también.
Jon Reid , "Análisis Final"
Según MSDN, Jon Reid y Alain Renon:
Desempeño de ASP.NET - Administración de excepciones - Código de escritura que evita las excepciones
Los métodos Server.Transfer, Response.Redirect, Response.End generan excepciones. Cada uno de estos métodos llama internamente a Response.End. La llamada a Response.End, a su vez, provoca una excepción ThreadAbortException .
Solución ThreadAbortException
HttpApplication.CompleteRequest () establece una variable que hace que el hilo pase por alto la mayoría de los eventos en la canalización de eventos HttpApplication [-] no la cadena de eventos de la página sino la cadena de eventos de la aplicación.
...
cree una variable de nivel de clase que marque si la página debe terminar y luego verifique la variable antes de procesar sus eventos o representar su página. [...] Recomendaría simplemente anular los métodos RaisePostBackEvent y Render
Response.End y Response.Close no se utilizan en el procesamiento normal de solicitudes cuando el rendimiento es importante. Response.End es un medio conveniente y de mano dura para terminar el procesamiento de solicitudes con una penalización de rendimiento asociada. Response.Close es para la terminación inmediata de la respuesta HTTP en el nivel de IIS / socket y causa problemas con cosas como KeepAlive.
El método recomendado para finalizar una solicitud ASP.NET es HttpApplication.CompleteRequest. Tenga en cuenta que la representación de ASP.NET deberá omitirse manualmente ya que HttpApplication.CompleteRequest omite el resto de la canalización de la aplicación IIS / ASP.NET, no la canalización de la página ASP.NET (que es una etapa en la canalización de la aplicación).
Código
Copyright © 2001-2007, C6 Software, Inc lo mejor que pude ver.
Referencia
HttpApplication.CompleteRequest
Hace que ASP.NET omita todos los eventos y el filtrado en la cadena de ejecución de la canalización HTTP y ejecute directamente el evento EndRequest.
Response.End
Este método se proporciona solo para la compatibilidad con ASP , es decir, para la compatibilidad con la tecnología de programación web basada en COM que precedió a ASP.NET. [Énfasis añadido]
Response.Close
Este método finaliza la conexión con el cliente de manera abrupta y no está diseñado para el procesamiento normal de solicitudes HTTP . [Énfasis añadido]
Este artículo de KB dice que Response.End()
ASP.NET aborta un hilo.
Reflector muestra que se ve así:
public void End()
{
if (this._context.IsInCancellablePeriod)
{
InternalSecurityPermissions.ControlThread.Assert();
Thread.CurrentThread.Abort(new HttpApplication.CancelModuleException(false));
}
else if (!this._flushing)
{
this.Flush();
this._ended = true;
if (this._context.ApplicationInstance != null)
{
this._context.ApplicationInstance.CompleteRequest();
}
}
}
Esto me parece bastante duro. Como dice el artículo de KB, cualquier código en la aplicación que sigue a Response.End()
no se ejecutará, y eso viola el principio de menos asombro. Es casi como Application.Exit()
en una aplicación de WinForms. La excepción de cancelación de subproceso causada por Response.End()
no es detectable, por lo que rodear el código en un try
... finally
no será satisfactorio.
Me hace preguntarme si siempre debería evitar Response.End()
.
¿Alguien puede sugerir cuándo debo usar Response.End()
, Response.Close()
y HttpContext.Current.ApplicationInstance.CompleteRequest()
?
ref: entrada de blog de Rick Strahl .
Según la información que recibí, mi respuesta es: Sí, Response.End
. La Response.End
es perjudicial , pero es útil en algunos casos limitados.
- use
Response.End()
como una tirada incuestionable, para terminar inmediatamente elHttpResponse
en condiciones excepcionales. Puede ser útil durante la depuración también. EviteResponse.End()
para completar las respuestas de rutina . - use
Response.Close()
para cerrar inmediatamente la conexión con el cliente. Según esta publicación del blog de MSDN , este método no está diseñado para el procesamiento normal de solicitudes HTTP. Es muy poco probable que tenga una buena razón para llamar a este método. - use
CompleteRequest()
para finalizar una solicitud normal.CompleteRequest
hace que la canalización de ASP.NETEndRequest
eventoEndRequest
, una vez que seHttpApplication
eventoHttpApplication
actual. Entonces, si llama aCompleteRequest
, luego escriba algo más en la respuesta, la escritura se enviará al cliente.
Edición - 13 de abril de 2011
Más claridad está disponible aquí:
- Post útil en el blog de MSDN
- Análisis útil por Jon Reid.
En la pregunta "Todavía no sé la diferencia entre Response.Close y CompleteRequest ()" diría:
Prefiere CompleteRequest (), no use Response.Close ().
Vea el siguiente artículo para un resumen bien hecho de este caso.
Tenga en cuenta que incluso después de llamar a CompleteRequest (), se agregará algún texto (por ejemplo, redndered del código ASPX) a la secuencia de salida de respuesta. Puede evitarlo anulando los métodos Render y RaisePostBackEvent como se describe en el siguiente artículo .
Por cierto: estoy de acuerdo con evitar el uso de Response.End (), especialmente cuando se escriben datos en el flujo http para emular la descarga de archivos. Hemos usado el Response.End () en el pasado hasta que nuestro archivo de registro se llenó de ThreadAbortExceptions.
Esta pregunta aparece cerca de la parte superior de todas las búsquedas de Google para obtener información sobre response.end, así que para otras búsquedas como yo que deseen publicar CSV / XML / PDF, etc. en respuesta a un evento sin presentar la página ASPX completa, así es como lo hago. . (la anulación de los métodos de renderización es demasiado compleja para una tarea IMO tan sencilla)
// Add headers for a csv file or whatever
Response.ContentType = "text/csv"
Response.AddHeader("Content-Disposition", "attachment;filename=report.csv")
Response.AddHeader("Pragma", "no-cache")
Response.AddHeader("Cache-Control", "no-cache")
// Write the data as binary from a unicode string
Dim buffer As Byte()
buffer = System.Text.Encoding.Unicode.GetBytes(csv)
Response.BinaryWrite(buffer)
// Sends the response buffer
Response.Flush()
// Prevents any other content from being sent to the browser
Response.SuppressContent = True
// Directs the thread to finish, bypassing additional processing
HttpContext.Current.ApplicationInstance.CompleteRequest()
He usado Response.End () tanto en .NET como en ASP clásico para terminar cosas con fuerza antes. Por ejemplo, lo uso cuando hay una cantidad certian de intentos de inicio de sesión. O cuando se accede a una página segura desde un inicio de sesión no autenticado (ejemplo aproximado):
if (userName == "")
{
Response.Redirect("......");
Response.End();
}
else
{
.....
Al entregar archivos a un usuario, usaría un Flush, el Fin puede causar problemas.
No estoy de acuerdo con la afirmación " Response.End es perjudicial ". Definitivamente no es perjudicial. Respuesta. Y hace lo que dice; Termina la ejecución de la página. El uso del reflector para ver cómo se implementó solo debe verse como instructivo.
Mi recomendación de 2 centavos
EVITE usar Response.End()
como flujo de control.
Use Response.End()
si necesita detener la ejecución de la solicitud y tener en cuenta que (normalmente) * ningún código se ejecutará más allá de ese punto.
* Response.End()
y ThreadAbortException s.
Response.End()
lanza una excepción ThreadAbortException como parte de su implementación actual (como lo señala OP).
La excepción ThreadAbortException es una excepción especial que se puede capturar, pero se volverá a generar automáticamente al final del bloque catch.
Para ver cómo escribir código que debe lidiar con ThreadAbortExceptions, vea la respuesta de @ Mehrdad a SO ¿Cómo puedo detectar una idea de threadaborte en un bloque finally donde hace referencia a RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup Método y regiones de ejecución restringida
El artículo de Rick Strahl mencionado es instructivo, y asegúrese de leer los comentarios también. Tenga en cuenta que el problema de Strahl era específico. Quería llevar los datos al cliente (una imagen) y luego procesar la actualización de la base de datos de seguimiento de aciertos que no ralentizaba el servicio de la imagen, lo que hacía que fuera el problema de hacer algo después de que Response.End había sido llamado.
Nunca he considerado usar Response.End () para controlar el flujo del programa.
Sin embargo, Response.End () puede ser útil, por ejemplo, cuando sirve archivos a un usuario.
Ha escrito el archivo en la respuesta y no desea que se agregue nada más a la respuesta, ya que puede dañar su archivo.
Si ha empleado un registrador de excepciones en su aplicación, se diluirá con las ThreadAbortException
s de estas llamadas benignas Response.End()
. Creo que esta es la forma en que Microsoft dice "¡Tíralo!".
Solo usaría Response.End()
si hubiera alguna condición excepcional y ninguna otra acción fuera posible. Tal vez entonces, el registro de esta excepción en realidad podría indicar una advertencia.
Solo he usado Response.End () como un mecanismo de prueba / depuración
<snip>
Response.Write("myVariable: " + myVariable.ToString());
Response.End();
<snip>
A juzgar por lo que ha publicado en términos de investigación, diría que sería un mal diseño si se requiriera Respuesta. Fin