New Files and Folders in ASP.NET 2.0

By Thiru Thangarathinam

With the release of ASP.NET 2.0, Microsoft has greatly increased the power of ASP.NET by introducing a suite of new features and functionalities. As part of this release, ASP.NET 2.0 also comes with a host of new special files and folders that are meant to be used to implement a specific functionality. In this article, we will get an understanding of these new files and folders by examining them in detail. Along the way, we will also look at examples that demonstrate how to utilize those files and folders to create ASP.NET 2.0 applications.


Introduction


Since the introduction of the powerful server side web technologies such as ASP, JSP, ASP.NET, developers have shown more interest in building web applications rather than in windows applications. The factors that attracted the developers toward web applications can be summarized as follows:

  • A web application is ubiquitous, making it accessible in all the places where an internet connection is available.
  • The second and most important factor is the deployment. With web applications, there is no need to deploy any software on the client side. All the client application needs is just the browser. This makes it possible for the developers to easily deploy updates to the existing web application without impacting the client machines.

ASP.NET 2.0 raises the bar of the server side Web development by providing a number of new features. These new features are geared toward either enhancing an existing feature or adding a completely new feature through the introduction of new files and folders. For example, in ASP.NET 2.0, Web sites can include an App_Code folder into which site developers can put source code that is then compiled automatically as part of the Web site, making it unnecessary to compile components or controls before using them in a site. Similar to App_Code folder, there are a number of new files and folders introduced with ASP.NET 2.0. This article will specifically focus on these new files and folders by discussing them in detail and providing examples. We will start this exploration by looking at the master files in ASP.NET 2.0.



Master Files


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. With ASP.NET 2.0, you isolate the look and feel and standard behavior for all the pages in your application by moving 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 are 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. In this article, we will take a look at the theory behind the master pages and understand how to leverage this feature in a web application. Along the way, we will also demonstrate some of the advanced concepts of master pages such as accessing master page controls from content pages, nesting master pages, and configuring master page for an entire web application and so on.

Master Pages Architecture

When using Master pages in your ASP.NET web application, you will create a Master Page for the site layout and design and create Content Pages for each content resource, and then connect the content pages to the master pages using the various new controls and attributes supplied by ASP.NET 2.0. After they are connected, as users navigate to the content pages, ASP.NET will serve up the page by merging the content from the master page with the content of the content pages.

As mentioned before, the master page defines content areas using the ContentPlaceHolder control, and the content pages place their content in the areas identified by the ContentPlaceHolder control in the master page. Pages that use a master page to define the layout can place content only in the areas defined by the ContentPlaceHolder, thus enabling a consistent site design. 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. Now that we have understood the concepts behind the master pages, let us take a look at an example.

Walkthrough of Creating a Master Page and a Content Page

In this section, we will consider an example to understand how we can take advantage of the master pages to provide the consistent look and feel throughout all the pages in the web application. In Visual Studio 2005, you can create a master page using the Add New Item dialog box, and then by selecting Master Page from the list. Once the master page is created, we will modify the master page to look like the following code.

<%@ Master Language="C#"%>
<html xmlns="http://www.w3.org/1999/xhtml" >

<head runat="server">
    <title>Master Page</title>
</head>
<body>

<form id="form1" runat="server">

<table bgcolor="#cccc99" id="header" style="WIDTH: 100%; HEIGHT: 80px"
    cellspacing="1" cellpadding="1" border="1">

    <tr>
        <td width="100%" style="TEXT-ALIGN: center">
            This is the header from the Master Page
        </td>
    </tr>

</table>
<b/>
<table bgcolor="#99cc99" id="leftNav" style="WIDTH: 108px; HEIGHT: 100%"
    cellspacing="1" cellpadding="1" border="1">

    <tr>
        <td style="WIDTH: 100px"> Left Navigation
        </td>
    </tr>
