How to rethrow exceptions in a program with multiple layers? - c#

I have an MVC EF5 setup, with classes:
Program - this is the controller
UserInterface - this is the view, responsible for displaying and prompting for data.
DataAccess - Model, this Creates, Reads, Updates, and Deletes data in my EF model classes
When the DataAccess class tries to do a CRUD operation on my database, if it catches an error, it needs to be handled, my UserInterface class needs to print messages to the user, reporting any errors if neccessary. So, when an error happens, it needs to go through the program class first, then to the UserInterface class, because data layer shouldn't directly communicate to the presentation layer.
It was suggested to me that I don't pass or return the exception to a calling function, but that I should "throw a new simpler exception to the layers above". All this talk about exceptions is confusing to me because My experience with exceptions is limited to this format:
try
{
// stuff
}
catch (exception ex)
{
console.writeline(ex.ToString());
}
I've done some of my own research to try and find the answer to this problem, and I've learned a few things but don't know how to put it all together:
I learned:
throw; rethrows an exception and preserves the stack trace
throw ex throws an existing exception, such as one caught in a catch block. and resets the stack trace.
There is a property called Exception.StackTrace. I understand that each time an exception is thrown, the frames in the call stack are recorded to the Exception.StackTrace property.
However, I don't know where to place my try/catch blocks to utilize rethrowing
Is it something like the following code? Or am I missing the point on how this works?
EDITED: (added a little more to make sense of this guesswork to others)
void MethodA()
{
try
{
MethodB();
}
catch (MyExceptionType ex)
{
// Do stuff appropriate for MyExceptionType
throw;
}
}
void MethodB()
{
try
{
MethodC();
}
catch (AnotherExceptionType ex)
{
// Do stuff appropriate for AnotherExceptionType
throw;
}
}
void MethodC()
{
try
{
// Do Stuff
}
catch (YetAnotherExceptionType ex)
{
// Do stuff appropriate for YetAnotherExceptionType
throw;
}
}

There is more than how you use different type of exception handling. Functionally you should define what layers has to do what with a exception.
Like data layer => dont throw anything other than DataException or SQLException. Log them and throw back a generic database exception back to UI.
Business layer => log and rethrow simple bussiness exception
UI layer => catch only business exception and alert it in a message inside business exception
Once all this is defined, you can use what you have learned and summarized in question to build this.

What (I think) was suggested you do by throw a new simpler exception is that you translate the exceptions from the lower layers into new, higher level exceptions for consuming in the outer layers. The lower level exceptions are not suitable for consumption at the upper levels of the program.
For example, in LINQ to Entities, the method Single() will throw an InvalidOperationException when the sequence has no elements. However, this exception type is very common, so catching it in the user interface levels is hard to do: how would you differentiate between different possibilities of this exception being thrown (for example, modifying a read-only collection)? The solution is to translate the exception into another (new, user-defined) type that the application can easily handle.
Here is a simple example of the idea:
public class MyUserService {
public User GetById(int id) {
try {
using(var ctx = new ModelContainer()) {
return ctx.Where(u => u.Id == id).Single();
}
}
catch(InvalidOperationException) {
// OOPs, there is no user with the given id!
throw new UserNotFoundException(id);
}
}
}
Then the Program layer can catch the UserNotFoundException and know instantly what happened, and thus find the best way to explain the error to the user.
The details will depend on the exact structure of your program, but something like this would work in an ASP.NET MVC app:
public class MyUserController : Controller {
private MyUserService Service = new MyUserService();
public ActionResult Details(int id) {
User user;
try {
user = Service.GetById(id);
}
catch(UserNotFoundException) {
// Oops, there is no such user. Return a 404 error
// Note that we do not care about the InvalidOperationException
// that was thrown inside GetById
return HttpNotFound("The user does not exist!");
}
// If we reach here we have a valid user
return View(user);
}
}

Related

How to be explicit about NOT throwing an exception?

