8

While executing Response.End(); method in asp.net it throws ThreadAbortException which I handled in catch block, after end of inner catch block I want to execute some further code but it directly jump to outer catch block. Is This happening because of response has ended and .net framework do not execute any further code?

protected void btn_click(object sender, EventArgs e)
{

    try
    {
        string fileToDownload = MapPath(@"~\Sample.txt");
        string fileToRead = MapPath(@"~\FileNotExist.txt");

        try
        {
            //Section 1
            try
            { 
                // try to read the file which does not exist to raise the exception
                StreamReader ss = new StreamReader(fileToRead);
            }
            catch (IOException IoEx)
            {
                // Just for sample exception
            }

            // Section 2 code block still execute because exception handled by upper try catch block 
            //Section 2

            Response.Clear();
            Response.ClearHeaders();
            Response.AddHeader("Content-Disposition", "attachment;filename=SampleTemplate.txt");
            Response.ContentType = "text";
            Response.WriteFile(fileToDownload);
            Response.Flush();
            Response.End();

        }
        catch (System.Threading.ThreadAbortException abrtEx)
        {
          // do not treat this exception as Exception
        }

        //Section 3 Code block not executing even after exception handeled by ThreadAbortException 
        //Section 3
         string test = "Do futher process after sample downloaded";


    }
    catch (Exception ex) // Outer Catch Block
    {
        throw ex;
    }


}
Neeraj Kumar Gupta
  • 2,157
  • 7
  • 30
  • 58
  • What is supposed to be done in "Do futher process after sample downloaded"? The Page will be finished with its task (serving the download file. What do you want it to do next? – Alexander Jan 10 '14 at 12:31
  • @Alexander: I posted only sampel code which I created to explain my scenario, real code doing a lot of thing before donloading and after download currentaly I have done our after doenload code under catch block which I want to correct and move out of catch block. – Neeraj Kumar Gupta Jan 10 '14 at 12:41
  • I thought as much, yes, but the reason I'm asking is that I am afraid you are using the Page Life Cycle wrong. Hence, to me it's an important question. For the Page, after you end the response, it's life is over. – Alexander Jan 10 '14 at 12:42
  • Yes I uderstand, but after downloading code nothing related to Page Life cycle its activating/Diactivating some services and writing some content received from some other sources. I have other work around for it, but first I am tring to correct code if I can – Neeraj Kumar Gupta Jan 10 '14 at 12:47

3 Answers3

7

Instead of

Response.End()

use

HttpContext.Current.ApplicationInstance.CompleteRequest()

Like this

protected void btn_click(object sender, EventArgs e)
{
    try
    {
        string fileToDownload = MapPath(@"~\Sample.txt");
        string fileToRead = MapPath(@"~\FileNotExist.txt");

        try
        {
            //Section 1
            try
            { 
                // try to read the file which does not exist to raise the exception
                StreamReader ss = new StreamReader(fileToRead);
            }
            catch (IOException IoEx)
            {
                // Just for sample exception
            }

            // Section 2 code block still execute because exception handled by upper try catch block 
            //Section 2

            Response.Clear();
            Response.ClearHeaders();
            Response.AddHeader("Content-Length", fileToDownload.Length.ToString()); 
            Response.AddHeader("Content-Disposition","attachment;filename=SampleTemplate.txt");
            Response.ContentType = "text";
            Response.WriteFile(fileToDownload);
            Response.Flush();
            HttpContext.Current.ApplicationInstance.CompleteRequest();

        }
        catch (System.Threading.ThreadAbortException abrtEx)
        {

        }

        //Section 3 Code block not executing even after exception handeled by ThreadAbortException 
        //Section 3
         string test = "Do futher process after sample downloaded";


    }
    catch (Exception ex) // Outer Catch Block
    {
        throw ex;
    }
}
demonplus
  • 5,613
  • 12
  • 49
  • 68
Vignesh Kumar A
  • 27,863
  • 13
  • 63
  • 115
  • your solution is also working but "Sample.txt" file content getting edited with page apsx content – Neeraj Kumar Gupta Jan 10 '14 at 11:35
  • 1
    Some extra content adding automatically in my Sample.txt file, and this connted seems like page aspx code. My Sample.txt file having only "Name ######## ID ######## DateDone" but after downloading it contains "Name ######## ID ######## DateDone" ; ; ..... . . .... – – Neeraj Kumar Gupta Jan 10 '14 at 12:01
  • hi you need to have addheader for content length. i have updated solution. please check that. and i too had the same problem. please refer here stackoverflow.com/questions/20605705/getting-unwanted-output-when-using-response-binarywritemybyte-and-context-appl – Vignesh Kumar A Jan 10 '14 at 13:28
  • @VigneshKumar in your sample fileToDownload.Length will return length of string variable with path, not length of content – Sergey Litvinov Jan 10 '14 at 14:24
5

According to PRB: ThreadAbortException Occurs If You Use Response.End, Response.Redirect, or Server.Transfer:

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.

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.

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.

This behavior is by design.

Jamil
  • 858
  • 11
  • 26
3

This is because you don't call Thread.ResetAbort in your catch block. Without it CLR won't continue to execute this method. So your code should be:

try
{
   ...
}
catch (System.Threading.ThreadAbortException abrtEx)
{
   Thread.ResetAbort();
}

But it's not a good practice. You can read why it's harmfull here - Is Response.End() considered harmful?

You can complete your logic, and then after it call Response.End(), and not in the middle of method

Community
  • 1
  • 1
Sergey Litvinov
  • 7,408
  • 5
  • 46
  • 67
  • Its working but "Sample.txt" file content getting edited with page apsx content – Neeraj Kumar Gupta Jan 10 '14 at 11:34
  • Some extra content adding automatically in my Sample.txt file, and this connted seems like page aspx code. My Sample.txt file having only "Name ######## ID ######## DateDone" but after downloading it contains "Name ######## ID ######## DateDone" ..... . . .... – Neeraj Kumar Gupta Jan 10 '14 at 11:40