2

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; } } 
1
  • 2
    if you're only going to re-throw the exception there's no point in catching it in the first place. If you want to catch the exception, do something (maybe log it, for example) and then re-throw it that can make sense. If that's what you're doing you should indicate that in your code somehow. Your question is also not clear. What are you trying to do that you can't? If you just want some advice you were given to be explained, ask the person who gave it to you; they know what they meant better than we do. Commented Dec 27, 2012 at 19:23

2 Answers 2

3

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); } } 
Sign up to request clarification or add additional context in comments.

4 Comments

How does the UserInterface layer catch the UserNotFoundException thrown by this class that you posted above? Is it something like what I posted at the end of my question with MethodA(), MethodB(), and MethodC()?
@ArmorCode Yes, similar although the details will depend on exactly how you structure your program. I have updated the answer with an example of how to catch it in the Program layer as is typical in MVC apps.
You put ASP.Net, but i'm working with C#.Net. But why does it look the same as C#?
@ArmorCode Because ASP.Net is not a language, but a framework. See this answer.
3

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.