This might be a broad question, but recently I ahve wondered about the following: In our C# backend we have many places that wrap some code in a try/catch block, specifically calls to external WcF services. Some of these calls are crucial for the application so in the catch block we log the error and rethrow, like:
catch(Exception ex)
{
_logger.Error("Some good error message");
throw ex;
}
On the other hand there are services we allow to fail, but we still want to log the error, so they look like:
catch(Exception ex)
{
_logger.Error("Some good error message");
}
Now reading the code of team members I can not be sure if they forgot to throw or if this is the intended behaviour.
Q: Is there a way, resp. what is the default way, to explicitly NOT rethrow (without including a comment in the code).
I have considered something like this:
catch(Exception ex)
{
_logger.Error("Some good error message");
NotThrowingHereOnPurpose();
}
// ...
// and further below a private method
// ...
private void NotThrowingHereOnPurpose(){}
One approach that may be useful here is to change the way of invoking the code that you explicitly allow to fail in such a way that it does not look like a try/catch block at all.
For example, you could write a helper method that does error reporting, and call it with actions expressed as lambdas:
void InvokeFailSafe(Action action, Action<Exception> onFailure = null) {
try {
action();
} catch (Exception e) {
if (onFailure != null) {
onFailure(e);
}
}
}
Now instead of try/catch you would write this:
InvokeFailSafe(
() => {
... The code that may fail
}
, exception => _logger.Error("Some good error message: {0}", exception)
);
or like this, if you don't want anything logged:
InvokeFailSafe(
() => {
... The code that may fail
}
);
If you code things this way, there would be no doubts about a missing throw statement.
It's an opposite solution to dasblinkenlight's answer. Instead of notifying others that the exception mustn't be rethrown it would say that it must be.
If you only want to log it then use the Error method as usual. Otherwise, you can write an extension method for your logger to log and throw exceptions.
The method would take the catched exception and rethrow it using the ExceptionDispatchInfo class. The ExceptionDispatchInfo is used to rethrow the exception with the original stack trace information and Watson information. It behaves like throw; (without the specified exception).
public static void ErrorAndThrow(this ILogger logger, string message, Exception exception)
{
var exceptionInfo = ExceptionDispatchInfo.Capture(exception);
logger.Error(message);
exceptionInfo.Throw();
}
And use it this way:
try
{
}
catch (Exception ex)
{
// ex would be rethrown here
_logger.ErrorAndThrow("Some good error message", ex);
}
Q: Is there a way, resp. what is the default way, to explicitly NOT
rethrow (without including a comment in the code).
Ideal way would be not to catch a generic exception. Now, to throw or not that entirely depends on your case. You need to understand that Exception handling is used when you know what to do in case an exception occurs. So, only specific exceptions should be handled. Catching exceptions without knowing what you are catching will change the behavior of your application.
Now reading the code of team members I can not be sure if they forgot
to throw or if this is the intended behaviour.
This is something the author of the code can explain to you. But here is a learning to take from this. Your code should be self explanatory. In specific cases where you are unable to express yourself with the code, add a meaningful comment.
You can check this link for better understanding.
I actually found another way that kind of includes what other have suggested here, but uses a built in feature: exception filters. I was free to modify the example given in here to illustrate this:
public void MethodThatFailsSometimes()
{
try {
PerformFailingOperation();
}
catch (Exception e) when (e.LogAndBeCaught())
{
}
}
and then one could have two extension methods on Exception, say LogAndBeCaught and LogAndEscape like so:
public static bool LogAndBeCaught(this Exception e)
{
_logger.Error(#"Following exception was thrown: {e}");
return true;
}
public static bool LogAndEscape(this Exception e)
{
_logger.Error(#"Following exception was thrown: {e}");
return false;
}

How to not throw exception in ASP.NET Web Api service?

I am building a ASP.NET Web Api service and I would like to create centralized exception handling code.
I want to handle different types of exceptions in different ways. I will log all exceptions using log4net. For some types of exceptions I will want to notify an administrator via email. For some types of exceptions I want to rethrow a friendlier exception that will be returned to the caller. For some types of exceptions I want to just continue processing from the controller.
But how do I do that? I am using an Exception Filter Attribute. I have this code working. The attribute is registered properly and the code is firing. I just want to know how I can continue if certain types of exceptions are thrown. Hope that makes sense.
public class MyExceptionHandlingAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext actionExecutedContext)
{
//Log all errors
_log.Error(myException);
if(myException is [one of the types I need to notify about])
{
...send out notification email
}
if(myException is [one of the types that we continue processing])
{
...don't do anything, return back to the caller and continue
...Not sure how to do this. How do I basically not do anything here?
}
if(myException is [one of the types where we rethrow])
{
throw new HttpResponseException(new HttpResponseMessage(StatusCode.InternalServerError)
{
Content = new StringContent("Friendly message goes here."),
ReasonPhrase = "Critical Exception"
});
}
}
}
For some types of exceptions I want to just continue processing from the controller. But how do I do that?
By writing try..catch where you want this behaviour to occur. See Resuming execution of code after exception is thrown and caught.
To clarify, I assume you have something like this:
void ProcessEntries(entries)
{
foreach (var entry in entries)
{
ProcessEntry(entry);
}
}
void ProcessEntry(entry)
{
if (foo)
{
throw new EntryProcessingException();
}
}
And when EntryProcessingException is thrown, you actually don't care and want to continue execution.
If this assumption is correct: you can't do that with a global exception filter, as once an exception is caught, there's no returning execution to where it was thrown. There is no On Error Resume Next in C#, especially not when the exceptions are handled using filters as #Marjan explained.
So, remove EntryProcessingException from your filter, and catch that specific exception by changing the loop body:
void ProcessEntries(entries)
{
foreach (var entry in entries)
{
try
{
ProcessEntry(entry);
}
catch (EntryProcessingException ex)
{
// Log the exception
}
}
}
And your loop will happily spin to its end, but throw on all other exceptions where it will be handled by your filter.

