Why does Response.End sometimes throw Thread was being aborted Exception?

I have two different web pages that both create text files that are returned to the user via Response.WriteFile.

On the first page, in a button's click event, I have the following:
   SendFileResponse(Response, sFileName, "Data_" & sNow & ".csv")

Open in new window


In the other page, I instantiate a class and then, within a try - catch block, call a class method that makes the following calle:
   SendFileResponse(HttpContext.Current.Response, sServerFilename, "Extract_" & DateTime.Now.ToString("yyyyMMdd_HHmmss") & ".csv")

Open in new window


Both pages inherit from a base page which traps and logs any errors.

The code for SendFileResponse is as follows:
   Public Sub SendFileResponse( _
         ByRef oResponse As HttpResponse, _
         ByVal sServerFileName As String, _
         ByVal sUserFileName As String)

      Dim fiDownload As FileInfo = New FileInfo(sServerFileName)

      oResponse.Clear()
      oResponse.ClearHeaders()      ' Required to clear caching headers
      oResponse.AddHeader("Content-Disposition", "attachment; filename=" & sUserFileName)

      oResponse.AddHeader("Content-Length", fiDownload.Length.ToString())
      oResponse.ContentType = "application/octet-stream"
      oResponse.WriteFile(fiDownload.FullName)

      oResponse.End()
   End Sub

Open in new window


The first page works fine without throwing any errors. The second page often throws the following exception: System.Threading.ThreadAbortException: Thread was being aborted.

Can someone explain why one page throws the error and the other doesn't?
Thanks in advance.
LVL 1
ZekeLAAsked:
Who is Participating?
 
Tuyau2poilConnect With a Mentor Commented:
in second page, you use try/catch but catch will nether be executed because response.end kill the current thread and nothing can be done after that. it seems that asp don't like to close himself it some code is still to be executed. In first page, reponse.end close thread at 'real' end of procedure.
anyway, Microsoft say that behavior is "by design" and can't be changed.
0
 
Göran AnderssonCommented:
The Response.End method always throws that exception, unless you use the overload that doesn't end the execution. It's the way that the framework uses to stop execution of the page and exit out to the code that finishes the response.

If you have a try-catch block that cathes any exception around the code where you use the Response.End, it will catch the exception. You should only catch the exceptions that you handle, not all kinds of exceptions.
0
 
ZekeLAAuthor Commented:
Thanks Tuyau2poil, I understand why I was getting the error with the new code.
0
Cloud Class® Course: C++ 11 Fundamentals

This course will introduce you to C++ 11 and teach you about syntax fundamentals.

 
Göran AnderssonCommented:
The accepted answer is not correct. It's just speculation, and has no basis in what's actually happens. The system has no sense of "code still to be executed".

The real reason is that you have a try-catch block in the second code, that catches the exception that the Response.End uses to exit out of the code. The Response.End method always throws that exception to exit out to the code that finishes the response, as I explained in my answer.
0
 
ZekeLAAuthor Commented:
That may be so GG but for now, the accepted answer matches the behavior better. Because of the base page Page_Error event, the error should always be caught. But it is only caught when called through the class object. I'll try looking into it further tonight. Perhaps the Page_Error event is ignoring certain errors.
0
 
ZekeLAAuthor Commented:
I've checked my code and I think I may have found part of the explanation but it still seems backwards to me. In my base page, I have the following code (stripped down):
        Private Sub Page_Error(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Error
            Call Me.PageError(Server, Page)
        End Sub

        Public Shared Sub PageError(ByVal oServer As System.Web.HttpServerUtility, ByVal oPage As Page) 'ByVal sender As Object, ByVal e As System.EventArgs)
            Dim ex As System.Exception = oServer.GetLastError
            Dim bEmailed As Boolean = SendErrorEmail(sErrorPageError & ex.Message, "", ex.ToString, oPage)

            oServer.ClearError()
        End Sub

Open in new window


Since Response.End is called from both pages, I would expect having a try catch block would trap and hide the error from being reported. And the other call should make its way to Page_Error normally. Even if Page_Error clears the error, it should still send me an email for the Abort error, but that doesn't happen from the first page. I only receive the notification from the second page.

For whatever reason, the abort exception gets swallowed up by the first page (no try catch) but not by the second page (has a try catch).
0
 
Göran AnderssonCommented:
The Error event is triggered when there is an unhandled exception in the page, but the exception that the Response.End method throws is handled before that. The system catches that exception and just continues to send the request.

If the exception used by Response.End wasn't handled by the system, it would always cause an Error event, and thus be pretty useless.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.