Knowing which method is throwing the exception - c#

I'm reading information from an xml file and at some point an exception may be thrown by two Boolean.Parse() instructions
Given that the whole snippet is already under a try statement, I wanted to put all catches in one place instead of putting the two above method calls under some other try-catch.
My question is how can I know which method is throwing the exception? I have to display different error messages depending on who's failing to convert.
try
{
XmlNode db = _xml.SelectSingleNode("root/database");
string usr = db.SelectSingleNode("username").InnerText;
string psw = db.SelectSingleNode("password").InnerText;
string srvr = db.SelectSingleNode("server").InnerText;
string dbn = db.SelectSingleNode("dbname").InnerText;
//Here a FormatException can be thrown by both these Parse()
//And I need to know which is the caller in order to display the correct error message
bool clean_db = Boolean.Parse(db.Attributes["clean"].Value);
bool functions = Boolean.Parse(db.Attributes["insertFunctions"].Value);
return new DatabaseConfiguration(usr, psw, srvr, dbn, clean_db, functions);
}
catch (XPathException)
{
Console.WriteLine("<database> node is missing");
}
catch(FormatException e)
{
//Here I'm supposed to do something to get the caller
Console.WriteLine("Error message");
}

Throw an additional try/catch around each of the boolean.parse methods, then have the catch just be:
try
{
XmlNode db = _xml.SelectSingleNode("root/database");
string usr = db.SelectSingleNode("username").InnerText;
string psw = db.SelectSingleNode("password").InnerText;
string srvr = db.SelectSingleNode("server").InnerText;
string dbn = db.SelectSingleNode("dbname").InnerText;
//Here a FormatException can be thrown by both these Parse()
//And I need to know which is the caller in order to display the correct error message
bool clean_db;
try
{
clean_db = Boolean.Parse(db.Attributes["clean"].Value);
}
catch
{
throw new Exception ("clean exception");
}
bool functions;
try
{
functions = Boolean.Parse(db.Attributes["insertFunctions"].Value);
}
catch
{
throw new Exception ("function exception");
}
return new DatabaseConfiguration(usr, psw, srvr, dbn, clean_db, functions);
}
catch (XPathException)
{
Console.WriteLine("<database> node is missing");
}
catch(FormatException e)
{
//Here I'm supposed to do something to get the caller
Console.WriteLine("Error message");
}
then the outer catch will tell which line the exception came from.
then modify your outer catch to show the exception message.
Here's how Steve suggested, since he told me to update my answer :)
try
{
XmlNode db = _xml.SelectSingleNode("root/database");
string usr = db.SelectSingleNode("username").InnerText;
string psw = db.SelectSingleNode("password").InnerText;
string srvr = db.SelectSingleNode("server").InnerText;
string dbn = db.SelectSingleNode("dbname").InnerText;
//Here a FormatException can be thrown by both these Parse()
//And I need to know which is the caller in order to display the correct error message
bool clean_db = ParseDbAttributeValue(db.Attributes["clean"].Value);
bool functions = ParseDbAttributeValue(db.Attributes["insertFunctions"].Value);
return new DatabaseConfiguration(usr, psw, srvr, dbn, clean_db, functions);
}
catch (XPathException)
{
Console.WriteLine("<database> node is missing");
}
catch(FormatException e)
{
//Here I'm supposed to do something to get the caller
Console.WriteLine("Error message");
}
private bool ParseDbAttributeValue(object myValue)
{
return Boolean.Parse(myValue);
}

