Reputation: 2363
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
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
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
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