Response.End()は有害と見なされますか?


198

このナレッジベース記事では、ASP.NET Response.End()がスレッドを中止すると説明しています。

Reflectorは次のように表示されます。

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

これは私にはかなり厳しいようです。KB記事に記載されているように、アプリの次のコードはResponse.End()実行されません。これは、驚きの原則に違反します。Application.Exit()WinFormsアプリとほぼ同じです。が原因で発生したスレッドアボート例外Response.End()はキャッチできないため、コードをtry... で囲むfinallyと満足できません。

いつも避けたほうがいいかなぁResponse.End()

誰がいつResponse.End()、いつResponse.Close()、いつ使用するべきかを提案できますHttpContext.Current.ApplicationInstance.CompleteRequest()か?

ref:Rick Strahlのブログエントリ


私が受け取った入力に基づくと、私の答えは「はい、Response.End有害です」ですが、いくつかの限られた場合に役立ちます。

  • Response.End()キャッチできないスローとして使用し、HttpResponse例外的な状況でを即座に終了します。デバッグ中にも役立ちます。 日常的な対応は避けてくださいResponse.End()
  • Response.Close()クライアントとの接続をすぐに閉じるために使用します。パーこのMSDNのブログの記事、この方法は、通常のHTTPリクエストを処理するためのものではありません。 このメソッドを呼び出す正当な理由がある可能性はほとんどありません。
  • CompleteRequest()通常のリクエストを終了するために使用します。 現在のイベントが完了した後CompleteRequest、ASP.NETパイプラインがEndRequestイベントにジャンプHttpApplicationします。したがって、を呼び出しCompleteRequestて、応答に何かを書き込むと、書き込みはクライアントに送信されます。

編集-2011年4月13日

また、透明度がここにあります:
- MSDNブログに便利なポスト
- ジョン・リードによって便利な分析


2
この回答から何が変更されたのかはわかりませんが、私はResponse.End ThreadAbortException問題なく動いています。
Maslow

1
ベアそれも念頭にResponse.RedirectしてServer.Transfer、コールの両方Response.Endとも避けるべきです。
Owen Blacker 2014年

回答:


66

アプリに例外ロガーを採用している場合はThreadAbortException、これらの無害なResponse.End()呼び出しからのsで骨抜きにされます。これはマイクロソフトの「ノックオフ!」という言い方だと思います。

Response.End()例外的な状態があり、他のアクションが実行できない場合にのみ使用します。おそらく、この例外のログは実際には警告を示している可能性があります。


107

TL; DR

最初は、[Response.End]へのすべての呼び出しを[...] CompleteRequest()呼び出しに置き換えることをお勧めしましたが、ポストバック処理とHTMLレンダリングを回避する場合は、[..を追加する必要があります。 。]オーバーライドも同様です。

ジョン・リード、「最終分析」


MSDN、Jon Reid、およびAlain Renonによると:

ASP.NETパフォーマンス-例外管理-例外を回避するコードを記述する

Server.Transfer、Response.Redirect、Response.Endメソッドはすべて例外を発生させます。これらの各メソッドは、内部的にResponse.Endを呼び出します。次にResponse.Endを呼び出すと、ThreadAbortException例外が発生します。

ThreadAbortExceptionソリューション

HttpApplication.CompleteRequest()は、ページイベントチェーンではなくアプリケーションイベントチェーンではなく、HttpApplicationイベントパイプライン[-]のほとんどのイベントをスレッドがスキップするようにする変数を設定します。

...

Pageを終了する必要があるかどうかにフラグを立てるクラスレベルの変数を作成し、イベントの処理またはページのレンダリングの前に変数を確認します。[...] RaisePostBackEventメソッドとRenderメソッドをオーバーライドすることをお勧めします

Response.EndとResponse.Closeは、パフォーマンスが重要な場合の通常のリクエスト処理では使用されません。Response.Endは、関連するパフォーマンスのペナルティを伴う要求処理を終了する便利で強引な手段です。Response.Closeは、IIS /ソケットレベルでHTTP応答を即座に終了するためのもので、KeepAliveなどの問題を引き起こします。

ASP.NET要求を終了するための推奨される方法は、HttpApplication.CompleteRequestです。HttpApplication.CompleteRequestはIIS / ASP.NETアプリケーションパイプラインの残りをスキップするため、ASP.NETレンダリングは手動でスキップする必要があることに注意してください(アプリケーションパイプラインの1つのステージである)ASP.NETページパイプラインではありません。


コード

Copyright©2001-2007、C6 Software、Incは、私が知る限り最良のものです。


参照

HttpApplication.CompleteRequest

ASP.NETに、実行のHTTPパイプラインチェーンのすべてのイベントとフィルタリングをバイパスさせ、EndRequestイベントを直接実行させます。

Response.End