What about using TryParse.
The TryParse method is like the Parse method, except the TryParse method does not throw an exception if the conversion fails.
So you can simply check for failure with the returning Boolean value
bool clean_db;
if(!Boolean.TryParse(db.Attributes["clean"].Value),out clean_db)
{
// Failled
}
bool functions;
if(!Boolean.TryParse(Boolean.Parse(db.Attributes["insertFunctions"].Value,out functions)
{
// Failled
}

Related

Exception is thrown but try-catch doesn't catch it?

I'm calling a method to get and parse a JSON from a URL. The code structure is as follows:
internal static void CheckIfSettingsExists()
{
settingsContainer.Values["ApplicationXCurrentVersion"] = Controller.GetCurrentVersionAsync();
}
and the GetCurrentVersionAsync() function:
internal static async Task<string> GetCurrentVersionAsync()
{
string temp = null;
using HttpClient client = new HttpClient();
try
{
temp = await client.GetStringAsync("https://someurl.cloud.io/api/v4/VersionCheck");
}
catch (Exception e)
{
App.log.Error("Error fetching version check json from API. Exception raised was: " + e.ToString());
return temp;
}
App.log.Info("Successfully got return for VersionCheck");
if (temp == null)
{
return temp;
}
dynamic JsonObj = JsonConvert.DeserializeObject<dynamic>(temp);
return JsonObj["LatestVersion"].ToString();
}
When I was trying to debug what's happening, I saw that after program runs the line temp = await client.GetStringAsync("https://someurl.cloud.io/api/v4/VersionCheck"); instead of executing the catch block, System.ArgumentException: 'The parameter is incorrect.' is thrown at the line that is calling the GetCurrentVersionAsync() (line 3 in the CheckIfSettingsExists()). I don't understand why this is thrown as even if there was an issue with GetStringAsync() function, I already have it in try block. Can someone shine a light for me why this is happening?

Should methods handle nulls? best practice in this case?

I have the following situation in code, whats the best way to manage it, the comments contains the situations, and please recommend the best practice.
try
{
string errorMessage = AccountClient.GetAccount(id, out accountDetails);
// FIRST WAY : REMOVE THIS NULL CHECK AT ALL AND LEAVE GetAccountDetails to control
// the Null situation?
if (accountDetails == null)
{
// Second Way: This way? Throw exception here?
throw new ArgumentNullException(nameof(accountDetails));
//Third way? break the function?
break;
}
// GetAccount Details already has null control
Subscription subscription = AccountProcessor.GetAccountDetails(accountDetails);
}
catch (Exception e)
{
throw;
}
First of all, the costruction
catch (Exception e) {
throw;
}
is redundant one and can be eliminated. Now about nulls. There're two
cases:
null is an erroneous value and so it should be signalled
null is an expected, ordinary value and thus it should be proceeded
And so you have (null is an error)
string errorMessage = AccountClient.GetAccount(id, out accountDetails);
// What's wrong: it's id which doesn't correspond to any detail
// (we expect id being s.t. AccountClient.GetAccount(id...) returns not null detail)
if (accountDetails == null)
throw new ArgumentException($"Incorrect id {id} which doesn't have any detail.",
nameof(id));
Subscription subscription = AccountProcessor.GetAccountDetails(accountDetails);
Or (null is an expected outcome)
string errorMessage = AccountClient.GetAccount(id, out accountDetails);
if (accountDetails == null)
return null; // or any reasonable value, or just return, or create new Subscription
Subscription subscription = AccountProcessor.GetAccountDetails(accountDetails);
If you can do anything about null input then handle it.
try
{
string errorMessage = AccountClient.GetAccount(id, out accountDetails);
if (accountDetails == null)
{
// do something about it. Maybe write some logs, substitute with a default value
// or throw appropriate exception ...
}
Subscription subscription = AccountProcessor.GetAccountDetails(accountDetails);
}
catch (Exception e)
{
throw;
}
if you can't then let GetAccountDetails decide what should happen.
try
{
string errorMessage = AccountClient.GetAccount(id, out accountDetails);
Subscription subscription = AccountProcessor.GetAccountDetails(accountDetails);
}
catch (Exception e)
{
throw;
}
Also there is no need to catch an exception, doing nothing and then throw it so you can remove the whole try catch block.
It depends on where this ID is coming from. If the user typed the ID, then I wouldn't generate an Exception, since it is not a error in your program. Just treat the user input and show a proper message. Exceptions are costly, so I usually use them only when i have a real programa failure. Besides that, if you write a custom Exception Handler, it wouldn`t make sense to log a error caused by wrong user input. So i would make it like this:
if (AccountClient.AccountExists(id))
{
AccountDetails details = AccountClient.GetAccount(id);
Subscription subscription = AccountProcessor.GetAccountDetails(accountDetails);
}
Anyway, its good to treat the input on the same way, even if you had treated like above, in case there is any other non treated call to it:
public AccountDetails GetAccount(int id)
{
if (Exists(id))
GetTheAccount(id);
else
throw new Exception(String.Format("Account {0} doesn't exists", id));
}
In this case I would use an Exception because it could really represent an error, if the caller function is passing a wrong value, for instance.

Best way to make a return propagate

I couldn't find a answer to this, probably because I'm not asking this question in a proper way.
So, I'm writting a method that is inside a class, and at some point I want it to test for the formatting of a string. If it is not correct, I want it to show a message to the user, and to stop the execution, so that the user can fix that mistake. I have this:
if (Is not properly formated)
{
//get error information
//show error box with the formation error line
MessageBox.Show(String.Format(
"Error message{0}",
errorLine.ToString()), "Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
return;
}
Of course, this will stop the execution of this method, but I want to stop the execution of the main method (a button click method).
What is the best way to do this in C#?
You should really be using exceptions in C#, for example
private void Calculate(string[] lines)
{
try
{
lines.ForEach(Validate);
// process lines
}
catch(InvalidArgumentException ex)
{
MessageBox.Show(...);
}
}
private void Validate(string s)
{
if(s.IsNullOrEmpty)
throw new InvalidArgumentException(/* some details here*/);
}
You could write a validation method that returns true if the value is valid, and optionally return a string telling what is wrong:
private bool Validate(string s, out string error)
{
if (string.IsNullOrEmpty(s))
{
error = "s is null";
return false;
}
else
{
error = null;
return true;
}
}
Then call it:
string error;
if (!Validate(null, out error))
{
MessageBox.Show(error);
// Do something
}
Instead of the string you could use an enum if you want to structure the list of possible errors.

Exception handling in .net

I have caught an exception and after catching it I have to append the method name so that I should know which method the error came from, and then throw it to another function and save it in database.
try
{
}
catch (Exception ex)
{
string strError = ex.Message.ToString() + "methodname:getNoOfRecordsForBatchProcess";
throw strError.ToString();
}
but it gives me error that you can't use string variable to throw exception.the throw exception only use with system exception. is there any way to handle this error.
The method name is visible in Exception.StackTrace property too.
By the way you may rely on some other way to recover its name using StackFrame Class, like for example:
private static string GetCallingMethodName()
{
const int iCallDeepness = 2; //DEEPNESS VALUE, MAY CHANGE IT BASED ON YOUR NEEDS
System.Diagnostics.StackTrace stack = new System.Diagnostics.StackTrace(false);
System.Diagnostics.StackFrame sframe = stack.GetFrame(iCallDeepness);
return sframe.GetMethod().Name;
}
An answer to your question:
throw new Exception(strError);
(However, as others have said, this might not be the best way to handle this.)
Possible duplicate of How to get the name of the method that caused the exception.
catch (Exception ex)
{
MethodBase site = ex.TargetSite;
string methodName = site == null ? null : site.Name;
...
}
When catching and rethrowing an exception it's 'recommended' to create a new Exception, with a meaningful error message, and pass the original exception in as the inner exception.
For example:
catch(Exception ex)
{
const string message = "Some error message.";
throw new MeaningfulException(message, ex);
}
I would also go for the StackFrame. I'm posting an extension to #Tigran's answer (because you asked for a bit more clarified usage inside the try{...}catch{...} block), so if this is helping you to understand the usage, please accept his answer, not mine:
try
{
int a = 0;
var r = 1 / a;
}
catch (Exception ex)
{
throw new Exception(
String.Format("{0} Method name: {1}",
ex.Message,
GetCallingMethodName()),
ex);
}
The GetCallingMethodName:
private static string GetCallingMethodName()
{
const int iCallDeepness = 1; //DEEPNESS VALUE, MAY CHANGE IT BASED ON YOUR NEEDS
System.Diagnostics.StackTrace stack = new System.Diagnostics.StackTrace(false);
System.Diagnostics.StackFrame sframe = stack.GetFrame(iCallDeepness);
return sframe.GetMethod().Name;
}
P.S. #Tigran, I will remove this answer if you consider that it's not needed.

try-catch blocks with the return type

If I have a method that returns something, like
public DataTable ReturnSomething()
{
try
{
//logic here
return ds.Tables[0];
}
catch (Exception e)
{
ErrorString=e.Message;
}
}
This produces compiler error, obviously because catch{} block does not return anything.
So when I have methods with return values I don't use try-catch block, which is a bad practice. If there is an error, I would like to set error string to that error. But then I need a return value as well. Advice?
Store your return value in a temporary variable like this:
public DataTable ReturnSomething()
{
DataTable returnValue = null;
try
{
//logic here
returnValue = ds.Tables[0];
}
catch (Exception e)
{
ErrorString=e.Message;
}
return returnValue;
}
You should raise/throw the exception in your catch block and handle it in the calling method.
public void invokeFaultyCode()
{
try
{
DataTable dt = ReturnSomething();
}
catch(Exception e)
{
// Print the error message, cleanup, whatever
}
}
public DataTable ReturnSomething() throws Exception
{
try
{
//logic here
return ds.Tables[0];
}
catch (Exception e)
{
ErrorString=e.Message;
throw;
}
}
PS: Sorry for any syntax error, I'm a bit rusty on C#.
You should wrap the caller with a try catch... any exceptions that happen in the routine that is called will bubble out to the caller and you can catch them there.
Personally, I think it is overkill to have a try catch in this routine as you should have the caller handling the exception.
For my example, this would be coded as follows...
private void DoSomething() {
try {
DataTable dt = ReturnSomething();
}
catch (Exception ex) {
}
}
public DataTable ReturnSomething() {
DataTable dt = new DataTable();
// logic here
return dt;
}
The ErrorString variable looks suspiciously like an error code variable. Recommended practice is to use exceptions to pass error information directly, where necessary, rather than storing things off into error codes.
You are effectively doing the same thing with your ErrorString as you would be if you just let the exception be caught by the caller: removing the responsibility of responding to an error from the method itself. This is a good goal to have. But the use of an error string doesn't gain you anything over the use of an exception. In fact, you lose information this way. There are any number of types of errors that could occur, and many have special exceptions associated with them, with their own special properties to hold contextual info about the failure. By just storing off the message in a String, you're losing this information.
So unless your goal is specifically to hide the type of error that is occurring from the caller, you can only gain by letting the exception through.
Another thing to consider is whether this is truly an error scenario. If it is, it's very unlikely that your calling method is going to care at all what the return value is. In which case, you have nothing to worry about by just letting the exception go and not returning anything. If it's NOT really an error scenario, and the caller is just going to continue on and do something else, well, that's for the caller to decide, right? There's still not much benefit to obtain by returning an error string and a dummy DataTable or a null, over throwing the exception with all its contextual failure info.
If you are going to head the "don't throw an exception route" (which I am not necessarily reccomending), you could follow the TryParse approach MS uses.
Something like:
private string FillDataTable(out DataTable results)
{
try
{
results = new DataTable(); //something like this;
return String.Empty;
}
catch (Exception ex)
{
results = null;
return ex.Message;
}
}
It depends on you application. You can return null, an empty DataTable or whatever is suitable under circumstances.
i'd assume you can still set the message, then return null or whatever the c# equivalent is
public DataTable ReturnSomething(){
try {
//logic here
return ds.Tables[0];
} catch (Exception e) {
ErrorString=e.Message;
return null;
}
}
How about this :
public DataTable ReturnSomething(out string errorString)
{
errorString = string.Empty;
DataTable dt = new DataTable();
try
{
//logic here
dt = ds.Tables[0];
}
catch (Exception e)
{
errorString = e.Message;
}
return dt;
}
Since you are cacthing the exception (and not throwing it again) in your example, The outside code assumes everyting is okay and therefor you should return something useful.
If you need to catch the exception there and do somthing that's all fine, but if it's still an error case you should also throw it, or a different exception, perhaps with the one you just caught as InnerException.
I think your code is being run at a sufficiently high level of the call stack and it's blended with UI code. If this is really the case, you could return null in the catch block. However, if you are writing reusable code, you should refactor it so that it doesn't contain UI manipulation and handle the exception at a higher level in the call stack.
You can do it like the sample code below.
public DataTable ReturnSomething(out string OutputDesc)
{
try
{
//logic here
OutputDesc = string.Format("Your Successful Message Here...");
return ds.Tables[0];
}
catch (Exception e)
{
OutputDesc =e.Message;
return null;
}
}
Simple
public DataTable ReturnSomething()
{
try
{
//logic here
return ds.Tables[0];
}
catch (Exception e)
{
ErrorString=e.Message;
throw new Exception(e.Message);
}
}

Categories