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

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?

Related

How to catch that there is an error from CommandLineParser so I can return my own error codes?

How to catch that there is an error from CommandLineParser so I can return my own error codes?
I need to return my own codes when my console application is called from say SSIS.
class Program
{
static void Main(string[] args)
{
try
{
var myParserResult = Parser.Default.ParseArguments<UploadFileCommand, DownloadFileCommand, CompressFileCommand>(args)
.WithParsed<ICommand>(t => t.Execute());
var parsed = myParserResult as NotParsed<object>;
if (parsed != null && parsed.Errors.Any())
{
Console.WriteLine("Has Errors");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
The method ParseArguments() will return a ParserResult<T> object to indicate if the parsing was successful or not. In case the parsing was not successful a NotParsed<T> instance is returned. This class has an Errors property to contain all the Error instances why the parsing failed. You can use it in a normal foreach() loop to iterate over the found errors:
ParserResult<Options> result = parser.ParseArguments<Options>(args);
Console.WriteLine(result);
NotParsed<Options> notParsed = result as NotParsed<Options>;
if (notParsed != null)
{
foreach (var error in notParsed.Errors)
{
Console.WriteLine(error);
}
}
This might print the following debug output:
CommandLine.NotParsed`1[Testing.Options]
CommandLine.UnknownOptionError
CommandLine.UnknownOptionError

Knowing which method is throwing the exception

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
}

System.Threading.ThreadAbortException on generic redirection

I am working on an ASP.Net project where we have an centralized redirection method. But some times it throws an exception:
System.Threading.ThreadAbortException
The main problem is that often the code execution is not stopping after calling SBA.Redirect("AnotherPage.aspx") and the following code is still executing.
My generic function:
public static class SBA
{
public static void Redirect(string Url)
{
try
{
HttpContext.Current.Response.Redirect(Url, false);
HttpContext.Current.ApplicationInstance.CompleteRequest();
}
catch (Exception ex)
{
if (ex.GetType() != typeof(System.Threading.ThreadAbortException))
{
throw;
}
}
}
}
Redirect raises a ThreadAbortException specifically in order to stop any following code from being run.
You are handling the ThreadAbortException.
Thus the following code is being run.
If you don't want the following code to be run, don't handle the ThreadAbortException.
Simply make the following call to make a redirect:
HttpContext.Current.Response.Redirect(Url);
There are two problems with your code:
You use an overload of Redirect where you decide to not end the response by supplying false for the endResponse parameter. Hence the code after the redirect executes.
You try to catch ThreadAbortException. When using the normal redirect as described above this exception is thrown. It is not an error condition but simply a way for ASP.NET to ensure proper termination of the current request. You can catch the exception but it is rethrown at the end of the catch block so your catch block will not do anything useful.
Because an exception is thrown when redirecting you should be aware of the following explained in the comment:
void HandleRequest() {
try {
Response.Redirect(" ... url ... ");
}
catch (Exception) {
// Code here will execute after the redirect.
}
}
To avoid problems the best thing is to catch a more specific exception type in the catch handler or at least not do anything in the handler that interferes with the redirect (like writing to the response stream).
I protected the redirection using the code below. It's working.
public static class SBA
{
public static void Redirect(string Url)
{
try
{
//redirect only when 'IsRequestBeingRedirected' is false
if (!HttpContext.Current.Response.IsRequestBeingRedirected)
{
Uri uri = null;
bool isUriValid = Uri.TryCreate(Url, UriKind.RelativeOrAbsolute, out uri);
if (!isUriValid)
{
throw new SecurityException("Invalid uri " + Url);
}
//Below check is not required but checked
//to make obsolate security check
if (uri.OriginalString == null)
{
throw new SecurityException("Invalid uri " + Url);
}
// check if host is from configured trusted host list
if (uri.IsAbsoluteUri)
{
var tempAppSetting = ConfigBLL.GetAppSetting(AppSettingSectionType.OtherSetting).Other;
if (!tempAppSetting.RedirectTrustedUrls.Contains(uri.Host))
{
throw new SecurityException("Untrusted url redirection detected. Can not redirect.");
}
}
var tempUrl = uri.OriginalString;
//Few more logical check
HttpContext.Current.Response.Redirect(tempUrl, true);
}
HttpContext.Current.ApplicationInstance.CompleteRequest();
}
catch (Exception ex)
{
if (ex.GetType() != typeof(System.Threading.ThreadAbortException))
{
throw;
}
}
}
}

How to do proper exception handling and return codes for Console Application

I have a simple C# console application that talks to a webservice. I am not sure if the way I am handling expections and returning error codes are proper. Would like to have comments on good pratice to do this. (I am using CommandLine.dll for option parsing)
class Program
{
static int Main(string[] args) {
var options = new Options();
if (CommandLine.Parser.Default.ParseArguments(args, options)) {
try {
var client = new MyWebService();
var response = client.MyFunction(new MyRequest() { Param1 = options.param1, Param2 = options.Param2 });
if (response.ErrorCode != 0) {
Console.WriteLine("Error code= " + response.ErrorCode);
}
else {
File.WriteAllText(options.OutputFile, response.File);
return 0;
}
}
catch (Exception exp) {
Console.WriteLine(exp.Message);
return 1;
}
}
return 1;
}
}
You should use the Console.Error.* to write errors. And I'll say that this:
if (response.ErrorCode != 0) {
Console.Error.WriteLine("Error code= " + response.ErrorCode);
return 1;
} else {
File.WriteAllText(options.OutputFile, response.File);
}
plus a final
return 0;
after the catch would be better, so that if you have multi-stage operations to do, it's easier to code (fall-through == ok, error == fast abort)
with multi-stage I mean:
call ws1
check for non-Exception errors of ws1, if errors abort
call ws2
check for non-Exception errors of ws2, if errors abort
call ws3
check for non-Exception errors of ws3, if errors abort
return success
In the cmd prompt, to save errors:
myprogram 2>err.txt
to redirect output + error:
myprogram > err.txt 2>&1
(the last one was taken from https://stackoverflow.com/a/1420981/613130)
Last thing: if the parsing of the arguments goes wrong, you should output an error.
You should refactor the MyWebService class and the MyFunction to throw exceptions if an error occurs. Instead of returning error codes. That gives you full flexibility in terms of who at which level can handle the errors and it makes the code much more readable.

Variable outside a try catch block loses value

I am having a little problem. I have a function with a string outside a try-catch-finally block that is changed depending on what happens inside the block. Once that is finished, I want to display it. My problem is that the value that was changed in the block returns to the original value it had. How can I fix this?
string error = "No issues";
try{
error = "Correct";
}catch(Exception ex){
error = "Wrong:" + ex.Message.ToString();
}finally{
// Closes connection
}
MessageBox.Show(error);
It's not clear to me, if the string in question declared outside the method. If you are 100% sure, that a new value is given to the string, the following code will probably do the problem you have:
static void Foo(string s)
{
try
{
s = "OK";
}
catch { }
}
static void Main(string[] args)
{
string temp = "??";
Foo(temp);
Console.WriteLine(temp); //prints ??
Console.ReadLine();
}
as you are passing string by value. If you need to change the value you should either:
make a ref parameter:
static void Foo(ref string s)
and call it
Foo(ref temp);
or return the new value from the method:
static string Foo(string s)
{
try
{
s = "OK";
}
catch { }
return s;
}
and call it:
temp = Foo(temp);
The code you posted will show a message box with the text
Correct
if no exceptions are thrown, otherwise the message
Wrong: (plus the exception's message property)
It will never show the message
No issues
because you overwrite the initial value of error in the first line of your try block.
error will never lose a value (as in I guess become null) given the code you post. Eventually error will go out of scope (e.g. when you exit the method that this code is defined in).
UPDATE
I took your code, created a brand-new WinForms project, double-clicked on Form1 to create a Load event handler, and posted in your code like this:
private void Form1_Load(object sender, EventArgs e)
{
string error = "No issues";
try
{
error = "Correct";
}
catch (Exception ex)
{
error = "Wrong:" + ex.Message.ToString();
}
finally
{
// Closes connection
}
MessageBox.Show(error);
}
The result was a message box that said "Correct".
If that is not what you see in your real code, you are not sharing enough code to reproduce the problem.

Categories