Throwing Exceptions Correctly - c#

I have the following code
public HttpResponseMessage AddDataToDatabase([FromBody] Data data)
{
try
{
var token = _tokenService.GetToken(Request.Headers.Authorization);
if (_pService.Permission(_tokenService.GetUserId(token), "Enable_Data"))
{
_noteService.AddData(data, _tokenService.GetUserId(token));
return Request.CreateResponse(HttpStatusCode.OK, "Data has been added to the case.");
}
throw new HttpResponseException(
Request.CreateErrorResponse(HttpStatusCode.Forbidden, "Cannot add data because you don't have permission."));
}
catch (Exception exception)
{
if (exception is SqlException)
{
throw new HttpResponseException(
Request.CreateErrorResponse(HttpStatusCode.ServiceUnavailable, exception));
}
if (exception is ArgumentException)
{
throw new HttpResponseException(
Request.CreateErrorResponse(HttpStatusCode.Conflict, exception.Message));
}
throw;
}
}
I want to catch the Forbidden Exception like other exception in the catch block but not sure how to do that. The way I am returning Forbidden exception right now breaks unit tests which return SqlException and ArgumentExpception.
How can I throw exceptions correctly?

By far, the easiest way is to simply do it like this.
catch (Exception exception)
{
throw;
}
Unlike your code, this code also handles unanticipated exceptions instead of just SqlException and ArgumentException.
But why are you doing this? If you want the exception to propagate out to the caller, then simply remove the try...catch block in this method. Then just throw the desired exception in your code.
If you are capturing and converting third-party exceptions, the recommended approach is as follows.
catch (SqlException exception)
{
throw new HttpResponseException(
Request.CreateErrorResponse(HttpStatusCode.ServiceUnavailable, exception));
}
catch (ArgumentException exception)
{
throw new HttpResponseException(
Request.CreateErrorResponse(HttpStatusCode.Conflict, exception.Message));
}

you should probably replace your if logic in your catch by using more selective catch :
catch (SqlException exception)
{
throw new HttpResponseException(
Request.CreateErrorResponse(HttpStatusCode.ServiceUnavailable, exception));
}
catch (ArgumentException exception)
{
throw new HttpResponseException(
Request.CreateErrorResponse(HttpStatusCode.Conflict, exception.Message));
}
The uncaught exceptions will simplypass through (as when you you use throw;).
If you want to catch another type of exception, just add it to the list.
However, it is not very clear how your tests are broken. You should provide more details at this level if you want more help.

Related

Re-throw an exception in a conditional expression

What is the correct way of rewriting the code in the following catch block using a conditional expression? if supported!?
try
{
return await _client.GetStreamAsync(_uri);
}
catch
{
if (IsConnected)
throw;
else
throw new IOException();
}
C# compiler does not like the following
IsConnected ? throw : new IOException();
Note that re-throwing a caught exception, like the following, is in violation of CA2200
try
{
return await _client.GetStreamAsync(_uri);
}
catch (Exception ex)
{
throw IsConnected ? throw ex : new IOException();
}
Your first example is fine. throw; will rethrow the exception leaving the stack trace in tact. As an alternative, I would suggest just conditionally catching the exception when IsConnected == false:
catch when (IsConnected)
{
throw new IOException();
}
You can read more about the when keyword in the docs.

How to catch a rethrown exception?

I have the following code:
try
{
await _policyService.QueuePayment();
}
catch (Exception ex)
{
var slackError = new ErrorNotificationMessage("{ex.Message}");
await Notify(slackError);
}
I want to give more detail and log it to Slack if the Exception is a Security Exception, so I extended this try/catch block as follows:
try
{
await _policyService.QueuePayment();
}
catch (SecurityException ex)
{
throw new Exception("detailed message", ex);
}
catch (Exception ex)
{
var slackError = new ErrorNotificationMessage("{ex.Message}");
await Notify(slackError);
}
However this does not catch the rethrown Exception and log it to Slack. What am I missing here?
As it was already mentioned in comments by #canton7, you'd need a try-catch inside the catch (SecurityException ex) in order to catch it. However, as it was also mentioned, that doesn't make sense here. It's also not a common (or rather, correct) practice to wrap an exception just to change the error message.
Just use standard boolean logic:
try
{
await _policyService.QueuePayment();
}
catch (Exception ex)
{
var message = ex is SecurityException ? "Some very important message" : ex.Message;
var slackError = new ErrorNotificationMessage(message);
await Notify(slackError);
}
However this does not catch the rethrown Exception and log it to Slack. What am I missing here?
When we throw an exception explicitly it can be catched at the caller end by enclosing the method call in a try catch block. We cannot throw and catch the exception from a catch block in same method unless we add another try catch which does not actually make sense here.
What you should be doing is directly throwing that exception like :
try
{
await _policyService.QueuePayment();
}
catch (Exception ex)
{
if(ex is SecurityException)
{
// for security exception do something different
}
else
{
var slackError = new ErrorNotificationMessage("{ex.Message}");
await Notify(slackError);
}
}

