I'm trying to log with Elmah exceptions handled in try...catch blocks.
I have added a global handle error filter on Global.axax:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new ElmahHandledErrorLoggerFilter());
filters.Add(new HandleErrorAttribute());
}
This is my ElmahHandledErrorLoggerFilter:
public class ElmahHandledErrorLoggerFilter : IExceptionFilter
{
public void OnException(ExceptionContext context)
{
if (context.ExceptionHandled)
ErrorSignal.FromCurrentContext().Raise(context.Exception);
}
}
It will only log the Exception as in try{ ... }catch{ throw new Exception(); }. But that's not the problem, the problem is that I have a method with a try-catch called from the code already inside another try-catch. In this case although I put throw new Exception() inside the catch of the inner-method it doesn't log the exception, it goes back to the catch in the first method without logging the Exception. For example:
public void MainMethod()
{
try
{
SecondMethod();
}
catch
{
....second method jump here.....
}
}
public void SecondMethod()
{
try
{
int a =0;
int b =;
int result = b/a;
}
catch
{
throw new Exception();
}
}
The exception thrown by SecondMethod is not being logged by Elmah. It goes back to the main method catch. If the main method catch also has a throw new Exception() code then it logs the exception. However it will be logged with the stack trace pointing to MainMethod and not to the SecondMethod.
What I wanted what was that every time it reaches a catch without rethrowing a new Exception, Elmah would log the exception. This is because I have many try-catch blocks in my application and I want to log these exceptions without manually logging on each try-catch. However if you tell me how can I log the exception from SecondMethod that would be fine.
Are you using ASP MVC?
The filters will only execute for unhandled exceptions thrown from the controller methods. (The context.ExceptionHandled property tells you if it has been handled by another filter, not in a try-catch block). So if you swallow the exceptions in try-catch blocks inside your methods then they will not be handled by the error filters.
You need to decide when you want to manually handle the exceptions inside your code using try-catch blocks (and in that case manually log the exceptions with the aid of a base controller class or a helper class) or let the exception bubble and be handled by your filters. (You probably will want a mixture of the two, depending on each particular use case)
When you decide to rethrow the exceptions, take a look at this SO question. Basically you can rethrow an exception preserving the stack trace with:
try
{
//code
}
catch (Exception ex)
{
//...some error handling code here...
//Otherwise why the try-catch at all?
throw;
}
You could do that in your sample MainMethod and the exception logged would preserve the stack trace.
Related
I want to be able to catch exception with the Postsharp OnMethodBoundary.OnException. But only once. Let me explain.
I have these method :
public void FooV1(){
throw new NotYetImplementedException();
}
public void FooV2(){
try{
throw new NotYetImplementedException();
} catch(Exception) {
Console.Writeline("Exception has be caught by catch block.");
}
}
And this OnException :
public void OnException(MethodExecutionArgs args){
Console.Writeline("Exception has be caught by Postsharp.");
}
When an exception occurs, the exception is beeing caught, I do some work (save the context) but I don't want to interfere with the program workflow. So if the exception is raised in a try catch block, it will be caught , if not, then it will raise the exception.
If in the OnException(...) I use args.FlowBehavior = FlowBehavior.Default;
I get :
In Foov1:
Exception has be caught by Postsharp.
Exception has be caught by Postsharp.
Because when the exception in rethrown Postsharp recatch it (but only one time ? I expected it to loop). I would like to get OnException to be called only once and if the exception is not caught higher in the callstack then the program should stop.
And in FooV2:
Exception has be caught by Postsharp.
Exception has be caught by catch block.
There I get the expected result.
I can't use FlowBehavior.Continue or FlowBehavior.Return because the catch block would not be reached.
And I don't see the difference between FlowBehavior.Throw and FlowBehavior.Rethrow
How can I fix that ?
I don't know what your actual code is but you're probably applying your OnException aspect to two or more methods: both the method that throws the original exception and the method that catches the exception. That would explain why you are seeing the OnException message twice.
When you do
[YourPostSharpOnExceptionAspect]
void A()
{
// code
}
It's translated into something roughly like:
void A()
{
try {
// code
} catch (Exception e) {
yourPostSharpOnExceptionAspectInstance.OnException(e);
throw;
}
}
Since each PostSharp aspect keeps rethrowing the same exception, you'll get to catch it multiple times.
You may need to add code of your own to handle each exception only once. You could do something like this:
public void OnException(MethodExecutionArgs args){
if (args.Exception.Data["Handled"]) {
// do nothing, already saved
args.FlowBehavior = FlowBehavior.Rethrow;
}
else
{
// first time seeing this exception, do stuff....
args.Exception.Data["Handled"] = true; // and mark the exception as processed
args.FlowBehavior = FlowBehavior.Throw;
}
}
The difference between Throw and Rethrow is that Throw adds something like throw args.Exception to the code while Rethrow adds merely throw; rethrowing the exception that was originally caught (and keeping the original stack trace).
I have the following code:
try
{
retval = axNTLXRemote.IsUnitPresent(_servers[0].IPAddress, 1, _servers[0].RemotePort, _servers[0].CommFailDelay * 1000);
}
catch (COMException ce)
{
throw ce;
}
Which gives me the followig warning which I want to get rid of:
CA2200 : Microsoft.Usage : 'Connect()' rethrows a caught exception and specifies it explicitly as an argument. Use 'throw' without an argument instead, in order to preserve the stack location where the exception was initially raised.
I have read the following The difference between try/catch/throw and try/catch(e)/throw e and I understand that the 'throw ce; will reset the stack trace and make it appear as if the exception was thrown from that function.
I want to simply change it to a 'throw' instead of a 'throw ce' which will get rid of the warning.
What is the difference in the following catches:
catch (COMException ce)
{
throw;
}
and
catch (COMException)
{
throw;
}
Do I only need to have 'COMException ce' if I wish to somehow use the ce variable?
Also, when I perform a 'throw' or 'throw ce', is it the calling function that will handle or catch it?? I'm a little unclear about this.
The only difference is that with catch (COMException ce), you are assigning the exception to a variable, thereby letting you access it within the catch block. Other than that, it is in every way identical.
I'm not sure what the question is here. If you want to access the exception object, you must give it a variable name in the catch clause.
No matter how or where an exception is thrown, the exception will bubble up through the call stack to the closest catch block that matches.
Here's an example.
void Method1()
{
try
{
Method2();
}
catch // this will catch *any* exception
{
}
}
void Method2()
{
try
{
Method3();
}
catch (COMException ex) // this will catch only COMExceptions and exceptions that derive from COMException
{
}
}
void Method3()
{
// if this code were here, it would be caught in Method2
throw new COMException();
// if this code were here, it would be caught in Method1
throw new ApplicationException();
}
I'm sure someone will jump in with an uber-technical answer, but in my experience the answer to your first two questions is that there is no difference, and as you stated you'd only include ce if you intended to use it to write the stack trace to a log or display the message to the user or similar.
The throw will send the exception up the chain. That may be the calling method or, if your method has several nested try/catch blocks, it will send the exception to the next try/catch block that the current try/catch block is nested within.
Here are a couple good resources to check out if you want to read further on the subject:
Exception Handling
Design Guidelines for Exceptions
There is no difference in both cases, but only when exception variable should be used for stack/message etc.
So:
catch(ComException);
and
catch(ComException ex);
statements will produce similar MSIL, except local variable for ComException object:
.locals init ([0] class [mscorlib]System.Exception ex)
i'm calling a function that throws a custom exception:
GetLockOwnerInfo(...)
This function in turn is calling a function that throws an exception:
GetLockOwnerInfo(...)
ExecuteReader(...)
This function in turn is calling a function that throws an exception:
GetLockOwnerInfo(...)
ExecuteReader(...)
ExecuteReader(...)
And so on:
GetLockOwnerInfo(...)
ExecuteReader(...)
ExecuteReader(...)
ExecuteReaderClient(...)
Fill(...)
One of these functions throws an SqlException, although that code has no idea what an SqlException is.
Higher levels wrap that SqlException into another BusinessRuleException in order to include some special properties and additional details, while including the "original" exception as InnerException:
catch (DbException ex)
{
BusinessRuleExcpetion e = new BusinessRuleException(ex)
...
throw e;
}
Higher levels wrap that BusinessRuleException into another LockerException in order to include some special properties and additional details, while including the "original" exception as InnerException:
catch (BusinessRuleException ex)
{
LockerException e = new LockerException(ex)
...
throw e;
}
The problem now is that i want to catch the origianl SqlException, to check for a particular error code.
But there's no way to "catch the inner exception":
try
{
DoSomething();
}
catch (SqlException e)
{
if (e.Number = 247)
{
return "Someone";
}
else
throw;
}
i thought about catching SqlException right when it's thrown, and copy various values to the re-thrown exception - but that code is not dependant on Sql. It is experiencing an SqlException, but it has no dependency on SqlException.
i thought about catching all exceptions:
try
{
DoSomething(...);
}
catch (Exception e)
{
SqlException ex = HuntAroundForAnSqlException(e);
if (ex != null)
{
if (e.Number = 247)
{
return "Someone";
}
else
throw;
}
else
throw;
}
But that's horrible code.
Given that .NET does not let you alter the Message of an Exception to include additional information, what is the intended mechanism to catch original exceptions?
You need c# 6 / visual studio 2015 in order to do this using a predicate:
catch (ArgumentException e) when (e.ParamName == “…”)
{
}
Official C# Try/Catch Documentation
I hate to have to tell you this, but you cannot catch an inner exception.
What you can do is inspect one.
I suggest you catch your high-level exception (I believe it was LockerException) and inspect the InnerException property of that exception. Check the type, and if it's not a SqlException, check the InnerException of that exception. Walk each one until you find a SqlException type, then get the data you need.
That said, I agree with dasblinkenlight that you should consider -- if possible -- a heavy refactor of your exception framework.
Checking the error code of a wrapped exception is not a good practice, because it hurts encapsulation rather severely. Imagine at some point rewriting the logic to read from a non-SQL source, say, a web service. It would throw something other than SQLException under the same condition, and your outer code would have no way to detect it.
You should add code to the block catching SQLException to check for e.Number = 247 right then and there, and throw BusinessRuleException with some property that differentiates it from BusinessRuleException thrown in response to non-SQLException and SQLException with e.Number != 247 in some meaningful way. For example, if the magic number 247 means you've encountered a duplicate (a pure speculation on my part at this point), you could do something like this:
catch (SQLException e) {
var toThrow = new BusinessRuleException(e);
if (e.Number == 247) {
toThrow.DuplicateDetected = true;
}
throw toThrow;
}
When you catch BusinessRuleException later, you can check its DuplicateDetected property, and act accordingly.
EDIT 1 (in response to the comment that the DB-reading code cannot check for SQLException)
You can also change your BusinessRuleException to check for SQLException in its constructor, like this:
public BusinessRuleException(Exception inner)
: base(inner) {
SetDuplicateDetectedFlag(inner);
}
public BusinessRuleException(string message, Exception inner)
: base(message, inner) {
SetDuplicateDetectedFlag(inner);
}
private void SetDuplicateDetectedFlag(Exception inner) {
var innerSql = inner as SqlException;
DuplicateDetected = innerSql != null && innerSql.Number == 247;
}
This is less desirable, because it breaks encapsulation, but at least it does it in a single place. If you need to examine other types of exceptions (e.g. because you've added a web service source), you could add it to the SetDuplicateDetectedFlag method, and everything would work again.
Having an outer application layer care about the details of a wrapped exception is a code smell; the deeper the wrapping, the bigger the smell. The class which you now have wrapping the SqlException into a dbException is presumably designed to expose an SqlClient as a generic database interface. As such, that class should include a means of distinguishing different exceptional conditions. It may, for example, define a dbTimeoutWaitingForLockException and decide to throw it when it catches an SqlException and determines based upon its error code that there was a lock timeout. In vb.net, it might be cleaner to have a dbException type which exposes an ErrorCause enumeration, so one could then say Catch Ex as dbException When ex.Cause = dbErrorCauses.LockTimeout, but unfortunately exception filters are not usable in C#.
If one has a situation where the inner-class wrapper won't know enough about what it's doing to know how it should map exceptions, it may be helpful to have the inner-class method accept an exception-wrapping delegate which would take an exception the inner class has caught or would "like" to throw, and wrap it in a way appropriate to the outer class. Such an approach would likely be overkill in cases where the inner class is called directly from the outer class, but can be useful if there are intermediate classes involved.
Good question and good answers!
I just want to supplement the answers already given with some further thoughts:
On one hand I agree with dasblinkenlight and the other users. If you catch one exception to rethrow an exception of a different type with the original exception set as the inner exception then you should do this for no other reason than to maintain the method's contract. (Accessing the SQL server is an implementation detail that the caller is not/must not/cannot be aware of, so it cannot anticipate that a SqlException (or DbException for that matter) will be thrown.)
Applying this technique however has some implications that one should be aware of:
You are concealing the root cause of the error. In your example you are reporting to the caller that a business rule was invalid(?), violated(?) etc., when in fact there was a problem accessing the DB (which would be immediately clear if the DbException were allowed to bubble up the call stack further).
You are concealing the location where the error originally occurred. The StackTrace property of the caught exception will point to a catch-block far away from the location the error originally occurred. This can make debugging notoriously difficult unless you take
great care to log the stack traces of all the inner exceptions as well. (This is especially true once the software has been deployed into production and you have no means to attach a
debugger...)
Given that .NET does not let you alter the Message of an Exception to include additional information, what is the intended mechanism to catch original exceptions?
It is true that .NET does not allow you to alter the Message of an Exception. It provides another mechanism however to supply additional information to an Exception via the Exception.Data dictionary. So if all you want to do is add additional data to an exception, then there is no reason to wrap the original exception and throw a new one. Instead just do:
public void DoStuff(String filename)
{
try {
// Some file I/O here...
}
catch (IOException ex) {
// Add filename to the IOException
ex.Data.Add("Filename", filename);
// Send the exception along its way
throw;
}
}
As other peeps say, you cannot catch an the InnerException. A function such as this could help you get the InnerException out of the tree though:
public static bool TryFindInnerException<T>(Exception top, out T foundException) where T : Exception
{
if (top == null)
{
foundException = null;
return false;
}
Console.WriteLine(top.GetType());
if (typeof(T) == top.GetType())
{
foundException = (T)top;
return true;
}
return TryFindInnerException<T>(top.InnerException, out foundException);
}
I agree with the other comments that this is a code smell 🦨 and should be avoided. But if a refactor is not possible you could try something like this...
Create an extension method...
public static bool HasInnerException(this Exception ex, Func<Exception, bool> match)
{
if (ex.InnerException == null)
{
return false;
}
return match(ex.InnerException) || HasInnerException(ex.InnerException, match);
}
And use it like...
catch (Exception ex) when (ex.HasInnerException(e => e is MyExceptionThatIsHidden))
{
...
But really you should be solving for 👇
var exception = new Exception("wrapped exception 3",
new Exception("wrapped exception 2",
new Exception("wrapped exception 1",
new MyExceptionThatIsHidden("original exception")))); // <--- ???
following is a code snippet:
class xxx
{
public xxx(){}
try
{
throw new Exception(InvalidoperationException);
}
catch(Exception x)
{
}
catch(InvalidoperationException x)
{
}
}
can anyone tell which exception will raise here and what is the reason behind it.
Wow, lots of problems here. Where to start?
That code won't compile. The try-catch block that you've defined is outside of any method, which is not allowed. You need to move it inside of a method.
Never throw a method that you intend to catch yourself later in the method. That's commonly known as using exceptions for "flow control", which is roundly discouraged. There is a performance cost associated with doing so, and it also makes it very confusing to monitor the exceptions that are being thrown when using a debugger when you have code that's throwing and catching it's own exceptions. Use boolean variables (known as flags) for flow control, if necessary.
Always catch the most derived exception class first. That means you should catch InvalidOperationException first, before trying to catch Exception. You need to reverse the order of your catch blocks in the code that you have.
You should practically never catch System.Exception. The only exceptions that you should catch are those that you explicitly understand and are going to be able to handle. There's virtually no way that you're going to know what went wrong or how to handle it when the only information you have is that a generic exception was thrown.
Along those same lines, you also should never throw this exception from your own code. Choose a more descriptive exception class that inherits from the base System.Exception class, or create your own by inheriting from the same.
I see that other answers are showing you sample code of what your code should look like, were it to be rewritten. I'm not going to do that because if I rewrote your code to be correct, I'd end up with this:
class Xxx
{
public Xxx()
{
}
}
Not particularly helpful.
If the code is like this
class xxx
{
public xxx(){
try
{
throw new Exception(InvalidoperationException);
}
catch(InvalidoperationException x)
{
}
catch(Exception x)
{
}
}
}
It should compile and raise your exception and catch. Otherwise your code will not compile at all.
No exception will be thrown as this code will not even compile.
Regardless - several points:
When using exception handling, put the more specific exception before the less specific ones (so the catch of InvalidOperationException should be before the one for Exception).
Catching Exception is normally no very useful.
If you catch an exception, do something with it.
You probably meant:
throw new InvalidOperationException();
However, the way you structured your exceptions, the catch(Exception x) block would have run.
You should write:
class xxx
{
public void Test()
{
try
{
throw new InvalidoperationException();
}
catch(InvalidoperationException exception)
{
// Do smth with exception;
}
catch(Exception exception)
{
throw; // Rethrows your exception;
}
}
}
InvalidOperationException inherits from Exception.
catch tries to processes the most specific branch, so catch (InvalidOperationException x) will be executed here.
Nope. It wouldn't compile. So, it there's no question about as to which exception will be generated.
Your code should be something like this :
class xxx
{
public void Test()
{
try
{
throw new InvalidoperationException();
}
catch(InvalidoperationException exception)
{
// Something about InvalidOperationException;
}
catch(Exception exception)
{
// Something about the Exception
}
}
}
Point to be noted :
Write more specific class of Exception first, hence we write InvalidOperationException prior to Exception class.
Ignoring the compile issue.... the first matching exception block (catch(Exception x)) will get the exception. You then ignore the exception and don't re-throw, so exception will be seen by the outside world. That doesn't make it good practice, though... in particular, catching an arbitrary Exception and ignoring it is risky - it could have been anything... it isn't necessarily the exception you thought it was.
Well, the code won't compile, but I'll just ignore that...
If I'll just look at the line:
throw new Exception(InvalidoperationException);
1st of all, according to MSDN there is no such constructor. So I will assume you meant the constructor: Exception(String msg, Exception innerException). Meaning:
throw new Exception("blabla", InvalidoperationException);
The exception that is being thrown is of type Exception and not InvalidOperationException. So ONLY catch(Exception x) can catch it.
If you would've thrown InvalidoperationException than the way you wrote the order of the catches, the Exception class would get caught first.
The order of the catches does matter.
The best advice I can give you is simply try it yourself and see what happens.
What is the difference between
try { }
catch
{ throw; }
and
try { }
catch(Exception e)
{ throw e;}
?
And when should I use one or the other?
The constructions
try { ... }
catch () { ... } /* You can even omit the () here */
try { ... }
catch (Exception e) { ... }
are similar in that both will catch every exception thrown inside the try block (and, unless you are simply using this to log the exceptions, should be avoided). Now look at these:
try { ... }
catch ()
{
/* ... */
throw;
}
try { ... }
catch (Exception e)
{
/* ... */
throw;
}
try { ... }
catch (Exception e)
{
/* ... */
throw e;
}
The first and second try-catch blocks are EXACTLY the same thing, they simply rethrow the current exception, and that exception will keep its "source" and the stack trace.
The third try-catch block is different. When it throws the exception, it will change the source and the stack trace, so that it will appear that the exception has been thrown from this method, from that very line throw e on the method containing that try-catch block.
Which one should you use? It really depends on each case.
Let's say you have a Person class with a .Save() method that will persist it into a database. Let's say that your application executes the Person.Save() method somewhere. If your DB refuses to save the Person, then .Save() will throw an exception. Should you use throw or throw e in this case? Well, it depends.
What I prefer is doing:
try {
/* ... */
person.Save();
}
catch(DBException e) {
throw new InvalidPersonException(
"The person has an invalid state and could not be saved!",
e);
}
This should put the DBException as the "Inner Exception" of the newer exception being throw. So when you inspect this InvalidPersonException, the stack trace will contain info back to the Save method (that might be sufficient for you to solve the problem), but you still have access to the original exception if you need it.
As a final remark, when you are expecting an exception, you should really catch that one specific exception, and not a general Exception, ie, if you are expecting an InvalidPersonException you should prefer:
try { ... }
catch (InvalidPersonException e) { ... }
to
try { ... }
catch (Exception e) { ... }
The first preserves the stack trace while the second resets it. This means that if you use the second approach the stack trace of the exception will always start from this method and you will lose the original exception trace which could be disastrous for someone reading exception logs as he will never find out the original cause of the exception.
The second approach might be useful when you want to add additional information to the stack trace but it is used like this:
try
{
// do something
}
catch (Exception ex)
{
throw new Exception("Additional information...", ex);
}
There's a blog post discussing the differences.
You should use
try { }
catch(Exception e)
{ throw }
if you want to do something with the exception before re-throwing it (logging for example). The lonely throw preserves stack trace.
The difference between a parameterless catch and a catch(Exception e) is that you get a reference to the exception. From framework version 2 unmanaged exceptions are wrapped in a managed exception, so the parameterless exception is no longer useful for anything.
The difference between throw; and throw e; is that the first one is used to rethrow exceptions and the second one is used to throw a newly created exception. If you use the second one to rethrow an exception, it will treat it like a new exception and replace all stack information from where it was originally thrown.
So, you shold not use either of the alternatives in the question. You should not use the parameterless catch, and you should use throw; to rethrow an exception.
Also, in most cases you should use a more specific exception class than the base class for all exceptions. You should only catch the exceptions that you anticipate.
try {
...
} catch (IOException e) {
...
throw;
}
If you want to add any information when rethrowing the exception, you create a new exception with the original exception as an inner exception to preservere all information:
try {
...
} catch (IOException e) {
...
throw new ApplicationException("Some informative error message", e);
}