このメソッドは、ASPとの互換性のためだけに提供されています。つまり、ASP.NET.preceded ASP.NETより前のCOMベースのWebプログラミングテクノロジーとの互換性のために提供されています。【エンファシス追加】

Response.Close

このメソッドは、クライアントへの接続を突然終了するものであり、通常のHTTP要求処理を対象としたものではあり ません。【エンファシス追加】


4
> HttpApplication.CompleteRequestはIIS / ASP.NETアプリケーションパイプラインの残りをスキップし、ASP.NETページパイプライン(アプリパイプラインの1つのステージ)ではなく、ASP.NETレンダリングを手動でスキップする必要があることに注意してください。そして、どのようにこれを達成しますか?
PilotBob 2012年

1
Jon Reidがフラグを設定し、必要に応じてページのRaisePostBackEventメソッドとRenderメソッドをオーバーライドして通常の実装をスキップする方法を示したコードへのリンクを参照してください。(あなたはおそらく、すべてのアプリのページから継承しなければならない基本クラスでこれを行うと思います。)web.archive.org/web/20101224113858/http://www.c6software.com/...
user423430

4
言い換えれば、HttpApplication.CompleteRequestはResponse.Endのように応答を終了しません。
Glen Little

2
HttpApplication.CompleteRequestもコードフローを停止しないため、後続の行は実行され続けます。ブラウザーの表示には影響しませんが、これらの行が他の処理を行うと、非常に混乱する可能性があります。
ジョシュアフランク

3
Webフォームは意図的に壊れているとは思えませんが。パフォーマンスの低下、Response.End()の呼び出し、またはページにすべてをロードさせてから応答を抑制することは何ですか?ここで、Response.End()が「より」有害である場所を確認できません。さらに、マイクロソフトはこのコードから明らかなように、「ThreadAbortedException」を通常のイベントとして扱います:referencesource.microsoft.com/#System.Web/UI/Page.cs,4875 Response.End()に対する1つの問題は、失敗する可能性があることです。応答を中止します。応答が表示されることがあります。
Ghasan

99

