Chapter 11

Monitoring, Troubleshooting, and Debugging

Debugging an application

Debugging an ASP.NET Web site can be complicated, as the client and server are typically distributed across different machines. In addition, the state that the application uses is also distributed among database, Web server, cache, session, cookie, and so on. Thankfully, Visual Studio and ASP.NET have a number of tools that allow you to get debugging information from your site during development.

You can debug an ASP.NET application using the standard features of the Visual Studio debugger like breakpoints, watch windows, code step-through, error information, and the like.

To do so, you must first configure ASP.NET for debugging. There are two areas where you set this information: the project’s property page and the Web.config file.

The first step is to enable the ASP.NET debugger in your project’s Property Pages dialog box.

For sites created through Visual Studio, this is enabled by default. However, if you need to set or modify this setting, you can do so by following these steps:

1. Right-click the Web site in Solution Explorer to open the shortcut menu.

2. Select Property Pages from the shortcut menu. This will open the Property Pages dialog

3. Select Start Options from the left side of the dialog box.

4. In the Debuggers section, at the bottom of the dialog box, select (or clear) the ASP.NET check box to enable (or disable) the ASP.NET debugger for Visual Studio.

The second step is to enable debugging either for your entire site or on a page-by-page

basis. By default, debugging is not enabled for Web sites created with Visual Studio. Doing so

will add debug symbols into the compiled code. Visual Studio uses these symbols to provide

debugging support. However, this can slow the performance of your Web application. In

addition, turning on debugging will output error information to the Web browser when you

run the page outside of Visual Studio. This can present a security risk, as error information

provides potential attackers with a lot of information about how your site works. For these

reasons, you only want to turn debugging on during development.

You enable debugging for your entire site through the Web.config file by setting the debug attribute of the compilation element to true. The following markup shows an example that includes the nesting level of the compilation element:



<compilation debug="true">




It might not always be desirable to turn on debugging for your entire site. In these cases, you can switch debugging on and off at the individual page level. This will compile only that page with the debug symbols. The rest of the site will be compiled without debugging. To enable page-level debugging, set the Debug attribute of the @ Page directive (found at the top of the markup for an .aspx page). The following shows an example:

<%@ Page Debug="true" ... %>

Once you have debugging enabled you can use the many features of the Visual Studio debugger.

Configuring a Custom Site-Level Error Page

You configure custom errors inside the Web.config file using the <customErrors> element nested inside <system.web>. This element has the attributes mode and defaultRedirect. The mode attribute can be set to on to turn custom errors on, off to turn them off, or RemoteOnly to turn custom errors on for remote clients only. With RemoteOnly, if a user (typically an administrator) is on the server, he or she will not get the custom error, but instead will get the real error message.

The defaultRedirect attribute is used to indicate the path to a default error page. This page will be hit when an unhandled exception occurs on the site. The only exception is when a specific custom error page is added to the <error> child elements of <customErrors> (as discussed in the next section). The following example shows markup for a custom error definition inside Web.config:



<customErrors defaultRedirect="SiteErrorPage.aspx" mode="RemoteOnly">




Configuring Error-Specific Error Pages

It is also possible to define specific pages for various HTTP status codes. This allows you to provide more specific information to users when they hit a given status code. For example, if users do not have access to a given page or resource, they will be shown the HTTP error 403.

This status code indicates they are denied access to the resource. You can then write a custom page that explains the process for obtaining access to a given resource. Use the <error> element to redirect to that custom page. The following markup shows an example:



<customErrors defaultRedirect="SiteErrorPage.aspx" mode="RemoteOnly">

<error statusCode="403" redirect="RestrictedAccess.aspx" />




Debugging Client-Side Script

Visual Studio also allows you to debug client script running inside a browser. This is useful if you write a lot of JavaScript and need to walk through the code line by line and use the other features of the debugging toolset.

To get started, you need to enable script debugging support inside the browser. To do so, you open Microsoft Internet Explorer and select Tools | Internet Options.