</table>
<table bgcolor="#ccff99" id="mainBody" style="LEFT: 120px; VERTICAL-
    ALIGN: top; WIDTH: 848px; POSITION: absolute; TOP: 94px; HEIGHT: 100%"
    border="1">

    <tr>
        <td width="100%" style="VERTICAL-ALIGN: top">
            <asp:contentplaceholder id="middleContent"
                runat="Server"></asp:contentplaceholder>
        </td>

    </tr>
</table>
</form>

</body>
</html>

The above code listing looks similar to a normal ASP.NET page and contains simple HTML and ASP.NET controls. The main difference between this page and a standard ASP.NET page is the use of the Master directive and the file suffix .master. The important thing to note is the use of the ContentPlaceHolder control, which dictates where content pages can insert content. The id attribute uniquely identifies the placeholder, allowing more than one placeholder to be in a master page. The master page can have code as well as content, allowing the master page to render contents dynamically. In the code, we have defined a header and a left navigation bar as well as the body of the page using HTML table elements. Inside the body table, we have also defined an asp:contentplaceholder control, which will be linked in all the content pages so that the content pages can insert their own content. Any content page that uses the above master page will automatically inherit the header, left navigation and the body from the master page.

Now that we have created the master page, let us create a content page that can leverage the master page. To create a content page using Visual Studio 2005, select Web Form from the Add New Item dialog box and select the Select master page check box at the bottom of the page. This is shown below:

Clicking Add in the above dialog box will result in the Master Picker dialog box being displayed. As you can see from the below screenshot, the master selection dialog box displays all the master pages available in the Web application.

After the content page is created, modify it to look like the following code.

<%@ Page Language="C#" MasterPageFile="~/MyMaster.master"
    Title="Content Page" %>

    <asp:Content ID="Content1" ContentPlaceHolderID="middleContent"
        Runat="Server">
    <asp:label runat="server" id="lblMessage">

        This content is from the content page
    </asp:label>
</asp:Content>

The code required for the content page is very simple and straightforward. Since we have already selected the master page at the time of creating the page, Visual Studio has already added a special attribute named master as part of the Page directive. This attribute is used to identify the name of master page that we want to use. Then we define an asp:content control and link that up to the master page’s asp:contentplaceholder using the contentplaceholderid attribute.

Now that we have created the content page, let us test it by navigating to it using the browser. This will result in an output that is somewhat similar to the below screenshot.


Web.SiteMap


In ASP.NET 2.0, you represent the navigation structures for a Web site in a file named Web.sitemap. A Web.sitemap file contains a single top-level siteMap element. Nested within the siteMap element is at least one siteMapNode element. There must always be a top-level siteMapNode within a site map. The Site Navigation feature requires a single root siteMapNode to ensure that you will always converge on a single well-known node when walking up through the hierarchy of the nodes. You can nest as many siteMapNode elements beneath the root siteMapNode element as needed. Additionally, you can nest siteMapNode elements to any arbitrary depth.

The siteMapNode element usually contains a Url, Title and Description attribute. The Url attribute indicates a virtual path that corresponds to a page in your application. It can also contain paths to pages in other applications, or URLs that point at completely different web sites. It is recommended that you use relative paths when specifying the Urls in the web.sitemap file. The Title attribute is used to display the textual content when rendering UI for navigational data. For example, the SiteMapPath control uses the Title attribute to display the text of the hyperlinks in the control. If the siteMapNode contains a Description attribute, that information will be used to display tooltips or ALT text.

Once you have the site navigation structure available in the web.sitemap file, you can then consume that information using the following two steps.

  • First, you need to add a SiteMapDataSource control to your page. This control will automatically consume the contents of the web.sitemap file and make it readily available for the hierarchical data bound controls.
  • Second, you bind the data bound controls such as SiteMapPath, TreeView and Menu to the SiteMapDataSource control and then display the site navigation information.

Now that we have had a look at the steps involved in utilizing a Web.sitemap file, let us look at an example that exercises these concepts.

