I am just starting with ASP.Net. I copied a ex-co-worker's code (from .Net 1.1 era) and it has a Response.End(); in case of an error. There is also a:
catch (Exception ex)
{
Response.Write(ex.Message);
Response.End();
}
at the end of Page_Load(object sender, System.EventArgs e) which always appends "Thread was aborted." or something like that at the end. I suspect that this worked differently before, or the error conditions were not tested very well.
Anyhow, I was able to stop using Response.End(); in case when I do not like the GET parameters, and use return; instead. It seemed to do the right think in a simple case.
Is this Ok in general?
There are some problems with the code I copied, but I do not want to do a rewrite; I just want to get it running first and find wrinkles later. The Response.End(); caused a mental block for me, however, so I want to figure it out.
I want to keep the catch all clause just in case, at least for now. I could also end the method with:
catch (System.Threading.ThreadAbortException)
{
Response.End();
}
catch (Exception ex)
{
Response.Write(ex.Message);
Response.End();
}
but that just seems extremely stupid, once you think about all of the exceptions being generated.
Please give me a few words of wisdom. Feel free to ask if something is not clear. Thanks!
P.S. Ex-coworker was not fired and is a good coder - one more reason to reuse his example.
catch (System.Threading.ThreadAbortException)
{
Response.End();
}
catch (Exception ex)
{
Response.Write(ex.Message);
Response.End();
}
This actually won't even work. ThreadAbortException is a special case exception, and when your catch block is done, it is automatically re-thrown.
Just using return is definitely the best case, if the method you are in is the last thing that will be run in terms of your code. If it's not, and you want to end the request gracefully, you can call HttpApplication.CompleteRequest(), which will skip processing the rest of the lifecycle and jump directly to the EndRequest event processing.
According to the MSDN, all this call does is stop processing and return the current results. Therefore, calling Response.End() at the END of your processing should have no effect.
In practice, I've only used this to abort current processing mid way through.
You shouldn't be catching all your exceptions at this level. Use the Application_Error event in the global.asax to handle unexpected errors and provide a custom error page to show to your clients (see the customError section in the web.config).
In general, you should only catch exceptions you should handle, and you should not output error trace to your users. The response.end he is using is only required due to this odd error handling technique.
Look at it this way.. If your page has any other page methods that run after Page_Load in the page lifecycle (Page_Render, Page_PreRender), or if there is any other code directly after the try-catch - then you should leave the Response.End() in place.
If there's nothing like it - then you can remove them if you want, nothing should happen differently. But taking into consideration that this is an old internal (even legacy maybe? copied from .NET 1.1) app, not written by yourself, you can probably leave them in place.. They will definitely not hurt, and might save you from hard-to-catch strange problems, which are usually found in legacy apps :D
Related
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.
Is there any performance problem or something else about letting the exception to propagate, or it is better to write it like this
try
{
}
catch
{
throw;
}
If you're not going to handle the exception it's better to have nothing rather than what you propose. All that does is add the overhead of catching and then rethrowing the same exception.
If you can handle the exception do so, but then don't propagate it further up the call stack.
The only time I can think of when I'd have that kind of empty catch\rethrow logic is when I'd want to log the exception in some way, otherwise I'd just let it propagate.
EDIT: added the missing word empty
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.
I am using Server.Transfer. Everything works fine, but exception log shows following exception.
System.Threading.ThreadAbortException: Thread was being aborted.
at System.Threading.Thread.AbortInternal()
at System.Threading.Thread.Abort(Object stateInfo)
at System.Web.HttpResponse.End()
at System.Web.HttpServerUtility.Transfer(String path, Boolean preserveForm)
at System.Web.HttpServerUtility.Transfer(String path)
Any idea to avoid above exception.
This exception is throw by the call to Server.Transfer in order to halt the execution of the current method - exactly the same thing gets thrown if you do Response.Redirect.
The two choices you have are:
Catch and rethrow the
ThreadAbortException / reperform the
Server.Transfer
Make sure that you
only do Server.Transfer in places
where it wont be caught (recommended)
EDIT: Scratch that, http://support.microsoft.com/kb/312629 has a couple of other suggestions to try, but I still recommend #2 above.
Another way to solve this, is to catch the generated error and to not rethrow it:
catch (ThreadAbortException)
{
}
Caling Server.Transfer will call Response.End which always throws a ThreadAbortException. This is a "special" exception because while it can be caught in a catch block, it will always be re thrown at the end of the catch block. I would have your error logging ignore ThreadAbortExceptions.
This problem occurs in the Response.Redirect and Server.Transfer methods because both methods call Response.End internally.
Solution for this Problem is as follows.
For Server.Transfer, use the Server.Execute method instead.
Visit this link for download sample example. http://jayeshsorathia.blogspot.com/2012/03/thread-was-being-aborted-error-occured.html
Replace Response.End() With HttpContext.Current.ApplicationInstance.CompleteRequest();
Replacing Response.End() by the following helped fix the problem.
Response.Flush();
Response.Close();
Refer Can we use Response.Flush () instead of Response.End()
I understand that if you put a Response.Redirect inside a try-catch that you're going to get this error unless you specify the 2nd param of the redirect as false.
But even looking at this article (PRB: ThreadAbortException Occurs If You Use Response.End, Response.Redirect, or Server.Transfer) I still don't understand why I have to set this to false for this particular line of code...we've always had true for that param until I wrapped that in a try-catch:
Response.Redirect(SecureUrl("Confirmation", SessionID), true);
We want to close it because it's the end of the line..the confirmation page. But when this is wrapped in the try-catch I get that error. I just want to understand better why false. I read the article and it doesn't jump out at me.
If you pass true as the second parameter, it will throw a ThreadAbortException to stop processing the request.
Code inside of ASP.Net will catch the ThreadAbortException, call Thread.ResetAbort, and send the (HTTP 301) response.
If you have a catch block, you will also see the ThreadAbortException, just as you'd see any other exception.
The best thing for you to do is to add an empty catch block for ThreadAbortException before your catch block, like this:
} catch(ThreadAbortException) { throw; }