I am working with WebApi and ELMAH and I would like to be able to wrap some business errors into web responses for some thypes of exceptions(no logging) and have the others logged by ELMAH. Right no I have this piece of code.
public async override Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)
{
try
{
return await base.ExecuteAsync(controllerContext, cancellationToken);
}
catch (MyException ex)
{
return new HttpResponseMessage(CustomCode)
{
Content = new StringContent(CustomMessage)
};
}
catch (Exception ex)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
return new HttpResponseMessage(HttpStatusCode.InternalServerError)
{
Content = new StringContent("Ups! Something went wrong. Please try again or contact administrator!")
};
}
}
The problem is I would expect ELMAH to log only unhandled exceptions. In my case, even the exception of type MyException is being logged, although it is caught by the catch block.
Is there any config I can apply to ELMAH to make it log only unhandled eceptions ?
ELMAH catches all exceptions thrown from your web app. If you want to filter out certain errors, you could the error filtering feature of ELMAH as described here:
https://code.google.com/p/elmah/wiki/ErrorFiltering
In your case you would probably need to add something like this to your global.asax.cs:
void ErrorMail_Filtering(object sender, ExceptionFilterEventArgs e)
{
if (e.Exception.GetBaseException() is MyException)
e.Dismiss();
}
Related
I have a GlobalExceptionFilterAttribute.cs file that I intend to catch unhandled exceptions globally:
public override void OnException (HttpActionExecutedContext actionExecutedContext)
{
// SplunkHelper has bug that creates other exception
SplunkerHelper.LogApplication(actionExecutedContext.Exception);
}
I have two questions:
How to take care the error raised by SplunkerHelper.LogApplication() to avoid crashing the server?
If there are some try catch blocks inside the application like below, would the exception caused by logger be caught in GlobalExceptionFilterAttribute.cs? If not, how to take care of it?
try
{
// do something here
}
catch (Exception ex)
{
// logger is a null, which causes exception
logger.log("error")
throw;
}
This might be a broad question, but recently I ahve wondered about the following: In our C# backend we have many places that wrap some code in a try/catch block, specifically calls to external WcF services. Some of these calls are crucial for the application so in the catch block we log the error and rethrow, like:
catch(Exception ex)
{
_logger.Error("Some good error message");
throw ex;
}
On the other hand there are services we allow to fail, but we still want to log the error, so they look like:
catch(Exception ex)
{
_logger.Error("Some good error message");
}
Now reading the code of team members I can not be sure if they forgot to throw or if this is the intended behaviour.
Q: Is there a way, resp. what is the default way, to explicitly NOT rethrow (without including a comment in the code).
I have considered something like this:
catch(Exception ex)
{
_logger.Error("Some good error message");
NotThrowingHereOnPurpose();
}
// ...
// and further below a private method
// ...
private void NotThrowingHereOnPurpose(){}
One approach that may be useful here is to change the way of invoking the code that you explicitly allow to fail in such a way that it does not look like a try/catch block at all.
For example, you could write a helper method that does error reporting, and call it with actions expressed as lambdas:
void InvokeFailSafe(Action action, Action<Exception> onFailure = null) {
try {
action();
} catch (Exception e) {
if (onFailure != null) {
onFailure(e);
}
}
}
Now instead of try/catch you would write this:
InvokeFailSafe(
() => {
... The code that may fail
}
, exception => _logger.Error("Some good error message: {0}", exception)
);
or like this, if you don't want anything logged:
InvokeFailSafe(
() => {
... The code that may fail
}
);
If you code things this way, there would be no doubts about a missing throw statement.
It's an opposite solution to dasblinkenlight's answer. Instead of notifying others that the exception mustn't be rethrown it would say that it must be.
If you only want to log it then use the Error method as usual. Otherwise, you can write an extension method for your logger to log and throw exceptions.
The method would take the catched exception and rethrow it using the ExceptionDispatchInfo class. The ExceptionDispatchInfo is used to rethrow the exception with the original stack trace information and Watson information. It behaves like throw; (without the specified exception).
public static void ErrorAndThrow(this ILogger logger, string message, Exception exception)
{
var exceptionInfo = ExceptionDispatchInfo.Capture(exception);
logger.Error(message);
exceptionInfo.Throw();
}
And use it this way:
try
{
}
catch (Exception ex)
{
// ex would be rethrown here
_logger.ErrorAndThrow("Some good error message", ex);
}
Q: Is there a way, resp. what is the default way, to explicitly NOT
rethrow (without including a comment in the code).
Ideal way would be not to catch a generic exception. Now, to throw or not that entirely depends on your case. You need to understand that Exception handling is used when you know what to do in case an exception occurs. So, only specific exceptions should be handled. Catching exceptions without knowing what you are catching will change the behavior of your application.
Now reading the code of team members I can not be sure if they forgot
to throw or if this is the intended behaviour.
This is something the author of the code can explain to you. But here is a learning to take from this. Your code should be self explanatory. In specific cases where you are unable to express yourself with the code, add a meaningful comment.
You can check this link for better understanding.
I actually found another way that kind of includes what other have suggested here, but uses a built in feature: exception filters. I was free to modify the example given in here to illustrate this:
public void MethodThatFailsSometimes()
{
try {
PerformFailingOperation();
}
catch (Exception e) when (e.LogAndBeCaught())
{
}
}
and then one could have two extension methods on Exception, say LogAndBeCaught and LogAndEscape like so:
public static bool LogAndBeCaught(this Exception e)
{
_logger.Error(#"Following exception was thrown: {e}");
return true;
}
public static bool LogAndEscape(this Exception e)
{
_logger.Error(#"Following exception was thrown: {e}");
return false;
}
I'd like simplify my current logging solution and extend NLog in such a way that I can log an exception only once but without checking whether it's already logged in each and every catch like in my current solution:
catch(Exception ex)
{
if (!ex.IsLogged())
{
logger.Error(ex);
ex.MarkAsLogged();
}
throw;
}
static bool IsLogged(this Exception ex)
{
return ex.Data.ContainsKey("Logged");
}
static void MarkAsLogged(this Exception ex)
{
if (!ex.IsLogged())
{
ex.Data["Logged"] = true;
}
}
Can I somehow extend NLog so that the Error method internally checks whether an exception is already marked as logged?
EDIT:
The shortest solution that I came up with is this one:
public static Exception IfNotLogged(this Exception ex, Action logAction)
{
if (ex.IsMarkedAsLogged() == true)
{
return ex;
}
logAction();
ex.MarkAsLogged();
return ex;
}
usage:
ex.IfNotLogged(() => logger.Error(ex));
...but still it does not work in C++/CLI and it has to be typed :-) Repeating the same code everywhere is not a good habit as I was taught so I'd rather delagate this responsibility to NLog.
Only catch it once. It doesn't matter how far up the call stack that is: the Stack Trace will be accurate. It's when you catch and rethrow and catch again that the Stack Trace gets changed.
Catch it once, log it, handle it as you can and then don't throw it again, continue.
I have a code segment that is responsible for orchestrating the execution of a few modules and it is very sensitive to errors - I want to make sure I log and alert about every exception that occurs.
Right now I have something like this:
try
{
ModuleAResult aResult = ModuleA.DoSomethingA();
}
catch (Exception ex)
{
string errorMessage = string.Format("Module A failed doing it's thing. Specific exception: {0}", ex.Message);
// Log exception, send alerts, etc.
}
try
{
ModuleBResult bResult = ModuleB.DoSomethingB();
}
catch (Exception ex)
{
string errorMessage = string.Format("Module B failed doing it's thing. Specific exception: {0}", ex.Message);
// Log exception, send alerts, etc.
}
// etc for other modules.
It looks to me that the multiple try-catch is making this segment less readable. Is it indeed the right thing to do?
Yes, it's the right thing.
But you should have the performance in in mind, maybe it's better to put all method calls in one try/catch and add stack trace and error information in the exception in the methiod itself.
public void ModuleA.DoSomethingA()
{
throw new Exception("Error in module A");
}
try
{
ModuleAResult aResult = ModuleA.DoSomethingA();
ModuleBResult bResult = ModuleB.DoSomethingB();
}
catch (Exception ex)
{
// get information about exception in the error message
}
You did well.
This way, you can process the error after each module. If you want to run it all and then do error handling, consider this alternative:
try
{
ModuleAResult aResult = ModuleA.DoSomethingA();
ModuleBResult bResult = ModuleB.DoSomethingB();
}
catch(ModuleAException ex)
{
// handle specific error
}
catch(ModuleBException ex)
{
// handle other specific error
}
catch (Exception ex)
{
// handle all other errors, do logging, etc.
}
i think that depends on the approach that you want to follow.
It seems like you error messsages are different for each module that raises exception so i guess the approach that you followed is right.
you could have put the whole thing in a big try - catch block then in that case you will not know which module caused the exception as a generic excpetion gets printed.
try
{
ModuleAResult aResult = ModuleA.DoSomethingA();
ModuleBResult bResult = ModuleB.DoSomethingB();
}
catch (Exception ex)
{
string errorMessage = string.Format("Either Module A or B failed", ex.Message);
// Log exception, send alerts, etc.
}
So if you want your exception handling to not be cleaner use the above code.
Otherwise what you followed is absolutely fine.
Is there anyway we can get HttpStatus code when exception caught? Exceptions could be Bad Request, 408 Request Timeout,419 Authentication Timeout? How to handle this in exception block?
catch (Exception exception)
{
techDisciplines = new TechDisciplines { Status = "Error", Error = exception.Message };
return this.Request.CreateResponse<TechDisciplines>(
HttpStatusCode.BadRequest, techDisciplines);
}
I notice that you're catching a generic Exception. You'd need to catch a more specific exception to get at its unique properties. In this case, try catching HttpException and examining its status code property.
However, if you are authoring a service, you may want to use Request.CreateResponse instead to report error conditions.
http://www.asp.net/web-api/overview/web-api-routing-and-actions/exception-handling has more information
I fell into the same trap when doing error handling in my WebAPI controllers. I did some research on best practices for exception handling and finally ended up with following stuff that works like a charm (hope it will will help :)
try
{
// if (something bad happens in my code)
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.BadRequest) { Content = new StringContent("custom error message here") });
}
catch (HttpResponseException)
{
// just rethrows exception to API caller
throw;
}
catch (Exception x)
{
// casts and formats general exceptions HttpResponseException so that it behaves like true Http error response with general status code 500 InternalServerError
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError) { Content = new StringContent(x.Message) });
}