Response.End () è considerato dannoso?

Questo articolo della Knowledge Base dice che Response.End() di ASP.NET interrompe una discussione.

Reflector mostra che assomiglia a questo:

 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(); } } } 

Questo mi sembra abbastanza duro. Come dice l’articolo della Knowledge Base, qualsiasi codice nell’app che segue Response.End() non verrà eseguito e questo viola il principio del minimo stupore. È quasi come Application.Exit() in un’app WinForms. L’eccezione di interruzione del thread causata da Response.End() non è catchable, quindi circondare il codice in una try … alla finally non soddisfa.

Mi chiedo se dovrei sempre evitare Response.End() .

Qualcuno può suggerire, quando dovrei usare Response.End() , quando Response.Close() e quando HttpContext.Current.ApplicationInstance.CompleteRequest() ?

ref: il blog di Rick Strahl .


Sulla base dell’input ricevuto, la mia risposta è Sì, Response.End è dannoso , ma è utile in alcuni casi limitati.

  • utilizzare Response.End() come lancio non acquisibile per terminare immediatamente HttpResponse in condizioni eccezionali. Può essere utile anche durante il debug. Evitare Response.End() per completare le risposte di routine .
  • utilizzare Response.Close() per chiudere immediatamente la connessione con il client. Per questo post del blog MSDN , questo metodo non è destinato alla normale elaborazione della richiesta HTTP. È altamente improbabile che tu abbia una buona ragione per chiamare questo metodo.
  • utilizzare CompleteRequest() per terminare una richiesta normale. CompleteRequest fa in modo che la pipeline ASP.NET salti all’evento EndRequest , al termine dell’evento HttpApplication corrente. Quindi, se chiami CompleteRequest , quindi scrivi qualcosa in più alla risposta, la scrittura verrà inviata al client.

Modifica – 13 aprile 2011

Un’ulteriore chiarezza è disponibile qui:
– Post utili su MSDN Blog
– Analisi utili di Jon Reid

Se hai utilizzato un logger di eccezioni nella tua app, verrà annacquato con le proprietà ThreadAbortException da queste benigne chiamate Response.End() . Penso che questo sia il modo in cui Microsoft dice “Toglilo fuori!”.

Vorrei usare solo Response.End() se ci fosse qualche condizione eccezionale e nessuna altra azione fosse ansible. Forse allora, la registrazione di questa eccezione potrebbe effettivamente indicare un avvertimento.

TL; DR

Inizialmente avevo raccomandato di sostituire semplicemente tutte le chiamate a [Response.End] con […] chiamate CompleteRequest (), ma se vuoi evitare l’elaborazione postback e il rendering html devi aggiungere [.. .] sovrascrive anche.

Jon Reid , “Analisi finale”


Per MSDN, Jon Reid e Alain Renon:

Prestazioni ASP.NET – Gestione delle eccezioni – Scrive codice che evita eccezioni

I metodi Server.Transfer, Response.Redirect, Response.End generano eccezioni. Ciascuno di questi metodi chiama internamente Response.End. La chiamata a Response.End, a sua volta, causa un’eccezione ThreadAbortException .

ThreadAbortException Solution

HttpApplication.CompleteRequest () imposta una variabile che fa sì che il thread salti la maggior parte degli eventi nella pipeline di eventi HttpApplication [-] non nella catena di eventi Page ma nella catena di eventi dell’applicazione.

crea una variabile di livello di class che contrassegna se la pagina deve terminare e quindi controlla la variabile prima di elaborare i tuoi eventi o eseguire il rendering della pagina. […] Suggerirei di sovrascrivere i metodi RaisePostBackEvent e Render

Response.End e Response.Close non vengono utilizzati nella normale elaborazione delle richieste quando le prestazioni sono importanti. Response.End è un mezzo comodo e pesante per terminare l’elaborazione delle richieste con una penalità legata alle prestazioni. Response.Close serve per la chiusura immediata della risposta HTTP a livello di IIS / socket e causa problemi con cose come KeepAlive.

Il metodo consigliato per terminare una richiesta ASP.NET è HttpApplication.CompleteRequest. Tenere presente che il rendering ASP.NET dovrà essere saltato manualmente poiché HttpApplication.CompleteRequest salta il resto della pipeline dell’applicazione IIS / ASP.NET, non della pipeline della pagina ASP.NET (che è una fase della pipeline dell’app).


Codice

