Up to now, whenever I wanted to show an exception thrown from my code I used:
try
{
// Code that may throw different exceptions
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
I used the above code mainly for debugging reasons, in order to see the exact type of exception and the according reason the exception was thrown.
In a project I am creating now, I use several try-catch clauses and I would like to display a popup message in case of an exception, to make it more "user friendly". By "user friendly", I mean a message that would hide phrases like Null Reference Exception or Argument Out Of Range Exception that are currently displayed with the above code.
However I still want to see relevant info with the type of exception that created the message.
Is there a way to format the displayed output of thrown exceptions according to previous needs?
You can use .Message, however I wouldn't recommend just catching Exception directly. Try catching multiple exceptions or explicitly state the exception and tailor the error message to the Exception type.
try
{
// Operations
}
catch (ArgumentOutOfRangeException ex)
{
MessageBox.Show("The argument is out of range, please specify a valid argument");
}
Catching Exception is rather generic and can be deemed bad practice, as it maybe hiding bugs in your application.
You can also check the exception type and handle it accordingly by checking the Exception type:
try
{
}
catch (Exception e)
{
if (e is ArgumentOutOfRangeException)
{
MessageBox.Show("Argument is out of range");
}
else if (e is FormatException)
{
MessageBox.Show("Format Exception");
}
else
{
throw;
}
}
Which would show a message box to the user if the Exception is an ArgumentOutOfRange or FormatException, otherwise it will rethrow the Exception (And keep the original stack trace).
try
{
/////Code that may throws several types of Exceptions
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
Use above code.
Can also show custom error message as:
try
{
/////Code that may throws several types of Exceptions
}
catch (Exception ex)
{
MessageBox.Show("Custom Error Text "+ex.Message);
}
Additional :
For difference between ex.toString() and ex.Message follow:
Exception.Message vs Exception.ToString()
All The details with example:
http://www.dotnetperls.com/exception
Exception.Message provides a more (but not entirely) user-friendly message than Exception.ToString(). Consider this contrived example:
try
{
throw new InvalidOperationException();
}
catch(InvalidOperationException ex)
{
Console.WriteLine(ex.ToString());
}
Although Message yields a simpler message than ToString() the message displayed will still not mean much to the user. It won't take you much effort at all to manually swallow exceptions and display a custom message to the user that will assist them in remedying this issue.
try
{
using (StreamReader reader = new StreamReader("fff")){}
}
catch(ArgumentException argumentEx)
{
Console.WriteLine("The path that you specified was invalid");
Debug.Print(argumentEx.Message);
}
catch (FileNotFoundException fileNotFoundEx)
{
Console.WriteLine("The program could not find the specified path");
Debug.Print(fileNotFoundEx.Message);
}
You can even use Debug.Print to output text to the immediate window or output window (depending on your VS preferences) for debugging purposes.
You can use Exception.Message property to get a message that describes the current exception.
catch (Exception ex)
{
MessageBox.Show(ex.Messagge());
}
try this code :
try
{
// Code that may throw different exceptions
}
catch (Exception exp)
{
MessageBox.Show(exp.Message());
}
The trick is using the Message method of the exception:
catch (Exception ex)
{
MessageBox.Show(this, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
Related
I'm making a save to the database. But an error occurs during the save process. When I catch it with try-catch block like below, it doesn't give detailed information.
try{
//save to database
}
catch (Exception ex){
Console.WriteLine(ex.message);
}
But if I return InnerException.Message it is returning quite detailed information.
My question is does it make sense in terms of security for me to return an InnerException.Message, not an ex.Message, to the end user in WebAPI?
Or do I have to manually catch the relevant error and return? If so can I get a hint?
There is no single answer to this. Giving the full exception can present multiple infosec problems. You could create a UserFacingException : Exception, and when your code throws an exception that is OK to repeat to the user: throw that one (or a specific subclass of that one). This includes places where your code might itself catch a more specific exception, and report it upwards, for example:
catch (SqlException sql) when (sql.ErrorCode = ...) // unique constraint violation
{
throw new UserFacingException("Username already exists", sql);
}
Then you could do:
try
{
// whatever
}
catch (UserFacingException uex)
{
Console.WriteLine(uex.Message); // TODO: to user, not console
}
catch (Exception ex)
{
Log(ex);
Console.WriteLine("An unknown error occurred"); // TODO: to user, not console
}
This question already has answers here:
Why catch and rethrow an exception in C#?
(17 answers)
Closed 6 years ago.
I have some code which catches the exception, rolls back the transaction and then rethrow the exception.
catch ( Exception exSys ) {
bqBusinessQuery.RollBackTransaction();
throw exSys ;
}
If I use this code, VS Code analysis throws warning saying
Use 'throw' without an argument instead, in order to preserve the stack location where the exception was initially raised.
If I use the code
catch ( Exception exSys ) {
bqBusinessQuery.RollBackTransaction();
throw;
}
then I get a warning saying
The variable 'exSys' is declared but never used
How should I solve this problem?
Edit
I tried this method, but it doesn't work. system.exception class requires an extra message, along with inner exception. If I do that, it will throw a new message overriding the message from the original exception. I don't want to get the new exception, I want to throw the same exception with same message.
catch (System.Exception ex)
{
throw new System.Exception(ex);
}
Edit
catch (System.Exception ex)
{
throw new System.Exception("Test",ex);
}
Tried this method. And then manually caused an exception using throw new Exception("From inside");. Now, ex.Message returns "Test" instead of "From inside". I want to keep that "From inside" message as is. This suggested change will cause problem with error display code everywhere. :/
You do not have to bind a variable to the exception:
try
{
...
}
catch (Exception)
{
bqBusinessQuery.RollBackTransaction();
throw;
}
Actually, in your case, as you catch any exception, you do not have to even name the exception type:
try
{
...
}
catch
{
bqBusinessQuery.RollBackTransaction();
throw;
}
Or (as suggested #Zohar Peled) throw a new exception, using the caught exception as an inner exception. This way you both preserve the stack and give the exception more context.
try
{
...
}
catch (Exception e)
{
throw new Exception("Transaction failed", e);
}
If you actually want to use the exception for some processing (e.g. log it), but want to rethrow it intact, declare the variable, but use a plain throw:
try
{
...
}
catch (Exception e)
{
Console.WriteLine(e.Message);
throw;
}
catch (Exception)
{
bqBusinessQuery.RollBackTransaction();
throw;
}
If you don't plan on using the exception (e.g. passing the message somewhere) then you don't need to pull it out into a variable. You can simply catch, do custom thing and throw.
I need to change specific system exception message with my custom one.
Is it bad practice to catch an exception and inside the catch block check if the system exception message matches a specific string and if so, throw my custom exception?
try
{
...
}
catch (System.Security.Cryptography.CryptographicException ex)
{
if (ex.Message.Equals("The specified network password is not correct.\r\n", StringComparison.InvariantCultureIgnoreCase))
throw new Exception("Wrong Password");
else
throw ex;
}
Or is there a better way to achieve this.
There's nothing inherently wrong with throwing an exception within a catch statement. However there are a couple of things to bear in mind:
Rethrow the exception using "throw" not "throw ex", otherwise you will loose the stack trace.
From [Creating and Throwing Exceptions] 1.
Do not throw System.Exception, System.SystemException,
System.NullReferenceException, or System.IndexOutOfRangeException
intentionally from your own source code.
If the CrytographicException is really not suitable for you, you could create a specific exception class to represent an invalid password:
try
{
...
}
catch (System.Security.Cryptography.CryptographicException ex)
{
if (ex.Message.Equals("The specified network password is not correct.\r\n",
StringComparison.InvariantCultureIgnoreCase))
throw new InvalidPasswordException("Wrong Password", ex);
else
throw;
}
Note how the original exception is preserved in the new InvalidPasswordException.
To save unwinding the stack when checking the message you could use user-filtered exception handlers - https://learn.microsoft.com/en-us/dotnet/standard/exceptions/using-user-filtered-exception-handlers. This will maintain the stack trace for the unfiltered exceptions.
try
{
// ...
}
catch (System.Security.Cryptography.CryptographicException ex) when (ex.Message.Equals("The specified network password is not correct.\r\n",
StringComparison.InvariantCultureIgnoreCase))
{
throw new InvalidPasswordException("Wrong Password", ex);
}
Let us say we have an external server which we use (e.g.-telephony station, etc.). Also we have the next code:
try
{
externalService.CreateCall(callParams);
}
catch (Exception ex)
{
_log.Error("Unexpected exception when trying execute an external code.", ex);
_callService.UpdateCallState(call, CallState.Disconnected, CallOutcome.Failed);
throw;
}
Theoretically UpdateCallState could throw but we would hide this exception using that code and would treat only exceptions generated by CreateCall in a right way.
The question is, what is the right pattern for these situations so that we treat all the exceptions correctly?
You can always nest another try..catch inside the first catch and deal with it appropriately.
try
{
externalService.CreateCall(callParams);
}
catch (Exception ex)
{
_log.Error("Unexpected exception when trying execute an external code.", ex);
try
{
_callService.UpdateCallState(call, CallState.Disconnected, CallOutcome.Failed);
}
catch(Exception updateEx)
{
// do something here, don't just swallow the exception
}
throw; // this still rethrows the original exception
}
Break it up. Something like
if !TryCreateExternalCall(callParams)
{
_log.Error("Unexpected exception when trying execute an external code.", ex);
_callService.UpdateCallState(call, CallState.Disconnected, CallOutcome.Failed);
}
else
{
throw new ExternalServiceException(???);
}
TryCreateExternalCall should of course log the exception and stacktrace, before it swallows and returns false.
It is not a good practice to throw exception in Catch block.
The try, Catch suggest that
try
{
//make some changes. If something goes wrong go to Catch.
}
Catch(exception)
{
//I will clean the mess. Rollback the changes.
}
Catch the exception, only if you can handle the exception. Else bubble it up let the caller decide on what to do with the exception.
You should catch the most specific exception first, followed by the most general exceptions.
try
{
externalService.CreateCall(callParams);
}
catch (CreateCallExceptionType ccEx)
{
_callService.UpdateCallState(call, CallState.Disconnected, CallOutcome.Failed);
}
catch (Exception ex)
{
//do something
}
And then you could handle the UpdateCallState exception within the method.
I am trying to propagate to my UI the GatewayConnectionFailedException as you can see. I want this code to catch everything except that exception which I want the presentation layer to catch to notify the user that the database was the problem so he can go and fix it. My problem is that when I throw it the first time then I get GatewayConnectionFailedException not handled by user code on the GatewayException catch clause.
Its also important to note the the GatewayConnectionFailedException extends GatewayException which extends Exception. Is there something I am missing or will I have to move all the catch to the presentation layer ?
try
{
something();
}
catch (GatewayConnectionFailedException gcfe)
{
throw;
}
catch (GatewayException ge)
{
if (ge.GetType() == typeof(GatewayConnectionFailedException))
throw;
string errMsg = "Records could not be retrieved due to a data gateway error. " + GetTypeInfo();
_logger.Error(errMsg + "\r\n{0}", ge);
}
catch (Exception e)
{
if (e.GetType() == typeof(GatewayConnectionFailedException))
throw;
string errMsg = "Records could not be retrieved due to an unexpected error. " + GetTypeInfo();
_logger.Error(errMsg + "\r\n{0}", e);
}
Stupid question... is your UI code try-catching in it's call to this layer? Something has to handle that second throw...
In a nutshell, it sounds like you're trying to do this:
using System;
namespace ConsoleApplication1
{
class ExceptionA : Exception
{
public override string Message
{
get
{
return "Exception A";
}
}
}
class ExceptionB : ExceptionA
{
public override string Message
{
get
{
return "Exception B";
}
}
}
class Program
{
static void Main(string[] args)
{
try
{
DoThing();
}
catch (Exception ex)
{
Console.WriteLine("Caught in 'UI' code: " + ex.Message);
}
}
static void DoThing()
{
try
{
throw new ExceptionB();
}
catch (ExceptionB ex)
{
Console.WriteLine("Caught B");
throw;
}
catch (ExceptionA ex)
{
Console.WriteLine("Caught A");
}
catch (Exception ex)
{
Console.WriteLine("Caught Generic");
}
}
}
}
Which yields this output:
Caught B
Caught in 'UI' code:
Exception B
Press any key to continue...
It just seems like you don't have anything catching the 2nd thrown exception, which is why it's "unhandled." If we comment out the try-catch in main, we end up with an unhandled exception:
static void Main(string[] args)
{
//try
//{
DoThing();
//}
//catch (Exception ex)
//{
//Console.WriteLine("Caught in 'UI' code: " + ex.Message);
//}
}
Yielding the following output:
Caught B
Unhandled Exception: ConsoleApplication1.ExceptionB: Exception B
at ConsoleApplication1.Program.DoThing() in C:\Users\Giovanni\AppData\Local\T
emporary Projects\ConsoleApplication1\Program.cs:line 50
at ConsoleApplication1.Program.Main(String[] args) in C:\Users\Giovanni\AppDa
ta\Local\Temporary Projects\ConsoleApplication1\Program.cs:line 33
Press any key to continue . . .
One item to not although this might not fix the exception, if you are catching and rethrowing the exception use this code instead:
catch (GatewayConnectionFailedException)
{
throw;
}
this way the stacktrace reflects the programs journey more accurately. It may not solve the issue though.
Hard to tell what is missing without full picture, but one important thing that you should throw exceptions in different way. The syntax should be
throw;
you will have full stacktrace. More info.
Catching of GatewayConnectionFailedException should solve your problem and in catch block just do throw, don't throw the exception object. Answer by Andy is correct.
Secondly I'm assuming GatewayConnectionFailedException inherits from GatewayException.
Select catch sequence in ascending of order of inheritance, child class should come first and then base class.
catch(Child){}
catch(Base){}
catch(Exception) {} //Base class for all exceptions
to start your try catch is redundant. the first catch will handle GatewayConnectionFailedException the remaining catches will never be of type GatewayConnectionFailedException because they were handled by the first catch. so the code can be simplified to
try
{
something();
}
catch (GatewayConnectionFailedException)
{
throw;
}
catch (GatewayException e)
{
_logger.Error(e.Message, e);
}
Now how the UI will handle this depends on how you handle the exception. if you just throw the exception, then you need a try catch in the presentation layer as well. However if the return type of this layer returned an object like
class Result<T>
{
T Value {get;set;}
Exception Error {get;set;}
}
Then you could simply process the type without need try/catch in the presentation layer.
Also worth noting is what you are catching and why you are trying to catch it. typically you don't want to catch Exception except at the application layer where you log the error and fail. Exceptions should be exceptional, and therefore only catch exceptions you expect can happen and why they may happen. otherwise let them bubble up.
Instead of using throw exceptionName try only throw.
Edit 1:
Try catching all exceptions in the same block, then throw back the exception only if it's the GatewayConnectionFailedException
try
{
something();
}
catch (Exception e)
{
if (e.GetType() == typeof(GatewayConnectionFailedException))
throw;
string errMsg = "Records could not be retrieved due to an unexpected error. " + GetTypeInfo();
_logger.Error(errMsg + "\r\n{0}", e);
}