Rethrowing an exception causes my data to not save - c#

I have this code:
catch (Exception e)
{
try
{
transmitModel.AddAck(transmitBatchId,
"<error><message>" + e.Message + "</message><stack>" + e.StackTrace +
"</stack><Location>FromLisAtOMServer<Location>" +
"<TransmitBatchId>" + message.TransmitBatchId +
"</TransmitBatchId></error>", false, true);
}
// If we fail to log, we don't want that to bubble up...
// We want the real error to do that.
catch (Exception){}
// Re-throw the exception so that the service bus will
// move this off to the error queue.);
throw;
}
The AddAck method will save that string to the database (Using Entity Framework).
When I run this without the last statement throw, it saves my error message to database fine.
When I have the throw; in there, it says it saves but when I query the database it is not in there. I can even run a entity query via my data context right after saving (in the code) and it returns the value as if it is saved (though that may be using a cached version). But if I go and query afterwards the data is not there....
I have checked to be sure that no other logic is causing the value to be removed on an exception.
Any ideas what could be causing this?

OK, post as an answer here, it comes in my mind very easily as I used to met the same issue, and figured out it was just caused I didn't commit the DB transaction.
Thanks, :)

This call is as a result of an NServiceBus message.
I forgot that my NServiceBus stuff runs in a distributed transaction. So when I threw the exception it roll back all my pending changes.
I need to find out how to get this log file to post outside the transaction...