Copyright © 2001-2007, C6 Software, Inc come meglio potrei dire.


Riferimento

HttpApplication.CompleteRequest

Fa in modo che ASP.NET ignori tutti gli eventi e filtri nella catena di esecuzione della pipeline HTTP e esegua direttamente l’evento EndRequest.

Response.End

Questo metodo viene fornito solo per compatibilità con ASP , ovvero per compatibilità con la tecnologia di programmazione Web basata su COM che ha preceduto ASP.NET.preced ASP.NET. [Enfasi aggiunta]

Response.Close

Questo metodo interrompe la connessione al client in modo brusco e non è destinato alla normale elaborazione della richiesta HTTP . [Enfasi aggiunta]

Questa domanda appare vicino alla parte superiore di tutte le ricerche di google per informazioni su response.end quindi per altre ricerche come me che desiderano pubblicare CSV / XML / PDF in risposta a un evento senza visualizzare l’intera pagina ASPX, questo è come lo faccio . (sovrascrivere i metodi di rendering è eccessivamente complesso per un compito così semplice IMO)

 // 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() 

Sulla questione di “Ancora non conosco la differenza tra Response.Close e CompleteRequest ()” direi:

Preferisci CompleteRequest (), non utilizzare Response.Close ().

Vedere il seguente articolo per un riepilogo ben fatto di questo caso.

Tenere presente che anche dopo aver chiamato CompleteRequest () un po ‘di testo (ad es. Redndered dal codice ASPX) sarà aggiunto al stream di output della risposta. Puoi prevenirlo sostituendo i metodi Render e RaisePostBackEvent come descritto nel seguente articolo .

BTW: Sono d’accordo con la prevenzione dell’utilizzo di Response.End (), specialmente quando si scrivono dati sullo stream http per emulare il download di file. Abbiamo utilizzato Response.End () in passato fino a quando il nostro file di registro non è diventato pieno di ThreadAbortExceptions.

Non sono d’accordo con l’affermazione ” Response.End is harmful “. Non è sicuramente dannoso. Response.End fa quello che dice; termina l’esecuzione della pagina. Usare il riflettore per vedere come è stato implementato dovrebbe essere considerato solo come istruttivo.


La mia raccomandazione 2cent
EVITARE di utilizzare Response.End() come stream di controllo.
Utilizzare Response.End() se è necessario interrompere l’esecuzione della richiesta e tenere presente che (tipicamente) * nessun codice verrà eseguito oltre quel punto.


* Response.End() e ThreadAbortException s.

Response.End() genera una ThreadAbortException come parte della sua implementazione corrente (come indicato da OP).

ThreadAbortException è un’eccezione speciale che può essere rilevata, ma verrà automaticamente rilanciata alla fine del blocco catch.

Per vedere come scrivere codice che deve occuparsi di ThreadAbortExceptions, vedere la risposta di @ Mehrdad a SO. Come posso rilevare un threadabortexception in un blocco finally in cui fa riferimento a RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup Method e Constrained Execution Regions


L’ articolo di Rick Strahl citato è istruttivo e assicurati di leggere anche i commenti. Si noti che il problema di Strahl era specifico. Voleva ottenere i dati sul client (un’immagine) e quindi elaborare l’aggiornamento del database di tracciamento degli accessi che non rallentava la pubblicazione dell’immagine, il che gli rendeva il problema di fare qualcosa dopo Response.End era stato chiamato.

Non ho mai considerato l’utilizzo di Response.End () per controllare il stream del programma.

Tuttavia, Response.End () può essere utile ad esempio quando si servono i file a un utente.

Hai scritto il file nella risposta e non vuoi aggiungere altro alla risposta in quanto potrebbe corrompere il tuo file.

Ho usato Response.End () in ASP sia .NET che Classic per terminare con forza le cose prima. Ad esempio, lo uso quando c’è un certo numero di tentativi di accesso. O quando una pagina sicura viene acceduta da un login non autenticato (esempio approssimativo):

  if (userName == "") { Response.Redirect("......"); Response.End(); } else { ..... 

Quando servo i file a un utente, utilizzerei una scala, la fine può causare problemi.

Ho usato solo Response.End () come meccanismo di test / debugging

  Response.Write("myVariable: " + myVariable.ToString()); Response.End();  

A giudicare da ciò che hai pubblicato in termini di ricerca, direi che sarebbe un cattivo progetto se richiedesse Response.End