Wrap an exception in a message without throwing it - c#

I'm writing a service which's methods must not throw exceptions but should return a generic Message-object which contains the actual result of the method call and exceptions if any have occured. This Message class looks like this:
public class Message<T>
{
private List<Exception> exceptions = new List<Exception>();
public T Result { get; set; }
public void AddException(Exception x)
{
this.exceptions.Add(x);
}
public bool HasExceptions
{
get
{
return this.exceptions.Count > 0;
}
}
public IEnumerable<Exception> Exceptions
{
get
{
foreach (var exception in this.exceptions)
yield return exception;
}
}
}
Usually the implementation of a service method then looks like this:
public Message<int> MyServiceMethod()
{
var msg = new Message<int>();
try
{
// do something useful here
msg.Result = 42;
}
catch (Exception x)
{
msg.AddException(x);
}
return msg;
}
The caller can then handle exceptions if necessary.
var msg = service.MyServiceMethod();
if (msg.HasExceptions)
{
// Handle exceptions here
}
Now I have a service method with an argument which must be in a certain range. Since it feels natural for me to respond with an ArgumentOutOfRangeException if the argument is out of range, I implemented it like this:
public Message<int> MyOtherServiceMethod(int arg)
{
var msg = new Message<int>();
if (arg < 1)
{
msg.AddException(new ArgumentOutOfRangeException("arg", "Argument must be greater than 0"));
return msg;
}
// ...
return msg;
}
Basically this works. The only thing I'm missing is the stack trace of the exception. This is not a problem since I don't need that in my scenario. But it made me wonder, are there any other "side effects" which might cause trouble when the exception is used but not thrown?

You should use some construction that takes message and exception as arguments:
try
{
// do something useful here
}
catch (Exception x)
{
throw YourPreferredException(some_message, x);
}
This will make x available as yourPreferredException.InnerException property.
Also, I don't think it's a good design choice to have a method returning Message and running the try/catch block inside it (should be the other way around).

