Neeraj Kumar Gupta
Neeraj Kumar Gupta

Reputation: 2363

ThreadAbortException handling in asp.net while executing Response.End() method

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


}

Upvotes: 8

Views: 16530

Answers (3)

Vignesh Kumar A
Vignesh Kumar A

Reputation: 28403

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

Upvotes: 7

Jamil
Jamil

Reputation: 858

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.

Upvotes: 5

Sergey Litvinov
Sergey Litvinov

Reputation: 7458

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

Upvotes: 3

Related Questions