Wednesday, July 27, 2011

Tips on Exception Handling

1. Never do a 'catch exception and do nothing'. If you hide an exception, you will never know if the exception happened or not. Lot of developers uses this handy method to ignore non-significant errors. You should always try to avoid exceptions by checking all the error conditions programmatically. In any case, catching an exception and doing nothing is not allowed. In the worst case, you should log the exception and proceed.

2. In case of exceptions, give a friendly message to the user, but log the actual error with all possible details about the error, including the time it occurred, method and class name etc.

3. Always catch only the specific exception, not generic exception.
Good:
Private Sub ReadFromFile (fileName As String)
Try
// read from file.
catch (FileIOException ex)
// log error.
// re-throw exception depending on your case.
Throw
End Try
End Sub

Not Good:
Private Function ReadFromFile (fileName As String) As String
Try
// read from file.
Catch (Exception ex)
// Catching general exception is bad... we will never know whether
// it was a file error or some other error.
// Here you are hiding an exception.
// In this case no one will ever know that an exception happened.
Return String.Empty
End Try
End Function

4. No need to catch the general exception in all your methods. Leave it open and let the application crash. This will help you find most of the errors during development cycle. You can have an application level (thread level) error handler where you can handle all general exceptions. In case of an 'unexpected general error', this error handler should catch the exception and should log the error in addition to giving a friendly message to the user before closing the application, or allowing the user to 'ignore and proceed'.

5. When you re throw an exception, use the throw statement without specifying the original exception. This way, the original call stack is preserved.
Good:
Catch
// do whatever you want to handle the exception
throw
Not Good:
catch (Exception ex)
// do whatever you want to handle the exception
throw ex

6. Do not write try-catch in all your methods. Use it only if there is a possibility that a specific exception may occur and it cannot be prevented by any other means. For example, if you want to insert a record if it does not already exists in database, you should try to select record using the key. Some developers try to insert a record without checking if it already exists. If an exception occurs, they will assume that the record already exists. This is strictly not allowed. You should always explicitly check for errors rather than waiting for exceptions to occur. On the other hand, you should always use exception handlers while you communicate with external systems like network, hardware devices etc. Such systems are subject to failure anytime and error checking is not usually reliable. In those cases, you should use exception handlers and try to recover from error.

7.Do not write very large try-catch blocks. If required, write separate try-catch for each task you perform and enclose only the specific piece of code inside the try-catch. This will help you find which piece of code generated the exception and you can give specific error message to the user.

8. Write your own custom exception classes if required in your application. Do not derive your custom exceptions from the ApplicationException class. Instead, inherit from base class System.Exception.

Good bye Exceptional Handling

Some Quick help

1) Make a field readonly:
txtName.Attributes.Add("readonly", "readonly")

2) Keyboard enter button is pressed in the textbox and fire an event:
This is done to ensure that when the keyboard enter button is pressed in the textbox we fire the "btnButton" click event
txtName.Attributes.Add("onkeypress", "return WebForm_FireDefaultButton(event, '" + btnButton.ClientID + "')")

3) To set the focus on a control like Textbox when the page loads.
ScriptManager.RegisterStartupScript(Page, Page.GetType(), "focus", "setTimeout(""try{ document.getElementById('" & txtName.ClientID & "').focus(); } catch(err){}"", 1200);", True)

4) To directly access the key and value of the resource file.
lblName.Text = GetGlobalResourceObject("ABC", "Name") ////Where Main refers for a file “ABC.resx”


5) To disable controls of a form/page

// Below is the method definition
Public Sub DisableControl(ByVal ctrl As Control)
For Each subctrl As Control In ctrl.Controls
DisableControl(subctrl)
Next

If TypeOf ctrl Is TextBox Then
CType(ctrl, TextBox).Enabled = True
CType(ctrl, TextBox).ReadOnly = True
ElseIf TypeOf ctrl Is RadioButtonList Then
CType(ctrl, RadioButtonList).Enabled = False
ElseIf TypeOf ctrl Is CheckBox Then
CType(ctrl, CheckBox).Enabled = False
ElseIf TypeOf ctrl Is RadioButton Then
CType(ctrl, RadioButton).Enabled = False
End If
End Sub