Shrink ASP.NET Code by 70 Percent
ASP.NET 2.0's new features let you create and maintain data-driven Web apps with 70 percent less code than you needed with ASP.NET 1.0
Technology Toolbox: ASP.NET
ASP.NET 2.0 can reduce the number of lines of code an ASP.NET application requires by a whopping 70 percent. ASP.NET 2.0's new data source controls and data-aware controls go a long way towards producing this result. I'll show you how to harness the new features in your own applications.
ASP.NET 1.0 lacked a declarative model for binding data to data-aware controls such as DataGrid, DataList, and Repeater. ASP.NET 2.0 fixes this with a declarative model for binding data directly from the database. The new data controls' advanced concepts include enabling caching on a data source control and declaratively passing values to the SQL statement parameters directly from a control value.
You begin binding data to data-aware controls by creating a data source control that encapsulates common functionality such as reading, writing, deleting, and inserting from the database. Once you have the data in the data source control, you can bind the data to data-aware controls, such as a dropdown list or a checkbox.
ASP.NET 2.0 provides half a dozen data source controls. <asp:SqlDatasource> enables you to select, update, delete, and insert data using SQL commands. It works with SQL Server, OLE DB, ODBC, and Oracle databases. I'll show you an example of this control later on.
<asp:ObjectDatasource> allows you to integrate the ASP.NET presentation layer seamlessly with data returned from middle-layer objects. This helps you build clean separation and easier maintenance into your n-tier Web apps. Most Web apps employ an n-tier architecture, with middle-layer objects returning complex objects you have to process in your ASP.NET presentation. That's where this control comes in.
<asp:AccessDatasource> works with Access databases. <asp:XmlDatasource> allows you to bind to XML data, which can come from a variety of sources such as an external XML file or a DataSet object. Once the XML data is bound to the XmlDataSource control, this control can then act as a source of data for data-bound controls such as TreeView and Menu.
<asp:DataSetDatasource> lets you switch between XML and relational data views. This control also lets you specify an XSLT Transformation to restructure the XML data. <asp:SitemapDatasource> lets users navigate between pages in a Web site. You implement this control by first creating an XML file named app.sitemap that lays out the site's pages hierarchically. Having the site hierarchy in the app.sitemap file enables you to databind the SitemapDataSource control with the app.sitemap file. After that, you can bind the contents of the SitemapDataSource control to data-aware controls such as TreeView.
ASP.NET 2.0 complements these six data source controls with a pair of data-bound controls used to display data contained in the data source controls. <asp:gridview> displays the values of a data source in a table (as did ASP.NET 1.0's DataGrid control). Each column represents a field, and each row a record. You can bind a GridView control to a SqlDataSource control and to any data source that implements the System.Collections.IEnumerable interface. This control can also render data adaptively for different types of devices and browsers that make the request. You can use <asp:detailsview> in conjunction with the GridView control, and you can display the details of a specific record in the data source.
Create a Data-Driven Web App
Now I'll show you how to put these new features to work as you create a data-driven Web app. I'll use the categories and product tables in SQL Server's venerable Northwind sample database for this example, displaying the categories in a dropdown list. I'll use the selected category in the dropdown list to display all the products in that category in a GridView control (see Listing 1).
The coding starts with declaring a SqlDataSource control named categoriesDataSource. Use this control to get category information from the Northwind database's Categories table. You also specify the ConnectionString and the Sql statement to be executed as attributes.
Use the SelectCommand attribute to specify the name of a stored procedure that executes when the page executes. The stored procedure usp_GetCategories simply returns all the categories from the Categories table. The SqlDataSource control can return data in two forms: as a dataset or as a data reader. A dataset contains all the data in memory, allowing you to manipulate the data in various ways after retrieving it. A data reader provides a read-only cursor that can fetch individual records. You choose between a dataset and a data reader by setting the data source control's DataSourceMode property.
Now declare a DropDownList named ddlCategoriesList and bind it to the Categories data source. Specify the data source for a control by setting the datasourceid attribute to an appropriate value. Then specify the datatextfield and datavaluefield attributes for the dropdown list. That's all there is to creating a data source control and binding it to a data-aware control. You can accomplish this declaratively without writing one line of code.
So far I've shown you how to display all the dropdown list categories. Now I'll move on to displaying all the products in the selected category. This requires declaring one more SqlDataSource control and naming it productsDataSource. In the SelectCommand attribute of the productsDataSource, use the @CategoryID identifier to specify a placeholder for the CategoryID parameter.
Use the SelectParameters template to specify the value for the sql query parameter. Retrieve the value of the category identifier using the DropDownList's SelectedValue property. Use the ControlParameter template to set the ControlId and PropertyName attributes. This lets you use the category ID selected in the Categories dropdown list as an argument to the sql query. You also use the defaultvalue property to set the default value of 1 for the CategoryID. You'll use this default value when the page is requested for the first time.
In this example, I use the ControlParameter template to specify input values for the parameterized query specified in the SelectCommand attribute. Apart from ControlParameter, you can also use any one of these parameter objects to provide values for the parameterized query: QueryStringParameter, SessionParameter, CookieParameter, or FormParameter. QueryStringParameter lets you get the value of the parameter from a key-value combination in the current query string. SessionParameter lets you get the parameter value from a specified Session variable. CookieParameter lets you get the parameter value from a specified cookie. FormParameter lets you get the parameter value from any property exposed in the current Request object, such as posted control values. The FormParameter object is a more general version of the QueryStringParameter and CookieParameter objects.
When you execute your code, you'll see a display that lets you select a given category and get a table output (see Figure 1).
Bind Objects Using ObjectDataSource
So far you've seen how to bind the data from a SQL Server table to a SqlDataSource control, then display it in a GridView control. Now I'll show you how to bind the data returned from an object's method directly to the controls in the ASP.NET page.
When you're creating a distributed ASP.NET app, you're likely to split your app into multiple layers, such as presentation, business, and data access. This approach produces extensible apps you can maintain and enhance easily. ASP.NET complements this type of application design with a new ObjectDataSource control you can use to directly bind an object's methods to data-bound controls such as GridView, DataList, and DropDownList. You get clean code separation and encapsulationand you don't have to write data access layer code in the presentation layer. Now that you (hopefully) understand the theory behind the ObjectDataSource control, you can create the component you'll use for databinding.
Start building a component or class in ASP.NET 2.0 by creating a folder named "Code" and placing all your components in that folder. Once the components are inside the Code folder, they'll be referenced automatically and made available to all the pages in your Web app. For the purposes of this example, I'll create a Customers class and place that in the Code folder (see Listing 2).
Declare a class named Customers. The Customers class contains only one methodGetCustomers. This method returns the details of the customers from the Customers table in the form of a SqlDataReader object. Once you've created the GetCustomers method, you write the code required for displaying the output of the GetCustomers method in a GridView control:
<%@ page language="C#" %>
<title>Object DataSource Example</title>
Your data display code leads off by declaring an ObjectDataSource control. You need to set two important attributes for this control: TypeName and SelectMethod. TypeName specifies the name of the class you want to use; SelectMethod specifies the name of the method in the class you want to use. Declare a GridView control and set the DataSourceID of the GridView control to the ID of the ObjectDataSource control. That's all there is to displaying the output of a method using a GridView control. Its output is a neat little table.
Once you've mastered the basics, you'll want to explore some of the advanced features provided by the data controls. Most importantly, data source controls let you focus on an application's core business logic while it handles all the low-level tasks, including opening the database connection, executing a command, retrieving the results of the command, and closing the connection.
I've discussed using ASP.NET 2.0's declarative model for creating data-driven Web apps. ASP.NET 2.0 also lets you access the same set of features programmatically, retaining the flexibility of the database features. Similarly, the declarative model provided by data controls lets you execute more than stored procedures; you can also pass parameters to the stored procedures. For example, you can retrieve the value of a textbox and pass it as a parameter to a stored procedure that can return appropriate rows depending on the value entered in the textbox.
I like the fact that data source controls all offer the same basic object model and API for you to program against, reducing the learning curve required for understanding the different types of controls. Go ahead and fire up ASP.NET 2.0. If you do data-driven apps, you'll be glad you did.
About the Author
Thiru Thangarathinam works at Intel in Chandler, Ariz. He specializes in architecting, designing, and developing .NET-based distributed enterprise-class applications. He has coauthored several books on .NET-related technologies. He has also been a frequent contributor to leading technology-related publications. Reach him at [email protected].