views:

1381

answers:

4

I am using asp.net and I am always struggling for a neat way to handle errors and if there are any, to pass the errormessage to the user. For example, I have an User class, UserManager class and a Database class. Imagina I want to show all the users, show I call the method GetAllUsers from UserManagerwhich returns a list of User objects. This method creates a Database object and calls the method ExecuteQuery(string query).

EDIT: And now my issue, imagine something goes wrong in the ExecuteQuery() method (failed to open database). I want to notify the user someting went wrong when opening the database connection. How should I do this and handle this a neat way?

EDIT 2:

Would you do it something like this? Or otherwise?

public class Database()
{
   private string _Error;

   // property error (only get)

   private void Open()
   {
     try
     {
       // Open DB
       // Fails because of error          
     }
     catch(Exception ex)
     {
       _Error = ex.Message;
     }
   }

   public DataSet ExecuteQuery(string query)
   {
      try
      {
        Open();

        // Execute query

        // return dataset
       }
       catch(Exception ex)
       {
          _Error = ex.Message;
          return null;
       }
   }
}

public class UserManager ()
{
   private string _Error;

   // Get property for Error       

   public List<User> GetAllUsers ()
   {
      Database db = new Database()

      Dataset DS = db.ExecuteQuery("my query goes here");

      (if DS == null)
      {
        _Error = db.Error;
        return null;
      }

   }
}

In user interface on a click event:

protected void onClick_event(args)
{

  Usermanager userman = new UserManager();
  List<User> users = userman.GetAllUsers();

  if(users == null)
  {
    // make a error panel visible
    pnlError.Visible = true;
    lblError.Text = userman.Error
  }
}

Is this a good approach?

A: 

Either by wrapping in a using statement or having a Try/Finally to ensure the db connection is disposed, as that particular type of exception could be trouble for you.

This free book by Karl Seguin has a chapter on Exception Handling which should make things quite clear for you.

Bubble up the exception to the UI where it can be handled according to your style there. For unhandled exceptions, as mentioned below, ELMAH is very useful.

dove
And how do you pass the error to the user?
Martijn
bubble the exception to the outermost point and then it's the responsiblity of your UI to decide what to show the user depending on the type of exception. Unless you are adding more information to the exception thrown this is the first place you should be capturing that exception. But honestly, take a read of the chapter in that book, it's hard to answer this in isolation, too many things to consider.
dove
I've edited my startpost. Did you mean something like that?
Martijn
in short, no. i'd not have any of those try catches in your data layer. bring them into your into your onclick event. and since you're simply displaying the excecption message, something more generic could be applied. Again, there are many good examples here and elsewhere of what to do. One important thing to ask yourself is why are you capturing exceptions at all in database layer since you're adding no information to the exception, doing nothing to log it or trying anything to rectify it. in this case just let the exception bubble until you want to do something specific to it
dove
How can I bubble up an exception?
Martijn
+2  A: 

It all depends on the type of issue you have with the query execution. Those issues could be anything from no records found to a connection failing. If the problem is something you can test for, which the absence of records would be, you can test for that and present your user with a message stating that no records were found. Even if a connection fails, you should be able to test for that and tell your user.

For issues you cannot test for, depending on the type of application you are writing, you may want to let the application fail and use some framework like ELMAH log and report the error.

try these links which come from my other post on this topic for more information

Code Analysis Team Blog

Martin Fowler - Fail Fast

MSDN on Exception Handling

Checked vs Unchecked Exceptions

Also, this excellent article was posted recently

jlembke
+1  A: 

If you don't want to use the usual try/catch and display error divs in the catch then there is a Page.Error event which you could use to catch handle errors with the context of your page. Within that you would call Server.GetLastError() to get the last exception thrown and then inform the user something went wrong by directing them to an error page, or by showing/hiding error elements on your page.

blowdart
A: 

I think you missed the right way to do exception handling. Storing the text that is language/locale dependent in your database is not really a good idea. The error might also not be meaningful in the context in which it it executed, the caller of the method knows what is intended but the code that retrieves a value from a database does not know about the "higher goals" of your code! The description of the database error might also not interest users at all, for them the system just cannot get the list of users, that's all. For developers it is important to know what exactly got wrong. Putting this visible to users might also show them data you do not want them to see like table names, passwords, database user names, depending on what the exception contains (which you cannot control)

So now how to handle it:

  1. Catch the exception where you handle it, that is in the onClick_Event
  2. Log out to a file detailed info, to the page only what users should see
  3. In your code (Database for e.g.) follow this principle:

    • Do not modify the object's state until it's clear that nothing can go wrong to keep your object in a consistent state. That means do not start to modify members, then the exception comes and you would have to reset them all to their previous state in a finally block.
    • Start your operations and throw an exception on problems (do not catch it here, pointless, you would just store a message or the whole exception for later retrieval!)
    • On success, copy the temporary variables to the members of the object

This way you would always have an object in a consistent state and clean code.

jdehaan