Response.Redirect exception - asp.net

Executing the line:
Response.Redirect("Whateva.aspx", true);
Results in:
A first chance exception of type 'System.Threading.ThreadAbortException' occurred in mscorlib.dll
An exception of type 'System.Threading.ThreadAbortException' occurred in mscorlib.dll but was not handled in user code
The exception is because of the "true" part, telling it to end the current request immediately.
Is this how it should be?
If we consider:
Exceptions are generally considered heavy, and many times the reason for ending the request early is to avoid processing the rest of the page.
Exceptions show up in performance monitoring, so monitoring the solution will show a false number of exceptions.
Is there an alternative way to achieve the same?

You're right regarding the fact that the developer should avoid raising of (and catching) exceptions since the execution runtime consumes time and memory in order to gather the information about the particular exception. Instead he (or she) should simply not let them occur (when it's possible).
Regarding the Response.Redirect: this behavior is "by-design" but you might want to use a well-known workaround. Please read this KB article.
-- Pavel

One approach I generally take in this scenario is to not end the response during the response, but to follow it immediately with a return (or other flow control). Something like this:
Response.Redirect("Whateva.aspx", false);
return;
This depends on where the redirect is taking place in your logic flow, of course. However you want to handle it is fine. But the idea is that, when you want to end the response on the redirect anyway, then exiting the method in question via a return isn't out of the question.
One approach I've seen people take in this matter quite often, and it should go without saying that this is to be avoided but for completeness I'm going to say it anyway (you never know who may stumble upon this question later via Google, etc.), is to catch and swallow the exception:
try
{
Response.Redirect("Whateva.aspx", true);
}
catch (Exception ex)
{
// do nothing
}
This, of course, should not be done, for a number of reasons. As I inferred from your description of exceptions, you undoubtedly already know that this would be bad practice. But, as I said, it's worth noting this fact in the answer.

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.
from:
http://support.microsoft.com/kb/312629/en-us
Same link posted by Volpav.
Regards.

Related

TRY CATCH THROWS exception without logging

I am looking through someone elses code and there is plenty of code like this:
try
'Logic here
catch e as exception
throw
end try
I believe that the TRY and CATCH cause are pointless (they were probably used for debugging). Is there ever a scenario were coding like this is good practice?
There is a global even handler (global.asa).
I agree that these clauses are pointless and worse, add clutter to your code that adds nothing other than confusion.
Worse still: if they ever do Throw e instead of just Throw the stack on the original exception is lost.
No. There is no reason to have a try..catch that only throws. If you want to debug and catch exceptions at the moment they occur, you should halt on framework exceptions within Visual Studio (Debug menu -> Exceptions...).
I have the exact same thing in one of the programs I inherited and it's actually worse because catching is expensive in C# (only trying is free). I made it a point to remove a dozen of these every day, I should be done in a few more weeks.
Generally, you don't want to do this (and you don't want to catch System.Exception either).
That being said, there might be some cases where you want to Throw the exception further up the call stack, and Catch it elsewhere. Here is a trivial example:
Try
' Do some stuff here. For this example, let's assume
' it cannot cause any exceptions
Try
' Do some other stuff here that CAN cause an exception
Catch innerEx as Exception
' Rethrowing so that the outer block handles this
Throw
End Try
Catch ex as Exception
MessageBox.Show("I just caught an exception.")
End Try
IF you do something like this, common sense dictates that you should place a comment that states WHY you are doing this.
As I said, that is an overly trivial example, but a more common usage might be that you have a method that calls another method, and you want the first method to handle any exceptions that the 2nd method might throw. The behavior will be the same if you leave the Try/Catch block out of the 2nd method instead of rethrowing, but the Try/Catch and the comment make your intent a little more obvious.
EDIT: If you know which line of code is likely to throw the exception, then putting a comment above that line is probably preferable to adding the Try/Catch blocks.

ApplicationInstance.CompleteRequest doesn't stop the execution of the code below it?