Displaying Site Navigation Data from the Web.sitemap File

In this example, we will use the TreeView control to display hierarchical information about the site structure using the contents of the Web.sitemap file. For the purposes of this example, add a new Web.sitemap file to the site and modify it to look as follows:

<?xml version="1.0" encoding="utf-8" ?>

<siteMap>
<siteMapNode title="Default" description="Home" url="Default.aspx" >
    <siteMapNode title="Members" description="Members" url="Members.aspx">

        <siteMapNode title="My Account" description="My Account"
            url="MyAccount.aspx" />
        <siteMapNode title="Products" description="Products"
            url="Products.aspx" />

    </net/codeguru-sitemap/Node>
    <siteMapNode title="Administration" description="Administration"
        url="~/Admin/Default.aspx">
        <siteMapNode title="Customer" description="Customer Admin"
            url="~/Admin/Customer/default.aspx" />

        <siteMapNode title="Products Admin" description="Products Admin"
            url="~/Admin/ProductsAdmin.aspx" />
    </net/codeguru-sitemap/Node>
</net/codeguru-sitemap/Node>
</net/codeguru-sitemap/>

As you can see, the Web.sitemap file specifies the list of nodes that specifies the navigation structure of the site, which can be completely independent of the site folder layout or other structure.

Let us create a new Web page named SiteNavigation.aspx and modify its code to look like the following.

<%@ Page Language="C#" %>
<html xmlns="http://www.w3.org/1999/xhtml" >

<head runat="server">
    <title>Site Navigation</title>
</head>
<body>

<form id="form1" runat="server">

<div>
    <asp:SiteMapDataSource ID="SiteMapDataSource1"
        Runat="server"/>
    <asp:TreeView ID="TreeView1" Runat="server"
        DataSourceID="SiteMapDataSource1"
        ExpandDepth="2" ShowExpandCollapse="False"
        NodeIndent="10">

        <LevelStyles>
            <asp:TreeNodeStyle Font-Bold="True"
                Font-Underline="False"/>
            <asp:TreeNodeStyle Font-Underline="False" />

            <asp:TreeNodeStyle Font-Size="X-Small"
                Font-Underline="False" />
        </LevelStyles>
        <NodeStyle ChildNodesPadding="10" />

    </asp:TreeView>
</div>
</form>

</body>
</html>

In the above code, the SiteMapDataSource control is placed in the page and it used as the data source control for the TreeView named TreeView1. The TreeView control also defines the styles for the different node levels. In this example, since we have a SiteMapDataSource placed on the page, it will specifically look for a file with the name Web.sitemap, by default. It will read the contents of the web.sitemap file and consume that information as a data source control. Once the information is available in a SiteMapDataSource control, we can then consume it from a data-bound control. In this example, we have used the TreeView control as a data-bound control. We set the DataSourceID property of the TreeView control to the id value of the SiteMapDataSource. Output produced by the above page in a browser is shown below:



App_Theme Directory


With ASP.NET 2.0, style handling has been simplified to a great extent. ASP.NET 2.0 incorporates a new feature named Themes that not only allows you to apply consistent styles across all the pages in the web site but also allows you to leverage your existing investments in CSS. A theme can consist of a combination of a css file and one or many skin files to control how ASP.NET server controls are rendered. These files are all contained within a folder, the name of which determines the theme. This folder, in turn, resides within a parent App_Themes folder. Any subfolders of the App_Themes folder act as themes for a site. For example, if you have a folder called MyTheme within the App_Themes folder, you can apply that theme to a page using the following declaration.


<%@ page theme="MyTheme" language="C#" %>

Once you place the theme attribute in the page directive, all the controls in that page automatically inherit the theme.

Creating a Theme

In this section, we will understand how to create a theme and subsequently use it in an ASP.NET page. The first step in creating a theme is to create custom skins. To create custom skins, you create .skin files and save them under the theme folder, which represents a specific theme. Skins look a bit like ASP.NET files in that they contain server control definitions, and are used to alter the visual appearance of ASP.NET elements.