I would say that's not really the intended use of exceptions in C#. If you want a custom message then you just use the Exception constructor that takes a message and another instance of type Exception, this will give you a new exception with your custom message plus the original exception set as the instances InnerException property. You're just reinventing the wheel here with some custom 'message' class. If all you want to do is return a message (like you don't want to throw) then you should be taking the exceptions Message property and assigning it to some string or returning that string directly.
Here are a couple more idiomatic examples for handling your error;
Message ret = new Message();
try
{}
catch (Exception e)
{
ret.ErrorPropertyOfTypeString = e.Message;
}
return ret;
Message ret = new Message();
try
{}
catch (Exception e)
{
throw new Exception("My custom message here", e);
}
return ret;
Whatever you're doing, one of the two patterns above should probably used instead.

Related

Best practice for many try-catch blocks

I have many statements that can throw exceptions. Exceptions are not important.
My system accepts missing patient data fields.
patientData.PatientId = message.Find(...);
try
{
patientData.Gender = message.Find(...);
}
catch
{
// no gender, no problem
}
try
{
patientData.DateOfBirth = message.Find(...);
}
catch
{
// no DateOfBirth, no problem
}
// and many other try-catch blocks ...
What is the best way to write these statements that can throw exceptions but not critical?
In your example, you can create static TryFindMessage method in addition to Find. In case of exception just return false.
For example:
bool Message.TryFind(..., Message message, out string result).
But, if you wish some generic approach which you can use with anything, then you can take advantage of delegates and create some static helper.
You can use Action or Func in that case. Add another extension method which accepts Func if you need to return some value from executed function.
public static class SilentRunner
{
public static void Run(Action action, Action<Exception> onErrorHandler)
{
try
{
action();
}
catch (Exception e)
{
onErrorHandler(e);
}
}
public static T Run<T>(Func<T> func, Action<Exception> onErrorHandler)
{
try
{
return func();
}
catch (Exception e)
{
onErrorHandler(e);
}
return default(T);
}
}
And then use it so:
SilentRunner.Run(
() => DoSomething(someObject),
ex => DoSomethingElse(someObject, ex));
In case of Func, you can take result as well:
var result = SilentRunner.Run(
() => DoSomething(someObject),
ex => DoSomethingElse(someObject, ex));
I have many statements that can throw exceptions. Exceptions are not
important.
This can be dangerous, because exceptions can be thrown for different reasons, not only because of missing property.
I would advise instead of swallowing exception, modify code to return default value(null) when value is not found.
You can introduce new method in message class, for example FindOrDefault
// Pseudo code
public T FindOrDefault(string property)
{
return CanFind(property) ? Find(property) : default(T);
}
Usage of such method will be self explanatory
patientData.PatientId = message.Find(...); // Mandatory - must throw if not found
patientData.Gender = message.FindOrDefault(...);
patientData.DateOfBirth = message.FindOrDefault(...);

Rethrow an exception is this case

I have something like this:
public byte[] AnyMethod(){
try {
...
}
catch (Exception e) {
string errorMessage =
"Some custom message, which should the caller of that method should receive";
// I thought something of this ,to pass through my custom exception to the caller?!
throw new ApplicationException(errorMessage);
//but this does not allow the method
}
}
But this:
throw new ApplicationException(errorMessage);
Will result in:
An exception of type 'System.ApplicationException' occurred in ...dll but was not handled in user code
How to do give the custom errror message to the caller of my above mentioned method ?
First, use a custom exception or at least one more meaningful instead of ApplicationException. Second, you have to catch the exception if your method throws it.
So the calling method should also wrap the method call in a try...catch:
try
{
byte[] result = AnyMethod();
}catch(MyCustomException ex)
{
// here you can access all properties of this exception, you could also add new properties
Console.WriteLine(ex.Message);
}
catch(Exception otherEx)
{
// all other exceptions, do something useful like logging here
throw; // better than throw otherEx since it keeps the original stacktrace
}
Here's an abstract, simplified example:
public class MyCustomException : Exception
{
public MyCustomException(string msg) : base(msg)
{
}
}
public byte[] AnyMethod()
{
try
{
return GetBytes(); // exception possible
}
catch (Exception e)
{
string errorMessage = "Some custom message, which should the caller of that method should receive";
throw new MyCustomException(errorMessage);
}
}
But note that you should not use exceptions for normal program flow. Instead you could either return true or false to indicate if the action was successful or use an out parameter for the byte[] like int.TryParse(or the other TryParse methods).
publy byte[] AnyMethod(){
try{
}catch(Exception e){
string errorMessage = string.Format("Some custom message, which should the caller of that method should receive. {0}", e);
//I thought something of this ,to pass through my custom exception to the caller?!
throw new ApplicationException(errorMessage);
//but this does not allow the method
}
}
OR
public byte[] AnyMethod(){
try{
}catch(Exception e){
string errorMessage = "Some custom message, which should the caller of that method should receive";
//I thought something of this ,to pass through my custom exception to the caller?!
throw new ApplicationException(errorMessage, e);
//but this does not allow the method
}
}

Design Pattern for Error Handling

I've ran into this problem a few times on various projects, and I've wondered if there's a better solution than the one I normally end up using.
Say we have a series of methods that need to execute, and we want to know if something goes wrong within one of the methods and break out gracefully (potentially undo-ing any previous changes...), I typically do the following (pseudo C# because it's what I'm most familiar with):
private bool SomeMethod()
{
bool success = true;
string errorMessage = null;
success = TestPartA(ref errorMessage);
if (success)
{
success = TestPartB(ref errorMessage);
}
if (success)
{
success = TestPartC(ref errorMessage);
}
if (success)
{
success = TestPartD(ref errorMessage);
}
//... some further tests: display the error message somehow, then:
return success;
}
private bool TestPartA(ref string errorMessage)
{
// Do some testing...
if (somethingBadHappens)
{
errorMessage = "The error that happens";
return false;
}
return true;
}
I just wondered (and this is my question) if there's a better methodology for coping with this kind of thing. I seem to end up writing a lot of if statements for something that seems like it should be slicker.
I've been suggested having a loop over a set of delegate functions, but I'd be worried that would be over-engineering the solution, unless there's a clean way to do it.
I think you should probably be using exceptions. Note you should generally only be catching exceptions at the "top level" in your application.
private void TopLevelMethod()
{
try
{
SomeMethod();
}
catch (Exception ex)
{
// Log/report exception/display to user etc.
}
}
private void SomeMethod()
{
TestPartA();
TestPartB();
TestPartC();
TestPartD();
}
private void TestPartA()
{
// Do some testing...
try
{
if (somethingBadHappens)
{
throw new Exception("The error that happens");
}
}
catch (Exception)
{
// Cleanup here. If no cleanup is possible,
// do not catch the exception here, i.e.,
// try...catch would not be necessary in this method.
// Re-throw the original exception.
throw;
}
}
private void TestPartB()
{
// No need for try...catch because we can't do any cleanup for this method.
if (somethingBadHappens)
{
throw new Exception("The error that happens");
}
}
I have used the built-in System.Exception class in my example; you can create your own derived exception classes, or use the built-in ones derived from System.Exception.
You could perhaps try looking at the "Open/Closed" section of the SOLID Principle. In your example you could perhaps create an ITestRule interface which contains a method called CheckRule() that will updated your message and return a bool. You would then create an interface implementation for each rule you want to test, and add that class to a List<ITestRule> object. From the Redmondo example above, I would change to the following:
var discountRules =
new List<ITestRule>
{
new TestPartA(),
new TestPartB(),
new TestPartC(),
new TestPartD(),
};
You would then pass the new List<ITestRule> to an evaluator which will loop through each of the classes and runs the CheckRule() method.
I try to stick to a principle known as 'Fail Fast'; methods should fail when they are supposed to, and return immediately with details of the error. The calling method then responds appropriately (re-throw the exception to its caller, log the details, show an error if it's a UI-bound method, etc): -
http://en.wikipedia.org/wiki/Fail-fast
However, this does not mean using exceptions to control the flow of your application. Just raising an exception when you could deal with it is generally bad practice: -
http://msdn.microsoft.com/en-us/library/dd264997.aspx
In your case, I'd re-write your code as (for example): -
private bool SomeMethod()
{
bool success = false;
try
{
TestPartA();
TestPartB();
TestPartC();
TestPartD();
success = true;
}
catch (Exception ex)
{
LogError(ex.Message);
}
//... some further tests: display the error message somehow, then:
return success;
}
private void TestPartA()
{
// Do some testing...
if (somethingBadHappens)
{
throw new ApplicationException("The error that happens");
}
}

How to check if something is an .net exception or the custom exception

Like in the question. I want to check if something on the collection of exceptions is my custom exception or is it the Exception class given by the .Net framework. Thnaks in advance for your help. \
Please note:
I don't know what is the class name of my custom exception it could be called exceptionA, exceptionB or for example xyzException
I have code like this:
public IEnumerable<Type> GetClassHierarchy(Type type)
{
if (type == null) yield break;
Type typeInHierarchy = type;
do
{
yield return typeInHierarchy;
typeInHierarchy = typeInHierarchy.BaseType;
}
while (typeInHierarchy != null && !typeInHierarchy.IsInterface);
}
public string GetException(System.Exception ex)
{
if (ex == null)
{
return null;
}
if (ex.InnerException == null)
{
return ex.Message;
}
var exceptionHerarchy = GetClassHierarchy(ex.GetType());
var isMyException = exceptionHerarchy.Any(t => t != typeof(System.Exception));
if (isMyException)
{
return string.Format("{0};{1}", ex.Message, GetException(ex.InnerException));
}
else
{
return GetException(ex.InnerException);
}
}
var isMyException = exceptionHerarchy.Any(t => t != typeof(System.Exception)); this is alays returning true because there is this type on the list probably
Very simple:
var t = myException.GetType().FullName;
bool isSystemException = (t.StartsWith("System."));
Exception types in the .NET Framework are all in System or one of its subnamespaces.
EDIT: To make this slightly prettier, create an extension function to the Exception class:
public static bool IsSystemException(this Exception exception)
{
return (exception.GetType().FullName.StartsWith("System."));
}
Double reconsider why do you want to do it. And then use one of the solutions below.
Better
Derive all custom exceptions from one base class exception provided by you and catch it in try-catch block.
Worse
Dynamically check some information about exception using Reflection, like its assembly:
ex.GetType().AssemblyQualifiedName
Make your Exception class extend from a custom base class.
class MyBaseEception : Exception
{
}
class MyCustomException : MyBaseException {}
try
{
}
catch (MyBaseException customException) {....}
catch (Exception e)
{
}
Although one wonders why you want to do this.
Heres my 2 pence...
try
{
}
catch (Exception e)
{
if (e.GetType().Assembly.GetName().Name != "My.Own.Namespace")
{
// this is a .net exception?
}
}
Why have custom exceptions if you're unsure when they would fire? IME, custom exceptions are typically used around business logic when you want to handle a specific case. Otherwise rely on the framework. In terms of the code, stack your custom exceptions first, then have a catch all in case the custom exception does not fire.
try
{
//do something
}
catch (MyCustomException ex)
{
//log, continue, throw, etc
}
catch (Exception e)
{
//log, continue, throw, etc
}

Adding Global Try Catch Exception

I implemented a Global Try Catch mechanism in this way. I added a seperate class called HandleException.cs
public static class HandleException
{
public static void GlobalTryCatch(Action action, object obj)
{
try
{
action.Invoke();
}
catch(SqlException ex)
{
obj.GetType().GetProperty("Success").SetValue(obj.GetType(), false);
obj.GetType().GetProperty("FailureMessage").SetValue(obj.GetType(), ex);
}
catch(Exception ex)
{
obj.GetType().GetProperty("Success").SetValue(obj.GetType(), false);
obj.GetType().GetProperty("FailureMessage").SetValue(obj.GetType(), ex);
}
}
}
And this way calling it.
public override Result<int> Update(UserProfile data)
{
var result = new Result<int> { Success = false };
HandleException.GlobalTryCatch(() =>
{
SqlParameter[] sParam =
{
DbHelper.CreateParameter("#UserId", ParameterDirection.Input, SqlDbType.Int, data.UserId),
DbHelper.CreateParameter("#FirstName", ParameterDirection.Input, SqlDbType.VarChar,100, data.FirstName),
DbHelper.CreateParameter("#LastName", ParameterDirection.Input, SqlDbType.VarChar,100, data.LastName),
DbHelper.CreateParameter("#Gender", ParameterDirection.Input, SqlDbType.Char,1, data.Gender),
DbHelper.CreateParameter("#Dob", ParameterDirection.Input, SqlDbType.Date, data.DateOfBirth),
DbHelper.CreateParameter("#ImageUrl", ParameterDirection.Input, SqlDbType.VarChar, 150, data.ImageUrl),
};
using(var sql = new DbHelper())
{
sql.ExecuteSpReturnScalar("UserProfile_Update", sParam);
}
result.Success = true;
}, result);
return result;
}
My questions are
Is this a standard practice for implementing global try catch mechanism or Is there any other standard way to implement this?
I had used this in GlobalTryCatch method. Whether this way we can assign value to a property by passing Generic Object?
obj.GetType().GetProperty("Success").SetValue(obj.GetType(), false);
Is this a standard practice for implementing global try catch mechanism
No, it is not. Moreover, mentioned "global try-catch mechanism" is a bad practice. Wrapping every method in try-catch assumes, that you definitely know, what to do after any exception has been thrown. In the real world this is false. Look at this sample:
void AnyMethod()
{
var result = // ...
HandleException.GlobalTryCatch(() => { /* action 1 */}, result);
// should we check result to continue?
// if so, this is a typical error-code approach, which annihilates
// all preferences, provided by .NET exceptions;
// if we shouldn't check it, what would be the behavior of our code,
// if the state is broken after action 1?
HandleException.GlobalTryCatch(() => { /* action 2 */}, result);
// the same questions
HandleException.GlobalTryCatch(() => { /* action 3 */}, result);
}
Similar approach from time-to-time being used to log exceptions (due to absence of out-of-box aspects inmplementation in .NET):
void Execute(Action action)
{
try
{
action();
}
catch (Exception e)
{
Logger.Log(e);
throw;
}
}
T Execute<T>(Func<T> func)
{
try
{
return func();
}
catch (Exception e)
{
Logger.Log(e);
throw;
}
}
but:
1) it logs full exception information (e.g., your code is missing stack trace and inner exceptions);
2) it re-throws the same exception (this allows to use all benefits from .NET exceptions);
3) it wraps only limited number of top-level methods, not every method.
Whether this way we can assign value to a property by passing Generic Object?
You could do something like this:
interface IActionResult
{
bool Success { get; set; }
string FailureMessage { get; set; }
}
public static void GlobalTryCatch<T>(Action action, T obj)
where T : IActionResult
{
// ...
}
but this doesn't cancel answer on your 1st question.
You can use http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx (or http://msdn.microsoft.com/en-us/library/system.windows.application.dispatcherunhandledexception.aspx for WPF applications).
Generally it is not a bad idea to do something meaningful during this events - logging the exceptions (or sending them to admin) and displaying a message to user (something like "Sorry, error occurred, contact your admin please").
But as others said - you should handle the excpetions in your methods where you can do something meaningful with them, not on global level. And even if it is not mandatory in c#, it's a good idea to add to comments that your method can throw some kind of exception on certain circumstances.

Categories

Resources