Click the Advanced tab. Find the Browsing node in the Settings tree and clear the Disable Script Debugging (Internet Explorer) check box. You can then begin debugging client script. You can get started by setting a breakpoint in your client script and running the site through Visual Studio. You can also manually attach to code running in a browser.

Shembull 1:

1. Open Visual Studio. Create a new, filebased Web site called debugging.

2. Open the Web.config file and navigate to the compilation node. Set the debug attribute to true as follows:

<compilation debug="true">

3. Open the code-behind fi le for Default.aspx. Add a Page_Load event handler. Inside this event throw an exception. The following code shows an example:

protected void Page_Load(object sender, EventArgs e)


throw new ApplicationException("Example exception.");


4. Run the Default.aspx page in a browser by right-clicking the page in Solution Explorer and choosing View in Browser.

Shembull 2:

1. Open the project you created in the previous exercise.

2. Add a new Web form to the site. Name this form resourcenotfound.aspx. Add text to the body of this page to display a custom error message to users when they try to access a resource that is not on the Web server. You can use the aspxerrorpath query string parameter to display the path of the requested resource inside the message.

3. Open the Web.config file again. Navigate to the customErrors section (commented out by default). Turn on custom errors. Add an error element for HTTP status code 404 (resource not found). The following markup shows an example:

<customErrors mode="On">

<error statusCode="404" redirect="ResourceNotFound.aspx" />


4. View Default.aspx in a browser again. Notice that the debugging error message is no longer shown. This is because the on setting in the customErrors node indicates that the site should only display custom errors.

Next, change the URL in your browser to request Default2.aspx (which should not exist in your site). This will redirect the browser to the ResourceNotFound.aspx page.

Shembull 3:

1. Open the project you created in the previous exercise.

2. Add a new Web page to your site. Name the page scriptdebug.aspx.

3. Add a JavaScript function to the markup. This can be a simple script as follows:

<script language="javascript" type="text/jscript">