I was told that Respond.Redirect is an expensive process because it raises a ThreadAbortException. So instead, we should be using the CompleteRequest function instead. So I gave it a try but I noticed the codes below it still runs, which I do not want. I want to instantly force the browser to jump to another website.
Public Shared Sub TestCompleteRequest()
If 1 = 1 Then
System.Web.HttpContext.Current.Response.Redirect("Http://Google.com", False)
System.Web.HttpContext.Current.ApplicationInstance.CompleteRequest()
End If
Throw New ApplicationException("Hello, why are you here?")
End Sub
As for the code above, the ApplicationException is still thrown. But why? :(
One method doesn't replace the other directly. The CompleteRequest() method does not end execution when it's called. So if that's really what you want to do then Response.Redirect(string) would be the way to go.
CompleteRequest() simply bypasses the Response.End() method, which is what generates the ThreadAbortException you mentioned, but crucially CompleteRequest() flushes the response buffer. This means the HTTP 302 redirect response is sent to the browser at the line where you call CompleteRequest(), which gives you a chance to do operations that don't affect the response after it's been sent to the user.
The solution for you really depends on what you need to achieve, can you provide an example of what you're using Response.Redirect for and what other code is in the same method?
Calling a method in the ASP.NET framework deals with the request, but the fact is you're still writing and running VB.NET - there's nothing in the language (nor should there be, I'd say) that indicates 'when this method returns, perform an Exit Sub'.
Who's to say you wouldn't want to execute some more of the method after telling ASP.NET to complete the request, anyway?

How to tell if Page_PreRender has run?

I'm running a method in an overridden Page OnUnload, but only if the Page_PreRender method has run.
Obviously, I can flip a class-level bool when I'm in Page_PreRender and check it in OnUnload, but if there's a more intrinsic way to tell is Page_PreRender has run, I'd like to use that.
Any ideas?
Thanks for any thoughts.
UPDATE: Let me rephrase my question slightly. I'm looking for the answer to whether there is a simple way, inherent in the Page life cycle, perhaps a property that is set by the ASP.Net frameowork, perhaps something else, that is different after Page_PreRender has run versus when Page_PreRender has not run.
I am currently setting a boolean in Page_PreRender to tell me if it has run. It works, but I don't like this solution if there is a way to accomplish the same thing without adding the extra boolean check. Creating an event that fires during Page_PreRender is the same level of redundancy I'd like to avoid, if possible.
You mention (in your comments on another post) that your problem manifests itself when calling Response.Redirect() because it throws a ThreadAbortException, which leads to your OnPreRender() event not being called. So why not use this instead?:
Response.Redirect("~/SomePage.aspx", false);
The "false" you see there indicates if execution of the page should terminate right there and then. By default, Response.Redirect() uses "true". If you need your OnPreRender() event to run so that your OnLoad() event will have everything it needs, then set it to "false" and just make sure you either jump to the end of your Page_Load() after calling Response.Redirect() or that the code that would execute after it is fine to run.
Maybe you don't like the idea of passing "false" using the overloaded Response.Redirect() method so that's why you didn't go that route. Here is some documentation that may help sway your mind:
Microsoft states that "passing false for the endResponse parameter is recommended" because specifying "true" calls the HttpResponse.End() method for the original request, which then throws a ThreadAbortException when it completes. Microsoft goes on to say that "this exception has a detrimental effect on Web application performance". See here in the "Remarks" section: http://msdn.microsoft.com/en-us/library/a8wa7sdt.aspx
This was posted last year on MSDN:
The End method is also on my “never
use” list. The best way to stop the
request is to call
HttpApplication.CompleteRequest. The
End method is only there because we
tried to be compatible with classic
ASP when 1.0 was released. Classic
ASP has a Response.End method that
terminates processing of the ASP
script. To mimic this behavior,
ASP.NET’s End method tries to raise a
ThreadAbortException. If this is
successful, the calling thread will be
aborted (very expensive, not good for
performance) and the pipeline will
jump ahead to the EndRequest event.
The ThreadAbortException, if
successful, of course means that the
thread unwinds before it can call any
more code, so calling End means you
won’t be calling any code after that.
If the End method is not able to raise
a ThreadAbortException, it will
instead flush the response bytes to
the client, but it does this
synchronously which is really bad for
performance, and when the user code
after End is done executing, the
pipeline jumps ahead to the EndRequest
notification. Writing bytes to the
client is a very expensive operation,
especially if the client is halfway
around the world and using a 56k
modem, so it is best to send the bytes
asynchronously, which is what we do
when the request ends the normal way.
Flushing synchronously is really bad.
So to summarize, you shouldn’t use
End, but using CompleteRequest is
perfectly fine. The documentation for
End should state that CompleteRequest
is a better way to skip ahead to the
EndRequest notification and complete
the request.
I added this line after calling Response.Redirect(), as MSDN suggests, and noticed everything appeared to run the same. Not sure if it's needed with 4.0, but I don't think it hurts:
HttpContext.Current.ApplicationInstance.CompleteRequest();
Update 1
Using "false" in the call to Response.Redirect() avoids the ThreadAbortException, but what about other Unhandled Exceptions that could be thrown on your page? Those exceptions will still cause your problem of OnUnload() being called without OnPreRender(). You can use a flag in OnPreRender() as everyone suggests to avoid this, but if you're throwing Unhandled Exceptions, you've got bigger problems and should be redirecting to an error page anyway. Since Unhandled Exceptions aren't something you plan to throw on every postback, it would be better if you wrapped your OnUnload() logic in a Try-Catch. If you're logging and monitoring your exceptions you will see that an Unhandled Exception was thrown right before logging a NullReference Exception in the OnUnload() event and will know which one to ignore. Because your OnUnload() will have a Try-Catch, it will safely continue processing the rest of the page so you can Redirect to the error page as expected.
Update 2
You should still have your OnUnload() wrapped in a Try-Catch, but I think this is what you're really looking for (remember IsRequestBeingRedirected will be true when calling Response.Redirect or when redirecting to an error page after an Unhandled Exception).:
if (HttpContext.Current.Response.IsRequestBeingRedirected != true)
{
//You're custom OnUnload() logic here.
}
With this, you will know if it is safe (or even worth it) to process your custom logic in the OnUnload() event. I realize I should have probably lead off with this, but I think we learned a lot today. ;)
NOTE: The use of Server.Transfer() will also call the dreaded Response.End(). To avoid this, use Server.Execute() with the preserveForm attribute set to "false" instead:
Server.Execute("~/SomePage.aspx", false);
return;
NOTE: The thing about Server.Execute("~/SomePage.aspx", false); is that IsRequestBeingRedirected will be false, but your OnPreRender() will still execute, so no worries there.
The answer is Yes, you can, but not always :)
According the Reflection code, the ScriptManager class contains the private bool field _preRenderCompleted, which is set to true while handling internal IPage interface PagePreRenderComplete event.
You can use the Reflection to get this field from ScriptManager.GetCurrent(page) resulting object
I am not sure what exactly you mean by this. According to the ASP.NET Page Lifecycle PreRender always runs before Unload. If you perform some if condition inside this PreRender event and you would like to test in the Unload whether the condition was satisfied a boolean field on the page class seems a good idea.
Add trace=true to the page directive.
Set a boolean field in the PreRender event handler, then check if it was set in the Unload event handler.
Create a custom event that fires in the PreRender event.
I don't think there is any sort of state stored because the ASP.NET engine does not really need that, as it knows its state implicitely.
Searching with .NET Reflector, it seems the page render events are raised from this internal System.Web.UI.Page method:
private void ProcessRequestMain(bool includeStagesBeforeAsyncPoint, bool includeStagesAfterAsyncPoint)
You can have a look at it, there is no notion of state. The only information you can get is the trace. If you have access to the Unload event, then you should have access to the trace? or I miss something :-)
Since the trace is in fact a dataset undercovers (see my answer here: Logging the data in Trace.axd to a text/xml file), you maybe could get the information. But
setting trace=true is not recommended in production though...