It is possible that NServiceBus provides hooks for this kind of thing.
Your problem is quite possibly what you have stated: the message handling has to happen in a transaction. You cannot commit that else you are also committing errors. So you definitely have to find out where you can hook into the post message handling exception processing.
With Shuttle ESB (http://shuttle.codeplex.com/) we use pipelines for handling different use cases and you can hook into the PipelineException event that is raised by the various pipelines. Shuttle has a the ability for developers to add modules that hook into the various events. There is already a SystemExceptionModule that does more-or-less what you want to do.

Related

Script task failed without going inside Try & Catch block

Here is the brief explanation for my script task in SSIS.
Read/Write variable LOGERROR, and it does exist in the Variables panel with string type.
Inside the script, C# code:
try
{
... //what here does is to iterate a folder and move all of them to another folder, codes here are working correctly
Dts.TaskResult = (int)ScriptResults.Success;
}
catch(Exception e)
{
Variables lockedVariables = null;
Dts.VariableDispenser.LockOneForWrite("User::LOGERROR", ref lockedVariables);
lockedVariables["User::LOGERROR"].Value = e.ToString();
lockedVariables.Unlock();
Dts.TaskResult = (int)ScriptResults.Failure;
}
The reason that I manually control the writes of the variable is that the same variable LOGERROR was added to the Event Handler for the same purpose of Point 4.
I direct the Failure to another Execute SQL task, which is trying to insert LOGERROR (Should contain the exception details) into an underlying table.
My questions:
Sometimes the SSISPackage failed at above task (not always, but at almost the same time every day, may have conflicts with the other jobs?) for not any apparent reasons (at least for now). That's why I would like to track what exactly the issue is, but if I query the target logging table. The details does not show anything, just empty.
And, I have a general logging task in Event Handler that logged all the message when task ran with errors. And that message shows nothing but Exception has been thrown by the target of an invocation.
Did I miss something when trying to log LOGERROR? Because it seems for me that the script did not go into the Try & Catch, just failed directly, otherwise it should store the Exception details. (Please correct me if I am wrong). Or, how could I track the error details?
After some investigations, I think the issue was caused by SQL Server Agent failed to access the shared folder during certain time frame.
Possible solution to my questions:
https://social.technet.microsoft.com/Forums/azure/en-US/988207fe-5a25-4da7-a8df-a38fada703da/ssis-script-task-exception-has-been-thrown-by-target-of-invocation?forum=sqlintegrationservices

handling errors through the async dll stack

I'm trying to handle errors that are passed through 2 dlls I've created. So Console.exe calls dll 1. dll 1 completes an async MQ message read and the handler calls dll 2. If dll 2 errors it passes the Exception (throw) without a problem. But the dll 1 (async) handler catch the throw from dll 2 and give me an unhandled by user message.. I have followed the msdn code to add in the IAsyncResult to keep the hander alive but the issue persists.
can anyone advise on how I should handle this stack and get the handler error returned to the console.exe program so I can present it to the user. Code below:-
Console.exe (snippet)
try
{
_msmq.MSMQ_GetMessage(_msgPath);
//set up the print of the number of queue messages
Console.WriteLine("Main thread: starting a timer");
Timer t = new Timer(ComputeBoundOp, _msgPath, 0, 2000);
Console.Write("Press any key to continue . . .");
Console.ReadKey(true);
t.Dispose(); // Cancel the timer now
}
catch (MessageQueueException _msgQex)
{
Console.WriteLine("An error occurred with the queue:- " + _msgQex);
}
catch (Exception _ex)
{
Console.WriteLine("An error occurred with the queue:- " + _ex);
}
dll 1
public void MSMQ_GetMessage(string _MQ_Path)
{
try
{
//set the correct message queue
MessageQueue _msgQ = new MessageQueue(_MQ_Path, QueueAccessMode.ReceiveAndAdmin);
//set the format of the message queue
_msgQ.Formatter = new XmlMessageFormatter(new Type[] { typeof(_TwitterStreamFeed) });
_msgQ.ReceiveCompleted += new ReceiveCompletedEventHandler(_msgQ_RecieveCompleted);
IAsyncResult _result = _msgQ.BeginReceive();
_asyncList.Add(_result); // asyncList is a global variable of type System.Collections - > this allows the callback to remain open and therefore nit garbage collected while the async thread runs off on it's own
}
catch (Exception _ex)
{
throw new Exception("_msgQ_get Message threw the following error :- " + _ex);
}
}
//method to process message
public void _msgQ_RecieveCompleted(object sender, ReceiveCompletedEventArgs e)
{
try
{
//queue that have received a message
MessageQueue _mq = (MessageQueue)sender;
//get the messge off the queue
Message _mqmsg = _mq.EndReceive(e.AsyncResult);
//set the values back into a formatted struct
//now process your SQL....
Azure_SQL _azuresql = new Azure_SQL();
_azuresql.writeMessageToStorage((_TwitterStreamFeed)_mqmsg.Body);
//refresh queue just in case any changes occurred (optional)
_mq.Refresh();
//tell MessageQueue to receive next message when it arrives
_mq.BeginReceive();
}
catch (Exception _ex)
{
throw;
}
dll 2
public void writeMessageToStorage(_TwitterStreamFeed _msmq_message_as_TSF)
{
try
{
// now do something with the class - i..e write the values to the database
SqlConnection _azurecon = new SqlConnection(_AzuzeSQLConnection);
SqlCommand _sqlcmd = new SqlCommand();
//Setup the command string to call the stored procedure
//Add the parameter to the parameters collection of the command
blah blah blah......... Do SQL writing to Db
_azurecon.Open();
SqlDataReader _sqldr_tweet_place = _sqlcmd_place.ExecuteReader(CommandBehavior.CloseConnection);
}
//now close things off
_azurecon.Close();
}
catch (Exception _ex)
{
// Throw the error to preserve the original
throw;
}
The reason for this is that, internally, the MessageQueue class is explicitly swallowing the exception. Where the MessageQueue class raises the ReceiveCompleted event, it's inside of a try-catch statement - and the catch block is empty. Suffice it to say, if an exception occurs inside your ReceiveCompleted event handler, _msgQ_RecieveCompleted(), nothing's ever going to know it happened.
I see a couple of options, in order of preference.
Option 1 - Shift where the asynchronous call is made
Since this exception-swallowing behavior only occurs when using BeginReceive(), in MSMQ_GetMessage(), you can switch from using BeginReceive() to just Receive(). Then, make your call to MSMQ_GetMessage() asynchronous and any exception that gets thrown will be propagated as expected.
As a side note, a new(er) alternative for making asynchronous calls is available; the Task<> class. As opposed to the Thread class, Task<> has exception handling functionality built in. It does, however, require Framework 4 or higher. There is a good explanation of it's use described in the answer here.
Option 2 - Use a custom event
If refactoring the asynchronous call isn't an option, you can create a custom event in your class in 'dll 2' and subscribe to that event in 'Console.exe'. So when an exception occurs in _msgQ_RecieveCompleted(), you can raise the event and 'Console.exe' will be notified.
The MessageQueue.BeginReceive() method uses the standard .NET APM (Asynchronous Programming Model) pattern. It is very important to understand how it works to know how to properly deal with exceptions. Be sure to read the MSDN article, there are lots of other googable resources available.
In APM, the callback that tells you that a message was received in executed on a thread-pool thread. Which is a very efficient way to get code to run quickly. It is however also a very troublesome way when something goes wrong. The EndReceive() method call is likely to throw an exception, it does so to tell you that the receive operation could not be completed. A standard exception it will throw is ObjectDisposedException. Which will happen when the MessageQueue object gets disposed. In your case when your program terminates. You need to catch that exception and exit from your event handler, it is an expected exception and signals that nothing more useful is going to happen next since the queue was closed.
Then there's a raft of possible exceptions that can be raised by major mishaps in the message queue plumbing. Plus whatever you do with the message. Looks like you execute some Azure code, plenty of ways that can fall over. If you let such an exception escape from the callback method, like you do, then there's no catch clause anywhere in the call stack that is going to handle the exception. The standard way .NET deals with unhandled exceptions is to raise the AppDomain.UnhandledException event and terminate your program. If you didn't actually implement that event then there's nothing decent to look at to diagnose the reason your program ended, the Windows Error Reporting dialog has no good diagnostic.
Whether or not you should try to handle the exception and prevent the program from terminating is up to you. But it pretty strongly fits the "don't shoot the messenger" pattern, it is very unlikely your program can meaningfully continue to execute when such an exception is raised. It invariably takes a human to fix the problem, like restoring the network connection or fixing the message queue. If you do catch it then the odds that the same exception is raised over and over again is fairly likely. After all, there wasn't anything decent you could do in your code to repair the network.
So the best guidance here is to not try, just make sure that IT staff has a good diagnostic so they can repair the problem. Do implement the AppDomain.UnhandledException and display and log the e.UnhandledException.ToString() value. This will also let you learn the number of ways that your program can fail. There might be some conditions that are common enough to warrant catching, something like a temporary network outage. At that point you'll also know what to do about it, in other words what kind of code to write in the catch clause. There is no possible way you know what to write right now, you should therefore not try.
Last but not least, do note that you got yourself into this pickle because you used BeginReceive() unnecessarily. You've already got a perfectly good thread to do work on. But it doesn't do anything useful, it is stuck in the Console.ReadKey() method. Particularly in .NET 4.5 a very tricky method to call, it prevents other threads from writing anything to the console. So your error reporting won't work, it will deadlock when it tries to use Console.WriteLine() to write a diagnostic.
You might as well use MessageQueue.Read() instead. Now dealing with exceptions is a lot easier since they occur on the same thread. The MessageQueue.SynchronizingObject can also be helpful to get completion callbacks to occur on the main thread, but that only works in a GUI app, not in a console app.

How can I add a message to an exception without losing any information in C#?

I have the following code:
catch(Exception ex)
{
throw new FatalException("An error occurred while trying to load the XSLT file.", ex);
}
This unfortunately just swallows up the Exception. I can fix this by doing the following:
catch(Exception ex)
{
throw;
}
But I would still like to include the custom message for help with event logging.
How do I add this message to the exception without losing any information? (stack trace/debug symbols, etc.)
If you just need to add information to the original exception, such as a user-readable message or specific details that will be useful to you in tracking down the error but that won't be useful to the end user, you can make use of the Exception's Data property, which is a key/value pair dictionary.
We use this extensively in order to record information such as the report being executed or file that is being processed so that operations can determine what exactly was happening at the time of the error. The user doesn't need this detail since they are working directly with the cause of the failure.
You could also use this to pass a plain text message that makes sense to the user. The only issue is that you will have to perform some additional work in your logging framework or end-user interface in order to extract the data and make it useful to the consumer.
For example, you could do:
catch (Exception ex)
{
ex.Data.Add("UserMessage", "An error occurred while trying to load the XSLT file.");
throw;
}
Then in the client-side code, you could test to see if UserMessage exists and, if so, present it to the user instead of the Exception:
catch (Exception ex)
{
if (ex.Data.Contains("UserMessage"))
{
MessageBox.Show(ex.Data["UserMessage"].ToString());
}
else
{
MessageBox.Show(ex.Message);
}
}
That original Exception is still there.
When you do your Exception logging, the Exception that you receive will be the FatalException that you made with your message. The original Exception is in ex.InnerException. You can continue to cycle through InnerException until it's null to get all of the Stack Trace information, etc.
In short, don't.
I'm sure you could find some way of getting around this with some reflection, but I would strongly caution you against this. It goes against the original design of exceptions in .NET. Exceptions are not just there to help with logging, they provide information about the original cause of an application failure.
Using the first option is generally preferred as it maintains the stack trace of the original exception but allows you to provide additional information by wrapping it in a separate exception. In my own code, whenever I log exceptions, my logging function will recurse through the InnerException property to find every bit of useful information possible about the error.
Just in case someone needs a good answer. The key is to use AppDomain.CurrentDomain.FirstChanceException
The you can create a custom object with IDisposable to put all info in it. And if exception happens then FirstChanceException handler gets that info and populate Exception.Data.
Use Local Thread Storage to make it thread safe. Then down the line the code that catches it will get the data and log it.
Example:
using(MyCustomMessage.EnterToLocalStorage("Info for logging"") )
{
...code
...exception thrown
.... FirstChanceException examines local thread storage and get's "info for logging" and puts into Exception.Data.
}
//Dispose is called and all messages that were put into LocalStorage are removed.
//So if exception was not thrown before then it like nothing happened.
Google AsyncDiagnosticStack for a good example. https://github.com/StephenCleary/AsyncDiagnostics/blob/master/src/Nito.AsyncEx.AsyncDiagnostics/AsyncDiagnosticStack.cs

Proper way of using try catch() in C#

I am using ASP.NET/C#.
Here is an example where I am updating some information in database using lambda expression.
try
{
using (var db = new DataClasses1DataContext())
{
var logSubGroup = db.sys_Log_Account_SubGroups
.SingleOrDefault(subGroup => subGroup.cSubGroupName.Equals(subGroupName));
logSubGroup.cRejectedBy = rejectedBy;
logSubGroup.dRejectedOn = DateTime.Now;
logSubGroup.cAuthorizedStatus = "Rejected";
db.SubmitChanges();
}
}
catch (Exception ex)
{
}
As you can see I am not doing anything inside catch() block.
I know this is a terrible way of using try catch.
Can anyone just help me to use try catch block in a correct manner.
I am just clueless as to what must come inside the catch block.
Any suggestions are welcome.
Don't use a try-catch block at all, unless you have a specific reason to catch a specific exception.
Instead, use one of the global exception handling methods (Application_Error in ASP.NET) to globally catch unhandled exceptions, show an error message and log the error.
As a general rule, there is no need to catch an exception if the code catching the exception cannot do something about the problem, then continue running correctly. In code like what you've presented, can you identify some action you could take within the catch block to restore the program to a state where you trust it to continue running? If not, then just let the exception bubble up the stack.
You should ideally handle the error so that your application can recover from it, at the very least though, you should log it. You should never just swallow it. Also, you shouldn't handle an exception that you don't expect or can't handle. For example, when opening a file, a FileNotFoundException can be expected and handled, for example by displaying a warning and letting the user pick another file.
Theoretically it's up to you to decide what kind of exception may occur inside your catch statement it's not totally wrong doing it this way of course if you are in the development phase I would highly not recommend doing try catch since you can miss some of the important exception that may occur and you would want to fix also in general you should include a message or an action that should occur if the exception or error was caught a message to the user can be notified that action did not executed well but ideally you have to let user know what went wrong so in this case better error handling is a way to go

Exception handling within an Exception in C#

i know this could be a little weird but a doubt is a doubt afterall...
what would happen in the following situation...
private void SendMail()
{
try
{
//i try to send a mail and it throws an exception
}
catch(Exception ex)
{
//so i will handle that exception over here
//and since an exception occurred while sending a mail
//i will log an event with the eventlog
//All i want to know is what if an exception occurs here
//while writing the error log, how should i handle it??
}
}
Thank you.
I would personally wrap the call to write to event log with another try\catch statement.
However, ultimately it depends on what your specification is. If it is critical to the system that the failure is written to the event log then you should allow it to be thrown. However, based on your example, I doubt this is what you want to do.
You can simply catch errors in the error logging method. However I wouldn't personally do that, as broken error logging is a sign your application can't function at all.
private void SendMail()
{
try
{
//i try to send a mail and it throws an exception
}
catch(Exception ex)
{
WriteToLog();
}
}
private void WriteToLog()
{
try
{
// Write to the Log
}
catch(Exception ex)
{
// Error Will Robinson
// You should probably make this error catching specialized instead of pokeman error handling
}
}
Each exception is caught only when inside a try-catch block. You could nest try-catch but is generally not a good idea.
You could add a try-catch block in your catch block as well.
Considering the kind of exceptions when writing to a file (rights, disk space...) I would advice not to handle it in here. If it fails the first time, there's good chance you won't be able to write to the event log that it's not possible to write in the event log...
Let it bubble up and be handled by an upper level try/catch.
Chris S. has the best answer. Placing a try-catch block inside a catch block is very rarely a good idea. and in your case it will just convolute your code. If you check to see if you were successful in writing to your log file here, you will have to do it in every place where you try to write into your log file. You can easily avoid this unnecessary code duplication by having all your individual modules be self contained when it comes to notifying/handling of error conditions within these modules. When sending your mail fails you perform the proper actions inside your catch block to handle this exceptional condition like:
disposing of the contents of your mail object
making sure your socket is closed
writing an entry into your log file to note the error
Inside your catch block just call whatever API you have defined to writing a log entry into your logfile and forget about about the rest. Inside your logging API is where you should handle any logging related exceptional cases (the disk is full, no permission to write to file, file not found, etc...). Your mailing module does not need to know if the logging was successful or not, that responsibility should be delegated to the logging module.
I personally handle this situation using a simple extension method.
public static class MyExtentions
{
public static void LogToErrorFile(this Exception exception)
{
try
{
System.IO.File.AppendAllText(System.IO.Path.Combine(Application.StartupPath, "error_log.txt"),
String.Format("{0}\tProgram Error: {1}\n", DateTime.Now, exception.ToString()));
}
catch
{
// Handle however you wish
}
}
}
The usage is simple:
try
{
...
}
catch(Exception ex)
{
ex.LogToErrorFile();
}
You can then handle the caught exception inside the extension method however you want, or simply don't catch it and let it bubble up to the top. I've found this design to be a simple, reproducible way to handle exceptions throughout the application.
Firstly I would say don't catch "Exception" in catch block. You could instead, for mailing, check for all validity and then catch specific exception(SmtpException, ) that you can do something about(and informing user with a friendly message). Throwing exception from your code and informing the UI about is not a bad idea. If your methods accepts inputs with certain specification and if they are not met, your method should/can throw error and inform user about it.
For exceptions that have no control over, use global handling exception, like Application_Error for web.
Getting Better Information on Unhandled Exceptions Peter Bromberg explains this better.
Also for any privildged resource you are accessing, like eventlogs, make sure you assembly has access to it.
Useful links Build a Really Useful ASP.NET Exception Engine By Peter A. Bromberg
and
Documenting Exceptional Developers By Peter A. Bromberg
For web application look into
Health monitoring
Exception logging
One more thing, if your application goes wrong/ throws error that can't handle( at all) its better to let it go down gracefully and not continue. Application in unstable state is not good idea.

Categories