I am working on an ASP.Net project where we have an centralized redirection method. But some times it throws an exception:
System.Threading.ThreadAbortException
The main problem is that often the code execution is not stopping after calling SBA.Redirect("AnotherPage.aspx") and the following code is still executing.
My generic function:
public static class SBA
{
public static void Redirect(string Url)
{
try
{
HttpContext.Current.Response.Redirect(Url, false);
HttpContext.Current.ApplicationInstance.CompleteRequest();
}
catch (Exception ex)
{
if (ex.GetType() != typeof(System.Threading.ThreadAbortException))
{
throw;
}
}
}
}
Redirect raises a ThreadAbortException specifically in order to stop any following code from being run.
You are handling the ThreadAbortException.
Thus the following code is being run.
If you don't want the following code to be run, don't handle the ThreadAbortException.
Simply make the following call to make a redirect:
HttpContext.Current.Response.Redirect(Url);
There are two problems with your code:
You use an overload of Redirect where you decide to not end the response by supplying false for the endResponse parameter. Hence the code after the redirect executes.
You try to catch ThreadAbortException. When using the normal redirect as described above this exception is thrown. It is not an error condition but simply a way for ASP.NET to ensure proper termination of the current request. You can catch the exception but it is rethrown at the end of the catch block so your catch block will not do anything useful.
Because an exception is thrown when redirecting you should be aware of the following explained in the comment:
void HandleRequest() {
try {
Response.Redirect(" ... url ... ");
}
catch (Exception) {
// Code here will execute after the redirect.
}
}
To avoid problems the best thing is to catch a more specific exception type in the catch handler or at least not do anything in the handler that interferes with the redirect (like writing to the response stream).
I protected the redirection using the code below. It's working.
public static class SBA
{
public static void Redirect(string Url)
{
try
{
//redirect only when 'IsRequestBeingRedirected' is false
if (!HttpContext.Current.Response.IsRequestBeingRedirected)
{
Uri uri = null;
bool isUriValid = Uri.TryCreate(Url, UriKind.RelativeOrAbsolute, out uri);
if (!isUriValid)
{
throw new SecurityException("Invalid uri " + Url);
}
//Below check is not required but checked
//to make obsolate security check
if (uri.OriginalString == null)
{
throw new SecurityException("Invalid uri " + Url);
}
// check if host is from configured trusted host list
if (uri.IsAbsoluteUri)
{
var tempAppSetting = ConfigBLL.GetAppSetting(AppSettingSectionType.OtherSetting).Other;
if (!tempAppSetting.RedirectTrustedUrls.Contains(uri.Host))
{
throw new SecurityException("Untrusted url redirection detected. Can not redirect.");
}
}
var tempUrl = uri.OriginalString;
//Few more logical check
HttpContext.Current.Response.Redirect(tempUrl, true);
}
HttpContext.Current.ApplicationInstance.CompleteRequest();
}
catch (Exception ex)
{
if (ex.GetType() != typeof(System.Threading.ThreadAbortException))
{
throw;
}
}
}
}
Related
While looking on C# try catch tutorial, I got following question. My sample code as follows,
Inside mainMethod() , I need to call three separate methods. Inside testMethodOne(), I need to handle exception as. If testMethodOne() throws exception, without executing testMethodTwo(dt), mainMethod() throwing exception. I need to call testMethodTwo(dt); and testMethodThreee(dt); if testMethodOne() throws exception, how can I do it.
public void MainMethod(data dt){
try{
testMethodOne(dt);
testMethodTwo(dt);
testMethodThreee(dt);
}catch(Exception ex){
throw ex;
}
}
public void testMethodOne(dt){
try
{
// Block of code to try
}
catch (Exception e)
{
// Block of code to handle errors
}
}
I understood your question as follows (but I might be wrong, your questions is not very clear):
Even if one of your testMethods throws an exception, you still want to continue in the normal program flow with the other methods. If at least one of the method failed, mainMethod could then report this as AggregateException.
public void MainMethod(data dt)
{
var exceptions = new List<Exception>();
try
{
testMethodOne(dt);
}
catch (Exception ex)
{
exceptions.Add(ex);
}
try
{
testMethodTwo(dt);
}
catch (Exception ex)
{
exceptions.Add(ex);
}
try
{
testMethodThreee(dt);
}
catch (Exception ex)
{
exceptions.Add(ex);
}
if (exceptions.Count > 0)
{
throw new AggregateException(exceptions);
}
}
It seems as if you want exceptions to alter the flow of your main method without breaking everything. One easy method is to make each 'testmethod' return a boolean.
public bool testMethodOne(dt){
try
{
// Block of code to try
return true;
}
catch (Exception e)
{
// Block of code to handle errors
return false;
}
}
Then in your main code you can go
if(!testMethodOne(dt))
if(!testMethodTwo(dt))
if(!testMethodThree(dt))
//log that all methods failed
The above snippet would try each method until it finds one that succeeds. If that's not the behaviour you are looking for can you reword your question to make it clearer? If you want the opposite to happen just get rid of the ! and it will go until one fails. Alternatively you could put a throw in your catch statement in each of the testMethods, and that would stop execution once one is reached as well.
I am getting error Unable to evaluate expression because the code is optimized or a native frame is on top of the call stack. while executing line
Server.Transfer("Payment.aspx?vpc_ChannelId=2", true);
so as pointed out by this answer https://stackoverflow.com/a/1252119/1169180 & https://stackoverflow.com/a/11130517/1169180
i changed my code to
protected void Page_Load(object sender, EventArgs e)
{
try
{
UserContext conObj = new UserContext();
HttpContext CurrContext = HttpContext.Current;
if (!IsPostBack)
{
// Code
}
else
{
string userContext = hdnContextObj.Value;
conObj = JsonConvert.DeserializeObject<UserContext>(userContext);
CurrContext.Items.Add("Context", conObj);
try
{
Server.Transfer("Payment.aspx?vpc_ChannelId=2", true);
}
catch (ThreadAbortException xObj)
{
}
finally
{
Server.Transfer("Payment.aspx?vpc_ChannelId=2", true);
}
}
}
catch (Exception xObj)
{
Response.Write("Exception : " + xObj.Message);
}
}
still i am getting same exception in out catch block
Also as pointed out here http://support.microsoft.com/kb/312629/EN-US/ i used Server.Execute but it didnt redirect to Payment.aspx page instead it just refreshes.
The exception is raised because the thread running the operation is forced to terminate in multiple locations due to the transfer. As such, it is safe to ignore this exception as your linked answers suggest.
You can ignore the exception by catching the exception and not throwing it.
try
{
Server.Transfer("Payment.aspx?vpc_ChannelId=2", true);
}
catch(ThreadAbortException)
{
// Exception ignored: Thread Abort = discontinue processing on the current page
}
Alternatively, as the MSDN article suggest, you can use Server.Execute instead.
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.
// Clarification on Server.Execute
The MSDN doc clarifies the usage of Server.Execute. It is important to remember this is not a redirect, it acts like a function call. So any code after the call will also be executed. If you do not want the code to execute you can use a return, or Response.End.
In the OP's example, his code might look something like this when using Server.Execute
protected void Page_Load(object sender, EventArgs e)
{
try
{
UserContext conObj = new UserContext();
HttpContext CurrContext = HttpContext.Current;
if (!IsPostBack)
{
// Code
}
else
{
string userContext = hdnContextObj.Value;
conObj = JsonConvert.DeserializeObject<UserContext>(userContext);
CurrContext.Items.Add("Context", conObj);
Server.Execute("Payment.aspx?vpc_ChannelId=2", true);
Response.End(); // or return;
}
}
catch (Exception xObj)
{
Response.Write("Exception : " + xObj.Message);
}
}
Server.Transfer("Payment.aspx?vpc_ChannelId=2", false);
This will work for you. It stops the rest of the remaining code after the transfer code, so that it will not execute that code.
ThreadAbortException exception caused because Response.End called both in Server.Redirect and Server.Transfer internally.Try something like this
Response.Write("<script language=\"javascript\" type=\"text/javascript\">window.location.href = 'Your.aspx'; </script>");
This issue drives me insane, as I can't see what's causing it. The behavior is unexpected and I just can't see how it can occur. When I execute my plugin using the code below, I get the error message "bada boom". Just as expected.
public void Execute(IPluginExecutionContext context)
{
throw new Exception("bada boom");
try
{
throw new Exception("bada bing");
...
} catch (Exception) { }
...
}
However, when I comment out the first throw, I don't get to see "bada bing". Instead, I get "object not set to a reference"! What the duck?! (Typo intended.)
public void Execute(IPluginExecutionContext context)
{
//throw new Exception("bada boom");
try
{
throw new Exception("bada bing");
...
} catch (Exception) { }
...
}
Here's graphics for the issue.
In your first example the exception is handled at the caller level and up till a catch block is found. In the second example the exception is handled in the mandatory catch or finally block associated with the try of the Execute method.
So in the code inside that catch or finally block you have a null reference exception
void Main()
{
try
{
Execute();
}
catch(Exception x)
{
Console.WriteLine("In main: " + x.Message);
}
}
public void Execute()
{
// Goes to the catch block in main
//throw new Exception("bada boom");
try
{
// Goes to the catch block associated with this try
throw new Exception("bada bing");
}
catch(Exception x)
{
// Uncomment this to see the null reference exception in main
// Console.WriteLine("In Execute: " + x.InnerException.Message);
Console.WriteLine("In Execute:" + x.Message);
}
}
Well, of course, when I say mandatory I want to say that you cant write
try
{
....
}
without a catch or a finally clause following the try. And you can write a catch or finally block without code, but you can't omit one of the two keywords and its block
I have a server-side WCF RIA Service that is intentionally throwing an exception because the user entered an invalid value. This exception comes across the wire, however, I can't figure out how to catch it. I currently have the following code:
try
{
DomainContext.CalculateRequest(OnCalculateCompleted, null);
}
catch (Exception ex)
{
MessageBox.Show("here");
}
...
private void OnCalculateCompleted(InvokeOperation response)
{
try
{
if (response.HasError == false)
{
// Do stuff with result
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
How do I handle exceptions thrown by a server-side operation on the client side? None of my catch statements are being triggered. Thank you!
On the client side the InvokeOperation.HasErrors will be true and you can get the Exception object from the InvokeOperation.Error. Note, if you handled the error you should also call MarkErrorAsHandled().
Your OnCalculateCompleted might looks something like this.
private void OnCalculateCompleted(InvokeOperation response)
{
if (response.HasError == false)
{
// Do stuff with result
}
else
{
MessageBox.Show(response.Error.Message);
response.MarkErrorAsHandled();
}
}
Yes, because in the callback (OnCalculateCompleted), exception will not be marshalled. The exception will reside in the response.Error property.
But take care, because your server-side thrown exception will NOT be found in the response.Error!
You should override your DomainService's OnError method, package your server-side exception via errorcodes or something, and on the client (SL) side, you have to unpack it again.
How is it possible to resume code execution after an exception is thrown?
For example, take the following code:
namespace ConsoleApplication1
{
public class Test
{
public void s()
{
throw new NotSupportedException();
string #class = "" ;
Console.WriteLine(#class);
Console.ReadLine();
}
}
public class Program
{
public static void Main(string[] args)
{
try
{
new Test().s();
}
catch (ArgumentException x)
{
}
catch (Exception ex)
{
}
}
}
}
After catching the exception when stepping through, the program will stop running. How can I still carry on execution?
EDIT: What I specifically mean is the line Console.WriteLine(#class); does not seem to be hit, because when I run to it when in debug mode, the program exits from debug mode. I want to run to this line and stop at it.
Thanks
Well, you don't have any code after the catch blocks, so the program would stop running. Not sure what you're trying to do.
The following should be proof that the program doesn't simply "stop" after the catch blocks. It will execute code after the catch blocks if there is code to be executed:
static void Main(string[] args)
{
try
{
new Test().s();
}
catch (ArgumentException x)
{
Console.WriteLine("ArgumentException caught!");
}
catch (Exception ex)
{
Console.WriteLine("Exception caught!");
}
Console.WriteLine("I am some code that's running after the exception!");
}
The code will print the appropriate string depending on the exception that was caught. Then, it will print I am some code that's running after the exception! at the end.
UPDATE
In your edit you asked why Console.WriteLine(#class); does not seem to be hit. The reason is that you are explicitly throwing an exception in the very first line of your s() method; anything that follows is ignored. When an exception is encountered, execution stops and the exception is propagated up the call stack until the appropriate handler can handle it (this may be a catch block that corresponds to the try that wraps the statement in question within the same method, or it may be a catch block further up the call-stack. If no appropriate handler is found, the program will terminate with a stacktrace [at least in Java - not sure if the same happens in C#]).
If you want to hit the Console.WriteLine line, then you shouldn't be explicitly throwing an exception at the beginning of the method.
It sounds like you're wanting resumeable exceptions. C# doesn't do resumeable exceptions, and I'm doubtful that CLR supports them.
The purpose of throwing an exception is to abort a function and an entire operation (call stack) if/when something in the call environment (parameters, object state, global state) makes the function's operation impossible or invalid. Passing a zero param to a function that needs to divide a quantity by that param, for example. Division by zero won't produce a meaningful result, and if that's the sole purpose of the function, then the function can't return a meaningful result either. So, throw an exception. This will cause execution to jump to the nearest catch or finally block on the call stack. There is no returning to the function that threw the exception.
If you want to step into your code in the debugger to trace the Console.WriteLine() calls, you need to remove the throw new NotSupportedException() line from your code and recompile.
If you're worried that an exception will be thrown in the method but you want the method to continue, add an error handler inside the method.
class Test
{
public void s()
{
try
{
// Code that may throw an exception
throw new NotSupportedException();
}
catch(Exception ex)
{
// Handle the exception - log?, reset some values?
}
string #class = "" ;
Console.WriteLine(#class);
Console.ReadLine();
}
}
You could also return a bool or some other value to indicate the state.
Disclaimer: I am not suggesting that you actually do this.
You can mimic the old VB style On Error Resume Next with the following code.
public static class ControlFlow
{
public static Exception ResumeOnError(Action action)
{
try
{
action();
return null;
}
catch (Exception caught)
{
return caught;
}
}
}
And then it could be used like the following.
public static void Main()
{
ControlFlow.ResumeOnError(() => { throw new NotSupportedException(); });
ControlFlow.ResumeOnError(() => { Console.WriteLine(); });
ControlFlow.ResumeOnError(() => { Console.ReadLine(); });
}
Some simple code I put together to catch exceptions that are thrown inside a catch block:
try
{
//do code here
}
catch (Exception ex)
{
try { SomeMethod1(); }
catch { }
try { SomeMethod2(); }
catch { }
try { SomeMethod3(); }
catch { }
}
finally
{
//cleanup goes here
}
Execution is still carying on but there is no code after the exception is caught. If you want to repeatedly call s then consider wrapping the try/catch block in a while loop.
The program stops running because there is no following code to be executed in the Main() method! You can add the following line to your code to keep the program running until there is a console input:
Console.ReadLine();
For that code, you can't. If you break the tasks up to smaller chunks, you can resume at the next chunk. But normally it's easier to have a different mechanism than exceptions to report non-fatal errors, such as a callback function which returns whether or not to continue.
You can use the "step-over" feature in debugging to achieve this on a per-run basis.
Instead of thowing the NotSupportedException, you could track that an exception was encountered, use a default value, and throw the exception at the end of the method call:
namespace ConsoleApplication1
{
public class Test
{
public void s()
{
bool exceptionEncountered = false;
if(someConditionNotSupported){//stub condition
exceptionEncountered=true
#class="DefaultValue";
}
Console.WriteLine(#class);
Console.ReadLine();
if(exceptionEncountered){
throw new NotSupportedException();
}
}
}
public class Program
{
public static void Main(string[] args)
{
try
{
new Test().s();
}
catch (ArgumentException x)
{
}
catch (Exception ex)
{
}
}
}
}
public static void Main()
{
for (int j = 0; j <= 100000; j++)
{
try
{
// TODO: Application logic...
}
catch
{
System.Threading.Thread.Sleep(1000);
}
}
}