この質問は、response.endに関する情報を検索するすべてのGoogle検索の上部に表示されるため、ASPXページ全体をレンダリングせずにイベントに応答してCSV / XML / PDFなどを投稿したい自分のような他の検索では、これは私が行う方法です。(レンダーメソッドのオーバーライドは、このような単純なタスク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()

1
これを行うためにAPSXページを使用しないでください。それは多くの無駄な努力です。ASMXページ以外のASMXまたはWebサービスを使用することになっています。
mattmanser 2013年

19
これが最も簡単な実装の答えのようです。キーはResponse.SuppressContent = Trueです。
Chris Weber

3
@mattmanser-同じリソースの異なる表現のために別のページを用意することは、常に簡単/最良/推奨であるとは限りません。RESTなどについて考えます。クライアントがヘッダーまたはパラメーターを介してcsv、xmlを要求している場合、asp.netの通常のレンダリング機能を通じてHTMLサポートを提供しながら、この方法が確実に最適です。
Chris Weber

1
これは私にはうまくいきませんでした。Response.End()で動作するページがありましたが、Response.Close()、Response.Flush()のあらゆる種類の組み合わせを使用しています。応答にGzipStreamフィルターがある場合、HttpContext.Current.ApplicationInstance.CompleteRequest()およびその他のさまざまなものが機能しませんでした。起こっているように見えたのは、ページが私のファイルと共にまだ出力されていたということでした。最後に、Render()関数をオーバーライドし(空白にする)、それで解決しました。
Aerik 2014

1
CompleteRequestはアプリケーションパイプラインの一部をスキップしますが、ページレンダリングプロセスの残りの部分を実行します。response.endのような即時停止ではなく、より優雅です。このページの他の回答には、理由に関する詳細な説明があります。
Jay Zelos、2016

11

「Response.CloseとCompleteRequest()の違いがまだわからない」という質問で、次のように言います。

CompleteRequest()を使用してください。Response.Close()は使用しないでください。

このケースの完全な要約については、次の記事を参照してください。

CompleteRequest()を呼び出した後でも、一部のテキスト(ASPXコードから変更されたテキストなど)が応答出力ストリームに追加されることに注意してください。次の記事で説明するように、RenderメソッドとRaisePostBackEventメソッドをオーバーライドすることで、これを防ぐことができます。

ところで、Response.End()を使用しないようにすることに同意します。特に、ファイルのダウンロードをエミュレートするためにhttpストリームにデータを書き込む場合はそうです。ログファイルがThreadAbortExceptionsでいっぱいになるまで、Response.End()を過去に使用しました。


あなたが説明するように私はレンダーをオーバーライドすることに興味がありますが、「次の記事」へのリンクは死んでいます。エントリを更新できますか?
paqogomez 14

返事が遅くなってすみません。その記事の内容は正確には覚えていません。:しかし、私はwebarchive.orgでそれを見つけたweb.archive.org/web/20101224113858/http://www.c6software.com/...
ヤンŠotola

9

Response.Endは有害です」という文言に同意しません。それは間違いなく有害ではありません。Response.Endはそれを実行します。ページの実行を終了します。リフレクターを使用してそれがどのように実装されているかを確認することは、参考情報としてのみ参照してください。


マイ2cent勧告
AVOID使用してResponse.End()制御フローとして。
DOの使用はResponse.End()、あなたがリクエストの実行を停止し、(通常は)*何のコードは、そのポイントを過ぎて実行しないことを認識する必要があります。


* Response.End()ThreadAbortException

Response.End() 現在の実装の一部としてThreadAbortExceptionをスローします(OPで注記)。

ThreadAbortExceptionはキャッチできる特別な例外ですが、catchブロックの最後で自動的に再度発生します。

、ThreadAbortExceptionsに対処しなければならないコードを書くSOにMehrdadの返信は、@見する方法を確認するにはどのように私はfinallyブロックでThreadAbortExceptionのを検出することができ、彼が参照するところRuntimeHelpers.ExecuteCodeWithGuaranteedCleanup方法制約実行領域


リックシュトラールの記事は有益である、とよくとしてのコメントを読んでください述べました。Strahlの問題は特定のものであったことに注意してください。彼はデータをクライアント(画像)に取得してから、画像の提供を遅くしないヒットトラッキングデータベースの更新を処理したかったため、Response.Endが呼び出された後に何かを行うという問題が発生しました。


この投稿を見たstackoverflow.com/questions/16731745/…Response.End()の代わりにResponse.SuppressContent = True HttpContext.Current.ApplicationInstance.CompleteRequest()を使用することを提案
jazzBox

3

Response.End()を使用してプログラムのフローを制御することを考えたことはありません。

ただし、Response.End()は、ユーザーにファイルを提供する場合などに役立ちます。

ファイルを応答に書き込みましたが、ファイルを破損する可能性があるため、応答に他のものを追加したくありません。


1
APIが「応答が完了した」と言う必要性を理解しています。ただし、Response.End()もスレッドアボートを実行します。これが問題の核心です。これら2つのことを組み合わせるのはいつ良い考えですか?
Cheeso 2009

2

以前に.NETとクラシックASPの両方でResponse.End()を使用して、強制的に終了しました。たとえば、一定量のログイン試行がある場合に使用します。または、認証されていないログインから安全なページにアクセスする場合(大まかな例):

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

フラッシュを使用するユーザーにファイルを提供する場合、エンドが問題を引き起こす可能性があります。


Flush()は「これで終わり」ではないことに注意してください。それは「今までのところすべてを洗い流す」だけです。「これで終わり」が必要になる理由は、サーバーがログファイルの更新、データベースカウンターのクエリなど、他のことを実行できる間、すべてのコンテンツがあることをクライアントに認識させるためです。Response.Flushを呼び出してから、それらのいずれかを実行すると、クライアントはさらに待機する可能性があります。あなたはResponse.Endの()を呼び出した場合など、制御が飛び出しとDBクエリを取得できません
Cheeso

「ページの現在の実行が終了するかどうかを示します。BOOLは「endResponseここであなたは、代わりのResponse.Redirect(」....」、true)をオーバーライドを使用することができます
ロバート・ポールソン

フォーム認証フレームワークを使用して、ログイン資格情報によって保護されることが意図されているページを保護することを常にお勧めします。
ロバートポールソン、

3
実際、自分自身を修正するために、オーバーライドを呼び出して 'false'を渡さない限り、Response.RedirectおよびServer.TransferのデフォルトはResponse.Endを呼び出すと考えています。コードの記述方法はResponse.Endが呼び出されることはありません、
ロバートポールソン

1
Response.endは、.netでの動作が従来のASPでの動作とは大きく異なります。.netでは、それはかなり嫌なスレッドアボテックスの受容を引き起こします。
アンディ

2

テスト/デバッグのメカニズムとしてResponse.End()のみを使用しました

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

リサーチの点であなたが投稿したものから判断すると、Response.Endを必要とする場合、それは悪いデザインになると思います。


0

クラシックaspでは、一部のajax呼び出しでTTFB(Time To First Byte)が3〜10秒であり、SQL呼び出しが多い通常のページのTTFBよりもはるかに大きかった。

返されたajaxは、ページに挿入されるHTMLのセグメントでした。

TTFBは、レンダリング時間よりも数秒長くなりました。

レンダリング後にresponse.endを追加した場合、TTFBは大幅に削減されました。

"</ body> </ html>"を発行することで同じ効果を得ることができますが、jsonまたはxmlを出力する場合はおそらく機能しません。ここではresponse.endが必要です。


これは古い答えですが、クラシックaspは古いものです。私はそれが役に立ったと感じました;-)
Leif Neland
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.