Asp.net MVC exception not being caught in try catch block

Could anyone tell me why a problem in the noun model would not be caught by this try catch?
I have tried this on two different controller methods now, and both times, even if the linq2sql doesn't allow the data to be saved, the code never jumps into the catch block.
I've watched the noun object in the middle of the trace, and the isvalid property is false, but the modelstate isvalid is true. Either way, the code never jumps into the catch block.
I'm pulling my hair out about this. I feel like it will be something really silly.
The code all works similar to nerd dinner.
NounRepository nounRepository = new NounRepository();
Noun noun = new Noun();
try
{
UpdateModel(noun);
nounRepository.Add(noun);
nounRepository.save();
}
catch (Exception ex)
{
ModelState.AddRuleViolations(noun.GetRuleViolations());
return View(noun);
}
return View(noun);
Update
I have just added this code, and now the rules are coming back to the front end fine, so it just seems that the try catch isn't catching!
UpdateModel(noun);
if (!noun.IsValid)
{
var errors = noun.GetRuleViolations();
ModelState.AddRuleViolations(noun.GetRuleViolations());
return View(noun);
}
nounRepository.Add(noun);
nounRepository.save();
I'd rather not have to add code in this manner though, as it seems like an unnecessary duplication.
You faced logical change in mvc - validation here do not throw exceptions. Indeed, you need to check it using if statement.
I doubt that exception is happening - you need to catch linq2sql exception anyway, code is correct. Also there is high a chance that inside 'save' or 'add' you have another catch - this is quite common mistake
Programming Rule #1: catch ain't broken (AKA: SELECT ain't broken).
If you're really in doubt, open up the Debug menu, choose "Exceptions", then tick the box for "Common Language Runtime Exceptions" under "Thrown." This will cause the debugger to break on all first-chance exceptions. If the debugger doesn't break during your update, then the exception is never getting thrown in the first place.
Don't forget to untick when you're done, as the behaviour gets pretty annoying under normal usage.
P.S. Never catch System.Exception. Catch the specific type(s) of exception(s) that you know might actually be thrown.
Are you doing something in another thread? That is often a cause exceptions not being caught.

