Handling Errors in the Northwind Application


Now that you have your error handling classes and can save errors in either the database or the Windows Event Log, it is time to implement the functionality in your application. In a typical application you might have to put an error handling routine, like you are going to create, in every form of your application. Thanks to .NET and visual inheritance, you have a convenient place to put your code—our base classes. For the purposes of this application, you will add your error handling routine to the frmListBase form and the frmEditBase form. You will also add it to the main form, frmMain. Add the method in Listing 4-10 to the frmListBase form.

Listing 4-10: The LogException Method

start example
 #Region " Error Logger"      Protected Sub LogException(ByVal exc As Exception)           Dim objLogErr As New NorthwindUC.ErrorLogging.LogError()           Try                objLogErr.LogException(exc)                MessageBox.Show("The NorthwindTrader application generated " _                & "the following error:" & ControlChars.CrLf & exc.Message, _                "NorthwindTrader Error", MessageBoxButtons.OK, _                MessageBoxIcon.Error)           Catch excNew As Exception                Dim objErrorEvent As NorthwindUC.ErrorLogging.LogErrorEvent                objErrorEvent = objErrorEvent.getInstance                objErrorEvent.LogErr(exc)                objErrorEvent.LogErr(excNew)                objErrorEvent = Nothing                MessageBox.Show("The NorthwindTrader application generated " _                & "the following critical error: " & excNew.Message, _                "NorthwindTrader Error", MessageBoxButtons.OK, _                MessageBoxIcon.Error)           Finally                objLogErr = Nothing           End Try      End Sub #End Region 
end example

The method is declared as protected so that you can access it from the forms that inherit from your base form. This routine tries to log the exception that was generated to the database. If an error occurs during the logging of the exception to the database, you can usually be guaranteed that it is a network connection or database connection issue (or some other issue that involves calling remote components). However, you do not want to lose the original error, so you log both errors to the event log and inform the user that a more serious error occurred. It is simple and elegant. Any Windows application can use this code (at least the code that logs to the event log).

Note

In an actual production environment, it would make more sense to split the database logging mechanism and the event log logging mechanism into two classes in different files, but for these purposes it will work fine. This is because it makes the code more reusable; not every application will have a database with this table in it.

Add the code in Listing 4-10 to the frmEditBase and the frmMain form as well.

Next you are going to add a little interface so that the users can send the errors that are in the event log to technical support.

Caution

It is easy to automatically send the errors via e-mail to technical support whenever an error occurs; however, with all of the issues surrounding privacy and information being sent with or without the user's permission, this could be problematic. Even though this is an enterprise application, you still do not want to violate that privacy. This is a personal choice, but if in doubt, have your company define these policies explicitly so you do not violate any of their privacy guidelines.

At this point, you can go back into the user interface and add error handling code in your application. I recommend that every routine (except the constructors) have a Try..Catch block if that routine is in the user interface (this includes the base forms). To add the Try..Catch blocks, enter the following code in every routine:

 Try    'Your routines code Catch exc As Exception    LogException(exc) End Try 

Note

If, as in the MenuItem1_Click method in frmMain, you turn the cursor into an hourglass, it makes sense to include a Finally block and in the Finally block turn the cursor back into the default cursor. This saves you the embarrassment of having the cursor looking like an hour-glass after an error occurred when there is no processing occurring.

Fortunately there is not a lot to retrofit right now so this process is fairly painless. Make sure to avoid adding error handling code in the txtRegionDescription_Validated event in the frmRegionEdit form. Until the next chapter, you are going to leave any error that occurs here unhandled because you will be performing some special error handling for the validated events.

Note

Some developers claim you do not have to include error handling in every routine. They may want to put an error handler only in code that is directly executed by the user. Further, if a method was called by another method, only the original method needs the error handler. However, how do you know all of the methods called by all of the other methods in the application? And what happens if the error occurred in an event raised by a class to which you did not have access? So, why take the chance? If there is an error handler in every routine, there is almost no chance of the application crashing without warning and without reporting the error that caused it to terminate.

Creating the ErrorReporting Form

Now that you have a way to retrieve the application errors from the Windows Event Log, you need to give the users a way to send you those errors when they occur. To start with, add a new form to the NorthwindTraders project called frmReportErrors. When you are done adding controls to the form, the form should look like the form in Figure 4-5.

click to expand
Figure 4-5: Report Error Wizard form

Add the controls in Table 4-2 to the form.

Table 4-2: Report Error Wizard Controls

Control

Control Name

Groupbox

Label

Label

Label

Listbox

lstErrors

Button

btnSend

Button

btnCancel

Set the properties for these controls according to Table 4-3.

Table 4-3: The Report Error Wizard Control Properties

Control Name

Property

Value

grpHeader

Backcolor

White

lblWizardLabel

Text

Report Error Wizard

lblWizardLabel

Font

Bold

lblInfo

Text

Send the error log to technical support for diagnosis.

lblOperation

Text

The following errors will be sent to the technical support personnel:

btnSend

Text

&Send

btnCancel

Text

&Cancel

frmReportErrors

FormBorderStyle

FixedSingle

frmReportErrors

MaximizeBox

False

frmReportErrors

MinimizeBox

False

frmReportErrors

Text

Northwind Wizard

Import the ErrorLogging namespace using the following line:

 Imports NorthwindTraders.NorthwindUC.ErrorLogging 

Next, add the following module-level variables:

 Private mobjLogErr As LogErrorEvent Private mobjErrArray() As structLoggedError 

Before adding any other code into this form, let's copy and paste the LogException method from one of the base classes. It would probably be embarrassing for your error reporting form to cause the application to fail because of an unhandled error!

In the form load event, you will retrieve your errors and place them in the listbox. To do this, add the code in Listing 4-11 to frmReportErrors.

Listing 4-11: The frmReportErrors_Load Method

start example
 Private Sub frmReportErrors_Load(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles MyBase.Load      Dim i As Integer      Try          mobjLogErr = mobjLogErr.getInstance          mobjErrArray = mobjLogErr.RetrieveErrors          For i = 0 To mobjErrArray.Length - 1               lstErrors.Items.Add(mobjErrArray(i).Message)          Next          If lstErrors.Items.Count = 0 Then               btnSend.Enabled = False          End If      Catch exc As Exception          LogException(exc)      End Try End Sub 
end example

This code simply retrieves the array of errors and loops through them to add them to the listbox. If there are no items in the array, it means there were no errors, so just disable the Send button.

Next, add the code in Listing 4-12 to implement the btnSend_Click method so that technical support can actually get the errors.

Listing 4-12: The btnSend_Click Method

start example
 Private Sub btnSend_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles btnSend.Click      Try           Cursor = Cursors.WaitCursor           mobjLogErr.SendErrors(mobjErrArray)      Catch exc As Exception           LogException(exc)      Finally           Cursor = Cursors.Default           Me.Close()      End Try End Sub 
end example

This code simply calls the SendErrors method of the LogErrorEvent. Finally, to finish the form, add the following two methods:

 Private Sub btnCancel_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles btnCancel.Click      Try           Close()      Catch exc As Exception           LogException(exc)      End Try End Sub Private Sub frmReportErrors_Closed(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles MyBase.Closed      Try           mobjLogErr = Nothing           mobjErrArray = Nothing      Catch exc As Exception           LogException(exc)      End Try End Sub 

The Cancel button click event simply closes the form, and the Closed event cleans up any of your variables. That is it for the errors form.

Note

This form only displays a list of error messages, with no other information. Extending this form to be able to show the actual information about the exception that is being sent to technical support should be easy if you desire to let them see this information. Remember, the more information an attacker has about vulnerabilities in your system, the easier it will be to take advantage of them. Of course, if an attacker is actually on the user's system, they probably already have access to the event log!

To implement the form, let's hard-code a menu item (you will create a dynamic menu structure in Chapter 5, "Building Business Objects," when you clean up the user interface). Go back into frmMain and add a new menu item called Report Errors. Double-click the new Report Errors menu item to create the MenuItem.Click event in the code module and alter the method so that it looks like the method in Listing 4-13.

Listing 4-13: Method to Display the Application Errors

start example
 Private Sub MenuItem2_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MenuItem2.Click      Dim objReportErrors As frmReportErrors      Try           objReportErrors = New frmReportErrors()           objReportErrors.ShowDialog()      Catch exc As Exception           LogException(exc)      Finally           objReportErrors = Nothing      End Try End Sub 
end example

Note

Your menu control name may not be the same, but it does not matter. As you will notice, I am not following any particular naming convention at this point because you are going to fix most of this work in Chapter 5, "Building Business Objects."

Because you are showing this form using the ShowDialog() method, you do not need to declare this form as a module-level variable.

Testing the NorthwindTraders Exception Storing

Now that you have all of your error handling capabilities in place, it is time to see what happens when you throw an exception that gets stored to the database. But before you can do anything, you need to rebuild the data-centric and shared assemblies and redeploy them to the IIS server.

For the purposes of this test only, modify the LoadList method of the frmRegionList form by adding the following line immediately after the Try statement:

 Throw New Exception("My Error Test") 

After you have redeployed the remote assemblies, run the application. When you try to open up the Region List form, you will receive the error shown in Figure 4-6.

click to expand
Figure 4-6: Error test

Assuming that there were no other errors, this will be the only error that is displayed and the form will then be displayed with an empty list. So now that you have an error, let's look at what it stored in the database. Figure 4-7 shows the exception as stored in the application_errors table.

click to expand
Figure 4-7: The exception as stored in application_errors table

Remember to remove the exception you added for this test!




Building Client/Server Applications with VB. NET(c) An Example-Driven Approach
Building Client/Server Applications Under VB .NET: An Example-Driven Approach
ISBN: 1590590708
EAN: 2147483647
Year: 2005
Pages: 148
Authors: Jeff Levinson

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net