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.
Related
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(...);
I have this method:
public object LongRunningTask()
{
return SomethingThatTakesTooLong();
}
I wrote the following code so I can transform a normal method in an async one and still get the Exception:
public async Task<object> LongRunningTaskAsync()
{
Exception ex = null;
object ret = await Task.Run(() =>
{
object r = null;
try
{
//The actual body of the method
r = SomethingThatTakesTooLong();
}
catch (Exception e)
{
ex = e;
}
return r;
});
if (ex == null)
return ret;
else
throw ex;
}
When I need to do this in several methods, I have to copy all this code and change only the middle.
Is there a way to do something like this?
[SomeAttributeThatDoesThatMagically]
public async Task<object> LongRunningTaskAsync()
{
return SomethingThatTakesTooLong();
}
Attributes are generally metadata though it is possible to define attributes that can be executed (such as security behaviours in WCF) however, something has to be looking for it first. Your attributes won't just magically run.
I suspect you might have to use a dynamic proxy.
Take a look at how WCF does things for ideas.
There are a lot of common bool TryXXX(out T result) methods in the .NET BCL, the most popular being, probably, int.TryParse(...).
I would like to implement an async TryXXX() method. Obviously, I can't use out parameters.
Is there an established pattern for this?
More to the point, I need to download and parse a file. It's possible that the file does not exist.
This is what I came up with so far:
public async Task<DownloadResult> TryDownloadAndParse(string fileUri)
{
try
{
result = await DownloadAndParse(fileUri); //defined elsewhere
return new DownloadResult {IsFound = true, Value = result}
}
catch (DownloadNotFoundException ex)
{
return new DownloadResult {IsFound = false, Value = null}
}
//let any other exception pass
}
public struct DownloadResult
{
public bool IsFound { get; set; }
public ParsedFile Value { get; set; }
}
I've come up with the following definitions. The defaultValue parameters are there mostly to be able to overload the TryGet method, as generic constraints are not part of a method's signature, that which makes the method unique when deciding which method to call (for instance, the return type is also not part of the signature).
public async Task<T> TryGet<T>(Func<Task<T>> func, T defaultValue = null) where T : class
{
try
{
return await func();
}
catch (ArgumentException)
{
return defaultValue;
}
catch (FormatException)
{
return defaultValue;
}
catch (OverflowException)
{
return defaultValue;
}
}
public async Task<Nullable<T>> TryGet<T>(Func<Task<T>> func, Nullable<T> defaultValue = null) where T : struct
{
try
{
return await func();
}
catch (ArgumentException)
{
return defaultValue;
}
catch (FormatException)
{
return defaultValue;
}
catch (OverflowException)
{
return defaultValue;
}
}
You should review exception handling, this example handles the common parsing exceptions. It may make more sense to react to other exceptions, such as InvalidOperationException and NotSupportedException, probably the most used exception types on the framework itself (not necessarily the most commonly thrown ones).
Another approach is to re-throw critical exceptions, such as ThreadAbortException and have a simple catch-all clause that returns the default value. However, this will hide every exception not deemed critical, no matter how severe it is.
As such, and because throwing exceptions is an expensive operation, it's Parse that is usually defined in terms of TryParse. So your TryGet should have a contract, e.g. deal with OperationCanceledException, which includes TaskCanceledException and nothing else.
Finally, you should name it TryGetAsync, following the Async-suffix convention. [1] [2]
One of possible decisions is an array of ParsedFile, containing 0 or 1 element.
public async Task<ParsedFile[]> TryDownloadAndParse(string fileUri)
{
try
{
return new[] { await DownloadAndParse(fileUri) };
}
catch (DownloadNotFoundException ex)
{
return new ParsedFile[0];
}
}
Now you can check the result:
. . .
var parsedFiles = await TryDownloadAndParse(url);
if (parsedFiles.Any())
{
var parsedFile = parsedFiles.Single();
// more processing
}
. . .
If you want to call void method, you can use ?. operator:
var parsedFiles = await TryDownloadAndParse(url);
parsedFiles.SingleOrDefault()?.DoVeryImportantWorkWithoutResult();
UPDATE
In Azure you can use ConditionalValue<TValue> class.
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.
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");
}
}