ASP.NET: What happens to code after Response.Redirect(...)?

Does Response.Redirect() cause the currently running method to abort? Or does code after Response.Redirect() execute also?
(That is, is it necessary to return/Exit Sub after a Response.Redirect?)
Response.Redirect has an overload accepting a boolean argument that indicates if the call to Response.Redirect should end the response. Calling the overload without this argument is the same as specifying true to indicate that the response should end.
Ending the reponse means that Response.End is called after the response has been modified to make the redirect happen, and Response.End throws an ThreadAbortException to terminate the current module.
Any code after a call to Response.Redirect is never called (unless you supply false for the extra argument). Actually, code in finally and certain catch handlers will execute, but you cannot swallow a ThreadAbortException.
This may not be a complete answer, but from what I've seen...
Response.Redirect does, actually cause the code to stop executing by throwing a System.Threading.ThreadAbortException.
You can see this for yourself by setting up global error handling in the Global.Asax and testing a Response.Redirect.
EDIT
and here is a link to the documentation that supports my answer:
Redirect calls End which raises a
ThreadAbortException exception upon
completion.
HttpResponse.Redirect Method (String, Boolean) (System.Web)
There is another parameter to Response.Redirect called endResponse. Setting it false is a good idea when you're redirecting in a try catch block because the context still needs control to be correct. So your catch block will pick up the exception.
The caveat to that is that when the page is not Cancelable then it won't try to get control. The most common case of this is Global.asax. So you don't need to worry about this exception in that context. If you don't believe me try reflecting the code for this method and take a look.
So to answer your question it isn't necessary to do much after a Response.Redirect when you set endResponse to true which it is by default (i.e. called with the method that doesn't take a bool).
My understanding is that upon issuing a Response.Redirect(), code following it will not execute. If you think about it, it would make sense not to execute it. You're basically telling your code that you want to go somewhere else.
Example: Think of it as ordering a value meal at McDonalds. After you order it and they start filling your drink, you change your mind and say "you know what, forget my order. I'm going to Redirect myself to Wendy's." At that point, they're going to stop making your fries and burger because, well... you've decided to go somewhere else -- i.e. redirecting the response.

Resources