下記エントリで書いていたコードに、実行ログを出力させよう!とlog4net出力コードを埋め込み、さらに「エラー処理も(エラー起きないだろうけど)やっておこう!」と張り切ってTry/Catchで囲ったら……エラー出てるし……
エラー内容
出てるエラーはこんな感じ
2015-04-14 19:09:33,119 [10] INFO - ■ Button_Click 開始 2015-04-14 19:09:33,146 [10] ERROR - エラー発生 System.Threading.ThreadAbortException: スレッドを中止しようとしました。 場所 System.Threading.Thread.AbortInternal() 場所 System.Threading.Thread.Abort(Object stateInfo) 場所 System.Web.HttpResponse.End() 場所 OfficeFileDownloadTest._Default.Button_Click(Object sender, EventArgs e) 場所 C:\Users\test\Documents\Visual Studio 2008\Projects\Test\Test\Default.aspx.cs:行 248
なんなのこれ?と思い、軽く検索するとこんなのが引っかかった。あとで詳細調べます。
- PRB/ ThreadAbortException Occurs If You Use Response.End, Response.Redirect, or Server.Transfer
- https://support.microsoft.com/en-us/kb/312629/
とりあえず、Response.Endの代わりにこれを書いて回避してみます。
HttpContext.Current.ApplicationInstance.CompleteRequest();
CompleteRequesetもダメだ
エラーは消えましたが、TransmitFileでファイルをダウンロードしたほうは、どうもファイル内に余計なタグがついたか何かでファイル表示時に修復の問い合わせがでるように。
また、Response.WriteでHTMLを返していた方は、なんとダウンロードされる内容がASP.NETが作ったページそのままをコピーしたExcelファイルに。HTMLの記述内容はどこかに行ってしまいました。
前者はおそらくこれです。
- HttpResponse.WriteとかWriteFileするとデフォルトで付いてしまう
- https://social.msdn.microsoft.com/Forums/ja-JP/b7b5e136-e8bd-457b-8993-aaa9893902ae/httpresponsewritewritefiledoctype-html-public-w3cdtd-?forum=aspnetja
上記のフォーラム内で「aspxを使わずに、ashxファイルつかってProcessRequestの中で同じことやればいいように思いますが。」といったコメントがあるので、このあたりを調べてみます。
いずれにしても、現時点ではResponseオブジェクトによるデータ返送の仕組みを調べるのは完全に脱線で、Excelデータをダウンロードするテストページを作ることがもくてきなので、とりあえずエラートラップをはずしてResponse.Endでやって行こうと思います。
分かりやすい説明があった
ここにわかりやすく書いてありました。もう少し噛み砕いてみますが、すこしすっきり。
- ThreadAbortExceptionの回避策について
- http://www.ailight.jp/BBSDetail/Index/08988dba-817c-4d2d-a64e-98159ccfd47c
参考: KB 312629 内容
マイクロソフトのリンク先が消える可能性を考慮して、概要を転記しておきます。
ThreadAbortException occurs if you use Response.End, Response.Redirect, or Server.Transfer
This article helps you resolve the ThreadAbortException error that occurs if you use Response.End, Response.Redirect, or Server.Transfer.
Symptmons
If you use the Response.End, Response.Redirect, or Server.Transfer method, a ThreadAbortException exception occurs. You can use a try-catch statement to catch this exception.
Cause
The Response.End method ends the page execution and shifts the execution to the Application_EndRequest event in the application's event pipeline. The line of code that follows Response.End is not executed.
This problem occurs in the Response.Redirect and Server.Transfer methods because both methods call Response.End internally.
Resolution
To work around this problem, use one of the following methods:
- For Response.End , call the HttpContext.Current.ApplicationInstance.CompleteRequest method instead of Response.End to bypass the code execution to the Application_EndRequest event.
- For Response.Redirect, use an overload, Response.Redirect(String url, bool endResponse) that passes false for the endResponse parameter to suppress the internal call to Response.End. For example:
Response.Redirect ("nextpage.aspx", false);
If you use this workaround, the code that follows Response.Redirect is executed.
- For Server.Transfer, use the Server.Execute method instead.
Although ASP.NET handles this exception, you can use the try-catch statement to catch this exception. For example:
try { Response.Redirect("nextpage.aspx"); } catch (Exception ex) { Response.Write (ex.Message); }
Add a breakpoint on the Response.Write line, and notice that this breakpoint is hit. When you examine the exception, notice that the ThreadAbortException exception occurs.