function buttonClick() {

alert('Button clicked.');



4. Add an HTML button to the page. Set the OnClick event to call the JavaScript function as follows: <input id="Button1" type="button" value="button" onclick="buttonClick()" />

5. Open Internet Explorer and select Tools | Internet Options. Click the Advanced tab and clear the Disable Script Debugging (Internet Explorer) check box. Click OK.

6. Return to Visual Studio. Set a breakpoint on the buttonClick function inside the markup. You can do so by clicking the margin area in the code editor (on the left side).

7. Run the application from Visual Studio by choosing Start Debugging from the Debug menu (or simply press F5). Navigate to the ScriptDebug.aspx page. Click the button to break into the script debugger.

Troubleshooting a running application

Not all issues can be found using Visual Studio. Therefore, ASP.NET provides the ability to trace and monitor your code as it executes in a test or production environment. These facilities of ASP.NET can be used to troubleshoot and diagnose problems that might otherwise prove impossible to re-create. In addition, these features allow you to examine statistics and usage on your Web site.

Implementing Tracing

Tracing is the process of emitting data about a running application. In ASP.NET, this data is logged to a trace log fi le that you can access through a Web browser. The data provides important information about your site, such as who accessed the site, what the results were,

what the various HTTP data looked like, and much more. You can also inject your own tracing calls into your code. This data will be emitted alongside the ASP.NET data. The following data is collected by ASP.NET tracing by default:

Request details This includes session ID, the type of request (GET/POST), and the status of the request.

Trace information This provides the timings for the various stages of your requests. This section also shows unhandled exceptions (in red) if there are any.

Controls This indicates the controls on your page, their view state, and their rendered bytes.

Session/application state This indicates the session and application variables and their current values for the given request.

Request/response cookies Indicates the value and size of any cookies that are part of the request or response.

Headers This indicates the HTTP header information such as the type of browser making the request.

Form data This indicates the name and value of any posted form fields.

Query string values This indicates the name and value of query string parameters sent as part of the request.

Server variables This is used to view each server variable and its value at the time of the request.

You enable tracing through the Web.config file. You can edit this file manually or you can use the Web Site Administration Tool (WSAT) to provide a user-friendly interface to enable and configure tracing.

Enabling Trace Using the Web Site Administration Tool

The following steps identify how to enable and configure the trace facility using the WSAT:

1. Open the WSAT by selecting Website | ASP.NET Configuration from the Visual Studio menu.

2. On the home page, click the Application tab of the WSAT. This will bring up settings for your application.

3. On the Application tab, click Configure Debugging And Tracing (bottom right). This will display the configuration options for debugging and tracing.

4. Select the Capture Tracing Information check box. This enables the tracing features to be changed as necessary.

Enabling Trace Using the Web.Config File

You can enable tracing manually through editing the Web.config file of an ASP.NET site. You do so by editing attributes of the <trace> element. This element is nested under <configuration><system.web>. The following markup shows an example:



<trace enabled="true"





mostRecent="true" />



In the preceding markup, tracing is enabled (enabled=”true”) for all requests to the server (localOnly=”false”). The trace log will cache the most recent 100 requests (“requestLimit=100” and mostRecent=”true”). The trace log will be sorted by time (“traceMode=SortyByTime”).

Enabling Tracing at the Page Level

You can also enable tracing for specific pages only. This is useful if you do not wish to turn on tracing at the site level, but instead enable it only on a page you are troubleshooting. You enable tracing at the page level by setting the trace attribute of the @ Page directive to true. This is found at the top of the page’s markup. The following shows an example:

<@Page trace="true" ... />

Viewing Trace Data

Once it is configured and turned on, you can view the ASP.NET trace data on each Web page (pageOutput=”true”) or view the trace output by navigating to the Trace.axd page on the current Web application (http://server/application/trace.axd). When viewing on the same page, the trace information is appended to the bottom of the page (for pages that use flow layout).

Shembull 1:

1. Open Visual Studio. Create a new, file-based Web site called TracingCode.

2. Open the Web Site Administration Tool from the Visual Studio menu by selecting Website | ASP.NET Configuration.

3. Click the Application tab to display the application settings. Click Configure Debugging And Tracing.

4. Select the Capture Tracing Information check box. This enables tracing for your site. Make the following additional changes using this page:

- Ensure the Display Tracing Information On Individual Pages check box is cleared.

- Set the Display Trace Output For option to Local Requests Only.

- Set the Select The Sort Order For Trace Results option to By Time.

- Set the Number Of Trace Requests To Cache drop-down list to 50.

- Set the Select Which Trace Results To Cache option to Most Recent Trace Results.

Close the Web Site Administration Tool when finished.

5. Open the Web.config file. Navigate to the trace element. The trace element should look as follows (notice defaults are not listed, only the items that had to be overridden):

<trace enabled="true" mostRecent="true" requestLimit="50" />

6. Run the Web application. Although the Default.aspx page is blank, tracing still logs the request. Refresh the Web page a few times to write more results to the log.

7. In the Address bar of the browser, change the URL to access Trace.axd for the site. This will bring up the trace log. You should see entries for each time you requested the page.

Click one of the View Details links to open a given record. Notice that Trace Information contains the timings for the events in the Web page life cycle. Close the Web browser.

8. Open Default.aspx in Visual Studio. Add the attribute trace=”true” to the @ Page directive at the top of the page. Run the site again; notice that the page now includes the trace information written out. Close the Web browser.

9. Open the code-behind fi le for Default.aspx in Visual Studio. Add an event handler for the Page_Load event. Inside the event handler use Page.Trace to write out a tracing message. Your code should look as follows:

protected void Page_Load(object sender, EventArgs e)


Trace.Write("Custom Category", "Page_Load called");


10. Run the application again. Notice your custom tracing message inside the Trace Information section of the page’s trace output.

Creating ASP.NET Mobile Web Applications

Since their initial release with .NET Framework 1.0, there have been multiple versions of mobile controls and varied levels of support within Visual Studio. Mobile Web controls were first introduced in ASP.NET 1.0. These controls used to be known as the Microsoft Mobile Internet Toolkit. However, they are now referred to as ASP.NET Mobile and consist of the mobile Web controls that ship with ASP.NET inside System.Web.UI.MobileControls and the features exposed by System.Web.Mobile.

Creating a Mobile Web Application

A mobile Web application has a similar programming model to that of any ASP.NET Web site. You create forms, code-behind classes, style sheets, configuration files, and more. The mobile Web application also uses the same server-side architecture for connecting to databases, managing state, and caching data. You can, of course, also use the same techniques for troubleshooting and debugging a mobile Web application. The primary difference is in the classes you use to create your forms and the controls you place on a page.

Therefore, to start creating a mobile Web application, you simply create an ASP.NET Web site as you would any other. You can even mix mobile pages with nonmobile pages.

Creating Mobile Web Forms

Like standard Web forms, the mobile Web form is an .aspx page that is accessible by a Uniform Resource Locator (URL) and can optionally have a code-behind page. The difference is that a mobile Web form inherits from System.Web.UI.MobileControls.MobilePage instead of System.Web.UI.Page.

public partial class Default : System.Web.UI.MobileControls.MobilePage


protected void Page_Load(object sender, EventArgs e)




Next, you register the MobileControls namespace and assembly with your page. Doing so will give you IntelliSense access to the mobile controls inside Source view for your Web page.

The following markup should be added to your page after the @ Page directive to accomplish this:

<%@ Register TagPrefix="mobile" Namespace="System.Web.UI.MobileControls" Assembly="System.Web.Mobile" %>

The last step is to replace the markup with mobile-like markup. This means adding a <mobile:Form> control to the <body> tag. The following shows an example:

<html xmlns="" >


<mobile:Form id="Form1" runat="server">




At this point, you can begin adding other mobile controls to your page.

Using Mobile Controls

The mobile control set should be familiar to ASP.NET developers. There are basic controls for user input such as Calendar, TextBox, Image, Label, Command (button-like behavior), and List. There are also a set of validation controls that work in a manner similar to those used by regular Web forms.

Label Control

The Label control can be used to display a string to the user that cannot be edited by the user. You use a Label control when you need access to the control from code at run time. In addition, the Label control has properties for various styles as well as Alignment and Wrapping properties.

When working with long strings, it is preferable to use the TextView control, because the Label control might not render as nicely.

TextBox Control

The TextBox control provides the user the ability to input a string. The TextBox control contains several style settings to allow customization of the TextBox view. This includes a Size property to limit the width of the TextBox to the number of characters to which Size is set. The TextBox also contains a MaxLength property that limits the number of characters that can be entered into the TextBox.

You can restrict entry in the TextBox control, too. For example, the TextBox can be configured to only accept numeric input by setting the Numeric property to true. The TextBox can also be used to enter passwords by setting the Password property to true.

TextView Control

The TextView control provides the ability to display many lines of text. This control allows the use of some HTML formatting tags to control the output, such as a (hyperlink), b (bold), br (break), i (italic), and p (paragraph).

Command Control

The Command control represents a programmable button. On some devices, the Command button renders as a button, whereas on other devices, such as cell phones, it renders as a soft key that can be pressed. The Text property of the button is displayed on the control or in the soft key layout.

The Command control raises the OnClick event when the button is clicked and has an ItemCommand that propagates to the container when the button is clicked.

Image Control

The Image control displays an image based on the capabilities of the device. The image also supports the ability to have device filters assigned, which means that each type of device can have a different image. The AlternateText property should always be set on the Image control, because some devices might not support images, and some devices might not support the type of image that is being provided. For example, if a .gif file is being provided and the device only works with .wbmp files, the AlternateText is displayed.

List Control

The List control displays a static list of items. List items can be added to the Items property of the control or by binding data to the control. This list is paginated as required.

The List control supports data binding using the DataSource, DataMember, DataTextField, and DataValueField properties. Whereas this list is primarily used to display static data with links, the SelectionList control (which we describe next) is intended to provide a selection list with options that are more similar to the menu type.

SelectionList Control

The SelectionList is very similar to the List control, except the SelectionList does not post back to the server. This means that a command button must be provided on the form.

The SelectionList also allows multiple selections, whereas the List control allows only a single selection. The SelectionList does not offer pagination, although the List control does. By default, this control renders on most devices as a drop-down list box, which means that only one selection is visible. The SelectType property of the SelectionList control can be set to CheckBox or MultiSelectListBox to allow multiple selections.

This control also supports data binding using the DataSource, DataMember, DataTextField, and DataValueField properties.

ObjectList Control

One might refer to the ObjectList control as being the mobile grid. This control is used to display tabular data. The ObjectList control is bound to data using the DataSource and DataMember properties and contains a property called LabelField, which displays when the control is initially rendered. The LabelField is typically set to the primary key field, and when rendered, produces a list of primary key values as hyperlinks that can be clicked to see the rest of the data.

As an example, suppose you wish to display the Customers table from the Northwind database on a mobile device. You could create a simple mobile form that included an ObjectList control as follows:

<html xmlns="" >


<mobile:Form id="Form1" runat="server">

<mobile:ObjectList Runat="server" ID="ObjectList1">





In the code-behind file, you need to add code to connect to your database, fill a data table, and then bind it to your list control. The following code shows the binding operations inside the MobilePage load event:

protected void Page_Load(object sender, EventArgs e)


if (!IsPostBack)


ObjectList1.DataSource = GetCustomerData();

ObjectList1.LabelField = "CustomerID";




Calendar Control

The Calendar control allows the user to specify a date. The presentation of the date selection might be very different, depending on the type of device. The Calendar control renders as a series of forms, in which the user can drill down to a specific date. The user also has the ability to manually enter a date.

AdRotator Control

The AdRotator control can be used to place an advertisement on a device. This control is similar to ASP.NET’s AdRotator control, except that the rendering adapts to the device.

The AdRotator control can be assigned a series of images. The AdRotator control does not require a specific image type. The image can be assigned, based on the device type, by assigning device filters (discussed later in this lesson).

The AdRotator control requires an .xml file to configure the advertisements. This file can be the same file that is used by the standard AdRotator Web server control, in which the root element of the .xml file is called Advertisements. The Advertisements element can contain many Ad elements. Each Ad element contains elements for each advertisement property.

PhoneCall Control

The PhoneCall control provides a simple method of dialing a phone number on devices that support placing calls. The PhoneCall control has a PhoneNumber property that can be set to the phone number that is to be dialed. The phone number is displayed on the device as a hyperlink, but if the Text property is set, the Text is displayed as the hyperlink text instead of the actual phone number. The SoftKeyLabel property can be set to a custom string, such as Call for the function key, if the device supports function keys.

The PhoneCall control displays the contents of the AlternateText property if the device does not support phone calls. The AlternateText property defaults to {0} {1}, where {0} is the Text property and {1} is the PhoneNumber property.

Validation Controls

Validation controls are a very important part of standard ASP.NET Web pages, and they are included as mobile controls as well. The following is a list of mobile validation controls:

- RequiredFieldValidator An entry is required in this field.

- RangeValidator The entry must be within the specified range.

- CompareValidator The entry is compared to another value.

- CustomValidator A custom validation function validates the entry.

- RegularExpressionValidator The entry must match the specified pattern.

- ValidationSummary This displays a summary of all input errors.

These controls are essentially the same as the controls that are available in the nonmobile version of ASP.NET except that the mobile validator controls do not provide client-side validation. You can combine these controls as necessary. For example, a TextBox can have both the RequiredFieldValidator and the RegularExpressionValidator.

Data Binding

Data binding with mobile controls is essentially the same as data binding in ASP.NET. Most controls support the DataSource and DataMember properties and some controls support the DataTextField and the DataValue fields as well. It is important to use the IsPostBack property and load data into the cache. Rather than binding all controls, only the controls for the current form should be bound.

Maintaining Session State

In a typical ASP.NET Web site, session state is maintained by issuing a session cookie to the browser. When the browser communicates to the Web server, the session cookie is passed to the Web server, and the Web server retrieves the session ID value from the session cookie to look up the session state data for your session.

Many mobile devices, such as most cell phones, don’t accept cookies. This causes problems with maintaining session state. The solution is to enable cookieless sessions. This can be accomplished by adding the following element to the Web.config file inside the system.web element:

<sessionState cookieless="true" />

With cookieless sessions, the session ID value is placed into the URL for the Web site instead of a cookie. You should plan on implementing cookieless sessions on all mobile applications to ensure that your mobile Web site is compatible with the majority of mobile devices.

If you are using forms-based authentication for your mobile application, you also need to configure the cookieless data dictionary. This can be done by adding the following to your configuration file:

<mobileControls cookielessDataDictionaryType="System.Web.Mobile.CookielessData" />


You can separate the mobile form content into smaller chunks by using pagination. Enabling pagination causes the runtime to format the output to the target device. Pagination is disabled by default but can be enabled by setting the Paginate property of each mobile form control to true.

For inputting data, pagination is typically not required, because many devices already contain mechanisms for allowing input of one item at a time. Pagination is best suited for mobile form controls that display lots of read-only data to keep a device from running out of memory.

In addition to enabling and disabling the pagination, custom pagination is also supported by the List, ObjectList, and TextView controls. These controls support internal pagination, which means that these controls provide pagination of their own items. These controls provide the ability to set the items per page and can raise the LoadItems event to load data.


Panels are container controls that can be used to provide further grouping of controls for the purpose of enabling, disabling, hiding, and showing controls as a single group. Panels cannot be navigated to in the same way that forms can. You can use panels as a placeholder for dynamically created controls. The runtime attempts to display all controls that are with the panel on the same screen.

Applying Best Practices to Mobile Applications

In many respects, writing applications for mobile use can be a challenging endeavor. The following list identifies some guidelines and best practices that you should consider.

- provide a separate desktop presentation Although many devices are adaptive, desktop users want and expect a much richer presentation. It’s usually best to provide two presentations: one for the desktop and one for the mobile devices.

- page content Keep page content as simple as possible.

- data access Instead of sending a complete result set to the user, only send the data record that the user is interested in. Only bind the required controls.

- adaptive controls Test adaptive controls with several devices, including devices that display a few lines.

- default values Present the user with default values whenever possible.

- evaluate ViewState In many applications, better performance can be obtained by turning off ViewState, because this reduces the amount of data that is being transferred to a slow mobile device. Turning off ViewState might require the server to rebuild the data each time the user posts back to the server.

- use caching Whenever possible, cache data access results to keep from retrieving data each time the user accesses the server.

- combine many forms on a page It is much easier to share data between forms on a page than it is to share data between pages. However, there is a point at which performance suffers. Look for places where it is easy to pass a few items to a new page.

- use cookieless sessions Many mobile devices do not support cookies, so it is important to use cookieless sessions.

- using hyperlinks to a form A hyperlink can be created to a form by using the syntax, #form2 (where form2 represents the name of the form). If the page has a user control called myControl, which has forms, a hyperlink can be created using the

#myControl:form2 syntax.

- minimize image usage Use of images should be kept to a minimum due to the low bandwidth and screen resolution that is available on most mobile devices. Some mobile devices might not support images, and others might not support the image type that is being supplied, such as when a .gif fi le is used on a mobile device that only supports .wbmp fi les. Be sure to assign a value to the AlternateText property of all graphics.

Shembull 1:

1. Open Visual Studio and create a new Web site called mobilesite.

2. Open the code-behind fi le for the Default.aspx page. Change the class inheritance to use the MobilePage class. Your code should look as follows:

public partial class _Default : System.Web.UI.MobileControls.MobilePage



3. Open the markup for Default.aspx in Source view. Remove the <!DOCTYPE> element from the page. Under the @ Page directive, add the @ Register directive to register the MobileControls namespace. This markup looks as follows:

<%@ Register TagPrefix="mobile" Namespace="System.Web.UI.MobileControls"

Assembly="System.Web.Mobile" %>

4. Next, you define the mobile form controls used by the page. The page is meant to walk a user through a search process on a mobile device. Create a mobile form for each of the following:

- ID = formmain and Title = select a search method.

- ID = formsearchname and Title = enter a name.

- ID = formsearchid and Title = enter id.

- ID = formsearchcategory and Title = select a category.

- ID = formresult and Title = search results.

5. Next, you need to defi ne the controls used by each form.

- formmain Add a mobile List control. Set the ID to Listmainmenu. Add the following to the Items collection: By Name (value=1), By ID (value=2), and By Category (value=3).

- formsearchname Add a Label control and set its ID to Labelsearchname and its Text to enter name. Add a mobile TextBox control and set its ID to textboxsearchname. Add a mobile Command control and set its ID to commandsearchname and its CommandName to search.

- formsearchid Add a Label control and set its ID to Labelsearchid and its Text to enter id. Add a mobile TextBox control and set its ID to textboxsearchid. Add a mobile Command control and set its ID to commandsearchid and its Command-Name to search.

- formsearchcategory Add a mobile List control. Set its ID to Listcategory.

- formresults Add an ObjectList control. Set its ID to ObjectListresults.

Your markup should now look as follows:

<html xmlns="" >


<mobile:Form id="FormMain" runat="server" Title="Select a Search Method">

<mobile:List ID="ListMainMenu" Runat="server">

<Item Text="By Name" Value="1" />

<Item Text="By ID" Value="2" />

<Item Text="By Category" Value="3" />



<mobile:Form id="FormSearchName" runat="server" Title="Enter Name">

<mobile:Label ID="LabelSearchName" Runat="server">Enter Name</mobile:Label>

<mobile:TextBox ID="TextBoxSearchName" Runat="server"></mobile:TextBox>

<mobile:Command ID="CommandSearchName" Runat="server" CommandName="Search">



<mobile:Form id="FormSearchId" runat="server" Title="Enter ID">

<mobile:Label ID="LabelSearchId" Runat="server">Enter ID</mobile:Label>

<mobile:TextBox ID="TextBoxSearchId" Runat="server"></mobile:TextBox>

<mobile:Command ID="CommandSearchId" Runat="server" CommandName="Search">



<mobile:Form id="FormSearchCategory" runat="server" Title="Select a Category">

<mobile:List Runat="server" ID="ListCategory"></mobile:List>


<mobile:Form id="FormResults" runat="server" Title="Search Results">

<mobile:ObjectList Runat="server" ID="ObjectListResults">






1. Continue working with the Web site you created in the previous exercise.

2. Add the Northwind database to the App_Data folder. You can copy this database from the installed samples.

3. Open your site’s Web.config file. Navigate to the <connectionStrings> element. Add markup to connect to the Northwind database. Your markup should look as follows:


<add name="NorthwindConnectionString" connectionString="Data Source=.\SQLEXPRESS;

AttachDbFilename=|DataDirectory|\northwind.mdf; Integrated Security=True;User Instance=True" providerName="System.Data.SqlClient"/>


4. Open the code-behind fi le for the Default.aspx page. Add the following bits of code:

- A private, class-level variable called _cnnstring for getting the database connection string

- A private function called getproducts that loads product data from the database and returns a DataTable object

- A private function called getcategories that loads category data from the database and returns a DataTable object

Your code should look similar to the following:

using System;

using System.Data;

using System.Data.SqlClient;

using System.Configuration;

public partial class _Default : System.Web.UI.MobileControls.MobilePage


private string _cnnString = ConfigurationManager.ConnectionStrings[ "NorthwindConnectionString"].ToString();

private DataTable GetProducts()


SqlDataAdapter adp = new SqlDataAdapter( "select * from products", _cnnString);

DataSet ds = new DataSet("products");

adp.Fill(ds, "products");

return ds.Tables["products"];


private DataTable GetCategories()


SqlDataAdapter adp = new SqlDataAdapter("SELECT * FROM categories", _cnnString);

DataSet ds = new DataSet("categories");

adp.Fill(ds, "categories");

return ds.Tables["categories"];



5. Add an event handler for the ListMainMenu control’s ItemCommand to the code-behind page. In Visual Basic, you can add the event handler as you would normally. However, in C#, you might not get the event button on the Properties window. Therefore, you might need to add the attribute setting, OnItemCommand=”ListMainMenu_Item-Command” to the markup for the ListMainMenu control.

This control’s event is used to set the active form based on the user’s search selection (by name, by ID, by category). If category is selected, bind the ListCategory control to the Categories table using the GetCategories method. Your code should look similar to the following:

protected void ListMainMenu_ItemCommand(object sender ,

System.Web.UI.MobileControls.ListCommandEventArgs e)


if (e.ListItem.Value == "1")


//search by name

this.ActiveForm = FormSearchName;


else if (e.ListItem.Value == "2")


//search by ID

this.ActiveForm = FormSearchId;


else if (e.ListItem.Value == "3")


//search by category

this.ActiveForm = FormSearchCategory;

ListCategory.DataSource = GetCategories();

ListCategory.DataTextField = "CategoryName";

ListCategory.DataValueField = "CategoryID";




6. The next step is to do the actual search based on user selection. In this case, you will return all the product data from the database and filter it on the server. This simplifies the lab. In a real scenario, you would either create separate search methods to get only the data you need or retrieve and cache this data on the server.

To respond to search requests, you need to add the following event handlers to your code.

- CommandSearchId Click handler Here you get the product data but filter it based on the user-entered ID value.

- CommandSearchName Click handler Again, you get the product data and filter the results. This time you do so based on the product name.

- ListCategory ItemCommand handler This time you get the product data and filter it based on the selected product category.

In addition, you need to add a method called ShowResults to your code-behind file. This method should be called at the end of each of the preceding events to display the results in the ObjectListResults control and set the active form to FormResults. The code for these three event handlers and ShowResults should look as follows:

protected void CommandSearchId_Click(object sender, EventArgs e)


DataTable products = GetProducts();

products.DefaultView.RowFilter =

String.Format("ProductID = {0}", TextBoxSearchId.Text);



protected void CommandSearchName_Click(object sender, EventArgs e)


DataTable products = GetProducts();

products.DefaultView.RowFilter =

String.Format("ProductName like '{0}%'", TextBoxSearchName.Text);



protected void ListCategory_ItemCommand(object sender,

System.Web.UI.MobileControls.ListCommandEventArgs e)


DataTable products = GetProducts();

products.DefaultView.RowFilter =

String.Format("CategoryID = {0}", e.ListItem.Value);



private void ShowResults(DataTable data)


ObjectListResults.DataSource = data.DefaultView;

ObjectListResults.LabelField = "ProductName";


this.ActiveForm = FormResults;


Depending on how you add these events to your code, you might have to wire them up to their controls. There are multiple ways to do so. An easy way is to use the markup for the given control’s event, for example, OnClick=”CommandSearchName_Click” for the CommandSearchName Click event and OnItemCommand=”ListCategory_ItemCommand” for the ListCategory control.

7. Run the mobile Web form in both Internet Explorer and a mobile emulator. Test each option by entering data or selecting a value.