When ASP.NET 1.0 was released, it revolutionized Web application development by providing a rich set of features that were aimed at increasing developers’ productivity. Now with ASP.NET 2.0 (code-named Whidbey), Microsoft increased the bar to a much higher level by providing excellent features out-of-the-box that are targeted towards reducing the code required for building Web applications.
These new enhancements arm the developers with a powerful platform that can make a significant impact in the way Web applications are developed and maintained. Apart from increasing the productivity of the developers, ASP.NET 2.0 also provides a number of excellent features, such as easy administration and management of the platform, an extensible platform that can be easily customized to meet the requirements of any enterprise, increased performance, and so on.
In this article, I will present you with the features of this new improved platform and to help you understand how you can use it to design, develop, and deploy enterprise-class Web applications. We will start off our discussion by taking a look at the changes to the ASP.NET Page architecture.
Changes to the Page Architecture
One of the significant improvements in ASP.NET 2.0 is the support for Single-Page architecture. This means that any Web page that you create can contain the server-side logic in the same page itself, instead of storing it in a separate .aspx.vb or .aspx.cs file, as is the case with current .NET version. The server-side code will be contained in a script block with a runat=server attribute. However, the object model and event model are still the same as in the current code-behind model.
Another important feature is the ability to request a Web form (.aspx file) from a browser without having to compile the code even once. When the page is first requested, ASP.NET compiles the page on the fly, dynamically generating the assembly. This makes it possible for you to resort to the “Just Hit Save” programming model (as similar to ASP) wherein you just develop the page and test the page without having to compile it.
As mentioned before, by default, ASP.NET Web pages and code files are compiled dynamically when a first request is made to the page. After the initial compilation, the compiled page is cached; the cache is used to satisfy the subsequent requests for the same page. Even though this approach is flexible, you should note that that when the page is requested for the first time, it requires a bit of extra time to compile the code. You can avoid this overhead by leveraging a new feature known as Precompilation; by using this feature, you can compile an ASP.NET Web site before making the Web site available to the users.
By using Precompilation, you also can catch all the compilation errors before deploying the application onto the production servers. ASP.NET 2.0 provides the following two options for precompiling a site.
- In-place Precompilation—When you perform in-place precompilation, all ASP.NET files are compiled and stored in the special folder named codegen. The precompilation process follows the same logic that ASP.NET uses for dynamic compilation, also taking into consideration the dependencies between files. During precompilation, the compiler creates assemblies for all executable output and places them in the codegen folder. After the compiled output is created, ASP.NET fulfills requests for pages using the assemblies contained in this folder. One of the important advantages of precompilation is the ability to check the Web site for compilation errors. To precompile a Web application named NorthwindWeb (that is present in the default Web site), you need to enter the following URL in the browser.
This command allows you to precompile the Web site and if there are any compilation errors, they will be displayed in the browser.
- Precompiling a site for deployment—By using this option, you can create a special output that can be deployed to production servers. Once the output is created, you can deploy the output using various mechanisms such as XCOPY or FTP, or Windows installers onto the production servers. To precompile a Web site for deployment, you need to use the aspnet_compiler utility.
Use of Master Pages
ASP.NET 2.0 introduces a new concept known as Master Pages, in which a common base master file is created to provide a consistent layout for all the pages in your application. Once you isolate the look and feel and standard behavior for all the pages in your application, you can move them to a master page. In the master page, you also add placeholders (known as ContentPlaceHolders) for the content (or child pages) to add their custom content. When users request the content pages, the output of the content pages is merged with the output of the master page, resulting in an output that combines the layout of the master page with the output of the content page.
Master pages are saved with the file extension .master. Apart from containing all the contents that are required for defining the standard look and feel of the application, the master pages also contain all the top-level HTML elements for a page, such as <html>, <head>, and <form>. The master pages also contain one or more content placeholders that are used to define regions that will be rendered through the content pages. Let us take a look at an example.
For the purposes of this example, let us create a new page named MasterPageExample.master and add the following lines of code to it.
<%@ master language="C#" %> <html> <head runat="server"> <title>Master Page</title> </head> <body> <form runat="server"> This content is from the Master Page from which the all the pages will be inherited <br /> <b> <asp:contentplaceholder id="MiddleContent" runat="server"> </asp:contentplaceholder> </b> </form> </body> </html>
In the above lines of code, we start by defining a new page directive named master. As the name suggests, this declarative is used to identify that the current page is a master page and prevents the users from requesting the page from a browser. Then, inside the code, we define an element named asp:contentplaceholder, which will be used by all the content pages to render appropriate content that is specific to their pages. Now that we have had a look at the master page, let us look at the content page. To create a content page, let us create a new ASP.NET page named ContentPageExample.aspx and add the following lines of code to it.
<%@ page language="c#" master="~/MasterPageExample.master" %> <script runat="server"> </script> <asp:content id="Content1" contentplaceholderid="MiddleContent" runat="server"> This content is from the child page </asp:content>
The code required for the content page is very simple and straightforward. We start by defining the Page directive. As part of the Page directive, we also specify a new attribute named master that is used to identify the name of master page that we want to use. Since we have already created a master page named MasterPageExample.master, we will specify that as the master file. Next, we have an element named content that is used to associate the contentplaceholder element in the master page with the content page. This is done through the use of the contentplaceholderid attribute. That’s all that is there to creating a master page and using the master page from a content page. Now, if you request the content page from a browser, you will get the following output.
Advantages of Master Pages
Master pages provide a clean approach for encapsulating the common functionality in a centralized location, allowing other pages to inherit from a single master page, thereby reducing the maintenance of the application.
- Master pages make it easy to create one set of controls and code and apply the results to a set of pages. For example, you can use controls on the master page to create a menu that applies to all pages.
- They provide a fine-grained control over the layout of the content pages by allowing you to control how the placeholder controls are rendered.
- Master pages also expose an object model that allows you to customize the master page from individual content pages.
Sharing Code in the Application
Before ASP.NET 2.0, if you were to reference a reusable component from your ASP.NET application, you had to compile the assembly and place it in the bin folder (or place it in the GAC) of the Web application. But now, with ASP.NET 2.0, creating a reusable component is very simple and straightforward. All you need to do is to create the component in a pre-defined subdirectory called Code. Any component placed in this directory will be automatically compiled at runtime into a single assembly. This assembly is automatically referenced and will be available to all the pages in the site. Note that you should only put components in the Code subdirectory.
Creating Web Portals Using Web Parts
There are many times where you would want to allow the users of your Web site to be able to customize the content by selecting, removing, and rearranging the contents of the Web page. Traditionally, implementing this capability required a lot of custom code or you had to depend on third-party products to build a Web site of this nature. To address this shortcoming, ASP.NET 2.0 ships with a Web Parts Framework that provides the infrastructure and the building blocks required for creating modular Web pages that can be easily customized by the users. You can also use Web Parts to create portal pages that aggregate different types of content such as static text, links, and content that can change at runtime. It is also possible for the users to change the layout of the Web parts by dragging and dropping from one place to another, providing a rich user experience.
New Data Controls
One of the limitations of ASP.NET 1.0 is that it did not provide a declarative model for binding data to data-aware controls such as DataGrid, DataList, and Repeater. Now, in ASP.NET 2.0, you have a very powerful and easy-to-use declarative model for binding data directly from the database. To this end, ASP.NET 2.0 provides a number of new data-bound controls. Before we take a look at this new set of controls, let us understand the theory behind this new declarative model. Binding data to data-aware controls requires the following two steps:
- You need to create a data source control that is responsible for reading and writing data from the database. Data source controls encapsulate common functionality such as reading, writing, deleting, and inserting from the database.
- Next, you need to bind the data-bound controls, such as a dropdown list or a checkbox, to the data source control.
ASP.NET 2.0 provides the following data source controls:
- <asp:SqlDatasource>—This data source control is designed to work with SQL Server, OLE DB, ODBC, and Oracle databases. As the name suggests, this control enables you to select, update, delete, and insert data using SQL commands. In the later section, we will see an example of this control.
- <asp:ObjectDatasource>—For reasons of clean separation and easier maintenance, most of the Web applications are constructed using N-Tier principles. When you work with an N-tier application, it is most likely that your middle layer objects may return complex objects that you have to process in your ASP.NET presentation. Keeping this in mind, Microsoft has created this new control that allows you to seamless integrate the data returned from the middle layer objects with the ASP.NET presentation layer.
- <asp:AccessDatasource>—As you can see from the name, this control is designed to work with Access databases.
- <asp:XmlDatasource>—This control allows you to bind to XML data, which can come from a variety of sources such as an external XML file, a DataSet object, and so on. Once the XML data is bound to the XmlDataSource control, this control then can act as a source of data for data-bound controls such as TreeView and Menu.
- <asp:DataSetDatasource>—The DataSetDataSource control allows you to easily switch between an XML and a relational view of the data. By using this control, you also can specify an XSLT Transformation to restructure the XML data.
- <asp:SitemapDatasource>—This control allows the users to navigate between the pages in the Web site. To perform this, you need to create an XML file named app.sitemap that lays out the pages of the site in a hierarchical fashion. Once you have the site hierarchy in the app.sitemap file, you then can data-bind the SitemapDataSource control with the app.sitemap file. After that, the contents of the SitemapDataSource control can be bound to data-aware controls such as TreeView and so on.
Apart from the above data source controls, ASP.NET 2.0 also provides the following data-bound controls that you will normally use to display data that is contained in the data source controls:
- <asp:gridview>—This control is the successor to the DataGrid control that was part of ASP.NET 1.0. Like the DataGrid control, this control is used to display the values of a data source in a table. In a grid view control, each column represents a field, while each row represents a record. As you would expect, you can bind a grid view control to a SqlDataSource control, as well as any data source that implements the System.Collections.IEnumerable interface. This control also can adaptively render data for different types of devices and browsers that are making the request.
- <asp:detailsview>—As the name suggests, this control can be used in conjunction with the grid view control and can be used to display the details of a specific record in the data source.
The following example demonstrates how to use the combination of SqlDataSource and GridView controls to retrieve and display data from the Categories table in the Northwind database without writing even a single line of code.
<%@ page language="C#" %> <script runat="server"> </script> <html> <head id="Head1" runat="server"> <title>Data Binding using SqlDataSource control</title> </head> <body> <form id="Form1" runat="server"> Enter the Category ID: <asp:textbox id="CategoryID" runat="server"></asp:textbox> <asp:button runat="server" id="btnGet" text="Get Category"/> <asp:sqldatasource id="categoriesSource" runat="server" connectionstring="server=localhost;database=northwind; uid=sa;pwd=" selectcommand="SELECT * From Categories Where [email protected]"> <SelectParameters> <asp:ControlParameter defaultvalue="1" Name="CategoryID" ControlId="CategoryID" PropertyName="Text"/> </SelectParameters> </asp:sqldatasource> <asp:gridview datasourceid="categoriesSource" runat="server" id="gridCategories"> </asp:gridview> </form> </body> </html>
In the above code, we start by declaring a button control named btnGet. This control is just used to perform a post-back to the server so that the SQL query can be re-evaluated. Then, we declare a SqlDataSource control named categoriesSource. While declaring the SqlDataSource control, we also specify the ConnectionString and the SQL statement to be executed as attributes. As you can see from the SelectCommand attribute value, we specify a placeholder for the CategoryID parameter by using the @CategoryID identifier. Then, we specify the value for the SQL query parameter by using the SelectParameters template. The combination of ControlId and PropertyName is used to specify the name of the control and the property of the control (that will return the value of the textbox in this case). This allows the category ID entered in the CategoryID textbox to be used as an argument to the SQL query. For the first time, we specify the default value of 1 for the CategoryID by using the defaultvalue property.
When you execute the above code, you will see an output that is somewhat similar to the following.
By default, when the above page comes up, it displays the details of the category that is identified by CategoryID 1. After that, if you enter a category ID in the textbox and click on Get Category, it will display the details of the category based on the value entered.
Advanced Features of Data Controls
Some of the advanced features provided by the data controls are as follows:
- By handling all the low level tasks such as opening connection to the database, executing a command, retrieving the results of the command, and closing the connection, data source controls allow you to focus on the core business logic of the application.
- Apart from providing a powerful declarative model for creating rich data-driven Web applications, ASP.NET 2.0 also allows you to access the same set of features programmatically, retaining the flexibility of the database features.
- By using the declarative model provided by data controls, not only you can execute stored procedures but 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.
- Another excellent feature of data source controls is that they 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.
The Cache API introduced with ASP.NET 1.0 was a powerful feature that can be immensely useful in increasing the performance of a Web application. The Cache API also allows you to invalidate items in the cache based on some pre-defined conditions such as change in an XML file, change in another cache item, and so on. By using this feature, you can remove or invalidate an item from the cache when the data or another cached item changes. However, the Cache API in ASP.NET 1.x versions did not provide a mechanism to invalidate an item in the cache when data in a SQL Server database changes. This is a very common capability that many Web applications require.Now, with ASP.NET 2.0, Microsoft has introduced a new cache invalidation mechanism that works with SQL Server as well. By using this new capability, you can invalidate an item in the Cache object whenever the data in a SQL Server database changes. This built-in cache invalidation mechanism works with SQL Server 7.0 and above. However, with SQL Server 7.0 and 2000, only Table-level cache invalidation mechanism is supported.
The next release of SQL Server (code-named Yukon) also will feature a row-level cache invalidation mechanism providing a finer level of accuracy over the cached data. To enable the SQL Server-based cache invalidation mechanism, you need to do the following:
- Add the OutputCache directive to the top of the page. The OutputCache directive also contains a new attribute named sqldependency and the value supplied to this attribute should be of the form <DatabaseName>:<TableName>. In this example, we are using the Employees table in the Northwind database.
<%@ OutputCache duration="3600" varybyparam="none" sqldependency="Northwind:Employees" %>
- The next step is to add the appropriate settings to the web.config file. After modification, the web.config file should look like the following:
<?xml version="1.0"?> <configuration> <connectionStrings> <add name="Northwind" connectionString="server=localhost;database=Northwind; UID=sa;PWD="/> </connectionStrings> <system.web> <cache> <sqlCacheDependency enabled = "true" pollTime = "1000" > <databases> <add name="Northwind" connectionStringName="Northwind" pollTime = "1000"/> </databases> </sqlCacheDependency> </cache> </system.web> --------- --------- </configuration>
By using the above configuration entries, we specify the name of the database in which we want to enable the cache notification mechanism.
- After that, we need to enable the specific tables in the Northwind database for notification. You can perform this using any one of the following two ways:
- Using the aspnet_regsqlcache
- Using the EnableTableForNotifications method of the SqlCacheDependencyAdmin class. Once we configure the table to send notifications, any time data in the table changes, it notifies the ASP.NET to invalidate the specific item in the cache.
There are many times when you would want to store and present information that is unique to a user. When a user visits your site, you can use the information that you have already collected from the user to present the user with a personalized version of your Web application. Traditionally, implementing this personalization capability required you to go through the following steps:
- You must store the information about the user using a unique user identifier. This information is required to recognize the user when they visit again.
- You need to fetch the user information as needed.
- Finally, present the user with the personalized content.
To simplify your applications, you can use ASP.NET personalization, which can abstract all of the above complexities from you. In ASP.NET personalization, information about a specific user is stored in a persistent format. ASP.NET personalization allows you to manage user information easily without requiring you to create and maintain your own database. In addition, the personalization system makes the user information available using a consistent, easy-to-use, strongly typed API that you can access from anywhere in your application. You also can store objects of any type in the personalization system, including user information, user preferences, or business information. The personalization system uses a generic storage system for storing the data and makes that data available to the users in a type-safe manner. By default, ASP.NET 2.0 uses SQL Server as the storage mechanism.
One of the important security enhancements made in ASP.NET 2.0 is the new role management system that helps you to manage authorization, allowing you to specify the resources that users in your application are allowed to access. ASP.NET Role management system lets you treat groups of users as a unit by assigning users to roles such as manager, sales, member, and so on. In Windows, you create roles by assigning users to groups such as Administrators, Power Users, and so on. After you have established roles, you can create access rules in your application. For example, your site might include a set of pages that you want to display only to members. Similarly, you might want to show or hide a part of a page based on whether the current user is a manager. With roles, you can establish these types of rules independently of individual application users.
In this new role management system, the provider of the roles is completely separated from the role management API. ASP.NET supports the following providers to maintain role information:
- Access—In this case, role information is stored in a Microsoft Access database and this is the default provider.
- SQL Server—Here, the role information is stored in a SQL Server database.
- Windows—In this case, the role information is based on Windows accounts.
ASP.NET provides a number of new controls that are built on top of the ASP.NET role management system. Some of the new controls are as follows:
- <asp:login>—Provides a standard login capability that allows the users to enter their credentials
- <asp:loginname>—Displays the name of the logged-in user
- <asp:loginstatus>—Indicates whether the user is authenticated or not
- <asp:loginviewv—Provides various login views depending on the selected template
- <asp:passwordrecovery>—Capability for e-mailing the users their lost password
Themes are rich skin templates that allow you to define the look of pages and controls, which then can be applied to all the pages in your application, providing a consistent look and feel for the entire application. Themes are extremely flexible in that they can be applied to an entire Web application, to a page, or to an individual control.
Theme files are stored with the extension .skin and all the theme files for a Web application are stored in the special folder named Themes. ASP.NET ships with several themes out of the box. However, it also is possible for you to create custom theme files. To create a custom theme and apply it to a specific page, you need to go through the following steps:
- Create a file with the extension .skin and add all the controls (that you want to use in a page) and their style properties. Remember to remove the ID attribute in all of the controls. For example, you can use the following code to define the theme for a button control.
<asp:Button runat="server" BackColor="Black" ForeColor="White" Font-Name="Arial" Font-Size="10px" />
- Once you have created the .skin file, you then can apply that theme to all the pages in your application. To apply the theme to a specific page, all you need to do is to add the Theme attribute to the Page directive, as shown below.
<%@Page theme="Testheme" %>
It also is possible for you to programmatically access the theme associated with a specific page by using the Page.Theme property. Even though themes are very similar to CSS Style Sheets, they differ from style sheets in the following ways:
- Themes can define many properties of a control or page, not just a specific set of style properties.
- Themes can also include external files such as graphics and so on.
In this section, we will browse through the remaining important features of ASP.NET 2.0.
- Within Whidbey, Intellisense (Statement Completion) is now available in the server side <script> blocks. It also is available in <% %> blocks, and in Page directives (starting with the letter @).
- ASP.NET 2.0 is 64-bit enabled.
- ASP.NET 2.0 will be almost completely backward compatible with ASP.NET 10.0 and ASP.NET 1.1.
- ASP.NET 2.0 comes bundled with a built-in development Web server, obviating the need to install IIS.
- You also can define a single class in multiple files; at runtime they will be compiled together to create a single assembly.
- With ASP.NET 2.0, you can perform postback across pages, meaning that you can postback from one page to another page. To perform cross-postback when the user clicks a button, set the PostTargetUrl property on the button control to the URL of the new page. From within the new page, you can reference the original page by using the PreviousPage property.
- In this release, all the <asp:> built-in controls will provide native support for mobile devices, obviating the need to learn a new <mobile:> programming language to program for mobile devices.
- In the health monitoring space, it will provide support for automated notification when exceptions occur in the Web site. For example, ASP.NET can automatically send an e-mail to the admin when an exception occurs in the Web site.
As you can see, ASP.NET 2.0 provides a number of new productivity enhancements for the developers to be excited about. The features we looked at in this article represent just the tip of the iceberg. But, they should help you get a kick start on this new and feature-rich platform. Once you get familiar with this new platform, you will have a rich set of tools and techniques that can go a long way in making the development of a Web application a breezy experience.
About the Author
Thiru Thangarathinam has six years of experience in architecting, designing, developing, and implementing applications using Object Oriented Application development methodologies. He also possesses a thorough understanding of the software life cycle (design, development, and testing). He holds several certifications, including MCAD for .NET, MCSD, and MCP. Thiru is an expert with ASP.NET, .NET Framework, Visual C# .NET, Visual Basic .NET, ADO.NET, XML Web Services, and .NET Remoting and holds. Thiru has authored numerous books and articles. He can be reached at [email protected].
# # #