Check if exception is handled on higher level

Is there a way to check if exception is handled on a higher application level to skip logging and re-throw? Like this, for example:
try
{
// Execute some code
}
catch (Exception e)
{
if(!ExceptionIsHandled())
LogError(e);
throw e;
}
Nothing that I'm aware of. If you're committed to this design (see note at end), you could write a wrapper for an Exception that's some sort of HandledException and just make its InnerException be the one that was thrown. Then you could make your code look like:
try
{
// Execute some code
}
catch (HandledException e)
{
LogError(e.InnerException);
// Do something else
}
catch (Exception e)
{
throw ;
}
Here comes the stereotypical Stackoverflow "you're doin it wrong" part of the answer...
However, if you've truly "handled" the exception, it doesn't make a lot of sense to be re-throwing it. Maybe your method should just return a failure result, possibly including the Exception as a detail item for what went wrong.
This is old, but I do have some input here. There is a design pattern I've used before that does this very well, but does add a little bit of overhead to everything.
Basically, all methods would return a response object (e.g., Response<T>). Any exceptions that occur should be wrapped in the response object and returned instead of thrown.
public class Response<T>
{
public T Payload { get; set; }
public bool IsSuccessful { get; set; } = false;
public string Message { get; set; }
public Exception Error { get; set; }
}
public class MyService
{
public Response<IEnumerable<Customer>> GetCustomers()
{
var response = new Response<IEnumerable<Customer>>();
try
{
var customers = new List<Customer>()
{
new Customer() { CompanyName = "ABC Co." },
new Customer() { CompanyName = "ACME" }
};
response.Payload = customers;
response.IsSuccessful = true;
}
catch (Exception e)
{
response.IsSuccessful = false;
response.Error = e;
// A friendly message, safe to show to users.
response.Message = "An error occurred while attempting to retrieve customers.";
}
return response;
}
}
You can bubble up the exception without rethrowing it, and handle appropriately. You can then add exception catches for more custom user-friendly messages.
I also use a custom base Exception type for any errors that are safe to show the client. This way I can add a generic catch at the controller level to propagate those prepared error messages.
Well no, hasn't got there yet has it. Exceptions bubble up through handlers.
Usual way to go about this.
Is define your own exceptions, then only catch the ones you are going to handle where you are.
If you could be certain that code was wrapped within a specially-designed try-catch block which was written in a language that supports exception filters, it would be possible to determine before or during stack unwinding whether the exception was likely to be caught by that outer block or by an inner one. The usefulness of this is rather limited, however, especially given the extremely common anti-pattern of code catching and rethrowing exceptions that it knows it's not going to resolve, simply for the purpose of finding out that they occurred.
If your goal is simply to avoid redundant logging, I'd suggest that you should use a logging facility which can deal efficiently with redundancy. While some people might argue that it's better to have exceptions logged just once at the outer layers, there are advantages to having more logging opportunities. If an exception occurs within the inner layer and a middle layer swallows it, logging code within the outer layer will never find out about it. By contrast, if the inner layer starts out by capturing the exception and arranging for it to get logged, then even if the middle layer swallows the exception the fact that it occurred could still get recorded.

