Apply Your Knowledge
Exercises
3.1 Handling Exceptions
Recall Step By Step 2.5 ("Common Dialog Boxes") from Chapter 2. This Step By Step demonstrated the use of common dialog boxes by creating a simple rich text editor. This editor allows you to open and save a rich text file. You can edit the text or change its fonts and colors. The program worked fine in all cases unless you tried to open or save a file that was already open; in this case the program throws a System.IO.IOException.
The objective of this exercise is to make a more robust version of this program that generates a warning about the open file rather than abruptly terminating the program.
Estimated Time: 15 minutes.
Create a new Visual Basic .NET Windows application.
Add a Windows Form to the project. Name this form Exercise3_1.
-
Place five Button controls to the form. Name them btnOpen, btnSave, btnClose, btnColor, and btnFont and change their Text property to &Open..., &Save..., Clos&e..., &Color..., and &Font..., respectively. Place a RichTextBox control and name it rtbText. Arrange all controls as shown in Figure 3.12.
Figure 3.12
A simple rich text editor.
-
Drag and drop the following components from the Toolbox to the form: OpenFileDialog, SaveFileDialog, ColorDialog, and FontDialog.
-
Switch to the Code view and add the following line of code at the top of the form's module:
Imports System.IO
-
Double-click on the Open button to attach an event handler to its Click event. Add the following code to the event handler:
Private Sub btnOpen_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnOpen.Click ' Allow the user to select ' only *.rtf files OpenFileDialog1.Filter = _ "Rich Text Files (*.rtf)|*.rtf" If OpenFileDialog1.ShowDialog() = _ DialogResult.OK Then Try ' Load the file contents ' in the RichTextBox rtbText.LoadFile( _ OpenFileDialog1.FileName, _ RichTextBoxStreamType.RichText) Catch ioe As System.IO.IOException MessageBox.Show(ioe.Message, _ "Error opening file") End Try End If End Sub
-
Add the following code to handle the Click event of the Save button:
Private Sub btnSave_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnSave.Click ' Default choice to save file ' is *.rtf but user can select ' All Files to save with other extension SaveFileDialog1.Filter = _ "Rich Text Files (*.rtf)|*.rtf|" & _ "All Files (*.*)|*.*" If SaveFileDialog1.ShowDialog() = _ DialogResult.OK Then Try ' Save the RichText ' content to a file rtbText.SaveFile( _ SaveFileDialog1.FileName, _ RichTextBoxStreamType.RichText) Catch ioe As System.IO.IOException MessageBox.Show(ioe.Message,_ "Error saving file") End Try End If End Sub
-
Add the following code to handle the Click event of the Close button:
Private Sub btnClose_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnClose.Click ' Close the form Me.Close() End Sub
-
Add the following code to handle the Click event of the Color button:
Private Sub btnColor_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnColor.Click If ColorDialog1.ShowDialog() = _ DialogResult.OK Then ' Change the color of selected text ' If no text selected, ' change the active color rtbText.SelectionColor = _ ColorDialog1.Color End If End Sub
-
Add the following code to handle the Click event of the Font button:
Private Sub btnFont_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnFont.Click If FontDialog1.ShowDialog() = _ DialogResult.OK Then ' Change the font of selected text ' If no text selected, ' change the active font rtbText.SelectionFont = _ FontDialog1.Font End If End Sub
-
Set this form as the startup object for the project.
-
Run the project. Click on the Open button and try to open an already opened file. You'll see an error message warning about the file being already open, as shown in Figure 3.13.
Figure 3.13
Error message warning user about an already open file.
3.2 Validating User Input
One of the techniques for input validation is to force the user to fix an erroneous field before allowing her to move to another field. To achieve this, you can set the Cancel property of the CancelEventArgs argument of the Validating event of a field to True.
In this exercise, you'll create a login form (see Figure 3.14) that accepts a username and a password. It forces the user to enter the username. The user should be also able to close the application by clicking the Cancel button irrespective of the validation status of the fields.
Estimated Time: 15 minutes.
Add a new form to your Visual Basic .NET application.
-
Place three Label controls, two TextBox controls named txtUserName and txtPassword, two Button controls named btnLogin and btnCancel and an ErrorProvider component named ErrorProvider1 on the form. The ErrorProvider component will be placed in the component tray. Arrange the controls in the form as shown in Figure 3.14.
Figure 3.14 The login form.
-
Change the ControlBox property of the form to False, the CharacterCasing property of the txtPassword control to Lower and the CausesValidation property of btnCancel to False.
-
Double-click the form to add an event handler for the Load event:
Private Sub Exercise3_2_Load( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles MyBase.Load ErrorProvider1.SetIconAlignment( _ txtUserName, _ ErrorIconAlignment.MiddleLeft) ErrorProvider1.SetIconAlignment( _ txtPassword, _ ErrorIconAlignment.MiddleLeft) End Sub
-
Declare the following variable outside a method block in the class:
' closingFlag is used to check ' if user has clicked on the Close button Private closingFlag As Boolean = False
-
Add the following code to the Click event handler of the Cancel button:
Private Sub btnCancel_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnCancel.Click closingFlag = True Me.Close() End Sub
-
Add the following code to the Click event handler of the Login button:
Private Sub btnLogin_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnLogin.Click Dim strMessage As String = _ String.Format( _ "The following information:" & _ vbCrLf & vbCrLf & "UserName: {0}" & _ vbCrLf & vbCrLf & _ "Password: {1}" & vbCrLf & vbCrLf & _ " can be now passed to " & _ " the middle-tier for validation", _ txtUserName.Text, txtPassword.Text) MessageBox.Show(strMessage, _ "User Input Validation Succeeded") End Sub
-
Add code to handle the Validating events of the txtUserName and txtPassword controls:
Private Sub txtUserName_Validating( _ ByVal sender As Object, _ ByVal e As System.ComponentModel. _ CancelEventArgs) _ Handles txtUserName.Validating If Not closingFlag Then If txtUserName.Text.Trim(). _ Length = 0 Then ErrorProvider1.SetError( _ txtUserName, _ "Please enter a value " & _ "for this field") e.Cancel = True ElseIf txtUserName.Text.Trim(). _ IndexOf(" ") >= 0 Then ErrorProvider1.SetError( _ txtUserName, _ "You can NOT have spaces " & _ "in this field") txtUserName.Select(0, _ txtUserName.Text.Length) e.Cancel = True End If End If End Sub Private Sub txtPassword_Validating( _ ByVal sender As Object, _ ByVal e As System.ComponentModel. _ CancelEventArgs) _ Handles txtPassword.Validating If Not closingFlag Then If txtPassword.Text.Trim(). _ Length = 0 Then ErrorProvider1.SetError( _ txtPassword, _ "Please enter a value " & _ "for this field") e.Cancel = True ElseIf txtPassword.Text.Trim(). _ IndexOf(" ") >= 0 Then ErrorProvider1.SetError( _ txtPassword, _ "You can NOT have spaces " & _ "in this field") txtPassword.Select(0, _ txtPassword.Text.Length) e.Cancel = True End If End If End Sub
-
Add code to handle the Validated event of the txtUserName and txtPassword controls:
Private Sub txtUserName_Validated( _ ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles txtUserName.Validated ErrorProvider1.SetError(txtUserName, "") End Sub Private Sub txtPassword_Validated( _ ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles txtPassword.Validated ErrorProvider1.SetError(txtPassword, "") End Sub
-
Set this form as the startup object for the project.
-
Run the project. If you click directly on the Login button, you will be forced to enter a username. However, you can click the Cancel button to close the application even without entering a valid username.
Review Questions
What is the default behavior of the .NET framework when an exception is raised?
Which is the base class of all the exceptions that provides the basic functionality for exception handling? What are the two main types of exception classes and their purposes?
Explain the Message and InnerException properties of the Exception class.
What is the purpose of Try and Catch blocks?
How many Catch blocks can be associated with a single Try block? How should they be arranged?
What is the importance of the Finally block?
Can you associate custom error messages with the exception types defined by the CLR? If yes, how can you do this?
What are some of the points you should consider before creating custom exceptions?
What is the importance of the Validating event?
Explain the purpose of the ErrorProvider component.
Exam Questions
-
You are creating a data import utility for a personal information system that you designed recently. When the record in the source data file is not in the required format, your application needs to throw a custom exception. You will create an exception class with the name InvalidRecordStructureException. Which of the following classes would you choose as the base class for your custom exception class?
-
ApplicationException
-
Exception
-
SystemException
-
InvalidFilterCriteriaException
-
-
You are assisting your colleague in solving the compiler error that his code is throwing. The problematic portion of his code is
Try Dim success As Boolean = GenerateNewtonSeries(500, 0) ' more code here Catch dbze As DivideByZeroException ' exception handling code Catch nfne As NotFiniteNumberException ' exception handling code Catch ae As ArithmeticException ' exception handling code Catch e As OverflowException ' exception handling code End Try
To remove the compilation error, which of the following ways would you modify the code?
-
Try Dim success As Boolean = GenerateNewtonSeries(500, 0) ' more code here Catch dbze As DivideByZeroException ' exception handling code Catch ae As ArithmeticException ' exception handling code Catch e As OverflowException ' exception handling code End Try
-
Try Dim success As Boolean = GenerateNewtonSeries(500, 0) ' more code here Catch dbze As DivideByZeroException ' exception handling code Catch ae As Exception ' exception handling code Catch e As OverflowException ' exception handling code End Try
-
Try Dim success As Boolean = GenerateNewtonSeries(500, 0) ' more code here Catch dbze As DivideByZeroException ' exception handling code Catch nfne As NotFiniteNumberException ' exception handling code Catch e As OverflowException ' exception handling code Catch ae As ArithmeticException ' exception handling code End Try
-
Try Dim success As Boolean = GenerateNewtonSeries(500, 0) ' more code here Catch dbze As DivideByZeroException ' exception handling code Catch nfne As NotFiniteNumberException ' exception handling code Catch ae As Exception ' exception handling code Catch e As OverflowException ' exception handling code End Try
-
- You need to debug a program containing some exception handling code. To understand the program better, you created a stripped down version of it and included some MessageBox statements that give clues about the flow of its execution. The program has the following code:
Try Dim num As Integer = 100 dim den as Integer = 0) MessageBox.Show("Message1") Try Dim res As Integer = num / den MessageBox.Show("Message2") Catch ae As ArithmeticException MessageBox.Show("Message3") End Try Catch dbze As DivideByZeroException MessageBox.Show("Message4") Finally MessageBox.Show("Message5") End Try
Which of these is the order of messages that you receive?
-
Message1 Message2 Message3 Message4 Message5
-
Message1 Message3 Message5
-
Message1 Message4 Message5
-
Message1 Message2 Message4 Message5
-
-
What is the output displayed by the MessageBox in the following code segment?
Try Try Throw _ New ArgumentOutOfRangeException() Catch ae As ArgumentException Throw New ArgumentException( _ "Out of Range", ae) End Try Catch ex As Exception MessageBox.Show( _ ex.InnerException.GetType().ToString()) End Try
-
System.Exception
-
System.ApplicationException
-
System.ArgumentException
-
System.ArgumentOutOfRangeException
-
- The Validating event of a text box in your Windows application contains the following code. The MyValidatingCode method validates the contents of the text box. If the contents are invalid, this method throws an exception and retains the focus in the text box. The line numbers in the code sample are for reference purpose only.
01 Private Sub TextBox1_Validating( _ 02 ByVal sender As System.Object, _ 03 ByVal e As System.EventArgs) _ 04 Handles TextBox1.Validating 05 Try 06 MyValidatingCode() 07 Catch ex As Exception 08 09 TextBox1.Select(0, _textBox1.Text.Length) 10 ErrorProvider1.SetError(textBox1, _ex.Message) 11 End Try 12 End Sub
Which of the following line of code should be in line 8?
-
e.Cancel = True
-
e.Cancel = False
-
TextBox1.CausesValidation = True
-
TextBox1.CausesValidation = False
-
-
You have designed a Windows Form that works as a login screen. The form has two TextBox controls named txtUserName and txtpassword. You want to ensure that the user can only enter lowercase characters in the controls. Which of the following methods should you use?
-
Set the form's KeyPreview property to True and program the KeyPress event of the form to convert uppercase letters to lowercase letters.
-
Create a single event handler attached to the KeyPress event of both txtUserName and txtpassword. Program this event handler to convert the uppercase letters to lowercase.
-
Use the CharacterCasing property of the controls.
-
Use the Char.ToLower method in the TextChanged event handlers of the controls.
-
You must create a custom exception class in your Windows application. You have written the following code for the exception class:
Public Class KeywordNotFound Inherits ApplicationException Public Sub New() ' Code here End Sub Public Sub New( _ ByVal message As String, _ ByVal inner As Exception) MyBase.New(message, inner) ' Code here End Sub End Class
A code review suggests that that you did not followed some of the best practices for creating a custom exception class. Which of these changes should you make? (Select two.)
-
Name the exception class KeywordNotFoundException.
-
Derive the exception class from the base class Exception instead of ApplicationException.
-
Add one more constructor to the class with the following signature:
Public Sub New(ByVal message As String) MyBase.New(message) ' Code here End Sub
-
Add one more constructor to the class with the following signature:
Public Sub New(ByVal inner As Exception) MyBase.New(inner) ' Code here End Sub
-
Derive the exception class from the base class SystemException instead of ApplicationException.
-
-
In your Windows application, you have created a dialog box that allows the user to set options for the application. You have also created a Help button that the user can press to get help on various options in the dialog box. You validate the data entered by the user in a TextBox control labeled Complex Script; if the user enters an invalid value in this text box, you set the focus back in the control by setting the cancel property of the CancelEventArgs object to True. While testing the application, you discovered that once you enter invalid data in the text box, you could not click on the Help button without correcting the data first. What should you do to correct the problem?
-
Set the CausesValidation property of the text box to False.
-
Set the CausesValidation property of the text box to True.
-
Set the CausesValidation property of the Help button to False.
-
Set the CausesValidation property of the Help button to True.
-
-
You are writing exception handling code for an order entry form. When the exception occurs, you want to get information about the sequence of method calls and the line number in the method where the exception occurs. Which property of your exception class can help you?
-
HelpLink
-
InnerException
-
Message
-
StackTrace
-
Your code uses the Throw statement in this fashion:
Catch e As Exception Throw
Which of these statements is true about this code?
-
The Throw statement catches and rethrows the current exception.
-
The Throw statement catches, wraps, and then rethrows the current exception.
-
The Throw statement must be followed by an exception object to be thrown.
-
The Throw statement transfers control to the Finally block following the Catch block.
-
-
You are creating a Windows Form that works as a login screen for an Order Entry system designed for the sales department of your company. Which of the following strategies should you follow?
-
Design a ValidateUser method. Throw a new custom exception named EmployeeNotFound when the entered username is not in the database.
-
Design a ValidateUser method. Throw an ArgumentException exception when the user types special characters in the User name or Password text boxes.
-
Design a ValidateUser method. It returns True if the username and password are correct; otherwise it returns False.
-
Design a ValidateUser method. Throw an ApplicationException when the entered username is not in the database.
-
-
You want to capture all the exceptions that escape from the exception handling code in your application and log them to Windows event log. Which of the following techniques would you use?
-
Write all the code of the application inside a Try block, attach a generic Catch block to that Try block, and handle the exception there.
-
Write all the code of the application inside a Try block, attach a Catch block that catches the super type of all exceptions (the Exception objects), and write code to make entries in the event log there.
-
Program the ProcessExit event handler of the AppDomain class.
-
Program the UnhandledException event handler of the AppDomain class.
-
-
Which of the following is generally the most robust way to record the unhandled exceptions in your application?
-
Create an entry in Windows event log.
-
Create an entry in the application's custom event log.
-
Create an entry in a table in Microsoft SQL Server 2000 database.
-
Send an email using SMTP.
-
-
The structured exception handling mechanism of the .NET Framework allows you to handle which of the following types of exceptions? (Select all that apply.)
-
Exceptions from all CLS-compliant languages
-
Exceptions from non-CLScompliant languages
-
Exceptions from unmanaged COM code
-
Exceptions from unmanaged nonCOM code
-
What is the result of executing this code snippet?
Const someVal1 As Int32 = Int32.MaxValue Const someVal2 As Int32 = Int32.MaxValue Dim result As Int32 result = someVal1 * someVal2
-
The code will generate an OverflowException.
-
The code will execute successfully without any exceptions.
-
The code will cause a compile-time error
- The code executes successfully but the value of the variable result is truncated.
-
Answers to Review Questions
-
The .NET framework terminates the application after displaying an error message when an exception is raised.
-
The Exception class is the base class that provides common functionality for exception handling. The two main types of exceptions derived from Exception class are SystemException and ApplicationException. SystemException represents the exceptions thrown by the common language runtime, whereas ApplicationException represents the exceptions thrown by user code.
-
The Message property describes the current exception. The InnerException property represents an exception object associated with the exception object; this property is helpful when a series of exceptions are involved. Each new exception can preserve information about a previous exception by storing it in InnerException property.
-
The Try block encloses code that might raise an exception. The Catch block handles any exception raised by the code in the Try block.
-
Zero or more Catch blocks can be associated with a single Try block. If no Catch block is associated with a Try block, a Finally block should follow the Try block; otherwise a compile-time error occurs. The Catch blocks should be arranged from specific to general exception types to avoid a compile-time error.
-
The code contained by the Finally block always executes regardless of any exception in the application. Therefore, you can use the Finally block to write cleanup code to complete tasks, such as closing data connections, closing files, and so on, that need to be performed regardless of whether an exception occurred.
-
Yes, you can associate custom error messages with the exception classes defined by the Common Language Runtime to provide more meaningful information to the caller code. The constructor of these classes that accepts the exception message as its parameter can be used to pass the custom error message.
-
Custom exceptions should be derived from ApplicationException and should be created only if existing classes do not meet the requirements of your application. They should have a name ending with the word Exception and should implement the three constructors (default, Message, and Message and Exception) of their base class.
-
The Validating event is the ideal place to store the field-level validation logic for a control. The Validating event handler can be used to cancel the event if validation fails, thus forcing the focus to the control. This forces the user to enter correct data.
- The ErrorProvider component in the Visual Studio .Net toolbox can be used to show validation-related error icons and error messages to the user.
Answers to Exam Questions
-
A. When creating a class for handling custom exceptions in your programs, the best practice is to derive it from the ApplicationException class. The SystemException class is for system-defined exceptions. The Exception class is the base class for both ApplicationException and SystemException classes and should not generally be derived from directly.
-
C. When you have multiple Catch blocks associated with a Try block, you must write them in order from the most specific to the most general one. The Catch block corresponding to the ArithmeticException should come at the end because it is a more general class than the three (DivideByZeroException, NotFiniteNumberException and the OverFlowException) classes derived from it.
-
B. When an exception occurs in a Try block, it will search for a matching Catch block associated with that Try block. In this case, the ArithmeticException generates a match for DivideByZeroException because DivideByZeroException is derived from ArithmeticException, and the exception is handled right there. In all cases the Finally block is executed.
-
D. The message box displays System.ArgumentOutOfRangeException because you caught and wrapped that exception in the InnerException property of the exception caught later by the outer Catch block.
-
A. When you want to retain the focus inside a control after the Validating event is processed, you must set the Cancel property of the CancelEventArgs argument in the Validating event, so the correct answer is e.Cancel = True. The CausesValidation property has a different purpose: It decides whether a Validating event will be fired for a control.
-
C. The CharacterCasing property when set to CharacterCasing.Lower for a text box will convert all uppercase letters to lowercase as you type them. It is the preferred way to enforce either lowercase or uppercase input in a text box.
-
A, C. The best practices for exception handling recommend that you end the name of your exception class with the word Exception. In addition, an exception class must implement three standard contructors. The missing constructor is the one given in option C.
-
C. When you want a control to respond regardless of the validation statuses of other controls, set the CausesValidation property of that control to True. Then the Help button should have its CausesValidation property set to False.
-
D. The StackTrace property of the Exception class and the classes that derive from it contains information about the sequence of method calls and the line numbers in which the exception occurred. Therefore, it is the right property to use.
-
A. The Throw statement just catches and throws the current exception.
-
C. It is obvious that user can make typing mistakes while typing her username or password. You should not throw exceptions for these situations; you should rather design a ValidateUser method that returns a result indicating whether the login was successful.
-
D. To capture all unhandled exceptions for an application, you must program the UnhandledEvent event handler of its AppDomian class.
-
A. Logging to the Windows event handler is the most robust solution because the other solutions have more assumptions that can fail. Sometimes your application can loose connectivity with the database or with the SMTP server, or you might have problems writing an entry in a custom log file.
-
A, B, C, D. The .NET Framework allows you to handle all types of exceptions including cross-language exceptions for both CLS- and nonCLS-complaint languages. It also allows you to handle exceptions from unmanaged code, both COM and nonCOM.
- C. Since you are multiplying two maximum possible values for integers, the result cannot be stored inside an integer. The compiler will detect it and will flag a compile-time error.
Suggested Readings and Resources
-
Ritcher, Jeffery. Applied Microsoft .NET Framework Programming. Microsoft Press, 2001.
-
Siler, Brian and Jeff Spotts. Special Edition Using Visual Basic .NET. Que, 2002.
-
Visual Studio .NET Combined Help Collection
-
Best Practices for Exception Handling
-
Exception Handling Statements
- Exception Management in .NET
-