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?
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:
- Catch the exception where you handle it, that is in the
onClick_Event
- Log out to a file detailed info, to the page only what users should see
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.
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
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.
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.