Here are the steps to be followed for creating a theme.

  • In Visual Studio 2005, create a new folder named App_Themes by right clicking on the web site name and selecting Add Folder->Theme Folder from the context menu. Note that the name "App_Themes" is a pre-defined one that must only be used to hold custom themes. Once the App_Themes folder is created, Visual Studio 2005 will automatically create a subfolder under that. Name the subfolder as MyTheme. The name of the folder is the name of the theme that will be used in different ASP.NET pages to refer to this theme.

  • Now, right click on the MyTheme folder and select Add New Item from the context menu. In the Add New Item dialog box, select Skin File from the list and enter the name of the file as Label.skin. As you can see from the name of the file, this will be used to hold the style and formatting for a label control. Once the Label.skin is created, add the following code to the Label.skin file.

    <asp:label runat="server" width="300px" height="24px" font-bold="True" font-overline="True" font-size="Medium" forecolor="Green" backcolor="Silver"/>

  • Note that the above code does not contain the id attribute for the label control since that will be specified in the pages that use the themes. The above line of code will automatically apply the specified formatting to any asp:label elements that are placed on a page to which the ControlsTheme is applied. The control definitions must include a runat="server" attribute, but they should never include an id attribute. Also, the style attributes for a control can be set to standard styles, or linked to the styles defined in a CSS sheet.

  • Now that we have created a skin for the label control, let us create a skin file for the button control as well. To do this, again right click on the MyTheme folder and select Add New Item from the context menu. In the Add New Item dialog box, specify the name of the .skin file as Button.skin. After the file is created, modify the file contents to look like the following.

    <asp:button runat="server" forecolor="RoyalBlue" backcolor="Silver" />

  • Now that we have created these custom skins file, we can apply these consistently to all the pages in the Web site thereby providing a consistent look and feel for the entire Web application. Note that we have not specified the id attribute in the control declarations, since the control that is actually inheriting this style will have its own id attribute.

As you have seen, a skin file can be used to apply styling and formatting to any ASP.NET element on a page, but they can’t be used to specify attributes that are non-visual. For example, using the above .skin files, you can’t specify a standard NavigateUrl attribute to be applied to all asp:hyperlink controls on a site. This is a design feature that will help to ensure that the skin files can only be used to apply formatting to a page.

Applying Themes to an ASP.NET Page

Once you create the custom themes, then applying them to individual ASP.NET pages is very simple. All you need to do is to set the new Theme attribute (that is part of the Page directive) to the name of the theme. For the purposes of this example, let us create an ASP.NET Page named ThemeClient.aspx and modify the code in the page to look like the following.

<%@ Page Language="C#" Theme="MyTheme" %>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Theme Example</title>
</head>
<body>

<form id="form1" runat="server">
<div>
    <asp:Label ID="lblDisplay" runat="server">
        This is an example label
    </asp:Label>

    <asp:Button ID="btnDisplay" runat="server" Text="Click here" />
</div>
</form>

</body>
</html>

In the above code, we start by specifying the name of the theme as the value of the theme attribute. Then we have a label control and a button control in the page. As you can see, we haven’t set any style attributes for these controls. But since we have already specified the skins for the button and the label control in the MyTheme folder, the controls in the page will automatically inherit the style settings specified in the skin files. If you navigate to the above page from the browser, you will see the following output.



App_Code Directory


In addition to the App_Themes folder, ASP.NET 2.0 also comes bundled with a number of App_XXX folders, of which App_Code folder is an important folder. App_Code directory is very useful in that it can be used to store all the reusable classes that you want to use from your ASP.NET pages. To utilize the App_Code directory, all you need to do is to create those reusable classes and place them under the App_Code directory. Whenever a change occurs in the App_Code directory, ASP.NET will dynamically recompile these classes and automatically make it available to all the pages in the web site. Note that you should put only classes into the App_Code subdirectory. You should not put pages, web user controls, or other non-code files containing non-code elements into this subdirectory.

