In this section, you will learn how to find and deal
with two exceptions that are common to Windows Phone applications. The
first is the navigation failed exception, which can be thrown when a
main page is loaded; the second deals with the web service call that is
consumed by the application.
The ErrorHandlingDemo application that you'll use contains two projects, a Windows Phone project and the Calculator web service project, which has an Add
method that adds two numbers and returns the result to the caller.
Being able to debug and handle web service call exceptions will be
critical especially if you are planning to work with external services
like Microsoft Bing Maps services.
When you finally debug and fix all the issues in the application, you will see the result shown in Figure 1.
1. Debugging Page Load Exceptions
TheErrorHandlingDemo
application contains bugs that will cause exceptions to be thrown when
the application's main page is loaded. In this section, you will learn
how to find and fix such problems in Visual Studio.
1.1. Catching an Exception
Whenever an application
throws an exception, Visual Studio will stop execution at the line where
it's thrown. To observe this behavior, let's run the application and
take a closer look using the Visual Studio IDE.
Fire up Visual Studio, select File=>Open, and browse to the following file, which you can download from the site for this book:
{unzippeddirectory}\ch04\ErrorHandlingDemo\Start\ErrorHandlingDemo.sln.
Once the solution file is loaded, press F5 to run it.
Notice the raised exception message in Figure 2, which points to the code that has caused ArgumentOutOfRangeExceptionto be thrown. From DeviceExtendedProperties you can obtain Windows Phone 7 system information, and only the following keys—DeviceManufacturer, DeviceName, DeviceUniqueId, DeviceTotalMemory, ApplicationCurrentMemoryUsage, andApplicationPeakMemoryUsage—will be available. And when you try to query the system information DName that does not exist, the application throws ArgumentOutOfException.
1.2. Querying Exception Object Values with Immediate Window
Whenever an application running in
Visual Studio pauses at a line where an exception has been thrown, you
always have an opportunity to observe its variables in Visual Studio's
Immediate Window.
Immediate Window is a
most useful debugging feature because it allows you to evaluate any
statement when the code execution pauses at the breakpoint. If you do
not see the immediate window when the breakpoint is hit, you can go to
Debug => Windows => Immediate to bring up the Immediate Window, as shown in Figure 4-3.
With ErrorHandlingDemo still paused in the debugger, go to the Immediate Window, type in DeviceExtendedProperties.GetValue("DeviceName") to query the object value, and press Enter. You will see the result printed in an Immediate Window, as shown in Figure 3.
1.3. Catching an Unhandled Exception in RootFrame_NavigationFailed or Application_UnhandledException
Unhandled exceptions in a Windows Phone application will be caught by one of two main methods: RootFrame_NavigationFailed, andApplication_UnhandledException.RootFrame_NavigationFailed catches unhandled exceptions thrown while a page is being loaded; Application_UnhandledException catches exceptions thrown in all other cases.
Press F5 to continue debugging from the breakpoint in the previous section.
The debugger will next break inside RootFrame_NavigationFailed in App.xaml.cs as shown in Figure 4. Notice that in App.xaml.cs you will find various Windows Phone application–related events such as Application_Launching, Application_Activated, Application_Deactivated, Application_Closing, RootFrame_NavigationFailed, andApplication_UnhandledException. As far as exceptions are concerned, only two events will be of interest. RootFrame_NavigationFailed captures unhandled exceptions when the Windows Phone page fails to load. In ErrorHandlingDemo, unhandled exceptions occur when MainPage tries to load and throws ArgumentOutOfException.
With your mouse, hover over NavigationFailedEventArgs e and you will be able to drill into the object value and see the e.Uri that contains the page that caused the error during the load, as shown in Figure 5.
Press F5 to continue debugging, and you will notice that code execution next breaks in the Application_UnhandledException method. All exceptions that are not handled specifically by a try-catch-finally block will ultimately end up in this method.
1.4. Handling an Exception RootFrame_NavigationFailed
When an exception is thrown in the MainPage of an application, the exception will be caught by the RootFrame_NavigationFailed method, and this is where you want to handle it in order to stop the exception from bubbling up to the Application_UnhandledException method.
In ErrorHandlingDemo, replace the RootFrame_NavigationFailed method with following code. Notice the use of MessageBox in the code to display the proper error with stack trace and set e.Handled to true, which will stop the breakpoint to move to the Application_UnhandledException method.
// Code to execute if a navigation fails
private void RootFrame_NavigationFailed(object sender, NavigationFailedEventArgs e)
{
if (System.Diagnostics.Debugger.IsAttached)
{
// A navigation has failed; break into the debugger
System.Diagnostics.Debugger.Break();
}
MessageBox.Show(
string.Format("Page {0} failed to load because of with error: {1}",
e.Uri.ToString(), e.Exception.StackTrace));
e.Handled = true;
}
1.5. Fixing the Error in the Code
In the previous section, you added a MessageBox
display in case any other page fails to load, and in the following
steps, you will be fixing the actual cause of the exception in MainPage. But first, let's fix the error in MainPage.xaml.cs.
Fix the error in MainPage.xaml.cs by replacing
txtDeviceName.Text = DeviceExtendedProperties.GetValue("DName").ToString()
with
txtDeviceName.Text = DeviceExtendedProperties.GetValue("DeviceName").ToString().