Reuse catch for all catches

is it possible to do something like the following:
I want to catch a custom exception and do something with it - easy: try {...} catch (CustomException) {...}
But then i want to run the code used in the "catch all" block still run some other code which is relevant to all catch blocks...
try
{
throw new CustomException("An exception.");
}
catch (CustomException ex)
{
// this runs for my custom exception
throw;
}
catch
{
// This runs for all exceptions - including those caught by the CustomException catch
}
or do i have to put whatever i want to do in all exception cases (finally is not an option because i want it only to run for the exceptions) into a separate method/nest the whole try/catch in another (euch)...?
I generally do something along the lines of
try
{
throw new CustomException("An exception.");
}
catch (Exception ex)
{
if (ex is CustomException)
{
// Do whatever
}
// Do whatever else
}
You need to use two try blocks:
try
{
try
{
throw new ArgumentException();
}
catch (ArgumentException ex)
{
Console.WriteLine("This is a custom exception");
throw;
}
}
catch (Exception e)
{
Console.WriteLine("This is for all exceptions, "+
"including those caught and re-thrown above");
}
Just do the overall catch and check to see if the exception is that type:
try
{
throw new CustomException("An exception.");
}
catch (Exception ex)
{
if (ex is CustomException)
{
// Custom handling
}
// Overall handling
}
Alternately, have a method for overall exception handling that both call:
try
{
throw new CustomException("An exception.");
}
catch (CustomException ex)
{
// Custom handling here
HandleGeneralException(ex);
}
catch (Exception ex)
{
HandleGeneralException(ex);
}
No, it doesn't do this way, you either catch a specific exception (linearly) or a generalisation. If you wish to run something for all exceptions you would need to keep a record of whether or not an exception has been thrown, perhaps what it was etc, and use finally, or another contrived, probably more 'messy' and verbose, mechanism.

Is the order of Catch blocks important?

Just making sure I understand it well. Is the correct schema correct? Catching the most specific exceptions first to catching broader exceptions with general catch at the end of the set of catch blocks.
try
{
some code
}
catch(SomeSpecificException ex)
{
}
catch(LessSpecificException ex)
{
}
catch
{
//some general exception
}
I believe it won't let you write it in the incorrect order.
This generates an error:
try
{
throw new OutOfMemoryException();
}
catch(Exception ex)
{
"B".Dump();
}
catch(OutOfMemoryException ex)
{
"A".Dump();
}

How do I bubble up an Exception to my UI?

I have an aspx page that, on a button click, creates an instance of a serviceRefernece object. In the code behind for my page I have the call wrapped in a try/catch.
try
{
var client = GetClient();
var request = new ActiveVerificationRequestDC();
var response = client.GetActiveVerification(request);
DoSomethingWithTheResponse(response);
}
catch (FaultException ex)
{
LogError(ex, MethodBase.GetCurrentMethod().Name);
throw;
}
catch (Exception ex)
{
var args = new[] { MethodBase.GetCurrentMethod().Name, ex.Message };
DisplayError(args);
}
The svc file that is referenced is using pretty much the same pattern. It is calling an internal client over net.tcp. The call is wrapped in a try/catch
try
{
var client = new InternalServiceClient();
var response = client.GetActiveVerification(request);
client.Close();
return response;
}
catch (FaultException fe)
{
LogError(MethodBase.GetCurrentMethod().Name, fe);
throw;
}
Here is my problem, how do I get errors here to bubble up to my UI catch statement? When I leave it like this, I get an unhandled exception error from visual studio. I have tried removing the throw which makes me specify a return value, and I return null. This makes the UI not work correctly. I have tried throw new Exception(fe.message) and I get the same problem with the unhandled exception. Basically my question is how can I accomplish what I need? What am I missing?
You need a separate try/catch block around your try/catch block. You have it such that you will catch a FaultException and any type of Exception, but your Exception block will not catch your throw from FaultException. So, just enclose this with another try/catch or handle it within both the FaultException catch and the Exception catch.
The reason could be the throwing of another exception in your second code snippet that isn't of the type FaultException; such an exception would pass as unhandled in this situation. Maybe you should add another catch block to your second code snippet that catches exceptions of the type Exception:
catch (FaultException fe)
{
LogError(MethodBase.GetCurrentMethod().Name, fe);
throw;
}
catch (Exception ex)
{
throw;
}
Is the FaultException you are re-throwing a generic type? Are the relevant classes detailed by any FaultContract attributes accessible to all assemblies in this execution stack?
Edit: In your first code snippet ...
catch (FaultException ex)
{
LogError(ex, MethodBase.GetCurrentMethod().Name);
throw;
}
If the unhandled error occurs on the throw statement of this handler, then #MCain is right.
I believe you have to throw in the catch block for the error to bubble up
try
{
}
catch (SqlException _SqlException)
{
//Log Error to file
throw;
}
catch (IOException _IOexception)
{
//Log Error to file
throw;
}
catch (Exception _exception)
{
//Log Error to file
throw;
}
This kind of a block will be in the calling method

Categories

Resources