Note that App_Code directory is not a replacement for the Bin directory, it just provides a way to store the reusable classes that can be accessed from an ASP.NET page. If you have an assembly (.dll file) that you want to use in your web site, create a Bin subdirectory and then copy the assembly to that subdirectory.

In Visual Studio 2005, if you create a new class using the Website->Add New Item from the menu, you will be prompted with the following dialog box asking you if you want to place the class under the App_Code directory.

Saying Yes in the above dialog box results in the class being created directly under the App_Code directory. Once the class is created, modify the class to look as shown below:

using System;
using System.Data;
using System.Configuration;
using System.Data.SqlClient;

public class Products
{
    public Products()
    {
    }
    public SqlDataReader GetProducts()
    {
        string connString =
            ConfigurationManager.ConnectionStrings["Northwind"].
            ConnectionString;
        SqlConnection sqlConn = new SqlConnection(connString);
        sqlConn.Open();
        SqlCommand sqlCmd = sqlConn.CreateCommand();
        sqlCmd.CommandText =
            "Select ProductID, ProductName, UnitPrice from Products";
        // Create the SqlDataReader object and return it
        SqlDataReader reader = sqlCmd.ExecuteReader();
        return reader;
    }
}

Now that you have seen the implementation of the class, let us look at the code required to consume this from an ASP.NET page.

Consuming the Component from an ASP.NET Page

When you are creating a distributed ASP.NET application, you will most likely split your application into multiple layers such as presentation, business, and data access. This approach will result in an extensible application that can be easily maintained and enhanced over a period of time. ASP.NET 2.0 complements this type of application design by providing a new ObjectDataSource control that can be used to directly bind an object’s methods to data-bound controls such as GridView, DataList, and DropDownList and so on. This approach provides for clean separation and encapsulation of code thereby eliminating the need to write data access layer code in the presentation layer. The following code snippet demonstrates the use of ObjectDataSource control in terms of consuming the output of a middle tier object.

<%@ Page Language="C#" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Products</title>

</head>
<body>

<form id="form1" runat="server">
<div>
    <asp:gridview runat="server"
        DataSourceID="productsSource" id="productsView">
        <alternatingrowstyle backcolor="Silver">

        </alternatingrowstyle>
    </asp:gridview>
    <asp:objectdatasource runat="server" id="productsSource"
        typename="Products" selectmethod="GetProducts">

    </asp:objectdatasource>
</div>
</form>

</body>
</html>

Let us walk through the above lines of code. We start by declaring an ObjectDataSource named productsSource. The ObjectDataSource control exposes two important attributes named TypeName and SelectMethod. The TypeName attribute allows us to specify the name of the class we want to bind this control to. The SelectMethod attribute allows us to specify the name of the select method to invoke in the class. In this example, we specify the previously created Products class and it’s GetProducts () method as the value for the TypeName and SelectMethod attributes respectively. Then we bind the data in this productsSource control to a GridView control named productsView by setting the DataSourceID attribute of the GridView to productsSource. That’s all there is to retrieving the products from the Northwind database and displaying that in an ASP.NET page.

The above screenshot shows the output produced by the page when requested from the browser.



Other App_XXX Directories


In addition to the App_Themes and App_Code directories, ASP.NET 2.0 also consists of the following App_XXX folders:

  • App_GlobalResources – Global resources reside in this folder at the root of the application. All pages, user-controls etc. can access these resources so they typically are used for shared resources.
  • App_LocalResources – Local resources specific to a certain page are defined in a peer-level App_LocalResources folder. You can also programmatically access these resources from within your code.
  • App_WebReferences – This folder acts as the container for storing proxy classes, schemas, and other files associated with using a Web service in your application.
  • App_Data – This folder is reserved for databases (for example, Microsoft Access .mdb files) and is preconfigured with appropriate permissions for the run-time user account.
  • App_Browsers – Browser definition files that ASP.NET uses to identify individual browsers and determine their capabilities.