How to handle exceptions?

It's a question about best .net practise. I always caught and stored information about exceptions in all of my web and window forms applications as follows:
Surrounded each method with try catch(Exception exception)
For any layer except front layer, threw exception to the layer above
In the front layer, logged the exception to a log file (usually using log4config.dll) and presented a user friendly message to the user.
Is this the best way to handle exceptions? Or should I do something different in my next projects?
I wouldn't add 1 & 2 unless I had some specific reason; for example to alter (wrap) the message; there is no need since exceptions will raise upwards anyway. And done incorrectly you can accidentally remove the all-important stack-trace (throw; vs throw ex; - the first being preferred).
The following code is problematic because it overwrites the original stack trace for e, which makes problems harder to diagnose:
public void Foo() {
try {
Bar();
} catch(Exception e) {
throw e; // re-throw; overwrites original stacktrace in 'e'
}
}
The following code does not have the above stacktrace overwrite problem, but is still unnecessarily verbose:
public void Foo() {
try {
Bar();
} catch(Exception e) {
throw; // re-throw; preserves original stacktrace in 'e'
}
}
Both would be better written as below. This is because, if the only thing you are doing in your catch block is re-throwing the exception, there is no need to write the catch block at all:
public void Foo() {
Bar();
}
The best answer you can get at Best Practices for Handling Exceptions
Here is how NOT to handle exceptions.
public void method1(){
try{
....
// all the code goes here
// declare any helper methods throw throwable
// eg: private boolean check1() throws Throwable{ ...}
....
}catch(Throwable t){
System.out.println("oops...error...good luck debugging. ");
}
}

Help with Exception handling

i have this application structure:
1. Presentation Layer which calls
2. Business Logic Layer which in turn calls
3. Data Access Layer to do the dealing with the database.
Now i have a Contacts page from where i can add a new contact to the database.
So to add a New Contact i fill in all the required details and then call a Add Method (residing in the BLL) from the page, which in turn call a Add Method residing in the DAL.
this method in the DAL returns the Current Identity of the record which is then return back to the BLL method and finally delivered on the page.
this is fine. but what if a get an exception how do i handle it properly because the method in DAL has a return type of int and i dont want to throw another error!! coz other wise i will have to write try catch in almost all the methods.
//something like this
public int AddMethod(ContactClass contactObj)
{
int result = 0;
try
{
result = ExecuteSomeSP("SPName", SP_Parameters);
}
catch(SQLException se)
{
throw new SQLException
}
return result;
}
rather i want to show the user a user-friendly message which they can easily understand and in the mean while i will send a mail to myself documenting the Error that just occurred.
Also kindly tell me how can i implement my custom exception classes.
Please tell me how do i do this!!
thank you.
You shouldn't need a try/catch in every method. But you usually need a try/catch in every Layer (for a certain action).
And that is proper, each layer has to deal with its own broken contracts, cleanup etc.
The conversion from Exception to "friendly message" is something for the GUI, not a lower layer.
And when you catch and re-throw an exception, make sure you don't loose information, forward it in the InnerException property:
try
{
// DAL
}
catch (DALException de)
{
// Log, ....
throw new BLLException(message, de);
}
Do not try catch in every method or layer, only were it is reasonable. A try catch should never act like a conditional. The presentation layer should never have logic in it.
Since your using a DAL interface I would create a custom DalException and throw that over the SQLException
public int addMethod(ContactClass contactObj) throws DalException {
try {
return ExecuteSomeSP("SPName", SP_Parameters);
}
catch(SQLException e) {
throw new DalException(e);
}
}
In your business logic layer catch the exception and produce the popup using the presentation layer
public void addMethod(ContactClass contactObj) {
try {
dal.addMethod(contactObj);
}
catch(DalException e) {
// notify user
view.alert(e.getMessage());
}
}

Categories

Resources