The content of application folders, except App_Themes, is not served by IIS, but can be accessed from application code.



Precompiling a Web Site Before Deployment


Another excellent feature of ASP.NET 2.0 web pages is dynamic compilation that makes it possible for you to easily make changes to an .aspx page, save the page, and request the page in the browser without having to recompile the web site. This feature is very similar to the "Just Hit Save" programming model that we were all used to, while programming in ASP. Even though this feature can be very powerful and useful while developing the application, dynamic compilation does result in a performance hit for the first time when someone makes a request for the web page. In that case, it would be beneficial to precompile the web site and make the compiled web site available so that the performance of the web site can be increased. This is exactly what ASP.NET 2.0 Precompilation does. Using this feature, you can precompile the web site and deploy it on to the server so that when someone requests the web page for the first time, ASP.NET 2.0 can serve up the page quickly without have to compile the web site.

Precompilation can also be useful in scenarios where you want to deploy your web application without the source code. Precompilation also allows you to ensure that the site is compilation error-free. If a page in your site contains a compile-time error and you do not precompile the site, it is possible that a user will see the error the first time the page is requested. Now that you have had an understanding of the concepts of Precompilation in a general sense, let us take a look at the different types of precompilation. ASP.NET 2.0 supports two modes of pre-compilation: in-place precompilation, and precompilation for deployment.

In-Place Precompilation

This type of precompilation allows you to batch-compile all the pages in your web site. This is essentially what ASP.NET does when someone hits a page for the first time within your application. There are two important advantages to in-place precompilation: first, it eliminates the performance hit of batch compiling on the first page request, and second, it allows you to find compilation errors before your users do. In-place precompilation is very easy to do. All you need to do is to simply browse to the Visual Studio 2005 command prompt root of your web site and then invoke the ASP.NET 2.0 command line utility named aspnet_compiler.exe that is present in the root of the virtual directory. To perform in-place precompilation, use the following syntax.


aspnet_compiler -v /<websitename>

To view all of the available options for the ASP.NET precompiler, simply enter the command aspnet_compiler /? in the command prompt.

For the purposes of our example, use the command as shown below.

If everything is fine and the Web site is compiled successfully, you will see the above output.

Once you have precompiled your Web site, requests for pages within the site should be fulfilled immediately, without any compilation lag.

Precompilation for Deployment

This type of precompilation enables you to create an executable version of your entire Web site that can be deployed without any source code, including HTML and other static files. Using this mode of precompilation, you can prevent easy access to the intellectual property represented by your code. The resulting set of assemblies and stub files can be deployed to a production server through XCOPY, FTP, Windows Explorer, and so on.

The ASP.NET 2.0 command line utility allows you to not only precompile but also deploy the Web site in a single step. To deploy the Web site, use the following command.


aspnet_compiler -v <source> <destination>

Where <websitename> is the name of the Web site, and <source> and <destination> are file system paths pointing to the location of the source Web site and the location to which the compiled version should be emitted to. For the purposes our example Web site, the command would look something like the following:


aspnet_compiler -v /MyProjects/15Seconds/NewFiles c:\NewFiles

After precompiling the Web site for deployment, if you navigate to the destination directory in Windows Explorer, you’ll see a Web site with a bin directory containing several assemblies and descriptive files, as well as a number of stub files with the same names as the original pages, but with the code (both HTML and executable code) stripped out. However if you browse the site, the output will be identical to the original site.



Conclusion


The features of new files and folders of ASP.NET 2.0 that we have seen in this article are only the tip of the iceberg and it offers many more benefits. However, the key motivation for using ASP.NET 2.0 features is the increased productivity that can result in code reduction of your ASP.NET 2.0 applications by as much as 70%.





More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read