You are on page 1of 5286

Visual Studio 2005 Visual Web Developer

Copyright© 2016 Microsoft Corporation

The content in this document is retired and is no longer updated or supported. Some links might not work. Retired content represents the
latest updated version of this content.
Visual Web Developer

Visual Web Developer


Visual Web Developer is a tool for creating and working with ASP.NET Web applications (called simply "Web sites") in a variety
of configurations.
In This Section
Welcome
Provides general information on Visual Web Developer and on improvements and enhancements in the Web development
tool since Visual Studio .NET 2003.
Guided Tour of Creating Web Sites in Visual Web Developer
Lists walkthrough topics (tutorials) that illustrate how to use Visual Web Developer to create and customize Web sites.
ASP.NET Web Sites (Visual Studio)
Provides information on how to create ASP.NET Web applications (sometimes referred to as a Web sites).
ASP.NET Web Pages (Visual Studio)
Provides information about how ASP.NET Web pages function and how to create and program them.
ASP.NET Web Server Controls (Visual Studio)
Provides information about how ASP.NET Web server controls work, how to add them to ASP.NET pages, and how to
program them.
ASP.NET Data Access (Visual Studio)
Provides information on displaying and editing data in ASP.NET Web pages.
ASP.NET Web Site Security (Visual Studio)
Provides information on security threats to your ASP.NET applications, ways to mitigate threats, and ways to authenticate
and authorize users.
ASP.NET Debugging and Troubleshooting (Visual Studio)
Provides information on handling errors, debugging ASP.NET pages, viewing trace information during page processing, and
monitoring the health of your application.
Customizing ASP.NET Web Sites (Visual Studio)
Provides information on enabling your Web site to track individual users, adding navigation features to your site, creating
Web pages for multiple languages and cultures, and creating Web pages that are accessible to people with disabilities.
Managing ASP.NET Web Sites in Visual Studio
Provides information on configuring an ASP.NET Web site, deploying (publishing) Web sites, and managing performance for
your applications.
XML Web Services (Visual Studio)
Provides information on creating and using components that can be accessed across the Web using standard protocols such
as HTTP.
Converting from Visual Studio .NET 2002 or 2003
Provides information on converting Web projects created in Visual Studio .NET 2002 or 2003 to the format used for projects
in Visual Web Developer, including details about how project settings are handled.
ASP.NET Web Sites for Mobile Devices (Visual Studio)
Provides information on features in ASP.NET that help you create applications that can render to browsers in mobile phones
and other devices.
Visual Web Developer

Welcome
This section welcomes you to Visual Studio and provides an overview of the product.
In This Section
What's New in Web Development for Visual Studio
Describes changes and improvements that have been introduced in ASP.NET 2.0.
Visual Web Developer

Introduction to Visual Web Developer


Welcome to Visual Web Developer. Visual Web Developer is a full-featured development environment for creating ASP.NET
Web applications (which are simply called "Web sites"). Visual Web Developer offers you the following features:
Web page design A powerful Web page editor that includes WYSIWYG editing and an HTML editing mode with
IntelliSense and validation.
Page design features Consistent site layout with master pages and consistent page appearance with themes and
skins.
Code editing A code editor that enables you to write code for your dynamic Web pages in Visual Basic or C#. The code
editor includes syntax coloration and IntelliSense.
Debugging A debugger that helps you find errors in your programs.
Controls An extensive suite of ASP.NET Web server controls that incorporate much of the functionality you need for
creating Web sites.
Data access Support for displaying and editing data in your Web pages. The data can be in a variety of data stores,
including databases or XML files. In many cases, you can add data display and editing to your Web pages without writing
any code.
Security, personalization, and more Built-in application services that enable you to add membership for login
security to your site, profile properties that enable you to maintain user-specific information, and other features, most
without requiring any code.
Development for hosted sites Tools for publishing sites to your hosting site, including a local Web server for testing.
Local Development for Hosted Sites
Visual Web Developer provides an ideal environment in which to build Web sites and then publish them to a hosting site.
Using the development tools in Visual Web Developer, you can develop ASP.NET Web pages on your own computer. Visual
Web Developer includes a local Web server that provides all the features you need to test and debug ASP.NET Web pages,
without requiring Internet Information Services (IIS) to be installed.
When your site is ready, you can publish it to the host computer using the built-in Copy Web tool, which transfers your files
when you are ready to share them with others. Alternatively, you can precompile and deploy a Web site by using the Build
Web Site command. The Build Web Site command runs the compiler over the entire Web site (not just the code files) and
produces a Web site layout that you can deploy to a production server.
Note
The Build Web Site feature is not available in Visual Web Developer Express Edition.

Finally, you can take advantage of the built-in support for File Transfer Protocol (FTP). Using the FTP capabilities of Visual Web
Developer, you can connect directly to the host computer and then create and edit files on the server.
Exploring Visual Web Developer
To learn more about creating dynamic Web sites with Visual Web Developer, see the following resources:
The guided tour, which introduces many of the features you will use frequently when creating ASP.NET Web sites. To
start, see Guided Tour of Creating Web Sites in Visual Web Developer.
The ASP.NET 2.0 Starter Kits for Visual Web Developer are complete Web sites that you can use with minor
customization for your own site. These starter kits show you creative ways to use the features of Visual Web Developer to
create professional, functional Web sites. To use a starter kit, create a new Web site and select the starter kit that you
want. Visual Web Developer comes packaged with the Personal Web Site Starter Kit, which creates a Web site that
includes your latest news, a photo album, and other features. For more information, see
Visual Web Developer Starter Kits.
If you need assistance while working with Visual Web Developer, you can refer to the online Help. The Help system can be
extended to take advantage of online information resources as well.
See Also
Other Resources
Guided Tour of Creating Web Sites in Visual Web Developer
Visual Web Developer

What's New in Web Development for Visual Studio


Microsoft Visual Studio 2005 includes the Visual Web Developer Web development tool, which is a set of tools and utilities for
creating ASP.NET version 2.0 Web sites. Visual Web Developer represents an evolutionary improvement in support for creating
Web sites. Visual Web Developer continues to bring you the productivity benefits of the integrated development environment
(IDE) while introducing a wide array of improvements.
The major improvements for this version of Visual Web Developer include the following:
ASP.NET 2.0 support.
Visual Web Developer supports new ASP.NET 2.0 features, including a host of new controls that are introduced in
ASP.NET 2.0. In addition, Visual Web Developer adheres closely to native ASP.NET 2.0 features and does not add
designer-specific features. For example, Visual Web Developer does not embed designer-specific tags in your
ASP.NET 2.0 pages.
More flexible project and deployment options.
Visual Web Developer allows you to create traditional Microsoft Internet Information Services (IIS) applications in the IIS
root on local and remote computers and it also supports virtual roots, opening Web sites by using File Transfer Protocol
(FTP), and using stand-alone files that reside outside a project. The end result is that it is substantially easier to create and
deploy ASP.NET 2.0 applications.
Improved code-behind model.
Visual Web Developer can create pages by using either a new code-behind model or by including code in the ASP.NET
page (the .aspx file).
Improved programming capabilities.
Many basic tasks have been greatly simplified. For example, you can create a data-bound page with no coding
whatsoever. New ASP.NET 2.0 controls add substantial functionality that used to require you to write your own code.
Microsoft IntelliSense and related technologies have been expanded to work virtually everywhere.
The following sections provide a high-level summary of the changes in Visual Web Developer.
Web Sites
Projects
Dynamic Compilation Model
Editing
Programming
Improved Code-Behind Model
Controls
Data Controls and Data Binding
Converting Existing Web Sites
Web Application Projects
For information about new features in ASP.NET 2.0, see What's New in ASP.NET.
Web Sites and Projects
Visual Web Developer features a flexible approach to creating Web sites (also called projects and Web applications in previous
versions of Visual Web Developer and the Web page designer, respectively). Web sites in Visual Web Developer are not
necessarily bound to Microsoft Internet Information Services (IIS) nor to physical folders on the IIS root.
You can now create the following types of Web sites:
File system.
You can keep all the files for a Web site in a simple folder. File-system Web sites do not depend on IIS. For details, see
Walkthrough: Creating a Basic Web Page in Visual Web Developer.
Local IIS.
As in previous versions of Visual Studio, you can create IIS applications that can reside either on the local IIS root or on a
virtual directory. You can create virtual folders, as well. For details, see Walkthrough: Basic Data Access in Web Pages.
Remote.
You can create applications residing on remote servers that support FrontPage 2002 Server Extensions from Microsoft.
This is the model that was used for previous versions of Visual Web Developer and continues to be supported in this
version.
FTP.
You can open Web sites across FTP. For details, see Walkthrough: Editing Web Sites with FTP in Visual Web Developer.
ASP.NET Development Server
The Visual Web Developer Web development tool ships with a lightweight test application server, the ASP.NET Development
Server, which you can use to test file system Web sites, without having to use IIS. For more information, see
Web Servers in Visual Web Developer.
Projects
In the new version of Visual Web Developer, Web sites are not dependent on project and solution files. You can add files to a
Web site either in Visual Web Developer or by using Microsoft Windows Explorer, and the files are automatically part of the
Web site.
Visual Web Developer still creates project and solution files to store a small amount of project-specific information, such as
your IDE settings. Much of the information that was previously stored in project files now either is stored in the Web.config file
as standard ASP.NET 2.0 configuration settings or is no longer necessary. The project file stores no information that is required
to run the application.
Working without a project model not only makes it possible to add, edit, and remove files outside of Visual Web Developer, it
also makes it easier for more than one developer to work together to create a Web site. More than one developer can add or
remove files from a Web site without requiring access to a centralized project file that needs to be updated with file
information. In addition, it is easier to keep Web site files in a source-control system, such as the Microsoft Visual SourceSafe
version control system, because developers do not have to exclusively check out a project file to add files to the Web site.
Dynamic Compilation Model
In Visual Web Developer, Web sites no longer use the compilation model that was used in previous versions, in which the
executable code for the entire project was compiled into a single assembly. Instead, by default, the new version uses the
dynamic compilation model that is native to ASP.NET 2.0.
Working with Web sites that do not produce an executable assembly as their output has a number of advantages:
You can test Web sites that contain pages still in development—pages that contain compilation errors do not prevent
other pages in the Web site from running.
For development on large Web sites, the entire application does not need to be recompiled every time a change is made
to a single page or component. When a developer changes a single page, only that page is recompiled when it is next
requested.
Different developers can make edits to different pages at the same time without interfering with one another's changes,
as could happen when compiling the project to a single assembly, as in Microsoft Visual Studio .NET 2003.
When you test a Web site, the Web site is still compiled (built). However, the compilation step is used as verification that all the
pages and their dependencies can be compiled; the output of the compilation process is not used as the basis for running the
Web site. This build step is more comprehensive than it was in earlier versions because it validates not only that the code can
be compiled but also finds errors in the markup syntax and Web.config file.
Publishing Web Sites
Because some developers do not want to deploy source code with their Web sites, the Visual Web Developer Web
development tool provides the option to precompile and deploy a Web site by using the Build Web Site command. The Build
Web Site command runs the compiler over the entire Web site (not just the code files) and produces a Web site layout that
you can deploy to a production server. The layout includes assemblies for individual pages, which include both the code and
the markup for the page (that is, the .aspx files are compiled also).
Note
This feature is not available in Visual Web Developer Express Edition.

The primary benefit of precompiling is that it allows you to deploy only executable code, thus bringing a measure of protection
to your intellectual property. In addition, precompiling finds any compile-time errors in the pages or dependent code. Finally,
precompiling improves performance and reduces the time it takes for pages in your Web site to render the first time.
Editing Pages
Visual Web Developer offers the following enhancements for creating and editing Web pages:
Support for new page features.
The Visual Web Developer Web page designer features WYSIWYG support for new ASP.NET 2.0 page elements, such as
master pages. For details, see ASP.NET Master Pages Overview and
Walkthrough: Creating and Using ASP.NET Master Pages in Visual Web Developer.
Preservation of source code.
Visual Web Developer maintains the HTML formatting of your page when you switch between Design and Source view
and when you save files.
Enhanced HTML generation and validation.
Visual Web Developer provides more options for generating and validating the HTML on your page. By default, the Web
page designer creates markup that is XHTML 1.1 compatible and new schemas include support for several variations of
XHTML. You can set options to determine how strictly Visual Web Developer validates the elements in your page and
HTML is also validated more strictly. Additionally, Visual Web Developer provides error information in ToolTips.
Drag-and-drop functionality in Source view.
You can drag controls from the Toolbox while in Source view.
For more information, see Walkthrough: Creating a Basic Web Page in Visual Web Developer.
Programming
Visual Web Developer includes a number of improvements to the code editor that help you code more productively, including
the following:
Microsoft IntelliSense technology.
Statement completion is now virtually everywhere when you edit Web pages. The IntelliSense technology helps you
create code in both code-behind and single-file pages, markup tags, page directives, and so on.
Event drop-down lists.
You can create event-handlers in Source view by using event drop-down lists, as you previously could do only in Code
view. The Properties window now allows you to create event handlers for both Visual Basic and C#.
Single-file page support.
The code editor now provides equivalent support for code-behind and single-file ASP.NET 2.0 pages. (For information
about changes to the code-behind model, see Improved Code-Behind Model.) Both code models support syntax
coloration, IntelliSense technology, and so on.
Shared code.
Classes for which the source code is in the App_Code folder for your Web application are automatically referenced; if you
have compiled components, you can place them in the Bin folder to have Visual Web Developer reference them
automatically. IntelliSense functionality picks up information about any components that are installed in the App_Code or
Bin folder of your application. For details, see Walkthrough: Using Shared Code in Web Sites in Visual Web Developer.
Debugging.
You have full debugging facilities for local Web sites, including file system Web sites. Debugging is less complex and
faster than in previous versions. For details, see Walkthrough: Debugging Web Pages in Visual Web Developer.

Improved Code-Behind Model


A significant difference between previous versions of Visual Web Developer and this release is in how code-behind pages
work. In Microsoft Visual Studio .NET 2002, when you created a new Web Forms page, Visual Web Developer created an .aspx
file with the markup and a separate .vb or .cs file (the code-behind file) for the page's code. The code-behind file defined a
complete class that was derived from the Page class.
The Web page designer kept the .aspx file and the code-behind file in synchronization. For example, if you added a Web server
control to the .aspx file, the Web page designer created a corresponding instance variable in the code-behind file for that
control.
In this version, the code-behind model takes advantage of a new language feature known as partial classes. The code-behind
file for a page is not a complete class definition. Instead, it includes only the application code that you need, such as event
handlers. The code-behind partial class does not need to include instance variables; ASP.NET 2.0 infers the control instances
from the markup at compile time. If you are coding in C#, you do not need to include explicit delegates for event binding,
because ASP.NET 2.0 can deduce them from the event attributes (for example, onclick) in the control markup. In Visual Basic,
you can add a Handles clause onto the declaration of an event method, as in the previous model, to bind the event to the
handler.
The new code-behind model offers a number of advantages over the previous model, as follows:
True separation of code and markup.
In previous versions, the markup and code were stored in separate files. However, because previous versions needed to
keep the files in synchronization by using instance variables and event delegates, it was not practical to work with the
files separately. For example, it was not practical for a page developer to work on the layout of the page while another
developer worked on the code. In this version, this is much more achievable.
Less complexity in referencing controls.
As noted, the new code-behind model does not require explicit instance variables in the code-behind page. Even though
previous versions managed the instance variables, it did not do so for all controls—notably for user controls or for some
HTML elements that were declared as controls. In this version, because no instance variables are required, all controls,
including user controls, are referenced implicitly.
Less generated code.
The new code-behind model contains virtually no generated code beyond the class definition itself. There are no reserved
areas in the code-behind that the editor might overwrite.

Controls
Visual Web Developer supports new ASP.NET 2.0 controls, which offer new functionality, which results in significantly greater
productivity. In addition to hosting new controls, the Web page designer includes improvements to help you work more easily
with controls. Highlights include the following:
More consistent and powerful editing model.
The overall model for working with controls is more consistent between controls and allows you to perform many more
actions without having to use the Properties window or edit the declarative syntax of a control.
Visual display of controls.
The Web page designer has improved support for rendering controls; for example, user controls are now rendered
visually in Design view.
Task-based editing.
As you work with controls, they display a Smart Tag menu (a floating, shortcut menu of tasks) for the current control.
Typical actions that are offered by task-based editing include editing templates and setting up data binding.
Template editing.
The Web page designer provides a simplified and more intuitive interface for creating and editing templates on complex
controls, such as the DataList and GridView controls.
Table editing.
It is now much easier to create and edit HTML tables in the Web page designer. For details, see
Walkthrough: Editing HTML Tables in Visual Web Developer.
Control Extensibility
You can now extend controls in powerful new ways. As before, you can create user controls and custom controls. This release
of the Visual Web Developer Web development tool provides improved support for user controls, including WYSIWYG
rendering in Design view and Properties window support.
You can extend the run-time behavior of controls by creating adapters, which define the output of the control for a specific
device or browser. At run time, ASP.NET 2.0 determines the type of device that generated the request and invokes a control
adapter to render the appropriate output for that device for a given control. By creating an adapter for a control and a specific
class of device, you can customize the output for that control for the device. Adapters are especially useful for creating custom
rendering for new devices. For more information, see Developing Adapters for ASP.NET Server Controls.
If you develop custom controls, you now have improved support for hosting your control in a Web page designer, including
the following:
Classes that allow you to add region-based editing to your controls at design time.
Support for task-based editing, so that you can define verbs (tasks) that are exposed for your control by using a shortcut
menu in the Web page designer.
Template-editing services that simplify adding support for templates in your controls.
Controls can take advantage of tool-based services for improved interaction with their hosting environment. For
example, controls have access to the page directive, the project system, and the current document.

Data Controls and Data Binding


Working with data is an important part of many ASP.NET 2.0 Web pages, and Visual Web Developer includes many
improvements to make data access easier to implement and manage. The overall goal for data binding in ASP.NET 2.0 is to be
able to accomplish a wide variety of data-binding scenarios without having to write any code at all. This version supports this
goal and extends it by providing wizards that help you configure data binding and create data components.
Data Binding with Data Source Controls
The model for binding controls on the page to data sources has been improved considerably. The data-binding model for
Microsoft Visual Studio .NET 2002 required that you add data components, such as a connection and dataset objects, on the
page. Then, you needed to write code to manage data binding to data controls, such as the DataList and DataGrid controls.
To simplify data binding, ASP.NET 2.0 introduces data source controls. Data source controls provide a single object in which
you can declaratively define the following:
Connection information.
Queries (a SQL statement, stored parameter name, or the names of methods to invoke on an object).
Parameters—you can define parameters declaratively and specify that they get their values from a control on the page,
from a query string, from session variables, or from other sources.
Behavior options (depending on the data source control), such as paging and caching.
In general, you do not need to work directly with the objects that are used to manage data access, such as datasets or data
readers. Data source controls create data components under the covers. You do not work with those components, but you do
need to be aware of them when you want to use a feature, such as paging, that depends on choosing between a dataset and a
data reader.
ASP.NET 2.0 provides data source controls for different types of data stores, including SQL (for OLE DB and Open Database
Connectivity [ODBC] databases), XML files, and business objects. All data source controls expose the same interface to data
controls on the page, so that controls, such as the DataList and Repeater controls, and the new GridView control, can bind
the same way to any data source control, regardless of the underlying data store that they represent, and then display data on
the page. The result is that you can use the full array of ASP.NET 2.0 data controls to work with a wide variety of data sources.
To help you create and configure data source controls, the Visual Web Developer Web development tool includes wizards that
help you to create connections, define queries or specify methods to call, and configure parameters.
Enhanced Data Controls
All data controls in ASP.NET 2.0 have been enhanced to work with data source controls. Instead of pointing a control at a
dataset or data reader, you reference a data source control. The data control and data source control then work together to
manage data binding automatically, so that in most cases you do not need to write code to perform data binding.
As a result, you can take advantage of automatic data binding in any data-bound control. In addition, ASP.NET 2.0 introduces
new data controls that provide additional functionality. These include the following:
The GridView control, which is the successor to the DataGrid control.
The GridView control automates many of the features of the DataGrid control, so that you do not need to write code for
editing, sorting, or paging. For situations in which you want to customize the control's behavior, you can continue to use
the object model that you are familiar with from the DataGrid control.
The DetailsView control displays one record at a time and allows you to edit, delete, and insert records.
You can also page through multiple records.
The FormView control is similar to the DetailsView control, but allows you to define a free-form layout for each record.
The FormView control is like a DataList control for a single record.
You can continue to use the DataGrid control, although it is superseded by the GridView control. Existing pages that use the
DataGrid control work as is. As with other data controls, the DataGrid control has been enhanced to interact with data source
controls.
Two-Way Data Binding
The combination of data source controls, declarative parameters, and enhanced data controls provides the ability to create
two-way data binding without having to write code. In data source controls, you can define queries or method names to use
for updates. Data controls, such as the GridView, DetailsView, and FormView controls, support edit and delete modes (and
for some controls, insert mode) that can automatically interact with the data source controls to write data to the data source.
Connection String Storage
To help make your Web sites more maintainable and more secure, you can keep connection strings in the Web.config file in a
new section that has been designed specifically for connection string storage. When you use the Visual Web Developer Web
development tool to create or configure data source controls, you can specify that the connection string be stored in the
Web.config file. If you change data sources, you can easily change the connection string in one location rather than having to
update all data components on all pages with a new connection string. For added security, you can encrypt the connection
string section of the Web.config file. For details, see Encrypting Configuration Information Using Protected Configuration.
Two-Tier and Three-Tier Data Access
The earlier data binding model encouraged the creation of two-tier data solutions, in which the Web pages interacted directly
with the database to fill a dataset and to bind controls to it. The new model continues to make it easy to work in a two-tier
structure. For example, the SqlDataSource control connects directly to a database and executes SQL statements or stored
procedures to read and write data.
The new data binding model also makes it much easier to create a three-tier structure in which data access is handled by a
middle-tier business object. The ObjectDataSource control interacts with a business object by calling methods on the object
to retrieve and update data. Data controls on the page can bind to the ObjectDataSource control as they do to other data
source controls, such as the SqlDataSource control.
The Visual Web Developer Web development tool includes a data component wizard that helps you create a custom object that
contains methods to read and update data. Alternatively, you can create your own middle-tier object that contains methods. As
long as your custom object exposes methods with the appropriate signatures, you can reference it from an ObjectDataSource
control. For details, see Walkthrough: Data Binding to a Custom Business Object.
Backward Compatibility for Data Access
The Visual Web Developer Web development tool continues to support pages that use the data binding model from previous
versions. Pages that contain datasets and other components run as they did before, and you can open them and edit the pages
in the Web page designer. Visual Web Developer does not remove the data components and does not convert the components
to data source controls.
Note
Data components, such as datasets and data connections, are not displayed in the Web page designer in Visual Web Develop
er. Therefore, you can neither set nor examine their properties by using the Properties window. However, you can still edit th
e code that is used to instantiate the data components and set their properties.

For more information, see Data Source Controls Overview and Walkthrough: Basic Data Access in Web Pages.
Converting Existing Web Sites
Visual Web Developer can automatically convert your existing projects to the new streamlined Web site layout. The conversion
process preserves the functionality of your application and the project options that apply. Existing code-behind Web pages are
converted to a new code-behind model that preserves the separation of HTML and code, but provides a simplified structure.
For more information, see Web Project Conversion from Visual Studio .NET.
After conversion, you can use the Web page designer to work with pages and controls that were developed with previous
versions of Visual Web Developer.
Web Application Projects
The new Web application project model provides the same Web project semantics as the Visual Studio .NET 2003 Web project
model. This includes a structure based on project files and a build model based on compiling all the code for a project into a
single assembly. In addition, the new project type supports many of the new features of Visual Studio 2005 (such as class
diagrams, test development, and generics) and of ASP.NET 2.0 (such as master pages, data controls, membership and logon,
role management, Web parts, personalization, site navigation, and themes).
For more information about Web application projects, see Web Application Projects Overview.
See Also
Concepts
What's New in Visual Studio 2005
Web Application Projects Overview
Other Resources
Guided Tour of Creating Web Sites in Visual Web Developer
Visual Web Developer

Community Resources for Visual Web Developer


Community is a vital part of working with Visual Web Developer. The ASP.NET and Visual Web Developer communities offer
news, information, support, and tools that help you create Web sites of your own.
This topic lists community resources that can help you work effectively with Visual Web Developer.
Site Description
ASP.NET Web site The official ASP.NET site. Includes news, tutorials, support, starter kits, and many tools for
download.

Microsoft ASP.NET Developer Center The MSDN site for ASP.NET development, a central location that brings together content
from many different sources. Includes articles, downloads, and blog feeds.

ASP.NET support forums Web site The support forums on the ASP.NET site, visited every day by thousands of knowledgeabl
e users. The site includes forums for many different aspects of ASP.NET and Visual Web
Developer, and offer assistance to both new and experienced users.

See Also
Concepts
Introduction to Visual Web Developer
Visual Web Developer

Guided Tour of Creating Web Sites in Visual Web Developer


This section contains topics designed to give a guided tour of creating Web sites in Visual Studio.
In This Section
Creating Pages
Describes how to create new ASP.NET Web sites and add ASP.NET Web pages to them. Includes information on editing
HTML, creating server code, and debugging.
Data-Driven Web Pages
Describes various ways to display and edit data in ASP.NET Web pages and explains how to optimize data access by using
caching.
Additional Page Techniques
Describes how to create specific types of ASP.NET Web pages, including master pages, Web Parts pages, and wizards. Also
includes information on creating reusable elements (user controls).
Customizing Web Pages
Describes how to add menus, define themes for consistent Web site appearance, create rotating advertisements, create
pages for browsers on mobile devices, create and use an ASP.NET Web service, and create pages that can display text in
different languages.
Building Professional Web Sites (Visual Studio), Building Professional Web Sites (Visual Web Developer Express Edition)
Describes how to use system diagnostics with ASP.NET Web pages and describes ways to deploy a Web site to a production
Web server.
Visual Web Developer

Creating Pages
The topics in this section include step-by-step walkthroughs that illustrate how to create new ASP.NET Web sites and add
ASP.NET Web pages to them. Additional walkthroughs illustrate how to edit HTML, create server code, and debug Web pages.
In This Section
Walkthrough: Creating a Basic Web Page in Visual Web Developer
Walkthrough: Creating a Basic Web Page with Code Separation in Visual Web Developer
Walkthrough: Basic HTML Editing in Visual Web Developer
Walkthrough: Working with Cascading Style Sheet Styles in Visual Web Developer
Walkthrough: Advanced HTML Editing in Visual Web Developer
Walkthrough: Code Editing in Web Pages in Visual Web Developer
Walkthrough: Debugging Web Pages in Visual Web Developer
Walkthrough: Creating a Local IIS Web Site in Visual Web Developer
Walkthrough: Editing Web Sites with FTP in Visual Web Developer
Walkthrough: Using Shared Code in Web Sites in Visual Web Developer
Related Sections
Guided Tour of Creating Web Sites in Visual Web Developer
Introduces topics that give a guided tour of creating Web sites in Visual Web Developer.
Visual Web Developer

Walkthrough: Creating a Basic Web Page in Visual Web


Developer
This walkthrough provides you with an introduction to Microsoft Visual Web Developer. It guides you through creating a
simple page by using Visual Web Developer, illustrating the basic techniques of creating a new page, adding controls, and
writing code.
Tasks illustrated in this walkthrough include:
Creating a file system Web site.
Familiarizing yourself with Visual Web Developer.
Creating a single-file ASP.NET page in Visual Web Developer.
Adding controls.
Adding event handlers.
Running pages with the Web Servers in Visual Web Developer.
Prerequisites
In order to complete this walkthrough, you will need:
Visual Web Developer
The .NET Framework
Creating a Web Site and Page
In this part of the walkthrough, you will create a Web site and add a new page to it. You will also add HTML text and run the
page in your Web browser.
For this walkthrough, you will create a file system Web site that does not require that you work with Microsoft Internet
Information Services (IIS). Instead, you will create and run your page in the local file system.
A file system Web site is one that stores pages and other files in a folder that you choose somewhere on your local computer.
Other Web site options include a local IIS Web site, which stores your files in a subfolder of the local IIS root (typically,
\Inetpub\Wwwroot\). An FTP site stores files on a remote server that you gain access to across the Internet by using File
Transfer Protocol (FTP). A remote site stores files on a remote server that you can access across a local network. For more
information, see Walkthrough: Editing Web Sites with FTP in Visual Web Developer. Also, Web site files can be stored in a
source control system such as Visual SourceSafe. For more information, see Introducing Source Control.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears, as shown in the following screen shot.
New Web Site dialog box
3. Under Visual Studio installed templates, click ASP.NET Web Site.
When you create a Web site, you specify a template. Each template creates a Web application that contains different files
and folders. In this walkthrough, you are creating a Web site based on the ASP.NET Web Site template, which creates
some folders and a few default files.
4. In the Location box, select the File System box, and then enter the name of the folder where you want to keep the pages
of your Web site.
For example, type the folder name C:\BasicWebSite.
5. In the Language list, click Visual Basic or Visual C#.
The programming language you choose will be the default for your Web site. However, you can use multiple languages
in the same Web application by creating pages and components in different programming languages.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx. When a new page is created, by default
Visual Web Developer displays the page in Source view, where you can see the page's HTML elements. The following
screen shot shows the Source view of a default Web page.
Source view of default page
A Tour of Visual Web Developer
Before you proceed with working on the page, it is useful to familiarize yourself with the Visual Web Developer development
environment. The following illustration shows you the windows and tools that are available in Visual Web Developer.
Diagram of Visual Web Developer environment

To familiarize yourself with the Web designer in Visual Web Developer


Examine the preceding illustration and match the text to the following list, which describes the most commonly used
windows and tools. (Not all windows and tools that you see are listed here, only those marked in the preceding
illustration.)
Toolbars. Provide commands for formatting text, finding text, and so on. Some toolbars are available only when
you are working in Design view.
Solution Explorer. Displays the files and folders in your Web site.
Document window. Displays the documents you are working on in tabbed windows. You can switch between
documents by clicking tabs.
Properties window. Allows you to change settings for the page, HTML elements, controls, and other objects.
View tabs. Present you with different views of the same document. Design view is a near-WYSIWYG editing
surface. Source view is the HTML editor for the page. You will work with these views later in this walkthrough. If
you prefer to open Web pages in Design view, on the Tools menu, click Options, select the HTML Designer
node, and change the Start Pages In option.
Toolbox. Provides controls and HTML elements that you can drag onto your page. Toolbox elements are grouped
by common function.
Server Explorer/Database Explorer. Displays database connections. If Server Explorer is not visible in Visual Web
Developer, on the View menu, click Other Windows, and then click Server Explorer.
Note
You can rearrange and resize the windows to suit your preferences. The View menu allows you to display addit
ional windows.

Creating a New Web Forms Page


When you create a new Web site, Visual Web Developer adds an ASP.NET page (Web Forms page) named Default.aspx. You
can use the Default.aspx page as the home page for your Web site. However, for this walkthrough, you will create and work
with a new page.
To add a page to the Web site
1. Close the Default.aspx page. To do this, right-click the tab containing the file name and select Close.
2. In Solution Explorer, right-click the Web site (for example, C:\BasicWebSite), and then click Add New Item.
3. Under Visual Studio installed templates, click Web Form.
4. In the Name box, type FirstWebPage.
5. In the Language list, choose the programming language you prefer to use (Visual Basic, C#, or J#).
When you created the Web site, you specified a default language. However, each time you create a new page or
component for your Web site, you can change the language from the default. You can use different programming
languages in the same Web site.
6. Clear the Place code in separate file check box. The following screen shot shows the Add New Item dialog box.
Add New Item dialog box

In this walkthrough, you are creating a single-file page with the code and HTML in the same page. The code for ASP.NET
pages can be located either in the page or in a separate class file. To learn more about keeping the code in a separate file,
see Walkthrough: Creating a Basic Web Page with Code Separation in Visual Web Developer.
7. Click Add.
Visual Web Developer creates the new page and opens it in Source view.
Adding HTML to the Page
In this part of the walkthrough, you will add some static text to the page.
To add text to the page
1. At the bottom of the document window, click the Design tab to switch to Design view.
Design view displays the page that you are working on in a WYSIWYG-like way. At this point, you do not have any text or
controls on the page, so the page is blank.
2. On the page, type Welcome to Visual Web Developer.
The following screen shot shows the text you typed in Design view.
Welcome text as seen in Design view

3. Switch to Source view.


You can see the HTML that you created by typing in Design view, as shown in the following screen shot.
Welcome text as seen in Source view

Running the Page


Before you proceed with adding controls to the page, you can try running it. To run a page, you need a Web server. In a
production Web site, you use IIS as your Web server. However, to test a page, you can use the ASP.NET Development Server,
which runs locally and does not require IIS. For file system Web sites, the default Web server in Visual Web Developer is the
ASP.NET Development Server.
To run the page
1. Press CTRL+F5 to run the page.
Visual Web Developer starts the ASP.NET Development Server. An icon appears on the toolbar to indicate that the Visual
Web Developer Web server is running, as shown in the following screen shot.
Visual Web Developer Web server icon

The page is displayed in the browser. Although the page you created has an extension of .aspx, it currently runs like any
HTML page.
Note
If the browser displays a 502 error or an error indicating that the page cannot be displayed, you might need to configur
e your browser to bypass proxy servers for local requests. For details, see
How to: Bypass a Proxy Server for Local Web Requests.

2. Close the browser.


Adding and Programming Controls
In this part of the walkthrough, you will add a Button, a TextBox, and a Label control to the page and write code to handle the
Click event for the Button control.
You will now add server controls to the page. Server controls, which include buttons, labels, text boxes, and other familiar
controls, provide typical form-processing capabilities for your ASP.NET Web pages. However, you can program the controls
with code that runs on the server, not the client.
To add controls to the page
1. Click the Design tab to switch to Design view.
2. Press SHIFT+ENTER a few times to make some room.
3. In the Toolbox, from the Standard group, drag three controls onto the page: a TextBox control, a Button control, and a
Label control.
4. Put the insertion point above the TextBox control, and then type Enter your name:.
This static HTML text is the caption for the TextBox control. You can mix static HTML and server controls on the same
page. The following screen shot shows how the three controls appear in Design view.
Controls in Design View

Setting Control Properties


Visual Web Developer offers you various ways to set the properties of controls on the page. In this part of the walkthrough,
you will set properties in both Design view and Source view.
To set control properties
1. Select the Button control, and then in the Properties window, set Text to Display Name, as shown in the following
screen shot.
Changed Button control text

2. Switch to Source view.


Source view displays the HTML for the page, including the elements that Visual Web Developer has created for the server
controls. Controls are declared using HTML-like syntax, except that the tags use the prefix asp: and include the attribute
runat="server".
Control properties are declared as attributes. For example, when you set the Text property for the Button control, in step
1, you were actually setting the Text attribute in the control's markup.
Note that all the controls are inside a <form> element, which also has the attribute runat="server". The
runat="server" attribute and the asp: prefix for control tags mark the controls so that they are processed by ASP.NET
on the server side when the page runs. Code outside of <form runat="server"> and <script runat="server">
elements is interpreted by the browser as client-side code, which is why the ASP.NET code must be inside.
3. Put the insertion point in a space within the <asp:label> tag, and then press SPACEBAR.
A drop-down list appears that displays the list of properties you can set for a Label control. This feature, referred to as
IntelliSense, helps you in Source view with the syntax of server controls, HTML elements, and other items on the page.
The following screen shot shows the IntelliSense drop-down list for the Label control.
IntelliSense for Label control

4. Select ForeColor and then type an equal sign (=). IntelliSense displays a list of colors.
Note
You can display an IntelliSense drop-down list at any time by pressing CTRL+J.

5. Select a color for the Label control's text.


The ForeColor attribute is completed with the color that you have selected.
Programming the Button Control
For this walkthrough, you will write code that reads the name that the user enters into the text box and then displays the name
in the Label control.
To add a default button event handler
1. Switch to Design view.
2. Double-click the Button control.
Visual Web Developer switches to Source view and creates a skeleton event handler for the Button control's default
event, the Click event.
Note
Double-clicking a control in Design view is just one of several ways you can create event handlers.

3. Inside the handler, type the following:


Label1.
Visual Web Developer displays a list of available members for the Label control, as shown in the following screen shot.
Available Label control members

4. Finish the Click event handler for the button so that it reads as shown in the following code example.
VB
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Label1.Text = Textbox1.Text & ", welcome to Visual Web Developer!"
End Sub

C#
protected void Button1_Click(object sender, System.EventArgs e)
{
Label1.Text = TextBox1.Text + ", welcome to Visual Web Developer!";
}

5. Scroll down to the <asp:Button> element. Note that the <asp:Button> element now has the attribute
OnClick="Button1_Click". This attribute binds the button's Click event to the handler method you coded in step 4.
Event handler methods can have any name; the name you see is the default name created by Visual Web Developer. The
important point is that the name used for the OnClick attribute must match the name of a method in the page.
Note
If you are using Visual Basic with code separation, Visual Web Developer does not add an explicit OnClick attribute. Ins
tead, the event is bound to the handler method using a Handles keyword on the handler declaration itself.

Running the Page


You can now test the server controls on the page.
To run the page
1. Press CTRL+F5 to run the page in the browser.
The page again runs using the ASP.NET Development Server.
2. Enter a name into the text box and click the button.
The name you entered is displayed in the Label control. Note that when you click the button, the page is posted to the
Web server. ASP.NET then recreates the page, runs your code (in this case, the Button control's Click event handler
runs), and then sends the new page to the browser. If you watch the status bar in the browser, you can see that the page
is making a round trip to the Web server each time you click the button.
3. In the browser, view the source of the page you are running.
In the page source code, you see only ordinary HTML; you do not see the <asp:> elements that you were working with in
Source view. When the page runs, ASP.NET processes the server controls and renders HTML elements to the page that
perform the functions that represent the control. For example, the <asp:Button> control is rendered as the HTML
element <input type="submit">.
4. Close the browser.
Working with Additional Controls
In this part of the walkthrough, you will work with the Calendar control, which displays dates a month at a time. The Calendar
control is a more complex control than the button, text box, and label you have been working with and illustrates some further
capabilities of server controls.
In this section, you will add a Calendar control to the page and format it.
To add a Calendar control
1. In Visual Web Developer, switch to Design view.
2. From the Standard section of the Toolbox, drag a Calendar control onto the page:
The calendar's smart tag panel is displayed. The panel displays commands that make it easy for you to perform the most
common tasks for the selected control. The following screen shot shows the Calendar control as rendered in the Design
view.
Calendar control in Design view
3. In the smart tag panel, choose Auto Format.
The Auto Format dialog box is displayed, which allows you to select a formatting scheme for the calendar. The following
screen shot shows the Auto Format dialog box for the Calendar control.
Auto Format dialog box for the Calendar control

4. From the Select a scheme list, select Simple and then click OK.
5. Switch to Source view.
You can see the <asp:Calendar> element. This element is much longer than the elements for the simple controls you
created earlier. It also includes subelements, such as <WeekEndDayStyle>, which represent various formatting settings.
The following screen shot shows the Calendar control in Source view.
Calendar control in Source view
Programming the Calendar Control
In this section, you will program the Calendar control to display the currently selected date.
To program the Calendar control
1. From the left-hand drop-down list at the top of Source view, select Calendar1.
The drop-down list displays a list of all the objects you can write code for.
2. From the right-hand drop-down list, select SelectionChanged.
Visual Web Developer creates a skeleton event handler for the Calendar control's SelectionChanged event.
You have now seen two ways to create an event handler for a control. The first was to double-click the control in Design
view. The second is to use the drop-down lists in Source view to select an object and the event to write code for.
3. Finish the SelectionChanged event handler with the following highlighted code.
VB
Protected Sub Calendar1_SelectionChanged(ByVal sender As Object, ByVal e As System.Eve
ntArgs)
Label1.Text = Calendar1.SelectedDate.ToString()
End Sub

C#
protected void Calendar1_SelectionChanged(object sender, System.EventArgs e)
{
Label1.Text = Calendar1.SelectedDate.ToString();
}

Running the Page


You can now test the calendar.
To run the page
1. Press CTRL+F5 to run the page in the browser.
2. Click a date in the calendar.
The date you clicked is displayed in the Label control.
3. In the browser, view the source code for the page.
Note that the Calendar control has been rendered to the page as a table, with each day as a <td> element containing an
<a> element.
4. Close the browser.
Next Steps
This walkthrough has illustrated the basic features of the Visual Web Developer page designer. Now that you understand how
to create and edit a Web page in Visual Web Developer, you might want to explore other features. For example, you might
want to:
Learn more about how to edit HTML in Visual Web Developer. For details, see
Walkthrough: Basic HTML Editing in Visual Web Developer.
Add data access to Web pages. For details, see Walkthrough: Basic Data Access in Web Pages.
Learn about the debugger for Web pages. For details, see Walkthrough: Debugging Web Pages in Visual Web Developer.
Create Web pages that are specifically designed for mobile phones and other devices. For details, see
Walkthrough: Creating Web Pages for Mobile Devices.
Create a consistent site layout using master pages. For details, see
Walkthrough: Creating and Using ASP.NET Master Pages in Visual Web Developer.
Add navigation to your site so users can easily move between pages. For details, see
Walkthrough: Adding Site Navigation to a Web Site.
See Also
Tasks
Walkthrough: Creating a Local IIS Web Site in Visual Web Developer
Walkthrough: Editing Web Sites with FTP in Visual Web Developer
Concepts
Introduction to Visual Web Developer
Other Resources
Welcome
Visual Web Developer

Walkthrough: Creating a Basic Web Page with Code Separation


in Visual Web Developer
When you create ASP.NET Web pages and write code in them, you can choose from two models for how to manage the visible
elements (controls, text) and your programming code. In the single-file model, the visible elements and code are kept together
in the same file. In the alternative model, called "code separation," the visible elements are in one file and the code is in another
file, referred to as the "code-behind" file. This walkthrough introduces you to Web pages that use code separation.
The single-file model is introduced in Walkthrough: Creating a Basic Web Page in Visual Web Developer. The walkthrough you
are reading now shows you how to create a Web page with the same functionality as the page in the single-file walkthrough,
but with a focus on using code separation.
The choice between using single-file pages and pages with code separation is primarily one of convenience and personal
preference. Working with both models in Microsoft Visual Web Developer is similar; both models have approximately equal
support in the editor. Both models have equivalent performance when the page runs. The page with code separation makes it
more practical to let a Web designer work on the layout of a page while a programmer creates the code for the page, because
the two pages can be edited separately. For more information on the differences between these models, see
ASP.NET Web Page Code Model.
Tasks illustrated in this walkthrough include:
Using Visual Web Developer to create an ASP.NET page with code separation.
Adding controls.
Adding event handlers.
Running pages with the ASP.NET Development Server.
Prerequisites
In order to complete this walkthrough, you will need:
Visual Web Developer and the .NET Framework.
Creating a Web Site and Page
In this part of the walkthrough, you will create a Web site and add a new page to it. You will also add HTML text and run the
page in your Web browser.
If you have already created a Web site in Visual Web Developer (for example, by following the steps in
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and skip to "Creating a New
Page" later in this walkthrough. Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, select File System and enter the name of the folder where you want to keep the pages of your Web
site.
For example, type the folder name C:\BasicWebSite.
5. In the Language list, click Visual Basic or Visual C#.
Note
Visual Web Developer currently does not support creating code-behind pages in Visual J#.

The programming language you choose will be the default for your Web site, but you can set the programming language
for each page individually.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Creating a New Page
When you create a new Web site, Visual Web Developer adds a page named Default.aspx. By default, Visual Web Developer
creates a page with code separation.
To add a page with code separation to the Web site
1. Close the Default.aspx page. To do this, right-click the tab with the file name in it and select Close.
2. In Solution Explorer, right-click the Web site (for example, C:\WebSites) and choose Add New Item.
3. Under Visual Studio installed templates, choose Web Form.
4. In the Name box, type WebPageSeparated.
5. From the Language list, choose the programming language you prefer to use (Visual Basic or C#).
6. Verify that the Place code in separate file check box is selected.
By default, this check box is selected.
7. Click Add.
Visual Web Developer creates two files. The first file, WebPageSeparated.aspx, will contain the page's text and controls,
and is opened in the editor. A second file, WebPageSeparated.aspx.vb or WebPageSeparated.aspx.cs (depending on what
programming language you selected), is the code file. You can see both files in Solution Explorer by clicking the plus sign
(+) next to the WebPageSeparated.aspx file; the code file has been created but is not open. You will open it later in the
walkthrough when you write code.
Adding HTML to the Page
In this part of the walkthrough, you will add some static HTML text to the WebPageSeparated.aspx page.
To add text to the page
1. Click the Design tab at the bottom of the document window to switch to Design view.
Design view displays the page you are working on in a WYSIWYG-like way. At this point, you do not have any text or
controls on the page, so the page is blank.
2. Type the words Welcome to Visual Web Developer Using Code Separation.
3. Switch to Source view.
You can see the HTML that you created by typing in Design view. At this stage, the page looks like an ordinary HTML
page. The only difference is in the <%@ page %> directive at the top of the page.
Adding and Programming Controls
In this part of the walkthrough, you will add a button, text box, and label control to the page and write code to handle the
button's Click event. Server controls, which include buttons, labels, text boxes, and other familiar controls, provide typical form-
processing capabilities for your ASP.NET Web pages. However, you can program the controls with code that runs on the server,
not the client.
To add controls to the page
1. Click the Design tab to switch to Design view.
2. Press ENTER a few times to make some room.
3. From the Standard group in the Toolbox, drag three controls onto the page: a TextBox control, a Button control, and a
Label control.
4. Put the insertion pointer in front of the text box and type Enter your name:.
This static HTML text is the caption for the TextBox control. You can mix static HTML and server controls on the same
page.
Setting Control Properties
Visual Web Developer offers you various ways to set the properties of controls on the page. In this part of the walkthrough,
you will work with properties in both Design view and Source view.
To set control properties
1. Select the Button control and, in the Properties window, set its Text property to Display Name.
2. Switch to Source view.
Source view displays the HTML for the page, including the elements that Visual Web Developer has created for the server
controls. Controls are declared using HTML-like syntax, except that the tags use the prefix asp: and include the attribute
runat="server".
Control properties are declared as attributes. For example, when you set the button's Text property in Step 1, you were
actually setting the Text attribute in the control's markup.
Note that all the controls are inside a <form> element that also has the attribute runat="server". The runat="server"
attribute and the asp: prefix for control tags mark the controls so that they are processed by ASP.NET when the page
runs.
Programming the Button Control
For this walkthrough, you will write code that reads the name that the user enters in the text box and then displays it in the
Label control.
To add a default button event handler
1. Switch to Design view
2. Double-click the Button control.
Visual Web Developer opens the WebPageSeparated.aspx.vb or WebPageSeparated.aspx.cs file in a separate window in
the editor. The file contains a skeleton Click event handler for the button.
3. Complete the Click event handler by adding the following highlighted code.
VB
Protected Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Label1.Text = Textbox1.Text & ", welcome to Visual Web Developer!"
End Sub

C#
protected void Button1_Click(object sender, System.EventArgs e)
{
Label1.Text = TextBox1.Text + ", welcome to Visual Web Developer!";
}

Notice that as you type, IntelliSense helps you with context-sensitive choices. This is identical to the behavior when you
are coding in a single-file page.
Examining the Page and Code File
You now have two files that make up the complete WebPageSeparated page: WebPageSeparated.aspx and
WebPageSeparated.aspx.vb or WebPageSeparated.aspx.cs. In this section of the walkthrough, you will examine how these files
are structured and how they relate to each other.
To examine the page and code file
1. Click the WebPageSeparated.aspx tab at the top of the editor window to switch to the page file.
2. Switch to Source view.
At the top of the page is an @ page directive that binds this page to the code file. The directive looks like the following
code.
VB
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="WebPageSeparated.aspx.vb" Inh
erits="WebPageSeparated" %>

C#
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="WebPageSeparated.aspx.cs" Inhe
rits="WebPageSeparated" %>

(The line does not wrap in the editor, and the language attribute and file name extensions will match the programming
language you selected.)
When the page runs, ASP.NET dynamically creates an instance of a class representing the page. The Inherits attribute
identifies the class defined in the code-behind file from which the .aspx page is derived. By default, Visual Web Developer
uses the page name as the basis for the class name in the code-behind file.
The CodeFile attribute identifies the code file for this page. In simple terms, the code-behind file contains the event-
handling code for your page.
3. Click the WebPageSeparated.aspx.vb or WebPageSeparated.aspx.cs tab to switch to the code file.
The code file contains code that is similar to a class definition. However, it is not a complete class definition; instead, it is a
"partial class" that contains only a portion of the complete class that will make up the page. Specifically, the partial class
defined in the code file contains the event handlers and other custom code that you write. At run time, ASP.NET
generates another partial class containing your user code. This complete class is then used as the base class that is used
to render the page. For more information, see ASP.NET Page Class Overview.
Note
If you are familiar with the code-behind model used in Microsoft Visual Studio .NET 2003, you will notice that in the ne
w model, the code-behind class does not contain any generated code beyond the class definition itself. For example, th
e class does not contain instance variables for controls on the page. This type of generated code is no longer required.

Running the Page


You can now test the page.
To run the page
1. Press CTRL+F5 to run the page in the browser.
The page runs using the ASP.NET Development Server.
Note
If the browser displays a 502 error or an error indicating that the page cannot be displayed, you might need to configur
e your browser to bypass proxy servers for local requests. For details, see
How to: Bypass a Proxy Server for Local Web Requests.

2. Enter a name in the text box and click the button.


The name you entered is displayed in the Label control.
3. In the browser, view the source of the page you are running.
4. Close the browser.
The page works exactly the same as it would if it were a single-file page. (If you followed the steps in
Walkthrough: Creating a Basic Web Page in Visual Web Developer to create a single-file page, you can compare the two
pages to see that they are the same when running.)
Next Steps
This walkthrough has illustrated how to create and edit a Web page that uses code separation. From the perspective of creating
and running the page, there is not a significant difference between a single-file page and a page with code separation.
You might want to explore other features. For example, you might want to:
Create different types of Web sites. In addition to creating a file-system Web site as you did in this walkthrough, you can
work with Web sites using Microsoft Internet Information Services (IIS), SharePoint, and FTP. For details, see
Types of Web Sites in Visual Web Developer.
Learn more about how to edit HTML in Visual Web Developer. For details, see
Walkthrough: Basic HTML Editing in Visual Web Developer.
Add data access to Web pages. For details, see Walkthrough: Basic Data Access in Web Pages.
Learn about the debugger for Web pages. For details, see Walkthrough: Debugging Web Pages in Visual Web Developer.
Create a consistent site layout using master pages. For details, see
Walkthrough: Creating and Using ASP.NET Master Pages in Visual Web Developer.
See Also
Tasks
Walkthrough: Creating a Basic Web Page in Visual Web Developer
Concepts
Types of Web Sites in Visual Web Developer
Visual Web Developer

Walkthrough: Basic HTML Editing in Visual Web Developer


The Microsoft Visual Web Developer Web development tool provides a rich HTML editing experience that lets you work in
WYSIWYG mode for visualizing Web pages and also lets you work directly with HTML markup for finer control. This
walkthrough introduces you to the HTML editing features of Visual Web Developer.
Tasks illustrated in this walkthrough include the following:
Creating and editing HTML in Design view.
Creating and editing HTML in Source view.
Using navigation tools to move quickly through your HTML tags.
Prerequisites
In order to complete this walkthrough, you will need the following:
A general understanding of Visual Web Developer.
For an introduction to creating Web pages in Visual Web Developer, see
Walkthrough: Creating a Basic Web Page in Visual Web Developer.
In this walkthrough, you will work with a Web site and a single ASP.NET Web page that is similar to the one that is created in
Walkthrough: Creating a Basic Web Page in Visual Web Developer. If you have completed that walkthrough, you can use that
Web site and page.
Creating the Web Site and Page
If you have already created a Web site in Visual Web Developer (for example, by completing
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and go to the next section.
Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, enter the name of the folder where you want to keep the pages of the Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click the programming language that you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Working in Design View
In this part of the walkthrough, you will learn how to work in Design view, which provides a WYSIWYG-like view of the page.
You can add text by typing, as you would in a word processing program. You can format text directly with formatting
commands or by creating in-line styles.
Design view displays your page in a way that is similar to how it will appear in a browser, with some differences. The first
difference is that in Design view, the text and elements are editable. The second difference is that to help you edit your pages,
Design view displays some elements and controls that will not appear in the browser. Additionally, some elements, such as
HTML tables, have a special Design view rendering that adds additional space for the editor. Overall, Design view helps you
visualize your page, but it is not an exact representation of how the page will render in a browser.
To add and format static HTML in Design view
1. If you are not in Design view, click Design, which is located at the lower left of the window.
2. At the top of the page, type ASP.NET Web Page.
3. Highlight the text to format to select it, and then on the Format toolbar, in the left-most list, click Heading 1.
4. Position the insertion pointer below ASP.NET Web Page, and then type This page is powered by ASP.NET.
5. Right-click This page is powered by ASP.NET., and then click Style.
The Style Builder dialog box appears.
6. Click Font, and then in Family, click the ellipsis (…) button.
The Font Picker dialog box appears.
7. Under Installed fonts, click Verdana, and then click the add (>>) button.
8. Click OK to close the Font Picker dialog box.
9. Click Text, and then in the Horizontal list, click Centered.
10. Click OK.
Viewing Tag Information
When you are working in Design view, you might find it useful to see the design surface tags, such as div and span, and others
that do not have a visual rendering.
To see HTML design surface tags in Design view
On the View menu, click Details.
The designer displays symbols for paragraphs, line breaks, and other tags that do not render text.
Adding Controls and Elements
In Design view, you can drag controls from the Toolbox onto the page. You can add some elements, such as HTML tables, using
a dialog box. In this section, you will add some controls and a table so that you have elements to work with later in the
walkthrough.
To add controls and a table
1. Position the insertion pointer to the right of the closing paragraph mark for This page is powered by ASP.NET., and
then press ENTER.
2. From the Standard group in the Toolbox, drag a TextBox control onto the page.
Note
You can also add a control by double-clicking it.

3. Drag a Button control onto the page.


The TextBox and Button controls are ASP.NET Web server controls, not HTML elements.
4. On the Layout menu, click Insert Table.
The Insert Table dialog box appears.
5. Click OK.
The Insert Table dialog box provides options for configuring the table that you are creating. However, for this
walkthrough, you can use a default table layout.
Creating Hyperlinks
Design view provides builders and other tools to help you create HTML elements that require property settings.
To create a hyperlink
1. In the text This page is powered by ASP.NET., highlight ASP.NET to select it.
2. On the Format menu, click Convert to Hyperlink.
The Hyperlink dialog box appears.
3. In the URL box, type http://www.asp.net.
4. Click OK.
Setting Properties in the Properties Window
You can change the look and behavior of the elements on the page by setting values in Properties.
To set properties by using the Properties window
1. Click the Button control that you added in "Adding Controls and Elements," earlier in this walkthrough.
2. In Properties, set Text to Click Here, ForeColor to a different color, and Bold to true.
3. Place the insertion point in the ASP.NET hyperlink that you created in the preceding section.
Notice that in Properties, the HRef property for the a element is set to the URL that you provided for the hyperlink.
Testing the Page
You can see the results of your editing by viewing the page in the browser.
To start the page in the browser externally
Right-click the page, and then click View in Browser.
If you are prompted to save your changes, click Yes.
Visual Web Developer starts the Visual Web Developer Web server, which is a local Web server that you can use to test
pages without using IIS.
Changing the Default View
By default, Visual Web Developer opens new pages in Source view.
To change the default page view to Design view
1. On the Tools menu, click Options
2. In the Options dialog box, click HTML Designer, and then under Start Pages in, click Design view.
Note
You can run pages in several ways. If you press CTRL+F5, Visual Web Developer performs the start action that is configured
on the property page for Start Options. The default start option for CTRL+F5 is to run the current page; that is, the page that
is currently active in Source or Design view. You can also run pages in the debugger. For more information, see
Walkthrough: Debugging Web Pages in Visual Web Developer.

Working in Source View


Source view lets you edit the markup of the page directly. The Source view editor gives you many features that help you as you
create HTML and ASP.NET controls. You can use the Toolbox in Source view just as you do in Design view to add new elements
to the page.
To add elements in Source view
1. Switch to Source view by clicking Source, which is located at the lower left of the window.
The controls that you have added are created as <asp:> elements. For example, the Button control is the <asp:button>
element. The property settings that you made are preserved as attribute settings in the <asp:button> tag.
2. From the HTML group in the Toolbox (not the Standard group), drag a Table control onto the page and place it just
above the closing </form> tag.
The editor also helps you when you type markup manually. For example, the editor provides context sensitive choices finishing
HTML tags and attributes as you type. The editor also provides error and warning information on markup by underlining
questionable markup with a wavy line. The error or warning information is available by positioning the mouse over the
markup text.
To edit HTML in Source view
1. Position the insertion point above the closing </form> tag, and then type a left angle bracket (<).
Notice that the editor offers you a list of tags that are appropriate in the current context.
2. Highlight a to select it, and then press the SPACEBAR.
The editor displays a list of attributes that are appropriate for an anchor tag.
3. In the list, click href, and then type an equal sign and a double quotation mark (=").
The editor offers you a list of currently available pages to link to and an option to open the Homepicker dialog box.
4. In file list, double-click Default.aspx, press the SPACEBAR, and then type a right angle bracket (>) to close the tag.
The editor inserts a closing </a> tag.
5. Finish the anchor element so that it links to the Default.aspx page using the link text Home and reads as follows:

<a href="Default.aspx">Home</a>

6. Position the insertion point in the a tag.


Notice that Properties displays the attributes for the tag.
7. In Properties, for the HRef property, click the ellipsis (…) button.
The Select Project Item dialog box appears.
Now, you can select a page in the current Web site as the target page. If you do not have other pages in the Web site to
choose from, close the Select Project Item dialog box and type a favorite URL into the Href box of the Properties
window.
8. Position the insertion point just above the closing </form> tag, and then type <invalid>.
The editor underlines the tag with a wavy line, indicating that the tag is not a recognized HTML tag.
9. Remove the tag that you created in the preceding step.
Examining HTML Formatting
An important feature of the page designer is that it preserves the HTML formatting that you apply to the page unless you
explicitly specify that the editor reformat the document.
To examine HTML formatting
1. Reformat the attributes for the Button control by aligning the attributes so that the declarative syntax looks like the
following:

<asp:Button
id="Button1"
runat="server"
Font-Bold="True"
ForeColor="Blue"
Text="Click Here" />

Notice that after you indent the first attribute, if you press ENTER in the tag, subsequent lines are indented to match.
2. Switch to Design view.
3. Right-click the new Button control, and then click Copy.
4. Position the insertion point below the new Button control, right-click, and then click Paste.
This creates a button with the ID of Button2.
5. From the Standard group in the Toolbox, drag a third Button control onto the page, which creates <Button3>.
6. Switch to Source view.
Notice that <Button2> is formatted exactly the way that you formatted <Button1>. On the other hand, <Button3> is
formatted using the default formatting for asp:button elements.
Note
For more information on how to customize the formatting of individual elements, see
Walkthrough: Advanced HTML Editing in Visual Web Developer.

7. Edit the document so that <Button1> and <Button2> are on the same line without a space between them:

<asp:Button ID="Button1" runat="server" Font-Bold="True"


ForeColor="Blue" Text="Click Here" /><asp:Button ID="Button2"
runat="server" Font-Bold="True" ForeColor="Blue" Text="Click Here"/>

The elements can wrap, but the end of <Button1> (that is, />) must be followed immediately by the beginning of
<Button2> (that is <asp:Button ID=).

8. Switch to Design view.


Notice that <Button1> and <Button2> are right next to each other without a space between them.
9. Switch to Source view
10. On the Edit menu, point to Advanced, and then click Format Document.
The document is reformatted, but <Button1> and <Button2> remain on the same line. If the editor were to separate the
buttons, it would introduce a space during rendering. Therefore, the editor does not change the formatting that you have
created.
Navigating Between Elements
As pages become larger and more complex, it is useful to be able to find tags quickly and to reduce the clutter in the page.
Visual Web Developer provides the following tools to help you with these tasks when you are working in Source view:
Document Outline, which provides a complete view of the document.
Tag navigator, which provides information about the currently selected tag and where it is in the page hierarchy.
To start, add more elements to the page so that you will be able to examine navigation features.
To add elements
1. Switch to Design view.
2. From the HTML group in the Toolbox, drag a Table control into a cell of the table that you created in "Working in Source
View," earlier in this walkthrough.
3. From the Standard group in the Toolbox, drag a Button control into the middle cell of the nested table.
With several nested elements on the page, you can see how Document Outline provides quick navigation to any tag in the
page.
To navigate with Document Outline
1. Switch to Source view.
2. On the View menu, point to Other Windows, and then click Document Outline.
3. In Document Outline, click Button4.
In the editor, the <Button4> control that you added in the preceding procedure is selected.
4. Right-click the <table> tag of the outer table, and then click Synchronize Document Outline.
The selection in Document Outline is moved to the outer table tag.
The tag navigator provides information about the currently selected tag and where it is in the page hierarchy.
To navigate with tag navigator
1. Position the insertion point in the <asp:button> tag.
Notice the tag navigator at the bottom of the window, which shows the <asp:button> tag and its parent tags. The tag
navigator includes the ID of the element, if any, so that you can identify which element is being displayed. The tag
navigator also displays the assigned cascading style sheet, if any, that was set with the Class attribute.
2. In the tag navigator, click the <table> tag that is closest to the <asp:button#Button4> tag.
The tag navigator moves to the inner <table> element and selects it.
3. In the tag navigator, click the <td> tag to the left of the selected <table>.
The whole cell that contains the nested table is selected.
Note
You can click to select either the tag or its contents by using the drop-down list in the tag navigator tag. By default, click
ing a tag in the tag navigator selects the tag and its contents.

You can also use the tag navigator to help you move or copy elements.
To move or copy elements using the tag navigator
1. Using the tag navigator, select the <tr> tag that contains <Button4>.
2. Press CTRL+C to copy the tag.
3. Use the tag navigator to move to the outer table.
4. In Source view, place the insertion pointer between the <table> tag and the first <tr> tag.
5. Press CTRL+V to paste the copied row into the table.
6. Switch to Design view.
Notice that the new row has been added, including a Button control.
Formatting Text
The Formatting toolbar applies inline styles for most settings. Bold and italic formatting is applied by using the b and i
tags. Paragraph formatting is applied a block tag, such as p (for normal), pre (for formatted), and so on. Paragraph
alignment is applied by using inline styles to conform with XHTML 1.1 standards.
The designer also lets you create a style block and a link to a cascading style sheet. For more information, see
Walkthrough: Working with Cascading Style Sheet Styles in Visual Web Developer.
By default, the editor creates markup that is compatible with the XHTML 1.1 standard and converts all HTML tag names
to lowercase, even if you type them in uppercase. The editor also encloses attribute (property) values in quotation marks.
For more information, see Walkthrough: Advanced HTML Editing in Visual Web Developer.

To change the default markup validation


1. In Source view, right-click the page, and then click Formatting and Validation.
2. In the Options dialog box, expand Text Editor, expand HTML, and then click Validation.
3. In the Target list, enter a validation type.
Next Steps
This walkthrough has given you an overview of the HTML capabilities of the Web page editor. This includes how to create
HTML in Design view and Source view, basic formatting, and navigation. You might want to learn more about the editing
facilities in Visual Web Developer. For example, you might want to do the following:
Learn about the additional capabilities of the HTML editor, including custom formatting options, outlining, and HTML
validation. For more information, see Walkthrough: Advanced HTML Editing in Visual Web Developer.
Learn how to work with cascading style sheet styles. For more information, see
Walkthrough: Working with Cascading Style Sheet Styles in Visual Web Developer .
See Also
Tasks
Walkthrough: Advanced HTML Editing in Visual Web Developer
Reference
Source View
Concepts
Design View
Visual Web Developer

Walkthrough: Working with Cascading Style Sheet Styles in


Visual Web Developer
The Visual Web Developer Web development tool gives you complete support for creating and applying styles to the text,
elements, and controls on Web pages.
Tasks illustrated in this walkthrough include the following:
Setting inline styles for individual elements.
Creating a style block for a page.
Creating a cascading style sheet (.css file), and then applying the .css file to one or more pages in your site.
Changing style sheet references programmatically.
Note
In addition to explicitly setting styles and style sheet references in a page, you can use ASP.NET themes to set the overal
l appearance of the pages in your site. For more information, see ASP.NET Themes and Skins Overview.

Prerequisites
In order to complete this walkthrough, you will need the following:
Visual Web Developer and the .NET Framework.
A general understanding of working in Microsoft Visual Studio.
For an introduction to Visual Studio, see Walkthrough: Creating a Basic Web Page in Visual Web Developer.
Creating the Web Site and Page
In the first part of the walkthrough, you will create a Web site and a page where you can work with styles.
If you have already created a Web site in Visual Studio by completing
Walkthrough: Creating a Basic Web Page in Visual Web Developer, you can use that Web site and go to the next section.
Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. In the Language list, click the programming language that you prefer to work in.
The programming language that you choose will be the default for the Web site, but you can set the programming
language for each page individually.
4. Under Visual Studio installed templates, click ASP.NET Web Site.
5. In the right-most Location box, type the name of the folder where you want to keep the pages of the Web site.
For example, type the folder name C:\WebSites.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Adding Controls
The next step is to add some controls to the page. The code will be simple, but enough to let you add breakpoints later.
To add controls
1. Switch to Design view.
2. From the Standard group in the Toolbox, drag the following controls onto the page and set their properties as shown.

a. Control a. Properties

Label ID: CaptionLabel


Text: (empty)

TextBox ID: NumberTextbox


Text: (empty)

Button ID: SquareButton


Text: Square

Label ID: ResultLabel


Text: (empty)
Note
For this walkthrough, the layout of the page is not important.

Setting Inline Styles


You set inline styles when you want to apply formatting to a single element on the page. Visual Web Developer gives you a
rich editor for editing inline styles for elements on the page. In this section of the walkthrough, you will set styles in both
Design view and Source view.
To set inline styles in Design view
1. Switch to Design view.
2. Right-click CaptionLabel, and then click Style.
The Style Builder dialog box appears.
The Style Builder helps you set style information by organizing style information into logical categories and offering
you appropriate values and options for each style setting.
3. Click Font, click Family, and then click the ellipsis (...) that is located to the right of the text box.
The Font Picker dialog box appears.
Under Installed fonts, click Arial, and then click add (>>).
Arial appears under Selected fonts.
4. Repeat the preceding step to add Times New Roman and Verdana to the list of selected fonts, and then click OK.
When you return to the Style Builder dialog box, the three font names are in the Family box. You have created the list
of fonts that will be used to render the contents of the Label control in order of preference.
5. Under Size, click Specific, in the box, type 1.2, and then in the list, enter em.
By setting the size to 1.2 ems, you are indicating that the text will appear 1.2 times larger than the current font size
setting in the user's browser. At the bottom of the dialog box, you can see a preview of what the text will look similar to.
6. Click Background, click the ellipsis (…) that is located to the right of the Color box, and in the Color Picker dialog box,
click a color.
7. Click OK to close the Style Builder dialog box.
The text in the label now reflects the style settings that you made.
From these few steps, you can see that the Style Builder lets you set any inline style for any element without requiring that you
know the syntax.
If you prefer working directly with HTML, you can also set styles in Source view.
To set inline styles in Source view
1. Switch to Source view.
The <asp:label> element for the CaptionLabel control now has a style attribute that reflects the settings that you
made in the Style Builder.
2. Position the insertion pointer on a space in the <asp:button> element, and then type style=.
Note
The editor always puts quotation marks around the style attribute, regardless of the formatting options that you have s
et. For more information, see Walkthrough: Advanced HTML Editing in Visual Web Developer.

3. Double-click background-color, and then type a colon (:).


Microsoft IntelliSense functionality displays a list of color names. A ToolTip displays the syntax for the background-
color style setting.
4. Double-click Blue, type a semicolon (;), which is the delimiter between style settings, and then press SPACEBAR to
display IntelliSense functionality.
5. Double-click color, type a colon (:), and then double-click a contrasting color, such as Yellow or White.
6. To see the effect of your choices, switch to Design view.
Creating and Applying a CSS Style Sheet
Besides setting inline styles for individual elements, you can also create and apply cascading style sheet (CSS) files. A cascading
style sheet lets you define styles that can be applied to multiple controls and pages without having to edit elements
individually.
In this section of the walkthrough, you will create a style sheet, which lets you use the same tools that you used to set inline
styles. You will then apply the style sheet to the page that you have been editing.
To create a style sheet
1. In Solution Explorer, right-click the name of the Web site (for example, C:\WebSites), and then click Add New Item.
2. Under Visual Studio installed templates, click Style Sheet.
3. In the Name box, type dark.css, and then click Add.
The editor opens with a new style sheet that contains a body style element.
4. Position the insertion pointer between the opening and closing braces ({ }), and then on the Styles menu, click Build
Style.
The Style Builder - body dialog box appears.
5. Click Font, under Font Attributes, click the ellipsis (…) that is located to the right Color box, in the Color Picker dialog
box, click a light color, and then click OK.
Note
Be sure to select a color that is different from the default color of the pages in the Web site.

6. Click Background, click a dark color, such as Maroon, that contrasts with the font color you selected in the preceding
step, and then click OK to close the Style Builder- body dialog box.
7. Position the insertion pointer after the closing brace of the body element, right-click, and then click Add Style Rule.
The Add Style Rule dialog box appears.
The Add Style Rule dialog box lets you create new styles that are bound to a particular HTML element type, to a style
class name, or to a specific element.
8. Click Class name, and then in the box, type reverse.
This will create a new style class named reverse. You will be able to apply the style settings that you defined for the
reverse class to any element on your page. You could optionally create the class so that it applies to only specific types of
elements (anchors, buttons, and so on), but in this walkthrough you will create a simple style class.
9. Click OK to close the Add Style Rule dialog box.
10. Use the style builder or IntelliSense functionality to set the colors for the reverse style to the opposite of the styles for
the body. The element will look similar to the following:

.reverse
{
background-color:white;
color:maroon;
}

Now that you have a style sheet, you can reference it in the page you have been editing.
To reference the style sheet on the Web page
1. Open Default.aspx page and switch to Design view.
2. From Solution Explorer, drag the dark.css file onto the page.
The page is updated, displaying the effect of the style sheet.
3. Click ResultLabel, and then in Properties, set CssClass reverse.
This applies the reverse style to ResultLabel.
4. Switch to Source view.
In the <head> element, you can see that the editor has added a <link> element that references the style sheet. You can
also see that the cssclass attribute of the second <asp:label> element has been set to reverse.
5. Right-click the page, and then click View in Browser.
The page appears in the browser with the style sheet applied.
Changing Style Sheets Programmatically
Sometimes, you might want to be able to dynamically change the style sheet that is referenced by a page. In this part of the
walkthrough, you will create a second style sheet, and then in your page, write several lines of code that switch style sheets
programmatically.
To create a new style sheet
1. In Solution Explorer, right-click the Web site name, and then click Add New Item.
2. Under Visual Studio installed templates, click Style Sheet, in the Name box, type light.css, and then click Add.
3. In the new style sheet, use the Style Builder or IntelliSense functionality to create the following styles:

body
{
background-color:white;
color:Black;
}
.reverse
{
background-color:Black;
color:White;
}

4. Save the new style sheet.


In your original page, you can now add the ability to switch style sheets. You will add two radio buttons that let the user select
between a dark look and a light look.
To let users change style sheets
1. Open the Default.aspx page and switch to Source view.
2. In the <link> element, which is in the <head> element, add the attribute ID="stylesheet".
The tag will look similar to the following:

<link href="dark.css" type="text/css" rel="stylesheet" id="stylesheet" />

Adding these two attributes makes the <link> element a server control that you can program using server-based code.
3. Switch to Design view, and then from the Standard group in the Toolbox, drag two RadioButton controls onto the
page.
Note
The layout of the RadioButton controls is not important for this walkthrough.

4. Set the following properties for the RadioButton controls.

a. Control a. Properties

RadioButton1 ID: radioDark


AutoPostBack: true
Checked: true
GroupName: grpSelectStylesheet
Text: Dark

RadioButton2 ID: radioLight


AutoPostBack: true
Checked: false
GroupName: grpSelectStylesheet
Text: Light

5. Click radioDark and on the Properties toolbar, click the events icon to display available events.
6. In the CheckedChanged box, type SwitchStylesheets, and then press ENTER.
The editor creates a handler for the CheckedChanged event of the radioDark control.
7. Type or copy the following code, which switches the Href attribute of the <link>.
VB
Protected Sub SwitchStylesheets(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles radioDark.CheckedChanged
If radioDark.Checked Then
stylesheet.Href = "dark.css"
ElseIf radioLight.Checked Then
stylesheet.Href = "light.css"
End If
End Sub

C#
protected void SwitchStylesheets(Object sender, EventArgs e)
{
if (radioDark.Checked)
stylesheet.Href = "dark.css";
if (radioLight.Checked)
stylesheet.Href = "light.css";
}

The code determines which option button is selected and sets the Href attribute of the <link> element, which you
named stylesheet, appropriately.
8. Switch to Design view.
9. Click radioLight, and in Properties, click the events icon.
10. In the CheckedChanged box, click SwitchStylesheets.
This binds the CheckedChanged event of the radioLight control to the handler that you have already written to switch
style sheets. Both radio buttons will call the same handler when they are clicked.
You can now test your page.
To test the page
1. Press Ctrl+F5 to run the page.
2. Click Light.
The appearance of the page changes.
3. Click Dark to make sure that both option buttons work.
Next Steps
This walkthrough has illustrated the basic techniques for working with CSS styles in your ASP.NET Web pages. You might also
want to explore the following ways you can control the appearance of the Web pages:
Setting style information programmatically for HTML elements.
For more information, see How to: Set HTML Server Control Properties Programmatically.
Creating styles programmatically and applying the styles to ASP.NET server controls.
Creating themes and skins, which let you specify not only CSS styles, but virtually any property of an ASP.NET control.
For details, see ASP.NET Themes and Skins Overview.
Visual Web Developer

Walkthrough: Advanced HTML Editing in Visual Web


Developer
The Microsoft Visual Web Developer Web development tool provides a rich HTML editing experience for creating Web pages.
This walkthrough introduces some of the more advanced HTML editing features of Visual Web Developer.
Note
For an introduction to HTML editing, see Walkthrough: Basic HTML Editing in Visual Web Developer.

Tasks illustrated in this walkthrough include the following:


Specifying options for how the HTML editor formats elements in the page.
Selecting options so that the HTML editor that you create is compatible with specific browsers.
Outlining your page — that is, creating collapsible regions in the editor to reduce clutter.
Prerequisites
In order to complete this walkthrough, you will need:
A general understanding of working in Visual Web Developer.
For an introduction to Visual Web Developer, see Walkthrough: Basic HTML Editing in Visual Web Developer.
Creating the Web Site and Page
If you have already created a Web site in Visual Web Developer (by completing
Walkthrough: Basic HTML Editing in Visual Web Developer), go to the next section. Otherwise, create a new Web site and page
by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, enter the name of the folder where you want to keep the pages of the Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click the programming language that you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Note
By default, Visual Web Developer creates ASP.NET Web pages using the code-behind model. For more information, see
ASP.NET Web Page Code Model. In this walkthrough, you will not be using the code-behind page.

Formatting Markup
The HTML editor provides a variety of options to help you format the markup in your pages according to your own
preferences. Formatting options include the following:
Whether tag and attribute names are in uppercase or lowercase letters. You can specify options separately for HTML tags
and ASP.NET Web server controls.
Whether attributes are added by enclosing them in quotation marks.
Whether elements are closed automatically by the editor. Choices include creating self-closing tags (for example, <br />),
creating opening and closing tags (<p></p>), and automatically inserting closing tags.
How child elements of a tag are indented.
Where line breaks are positioned around tags.
Regardless of what formatting options you set, an important feature of HTML formatting is that you have ultimate control over
the layout and appearance of the markup in the page. You can format elements manually (for example, by indenting them),
and the editor leaves your formatting as is unless you explicitly make a request to have the markup reformatted.
In this part of the walkthrough, you will explore different formatting options and see the effect of different settings. You will
also learn how to apply formatting to the whole page or to a selection within the page.
Note
This walkthrough reviews only the formatting features that are unique to working with HTML. As a Visual Web Developer tex
t editor, the HTML editor also supports various options that apply to all text editing, such as setting tab size and line wrap. For
information about general text editing options, see Editing Text, Code, and Markup.

In this part of the walkthrough, you will add some simple HTML to the page, change formatting options, and then add more
HTML. This illustrates how changing the settings affects how the HTML is formatted.
To add HTML elements that have default formatting options
1. Switch to Design view.
2. On the Layout menu, click Insert Table, and then click OK.
Do not change any one of the default settings in the dialog box.
The designer creates an HTML table with three columns and three rows.
3. Below the table, click the page.
4. Press ENTER several times to create some blank space, and then from the HTML group in the Toolbox, drag an Image
control onto the page.
5. Switch to Source view.
You will see that the <table> and <img> elements have been inserted in the page.
By default, the designer creates elements in which the tag and attribute names are lowercase and attributes are enclosed
in quotation marks.
You can now change the formatting options.
To change formatting and validation options
1. On the Tools menu, click Options.
2. Click Validation, and then in the Target list, click Internet Explorer 6.0.
3. Click Format.
You can set some options separately for server tags (ASP.NET server controls) and client tags (HTML elements).
4. In the Client tag list, click Uppercase.
5. Clear the Insert attribute value quotes when formatting and Insert attribute value quotes when typing check
boxes.
6. Click OK to return the editor.
Notice that although you changed formatting options, the existing markup in the page does not change.
You can now add new elements.
To add HTML elements using the new formatting options
1. Scroll to the bottom of the page.
2. From the HTML group in the Toolbox, drag a Table control onto the page and position it above the </form> tag.
This time, the tags in the <TABLE> element are in uppercase letters.
3. Below the table that you just created, position the insertion point, and then type a right angle bracket (<) to start a new
tag.
A list appears in which all the tag names are offered in uppercase, because that is the option that you have set for
formatting.
4. In the list, double-click IMG, and then press the SPACEBAR.
A list of attributes for the <img> tag appears. The attributes are in lowercase, because when you set formatting options,
you left Client attributes as the default setting for Lowercase.
5. In Properties, set Src to graphic.gif, which is an invented graphic file name, and make sure that the tag now looks
similar to the following:

<IMG src=graphic.gif

Because you disable the Insert attribute value quotes when typing option in the preceding procedure, the editor does
not automatically enclose the attribute in quotation marks.
Note
The editor inserts quotation marks, regardless of the options setting, if the attribute requires them, such as when an att
ribute value contains a space.

6. Type a slash mark (/) and a right angle bracket (>) to close the <img> tag.
As noted earlier in this section, the formatting options that you set were not applied to existing markup in the page. However, if
you want, you can apply formatting settings to the page or to individual elements in the page.
To apply formatting to existing elements
1. In Source view, highlight to select the first table that you created.
2. On the Edit menu, click Format Selection.
The tag names are changed to uppercase.
Note
The editor does not remove quotation marks, even if you change the option setting. Similarly, the editor does not chan
ge the termination of existing tags, even if you change the option for how to close tags.

You can see from this example how formatting works in the HTML editor. When you use editing tools, such as Toolbox or
Properties, to edit elements, the editor uses the current set of formatting options to generate the markup. However, the editor
does not change any existing markup. If you want to apply new formatting options to existing markup, you can apply it
manually by using the Edit menu commands.
Setting Tag Formatting Options
The formatting options that you have worked with up to this point apply to all elements in the page. If you want, you can
specify formatting options for individual tags also. This is useful if you frequently use certain tags and want to use non-default
formatting for those tags. Per-tag formatting lets you set the following formatting options:
How the tags are closed—that is, not closed, self-terminated, or with a separate closing tag.
How line breaks are used around and within tags.
How child elements of a tag are indented.
Note
Tag-specific formatting rules that you specify can be overridden by the rule that the HTML editor will not change the re
ndering of tags. If a tag formatting rule would change the way a tag is rendered, the rule is ignored.

In this part of the walkthrough, you will set several tag formatting options and see how the editor works with them. Up to this
point, you have worked with HTML elements, such as the <table> element. Now, you will work with some ASP.NET server
controls, so that you can see that formatting options apply equally to controls and elements.
You will start by setting some options that apply to all tags of a certain type. You can set options for the following types of
elements:
HTML elements that do not have content, such as br and input.
HTML elements that can have content, such as table and span.
Server elements (asp:) that cannot have content, such as asp:image.
Server elements that can have content, such as asp:textbox.
Security Note
A TextBox control accepts user input, which is a potential security threat. By default, ASP.NET Web pages validate that user in
put does not include script or HTML elements. For more information, see Script Exploits Overview.

For the first part of this section, you will add an HTML table. You will then change the tag formatting rules for table elements
and reformat the document to see the effect of changing the formatting rule.
To set tag-formatting rules for an HTML table
1. In Source view, in a blank part of the window, right-click, and then click Formatting and Validation.
The Options dialog box appears with the options for formatting that you set in the preceding section.
2. In the Client Tag list, click Lowercase to reset the formatting for client tags.
3. Click OK to close the Options dialog box.
4. From the HTML group in the Toolbox, drag a Table control onto the page.
The editor creates a <table> element that has three rows (<tr> elements) and three cells (<td> elements) in each row.
Each tag is on a separate line:

<table>
<tr>
<td>
</td>
</tr>

5. In a blank part of the window, right-click, and then click Formatting and Validation.
6. Click Tag specific options.
7. Expand Default Settings.
A list of tag types appears, starting with Client tag does not support contents. By selecting an item in the list, you can
set different options for client and server elements, for elements that have content (such as a table element), and for
elements that do not (such as an img element).
8. Click Client tag supports contents.
Notice that the default setting is that tags use a separate closing tag and that the tags have line breaks before, within, and
after the tag.
9. Expand Client HTML tags.
10. Click td.
You will set options to change how td tags are formatted.
11. In the Line breaks list, click None.
12. Click OK to close the Tag Specific Options dialog box, and then click OK to close the Options dialog box.
13. On the Edit menu, click Format Document.
The document is reformatted. The <td> tags in the table that you added are placed in a single line:

<table>
<tr>
<td></td><td></td><td></td>

You can work with tag-specific options for an ASP.NET server control.
To set formatting options for an ASP.NET server control
1. Switch to Design view.
2. From the Standard group in the Toolbox, drag a ListBox control onto the page.
3. Right-click the ListBox control, and then click Show Smart Tag.
4. In the ListBox Tasks dialog box, click Edit Items.
The ListItem Collection Editor dialog box appears.
5. Click Add two times to add two items.
6. Under Members, click the first ListItem, and then under ListItem properties, set Text to Item 1.
7. Under Members, click the first ListItem, and then under ListItem properties,, set Text to Item 2.
8. Click OK to close the ListItem Collection Editor dialog box.
9. Switch to Source view.
Notice that the control has been formatted in the following manner:

<asp:Listbox ID="ListBox1" runat="server">


<asp:ListItem>Item 1</asp:Listitem>
<asp:ListItem>Item 2</asp:Listitem>
</asp:Listbox>

10. In a blank part of the window, right-click, and then click Formatting and Validation.
11. Click Tag specific options.
12. In the Tag Specific Options dialog box, click ASP.NET Controls, and then click New Tag.
13. In the Tag name box, type asp:listitem.
Do not type the right and left angle brackets (< and >) as part of the tag name.
You are setting options for the asp:ListItem element that is used inside a ListBox control. You are not setting options for
the asp:ListBox element, because you want to control how the contents (children) of the asp:ListBox element are
formatted.
14. Click OK to close the New Tag dialog box.
15. In the Line breaks list, click None.
This will cause the control to have no line breaks in it.
16. Click OK to close the Tag Specific Options dialog box, and then click OK to close the Options dialog box.
You can now see the effect of your new formatting options.
To add an ASP.NET server control using the new formatting options
1. Switch to Design view.
2. From the Standard group in the Toolbox, drag a second ListBox control onto the page.
3. Right-click ListBox, and then click Show Smart Tag.
4. On the ListBox Tasks menu, click Edit Items.
5. For the ListBox control, create two items as you did in the preceding procedure.
6. Switch to Source view.
Notice that the <asp:ListItem> elements are all on one line. The </asp:ListBox> element appears on the next line
because tag wrapping is set to 80 characters. You can modify this value in the Options dialog box.
Although you worked with only two controls and changed only one formatting option (line breaks), you can see how to apply
options to any element that you typically work with.
Outlining Elements
In Source view, you can outline elements (collapse and expand them) so that they are out of your way when you are not
working with them. This is particularly useful for elements such as tables, which often take up a lot of space. You can also use
the collapse feature for any elements in the page.
To outline elements
1. Switch to Source view.
2. Select one of the tables that you added earlier.
If you no longer have the tables, from the HTML group in the Toolbox, drag one onto the page.
3. On the Edit menu, point to Outlining, and then click Hide Selection.
The <table> tag is collapsed and a plus sign (+) is displayed in the margin.
4. Click the plus sign to expand the table element.
You can also configure elements so that the plus (+) and minus (-) signs appear automatically in the margin when the
elements exceed a certain size.
To configure how elements are outlined automatically
1. Right-click the page, click Formatting and Validation, click Format, and then click Tag specific options.
2. In the Tab Specific Options dialog box, expand Client HTML tags, and then click table.
3. Under Outlining in code editor, in the Minimum lines box, enter 5.
4. Click OK, and then click OK.
For existing tables and any new tables that are added, outlining appears automatically, if the table exceeds five lines.
Validating HTML
The HTML editor can validate your HTML or make sure that it complies with the rules for specific browsers or standards, such
as XHTML. For example, the editor can find tags and attributes that are not accepted by Netscape Navigator 4.0 or that do not
comply with XHTML standards.
In this part of the walkthrough, you will work with different schemas (browser types or standards) and introduce various types
of small errors to see how the editor flags the errors.
To test validation in the editor
1. In Source view, open or switch to the Default.aspx page.
2. On the HTML Source Editing toolbar, in the list, click Internet Explorer 3.02/Netscape Navigator 3.0.
3. Scroll to the bottom of the page.
4. Inside the </form> tag, type the following HTML:

<font face=arial>
<a href=Default.aspx >Default Page </a>
</font>

As you type, Microsoft IntelliSense technology provides assistance in completing the tags.
5. On the HTML Source Editing toolbar, in the list, click XHTML 1.0 Transitional (Netscape 7, Opera 7, Internet Explorer
6).
After a short pause (because validation is performed as a background task), you see red squiggly lines underneath
various parts of the tags. Like a spell checker, the HTML validation feature finds markup in your page that is not
acceptable for the currently selected browser.
6. In the <font> tag, rest the mouse pointer over the word font.
A ToolTip informs you that the font element is considered outdated. Current standards now recommend that you use
cascading style sheet styles for text formatting. For example, <span style="font-name:Arial;">.
7. In the href attribute of the <a> tag, rest the mouse pointer over Default.aspx.
A ToolTip informs you that in the current schema, attributes must be enclosed in quotation marks.
8. Enclose Default.aspx in quotation marks.
The value for the href attribute is no longer underlined. If you use relative references for anchor tags or other tags that
require a URL, validation determines whether the target element is available.
9. In the line below the HTML you are working with, type a right angle bracket (<).
The IntelliSense drop-down list appears, but this time it does not offer font, because the font element is not valid in
XHTML schemas.
10. Delete the right angle bracket (<).
Setting Validation Options
You can control the types of errors that validation shows you. This is useful if you want validation to find certain types of
errors, even if the errors would be allowed in a particular schema.
To set validation options
1. Right-click anywhere in the page, and then click Formatting and Validation.
Note
The Formatting and Validation command is available only in Source view.

2. In the Options dialog box, click Validation.


Notice that regardless of whether you select or clear the Show errors check box, the error display for check boxes is not
enabled. This is because the current schema is XHTML, which already shows you all possible validation errors.
3. In the Target list, click Internet Explorer 6.
4. Make sure that the Show errors check box is selected, and then under Show errors, select all check boxes.
5. Click OK to return to the editor.
6. Select the HTML that you entered in the preceding procedure, and then on the Edit menu, click Make Uppercase.
After a brief pause, the tag names are underlined. When you rest the mouse pointer over a tag name, a ToolTip indicates
that the name contains uppercase letters. Generally, Internet Explorer 6 allows for uppercase tag names, but you now see
this validation error because you have changed the validation options for that schema.
Validation can find many other types of errors also, such as duplicated control IDs, crossed opening and closing tags (for
example, <b><i></b></i>), and so on. However, validation in the editor does not prevent you from creating any HTML code
that you want. Validation just identifies markup that does not comply with the rules for the specified browser.
You should understand that when an ASP.NET page runs, the resulting output consists not only of the HTML elements that you
create, but also of the HTML that is rendered by ASP.NET server controls and any code that writes to the page. Validation
cannot examine the output of those dynamic elements; that is, the editor cannot examine the validity of generated output. By
default, ASP.NET controls generate output that complies with XHTML 1.1 standards. This means that the output is suited for
most browsers. For more information about the markup that is generated by ASP.NET controls, see ASP.NET and XHTML.
Next Steps
This walkthrough has introduced you to some of the more advanced features of the HTML editor. Although the walkthrough
did not illustrate every feature, you have seen how formatting options, outlining, and validation can help you produce well-
formed, custom-formatted markup, although still giving you final control over the markup.
See Also
Concepts
XHTML in Visual Web Developer
Markup Validation in Visual Web Developer
Other Resources
Editing Text, Code, and Markup
Product Support and Accessibility
Visual Web Developer

Walkthrough: Code Editing in Web Pages in Visual Web


Developer
Many ASP.NET Web pages involve writing code in Visual Basic, C#, or another language. The code editor in the Microsoft Visual
Web Developer Web site development tool can help you write code quickly while helping you avoid errors. In addition, the
editor provides ways for you to create reusable code to help reduce the amount of work you need to do.
This walkthrough illustrates various features of the code editor. Some of the features of the code editor depend on what
language you are coding in. Therefore, in this walkthrough you will create two pages, one that uses Visual Basic as its
programming language and another that uses C#.
During this walkthrough, you will learn how to:
Correct errors (in Visual Basic).
Refactor and rename code (in C#).
Rename symbols.
Insert code snippets (in Visual Basic and C#).
Prerequisites
In order to complete this walkthrough, you will need:
A general understanding of working in Visual Web Developer.
For an introduction to Visual Web Developer, see Walkthrough: Creating a Basic Web Page in Visual Web Developer.
Creating the Web Site and Page
If you have already created a Web site in Visual Web Developer (for example, by following the steps in
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and skip to the next section.
Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, point to New, and then click Web Site.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, select File System, and then enter the name of the folder where you want to keep the pages of your
Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click Visual Basic.
Note
Visual Web Developer currently does not support creating code-behind pages in the Microsoft Visual J# development t
ool.

The programming language you choose will be the default for your Web site, but you can set the programming language
for each page individually.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Correcting Errors in Visual Basic
The code editor in Visual Web Developer helps you to avoid errors as you code, and if you have made an error, the code editor
helps you to correct the error. In this part of the walkthrough, you will write a few lines of code that illustrate the error
correction features in the editor.
The behavior of the code editor depends on which language you are coding in. In general, the code editor for Microsoft Visual
Basic 2005 provides more detailed error information as you code.
To test error correction in Visual Basic
1. In Design view, double-click the blank page to create a handler for the Load event for the page.
You are using the event handler only as a place to write some code.
2. Inside the handler, type the following line that contains an error:

dim var1 as inger

When you press ENTER, the code editor underlines the word inger, indicating that the word is not recognized. Note that
part of the underline is a small underscore.
3. Hold the mouse pointer over the word inger to see a ToolTip that tells you what the error is.
4. Hold the mouse pointer over the underscore in the underline.
The underscore expands into an icon.
5. Click the icon.
A list of possible corrections for the word inger is displayed.
6. Select Change 'inger' to Integer.
Refactoring and Renaming in C#
Refactoring is a software methodology that involves restructuring your code to make it easier to understand and to maintain,
while preserving its functionality. A simple example might be that you write code in an event handler to get data from a
database. As you develop your page, you discover that you need to access the data from several different handlers. Therefore,
you refactor the page's code by creating a data-access function in the page and inserting calls to the function in the handlers.
The code editor includes tools to help you perform various refactoring tasks. In this walkthrough, you will work with two
refactoring techniques: renaming symbols and extracting a method. Other refactoring options include encapsulating fields,
promoting local variables to method parameters, and managing method parameters. The availability of these refactoring
options depends upon the location in the code. For example, if you highlight code that is not a field declaration, you can not
select the Encapsulate Field option. If you highlight a variable in an event method, you can not select Promote Local
Variable to Parameter because event handler signatures are constant.
Refactoring Code
A common refactoring scenario is to create (extract) a method from code that is inside another member. This reduces the size
of the original member and makes the extracted code reusable.
In this part of the walkthrough, you will write some simple code, and then extract a method from it. Refactoring is supported
for C#, so you will create a page that uses C# as its programming language.
To create a C# page
1. In Solution Explorer, right-click the name of your Web site, and then click Add New Item.
2. Under Visual Studio installed templates, click Web Form.
3. In the Language list, click C#.
Note
You can leave the name Default2.aspx.

4. Click Add to create and open the new page.

To extract a method in a C# page


1. Switch to Design view.
2. In the Toolbox, from the Standard group, drag a Button control onto the page.
3. Double-click the Button control to create a handler for its Click event, and then add the following highlighted code.
C#
protected void Button1_Click(object sender, EventArgs e)
{
System.Collections.ArrayList alist =
new System.Collections.ArrayList();
int i;
string arrayValue;
for(i=0; i<5; i++)
{
arrayValue = "i = " + i.ToString();
alist.Add(arrayValue);
}
for(i=0; i<alist.Count; i++)
{
Response.Write("<br>" + alist[i]);
}
}

The code creates an ArrayList object, uses a loop to load it with values, and then uses another loop to display the contents
of the ArrayList object.
4. Press CTRL+F5 to run the page, and then click the Button control to be sure that you see the following output:

i = 0
i = 1
i = 2
i = 3
i = 4

5. Return to the code editor, and then select the following lines in the event handler.
C#

for(i=0; i<alist.Count; i++)


{
Response.Write("<br>" + alist[i]);
}

6. Right-click the selection, click Refactor, and then choose Extract Method.
The Extract Method dialog box appears.
7. In the New Method Name box, type DisplayArray, and then click OK.
The code editor creates a new method named DisplayArray, and puts a call to the new method in the Click handler
where the loop was originally.
C#
protected void Button1_Click(object sender, EventArgs e)
{
System.Collections.ArrayList alist =
new System.Collections.ArrayList();
int i;
string arrayValue;
for(i=0; i<5; i++)
{
arrayValue = "i = " + i.ToString();
alist.Add(arrayValue);
}
i = DisplayArray(alist, i);
}

8. Press CTRL+F5 to run the page again, and click the Button control.
The page functions the same as it did before.
Renaming Symbols
When working with variables and objects (both are also known as symbols), you might want to be able to rename the symbols
after they are already referenced in your code. However, renaming the symbol can potentially cause the code to break if you
miss renaming one of the references to the symbol. Therefore, you can use refactoring to perform the renaming.
To use refactoring to rename symbols
1. In the Click event handler, locate the following line:
C#
System.Collections.ArrayList alist =
new System.Collections.ArrayList;

2. Right-click the variable name alist, choose Refactor, and choose Rename.
The Rename dialog box appears.
3. In the New name box, type ArrayList1, and then press ENTER.
The Preview Changes dialog box appears, and displays a tree containing all references to the symbol that you are
renaming.
4. Click Apply to close the Preview Changes dialog box.
The variables that refer specifically to the instance that you selected are renamed. Note, however, that the variable alist
in the following line is not renamed.
C#
private int DisplayArray(System.Collections.ArrayList alist,
int i)

The variable alist in this line is not renamed because it does not represent the same value as the specific variable alist
that you renamed. The variable alist in the DisplayArray declaration is a local variable for that method. This illustrates
that using refactoring to rename symbols is different than simply performing a find-and-replace action in the editor;
refactoring renames symbols with knowledge of the semantics of the symbol that it is working with.
Inserting Snippets
Because there are many coding tasks that Web page developers frequently need to perform, the code editor provides a library
of snippets, or blocks of prewritten code. You can insert these snippets into your page.
Each Visual Studio language has slight differences in the way you insert code snippets. For information on inserting snippets in
Visual Basic, see How to: Insert Snippets Into Your Code (Visual Basic). For information on inserting snippets in Visual J# and
Visual C#, see How to: Use Code Snippets (C#).
Next Steps
This walkthrough has illustrated the basic IntelliSense features of the Visual Studio IDE for correcting errors in your code,
refactoring code, renaming symbols, and inserting code snippets into your code. There is more to these IntelliSense features
that make application development fast and easy. For example, you might want to:
Learn more about the features of IntelliSense, such as modifying IntelliSense options, managing code snippets, and
searching for code snippets online. For more information, see Using IntelliSense.
Learn how to create your own code snippets. For more information, see Creating and Using IntelliSense Code Snippets.
Learn more about the Visual Basic-specific features of IntelliSense code snippets, such as customizing the snippets and
troubleshooting. For more information, see Visual Basic IntelliSense Code Snippets.
Learn more about the C#-specific features of IntelliSense, such as refactoring and code snippets. For more information,
see Visual C# Code Editor Features.
See Also
Concepts
Visual Basic IntelliSense Code Snippets
Refactoring
Code Snippets (C#)
Other Resources
Editing Text, Code, and Markup
Using IntelliSense
Visual Web Developer

Walkthrough: Debugging Web Pages in Visual Web Developer


Visual Web Developer provides you with tools to help track down errors in your ASP.NET Web pages. In this walkthrough, you
will work with the debugger, which allows you to step through the page's code line by line and examine the values of variables.
In the walkthrough, you will create a Web page that contains a simple calculator that squares a number. After creating the page
(which will include a deliberate error), you will use the debugger to examine the page as it is running.
Tasks illustrated in this walkthrough include:
Setting breakpoints.
Invoking debugger from a Web Forms page in a file system Web site.
Prerequisites
In order to complete this walkthrough, you will need:
Visual Web Developer and the .NET Framework.
You should also have a general understanding of working in Visual Web Developer. For an introduction to Visual Web
Developer, see Walkthrough: Creating a Basic Web Page in Visual Web Developer.
Creating the Web Site and Page
In the first part of the walkthrough, you will create a page that you can debug.
If you have already created a Web site in Visual Web Developer (for example, by working with the topic
Walkthrough: Creating a Basic Web Page in Visual Web Developer ), you can use that Web site and skip to "Adding Controls to
Debug" later in this walkthrough. Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, click File System and then type the name of the folder where you want to keep the pages of your
Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click the programming language that you prefer to work in.
The programming language you choose will be the default for your Web site. However, you can use multiple languages
in the same Web application by creating pages and components in different programming languages. For information on
creating components using different languages, see Shared Code Folders in ASP.NET Web Sites.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Creating a Page to Debug
You will begin by creating a new page. For this walkthrough, it is important that you create a new page as specified in the
following procedure.
To add a page to the Web site
1. Close the Default.aspx page.
2. In Solution Explorer, right-click the name of your Web site (for example, C:\WebSite) and choose Add New Item.
3. Under Visual Studio installed templates, choose Web Form.
4. In the Name box, type DebugPage.aspx.
5. From the Language list, choose the programming language you prefer to use.
6. Be sure that the Place code in separate file check box is cleared.
In this walkthrough, you are creating a single-file page with the code and HTML in the same page. The code for ASP.NET
pages can be located either in the page or in a separate class file. To learn more about keeping the code in a separate file,
see Walkthrough: Creating a Basic Web Page with Code Separation in Visual Web Developer .
7. Click Add.
Visual Web Developer creates the new page and opens it in Source view.
You can now add some controls to the page and then add code. The code will be simple, but enough to allow you to add
breakpoints later.
To add controls and code for debugging
1. Switch to Design view, and then from the Standard folder of the Toolbox, drag the following controls onto the page
and set their properties as indicated:
Control Properties
Label ID: CaptionLabel
Text: (empty)

TextBox ID: NumberTextBox


Text: (empty)

Button ID: SquareButton


Text: Square

Label ID: ResultLabel


Text: (empty)
Note
For this walkthrough, the layout of the page is not important.

2. Double-click the Button control to create a Click handler for it.


3. Add logic to the Click handler to call a function called Square to square the number entered by the user. The handler
might look like the following example.
Note
The code example deliberately does not include error checking.

VB
Sub SquareButton_Click(ByVal sender As Object, _
ByVal e As System.EventArgs)
Dim number As Integer
Dim result As Integer
number = CInt(NumberTextBox.Text)
result = Square(number)
ResultLabel.Text = CStr(number) & " squared is " & CStr(result)
End Sub

C#
protected void SquareButton_Click(object sender, System.EventArgs e)
{
int number, result;
number = System.Convert.ToInt32(NumberTextBox.Text);
result = Square(number);
ResultLabel.Text = NumberTextBox.Text +
" squared is " + result.ToString();
}

4. Create the function that squares the number. Include a bug in the code to add the number to itself instead of multiplying
it. The code might look like the following example.
VB
Function Square(number As Integer) As Integer
Square = number + number
End Function

C#
int Square(int number )
{
int Square;
Square = number + number;
return Square;
}

You can also add code to the page that will change the text of the label depending on whether this is the first time the page is
running.
To change the caption Label control
1. In Design view, double-click the design surface (not a control) to create a Page_Load event handler.
2. Set the text of the Caption Label control to Enter a number: if this is the first time the page is running, or Enter
another number: otherwise. The handler will look like the following code example.
VB
Sub Page_Load(ByVal sender As Object, ByVal e as System.EventArgs)
If Page.IsPostBack = False Then
CaptionLabel.Text = "Enter a number: "
Else
CaptionLabel.Text = "Enter another number: "
End If
End Sub

C#
if(Page.IsPostBack == false)
{
CaptionLabel.Text = "Enter a number: ";
}
else {
CaptionLabel.Text = "Enter another number: " ;
}

Testing the Page


To make sure the page is working, run it in its current state.
To run the page
1. Save the page.
2. Press CTRL+F5 to run the page.
3. Enter a number (other than 2) and press the Square button.
Note that the result is incorrect, because there is a bug in the program.
4. Close the browser.
Debugging the Page
In this part of the walkthrough, you will use the debugger to examine the page code line by line as it is running, add
breakpoints to the code, and then run the page in Debug mode.
You will start by setting breakpoints in your code. A breakpoint is a line in your code where execution stops and the debugger
is invoked.
To set breakpoints
1. Switch to Source view.
2. Right-click the following line, choose Breakpoint, and then choose Insert Breakpoint.
Note
You can toggle breakpoints by pressing F9.

VB
If Page.IsPostBack = False Then

C#
if(Page.IsPostBack == false)

3. Set another breakpoint on the following line of the SquareButton_Click handler:


VB
result = Square(number)

C#
result = Square(number);

Note
You cannot set a breakpoint on a statement that declares a variable.

With at least one breakpoint set, you are ready to run the debugger.
To run the debugger
1. From the Debug menu, choose Start Debugging (or press F5) to run the page in debug mode.
If you have never run the debugger before, your application probably is not configured to support debugging. By default,
debugging is turned off in applications both for performance (pages run more slowly in the debugger) and for security
reasons. Visual Web Developer displays a message telling you what it must do to enabled debugging.
The switch to enable debugging is stored as a setting in the Web.config file, which maintains various site-specific
configuration options. If the Web.config file does not exist, Visual Web Developer will both create the file and make the
appropriate debugger setting.
If the Web.config file already exists but debugging is not enabled, you will see a slightly different message telling you that
Visual Web Developer will modify the Web.config file.
2. If you see the message telling you that debugging has not been enabled, click OK to enable debugging.
In Visual Web Developer, the designer changes to debug mode displaying the code for your page and some debugger
windows.
The debugger runs your page line by line. When the debugger gets to the line with the breakpoint, it stops and highlights
the line.
Because the breakpoint is in the Page_Load handler, the page has not finished processing yet. The browser is open, but
the page is not yet displayed.
3. In the Debug menu, click Windows, click Watch, and then click Watch 1.
Note
If you are using Visual Web Developer Express Edition, the debugger offers only a single Watch window.

This opens a Watch window, where you can specify the values you want to track.
4. In the editor, right-click the IsPostBack portion of the Page.IsPostBack expression, and then click Add Watch.
This adds the expression to the Watch window and displays the current value of the property (false) is displayed in the
Value column. If you prefer, you can type the name of a variable or property in the Name column of the Watch window.
5. From the Debug menu, choose Continue to continue execution, or press F5.
The Continue command tells the debugger to proceed until it gets to the next breakpoint. The Page_Load event handler
finishes processing and the page is displayed in the browser.
6. Enter the value 2 into the text box and click the Square button.
The debugger is displayed again, with the breakpoint on the line in the Page_Load handler. This time, the Watch
window shows you that the value of Page.IsPostBack is true.
7. Press F5 again to continue.
The debugger processes the Page_Load handler and enters the SquareButton_Click handler, where it stops on the
second breakpoint you set.
8. In the Debug menu, click Windows and then click Locals.
This opens the Locals window, which displays the values of all variables and objects that are in scope at the current line
being executed. The Locals window provides an alternative way for you to view these values, with the advantage that
you do not have to explicitly set a watch on the elements, but with the disadvantage that the window might contain more
information than you want to see at once.
In the Locals window, you see that the value of number is 2 and the value of result is 0.
Note
You can also see the value of any variable in the program by holding the mouse pointer over it.

9. In the Value column of the Locals window, right-click the line for the number variable and select Edit value. Edit the
value of the number variable and change it to 5.
The value 2 for the variable number is not a good test of the program, because adding and squaring 2 both result in 4.
Therefore, while the program is running, you can change the value of this variable.
10. From the Debug menu, choose Step Into to step into the Square function, or press F11.
The Step Into command causes the debugger to execute a line and then stop again.
11. Continue stepping by pressing F11 until you reach the following line of code.
VB
ResultLabel.Text = CStr(number) & " squared is " & CStr(result)

C#
ResultLabel.Text = NumberTextBox.Text +
" squared is " + result.ToString();

The debugger walks through your code line by line. When the debugger executes the Square function, you can use the
Locals window to check the data passed to the function (number) and the return value of the function (Square).
12. In the Debug menu, click Windows and then Immediate.
The Immediate window allows you to execute commands. You can use the window to evaluate expressions (for
example, to get the value of a property).
13. In the Immediate window, type the following expression and press Enter.

? NumberTextBox.Text

The question mark (?) is an operator in the Immediate window that evaluates the expression following it. In this
example, you are evaluating the Text property of the NumberTextBox control on the page. You can evaluate any variable,
object property, or expression that combine these, using the same syntax that you would use in code.
14. In the Immediate window, type the following and press Enter:

NumberTextBox.Text = "5"

In addition to evaluating expressions, the Immediate window allows you to change variables or properties
15. Press F5 to continue running the program.
When the page appears, it displays the result of passing 5 to the Square function. In addition, the text in the text box has
been changed to 5.
The result you see — 10 — is not correct, since 10 is not the square of 5. You can now fix the bug.
To fix the bug and test again
1. Switch from the browser to Visual Web Developer.
Note
Do not close the browser window.

2. In the Square function, change the "+" operator to the "*" operator.
Because the code is not currently running (the page has finished processing), you are in edit mode and can make
permanent changes.
3. Press CTRL+S to save the page.
4. From the Debug menu, choose Delete All Breakpoints so that the page will not stop each time you run it.
Note
You can also clear breakpoints by pressing CTRL+SHIFT+F9.

5. Switch to the browser window.


6. Enter 5 in the text box and click the button.
This time, when you run the page and enter a value, it is squared correctly. The temporary changes you made earlier,
such as changing the Text property of the NumberTextBox control, have not been persisted, because they applied only
when the page was running the last time.
7. Close the browser to stop the debugger.
Next Steps
The debugger includes additional features to help you work with your code. In addition, you might want to learn about
techniques for handling error conditions and ways in which you can monitor page processing at run time. For example, you
might want to explore tracing. For details, see
Walkthrough: Using Tracing in Visual Web Developer to Help Find Web Page Errors.
See Also
Other Resources
Debugging in Visual Studio
Visual Web Developer

Walkthrough: Creating a Local IIS Web Site in Visual Web


Developer
In the Microsoft Visual Web Developer Web development tool, you can create and edit Web sites that keep the Web pages and
other files in different locations. Your choices for locating Web pages and other files include the following:
In a folder on the local hard disk, which is referred to as a file system Web site.
As a Web application under a local copy of Microsoft Internet Information Services (IIS), which is referred as a local IIS
Web site.
You can also work with Web sites on a remote server by creating a Microsoft SharePoint Services Web site or by connecting to
a server that uses FTP. For more information, see Types of Web Sites in Visual Web Developer.
In this walkthrough, you will work with two Web sites that run under a locally installed copy of IIS. One of the Web sites is
physically located under the root folder of IIS (typically C:\Inetpub\wwwroot). A second Web site is located in a convenient
folder on the hard disk but the second Web site is available to IIS by using a virtual directory.
You can use IIS to test the Web site. If the computer is configured to permit other users to connect to it, the Web site is
available to those users.
Note
If you cannot run IIS on the computer, you can still create and test ASP.NET Web sites by running Visual Web Developer. For
more information, see Walkthrough: Creating a Basic Web Page in Visual Web Developer.

Tasks illustrated in this walkthrough include the following:


Creating an application and page under the IIS root.
Creating an application that uses an IIS virtual root.
Using IIS to run the page.
Working with IIS in Solution Explorer.
Prerequisites
To complete this walkthrough, you must have IIS installed locally on the computer, and you must be logged in as a user with
administrative privileges. This is required because working with the IIS metabase (where information about IIS applications is
stored) requires administrative privileges.
Creating a Web Site under the IIS Root
In the first part of the walkthrough, you will create a Web site that resides under the IIS default folder (typically
\Inetpub\wwwroot).
To create a new local IIS Web site under the IIS root
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. Click Browse.
The Choose Location dialog box appears.
5. Click Local IIS.
6. Click Default Web Site.
7. Click the Create new Web program icon, which is located in the upper-right corner.
This icon is not labeled, but when you pause the mouse pointer on it, the Create New Web Application ToolTip text
appears.
A new application, named WebSite, is added under Default Web Site.
8. In the box for the new Web site, type LocalIISWebSite, and then click Open.
The New Web Site dialog box appears with the right-most Location box filled in with
http://localhost/LocalIISWebSite.
9. In the Language list, click the programming language that you prefer to work in.
The programming language that you choose will be the default for the Web site. However, you can use multiple
languages in the same Web application by creating pages and components in different programming languages.
10. Click OK.
Visual Web Developer creates the new Web site and opens a new page named Default.aspx. Keep this page open. This
initial Default.aspx page uses the Web page code-behind model. For more information, see
ASP.NET Web Page Code Model.
Visual Web Developer not only creates the folders and files for the Web site but it also interacts with IIS to create an IIS Web
application for your site. Essentially, Visual Web Developer calls IIS to create the metadata that IIS requires in order to be able
to recognize your folder and pages as a Web site.
You can examine what Visual Web Developer has performed by looking at the files and folders that have been created.
To examine the structure of the local IIS Web site
1. In Microsoft Windows, click Start, and then click Run.
In the Run dialog box, in the Open box, enter C:\Inetpub\wwwroot, and then click OK.
Note
If IIS is installed on a different drive or folder, change the path, as appropriate.

Under \wwwroot, you now see a new folder named LocalIISWebSite.


2. In the Path dialog box, double-click LocalIISWebSite.
You see the contents of the Web site, which include the following:
An App_Data folder, which is created automatically by Visual Web Developer.
A Default.aspx page.
The code-behind file, which is Default.aspx.cs or Default.aspx.vb, depending on the default language for the Web
application.
You can add pages to the Web site as you would ordinarily. However, you can also add pages to the Web site externally and
Visual Web Developer will recognize them as part of the application, although you might have to update Solution Explorer in
order to see them.
Adding and Programming Controls
In this part of the walkthrough, you will add a Button, TextBox, and Label control to the page and write code to handle the
Click event for the Button control.
To add controls to the page
1. In Visual Web Developer, open or switch to the Default.aspx page, and then switch to Design view.
2. Press SHIFT+ENTER several times to make some room.
3. From the Standard group in the Toolbox, drag three controls onto the page: a TextBox, Button, and Label.
Note
If you cannot see the Toolbox, on the View menu, click Toolbox.

4. Position the insertion pointer in front of the text box, and then type Enter your name:.
5. Click the Button control, and then in Properties, set Text to Display Name.
6. Click the Label control, and then in Properties, clear Text.
7. Double-click the Button control, which is now labeled Display Name.
Visual Web Developer opens the code file for the page in a separate window in the editor.
The file contains a skeleton Click handler for the Button control.
8. Complete the Click handler by adding the following highlighted code that will display the text string after the Button
control is clicked.
Security Note
User input in an ASP.NET Web page can include potentially malicious client script. By default, ASP.NET pages check pag
es on postback to guarantee that user input does not include script or HTML elements. For more information, see
Script Exploits Overview.

VB
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handl
es Button1.Click
Label1.Text = Textbox1.Text & ", welcome to Visual Web Developer!"
End Sub

C#
protected void Button1_Click(object sender, EventArgs e)
{
Label1.Text = TextBox1.Text + ", welcome to Visual Web Developer!";
}

9. Save the files.


You will test this Web page in "Testing the IIS Web Application," later in this walkthrough.
Updating the Web Site Outside Visual Web Developer
You can see that Visual Web Developer is reading the IIS path by adding a new file to the application from outside Visual Web
Developer.
To update the Web outside Visual Web Developer
1. Using Notepad or another text editor, create a new file that contains the following text, depending on whether you are
using Visual Basic or C#.
VB
<%@Page language="VB"%>
<script runat="server">
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handl
es Button1.Click
Button1.Text = "I was clicked!"
End Sub
</script>
<html>
<body>
<form runat="server" id="form1">
<asp:button runat="server" text="Button1" Id="Button1"
OnClick="Button1_Click"></asp:button>
</form>
</BODY>
</HTML>

C#
<%@Page language="C#"%>
<script runat="server">
protected void Button1_Click(object sender, System.EventArgs e)
{
Button1.Text = "I was clicked!";
}
</script>
<html>
<body>
<form runat="server" id="form1">
<asp:button runat="server" text="Button1" Id="Button1"
OnClick="Button1_Click"></asp:button>
</form>
</BODY>
</HTML>

2. Save the file in the path C:\inetpub\wwwroot\LocalIISWebSite under the name TestPage.aspx.
Note
If IIS is installed on a different drive or folder, change the path, as appropriate.

3. In Visual Web Developer, in Solution Explorer, click the Web site name (http://localhost/LocalIISWebSite/), and then
on the View menu, click Refresh.
The list of files that are in the Web site is updated to include the file that you added. Next, you will test the Web pages.
Testing the IIS Web Application
You can now test the Web site.
To test the local IIS Web site
1. In Visual Web Developer, open the Default.aspx page.
2. Press CTRL+F5 to run the page.
The page opens in the browser. Notice that the URL in the browser is http://localhost/LocalIISWebSite/default.aspx.
The request for the page is being made to localhost (without a port number), which is handled by IIS.
3. When the page appears in the browser, in the text box, enter your name, and then click Display Name to make sure it is
working.
4. In Visual Web Developer, open the TestPage.aspx page.
5. Press CTRL+F5 to run the page.
The page opens in the same instance of the browser.
6. When the page appears in the browser, click Button1 to make sure it is working.
7. Close the browser.
If you can connect to the computer from another computer, you can try accessing your site as if it were a public site. If you
cannot connect to the computer from another computer, you can skip this procedure.
To test your site as a public site
From a different computer, type the URL that includes the Web server computer name, Web site name, and default.aspx
as the page:
If the computer can be accessed over a local area network, use the computer name for the server that has a URL
such as the following:
http://server1/LocalIISWebSite/default.aspx
If you host a domain on the computer, you can access the page using a URL such as the following:
http://www.contoso.com/LocalIISWebSite/default.aspx
If the computer is either on a network or directly connected to the Internet, you can use the IP address for the
computer as the server name. For example:
http://172.19.195.700/LocalIISWebSite/default.aspx
Note
If you are not able to view your application from a different computer because of the Windows Firewall settings, you m
ight have to enable the Web server on port 80. You can do this on the Advanced tab of Windows firewall by clicking S
ettings. For more information, go to Security Developer Center -- .NET Framework Security and search for information
about Windows firewall settings.

Creating a Web Site as an IIS Virtual Root


As you have seen up to this point, IIS lets you create Web applications that are physically located under the default Web server
root folder (wwwroot). However, you can also create IIS virtual directories, which are IIS Web applications that point to files and
folders that can be located anywhere on the hard disk.
Note
For security reasons, IIS does not let you create virtual directories that point to folders on other computers. Virtual directories
must always point to the local computer.

In this part of the walkthrough, you will use Visual Web Developer to create a virtual directory that points to a Web site that is
stored in a local folder on the computer.
The first step is to create the virtual directory. If you have already created a file system Web site in Visual Web Developer (for
example, by completing Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site.
To create a local IIS Web site using a virtual folder
1. In Visual Web Developer, on the File menu, click New Web site.
2. Under Visual Studio Installed Templates, click ASP.NET Web Site.
3. Click Browse.
The Choose Location dialog box appears.
4. Click Local IIS.
5. Under Select the Web site you want to open, in the tree view, click Default Web Site, and then click the Create new
virtual directory icon, which is located in the upper-right corner.
This icon is not labeled, but when you pause the mouse pointer on it, the Create New Virtual Directory ToolTip text
appears.
The New Virtual Directory dialog box appears.
6. In the Alias Name box, type WebSite_vdir.
Note
You can name your virtual directory anything that you like, as long as you use a name that is valid in IIS.
7. In the Folder box, type one of the following:
The path of an existing file system Web site, if you have one. You can click Browse, and then locate the root folder
of that site, if you do not remember the exact path.
The path where you want to create a new folder to store the folders and files for the Web site.
8. Click OK.
If you specified a folder that does not exist, Visual Web Developer prompts you to create it.
Visual Web Developer then returns to the Choose Location dialog box and updates the list of IIS Web applications that
have the virtual directory that you created.
9. Select the virtual directory that you just created, click Open, and then click OK to create the Web site.
If you pointed the virtual directory to a new folder or an existing folder that does not contain a Web site, Visual Web
Developer creates the App_Data folder, a default page, and opens the page in the designer.
If your virtual folder points to an existing file system Web site, Visual Web Developer opens a Web Site Already Exists
dialog box and gives you the option to select a new folder, open the existing site, or create a new Web site in the existing
location. After you select your option and click OK, Visual Web Developer displays the contents of the folder in Solution
Explorer and opens the Default.aspx page, if it exists.
Adding Controls to the Web Page
As you did in " Testing the IIS Web Application," earlier in this walkthrough, you will use a simple ASP.NET Web page to test the
IIS Web site that you are creating. If you are working with an existing file system Web site, you do not have to create a new
page. If your virtual directory points to a new folder, you can use that page.
If this is a new Web site, you will add some controls to the default page so that you can test that the page is working correctly.
To add controls to the page
1. In Visual Web Developer, open the Default.aspx page and switch to Design view.
2. From the Standard group in the Toolbox, drag a TextBox, Button, and Label control onto the page.
3. Double-click the Button control, and then add the following highlighted code:
VB
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handl
es Button1.Click
Label1.Text = "Welcome to Visual Web Developer!"
End Sub

C#
protected void Button1_Click(object sender, System.EventArgs e)
{
Label1.Text = "Welcome to Visual Web Developer!";
}

4. Save the files.


Testing the Virtual Directory
You can now test the Web site.
To test the local IIS Web site using the virtual directory
1. In Visual Web Developer, open a page in the Web site, which can be the Default.aspx page or another page.
2. Press CTRL+F5 to run the page.
The page opens in the browser. Notice that the URL in the browser is http://localhost/Website_vdir/default.aspx.
When IIS resolves the URL, it looks up the physical path that is associated with the virtual directory named Website_vdir
and looks for the page there.
3. When the page appears in the browser, click the Button control to make sure it is working.
4. Close the browser.
If you can connect to the computer from another computer, you can try the same tests that you used in the preceding section
to try accessing the page.
Deleting a Local IIS Web Site
You can manage local IIS Web sites in Visual Web Developer by deleting ones that you no longer need. There is an important
difference in how deletion works, depending on which type of local IIS Web site that you are working with, as follows:
When you delete a Web site under the IIS root, the Web application is deleted from IIS and the files and folders for the
Web site are deleted also.
When you delete a virtual directory, the IIS information about that Web site is deleted but the files and folders in the local
file system folder are left intact.

To delete the local IIS Web site


1. On the File menu, click Close Solution or Close Project.
2. On the File menu, click Open Web site.
3. In the Open Web Site dialog box, click Local IIS.
4. Click the name of the virtual directory (Website_vdir) that you created in "Creating a Web Site as an IIS Virtual Root,"
earlier in the walkthrough.
Caution
If you select a different Web site, the files and folders for that Web site might be deleted.

5. Click the delete icon in the upper-right corner.


This icon is not labeled, but when you pause the mouse pointer on it, the Delete ToolTip text appears.
6. When you are prompted for confirmation to delete the Web site, click Yes.
7. Click Cancel to close the Open Web Site dialog box.
8. Open the browser, and then type the URL for the virtual directory:
http://localhost/Website_vdir/default.aspx
This time, the browser reports that the page cannot be found, because IIS no longer recognizes Website_vdir as a Web
site on the local computer.
Note
It is possible that the page was cached by the local browser. In that case, the page might still display until you flush the
browser cache, and then try to view the page again.

Next Steps
In this walkthrough, you have learned how to create a Web site using the local copy of IIS. You might also want to learn about
other types of Web sites that you can create in Visual Web Developer. For example, you might want to do the following:
Create a file system Web site, where the pages are stored in a folder anywhere on the hard disk.
For more information, see Walkthrough: Creating a Basic Web Page in Visual Web Developer.
Learn how to use FTP to open and edit Web sites.
For more information, see Walkthrough: Editing Web Sites with FTP in Visual Web Developer.
See Also
Concepts
Types of Web Sites in Visual Web Developer
Using Visual Web Developer as a Non-Administrative User
Visual Web Developer

Walkthrough: Editing Web Sites with FTP in Visual Web


Developer
The Microsoft Visual Web Developer Web development tool lets you read from and write to a remote server by using the File
Transfer Protocol (FTP). The most common use for FTP Web sites is to update Web pages on a hosting site, which is faster than
updating files that use an HTTP connection. After you connect to the FTP site in Visual Web Developer, you can create and edit
files in those sites. For information about FTP, see FTP-Deployed Web Sites.
Tasks illustrated in this walkthrough include the following:
Using FTP to connect to an existing Web site from within Visual Web Developer.
Creating and editing pages by using FTP.
Prerequisites
In order to complete this walkthrough, you will need the following:
Access to a folder on an FTP server that supports the .NET Framework.
If you have access to an existing FTP site, you can use that. For example, if you have an account that has a commercial
hosting service that provides ASP.NET support, you can use that account in this walkthrough. Otherwise, you can
configure a computer by running Microsoft Internet Information Services (IIS) as an FTP server. For more information
about how to configure IIS as an FTP server, see How to: Create and Configure FTP Sites in IIS.
Read and write permissions for the FTP directory on the server.
Optionally, a virtual Web root that points to the FTP location. This lets you to test the files that you work with.
For purposes of this walkthrough, you can use a local copy of IIS as an FTP server. Ordinarily, you do not have to use FTP to
communicate with the local copy of IIS.
Accessing the FTP Web Site
To start, you will connect to the FTP Web site from within Visual Web Developer. You must know the FTP address of the FTP
Web site and, if it is required, you must have a user name and password.
To access the FTP Web site
1. In Visual Web Developer, on the File menu, click New Web Site.
2. In the New Web Site dialog box, in the left-most Location list, click FTP Site, and then click Browse.
3. In the Choose Location dialog box, in the Server and Directory boxes, enter the appropriate information.
The Server field refers to the name or IP address of the FTP server. The Directory field refers to a specific directory on
the FTP server that you want to put the content in. By default, many FTP sites connect you to a home directory, although
there might still be a directory below that or a separate virtual directory where the Web content should be put. If you do
not know these values, contact the FTP site administrator.
For Port, the most common value is 21, but you should confirm that value with the FTP site administrator also.
4. Examine the following values:
Passive Mode
Leave this check box clear at first. Passive mode is sometimes required, if there is a firewall between your server
and the FTP server.
Anonymous Login
If the FTP site administrator has provided you with a user name and password, clear the Anonymous Login check
box, and then in the Username and Password boxes, enter the appropriate information.
5. Click Open.
Visual Web Developer will try to connect to the FTP server by using the information that you have provided. If the
connection is successful, Visual Web Developer displays the FTP Web site name in Solution Explorer and lists the files
that are already in the FTP Web site.
Troubleshooting
If the connection fails, examine the following:
If you have administrative rights on the server, use IIS Manager to add the Write permission to the FTP virtual directory.
Do not complete this before you have set restricted NTFS File System permissions on the virtual directory, either by
using IIS Manager or Microsoft Windows Explorer. For more information, go to Microsoft Technet and search for
information about how to help secure FTP sites.
Confirm that the server name and directory name are correct.
Use the URL of the Web site or the FTP site in the Server field and leave the Directory field blank.
Try connecting with Passive Mode enabled. This frequently lets you get through a firewall.
Make sure that the FTP Web site has the directory that you have indicated. If you are using IIS as the FTP server,
remember that the directory is typically defined under the ftproot directory, not the wwwroot directory.
Contact the FTP site administrator to determine whether anonymous log on is allowed. If not, make sure that you have
credentials for a user account that has permission to access and modify the FTP directory.
Creating and Editing Pages
Working with Web pages in an FTP Web site is the same as working with Web pages in any other Web site. The only difference
is that the files are stored on the FTP server, so that when you open or save the files, you are invoking the FTP connection.
To create a page
1. In Solution Explorer, right-click the FTP Web site name, click Add New Item, and then create a new Web Forms page.
Note
If you have access to the physical folder that is represented by the FTP Web site, you can confirm that the file is created
in that folder.

2. Switch to Design view.


3. From the Standard group in the Toolbox, drag a Button control and a Label control onto the page.
4. Double-click the Button control.
5. The file contains a skeleton Click handler for the Button control.
6. Complete the Click handler by adding the following highlighted code:
VB
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Label1.Text = "The FTP Web site is working!"
End Sub

C#
protected void Button1_Click(object sender, System.EventArgs e)
{
Label1.Text = "The FTP Web site is working!";
}

7. Save your files.


Testing the FTP Web Site
If the FTP Web site has been set up to have an equivalent Web site, you can test the Web site by displaying it in the browser.
To test the FTP Web site on the server
1. Press CTRL+F5.
Visual Web Developer prompts you for the location to go to. The location is stored as part of the Web site configuration
information.
2. Enter the HTTP URL that points to the server and the Web virtual directory that you created in "Accessing the FTP Web
Site," earlier in this walkthrough.
For example, the URL might be the following:
http://<server>/ExampleFtpFiles

Note
You can change or set the browser location at any time. To do this, in Solution Explorer, right-click the Web site name, a
nd then click Property Pages. On the Start Options tab, under Server, click Use custom server, and then in the Base
URL box, type the location.

The page is displayed in the browser.


3. Close the browser.
See Also
Concepts
What's New in Web Development for Visual Studio
Types of Web Sites in Visual Web Developer
Visual Web Developer

Walkthrough: Using Shared Code in Web Sites in Visual Web


Developer
When you are creating Web sites, Visual Web Developer lets you easily create shared code in class files, which can then be
used by pages in your application, even without compiling the class files.
Note
If you have existing assemblies (.dll files), you can add them to the Bin directory of the Web site, and then the assemblies are
automatically referenced by the Web site.

In this walkthrough, you will create a simple class and then use it in an ASP.NET Web page.
Tasks illustrated in this walkthrough include the following:
Adding a class to a Web site.
Having Visual Web Developer reference the component automatically.
Prerequisites
In order to complete this walkthrough, you will need the following:
Visual Web Developer (Visual Studio).
The .NET Framework.
This walkthrough assumes that you have a general understanding of working in Visual Web Developer. For an introduction,
see Walkthrough: Creating a Basic Web Page in Visual Web Developer.
Creating the Web Site and Page
If you have already created a Web site in Visual Web Developer (for example, by completing either
Walkthrough: Creating a Basic Web Page in Visual Web Developer or
Walkthrough: Creating a Local IIS Web Site in Visual Web Developer), you can use that Web site and go to the next section.
Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site. (In Visual Web Developer Express Edition, on the File menu, click New, and then
click Web Site.)
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, enter the name of the folder where you want to keep the pages of the Web site.
For example:
If you are creating a file system Web site, type C:\SampleSite.
If you have IIS installed and you are creating an HTTP Web site, type http://localhost/SampleSite.
5. In the Language list, select the programming language that you prefer to work in.
6. Click OK.
Visual Web Developer creates the Web site and opens a new page named Default.aspx.
Creating a Shared Class
You can create reusable classes by keeping them in a folder named App_Code. Visual Web Developer monitors the App_Code
folder and when new class files are added, makes the components available to the rest of the code in your application. By
default, the classes in the App_Code folder are compiled into a single assembly at run time.
Note
You should put only classes (and other supported shared types) into the App_Code folder. Do not put pages, Web user contr
ols, or other files that contain non-code elements into the App_Code folder.

To create an App_Code folder


In Solution Explorer, right-click the name of the Web site, click Add Folder, and then click App_Code Folder.
You can now add the component to your site.
To create a shared class in the App_Code folder
1. In Solution Explorer, right-click App_Code, and then click Add New Item.
Note
Be sure to create the new item in the App_Code folder, not in the root folder of the Web site.

2. Under Visual Studio installed templates, click Class.


3. In the Name box, type SampleClass1.
4. In the Language list, select the language that is used by the Web page that will use the shared class.
5. Click Add.
Visual Web Developer opens the new class file in the editor.
6. Create a class that has a single property named testString by copying the following code into the class file:
VB
Public Class SampleClass1
private testStringValue As String
Public Property testString as String
Get
return testStringValue
End Get
Set (Value as String)
testStringValue = value
End Set
End Property
End Class

C#
using System;
public class SampleClass1
{
public SampleClass1()
{
}
private string testStringValue;
public string testString
{
get
{
return testStringValue;
}
set
{
testStringValue = value;
}
}
}

7. Save the file and then close it.


Note that the file is not stored as a compiled file.
Note
When you work with shared classes in the App_Code folder, you do not have to save the components in order for Visu
al Web Developer to maintain a reference to the components. If the Web page and component are in the same progra
mming language, Visual Web Developer maintains a reference to the component in memory. In this case, you are closi
ng the file because you are finished with it.

Using the Shared Class


The next step is to use the shared class in an ASP.NET Web page. You can use the Default.aspx page that was created when you
created the Web site.
To use the shared class
1. Open or switch to the Default.aspx page, and then switch to Design view.
Note
If you do not have a Default.aspx page, you can use another page. Alternatively, you can add a new page to the Web sit
e. To do this, in Solution Explorer, right-click the name of the Web site, click Add New Item, and then click Web Form.
In the Language list, enter the same programming language that you used for the component, and then click OK.

2. From the Standard folder in the Toolbox, drag a TextBox control, Label control, and Button control onto the page.
Note
For this walkthrough, the layout of the page is not important.

3. Double-click the Button control to create a Click handler for it.


The click handler code might look similar to the following:
VB
Protected Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Button1.Click

End Sub

C#
protected void Button1_Click(object sender, EventArgs e)
{

4. In the handler, type the following:


VB
Dim sc As New
C#
SampleClass1 sc = new

When you press SPACEBAR after typing New or new, Visual Web Developer displays a list of the available classes. The
class that you created in the preceding section, SampleClass1, is included in the list.
5. Finish the statement by typing SampleClass1 or by double-clicking it in the list, so that the statement reads as follows:
VB
Dim sc As New SampleClass1

C#
SampleClass1 sc = new SampleClass1();

6. Press ENTER, and then type the following:

sc.

As soon as you type the period, Visual Web Developer again displays a list of members to help you select a member
from the sample class.
7. Finish the statement and the handler in the following manner:
VB
sc.testString = TextBox1.Text
Label1.Text = sc.testString

C#
sc.testString = TextBox1.Text;
Label1.Text = sc.testString;

8. Save your files.


Testing the Page and Class
You can run the Web site to see that the shared class is working.
To test the page and component
1. Open the Default.aspx page.
2. Press CTRL+F5 to run the page.
3. When the page appears in the browser, type something in the text box, and then click the button.
Doing this sets a property in your simple class, which is then displayed in the Label control.
If you use Microsoft Windows Explorer to examine the directory where the Web site is located, you will see your page and the
App_Code folder. Note that there is no .dll or other executable code in the App_Code folder or anywhere under the root of the
Web site. Instead, Visual Web Developer has compiled the page and the shared class dynamically.
Next Steps
This walkthrough illustrates how to add shared classes to a Web site without compiling the components. You might want to
use shared classes in different ways. For example, you might want to:
Work with a compiled component.
If you have an assembly that you can use in the Web site, create a Bin folder, and then copy the .dll to Bin. You can then
reference the assembly in your page in the same way that you referenced the component that you created in this
walkthrough.
Create a component for data access.
For more information, see Walkthrough: Data Binding to a Custom Business Object.
Create a Web service.
For more information, see Walkthrough: Creating and Using an ASP.NET Web Service in Visual Web Developer.
See Also
Concepts
ASP.NET Web Site Layout
Shared Code Folders in ASP.NET Web Sites
Visual Web Developer

Data-Driven Web Pages


The topics in this section include step-by-step walkthroughs that illustrate various ways to display and edit data using ASP.NET
Web pages and how to optimize data access using caching.
In This Section
Walkthrough: Basic Data Access in Web Pages
Walkthrough: Editing and Inserting Data in Web Pages with the DetailsView Web Server Control
Walkthrough: Displaying and Formatting Data with the DataList Web Server Control
Walkthrough: Displaying Formatted Data in Web Pages with the FormView Web Server Control
Walkthrough: Creating Master/Detail Web Pages in Visual Studio
Walkthrough: Data Binding Web Pages with a Visual Studio Data Component
Walkthrough: Data Binding to a Custom Business Object
Walkthrough: Creating a Web Page to Display XML Data
Walkthrough: Displaying Hierarchical Data in a TreeView Control
Walkthrough: Using Output Caching to Enhance Web Site Performance
Walkthrough: Using ASP.NET Output Caching with SQL Server
Related Sections
Guided Tour of Creating Web Sites in Visual Web Developer
Introduces topics designed to give a guided tour of creating Web sites in Microsoft Visual Web Developer.
Visual Web Developer

Walkthrough: Basic Data Access in Web Pages


This walkthrough shows you how to create a simple data-bound page by using controls that are specially designed for data
access.
During this walkthrough, you will learn how to do the following:
Connect to a Microsoft SQL Server database in the Microsoft Visual Web Developer Web development tool.
Use drag-and-drop editing to create data-access elements that can be used in the page without code.
Use the SqlDataSource control to manage data access and binding.
Display data with the GridView control.
Configure the GridView control to allow for sorting and paging.
Create a filtered query that displays only selected records.
Prerequisites
In order to complete this walkthrough, you will need the following:
Access to the SQL Server Northwind database. For information about downloading and installing the SQL Server sample
Northwind database, see Installing Sample Databases on the Microsoft SQL Server Web site.
Note
If you need information about how to log on to the computer running SQL Server, contact the server administrator.

Microsoft Data Access Components (MDAC) version 2.7 or later.


If you are using Microsoft Windows XP or Windows Server 2003, you already have MDAC 2.7. However, if you using
Microsoft Windows 2000, you might have to upgrade the MDAC version that is already installed on the computer. To
download the current MDAC version, see Data Access and Storage Developer Center.
Creating the Web Site
If you have already created a Web site in Visual Web Developer by completing
Walkthrough: Creating a Basic Web Page in Visual Web Developer, you can use that Web site and go to the next section.
Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the right-most Location box, enter the name of the folder where you want to keep the pages of the Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click the programming language that you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Adding a GridView Control to Display Data
To display data on an ASP.NET Web page, you need the following:
A connection to a data source (such as a database).
In the following procedure, you will create a connection to the SQL Server Northwind database.
A data source control on the page, which executes queries and manages the results of the queries.
A control on the page to actually display the data.
In the following procedure, you will display data in a GridView control. The GridView control will get its data from the
SqlDataSource control.
You can add these elements to the Web site separately. However, it is easiest to start by visualizing the data display using
GridView control, and then using wizards to create the connection and data source control. The following procedure explains
how to create all three of the elements that you must have to display data on the page.
To add and configure a GridView control for displaying data
1. In Visual Web Developer, switch to Design view.
2. From the Data folder in the Toolbox, drag a GridView control onto the page.
3. If the GridView Tasks shortcut menu does not appear, right-click the GridView control, and then click Show Smart Tag.
4. On the GridView Tasks menu, in the Choose Data Source list, click <New data source>.
The Data Source Configuration dialog box appears.

5. Click Database.
This specifies that you want to obtain data from a database that supports SQL statements. This includes SQL Server and
other OLE-DB–compatible databases.
In the Specify an ID for the data source box, a default data source control name appears (SqlDataSource1). You can
leave this name.
6. Click OK.
The Configure Data Source Wizard appears, displaying a page on which you can choose a connection.
7. Click New Connection.
8. In the Choose Data Source dialog box, under Data source, click Microsoft SQL Server, and then click Continue.
The Add Connection dialog box appears.
9. In the Server name box, enter the name of the SQL Server that you want to use.

10. For the logon credentials, select the option that is appropriate for accessing the SQL Server database (integrated security
or specific ID and password) and if it is required, enter a user name and password.
11. Click Select or enter a database name, and then enter Northwind.
12. Click Test connection, and when you are sure that it works, click OK.
The Configure Data Source - <DataSourceName> Wizard appears and the connection information is filled in.
13. Click Next.
The wizard appears, displaying a page on which you can choose to store the connection string in the configuration file.
Storing the connection string in the configuration file has two advantages:
a. It is more secure than storing the connection string in the page.
b. You can reuse the same connection string in multiple pages.
14. Make sure that the Yes, save this connection as check box is selected, and then click Next. (You can leave the default
connection string name of NorthwindConnectionString.)
The wizard appears, displaying a page on which you can specify the data that you want to fetch from the database.
15. Under Specify columns from a table or view, in the Name list, click Customers.
16. Under Columns, select the CustomerID, CompanyName, and City check boxes.
The wizard appears, displaying the SQL statement that you are creating in a box at the bottom of the page.

Note
The wizard lets you specify selection criteria (a WHERE clause) and other SQL query options. For this part of the walkthr
ough, you will create a simple statement without selection or sort options.

17. Click Next.


18. Click Test Query to make sure that you are fetching the data you want.
19. Click Finish.
The wizard closes and you are returned to the page. Running the wizard has accomplished two tasks:
The wizard created and configured a SqlDataSource control (named SqlDataSource1), which incorporates the
connection and query information that you specified.
The wizard bound the GridView control to the SqlDataSource. Therefore, the GridView control will display data
that is returned by the SqlDataSource control.
If you view the properties for the SqlDataSource control, you can see that the wizard has created values for the
ConnectionString and SelectQuery properties.
Note
You can easily change the look of the GridView control. In Design view, right-click the GridView control, and then clic
k Show Smart Tag. On the GridView Tasks menu, click Auto Format, and then apply a scheme.
Testing the Page
You can now run the page.
To test the page
1. Press CTRL+F5 to run the page.
The page appears in the browser. The GridView control displays all data rows from the Customers table.
2. Close the browser.
Adding Sorting and Paging
You can add sorting and paging to the GridView control without writing any code.
To add sorting and paging
1. In Design view, right-click the GridView control, and then click Show Smart Tag.
2. On the GridView Tasks shortcut menu, select the Enable Sorting check box.
The column headings in the GridView control change to links.
3. On the GridView Tasks menu, select the Enable Paging check box.
A footer is added to the GridView control with page number links.
4. Optionally, use Properties to change the value of the PageSize property from 10 to a smaller page size.
5. Press CTRL+F5 to run the page.
You will be able to click a column heading to sort by the contents of that column. If there are more records in the data
source than the page size of the GridView control, you will be able to use the page navigation links at the bottom of the
GridView control to move between pages.
6. Close the browser.
Adding Filtering
Frequently you want to display only selected data in the page. In this part of the walkthrough, you will modify the query for the
SqlDataSource control so that users can select customer records for a particular city.
First, you will use a TextBox control to create a text box in which users can type the name of a city. Then, you will change the
query to include a parameterized filter (WHERE clause). As part of that process, you will create a parameter element for the
SqlDataSource control. The parameter element establishes how the SqlDataSource control will get the value for its
parameterized query—namely, from the text box.
When you are finished with this part of the walkthrough, the page might look similar to the following in Design view.
To add the text box for specifying a city
1. From the Standard group in the Toolbox, drag a TextBox control and a Button control onto the page.
The Button control is used only to post the page to the server. You will not need to write any code for it.
2. In Properties, for the TextBox control, set ID to textCity.
3. If you want, type City or similar text before the text box to act as a caption.
4. In Properties for the Button control, set Text to Submit.
You can now modify the query to include a filter.
To modify the query with a parameterized filter
1. Right-click the SqlDataSource control, and then click Show Smart Tag.
2. On the SqlDataSource Tasks menu, click Configure Data Source.
The Configure Data Source - <Datasourcename> wizard appears.
3. Click Next.
The wizard displays the SQL command that is currently configured for the SqlDataSource control.
4. Click WHERE.
The Add WHERE Clause page appears.
5. In the Column list, click City.
6. In the Operator list, click =.
7. In the Source list, click Control.
8. Under Parameter properties, in the Control ID list, click textCity.

The previous five steps specify that the query will get the search value for City from the TextBox control that you added
in the preceding procedure.
9. Click Add.
The WHERE clause that you have created appears in a box at the bottom of the page.
10. Click OK to close the Add WHERE Clause page.
11. In the Configure Data Source - <DataSourceName> wizard, click Next.
12. On the Test Query page, click Test Query.
The wizard appears, displaying the Parameter Values Editor page, which prompts you for a value to use in the WHERE
clause.
13. In the Value box, type London, and then click OK.
The customer records for London appear.
14. Click Finish to close the wizard.
You can now test filtering.
To test filtering
1. Press CTRL+F5 to run the page.
2. In the text box, type London, and then click Submit.
A list of customers from the city of London appears in the GridView control.
3. Try other cities, such as Buenos Aires and Berlin.
Next Steps
Data access is an important part of many Web applications, and this walkthrough has provided only a glimpse of what you can
do with data in the Web pages. You might want to experiment with additional features of data access. For example, you might
want to do the following:
Work with Microsoft Access instead of SQL Server. (You cannot use SQL cache dependency with Access.)
For detailed information, see Walkthrough: Creating a Web Page to Display Access Database Data.
Edit and insert records.
For detailed information, see
Walkthrough: Editing and Inserting Data in Web Pages with the DetailsView Web Server Control.
Work with records that have a master-detail relationship.
For detailed information, see Walkthrough: Creating Master/Detail Web Pages in Visual Studio.
Create a middle-tier (business) component that performs data access, and then use that as the data source in a page.
For detailed information, see Walkthrough: Data Binding to a Custom Business Object.
See Also
Concepts
Data Source Controls Overview
Visual Web Developer

Walkthrough: Editing and Inserting Data in Web Pages with


the DetailsView Web Server Control
Microsoft Visual Web Developer allows you to create data entry forms for updating records and inserting new ones into a
database with only a few lines of code. By using a combination of a data source control that encapsulates data access and
DetailsView and GridView controls that display records in an editable format, you can create a data entry page that allows
users to edit existing records or insert new ones, all without any code.
During this walkthrough, you will learn how to:
Create a data entry page.
Configure a data source control with information required to make database updates and inserts.
Use the DetailsView control to view individual records, change them, and insert new ones.
Use a GridView control to enable database modification from the data entry page.
Prerequisites
In order to complete this walkthrough, you will need:
Visual Web Developer.
Microsoft Data Access Components (MDAC) version 2.7 or later.
If you are using the Microsoft Windows XP or Windows Server 2003 operating systems, you already have MDAC 2.7.
However, if you are using the Microsoft Windows 2000 Server operating system, you might need to upgrade the MDAC
already installed on your computer. To download the current MDAC version, see the
Data Access and Storage Developer Center.
Access to the SQL Server Northwind database. For information about downloading and installing the SQL Server sample
Northwind database, see Installing Sample Databases on the Microsoft SQL Server Web site.
Note
If you need information about how to log on to the computer running SQL Server, contact the server administrator.

Permission to modify data in the sample Northwind database.


Creating the Web Site and Page
Create a new Web site and page by following these steps.
To create a new file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New, and then click Web Site. If you are using Visual Web Developer Express, on the File menu,
click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, select File System, and enter the name of the folder where you want to keep the pages of your Web
site.
For example, type the folder name C:\WebSites\EditData.
5. In the Language list, click the programming language you prefer to work in.
The programming language you choose will be the default for your Web site, but you can set the programming
languages for each page individually.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Connecting to SQL Server
The next step is to establish a connection to the SQL Server database.
To create a connection to a SQL Server database
1. In Server Explorer, right-click Data Connections, and then click Add Connection. If you are using Visual Web
Developer Express, use Database Explorer.
The Add Connection dialog box appears.
If the Data source list does not display Microsoft SQL Server (SqlClient), click Change, and in the Change Data
Source dialog box, select Microsoft SQL Server.
If the Choose Data Source page appears, in the Data source list, select the type of data source you will use. For
this walkthrough, the data source type is Microsoft SQL Server. In the Data provider list, click .NET Framework
Data Provider for SQL Server, and the click Continue.
Note
If the Server Explorer tab is not visible in Visual Web Developer, in the View menu, click Server Explorer. If the Data
base Explorer tab is not visible in the Express edition, in the View menu, click Database Explorer.

2. In the Add Connection box, enter your server name in the Server Name box.
3. For the Log on to the server section, select the option that is appropriate to access the running the SQL Server database
(integrated security or specific ID and password) and, if required, enter a user name and password. Select the Save my
Password check box if you entered a password.
4. Under Select or enter a database name, enter Northwind.
5. Click Test Connection, and when you are sure that it works, click OK.
Your new connection has been created under Data Connections in Server Explorer.
Creating the Data Entry Page
In this section, you will create a data entry page and configure a DetailsView control so that you can view employee data that
is stored in the Employees table of the Northwind database. To handle the data access for the page, you will configure a SQL
data source control.
To create a data entry page and configure a DetailsView control
1. On the Website menu, click Add New Item.
The Add New Item dialog box appears.
2. Under Visual Studio installed templates, click Web Form, and then in the Name box, type EditEmployees.aspx.
3. Click Add.
4. Open the EditEmployees.aspx page.
5. Switch to Design view.
6. Type Edit Employees, select the text, and then format the text as a heading.
7. In the Toolbox, from the Data group, drag a DetailsView control onto the page.
8. Right-click the DetailsView control, click Properties, and then set AllowPaging to true.
This will allow you to page through individual employee entries when they are displayed.
The next step is to create and configure a data source control that can be used to query the database. There are a number of
ways to create a data source control, including dragging data elements from Server Explorer or Database Explorer onto the
page. In this walkthrough, you will start with the DetailsView control and configure the data source control from there.
To configure a data source control
1. Right-click the DetailsView control and click Show Smart Tag.
2. On the DetailsView Tasks menu, in the Choose Data Source box, click <New data source>.
The Data Source Configuration Wizard dialog box appears.
3. Under Select a data source type, click Database.
4. Leave the default name of SqlDataSource1, and then click OK.
The Configure Data Source wizard displays the Choose a connection page.
5. In the Which data connection should your application use to connect to the database? box, enter the connection
that you created in "To create a connection to SQL Server," and then click Next.
The wizard displays a page where you can choose to store the connection string in a configuration file. Storing the
connection string in the configuration file has two advantages:
It is more secure than storing it in the page.
You can use the same connection string in multiple pages.
6. Select the Yes, save this connection as check box, and then click Next.
The wizard displays a page where you can specify what data you want to retrieve from the database.
7. On the Configure the Select Statement page, select Specify columns from a table or view, and then in the Name
box, click Employees.
8. Under Columns, select the EmployeeID, LastName, FirstName, and HireDate check boxes, and then click Next.
9. Click Test Query to preview the data, and then click Finish.
You can now test the employee records display page.
To test displaying the employee records
1. Press CTRL+F5 to run the page.
The first employee record is displayed in the DetailsView control.
2. Click the page number links to see additional employee records.
3. Close the browser.
Allowing Editing in a GridView Control
At this point, you can view employee records, but you cannot edit them. In this section, you will add a GridView control and
configure it so that you can edit individual records.
Note
The GridView control presents a list of records and allows you to edit them. However, it does not allow you to insert them. L
ater in this walkthrough, you will use the DetailsView control, which allows you to add new records.

To support editing, you must configure the data source control you created earlier (SqlDataSource1) with SQL statements that
perform updates.
To add a GridView control to allow editing
1. In the Toolbox, from the Data group, drag a GridView control onto the page.
2. Right-click the GridView control, click Show Smart Tag, and then on the GridView Tasks menu, in the Choose Data
Source box, click SqlDataSource1.
3. On the GridView Tasks menu, click Configure Data Source.
4. Click Next to advance to the Configure the Select Statement page of the wizard.
5. On the Configure the Select Statement page, click Advanced, select the Generate INSERT, UPDATE, and DELETE
statements check box, and then click OK.
This generates Insert, Update, and Delete statements for the SqlDataSource1 control based on the Select statement that
you configured earlier.
Note
Alternatively, you could manually create the statements by selecting Specify a custom SQL statement or stored pro
cedure and entering SQL queries.

6. Click Next, and then click Finish.


The SqlDataSource control is now configured with additional SQL statements.
Note
You can examine the statements generated by the wizard by selecting the SqlDataSource control and viewing the
DeleteQuery, InsertQuery, and UpdateQuery properties. You can also view the updated control properties by switching
to Source view and examining the markup of the control.

7. On the GridView Tasks menu, select the Enable Paging and Enable Editing check boxes.
Security Note
User input in an ASP.NET Web page can include potentially malicious client script. By default, ASP.NET Web pages valid
ate user input to make sure input does not include script or HTML elements. As long as this validation is enabled, you d
o not need to explicitly check for script or HTML elements in user input. For more information, see
Script Exploits Overview.

You can now test the editing of employee records.


To test the editing in the GridView control
1. Press CTRL+F5 to run the page.
The GridView control is displayed with the data in text boxes.
2. Choose a row in the GridView control and click Edit.
3. Make a change to the record, and then click Update.
The updated data now appears in both the GridView control and the DetailsView control.
4. Close the browser.
Allowing Editing, Deleting, and Inserting Using a DetailsView Control
The GridView control allows you to edit records, but it does not allow you to insert data. In this section, you will modify the
DetailsView control so that you can see records individually, as well as delete, insert, and update records.
To use a DetailsView control to allow deleting, inserting, and updating
1. Right-click the DetailsView control and then click Show Smart Tag.
2. On the DetailsView Tasks menu, select the Enable Inserting, Enable Editing, and Enable Deleting check boxes.
When you used the DetailsView control earlier in the walkthrough, the options for enabling editing, inserting, and
deleting were not available. The reason is that the SqlDataSource1 control that the DetailsView control is bound to did
not have the necessary SQL statements. Now that you have configured the data source control to include update
statements, the update options are available on the DetailsView control.
You can now test deleting, inserting, and updating in the DetailsView control.
To test the updating, inserting, and deleting in the DetailsView control
1. Press CTRL+F5 to run the page.
The DetailsView control displays an employee record.
2. In the DetailsView control, click Edit.
The DetailsView control now displays the data in text boxes.
3. Make a change to the record, and then click Update.
The updated record is displayed in the control.
4. In the DetailsView control, click New.
The control now displays blank text boxes for each column.
5. Enter values for each column.
The Employees table has an auto-increment key column, so the value for EmployeeID is assigned automatically when
you save the record.
6. When you are finished, click Insert.
The new record is added as the last record.
Note
Inserting a new record in the Employees table in this walkthrough will not generate any errors. However, when you wo
rk with production data, the tables might have constraints (such as a foreign key constraint) that you must be aware of
when configuring the DetailsView control.

7. Use paging in the DetailsView control to navigate to the last record, and then click Delete.
The new record is removed.
Note
As with inserting data, you must always be aware of any constraints that apply to the data row when configuring a Det
ailsView control to allow deletion.

Next Steps
This walkthrough has illustrated the basics of creating a Web page that allows users to modify data records. You might want to
explore additional data capabilities of ASP.NET Web pages. For example, you might want to do the following:
Work with records in related tables. For details, see Walkthrough: Creating Master/Detail Web Pages in Visual Studio.
Use a middle-tier component for data access. For details, see Walkthrough: Data Binding to a Custom Business Object.
Use other ways to configure data access in a Web page. For details, see Walkthrough: Basic Data Access in Web Pages.
See Also
Tasks
Walkthrough: Creating a Web Page to Display Access Database Data
Concepts
Data Source Controls Overview
Binding to Data Using a Data Source Control
Visual Web Developer

Walkthrough: Displaying and Formatting Data with the


DataList Web Server Control
A common task in Web pages is to display data — in effect, to create data reports. In this walkthrough, you will work with the
DataList control, which allows you to create free-form layout for records that you display on an ASP.NET Web page.
During this walkthrough you will learn how to:
Add a DataList control and use templates to lay out the data that is displayed by the DataList control.
Bind the DataList control to a data source.
Add a child data control and some code to the DataList control to display data in a master/detail relationship.
Prerequisites
In order to complete this walkthrough, you will need:
Microsoft Visual Web Developer (Visual Studio).
Access to the SQL Server Northwind database. For information about downloading and installing the SQL Server sample
Northwind database, see Installing Sample Databases on the Microsoft SQL Server Web site.
Note
If you need information about how to log on to the computer running SQL Server, contact the server administrator.

Microsoft Data Access Components (MDAC) version 2.7 or later.


If you are using Microsoft Windows XP or Windows Server 2003, you already have MDAC 2.7. However, if you are using
Microsoft Windows 2000, you might need to upgrade the MDAC already installed on your computer. For more
information, see "Microsoft Data Access Components (MDAC) Installation" in the MSDN Library.
Creating the Web Site
Create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New, and then click Web Site. If you are using Visual Web Developer Express, on the File menu,
click New Web Site.
The New Web Site dialog box is displayed.
3. Under Visual Studio installed templates, select ASP.NET Web Site.
4. In the Location box, select File System, and enter the name of the folder where you want to keep the pages of your Web
site.
For example, type the folder name C:\WebSites\FormatDataList.
5. In the Language list, click the programming language you prefer to work in.
The programming language you choose will be the default for your Web site, but you can set the programming language
for each page individually.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Adding a DataList Control
For the first part of this walkthrough, you will add a DataList control, and then configure its data source.
To add and configure a DataList control to display data in a grid
1. Switch to Design view.
2. In the Toolbox, from the Data group, drag a DataList control onto the page.
3. Right-click the DataList control, and then click Show Smart Tag.
4. On the DataList Tasks menu, in the Choose Data Source list, click New Data Source.
The Configure Data Source wizard appears.
5. Click Database.
This specifies that you want to get data from a database that supports SQL statements. (This includes SQL Server and
other OLE-DB–compatible databases.)
6. In the Specify an ID for the data source box, a default data source control name is displayed (SqlDataSource1). You
can leave this name.
7. Click OK.
The Configure Data Source wizard displays a page in which you can create a connection.
8. Click New Connection.
If the Choose Data Source page appears, in the Data source list, select the type of data source you will use. For
this walkthrough, the data source type is Microsoft SQL Server. In the Data provider list, click .NET Framework
Data Provider for SQL Server, and the click Continue.
The Add Connection page appears.
9. On the Add Connection page, in the Server name text box, type the name of the computer running the SQL Server
database.
10. For the logon credentials, select the option that is appropriate for accessing the computer running the SQL Server
database (either integrated security or a specific ID and password) and, if required, enter a user name and password.
11. Select the Save my Password check box.
12. Click the Select or enter a database name button, and then enter Northwind.
13. Click Test Connection, and when you are sure that it works, click OK.
The Configure Data Source wizard appears with the connection information filled in.
14. Click Next.
The Configure Data Source wizard displays a page in which you can choose to store the connection string in the
configuration file. Storing the connection string in the configuration file has two advantages:
It is more secure than storing it in the page.
You can reuse the same connection string in multiple pages.
15. Be sure that the Yes, save this connection as check box is selected, and then click Next. You can leave the default
connection string.
The Configure Data Source wizard displays a page in which you can specify what data you want to fetch from the
database.
16. Make sure that Specify columns from a table or view is selected.
17. In the Name list, click Categories.
18. Under Columns, select the CategoryID and CategoryName check boxes.
The Configure Data Source wizard displays the SQL statement that you are creating in a box at the bottom of the page.
Note
The Configure Data Source wizard allows you to specify selection criteria (a WHERE clause) and other SQL query opti
ons. For this part of the walkthrough, you will create a simple statement with no selection or sort options.

19. Click Next.


20. Click Test Query to be sure that you are getting the data you want.
21. Click Finish.
The Configure Data Source wizard closes and you are returned to the SqlDataSource control. If you view the
properties for the SqlDataSource control, you can see that the Configure Data Source wizard has created values for
the ConnectionString and SelectQuery properties. Even though Properties in Visual Web Developer displays the full
connection string, only the connection string identifier is saved in the page (in this case, NorthwindConnectionString).
Formatting the Layout of the DataList Control
At this point, you have a DataList control on the page with a default layout for information from the Categories table. The
benefit of the DataList control is that you can create a free-form layout for the data. In this section, you will work with a
template and configure it with text and controls to customize the data display.
To format the layout in the DataList control
1. Right-click the DataList control, click Edit Template, and then click Item Templates.
The DataList control switches to template editing mode and displays template boxes for these templates:
ItemTemplate, which contains the text and controls that are displayed by default in the DataList control.
AlternatingItemTemplate, which is an optional template in which you can create a layout that is used for every
other data record. Typically, the AlternatingItemTemplate property is similar to the ItemTemplate property, but the
AlternatingItemTemplate property uses a different background color for a banded effect.
SelectedItemTemplate, which defines the layout for a data record that is explicitly selected using a button click or
other gesture. Typical uses for this template are to provide an expanded view of a data record or to serve as the
master record for a master/detail relationship. You must write code to support putting a record into selected mode.
(You will not do so in this walkthrough. For more information, see
How to: Allow Users to Select Items in DataList Web Server Controls and
Walkthrough: Creating Master/Detail Web Pages in Visual Studio.)
EditItemTemplate, which defines the layout for edit mode for a data record. Typically, the EditItemTemplate
property includes editable controls, such as the TextBox and CheckBox controls in which users can modify the data
record. You must write code to support putting a record into edit mode and to handle saving the record when the
edits are complete. (You will not do so in this walkthrough. For information about writing code to edit records, see
How to: Allow Users to Edit Items in DataList Web Server Controls.)
By default, Visual Web Developer populates the item template with a data-bound Label control for each data column in
the data source. In addition, Visual Web Developer generates static text for each label to act as a caption.
2. Drag the right-hand resize handle to widen the DataList control so it takes up most of the page width.
3. Edit the item template to rearrange the Label controls and create a new caption so that the template contents look
similar to the following code example.

Name: [CategoryNameLabel] (ID: [CategoryIDLabel])

4. Click the CategoryNameLabel control. In Properties, expand the Font node, and then set Bold to true.
5. In Design view, on the DataList control, right-click the title bar, click Edit Template, and then click Separator Template.
The separator template allows you to specify what text or other elements are displayed between data records.
6. In the Toolbox, from the HTML group, drag a Horizontal Rule element into the separator template.
7. On the DataList control, right-click the title bar, and then click End Template Editing.
Testing the DataList Control
You can now test the layout that you have created.
To test the DataList control
Press CTRL+F5 to run the page.
The page displays a list of category names and IDs, with a line between each record.
Displaying Related Information Inside the DataList Control
The DataList control that you are using currently displays individual Category records, using the custom layout that you
defined previously. You changed the default layout only a little bit, but you can see that by working with the template, you can
arrange text and controls, format the content, and modify the data record display in other ways.
The layout can include the current record, as well as related records. In this part of the walkthrough, you will change the layout
so that each row displays a category and the products in that category. In effect, you will display a master/detail relationship
within each row of the DataList control. You will need to write a short piece of code to enable this scenario.
To display related information inside the DataList control
1. Right-click the DataList control, click Edit Templates, and then click Item Templates.
2. In the Toolbox, from the Standard group, drag a BulletedList control onto the item template, and then drop the
BulletedList control below the category information.
The BulletedList control can display data, with one data column per bulleted item.
3. Right-click the BulletedList control, and then click Show Smart Tag.
4. Click Choose Data Source.
You will create a second data source control to read the related records.
5. In the Choose Data Source dialog box, in the Select a data source list, click New Data Source.
6. Click Database.
7. In the Specify an ID for the data source box, type bulletedListDataSource.
Although you can usually leave the default name for the data source, in this case it is useful to assign a specific,
predictable name to the data source so that you can reference it later in code.
8. Click OK.
The Configure Data Source wizard appears.
9. In the Which data connection should your application use to connect to the database? list, click the name of the
connection that you created earlier in this walkthrough, and then click Next.
The Configure Data Source wizard displays a page in which you can create an SQL statement.
10. Under Specify columns from a table or view, in the Name box, click Products.
11. In the Columns box, select the ProductName box.
The BulletedList control displays only one column.
12. Click the WHERE button.
The Add WHERE Clause dialog box appears.
13. In the Column list, click CategoryID.
14. In the Operator list, click =.
15. In the Source list, click None.
This indicates that the value of the CategoryID column will be provided in a variable.
16. Click Add, click OK, click Next, and then click Finish.
Testing the query will not work with the variable.
17. In the Select a data field to display in the BulletedList list, click ProductName. Click OK.
18. In the DataList control, right-click the title bar, and then click End Template Editing.
Writing Code to Set the Category ID
The SQL statement that you created for the bulletedListDataSource control looks similar to the following code:

SELECT [ProductName] FROM [Products] WHERE ([CategoryID] = @CategoryID)

At run time, the DataList control displays a list of category records, which includes both the category name and the category
ID. In the preceding section, you added a BulletedList control that will display all the products for each category. As each
category record is being displayed, the DataList control executes a query to get the products for that category, using the
preceding query.
For each record being displayed, you must provide the category ID to the query. You can do this by writing a short piece of
code that gets the category ID from the record that is currently being displayed, and then passes the category ID as a
parameter to the query in the bulletedListDataSource control.
To write code to set the category ID
1. Click the DataList control, and then in Properties, on the toolbar, click Events.
2. Double-click ItemDataBound to create an event handler for that event.
3. Copy the following code into the handler.
VB
If e.Item.ItemType = ListItemType.Item Or _
e.Item.ItemType = ListItemType.AlternatingItem Then
Dim ds As SqlDataSource
ds = CType(e.Item.FindControl("bulletedListDataSource"), _
SqlDataSource)
Dim categoryID As String
categoryID = DataBinder.Eval(e.Item.DataItem, _
"categoryid").ToString()
ds.SelectParameters("CategoryID").DefaultValue = _
categoryID
End If

C#
if (e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem)
{
SqlDataSource ds;
ds = e.Item.FindControl("bulletedListDataSource")
as SqlDataSource;
ds.SelectParameters["CategoryID"].DefaultValue =
DataBinder.Eval(e.Item.DataItem,
"categoryid").ToString();
}

The ItemDataBound event is raised for each data record being displayed, providing you with an opportunity to read or
modify the data. This code does the following:
a. Checks to be sure that the event is occurring while binding an ItemTemplate or AlternatingItemTemplate
object (and not a SeparatorTemplate object or other type of template).
b. Uses the FindControl method to get a reference to the SqlDataSource control instance that is created inside each
item template.
c. Gets the value of the CategoryID data column by evaluating the current DataItem property.
d. Sets the CategoryID variable of the parameterized query by setting its DefaultValue property in the
SelectParameters collection.
Testing the Code
You can now test your code.
To test the code to set the category ID
Press CTRL+F5 to run the page.
The DataList control displays each category record, and for each record, it also displays, in a bulleted list, the products
that belong to that category.
Next Steps
This walkthrough has illustrated a simple but complete scenario for displaying and formatting data with the DataList Web
server control. You can create more sophisticated data-driven pages and applications using the techniques and controls
illustrated in the walkthrough. For example, you might want to:
Write code to allow users to select items in the DataList Web server control. For more information, see
How to: Allow Users to Select Items in DataList Web Server Controls.
Create a master record for a master/detail relationship. For more information, see
Walkthrough: Creating Master/Detail Web Pages in Visual Studio.
Learn how to use output caching in your data applications to improve performance. For more information, see
Walkthrough: Using Output Caching to Enhance Web Site Performance.
See Also
Tasks
How to: Allow Users to Select Items in DataList Web Server Controls
Walkthrough: Creating Master/Detail Web Pages in Visual Studio
Reference
DataList
Concepts
Walkthrough Topics — ASP.NET Data Access (Visual Studio)
Visual Web Developer

Walkthrough: Displaying Formatted Data in Web Pages with


the FormView Web Server Control
ASP.NET provides various controls that allow you to display and edit data records. In this walkthrough, you will work with the
FormView control, which works with a single data record at a time. The FormView control's primary feature is that it allows
you to create the record layout yourself by defining templates. By working with templates, you can have complete control over
the layout and appearance of the data within the control. The FormView control also supports updates such as editing,
inserting, and deleting data records. If the data source provides more than one record to the FormView control, the control
allows you to page through the records individually.
Note
You can also edit individual data records with the DetailsView control, which provides a predefined layout for the data. For de
tails, see DetailsView Web Server Control (Visual Studio).

Tasks illustrated in this walkthrough include:


Creating a page to display master/detail information.
Using a FormView control to create a free-form layout for a data record.
Configuring the FormView control to allow editing.
Prerequisites
In order to complete this walkthrough, you will need:
Microsoft Visual Web Developer.
Access to the SQL Server Northwind database. For information about downloading and installing the SQL Server sample
Northwind database, see Installing Sample Databases on the Microsoft SQL Server Web site.
Note
If you need information about how to log on to the computer running SQL Server, contact the server administrator.

Microsoft Data Access Components (MDAC) version 2.7 or later.


If you are using Microsoft Windows XP or Windows Server 2003, you already have MDAC 2.7. However, if you are using
Microsoft Windows 2000, you might need to upgrade the MDAC already installed on your computer. For more
information, see "Microsoft Data Access Components (MDAC) Installation" in the MSDN Library.
Creating the Web Site
Create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New, and then click Web Site. If you are using Visual Web Developer Express, on the File menu,
click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, enter the name of the folder where you want to keep the pages of your Web site.
For example, type the folder name C:\WebSites\FormViewData.
5. In the Language list, click the programming language you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Using a Drop-Down List as the Master
In this part of the walkthrough, you will add a drop-down list to a page and populate it with a list of product names. When
users select a product, the page will display the details for that product in a FormView control.
To create and populate a drop-down list
1. Switch to or open the Default.aspx page. If you are working with a Web site you had already created, add or open a page
that you can work with in this walkthrough.
2. Switch to Design view.
3. Type Display Product Information in the page.
4. From the Standard group in the Toolbox, drag a DropDownList control onto the page.
5. If the DropDownList Tasks menu does not appear, right-click the DropDownList control, and then click Show Smart
Tag.
6. On the DropDownList Tasks menu, select the Enable AutoPostBack check box.
7. Click Choose Data Source to open the Data Source Configuration Wizard.
8. In the Select a data source list, click <New Data Source>.
9. Click Database.
This specifies that you want to get data from a database that supports SQL statements.
In the Specify an ID for the data source box, a default data source control name is displayed. You can leave this name.
10. Click OK.
The wizard displays a page where you can select a connection.
11. Click the New Connection button.
The Add Connection dialog box appears.
If the Data source list does not display Microsoft SQL Server (SqlClient), click Change, and in the Change Data
Source dialog box, select Microsoft SQL Server.
If the Choose Data Source page appears, in the Data source list, select the type of data source you will use. For
this walkthrough, the data source type is Microsoft SQL Server. In the Data provider list, click .NET Framework
Data Provider for SQL Server, and then click Continue.
12. In the Add Connection dialog box, do the following:
a. In the Server name box, enter the name of the computer running SQL Server.
b. For the logon credentials, select the option that is appropriate to access the running the SQL Server database
(integrated security or specific ID and password) and, if required, enter a user name and password. Select the Save
my Password check box if you entered a password.
c. Select the Select or enter a database name button, and then enter Northwind.
d. Click Test connection, and when you are sure that the connection works, click OK.
You are returned to the wizard, and the connection information is filled in.
13. Click Next.
14. Be sure that the Yes, save this connection as check box is selected, and then click Next. (You can leave the default
connection string name.)
The wizard displays a page where you can specify what data you want to retrieve from the database.
15. Click Specify columns from a table or view.
16. In the Name list, click Products.
17. Under Columns, select ProductID and ProductName.
18. Click Next.
19. Click Test Query to be sure that you are retrieving the data you want.
20. Click Finish.
You are returned to the wizard.
21. In the Select a data field to display in the DropDownList list, click ProductName.
22. From the Select a data field for the value of the DropDownList list, select ProductID.
This specifies that when an item is selected, the ProductID field will be returned as the value of the item.
23. Click OK.
Before proceeding, test the drop-down list.
To test the drop-down list
1. Press CTRL+F5 to run the page.
2. When the page is displayed, examine the drop-down list.
3. Select a product name to be sure that the list performs a postback.
Adding a FormView Control
You will now add a FormView control to display product details. The FormView control gets its data from a second data
source control that you add to the page. The second data source control contains a parameterized query that gets the product
record for the item currently selected in the DropDownList control.
To add a FormView control
1. From the Data group in the Toolbox, drag a FormView control onto page.
2. If the FormView Tasks menu does not appear, right-click the FormView control, and then click Show Smart Tag.
3. On the FormView Tasks menu, in the Choose Data Source list, click <New Data Source>.
The Data Source Configuration Wizard dialog box appears.
4. Click Database.
The FormView control will get data from the same table as the DropDownList control.
In the Specify an ID for the data source box, a default data source control name is displayed. You can leave this name.
5. Click OK.
The Configure Data Source wizard starts.
6. From the Which data connection should your application use to connect to the database? list, select the
connection you created and stored earlier in the walkthrough.
7. Click Next.
The wizard displays a page where you can create a SQL statement.
8. From the Name list under Specify columns from a table or view, select Products.
9. In the Columns box, select ProductID, ProductName, and UnitPrice.
10. Click the WHERE button.
The Add WHERE Clause dialog box is displayed.
11. From the Column list, select ProductID.
12. From the Operator list, select =.
13. From the Source list, select Control.
14. Under Parameter properties, in the Control ID list, select DropDownList1.
The last two steps specify that the query will get the search value for the product ID from the DropDownList control you
added earlier.
15. Click Add.
16. Click OK to close the Add WHERE Clause dialog box.
17. Click Advanced.
The Advanced SQL Generation Options dialog box appears.
18. Select the Generate INSERT, UPDATE, and DELETE statements check box.
This option causes the wizard to create SQL update statements based on the Select statement you have configured. Later
in the walkthrough you will use the FormView control to edit and insert records, which requires update statements in
the data source control.
19. Click OK.
20. Click Next.
21. In the Preview page, click Test Query.
The wizard displays a dialog box that prompts you for a value to use in the WHERE clause.
22. In the Value box, type 4 and then click OK.
The product information appears.
23. Click Finish.
Customizing the Layout in the FormView Control
The reason to use the FormView control is that you can define the layout of the record that it displays. In this section of the
walkthrough, you will customize the record layout by editing a template. For your layout, you will use an HTML table.
To format the layout
1. Click the FormView control to select it, and then drag the resize handle on the right side of the control to make the
control as wide as the current page.
2. Drag the resize handle on the bottom of the control to change the height of the control to about 400 pixels. (The exact
height is not important.)
3. Right-click the control, click Edit Template, and then click ItemTemplate.
The control is redisplayed in item template editing mode. The item template contains the static text and controls that are
used to display the data record when the page runs. By default, Visual Web Developer populates the item template with a
data-bound Label control for each data column in the data source. In addition, Visual Web Developer generates static text
for each label to act as a caption.
The template is also generated with three LinkButton controls with the text Edit, Delete, and New.
4. Put the insertion point at the top of the item template, press ENTER a few times to make room, and then at the top of the
template type Product Details to act as a heading.
5. Put the insertion point below the controls and static text and, in the Layout menu, click Insert Table.
You are creating an HTML table as a container for the text and controls.
6. In the Insert Table dialog box, do the following:
a. Set Rows to 4.
b. Set Columns to 2.
c. Click the Cell Properties button, and set Width to 35 pixels (px) and Height to 30 pixels (px).
7. Click OK to close the Cell Properties dialog box, and then click OK to close the Insert Table dialog box.
8. Drag the ProductIdLabel control into the top right-hand cell.
9. Drag the ProductNameLabel control into the second right-hand cell.
10. Drag the UnitPriceLabel control into the third right-hand cell.
11. In the left-hand column, type static text to act as captions for the Label controls. For example, in the cell next to the
ProductIdLabel control, type ID. You can type any caption text that you like.
12. Right-click the left-hand column, click Select, and then click Column.
13. In the Properties window, set align to right to make the caption text right-aligned.
14. Select the right-hand column and drag its right-hand border to make the table wide enough to display long product
names.
15. Select the text generated by Visual Web Developer (for example, the text ProductID) and delete it.
16. Right-click the FormView control's title bar and click End Template Editing.
The template editor closes and the control appears with the layout you have created.
Testing the FormView Control
You can now test your layout.
To test the FormView control
1. Press CTRL+F5 to run the page.
2. In the DropDownList control, click a product name.
The FormView control displays details about that product.
3. Select a different product and confirm that the FormView control displays the product details.
4. Close the browser.
Adding Edit and Insert Capabilities to the FormView Control
The FormView control can display individual records and also supports editing, deleting, and inserting.
In this part of the walkthrough, you will add the ability to edit the currently displayed record. To edit the record, you define a
different template that contains text boxes (and potentially other controls).
To add editing capability to the FormView control
1. Right-click the FormView control, click Edit Template, and click EditItemTemplate.
The template editor appears, displaying the EditItemTemplate property, which defines how records are laid out when the
control is in edit mode. Visual Web Developer populates the edit template with a TextBox control for each data column
that is not a key and adds static text for captions. This is similar to the way the item template was generated, except that
in the edit template, Visual Web Developer generates text boxes.
As before, the template is generated with Update and Cancel LinkButton controls that are used to save and discard
changes while editing.
2. Optionally, add a layout table and arrange the controls as you did when working with the item template earlier in the
walkthrough.
3. Right-click the FormView control, click Edit Template, and then click InsertItemTemplate.
As with the EditItemTemplate property, Visual Web Developer automatically creates a template layout of labels and
TextBox controls. The controls will be displayed when users want to insert a new record into the Products table. The
template is also generated with Insert and Cancel LinkButton controls.
4. Optionally, add a layout table and arrange the controls as you did when working with the edit item template.
5. Right-click the FormView control and click End Template Editing.
Security Note
User input in an ASP.NET Web page can include potentially malicious client script. By default, ASP.NET Web pages valid
ate user input to make sure input does not include script or HTML elements. As long as this validation is enabled, you d
o not need to explicitly check for script or HTML elements in user input. For more information, see
Script Exploits Overview.

Testing Editing and Inserting


You can now test editing and inserting.
To test editing capabilities of the FormView control
1. Press CTRL+F5 to run the page.
2. Select a product in the DropDownList control.
The product details appear in the FormView control.
3. Click Edit.
The FormView control switches to edit mode.
4. Make a change to the product name or unit price.
5. Click Update.
The record is saved and the FormView control switches to display mode. The change is reflected in the display.
6. Select a different product.
7. Click Edit.
8. Make a change to the product name.
9. Click Cancel.
Confirm that the change was not saved.

To test insert capabilities of the FormView control


1. Click New in the FormView control.
The FormView control switches to insert mode, displaying two empty text boxes.
2. Enter a new product name and price, and then click Insert.
The record is saved in the database and the FormView control switches to display (ItemTemplate) view.
Note
The new record is not displayed in the drop-down list. You will add that capability in the next section.

Redisplaying Updated Product Names in the Drop-Down List


Your page now allows you to view, edit, or delete records in the Products database table. However, the drop-down list is not
yet synchronized with changes that you make in the FormView control. For example, if you insert a new Products record, the
drop-down list does not display the new record unless you close the page and reopen it. In addition, the page is displayed
initially with the first record in the Products table, which might not be what you want.
You can add some code to fix these minor issues. In this section of the walkthrough, you will do the following:
Update the drop-down list whenever users edit or insert a record.
Add the text "(Select)" to the drop-down list when the page first appears, and remove it when the user has made the first
selection.

To update the drop-down list when records are edited or inserted


1. In Design view of the page, select the FormView control.
2. In the Properties window, click the Events button to display a list of events for the FormView control.
3. Double-click the ItemInserted box.
Visual Web Developer switches to code-editing view and creates a handler for the ItemInserted event.
4. Add the following highlighted code to the event handler.
VB
Protected Sub FormView1_ItemInserted(ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.FormViewInsertedEventArgs) _
Handles FormView1.ItemInserted
DropDownList1.DataBind()
End Sub

C#
protected void FormView1_ItemInserted(object sender,
FormViewInsertedEventArgs e)
{
DropDownList1.DataBind();
}

The code runs after the new record has been inserted. It re-binds the drop-down list to the Products table, which causes
the contents of the list to be refreshed.
5. Switch to Design view. (If you are working with a code-behind page, switch to the Default.aspx page and then switch to
Design view.)
6. In the Properties window, click the Events button to display a list of events for the FormView control.
7. Double-click the ItemUpdated box.
Visual Web Developer switches to code-editing view and creates an event handler for the ItemUpdated event.
8. Add the following highlighted code.
VB
Protected Sub FormView1_ItemUpdated(ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.FormViewUpdatedEventArgs) _
Handles FormView1.ItemUpdated
DropDownList1.DataBind()
End Sub

C#
protected void FormView1_ItemUpdated(object sender,
FormViewUpdatedEventArgs e)
{
DropDownList1.DataBind();
}

The code runs after the record has been updated. It re-binds the drop-down list to the Products table, which causes the
contents of the list to be refreshed.
9. Press CTRL+F5 to run the page.
10. Edit the product name of a record, click Update, and then examine the drop-down list to be sure that the updated name
is displayed.
11. Insert a new product record, click Insert, and then examine the drop-down list to be sure that the new name has been
added to the list.
The final step is to change the drop-down list to display "(Select)" and to display the FormView control only when users have
made a selection.
To add a Select entry to the DropDownList control
1. In Design view, double-click a blank part of the page.
Visual Web Developer creates an event handler for the page's Load event.
2. In the handler, add the following highlighted code.
VB
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
FormView1.Visible = False
End If
End Sub

C#
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
FormView1.Visible = false;
}
}

The code runs when the page runs. It tests first to see if this is a postback; if not, this is the first time the page has run. If it
is not a postback, the code hides the FormView control, because you want to display it only when the user has explicitly
selected a record to view or edit.
3. In Design view for the page, select the DropDownList control.
4. In the Properties window, click the ellipsis (...) in the Items box.
The ListItem Collection Editor dialog box appears.
5. Click Add to create a new item.
6. Under ListItem properties, in the Text box, type (Select).
7. Click OK to close the ListItem Collection Editor dialog box.
8. In the Properties box, set AppendDataBoundItems to true.
When the drop-down list is populated during data binding, the product information will be added to the (Select) item
you defined.
9. In the Properties window, click the Events button to display a list of events for the DropDownList control.
10. Double-click the SelectedIndexChanged box.
11. Add the following highlighted code.
VB
Protected Sub DropDownList1_SelectedIndexChanged(ByVal sender _
As Object, ByVal e As System.EventArgs) _
Handles DropDownList1.SelectedIndexChanged
If DropDownList1.Items(0).Text = "(Select)" Then
DropDownList1.Items.RemoveAt(0)
End If
FormView1.Visible = True
End Sub
C#
protected void DropDownList1_SelectedIndexChanged(object sender,
EventArgs e)
{
if(DropDownList1.Items[0].Text == "(Select)")
{
DropDownList1.Items.RemoveAt(0);
}
FormView1.Visible = true;
}

The code runs when users select an item in the DropDownList control. It removes the "(Select)" item that you added
earlier (checking first to be sure it exists), because after the first time users have selected an item, you no longer need to
prompt them to select an item. The code also displays (un-hides) the FormView control so that users can see the record
they have selected.
12. Press CTRL+F5 to run the page.
The page displays only the drop-down list, with the word (Select) displayed.
13. Select an item in the list.
The item is displayed in the FormView control.
14. Examine the drop-down list and note that the word (Select) is no longer in the list.
Next Steps
This walkthrough has shown you the basic steps for using a FormView control to display and edit individual data records
using a custom layout. The FormView control allows you to perform more sophisticated formatting than what you have done
in this walkthrough. In addition, you can create templates for other modes, including selection mode and insertion mode, and
for headers and footers that are displayed with the record. For other scenarios to explore with the FormView, see the
following:
Creating Templates for the FormView Web Server Control
Modifying Data Using a FormView Web Server Control
See Also
Other Resources
FormView Web Server Control
DetailsView Web Server Control
Visual Web Developer

Walkthrough: Creating Master/Detail Web Pages in Visual


Studio
Many Web pages display data in more than one way, often displaying data from related tables. This walkthrough shows you
various ways to work with data in multiple controls and from multiple tables, including those that have a master/detail
relationship. Tasks illustrated in this walkthrough include:
Populating a drop-down list with database data.
Creating filters — SQL statements with a WHERE clause (parameterized queries).
Displaying filtered data based on the user's selection in a drop-down list.
Displaying details about a selected record using the DetailsView control.
Selecting a record in one page and displaying a related record in a second page.
Prerequisites
In order to complete this walkthrough, you will need:
Access to the SQL Server Northwind database. For information about downloading and installing the SQL Server sample
Northwind database, see Installing Sample Databases on the Microsoft SQL Server Web site.
Note
If you need information about how to log on to the computer running SQL Server, contact the server administrator.

Microsoft Data Access Components (MDAC) version 2.7 or later.


If you are using Microsoft Windows XP or Windows Server 2003, you already have MDAC 2.7. However, if you are using
Microsoft Windows 2000, you might to need to upgrade the MDAC already installed on your computer. For more
information, see the article " Microsoft Data Access Components (MDAC) Installation" in the MSDN Library.
Creating the Web Site
If you have already created a Web site in Microsoft Visual Web Developer (for example, by following the steps in
Walkthrough: Creating a Basic Web Page in Visual Web Developer or Walkthrough: Basic Data Access in Web Pages), you can
use that Web site and skip to the next section, "Connecting to SQL Server." Otherwise, create a new Web site and page by
following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, enter the name of the folder where you want to keep the pages of your Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click the programming language you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Connecting to SQL Server
To work with data, you need to establish a connection to a database. In this walkthrough, you will create a connection
independently of working with Web pages or controls.
To create a connection to SQL Server
1. Press CTRL+ALT+S to display the Database Explorer. In Database Explorer, right-click Data Connections and choose
Add Connection.
The Change Data Source dialog box is displayed.
2. In the Change Data Source dialog box, select Microsoft SQL Server. and click OK.
3. In the Add Connection dialog box, do the following:
Enter or select the name of your SQL Server computer. For a server on your computer, enter (local).
Select Use SQL Server Authentication.
Enter a user name and password.
Select Save my password.
Select Northwind as the database.
4. Click Test Connection, and when you are sure that it works, click OK.
The connection is added to Server Explorer.
Using a Drop-Down List as the Master
In this part of the walkthrough, you will add a drop-down list to a page and populate it with a list of categories from the
Northwind table. When users select a category, the page will display the products for that category.
To create and populate a drop-down list
1. Switch to or open the Default.aspx page. If you are working with a Web site you had already created, add or open a page
that you can work with in this walkthrough.
2. Switch to Design view.
3. Type Select Products By Category in the page and format the text as a heading using the Block Format drop-down list
above the Toolbox.
4. From the Standard group in the Toolbox, drag a DropDownList control onto the page.
5. In the DropDownList Tasks, select the Enable AutoPostBack check box.
This configures the control so that it causes the page to post back to the server whenever a selection is made from the
list, rather than waiting until the user clicks a button.
6. In the DropDownList Tasks, select Choose Data Source.
The Choose Data Source wizard starts.
7. In the Select a data source list, click <New Data Source>.
The Data Source Configuration Wizard dialog box is displayed.
8. Select Database.
This specifies that you want to get data from a database that supports SQL statements. (This includes SQL Server and
other OLE-DB-compatible databases.)
In the Specify an ID for the data source box, a default data source control name is displayed (SqlDataSource1). You
can leave this name.
9. Click OK.
The wizard displays the Configure Data Source - SqlDataSource1 page in which you can select a data connection.
10. From the drop-down list, select the Northwind connection you created earlier in the walkthrough.
11. Click Next.
The wizard displays a page in which you can choose to store the connection string in the configuration file.
12. Be sure the Yes, save this connection as check box is selected, and then click Next. (You can leave the default
connection string name.)
The wizard displays a page in which you can specify what data you want to retrieve from the database.
13. From the Name list under Table or View Options, select Categories.
14. In the Columns box, select CategoryID and CategoryName.
15. Click Next.
16. Click Test Query to be sure that you are getting the data you want.
17. Click Finish.
The Data Source Configuration Wizard is displayed, with the name of the data source control you have configured
displayed.
18. From the Select a data field to display in the DropDownList list, select CategoryName.
Note
If no items appear in the list, click the Refresh Schema link.

This specifies that the value of the CategoryName field will be displayed as the text of the item in the drop-down list.
19. From the Select a data field for the value of the DropDownList list, select CategoryID.
This specifies that when an item is selected, the CategoryID field will be returned as the value of the item.
20. Click OK.
Before proceeding, test the drop-down list.
To test the drop-down list
1. Press CTRL+F5 to run the page.
2. When the page is displayed, examine the drop-down list.
3. Select a category to be sure that the list performs a postback.
You can now display products for the category selected in the drop-down list.
Using a Grid to Display Detail Information
You can now extend the page to include a grid. When users make a selection from the categories drop-down list, the grid will
display the products for that category.
To use a grid to display detail information
1. Switch to or open the Default.aspx page (or the page you have been working with), and switch to Design view.
2. From the Data group of the Toolbox, drag a GridView control onto the page.
3. From the GridView Tasks menu, select <New Data Source> from the Choose Data Source list.
The Data Source Configuration Wizard opens.
4. Select Database.
In the Specify an ID for the data source box, a default data source control name is displayed (SqlDataSource2). You
can leave this name.
5. Click OK.
The wizard displays a page where you can select a connection.
6. From the connections drop-down list, select the connection you created and stored earlier in the walkthrough
(NorthwindConnectionString).
7. Click Next.
The wizard displays the Configure Data Source - SqlDataSource2 page in which you can create a SQL statement.
8. From the Name list, select Products.
9. In the Columns box, select ProductID, ProductName, and CategoryID.
10. Click WHERE.
The Add WHERE Clause dialog box is displayed.
11. From the Column list, select CategoryID.
12. From the Operator list, select =.
13. From the Source list, select Control.
14. Under Parameter Properties, in the Control ID list, select DropDownList1.
The last two steps specify that the query will get the search value for the category ID from the DropDownList control you
added earlier.
15. Click Add.
16. Click OK to close the Add WHERE Clause dialog box.
17. Click Next.
18. In the Preview page, click Test Query.
The wizard displays a dialog box that prompts you for a value to use in the WHERE clause.
19. Type 4 in the box and click OK.
The products records for category 4 are displayed.
20. Click Finish to close the wizard.
You can now test the master/detail display.
To test the page
1. Press CTRL+F5 to run the page.
When the page appears, products from the first item in the drop-down list are displayed.
2. Select a category from the list and confirm that the corresponding products appear in the grid.
Displaying Master/Detail Data on the Same Page
In this part of the walkthrough, you will display data from related tables in one page. The master table data is displayed in a
grid where users can select individual rows. When they do, one or more detail records are displayed in a scrollable control
elsewhere on the page. For illustration purposes, you will use the Northwind Categories table as the master table and the
Products table as the details table.
To display the master records
1. Add a new page to the Web site and name it MasterDetails2.aspx.
2. Switch to Design view.
3. Type Master/Detail Page in the page and format the text as a heading.
4. From the Data group of the Toolbox, drag a GridView control onto the page.
5. In the GridView Tasks menu, in the Choose Data Source list, click <New Data Source> and then use these steps to
configure a data source for the GridView control:
a. Select Database.
b. Click OK.
c. From the connection drop-down list, select the connection you created and stored earlier in the walkthrough
(NorthwindConnectionString).
d. Click Next.
e. From the Name list, select Categories.
f. In the Columns box, select CategoryID and CategoryName.
g. Click Next and then click Finish.
6. Select the GridView control, and in the GridView Tasks menu, choose Edit Columns.
The Fields dialog box is displayed.
7. Under Available Fields, open the Command Field node, choose Select, and then click Add to add it to the Selected
Fields list.
8. In the Selected Fields list, choose Select, and then in the CommandField property grid, set its SelectText property to
Details.
9. Click OK to close the Fields dialog box.
A new column with a Details hyperlink is added to the grid.
10. Select the GridView control and in the Properties window, be sure its DataKeyNames property is set to CategoryID.
This specifies that when you select a row in the grid, ASP.NET can find the key of the currently displayed Categories
record in a known location.
The grid allows you to select an individual category. The next step is to add the DetailsView control that will display the detail
records — the products associated with the selected category. The DetailsView control will use a different SQL query to get its
data, so it requires a second data source control.
To configure a query to display related records
1. Press ENTER to make space underneath the SqlDataSource1 control on the MasterDetails2.aspx page in Details view.
2. From the Data group of the Toolbox, drag a DetailsView control onto the page.
3. Configure it to use a second data source control using the following steps:
a. From the Choose Data Source list, select <New Data Source>.
b. Select Database.
c. Click OK.
d. In the connection drop-down list, click the connection you created and stored earlier in the walkthrough.
e. Click Next.
f. From the Name list under Table or View Options, select Products.
g. In the Columns box, select ProductID, ProductName, and CategoryID.
h. Click WHERE.
The Add WHERE Clause dialog box is displayed.
i. From the Column list, select CategoryID.
j. From the Operator list, select =.
k. From the Source list, select Control.
l. Under Parameter Properties, in the Control ID list, select GridView1. The query for the second grid will get its
parameter value from the selection in the first grid.
m. Click Add and then click OK to close the Add WHERE Clause dialog box.
n. Click Next.
o. In the Preview page, click Test Query.
The wizard displays a dialog box that prompts you for a value to use in the WHERE clause.
p. Type 4 in the box and click OK.
The products records for category 4 are displayed.
q. Click Finish.
4. In the DetailsView Tasks menu, check Enable Paging.
This will allow you to scroll through individual product records.
5. Optionally, in the Properties window, open the PagerSettings node and select a different Mode value.
By default, you page through records by clicking a page number, but you can select options to use next and previous
links.
You can now test the combination of the master grid and the details view.
To test the page
1. Press CTRL+F5 to run the page.
2. In the grid, select a category.
The DetailsView control displays a product associated with that category.
3. Use the pager links in the DetailsView control to navigate to other products for the same category.
4. In the grid, select a different category.
5. Review the products for that category in the DetailsView control.
Displaying Master/Detail Data on Separate Pages
For the final part of the walkthrough, you will create another variation — displaying master and detail records on separate
pages. The master records are again displayed in a grid that contains a hyperlink for each record. When users click the
hyperlink, they navigate to a second page where they can view detail records in a DetailsView control that displays the
complete Products record.
To display the master records
1. Add a new page to the Web site and name it MasterCustomers.aspx.
2. Switch to Design view.
3. Type Customers in the page and format the text as a heading.
4. From the Data folder of the Toolbox, drag a GridView control onto the page.
5. From the GridView Tasks menu on the control, choose <New Data Source> from the Choose Data Source list and
then use the wizard to do the following:
Click Database.
Connect to the Northwind database (connection NorthwindConnectionString).
Retrieve the CustomerID, CompanyName, and City columns from the Customers table.
6. Optionally, on the GridView Tasks menu, select the Enable paging check box.
7. In the GridView Tasks menu, choose Edit Columns.
The Fields dialog box is displayed.
8. Clear the Auto-Generate Fields check box.
9. Under Available Fields, choose HyperLink Field, click Add, and then set the following properties:
Property Value
Text Details

DataNavigat CustomerID
eUrlFields
This indicates that the hyperlink should get its value from the CustomerID column

DataNavigat DetailsOrders.aspx?custid={0}
eUrlFormatSt
ring This creates a link that is hard-coded to navigate to the DetailsOrders.aspx page. The link also passes a qu
ery string variable named custid whose value will be filled using the column referenced in the DataNavi
gateUrlFields property.

10. Click OK to close the Fields dialog box.


You can now create the details page that accepts a value from the master page.
To create the details page
1. Add a new page to the Web site and name it DetailsOrders.aspx.
2. Switch to Design view.
3. Type Orders in the page and format the text as a heading.
4. From the Data folder of the Toolbox, drag a GridView control onto the page.
5. In the GridView Tasks menu on the control, select <New Data Source> from the Choose Data Source list
6. In the Select a data source type list, click Database and then click OK.
7. From the connection list, select the connection you created and stored earlier in the walkthrough
(NorthwindConnectionString).
8. Click Next.
The wizard displays a page where you can create a SQL statement.
9. From the Name list, select Orders.
10. In the Columns box, select OrderID, CustomerID, and OrderDate.
11. Click WHERE.
12. From the Columns list, select CustomerID.
13. From the Operators list, select =.
14. From the Source list, select QueryString.
This specifies that the query will select records based on the value passed into the page with the query string.
15. Under Parameter Properties, in the QueryString field box, type custid.
The query will get the customer ID value from the query string, which is created when you click a Details link in the
MasterCustomers.aspx page.
16. Click Add.
17. Click OK to close the Add WHERE Clause dialog box.
18. Click Next, and then click Finish to close the wizard.
19. From the Standard node of the Toolbox, drag a Hyperlink control onto the page. Set its Text property to Return to
Customers and its NavigateUrl property to MasterCustomers.aspx.
You can now test the related master-detail pages.
To test the pages
1. Switch to the MasterCustomers.aspx page.
2. Press CTRL+F5 to run the page.
3. Click the Details link for a customer.
The browser displays the DetailsOrders.aspx page with the order for the selected customer. Note that the URL in the
browser's Address box is:

DetailsOrder.aspx?custid=x

where x is the ID of the customer you selected.


4. Click the Return to Customers link, select a different customer, and click the Details link again to test that you can view
orders for any customer.
Next Steps
This walkthrough has illustrated various ways to display data from related tables. All the scenarios have the following in
common: they rely on a parameterized query, and the parameter values can be passed to the query automatically at run time.
You might want to experiment with additional ways to use related data. For example, you might want to:
Experiment with parameters that get their values from other sources, such as a Session variable or a cookie. For more
information, see Using Parameters with Data Source Controls.
Expand what you can do with the DetailsView control from the second part of the walkthrough. For example, you can
configure the control to allow users to edit detail records. For details, see
Walkthrough: Editing and Inserting Data in Web Pages with the DetailsView Web Server Control.
See Also
Concepts
Data Source Controls Overview
Modifying Data using Data Source Controls
Visual Web Developer

Walkthrough: Data Binding Web Pages with a Visual Studio


Data Component
Many Web applications are built by using multiple tiers, with one or more components in the middle tier that combine data
access together with business logic. This walkthrough shows you how to build a data-access component in a Web site and bind
a Web server control (a GridView control) to the data that is managed by the component. The data component interacts with a
Microsoft SQL Server database, and can both read and write data.
Tasks illustrated in this walkthrough include the following:
Creating a component that can read and write data.
Referencing the data component as a data source on a Web page.
Binding a control to the data that is returned by the data component.
Reading and writing data using the data component.
Prerequisites
In order to complete this walkthrough, you will need the following:
Access to the SQL Server Northwind database. For information about downloading and installing the SQL Server sample
Northwind database, see Installing Sample Databases on the Microsoft SQL Server Web site.
Note
If you need information about how to log on to the computer running SQL Server, contact the server administrator.

Microsoft Data Access Components (MDAC) version 2.7 or later.


If you are using Microsoft Windows XP or Windows Server 2003, you already have MDAC 2.7. However, if you using
Microsoft Windows 2000, you might to have to upgrade the MDAC version that is already installed on the computer. To
download the current MDAC version, see the Data Access and Storage Developer Center.
Creating the Web Site
If you have already created a Web site in Visual Web Developer by completing
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and go to the next section.
Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the left-most Location list, click File System, and then in the right-most Location textbox, enter the name of the folder
where you want to keep the pages of the Web site.
For example, type the folder name C:\WebSites\ComponentSample.
5. In the Language list, click the programming language that you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Creating a Data-Access Component
In this walkthrough, you will use a wizard to generate a component that reads data from and writes data to the Northwind
database. The component includes a schema file (.xsd) describing the data that you want and the methods that will be used to
read and write data. You will not have to write any code. At run time, the .xsd file is compiled into an assembly that performs
the tasks that you specify in the wizard.
To create a data-access component
1. If the Web site does not already have an App_Code folder, do the following:
a. In Solution Explorer, right-click the name of the Web site.
b. Point to Add Folder, and then click App_Code Folder.
2. Right-click the App_Code folder, and then click Add New Item.
The Add New Item dialog box appears.
3. Under Visual Studio installed templates, click DataSet.
4. In the Name box, type EmployeesObject, and then click Add.
The TableAdapter Configuration wizard appears.
5. Click New Connection.
6. If the Choose Data Source dialog box appears, click Microsoft SQL Server and then click Continue.
7. In the Server name box, enter the name of the computer that is running SQL Server.
8. For the logon credentials, select the option that is appropriate for accessing the SQL Server database (integrated security
or specific ID and password) and if it is required, enter a user name and password.
If you specify explicit credentials, select the Save my password check box.
9. Click Select or enter a database name, and then enter Northwind.
10. Click Test connection, and when you are sure that the connection works, click OK.
The TableAdapter Configuration wizard appears with the connection information filled in.
11. Click Next.
A page where you can choose to store the connection string in the configuration file appears.
12. Select the Yes, save this connection as check box, and then click Next.
You can leave the default connection string name.
A page where you can choose to use SQL statements or stored procedures appears.
13. Click Use SQL statements, and then click Next.
Using stored procedures has some advantages, including performance and security. However, for simplicity in this
walkthrough, you will use an SQL statement.
A page where you can define the SQL statement appears.
14. Under What data should be loaded into the table, type the following SQL statement:

SELECT EmployeeID, LastName, FirstName, HireDate FROM Employees

Note
You can click Query Builder to use a builder tool, if you prefer.

15. Click Next.


A page where you can define the methods that the component will expose appears.
16. Click to clear the Fill a DataTable check box, and then select the Return a DataTable and Create methods to send
updates directly to the database check boxes.
You do not need a method to fill a data table for this walkthrough. However, you will need a method that returns the data
and you also want the component to contain methods that update the database.
17. In the Method Name box, type GetEmployees.
You are naming the method that will be used later to obtain data.
18. Click Finish.
The wizard configures the component and displays it in the component designer, displaying the data that the component
manages and the methods that the component exposes.
19. Save the data component, and then close the component designer.
20. On the Build menu, click Build Web Site to make sure that the component compiles correctly.
Using the Data Component on a Page
You can now use the data component as a data source in an ASP.NET Web page. To access the data component, you will use an
ObjectDataSource control, configuring it to call the data-access methods that are exposed by the data component. You can
then add controls to the page and bind them to the data source control.
To add a data source control to the page
1. Open the Default.aspx page and switch to Design view.
2. From the Data group in the Toolbox, drag an ObjectDataSource control onto the page.
If the ObjectDataSource Tasks shortcut menu does not appear, right-click the ObjectDataSource control, and
then click Show Smart Tag.
3. On the ObjectDataSource Tasks shortcut menu, click Configure Data Source.
The Configure Data Source wizard appears.
4. In the Choose your business object list, click EmployeesObjectTableAdapters.EmployeesTableAdapter.
This is the type name (namespace and class name) of the component that you created in the preceding section.
5. Click Next.
6. On the Select tab, in the Choose a method list, click GetEmployees(), returns EmployeesDataTable.
The GetEmployees method is a method that was defined in the component that you created in the preceding section. It
returns the results of the SQL statement, available in a DataTable object that data controls can bind to.
7. Click Finish.
You can now add data controls to the page and bind them to the ObjectDataSource control. In this walkthrough, you will
work with the GridView control.
To add a GridView control to the page and bind it to the data
1. From the Data group in the Toolbox, drag a GridView control onto the page.
If the GridView Tasks shortcut menu does not appear, right-click the GridView control, and then click Show
Smart Tag.
2. On the GridView Tasks shortcut menu, in the Choose Data Source list, click ObjectDataSource1, which is the ID of
the control that you configured in the preceding section.
The GridView control reappears with a column for each data column that is returned by the SQL statement.
3. In Properties, verify that the DataKeyNames is set to EmployeeID.
Testing the Page
Now that all controls that you need are on the page, you can test the page.
To test the page
1. Press CTRL+F5 to run the page.
2. Confirm that the EmployeeID, LastName, FirstName, and HireDate columns from the Employees table are displayed in
the grid.
3. Close the browser.
The GridView control requests data from the ObjectDataSource control. In turn, the ObjectDataSource control creates an
instance of the data component and calls GetEmployees method for the data component. The GetEmployees method
returns a DataTable object, which the ObjectDataSource control returns to the GridView control.
Adding Updates to the Page
The data component that you created includes SQL statements to update the database (update, insert, and delete records). The
update facilities of the data component are exposed by methods that were generated automatically when the wizard created
the component. The GridView control and ObjectDataSource control can interact to automatically start the update methods.
Note
The GridView control does not support Insert.

To enable updates and deletes


1. Right-click the GridView control, and then click Show Smart Tag.
2. Select the Enable Editing check box.
3. Select the Enable Deleting check box.
Note
Enabling deletion lets you permanently remove records from the database. Do not enable deletion unless you are work
ing with expendable test data.

Testing Updates
You can now test to make sure that you can use the component to update the database.
To test updates
1. Press CTRL+F5 to run the page.
This time, the GridView control displays Edit and Delete links in each row.
2. Click the Edit link that is next to a row.
3. Make a change to the row, and then click Update.
The grid is redisplayed with the updated date.
4. Click the Delete link that is in a row.
The row is permanently deleted from the database. The grid is redisplayed without that row.
5. Close the browser.
Next Steps
This walkthrough illustrates how to work with a data component. You might want to experiment with additional features of
navigation. For example, you might want to do the following:
Create a custom data component instead of using the wizard.
For an example, see Walkthrough: Data Binding to a Custom Business Object.
Restrict which users can change the data. A typical method is to add membership and roles to the Web site, and then
establish rules that the business component can check before allowing changes to data.
For detailed information, see Walkthrough: Creating a Web Site with Membership and User Login (Visual Studio) and
Walkthrough: Managing Web Site Users with Roles.
See Also
Tasks
Walkthrough: Using Shared Code in Web Sites in Visual Web Developer
Walkthrough: Creating a Basic Web Page in Visual Web Developer
Concepts
Data Source Controls Overview
Using Parameters with Data Source Controls
Visual Web Developer

Walkthrough: Data Binding to a Custom Business Object


Many Web applications are built by using multiple tiers, with one or more components in the middle tier to provide data
access. Microsoft Visual Web Developer includes a wizard that helps you create a data component you can use as a middle-tier
data object, as described in Walkthrough: Data Binding Web Pages with a Visual Studio Data Component.
However, you might also want to build a custom business object, rather than relying on the data component created by the
wizard. Creating a custom business object allows you to implement your own business logic. This walkthrough illustrates how
to create a basic business object that you can use as a data source for ASP.NET Web pages.
During this walkthrough, you will learn how to:
Create a component that can return data to a Web page. The component uses an XML file for its data.
Reference the business object as a data source on a Web page.
Bind a control to the data returned by the business object.
Read and write data by using the business object.
Prerequisites
In order to complete this walkthrough, you will need:
Visual Web Developer (Visual Studio).
The .NET Framework.
This walkthrough assumes that you have a general understanding of how to use Visual Web Developer.
Creating the Web Site
If you have already created a Web site in Visual Web Developer (for example, by following the steps in
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and go to the next section,
"Creating an XML File for Business Data." Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, enter the name of the folder where you want to keep the pages of your Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click the programming language you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Creating an XML File for Business Data
In the following procedure, you will create a simple XML file for the business component data.
To create the XML file
1. In Solution Explorer, right-click App_Data, and then click Add New Item.
Note
Be sure you create the XML file in the App_Data folder. The App_Data folder has permissions set on it that will allow t
he Web page to read and write data to the XML file.
2. Under Visual Studio installed templates, click XML file.
3. In the Name box, type Authors.xml.
4. Click Add.
A new XML file is created that contains only the XML directive.
5. Copy the following XML data, and then paste it into the file, overwriting what is already in the file.
The XML file includes schema information that identifies the database structure of the data, including a primary-key
constraint for the key.
Note
Business components can work with data in any way that is suitable for your application. This walkthrough uses an XM
L file.

<?xml version="1.0" standalone="yes"?>


<dsPubs xmlns="http://www.tempuri.org/dsPubs.xsd">
<xs:schema id="dsPubs" targetNamespace="http://www.tempuri.org/dsPubs.xsd" xmlns:mstns
="http://www.tempuri.org/dsPubs.xsd" xmlns="http://www.tempuri.org/dsPubs.xsd" xmlns:x
s="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdat
a" attributeFormDefault="qualified" elementFormDefault="qualified">
<xs:element name="dsPubs" msdata:IsDataSet="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="authors">
<xs:complexType>
<xs:sequence>
<xs:element name="au_id" type="xs:string" />
<xs:element name="au_lname" type="xs:string" />
<xs:element name="au_fname" type="xs:string" />
<xs:element name="au_phone" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
<xs:unique name="Constraint1" msdata:PrimaryKey="true">
<xs:selector xpath=".//mstns:authors" />
<xs:field xpath="mstns:au_id" />
</xs:unique>
</xs:element>
</xs:schema>
<authors>
<au_id>172-32-1176</au_id>
<au_lname>West</au_lname>
<au_fname>Paul</au_fname>
<au_phone>408 555-0123</au_phone>
</authors>
<authors>
<au_id>213-46-8915</au_id>
<au_lname>Gray</au_lname>
<au_fname>Chris</au_fname>
<au_phone>415 555-0120</au_phone>
</authors>
</dsPubs>

6. Save the Authors.xml file, and then close it.


Creating a Component
The next step is to create a class to act as your business component. You will keep the component in the App_Code folder of
your Web site. In a real application, you can keep the component in any convenient store, including the global assembly cache.
If your Web site does not already have a directory named App_Code, you must create one.
To create an App_Code folder
In Solution Explorer, right-click the name of your Web site, click Add ASP.NET Folder, and then click App_Code.
Note
The folder must be named App_Code.

You can now add the component to your site.


To create the business component
1. In Solution Explorer, right-click the App_Code folder, and then click Add New Item.
Note
Be sure to create the new item in the App_Code folder.

The Add New Item dialog box appears.


2. Under Visual Studio installed templates, click Class.
3. In the Language box, click the programming language you prefer.
4. In the Name box, type BusinessObject.
5. Click Add.
Visual Web Developer creates the new class file and opens the code editor.
6. Copy the following code, and then paste it into the file, overwriting what is already in the file.
VB
Imports Microsoft.VisualBasic
Imports System
Imports System.Web
Imports System.Data
Namespace PubsClasses
Public Class AuthorClass
Private dsAuthors As DataSet = _
New System.Data.DataSet("ds1")
Private filePath As String = _
HttpContext.Current.Server.MapPath _
("~/App_Data/authors.xml")
Public Sub New()
dsAuthors.ReadXml(filePath, Data.XmlReadMode.ReadSchema)
End Sub

Public Function GetAuthors() As DataSet


Return dsAuthors
End Function
End Class
End Namespace

C#
using System;
using System.Web;
using System.Data;
namespace PubsClasses
{
public class AuthorClass
{
private DataSet dsAuthors = new DataSet("ds1");
private String filePath =
HttpContext.Current.Server.MapPath
("~/App_Data/Authors.xml");
public AuthorClass()
{
dsAuthors.ReadXml (filePath, XmlReadMode.ReadSchema);
}
public DataSet GetAuthors ()
{
return dsAuthors;
}
}
}

Note
Make sure the value of the filePath variable references the name of the XML file that you created previously.

When an instance of the class is created, it reads the XML file and translates it into a dataset. The class's GetAuthors
method returns the dataset.
7. Save the file. You must save the file for the next section to work properly.
Displaying Data by Using the Business Component
You can now invoke the business component in a Web page and display its data. To reference the component, you use an
ObjectDataSource control, which is specifically designed to work with objects.
To create an ObjectDataSource control that references the component
1. Switch to or open the Default.aspx page.
Note
If you do not have a Default.aspx page, you can use another page. Alternatively, you can add a new page to the Web sit
e. In Solution Explorer, right-click the name of your Web site, click Add New Item, and then add a Web Form.

2. Switch to Design view.


3. In the Toolbox, from the Data folder, drag an ObjectDataSource control onto the page.
4. In the Properties window, set ID to AuthorsObjectDataSource.
5. Right-click the ObjectDataSource control, and then click the smart tag to display the ObjectDataSource Tasks menu.
6. On the ObjectDataSource Tasks menu, click Configure Data Source.
The Configure Data Source wizard appears.
7. In the Choose your business object list, click PubsClasses.AuthorClass.
8. Click Next.
9. In the Select tab, in the Choose a method list, click GetAuthors(), returns Dataset.
The GetAuthors method is defined in the business class you created previously. It returns a dataset containing the data
from the Authors.xml file.
10. Click Finish.
The configuration information you have entered specifies that to get data from the component, the component's
GetAuthors method should be called.

Note
The name of the method you specify for the SelectMethod property is case-sensitive, even if you are programming in V
isual Basic .NET.

You can now get data from the component by using the ObjectDataSource control. You will display the data in a GridView
control on the page.
To display data from the component
1. In the Toolbox, from the Data folder, drag a GridView control onto the page.
2. Right-click the GridView control, and then click the smart tag if the Common GridView Tasks menu is not showing.
3. On the Common GridView Tasks menu, in the Choose Data Source box, click AuthorsObjectDataSource.
4. Press CTRL+F5 to run the page.
The GridView control with the XML data in it is displayed.
Inserting Data by Using the Business Component
As with other data source controls, such as the SqlDataSource control, the ObjectDataSource control supports updating
(inserting, updating, and deleting). In this section, you will modify the business component with a method that inserts an
author record. Then you will change the page so that users can type new author information and modify the
ObjectDataSource control to perform the insertion.
Note
During this part of the walkthrough, the Authors.xml file you created previously will be updated. It is important that the appli
cation have permission to write to the file at run time or the Web page will display an error when you try to update the file. If
you created the Authors.xml file in the App_Data folder, permissions are set automatically.

To modify the business component to allow inserts


1. Switch to the BusinessObject file.
2. Add the following method as the final member of AuthorClass.
VB
Public Sub InsertAuthor(ByVal au_id As String, _
ByVal au_lname As String, _
ByVal au_fname As String, ByVal au_phone As String)
Dim workRow As DataRow = dsAuthors.Tables(0).NewRow
workRow.BeginEdit()
workRow(0) = au_id
workRow(1) = au_lname
workRow(2) = au_fname
workRow(3) = au_phone
workRow.EndEdit()
dsAuthors.Tables(0).Rows.Add(workRow)
dsAuthors.WriteXml(filePath, Data.XmlWriteMode.WriteSchema)
End Sub

C#
public void InsertAuthor (String au_id, String au_lname,
String au_fname, String au_phone)
{
DataRow workRow = dsAuthors.Tables[0].NewRow ();
workRow.BeginEdit ();
workRow[0] = au_id;
workRow[1] = au_lname;
workRow[2] = au_fname;
workRow[3] = au_phone;
workRow.EndEdit ();
dsAuthors.Tables[0].Rows.Add (workRow);
dsAuthors.WriteXml (filePath, XmlWriteMode.WriteSchema);
}

Note
Pay close attention to the names of the variables used to pass author information into the method (au_id, au_lname, au
_fname, and au_phone). They must match the column names defined in the schema of the XML file you created previous
ly.

The new method takes four values to insert, which you will provide in the page as parameters. The method creates a new
row in the dataset, and then writes the updated dataset out as an XML file.
3. Save the file.
The next step is to change the page so that users can enter new author information. For the following procedure, you will use
the DetailsView control.
To add a control for inserting data
1. Switch to or open the Default.aspx page.
2. Switch to Design view.
3. In the Toolbox, from the Data folder, drag a DetailsView control onto the page.
Note
The exact layout of the page is not important.

4. On the DetailsView Tasks menu, in the Choose Data Source box, click AuthorsObjectDataSource.
Note
If the DetailsView Tasks menu is not visible, click the smart tag.

5. In the Properties window, set AutoGenerateInsertButton to true.


This causes the DetailsView control to render a New button that users can click to put the control into data-entry mode.
Finally, you must configure the ObjectDataSource control to specify what action the control should take to insert data.
To configure the data source control for inserting data
Right-click AuthorsObjectDataSource, click Properties, and then set InsertMethod to InsertAuthor.
This is the name of the method that you added to the business component.
You can now insert new authors into the XML file.
To test insertion
1. Press CTRL+F5 to run the Default.aspx page.
2. In the DetailsView control, click the New button.
The control is redisplayed with text boxes.
3. Enter new author information, and then click Insert.
The new author information is added to the XML file. The GridView control immediately reflects the new record.
Next Steps
This walkthrough illustrates how to work with a data component. You might want to experiment with additional features of
navigation. For example, you might want to:
Add update and delete functionality. To do so, you would add methods to the component. Doing so is similar to adding
the insertion logic — you add a method to the component, configure the data source control to invoke the component
method, add appropriate parameters, and add a line of code to call the Update and Delete methods of the data source
control. For details, see Walkthrough: Editing and Inserting Data in Web Pages with the DetailsView Web Server Control.
Change the business component to work with database data instead of with an XML file. You do not need to make any
changes to the controls on the page.
Restrict which users can make changes to the data. A typical method is to add membership and roles to your Web site,
and then establish rules that the business component can check before allowing changes to data. For details, see
Walkthrough: Creating a Web Site with Membership and User Login (Visual Studio) and
Walkthrough: Managing Web Site Users with Roles.
See Also
Tasks
Walkthrough: Data Binding Web Pages with a Visual Studio Data Component
Walkthrough: Using Shared Code in Web Sites in Visual Web Developer
Walkthrough: Creating a Basic Web Page in Visual Web Developer
Concepts
Data Source Controls Overview
Using Parameters with Data Source Controls
Visual Web Developer

Walkthrough: Creating a Web Page to Display XML Data


Data is often made available to Web applications in XML format. However, XML data is inherently hierarchical, and you might
want to be able to use the XML data in list-based controls, such as the GridView or DropDownList control. This walkthrough
shows you how to work with XML data as if it were in a tabular database table.
During this walkthrough, you will learn how to:
Use a data source control to read XML data and make it available to list controls.
Bind the GridView and DataList controls to XML data.
Create a master-detail page that displays logically related XML data.
Apply a transformation to an .xml file to make the file usable as tabular data.
Note
You can also work with XML in hierarchical form. For details, see
Walkthrough: Displaying Hierarchical Data in a TreeView Control.

Prerequisites
In order to complete this walkthrough, you will need:
Microsoft Visual Web Developer
The .NET Framework
This walkthrough assumes that you know how to use Visual Web Developer.
Creating a Web Site
If you have already created a Web site in Visual Web Developer (for example, by following the steps in
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and skip to the next section.
Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, point to New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, click File System, and then enter the name of the folder where you want to keep your Web site.
For example, type the folder name C:\WebSites\XMLWalkthrough.
5. In the Language list, click the programming language you prefer to work in, such as Visual Basic or Visual C#.
The programming language you choose will be the default for your Web site, but you can set the programming language
for each page individually.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Creating an .xml file for Data
To have XML data to work with, create an .xml file in the Web site.
To create the .xml file
1. In Solution Explorer, right-click the App_Data folder, and then click Add New Item.
Note
When you put the .xml file in the App_Data folder, the .xml file has the correct permissions to allow ASP.NET to read fro
m and write to the file at run time. In addition, keeping files in the App_Data folder protects them from being viewed in
a browser, because the App_Data folder is marked as non-browsable.

2. Under Visual Studio installed templates, click XML file.


3. In the Name box, type Bookstore.xml.
4. Click Add.
A new .xml file is created containing only the XML directive.
5. Copy the following XML data, and then paste it into the file, overwriting what is already in the file.

<?xml version="1.0" standalone="yes"?>


<bookstore>
<book ISBN="10-000000-001"
title="The Iliad and The Odyssey"
price="12.95">
<comments>
<userComment rating="4"
comment="Best translation I've read." />
<userComment rating="2"
comment="I like other versions better." />
</comments>
</book>
<book ISBN="10-000000-999"
title="Anthology of World Literature"
price="24.95">
<comments>
<userComment rating="3"
comment="Needs more modern literature." />
<userComment rating="4"
comment="Excellent overview of world literature." />
</comments>
</book>
<book ISBN="11-000000-002"
title="Computer Dictionary"
price="24.95" >
<comments>
<userComment rating="3"
comment="A valuable resource." />
</comments>
</book>
<book ISBN="11-000000-003"
title="Cooking on a Budget"
price="23.95" >
<comments>
<userComment rating="4"
comment="Delicious!" />
</comments>
</book>
<book ISBN="11-000000-004"
title="Great Works of Art"
price="29.95" >
</book>
</bookstore>
The Bookstore.xml file contains information about books that might be available from an online bookstore. Notice the
following about the .xml file:
The property values for elements are all expressed as attributes.
The file contains a nested structure — each book can contain its property values, as well as one or more comments
as separate elements.
6. Save the Bookstore.xml file, and then close it.
Displaying XML Data in a List Control
To make data available to the controls on an ASP.NET Web page, you use a data source control.
To configure data access to the .xml file
1. Open the Default.aspx file, and then switch to Design view.
2. In the Toolbox, from the Data group, drag an XmlDataSource control onto the page.
3. On the XmlDataSource Tasks menu, click Configure Data Source.
The Configure Data Source <DataSourceName> dialog box appears.
4. In the Data file box, type ~/App_Data/Bookstore.xml.
5. Click OK.
The XmlDataSource control makes the data in the .xml file available to controls that are on the page. The data is available in
two formats: hierarchical and tabular. Controls that bind to the XmlDataSource control can get the data in the format that
works for them.
In this case, the hierarchy of the Bookstore.xml file lends itself to a relational interpretation. The two levels of the file (books and
comments) can be thought of as two related tables.
You can now display the XML data in a list control. To begin, display some of the XML data in a GridView control.
To use a GridView control for basic display of XML data
1. In the Toolbox, from the Data group, drag a GridView control onto the page.
2. On the GridView Tasks menu, in the Choose Data Source list, click XmlDataSource1.
3. Press CTRL+F5 to run the page.
The page displays the XML data in a grid.
The data displayed in the GridView control illustrates the following points about how the XML data is interpreted:
When the XML data is represented as a data record, by default, the columns are created from attributes (such as ISBN).
Child elements are treated as part of a separate related table. For this example, the GridView control does not bind to the
comments elements in the file.
Filtering XML Data Using an XPath Expression
In the first part of this walkthrough, you relied on the default behavior of the XmlDataSource and GridView controls to
extract information from the .xml file. However, the control displays only some of the XML data.
In this part of the walkthrough, you will add a second GridView control and use it to show master-detail information. Users
will be able to select an individual book in the first GridView control, and the second GridView control will display the related
user comments, if any, for that book. To display comments, you will use an XPath expression, which allows you to specify which
level of the XML data file you want to extract. Because you want to display comments for a specific book only, you will create
the XPath expression dynamically, depending on which book the user has selected.
To begin, you will add a second GridView control to the page, and then configure the GridView control so that it will display
user comments.
To add a GridView control to display user comments
1. Switch to Design view.
2. In the Toolbox, from the Data group, drag a GridView control onto the page and place it below the first GridView
control.
The GridView Tasks menu appears.
3. In the Choose Data Source box, click New data source.
The Data Source Configuration Wizard appears.
4. Click XML File as the data source.
5. In the Specify an ID for the data source box, leave the default, XmlDataSource2.
6. Click OK.
The Configure Data Source dialog box appears.
7. In the Data file box, type ~/App_Data/Bookstore.xml.
You will use the same .xml file that you used previously in this walkthrough, but you will extract different information
from it for the second GridView control.
8. In the XPath Expression box, type the following expression:
/bookstore/book/comments/userComment
Later, you will change the XPath property dynamically in code. However, by defining an XPath expression for the data
source now, you will help the tools in Visual Web Designer determine what information will ultimately be displayed in
the control.
9. Click OK.
The second GridView control appears, showing ratings and user comments as sample data.
10. Select the GridView2 control, and in Properties, set Visible to False.
The second GridView control will appear only when the user has selected a book in the first GridView control.
You can now configure the first GridView control to allow users to select a book. You will also add code that creates an XPath
expression based on the user's selection and assigns it to the XmlDataSource2 control. The end result is that the second
GridView control will display the user comments for the selected book.
To configure the GridView control for selection
1. Switch to Design view, and then select the first GridView control.
2. On the GridView Tasks menu, select Enable Selection.
A new column is added to the GridView control containing a link button with the text Select.
3. In Properties, set DataKeyNames to ISBN.
You can click the property box to select the value.
This configures the GridView control to treat the ISBN property as the primary key for each element in the XML data.
4. Click the GridView control. In the Properties window, select Events from the drop-down list at the top of the
Properties window. This will display all events associated with the control.
5. Double-click the box for the SelectedIndexChanged event.
This switches you to the code editor and creates a skeleton handler for the SelectedIndexChanged event.
6. Add the following highlighted code to the handler.
VB
Protected Sub GridView1_SelectedIndexChanged(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles GridView1.SelectedIndexChanged
Dim currentIndex As Integer
currentIndex = GridView1.SelectedIndex
Dim isbn As String
isbn = CStr(GridView1.DataKeys(currentIndex).Value)
XmlDataSource2.XPath = _
String.Format( _
"/bookstore/book[@ISBN='{0}']/comments/userComment", _
isbn)
GridView2.Visible = true
End Sub

C#
protected void GridView1_SelectedIndexChanged(Object sender, EventArgs e)
{
String isbn = (String)
GridView1.DataKeys[GridView1.SelectedIndex].Value;
XmlDataSource2.XPath =
String.Format(
"/bookstore/book[@ISBN='{0}']/comments/userComment",
isbn);
GridView2.Visible = true;
}

The code does the following:


It uses the SelectedIndex property (of the GridView control) to index into the array of data keys, and then return
the primary key of the selected row. Previously, you set the DataKeyNames property to contain ISBN numbers.
It creates a new XPath expression that includes the selected ISBN.
It assigns the new XPath expression to the XPath property (of the XmlDataSource2 control). Assigning a new XPath
expression to the XPath property causes the XmlDataSource control to re-evaluate the data it returns. The
GridView control, in turn, rebinds to the data.
It sets the Visible property to true, which causes the second GridView control to be displayed. You declaratively
set the visibility to false when you created the second GridView control so that it does not appear until the user
selects a book.
You can now test the page.
To test filtering with the XPath expression
1. View the Default.aspx page and press CTRL+F5 to run the page.
The page is displayed with a grid of information about books.
2. Click the Select link next to the first book.
The comments about that book are displayed in a second grid.
3. Click the Select link next to the last book.
No comments are displayed, because there are none for this book.
Displaying XML Data with a Custom Layout
To create a custom layout for data, you can use a DataList control. In the DataList control, you can define one or more
templates. Each template contains a combination of static text and controls that you can arrange in any layout you want.
In this part of the walkthrough, you will use a DataList control to display the same information that you previously displayed
using the GridView2 control. However, you will be able to create a custom layout for the user comments.
To display XML data with a custom layout
1. Switch to Design view, click the GridView2 control, and then press DELETE to remove it from the page.
2. In the Toolbox, from the Data group, drag a DataList control onto the page.
3. On the DataList Tasks menu, in the Choose Data Source list, click XmlDataSource2.
You will use the same data source for the DataList control that you used for the GridView2 control.
4. In Properties, set Visible to false.
5. If the smart tag does not appear, right-click the DataList control and then click Show Smart Tag.
6. On the DataList Tasks menu, click Edit Templates, and then in the Display box, click Item Template.
The DataList control appears with an editable region for the item template. The template contains a default layout that
consists of static text and Label controls that are bound to the Rating and Comment columns in the data record. (The
DataList control is able to infer the structure of the data that it will display because you defined a static XPath expression
for the XmlDataSource2 control earlier in this walkthrough.)
7. In the editable region, change the first caption to User rating:.
8. Change the caption comment to Comment:.
9. Right-click the title bar of the DataList control, point to Edit Template, and then click Separator Template.
Another editable region is displayed in the DataList control, this one for defining the layout of the elements that will
appear between each data record.
10. In the Toolbox, from the HTML group, drag a Horizontal Rule control onto the editable region.
11. Right-click the DataList control, and then click End Template Editing.
12. Right-click the page, and then click View Code to switch to the code for the page.
13. In the GridView1_SelectedIndexChanged handler, change the following line:
VB
GridView2.Visible = True

C#
GridView2.Visible = true;

to the following:
VB
DataList1.Visible = True

C#
DataList1.Visible = true;

You can now test the custom layout.


To test the custom layout
1. View the Default.aspx page and press CTRL+F5 to run the page.
The page is displayed with a grid of information about books.
2. Click the Select link next to the first book.
The comments about the first book are displayed in a list.
3. Click the Select link next to the last book.
No comments are displayed, because there are none for this book.
Using Transformations to Restructure XML Data
The .xml file that you have used in this walkthrough is structured so that the properties of each element are expressed as
attributes. In many cases, .xml files that you work with are structured differently. For example, values in an .xml file are often
created as elements with inner text.
If you have an .xml file in which property values are expressed in a format other than attributes, you can create a
transformation file (.xslt) that can dynamically reformat the .xml file so that it is compatible with the XmlDataSource control.
In this part of the walkthrough, you will work with an .xml file that contains the same data as the Bookstore.xml file that you
used previously. However, the data will be structured differently than it was in the Bookstore.xml file, so you will use a
transformation to dynamically reformat it.
To begin this section, you will create a second .xml file.
To create the second .xml file
1. In Solution Explorer, right-click the App_Data folder, and then click Add New Item.
2. Under Visual Studio installed templates, click XML file.
3. In the Name box, type Bookstore2.xml.
4. Click Add.
A new .xml file is created containing only the XML directive.
5. Copy the following XML data, and then paste it into the file, overwriting what is already in the file.

<?xml version="1.0" standalone="yes"?>


<bookstore>
<book ISBN="10-000000-001">
<title>The Iliad and The Odyssey</title>
<price>12.95</price>
<comments>
<userComment rating="4">
Best translation I've read.
</userComment>
<userComment rating="2">
I like other versions better.
</userComment>
</comments>
</book>
<book ISBN="10-000000-999">
<title>Anthology of World Literature</title>
<price>24.95</price>
<comments>
<userComment rating="3">
Needs more modern literature.
</userComment>
<userComment rating="4">
Excellent overview of world literature.
</userComment>
</comments>
</book>
<book ISBN="11-000000-002">
<title>Computer Dictionary</title>
<price>24.95</price>
<comments>
<userComment rating="3">
A valuable resource.
</userComment>
</comments>
</book>
<book ISBN="11-000000-003">
<title>Cooking on a Budget</title>
<price>23.95</price>
<comments>
<userComment rating="4">Delicious!</userComment>
</comments>
</book>
<book ISBN="11-000000-004">
<title>Great Works of Art</title>
<price>29.95</price>
</book>
</bookstore>

6. Save the Bookstore2.xml file, and then close it.


You now need a transformation file that will convert the data in the Bookstore2.xml file into the attribute-based format that is
used by the XmlDataSource control.
To create the transformation file
1. In Solution Explorer, right-click the App_Data folder, and then click Add New Item.
2. Under Visual Studio installed templates, click Text File.
There is no template for a transform file, so you can create it as a text file with the correct extension.
3. In the Name box, type Bookstore2.xsl.
Note
Be sure to use the .xsl extension.

4. Click Add.
A new blank file is created.
5. Copy the following transformation code, and then paste it into the file.

<?xml version="1.0"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
>
<xsl:strip-space elements="*"/>
<xsl:output method="xml"
omit-xml-declaration="yes"
indent="yes"
standalone="yes" />

<xsl:template match="/">
<xsl:for-each select="bookstore">
<xsl:element name="bookstore">
<xsl:for-each select="book">
<xsl:element name="book">
<xsl:attribute name="ISBN">
<xsl:value-of select="@ISBN"/>
</xsl:attribute>
<xsl:attribute name="title">
<xsl:value-of select="title"/>
</xsl:attribute>
<xsl:attribute name="price">
<xsl:value-of select="price"/>
</xsl:attribute>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

6. Save the Bookstore2.xsl file, and then close it.


From this point, working with the XML data is very similar to what you did earlier in this walkthrough, except that you can
specify the transformation file when you configure the XmlDataSource control. For the last part of this walkthrough, you will
create a new page, and then repeat some of the steps from the first part of this walkthrough. However, this time you will show
the data from the Bookstore2.xml file.
To configure data access to the .xml file
1. In Solution Explorer, right-click the name of your Web site, and then click Add New Item.
2. Under Visual Studio installed templates, click Web Form.
3. In the Name box, type Bookstore2.aspx.
4. Click Add.
5. Switch to Design view.
6. In the Toolbox, from the Data group, drag an XmlDataSource control onto the page.
7. On the XmlDataSource Tasks menu, click Configure Data Source.
The Configure Data Source dialog box appears.
8. In the Data file box, type ~/App_Data/Bookstore2.xml.
9. In the Transform file box, type ~/App_Data/Bookstore2.xsl.
10. Click OK.
11. In the Toolbox, from the Data group, drag a GridView control onto the page.
12. On the GridView Tasks menu, in the Choose Data Source list, click XmlDataSource1.
13. Press CTRL+F5 to run the page.
The page displays the XML data in a grid. The data will appear in the grid the same as it did in the first page, even though
the format of the underlying .xml file is different this time.
Next Steps
This walkthrough has illustrated only the basics of how to work with an XML document and transformations. In a real
application, you will often need to work with the XML document in more depth. The following are suggestions for further
investigation:
Creating more sophisticated transformations. In this walkthrough, you have seen only one example of how you can use
transformations. XSL is a powerful language, with sophisticated support not just for creating HTML pages, but also for
virtually any kind of transformation from XML to another structure.
Writing XML documents (instead of simply reading them). The Xml control makes it easy to display the contents of an
XML file in an ASP.NET Web page. However, you might want to create or amend XML files yourself. For details, see
XML Documents and Data. For an example of writing to an XML file, see
Walkthrough: Displaying and Tracking Advertisements with the AdRotator Control.
See Also
Tasks
Walkthrough: Displaying Hierarchical Data in a TreeView Control
Walkthrough: Creating a Basic Web Page in Visual Web Developer
Visual Web Developer

Walkthrough: Displaying Hierarchical Data in a TreeView


Control
The ASP.NET TreeView control is designed to present users with data in a hierarchical structure. Users can open individual
nodes that can in turn contain child nodes. The TreeView control is suitable for displaying XML data, but can be used for any
data that can be represented in a hierarchy. This walkthrough shows you the basics of using the TreeView control and various
ways to display hierarchical data.
Tasks illustrated in this walkthrough include:
Using the TreeView control to display XML data.
Customizing the display of the TreeView control.
Displaying records from related database tables in the TreeView control.
Prerequisites
In order to complete this walkthrough, you will need:
Microsoft Visual Web Developer (Visual Studio).
Microsoft Data Access Components (MDAC) version 2.7 or later.
If you are using Microsoft Windows XP or Windows Server 2003, you already have MDAC 2.7. However, if you are using
Microsoft Windows 2000, you might need to upgrade the MDAC already installed on your computer. For more
information, see "Microsoft Data Access Components (MDAC) Installation" in the MSDN Library.
Access to the SQL Server Northwind database. For information about downloading and installing the SQL Server sample
Northwind database, see Installing Sample Databases on the Microsoft SQL Server Web site.
Note
If you need information about how to log on to the computer running SQL Server, contact the server administrator.

A user name and password for a SQL Server account that has access to the Northwind database, if the SQL Server
database is not on the same computer as the Web server.
Creating the Web Site
Create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New, and then click Web Site. If you are using Visual Web Developer Express, on the File menu,
click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, select File System, and enter the name of the folder where you want to keep the pages of your Web
site.
For example, type the folder name C:\WebSites\HierarchicalData.
5. In the Language list, click the programming language you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Creating an XML File for Data
Create a new XML file by following these steps.
To create the XML file
1. In Solution Explorer, right-click the Web site, and then click Add New Item.
2. In the Add New Item dialog box, under Standard Templates, click XML File.
3. In the Name box, type Bookstore.xml, and then click Add.
Visual Web Developer creates the new Bookstore.xml file and opens the code editor.
4. Copy the following XML data, and then paste it into the Bookstore.xml file, overwriting what is already in the file.

<?xml version="1.0" standalone="yes"?>


<bookstore>
<genre name="fiction">
<book ISBN="10-000000-001">
<title>The Iliad and The Odyssey</title>
<price>12.95</price>
<comments>
<userComment rating="4">
Best translation I've read.
</userComment>
<userComment rating="2">
I like other versions better.
</userComment>
</comments>
</book>
<book ISBN="10-000000-999">
<title>Anthology of World Literature</title>
<price>24.95</price>
<comments>
<userComment rating="3">
Needs more modern literature.
</userComment>
<userComment rating="4">
Excellent overview of world literature.
</userComment>
</comments>
</book>
</genre>
<genre name="nonfiction">
<book ISBN="11-000000-002">
<title>Computer Dictionary</title>
<price>24.95</price>
<comments>
<userComment rating="3">A valuable resource.</userComment>
</comments>
</book>
<book ISBN="11-000000-003">
<title>Cooking on a Budget</title>
<price>23.95</price>
<comments>
<userComment rating="4">Delicious!</userComment>
</comments>
</book>
</genre>
</bookstore>

The XML file contains information about books that might be available from an online bookstore.
5. Save the Bookstore.xml file, and then close it.
Displaying XML Data in the TreeView Control
In this section, you will use the TreeView control to display the XML data. To begin, you can display the XML information
without any special configuration.
To display the XML data
1. Open the Default.aspx page, and then switch to Design view.
2. In the Toolbox, from the Navigation group, drag a TreeView control onto the page.
3. Right-click the TreeView control, and then click Show Smart Tag.
4. On the TreeView Tasks menu, in the Choose Data Source drop-down list, select New Data Source. The Data Source
Configuration Wizard appears.
5. In the Where will the application get data from? window, select XML File. Leave the default ID for the data source.
Click OK.
6. In the Configure Data Source dialog box, in the Data file box, enter ~/Bookstore.xml, and then click OK.
You can now test the page.
To test the page
1. Press CTRL+F5 to run the page.
2. Collapse, and then expand, the nodes in the control.
By default, the nodes display only the tag names of the elements in the Bookstore.xml file.
You can customize the information displayed in the TreeView control by creating custom bindings, which allow you to specify
what information from the XML file to display for each node.
To create custom bindings
1. On the Default.aspx page, right-click the TreeView control, and then click Show Smart Tag.
2. On the TreeView Tasks menu, click Edit TreeNode Databindings.
The TreeView DataBindings Editor dialog box appears.
3. Clear the Auto generate data bindings check box, because you will define the data bindings.
4. Click Add to create a new binding, and then, under Data binding properties, set DataMember to bookstore and set
Text to Book Information.
You are configuring the binding to display a static value, because the Bookstore node is the top-most node in the .xml
file and appears only once in the TreeView control.
5. Click Add to create a second binding, and then, under Data binding properties, set DataMember to genre and
TextField to name.
This specifies that the node will read the <genre> element in the .xml file and assign its name attribute to the TextField
property.
6. Click Add to create a third binding for books, and then, under DataBinding Properties, set DataMember to book and
TextField to ISBN.
7. Click OK.
You can now test the page.
To test the page
Press CTRL+F5 to run the page.
This time, the TreeView control displays the three levels corresponding to the bindings that you have defined. The three
levels are the root node, labeled Book Information, the genre groups, and the ISBN details.
You can create a data binding for any element in an XML file, but you can bind only to the attributes of the element, the inner
text, the name of the element, or the value of the element. You cannot bind to any of the nested elements. To display values in
the nested elements, you create separate bindings to those elements. An alternative method is to transform the XML file using
XSLT, so that the inner elements are converted to attributes. For more information and an example, see the
System.Web.UI.WebControls.XmlDataSource.TransformFile property.
Displaying Relational Data in the TreeView Control
The TreeView control can display any type of hierarchical data, even if the data hierarchy is logical, as in a database, and not
physical, as in an XML file. In this section, you will use the TreeView control to display data from related tables in the
Northwind database.
To start, you will create a connection to the computer running SQL Server where you have the Northwind database.
To create a connection to SQL Server
1. In Server Explorer, right-click Data Connections, and then click Add Connection. If you are using Visual Web
Developer Express, use Database Explorer.
The Add Connection dialog box appears.
If the Data source list does not display Microsoft SQL Server (SqlClient), click Change, and in the Change Data
Source dialog box, select Microsoft SQL Server.
If the Choose Data Source page appears, in the Data source list, select the type of data source you will use. For
this walkthrough, the data source type is Microsoft SQL Server. In the Data provider list, click .NET Framework
Data Provider for SQL Server, and then click Continue.
Note
If the Server Explorer tab is not visible in Visual Web Developer, in the View menu, click Server Explorer. If the Databa
se Explorer tab is not visible, in the View menu, click Database Explorer.

2. In the Add Connection box, enter your server name in the Server Name box.
3. For the Log on to the server section, select the option that is appropriate to access the running the SQL Server database
(integrated security or specific ID and password) and, if required, enter a user name and password.
4. Select the Save my Password check box.
Note
In production applications, do not use Save my Password because this embeds the user name and password in the ap
plication files.

5. Under Select or enter a database name, enter Northwind.


6. Click Test Connection, and when you are sure that it works, click OK.
Your new connection has been created under Data Connections in Server Explorer (or Database Explorer).
Configuring a TreeView Control to Display Database Data
In this section, you will dynamically populate nodes with data. The first-level nodes will represent master data — in this case,
categories. When users click a node, the child nodes for the category will be created by making a query to the database that
retrieves the products for that category. To retrieve the data, you can use a data source control. However, in this walkthrough,
you will create and execute a query programmatically.
To begin, create a new page and a new TreeView control.
To create the new page and TreeView control
1. Add an ASP.NET Web page (Web Form page) named TreeViewDynamic.aspx to your Web site.
2. Open the TreeViewDynamic.aspx page, switch to Design view, and then in the Toolbox, from the Standard group, drag a
Label control onto the page and name it labelStatus.
The labelStatus control is used for error reporting only.
3. In the Toolbox, from the Navigation group, drag a TreeView control onto the page.
4. Right-click the TreeView control, click Properties, and then set MaxDataBindDepth to 2.
5. Right-click the TreeView control, click Show Smart Tasks, and then on the TreeView Tasks menu, click Edit Nodes.
6. In the TreeView Node Editor dialog box, click the icon labeled Add a root node, and then, under Properties, set Text
to Product List and PopulateOnDemand to true.
7. Click OK.
You are creating the topmost node of the tree, which contains only static text.
To configure the Web.config file
1. In the Toolbox, from the Data group, drag a SqlDataSource control onto the page.
2. Select the SqlDataSource control, and then click Show Smart Tag.
3. On the SqlDataSource Tasks menu, click Configure Data Source.
The Configure Data Source - SqlDataSource1 wizard displays a page in which you can choose a connection.
4. In the Which data connection should your application use to connect to the database? box, enter the connection
that you created in "To create a connection to SQL Server," and then click Next.
The wizard displays a page in which you can choose to store the connection string in a configuration file. Storing the
connection string in the configuration file has two advantages:
It is more secure than storing it in the page.
You can use the same connection string in multiple pages.
5. Select the Yes, save this connection as check box, and then click Next.
The wizard displays a page in which you can specify what data you want to retrieve from the database.
6. Under Specify columns from a table or view, in the Name box, click Categories.
7. Under Columns, select the CategoryID and CategoryName boxes.
8. Click Next.
9. Click Finish.
You will use the connection string created in the Web.config file later, in the RunQuery method defined later in this
walkthrough. You will not use the SqlDataSource control.
Now, you will add code to populate the control's child nodes when users click the node. To add nodes dynamically, you create
an event handler for the TreeNodePopulate event.
To create the event handler
1. Right-click the TreeView control, and then in Properties, click the Events icon.
2. Double-click the box for the TreeNodePopulate event.
Visual Web Developer switches to Source view.
3. Add the following highlighted code to the handler.
VB
Protected Sub TreeView1_TreeNodePopulate(ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.TreeNodeEventArgs) _
Handles TreeView1.TreeNodePopulate
If e.Node.ChildNodes.Count = 0 Then
Select Case e.Node.Depth
Case 0
PopulateCategories(e.Node)
Case 1
PopulateProducts(e.Node)
End Select
End If
End Sub

C#
protected void TreeView1_TreeNodePopulate(
object sender, TreeNodeEventArgs e)
{
if (e.Node.ChildNodes.Count == 0)
{
switch (e.Node.Depth)
{
case 0:
PopulateCategories(e.Node);
break;
case 1:
PopulateProducts(e.Node);
break;
}
}
}

This code is called when a user clicks a node to open it. Because you want to display different data at different levels of
the tree, you must determine which node depth the user has clicked, and then populate the nodes at that level
appropriately. In this walkthrough, the PopulateCategories method is called if the user clicks the root node (depth 0).
The PopulateProducts method is called if the user clicks a category name (depth 1). The methods are shown in the next
section.
The TreeNodeEventArgs object provides programmatic access to the current node. To populate the node, you add
elements to it. In the example code, the node is passed to the method that will add the child nodes.
Reading Node Data from the Database
The information to display in each node comes from the database. You must write the code that performs the database query,
reads the records, and creates a node for each record. This walkthrough assumes that you are working with the SQL Server
Northwind sample database, so you must use ADO.NET objects from the System.Data.SqlClient namespace.
For the first level of nodes (level 0), you will display a list of all available categories. The code you create calls a RunQuery
method that you will create later in the walkthrough.
To add nodes for all categories
1. Switch to Source view.
2. If you are working with a single-file page, add the following directives to the top of the code page.

<%@ Import Namespace="System.Data" %>


<%@ Import Namespace="System.Data.SqlClient" %>

Importing the namespaces will make it easier to write the code you need.
3. If you are working with a code-behind page, switch to the code-behind page (TreeViewDynamic.aspx.vb or
TreeViewDynamic.aspx.cs) and add the following lines to the top of the code file, outside the class declaration.
VB
Imports System.Data
Imports System.Data.SqlClient

C#
using System.Data;
using System.Data.SqlClient;

4. Make sure the page is still in Source view.


5. Add the following method to the page code.
VB
Sub PopulateCategories(ByVal node As TreeNode)
Dim sqlQuery As New SqlCommand( _
"Select CategoryName, CategoryID From Categories")
Dim ResultSet As DataSet
ResultSet = RunQuery(sqlQuery)
If ResultSet.Tables.Count > 0 Then
Dim row As DataRow
For Each row In ResultSet.Tables(0).Rows
Dim NewNode As TreeNode = New _
TreeNode(row("CategoryName").ToString(), _
row("CategoryID").ToString())
NewNode.PopulateOnDemand = True
NewNode.SelectAction = TreeNodeSelectAction.Expand
node.ChildNodes.Add(NewNode)
Next
End If
End Sub

C#
void PopulateCategories(TreeNode node)
{
SqlCommand sqlQuery = new SqlCommand(
"Select CategoryName, CategoryID From Categories");
DataSet resultSet;
resultSet = RunQuery(sqlQuery);
if (resultSet.Tables.Count > 0)
{
foreach (DataRow row in resultSet.Tables[0].Rows)
{
TreeNode NewNode = new
TreeNode(row["CategoryName"].ToString(),
row["CategoryID"].ToString());
NewNode.PopulateOnDemand = true;
NewNode.SelectAction = TreeNodeSelectAction.Expand;
node.ChildNodes.Add(NewNode);
}
}
}

The code creates a SqlCommand object that encapsulates the text of the query. It passes the object to a method (which
you will write) that performs the database query and returns a DataSet object. The code then loops through the records
in the DataSet object and creates a new node for each record, setting the text and value of the node with database
information. Then, the code sets the PopulateOnDemand property of each node to true so that the node will raise its
TreeNodePopulate event when clicked. The SelectAction property is set so that the nodes are expanded by default.
The second level of nodes will display the products for each category. For this reason, populating the products nodes requires a
parameterized query so that you can retrieve the products for the current category and populate the child nodes appropriately.
To add nodes for products
Add the following method to the page code.
VB
Sub PopulateProducts(ByVal node As TreeNode)
Dim sqlQuery As New SqlCommand
sqlQuery.CommandText = "Select ProductName From Products " & _
" Where CategoryID = @categoryid"
sqlQuery.Parameters.Add("@categoryid", SqlDbType.Int).Value = _
node.Value
Dim ResultSet As DataSet = RunQuery(sqlQuery)
If ResultSet.Tables.Count > 0 Then
Dim row As DataRow
For Each row In ResultSet.Tables(0).Rows
Dim NewNode As TreeNode = New _
TreeNode(row("ProductName").ToString())
NewNode.PopulateOnDemand = False
NewNode.SelectAction = TreeNodeSelectAction.None
node.ChildNodes.Add(NewNode)
Next
End If
End Sub

C#
void PopulateProducts(TreeNode node)
{
SqlCommand sqlQuery = new SqlCommand();
sqlQuery.CommandText = "Select ProductName From Products " +
" Where CategoryID = @categoryid";
sqlQuery.Parameters.Add("@categoryid", SqlDbType.Int).Value =
node.Value;
DataSet ResultSet = RunQuery(sqlQuery);
if (ResultSet.Tables.Count > 0)
{
foreach (DataRow row in ResultSet.Tables[0].Rows)
{
TreeNode NewNode = new
TreeNode(row["ProductName"].ToString());
NewNode.PopulateOnDemand = false;
NewNode.SelectAction = TreeNodeSelectAction.None;
node.ChildNodes.Add(NewNode);
}
}
}

This code is similar to the code used to populate the categories node. One difference is that the SqlCommand object is
configured with a parameter that is set at run time with the value of the node that the user clicked; that is, of the selected
category. Another difference is that the PopulateOnDemand property is set to false. This causes the products nodes to
be displayed without an expansion button, which is necessary because there are no more nodes below products.
The final step is to create the method that performs the query and returns the dataset.
To perform the query
Add the following subroutine to the page.
VB
Function RunQuery(ByVal sqlQuery As SqlCommand) As DataSet
Dim connectionString As String
connectionString = _
ConfigurationManager.ConnectionStrings _
("NorthwindConnectionString").ConnectionString
Dim dbConnection As New SqlConnection
dbConnection.ConnectionString = connectionString
Dim dbAdapter As New SqlDataAdapter
dbAdapter.SelectCommand = sqlQuery
sqlQuery.Connection = dbConnection
Dim resultsDataSet As DataSet = New DataSet
Try
dbAdapter.Fill(resultsDataSet)
Catch ex As Exception
labelStatus.Text = "Unable to connect to SQL Server."
End Try
Return resultsDataSet
End Function

C#
private DataSet RunQuery(SqlCommand sqlQuery)
{
string connectionString =
ConfigurationManager.ConnectionStrings
["NorthwindConnectionString"].ConnectionString;
SqlConnection DBConnection =
new SqlConnection(connectionString);
SqlDataAdapter dbAdapter = new SqlDataAdapter();
dbAdapter.SelectCommand = sqlQuery;
sqlQuery.Connection = DBConnection;
DataSet resultsDataSet = new DataSet();
try
{
dbAdapter.Fill(resultsDataSet);
}
catch
{
labelStatus.Text = "Unable to connect to SQL Server.";
}
return resultsDataSet;
}

This code creates a data adapter based on the SqlCommand object passed to it. Then, it creates and populates a dataset
with the adapter.
You can now test the page.
To test the page
1. Press CTRL+F5 to run the page.
The TreeView control is displayed with a list of categories and products.
2. Click a category to confirm that it collapses and expands to show a list of products for each category.
Next Steps
This walkthrough used both hierarchical XML data and a relational database to populate a TreeView control. You can use the
TreeView control to work with site navigation information and XML data as tabular (list) data.
For details on site navigation, see Walkthrough: Adding Site Navigation to a Web Site.
For details on working more with XML data, see Walkthrough: Creating a Web Page to Display XML Data.
See Also
Tasks
Walkthrough: Creating a Web Page to Display XML Data
How to: Secure Connection Strings When Using Data Source Controls
Visual Web Developer

Walkthrough: Using Output Caching to Enhance Web Site


Performance
Performance is a critical aspect of any Web application. Decreasing the amount of processing a Web server must do to comply
with individual requests results in quicker response times, the server's ability to handle more concurrent requests, and a
reduced load on intermediate and back-end data systems.
One way to achieve better performance with ASP.NET is by using output caching to reduce server workload. Output caching is
an optimization that reduces Web server response time.
Normally, when a browser requests an ASP.NET page, ASP.NET creates an instance of the page, runs any code in the page, runs
database queries (if any), dynamically assembles the page, and then sends the resulting output to the browser. Output caching
allows ASP.NET to send a pre-processed copy of a page rather than go through this process for each request. This difference
cuts down the amount of processing the Web server does, which increases performance and enables greater scalability.
Tasks illustrated in this walkthrough include:
Caching pages, using either a page directive to have the entire page output cached, regardless of browser type, individual
parameters, or data.
Using application-level cache profiles, a feature that enables you to define output caching settings for an entire
application. Individual pages can associate themselves with profiles contained in your Web.config file. This enables you to
control caching centrally instead of editing each page.
Caching based on individual parameters sent with the page.
Prerequisites
In order to complete this walkthrough, you will need:
Visual Web Developer (Visual Studio).
Microsoft .NET Framework version 2.0.
Creating the Web Site
If you have already created a Web site in Visual Web Developer (see
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and go to the next topic in this
walkthrough. Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site. (In Visual Web Developer Express Edition, on the File menu, click New, and then
click Web Site.)
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, select ASP.NET Web Site.
4. In the Location box, type the name of the folder where you want to keep the pages of your Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, select the programming language that you prefer to work in.
6. Click OK.
7. Visual Web Developer creates the folder and a new page named Default.aspx.
Configuring Page-Level Caching
This procedure introduces you to basic page caching. In this procedure, you will add a Label control to your page that displays
the time when the page was created, and then configure the page to be cached. By displaying the page's creation time you can
see that the page request is fulfilled from the cache.
To configure page-level caching
1. Open or switch to the Default.aspx page. (Alternatively, you can use any other page in your Web site.)
2. Switch to Design view.
3. From the Standard group in the toolbox, drag a Label control to your page, leaving the default name of Label1.
4. Double-click a blank are of the page.
The designer switches to the code editor and creates a Page_Load method.
5. Add the following highlighted code to the method:
VB
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs)
Label1.Text = System.DateTime.Now.ToString()
End Sub

C#
protected void Page_Load(Object sender, System.EventArgs e)
{
Label1.Text = System.DateTime.Now.ToString();
}

6. Press CTRL+F5 to run the page.


When the page appears in the browser, you will see the current date and time. Press your browser's refresh button and
notice that the timestamp changes each time.
7. Close the browser.
8. Add the following @ OutputCache directive to the top of the page:

<%@ OutputCache Duration="15" VaryByParam="none" %>

This directive configures the page to be cached. The Duration attribute specifies that the page will remain in the cache
for 15 seconds.
9. Press CTRL+F5 to run the page again.
10. Refresh the page several times.
Notice that the time display is updated only every 15 seconds, regardless of how many times you refresh the browser.
This is because the request is fulfilled from the cache until the duration time has elapsed, at which point the page code is
executed again.
Setting Application-Level Caching
In the preceding procedure, you configured caching for an individual page. In some circumstances you might want to configure
caching for all pages in your Web site. You might also want to establish different caching rules (profiles) and apply the cache
profiles to sets of individual pages. Setting application-level caching enables you to change cache behavior from a single
configuration file rather than editing the @ OutputCache directive of individual pages. In the following procedure, you will set
up a simple cache profile and use it for the page that you were just working with.
To configure application-level caching
1. If you already have a Web.config file, go to step 4.
2. In Solution Explorer, right-click the name of your Web site, and then click Add New Item.
3. In the Add Item dialog box, click Web Configuration File, and then click Add.
Be sure that you use the name Web.config.
4. Add the following XML as a child of the system.web element:

<!-- caching section group -->


<caching>
<outputCacheSettings>
<outputCacheProfiles>
<add name="AppCache1" enabled="true" duration="60"/>
</outputCacheProfiles>
</outputCacheSettings>
</caching>

5. Save the file and then close it.


6. Open or switch to the Web page you were working with, and then switch to Source view.
7. Change the @ OutputCache directive to read as follows:

<%@ OutputCache CacheProfile="AppCache1" VaryByParam="none" %>

8. Press CTRL+F5 to run the page.


9. Refresh the page a number of times.
This time the date will remain the same for the duration specified in the cache profile, which is 60 seconds.
Caching Using Parameters
The @ OutputCache directive requires you to set the VaryByParam attribute, which until you now you have set to "none".
The VaryByParam attribute enables you to configure caching so that ASP.NET stores different versions of a page depending
on parameters such as query strings, form post values, request headers, and so on.
For example, you can use cache parameters in a page that displays weather conditions for select cities, where the weather data
is refreshed only every three hours. In this scenario, you want to cache a separate version of the page for each city. You can do
so by setting the cache parameter to vary by a query string parameter.
In the following procedure, you will change the Label control you added to your page so that it displays the time with a
colored background. You can change the color by using a TextBox control for entering a color name.
When you submit the page, the color you type is submitted as post data, and the color behind the Label control changes.
When a new color is requested (when the page includes new post data), the page is regenerated and the timestamp is updated.
However, subsequent requests for the same color will result in the cached page being returned (until the duration interval has
been exceeded).
To cache based on parameters
1. Open or switch to the page you have been working on.
2. Switch to Design view.
3. From the Standard group of the toolbox, drag a TextBox control onto the page and set its ID to Color.
4. Drag a Button control onto the page, leaving the default name of Button1.
5. Set the Button control's Text property to "Change Color".
Double-click the Button control to create a Click event handler.
6. Within the method, add the following highlighted code:
VB
Protected Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Label1.BackColor = _
System.Drawing.Color.FromName(Server.HtmlEncode(Color.Text))
End Sub
C#
protected void Button1_Click(Object sender, System.EventArgs e)
{
Label1.BackColor =
System.Drawing.Color.FromName(Server.HtmlEncode(Color.Text));
}

7. Set the defaultbutton attribute of the form element to "Button1".


This causes the Click event handler for the button to be invoked when the ENTER key is pressed.
8. Replace the @ OutputCache directive with the following version:

<%@ OutputCache Location="Server" Duration="60" VaryByParam="Color" %>

9. Press CTRL+F5 to run the page.


10. Type a color name such as "red" or "blue" in the text box, and then click Change Color.
ASP.NET caches a version of the page that uses the color you specify.
11. Refresh the page a number of times.
If you do not type in a new color name, the date and time will not change for at least one minute, as specified by the
Duration attribute in your @ OutputCache directive.
12. Enter a new color, such as "green" or "orchid" and then submit the page.
This time you will see the time update along with the new color.
Next Steps
This walkthrough has illustrated basic concepts of caching ASP.NET pages. You might also want to explore these additional
caching techniques:
Instead of using page declarations, specify caching programmatically. For example, in your Page_Load method you could
access the HttpCachePolicy class (through Page.Response.Cache), and set values and behavior accordingly.
Cache data-bound pages so that they are regenerated only when the data they are dependent on has changed. For
details, see Walkthrough: Using ASP.NET Output Caching with SQL Server.
See Also
Tasks
Walkthrough: Using ASP.NET Output Caching with SQL Server
Reference
@ OutputCache
HttpCachePolicy
VaryByParams
Concepts
ASP.NET Caching Overview
Visual Web Developer

Walkthrough: Using ASP.NET Output Caching with SQL Server


This walkthrough shows how to cache ASP.NET pages that depend on data in a SQL Server database.
An advanced feature of ASP.NET output caching is SQL cache dependency. SQL cache dependency enables you to cache pages
that are dependent on data from SQL Server tables. You can configure SQL Server and ASP.NET to cache page requests,
reducing server workload, until the data on which the page depends has been updated in SQL Server. SQL cache dependency
is useful for data such as product catalogs or customer registration information that remains comparatively static.
Tasks illustrated in this walkthrough include:
Creating and configuring a page to display data from the Northwind database.
Enabling a database for SQL cache notification.
Specifying the SQL cache dependency on your page and in your Web.config file.
Making changes to the Northwind database and viewing the caching behavior.
Prerequisites
In order to complete this walkthrough, you will need:
Access to SQL Server 2000 or SQL Server 2005 with the Northwind database.
Access to the SQL Server Northwind database. For information about downloading and installing the SQL Server sample
Northwind database, see Installing Sample Databases on the Microsoft SQL Server Web site.
Note
If you need information about how to log on to the computer running SQL Server, contact the server administrator.

Microsoft Data Access Components (MDAC) version 2.7 or later.


If you are using Windows XP or Windows Server 2003, you already have MDAC 2.7. However, if you are using Windows
2000, you might to need to upgrade the MDAC already installed on your computer. For more information, see the MSDN
article MDAC Installation.
The .NET Framework version 2.0.
Creating the Web Site
If you have already created a Web site in Visual Web Developer (see
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and go to "Enabling Cache
Notification for SQL Server" later in this walkthrough. Otherwise, create a new Web site and page using the following
procedure.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site. (In Visual Web Developer Express Edition, on the File menu click New, and then
click Web Site.)
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, enter the name of the folder where you want to keep the pages of your Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click the programming language you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Enabling Cache Notification for SQL Server
You must configure SQL Server to provide proper notification to ASP.NET regarding changes in dependent data. You will need
administrative privileges to configure the server.
To enable cache notification for SQL Server
1. On the Windows Start menu, point to All Programs, point to Accessories, and then click Command Prompt to open a
command prompt window.
2. Locate the Aspnet_regsql.exe executable file on your disk drive. This file is installed with the .NET Framework version 2.0
in the following location:

%windir%\Microsoft.NET\Framework\FrameworkVersion

Be sure that %windir% represents your Windows directory and that the .NET Framework version is 2.0 or later. The path
might look like the following:

C:\WINDOWS\Microsoft.NET\Framework\v2.0.40217

3. Use the following command to enable cache notification for the Employees table in the Northwind database:

aspnet_regsql.exe -S <Server> -U <Username> -P <Password> -ed -d Northwind -et -t Empl


oyees

Note
You will need administrative privileges or the administrative account and password. If you do not have this information
, contact your database administrator.

A message will appear indicating success or failure in enabling the database. The following message indicates success:

Enabling the table for SQL cache dependency.


..
Finished.

Adding a Data Connection to the Project


To work with the SQL Server database in Visual Web Developer, you need to add a connection to the Northwind database.
To add a data source to the project
1. In Server Explorer (Database Explorer in Visual Web Developer Express Edition), right-click Data Connections, and
then click Add Connection.
Note
Server Explorer (Database Explorer in Visual Web Developer Express Edition) is typically docked behind Solution Ex
plorer.

If Server Explorer (Database Explorer in Visual Web Developer Express Edition) is not visible, in the View menu, click
Server Explorer (Database Explorer in Visual Web Developer Express Edition).
2. If the Choose Data Source dialog box is displayed, do the following:
a. In the Data source list, click Microsoft SQL Server.
b. In the Data provider list, click .NET Framework Data Provider for SQL Server.
c. Click Continue.
3. In the Add Connection dialog box, provide the details (server name, login credentials, and so on) for your database, and
then select the Northwind database.
4. Click OK.
Adding a Time Stamp and Data to the Web Page
You can now create a Web page to demonstrate caching. In this section you will add a time stamp to track page creation times
and a GridView control to view the Employees table of the Northwind database.
To add a time stamp and data to the Web page
1. Switch to or open the Default.aspx page.
2. Switch to Design view.
3. From the Standard group in the Toolbox, drag a Label control onto the page, leaving the default name of Label1.
4. In Server Explorer (Database Explorer in Visual Web Developer Express Edition), expand Data Connections.
5. Expand the node for the data connection you created earlier.
6. Expand the Tables node.
7. Drag the Employees table to your page.
Visual Web Designer creates a GridView control that is configured to use the connection and table you selected.
8. In the GridView Tasks menu, click Configure Data Source.
The default data connection string name NorthwindConnectionString1 appears in the first step of the Configure Data
Source wizard.
9. Click Next.
10. In the Configure Select Statement pane, select Specify columns from a table or view.
11. In the Name list, click Employees.
12. In the Columns list, select the EmployeeID, LastName, and FirstName columns.
13. Click Next.
14. Click Finish.
Visual Web Designer configures the GridView control to display the data you have selected.
Note
If you see a message asking whether you want to refresh the fields and keys for the GridView control, click Yes.

15. Double-click a blank part of the page.


The designer generates a Page_Load method and switches views.
16. Add the following highlighted code to display a time stamp indicating page creation:
VB
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles Me.Load
Label1.Text = System.DateTime.Now
End Sub

C#
protected void Page_Load(Object sender, System.EventArgs e)
{
Label1.Text = System.DateTime.Now.ToString();
}

17. Save the file.


Testing the Page without Caching
Now you can run the page and observe the behavior without caching. The page is loaded and the current server time is
displayed, and then the data is retrieved and placed on the page.
To test the page without caching
1. Press CTRL+F5 to run the page.
2. Refresh the page in the browser
Note that the time stamp changes with each page refresh. The data remains the same.
Configuring the Web Page for Caching
In this part of the walkthrough, you will configure the page for SQL cache dependency based on the Employees table of the
Northwind database.
To configure the Web page for caching
1. Switch to Source view.
2. At the top of the page, add the following directive to indicate the dependency:

<%@ OutputCache Duration="3600" SqlDependency="Northwind:Employees" VaryByParam="none"


%>

The VaryByParam attribute indicates whether ASP.NET should take into consideration page parameters (such as query string
or posted values) when caching. When VaryByParam is set to none, no parameters will be considered; all users are sent the
same page no matter what additional parameters are supplied. Setting VaryByParam to * (an asterisk) means that for each
unique combination of request parameters a unique page will be cached. However, setting VaryByParam to * can cause many
different versions of the page to be cached, so if you know the parameters to vary caching by, it is recommended that you
explicitly specify them in the VaryByParam attribute. For details, see Caching Multiple Versions of a Page.
Setting Caching Configuration in the Web.config File
In addition to the OutputCache declaration on your Web page in the preceding section, you need to specify caching details in
the Web.config file.
To create and update the Web.config file
1. If your Web site already has a Web.config file, go to step 4.
2. In Solution Explorer, right-click the name of your Web site and then click Add New Item.
3. In the Add Item dialog box, click Web Configuration File, and then click Add.
Be sure to use the name Web.config.
4. Add the following XML to the Web.config file as a child of the system.web element:

<!-- caching section group -->


<caching>
<sqlCacheDependency enabled = "true" pollTime = "1000" >
<databases>
<add name="Northwind"
connectionStringName="NorthwindConnectionString1"
pollTime = "1000"
/>
</databases>
</sqlCacheDependency>
</caching>

Note
The connection string name NorthwindConnectionString1 was established earlier when you created the data conne
ction. If your connection string has a different name, substitute that name instead.

Note
The account credentials specified in the connection string must have sufficient privileges to poll the database.

5. Save the file and then close it.


Testing the Page with Caching
With caching enabled, refreshing the page will no longer result in an updated time stamp or a database query, because
ASP.NET will fulfill the page request from the cache.
To test the page with caching
Press CTRL+F5 to run the page.
Note that the time stamp remains the same with each page refresh. The page is being retrieved from the cache.
Changing the Data
Now you can change the data in the database and see that the cache is invalidated and a new page is created.
To change the data
1. In Server Explorer (Data Explorer in Visual Web Developer Express Edition), expand the Data Connections node.
2. Expand the connection you created earlier.
3. Expand the Tables node.
4. Right-click Employees, and then click Show Table Data.
5. Update the database by editing any field in the data table, ensuring it is a field your Web page is displaying.
Alternatively, you can use the SQL pane (if the SQL pane is not visible, in the Query Designer menu, click Pane, and
then click SQL). Enter a SQL command directly and then click the Execute SQL button in the Query Designer toolbar. For
example, run the following command:

UPDATE dbo.Employees SET LastName = 'Doe' WHERE (EmployeeID = 5)

This changes the name of employee 5 to Doe.


6. Close the view of the data.
Testing the SQL Cache Dependency
You can now test the page to see whether the data and timestamp have changed.
To test SQL cache dependency
1. Press CTRL+F5 to run the page.
Note that the time stamp has changed and that the new data is displayed.
2. Press CTRL+F5 to run the page again.
This time the time stamp remains the same, because the data has not changed, and the page is now being retrieved once
again from the cache.
Next Steps
You can cache pages using other parameters as well. For information, see
Walkthrough: Using Output Caching to Enhance Web Site Performance. If you are not familiar with data access, see
Walkthrough: Basic Data Access in Web Pages.
See Also
Reference
DefaultHttpCachePolicy
OutputCacheSettingsSection
Concepts
Caching in ASP.NET with the SqlCacheDependency Class
Visual Web Developer

Additional Page Techniques


The topics in this section include step-by-step walkthroughs that illustrate how to create reusable elements by using user
controls, HTML tables, master pages, Web parts, and the Wizard control.
In This Section
Walkthrough: Creating Reusable Elements with ASP.NET User Controls
Walkthrough: Editing HTML Tables in Visual Web Developer
Walkthrough: Creating and Using ASP.NET Master Pages in Visual Web Developer
Walkthrough: Creating a Basic ASP.NET Wizard Control
Walkthrough: Creating a Web Parts Page in Visual Web Developer
Related Sections
Guided Tour of Creating Web Sites in Visual Web Developer
Contains topics that give an introductory guided tour of the process of creating Web sites in Visual Web Developer.
Visual Web Developer

Walkthrough: Creating Reusable Elements with ASP.NET User


Controls
ASP.NET user controls let you encapsulate the functionality of multiple server controls in a unit. User controls are made up of
one or more ASP.NET server controls—Button controls, TextBox controls, and so on—along with any code that is required for
the controls to perform the function that you want to accomplish. The user control can also include custom properties or
methods that reveal the functionality of the user control to a container, which is typically an ASP.NET page.
In this walkthrough, you will create an ASP.NET user control that acts as a picker control. The picker control has two lists, with a
set of choices in one list (the source). Users can select items in the SourceList list, and then add the items to the TargetList list.
This walkthrough has three parts, as follows:
In the first part, you will create the basic user control, adding controls and code.
In the second part, you will create a new ASP.NET page (the host page), and then add the user control to the ASP.NET
page.
In the third part, you will add custom properties and methods to the user control so that you can interact with the control
from the host page.
Tasks illustrated in this walkthrough include the following:
Creating a user control and adding ASP.NET server controls to the user control.
Creating properties and a method in the user control.
Adding a user control to a host page.
Adding code to the host page to handle the user control.
Prerequisites
In order to complete this walkthrough, you will need the following:
The Microsoft Visual Web Developer Web development tool.
The Microsoft .NET Framework.
This walkthrough assumes that you have a general understanding of working in Visual Web Developer. For an introduction,
see Walkthrough: Creating a Basic Web Page in Visual Web Developer.
Creating the Web Site
If you have already created a Web site in Visual Web Developer (for example, by completing
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and go to the next section.
Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, point to New, and then click Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the right-most Location box, enter the name of the folder where you want to keep the pages of the Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click the programming language that you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Creating the User Control
Creating a user control is similar to creating an ASP.NET Web page. In fact, a user control is effectively a subset of an ASP.NET
page and it can include most of the types of elements that you put on an ASP.NET page.
To create a user control
1. In Solution Explorer, right-click the name of the Web site, and then click Add New Item.
2. In the Add New Item <Path> dialog box, under Visual Studio installed templates, click Web User Control.
3. In the Name box, type ListPicker.
The user control file will have an .ascx extension, which is added automatically to ListPicker.
4. In the Language list, select the programming language that you prefer to work in.
5. Click Add.
The new control is created and is opened in the designer. The markup for the control looks similar to that for a page, with
one important exception: there is no @ Page directive at the top of the page. Instead, there is an @ Control directive,
which identifies the file to ASP.NET as a user control.
Adding Server Controls to the User Control
In this part of the walkthrough, you will add the controls that make up the user interface for the user control.
To add server controls
1. Switch to Design view.
2. On the Layout menu, click Insert Table.
3. Use the Insert Table dialog box to create a table with one row and three columns, and then click OK.
You are creating the table to hold the controls; that is, a layout table.
4. In the table, in the left column, type Available, and then press ENTER to create a new line.
5. In the right column, type Selected, and then press ENTER to create a new line.
6. from the Standard group in the Toolbox, drag the following controls onto the table and set their properties as indicated.
Control Properties
Drag a ListBox to the left column and place it under Available. Height: 200px
ID: SourceList
Width: 200px

Drag a Button to the middle column. ID: AddAll


Text: >>

Drag a Button to the middle column. ID: AddOne


Text: (SPACEBAR)>( SPACEBAR)

Drag a Button to the middle column. ID: Remove


Text: (SPACEBAR)X(SPACEBAR)

Drag a ListBox to the right column and place it under Selected. Height: 200px
ID: TargetList
Width: 200px

ImageButton controls can be used instead of Button controls so that an image is displayed that responds to mouse clicks.
However, for this walkthrough, it is sufficient to use text that emulates the type of graphic that is frequently used to
indicate Add All, Add, and Remove, which are the two right angle brackets (>>), one right angle bracket (>), and the X,
respectively.
7. If you want, adjust the width and height of the table columns to your preference.
8. Click the SourceList list, and then in Properties, for the Items property, click the ellipsis (…) button.
The ListItem Collection Editor dialog box appears.
9. Click Add three times to add three items
10. For the first, second, and third item, under ListItem properties, set Text to A, B, and C, respectively.
You are creating test data for now. Later in this walkthrough, in "Adding Custom Properties and Methods to the User
Control," you will remove the test data and add code to load the SourceList list dynamically.
Adding Code to Handle User Selections
Users will select items using the buttons that are in the middle column of the table. Therefore, most of the code for the control
is in handlers for the Click events.
To add code to handle user selections
1. In Design view, double-click the >> (AddAll) button to create an event handler for the Click event, and then add the
following highlighted code.
VB
Protected Sub AddAll_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles AddAll.Click
TargetList.SelectedIndex = -1
Dim li As ListItem
For Each li In SourceList.Items
AddItem(li)
Next
End Sub

C#
protected void AddAll_Click(object sender, EventArgs e)
{
TargetList.SelectedIndex = -1;
foreach(ListItem li in SourceList.Items)
{
AddItem(li);
}
}

The code loops through all the list items in the SourceList list. For each item, it calls the AddItem method and passes it
the current item. Later in this procedure, you will write the code for the AddItem method.
2. Switch to Design view, double-click the > (AddOne) button to create an event handler for the Click event, and then add
the following highlighted code:
VB
Protected Sub AddOne_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles AddOne.Click
If SourceList.SelectedIndex >= 0 Then
AddItem(SourceList.SelectedItem)
End If
End Sub
C#
protected void AddOne_Click(object sender, EventArgs e)
{
if(SourceList.SelectedIndex >= 0)
{
AddItem(SourceList.SelectedItem);
}
}

This code first checks that there is a selection in the SourceList list. If there is, the code calls the AddItem method, which
you will write later in this procedure, passing it the item that is currently selected in the SourceList list.
3. Switch to Design view, double-click the X (Remove) button to create an event handler for the Click event, and then add
the following highlighted code:
VB
Protected Sub Remove_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles Remove.Click
If TargetList.SelectedIndex >= 0 Then
TargetList.Items.RemoveAt(TargetList.SelectedIndex)
TargetList.SelectedIndex = -1
End If
End Sub

C#
protected void Remove_Click(object sender, EventArgs e)
{
if(TargetList.SelectedIndex >= 0)
{
TargetList.Items.RemoveAt(TargetList.SelectedIndex);
TargetList.SelectedIndex = -1;
}
}

The code first checks that the TargetList list contains a selection. If there is a selection, the code removes the selected
item from the list and the selection.
4. Add the following AddItem method:
VB
Protected Sub AddItem(ByVal li As ListItem)
TargetList.SelectedIndex = -1
TargetList.Items.Add(li)
End Sub

C#
protected void AddItem(ListItem li)
{
TargetList.SelectedIndex = -1;
TargetList.Items.Add(li);
}

This code unconditionally adds an item to the TargetList list. Later in this walkthrough, in "Adding Custom Properties
and Methods to the User Control," you will improve this code by adding the option to determine whether there are
duplicates.
You cannot directly test a user control, because it must be hosted in a page. In the next section, you will create an ASP.NET Web
page where you can work with the control.
Using the User Control
Like any control, a user control must be hosted in a page. In this part of the walkthrough, you will create a host page for the
control, and then you will add a user control to the page.
To create a host page
1. In Solution Explorer, right-click the name of the Web site, and then click Add New Item.
2. Under Visual Studio installed templates, click Web Form.
3. In the Name box, type HostUserControl.
4. In the Language list, select the language that you prefer to work in, and then click Add.
The new page appears in the designer.

To add the user control to the page


1. Switch to Design view.
2. From Solution Explorer, drag the user control file (ListPicker.ascx) onto the page.
Note
Be sure that you are in Design view when you drag ListPicker.ascx onto the page.

The control appears in the designer.


3. Switch to Source view.
Placing the user control on the page creates two new elements in the page:
At the top of the page is a new @ Register directive and it looks similar to the following:

<%@ Register Src="ListPicker.ascx" TagName="ListPicker"


TagPrefix="uc1" %>

The @ Register directive is required, because the user control is an external component. The values that are in the
directive provide information that is required by ASP.NET to find the control when compiling and running the page.
Together, the TagPrefix and TagName attributes specify how the user control is declared on the page. The Src
attribute specifies the file, and if it is necessary, the path, where the source file is located.
The second new element is the element for the user control and it looks similar to the following:

<uc1:ListPicker id="ListPicker1" Runat="server" />

The element for a user control looks similar to the element for an ordinary ASP.NET server control. The difference is
that the user control has a different tag prefix (uc1) and a unique tag name (ListPicker). Although the values were
established automatically by the @ Register directive when you placed the user control on the page, you can use
any tag prefix and tag name for your user control, as long as the values are not already being used in the page.
Testing the User Control
Now, you can test the preliminary version of the user control.
To test the user control
1. Press CTRL+F5 to run the page.
The page appears in the browser and you can see the two lists and three buttons that make up your user control.
2. Click the >> (AddAll) button.
All values from the SourceList list are copied to the TargetList list.
3. Click each item in the TargetList list in turn, and then click the X (Remove) button until you have removed all items.
4. Select a single value in the SourceList list, and then click the > (AddOne) button.
The single value is copied to the TargetList list.
5. Optionally, experiment more with the control until you are sure that it works as you intend it to.
6. When you are finished, close the browser.
Adding Custom Properties and Methods to the User Control
Your user control now works, but it is not yet useful as a general-purpose control. A more practical version of the user control
would let you do the following:
Specify the list of items to display in the SourceList list dynamically.
Get the list of items that the user selected in the TargetList list.
Specify whether you want to allow duplicate values in the TargetList list, optionally.
Provide a way for users to clear all items in the TargetList list quickly.
Performing these tasks requires that the host page can communicate with the user control, both to share values (set and read
properties) and to issue commands (call methods). In this part of the walkthrough, you will change the user control and add
some members (properties and methods) to it.
You will add two properties to the user control. The first property retrieves the list of items that are in the TargetList list. The
second property lets you specify whether the TargetList list accepts duplicate values. Later in this section, you will add a
method that will let you populate the SourceList list.
To add code to define custom properties
1. For the ListPicker control, open or switch to the code file.
2. Use the following code to create the SelectedItems property:
VB
Public ReadOnly Property SelectedItems() As ListItemCollection
Get
Return TargetList.Items
End Get
End Property

C#
public ListItemCollection SelectedItems
{
get { return TargetList.Items ; }
}

The SelectedItems property retrieves the values that are in the TargetList list. It can be read-only, because you will
never have to set the values in the TargetList list programmatically.
3. Use the following code to create the AllowDuplicates property:
VB
Public Property AllowDuplicates() As Boolean
Get
Return CType(ViewState("allowDuplicates"), Boolean)
End Get
Set(ByVal value As Boolean)
ViewState("allowDuplicates") = value
End Set
End Property

C#
public Boolean AllowDuplicates
{
get
{
return (Boolean)ViewState["allowDuplicates"];
}
set
{
ViewState["allowDuplicates"] = value;
}
}

The AllowDuplicates property is a read/write property. The value of the AllowDuplicates property must be saved
explicitly in View state so that it persists between round trips. (The SelectedItems property does not have to be explicitly
saved in View state, because the TargetList list saves the values in View state.)
You now have the properties defined. However, you still must modify the existing code in the user control to take advantage of
the AllowDuplicates property setting.
To modify existing code to use the AllowDuplicates property
Find the AddItem method that you wrote in "Adding Code to Handle User Selections," earlier in this walkthrough, and
replace the contents with the following highlighted code:
VB
Protected Sub AddItem(ByVal li As ListItem)
TargetList.Selectedindex = -1
If Me.AllowDuplicates = True Then
TargetList.Items.Add(li)
Else
If TargetList.Items.FindByText(li.Text) Is Nothing Then
TargetList.Items.Add(li)
End If
End If
End Sub

C#
protected void AddItem(ListItem li)
{
TargetList.SelectedIndex = -1;
if(this.AllowDuplicates == true)
{
TargetList.Items.Add(li);
}
else
{
if(TargetList.Items.FindByText(li.Text) == null)
{
TargetList.Items.Add(li);
}
}
}

The code performs the same function as before (adding an item to the TargetList list), but now the code checks to
determine whether the AllowDuplicate property is set to true. If the AllowDuplicate property is set to true, the code
first looks for an existing item with the same value as the proposed new item, and then adds the new item, but only if no
existing item is found.
Because you will be setting the contents of the SourceList list using a property, you can remove the test data that you entered
in "Adding Server Controls to the User Control," earlier in this walkthrough.
To remove the test data for the SourceList list
1. Switch to Design view.
2. Click the SourceList control, and then, in Properties, for Items, click the ellipsis (…) button.
The ListItem Collection Editor appears.
3. Click the X (Remove) button to remove each sample item, and then click OK.
Adding a Method to the User Control
You can also add methods to perform tasks in the user control when the methods are called by code in the host page. To
illustrate this, in this walkthrough, you will add two methods. The first method can be called to add items to the SourceList list.
The second method clears the contents of the TargetList list.
To add a method to clear the TargetList list
1. Use the following code to add the AddSourceItem method:
VB
Public Sub AddSourceItem(ByVal sourceItem As String)
SourceList.Items.Add(sourceItem)
End Sub

C#
public void AddSourceItem(String sourceItem)
{
SourceList.Items.Add(sourceItem);
}

2. Use the following code to add the ClearAll method:


VB
Public Sub ClearAll()
SourceList.Items.Clear()
TargetList.Items.Clear()
End Sub

C#
public void ClearAll()
{
SourceList.Items.Clear();
TargetList.Items.Clear();
}

3. On the File menu, click Save All to save the changes that you made to the user control.
Testing the User Control Properties and Method
The final task in this walkthrough is to enhance the host page to be able to share values with the user control. You can set
some of the properties for the user control declaratively. (You cannot set the SourceList list directly using the code in this
walkthrough, but you can set it programmatically.) In this procedure, you will set the AllowDuplicates property to a default
value of true.
To set user control properties declaratively
1. Switch to or open the HostUserControl.aspx page.
2. In Source view, set AllowDuplicates declaratively by using syntax that it similar to the following:

<uc1:ListPicker id="ListPicker1" Runat="server"


AllowDuplicates="true" />

Notice that you obtain Microsoft IntelliSense functionality for AllowDuplicates.


Working with the User Control Programmatically
You can also work with the user control programmatically, setting and retrieving the properties and calling the methods. To
illustrate how to work with the user control programmatically, you will add some controls to the host page.
To work with the user control programmatically
1. Switch to Design view.
2. From the Standard group in the Toolbox, drag the following controls onto the table on the host page, and then set the
properties as indicated.
Control Properties
TextBox ID: NewItem
Text: (empty)

Button ID: AddItem


Text: Add Item

Button ID: LoadFiles


Text: File List

Button ID: ClearSelection


Text: Clear All

CheckBox AutoPostBack: True


Checked: True
ID: AllowDuplicates
Text: Allow duplicates

Button ID: ShowSelection


Text: Show Selection

Label ID: Selection


Text: (empty)

3. In Design view, double-click AllowDuplicates to create an event handler for the CheckedChanged event, and then add
the following highlighted code:
VB
Protected Sub AllowDuplicates_CheckedChanged( _
ByVal sender As Object, _
ByVal e As EventArgs) Handles AllowDuplicates.CheckedChanged
ListPicker1.AllowDuplicates = AllowDuplicates.Checked
End Sub

C#
protected void AllowDuplicates_CheckedChanged(Object sender, EventArgs e)
{
ListPicker1.AllowDuplicates = AllowDuplicates.Checked;
}

4. Switch to Design view, double-click AddItem to create an event handler for the Click event, and then add the following
highlighted code:
VB
Protected Sub AddItem_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles AddItem.Click
Dim sourceItem As String = Server.HtmlEncode(NewItem.Text)
ListPicker1.AddSourceItem(sourceItem)
End Sub

C#
protected void AddItem_Click(object sender, EventArgs e)
{
ListPicker1.AddSourceItem(Server.HtmlEncode(NewItem.Text));
}

The code creates a ListItemCollection collection in code and populates it with sample data. Then, the code sets the
SourceItems property to the collection.

5. Switch to Design view, double-click LoadFiles to create an event handler for the Click event, and then add the following
highlighted code:
VB
Protected Sub LoadFiles_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles LoadFiles.Click
Dim path As String = Server.MapPath(Request.ApplicationPath)
Dim files() As String = System.IO.Directory.GetFiles(path)
Dim filename As String
For Each filename in Files
ListPicker1.AddSourceItem(filename)
Next
End Sub

C#
protected void LoadFiles_Click(object sender, EventArgs e)
{
String path = Server.MapPath(Request.ApplicationPath);
String[] files = System.IO.Directory.GetFiles(path);
foreach(String filename in files)
{
ListPicker1.AddSourceItem(filename);
}
}
This code is similar to the code for AddItem, except that this code adds a list of files in the Web site root directory.
6. Switch to Design view, double-click ShowSelection to create an event handler for the Click event, and then add the
following highlighted code:
VB
Protected Sub ShowSelection_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles ShowSelection.Click
Dim lItem As ListItem
Dim selectedItemsString As String = ""
For Each lItem in ListPicker1.SelectedItems
selectedItemsString &= "<br>" & lItem.Text
Next
Selection.Text = selectedItemsString
End Sub

C#
protected void ShowSelection_Click(object sender, EventArgs e)
{
String selectedItemsString = "";
foreach(ListItem lItem in ListPicker1.SelectedItems)
{
selectedItemsString += "<br>" + lItem.Text;
}
Selection.Text = selectedItemsString;
}

This code retrieves an object that is typed as a ListItemCollection object, reads each item in the collection, and then
displays the results in Selection.
7. Switch to Design view, double-click ClearSelection to create an event handler for the Click event, and then add the
following highlighted code:
VB
Protected Sub ClearSelection_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles ClearSelection.Click
ListPicker1.ClearAll()
End Sub

C#
protected void ClearSelection_Click(object sender, EventArgs e)
{
ListPicker1.ClearAll();
}

This code invokes the ClearAll method for the user control to remove all items from the TargetList.
Testing the Finished User Controls
Now, you can test your finished user control.
To test the user control
1. Press CTRL+F5 to run the page.
2. In the text box, type a value, and then click Add Item.
3. Repeat step 2 several times, until you have a selection of items in the user control.
4. Use the buttons to select one or more of the source items from the SourceList list, and then add them to the TargetList
list.
5. Click Show Selection.
The TargetList list items are displayed in Selection.
6. Click Clear All.
7. Click File List.
The SourceList list now displays a list of file names.
8. In the user control, click Add to add several items to the TargetList list.
9. Try adding an item to the TargetList list that is already in the list.
The duplicate value is added.
10. Clear the Allow duplicates box, and then try adding duplicates again.
This time, the duplicates are not added to the TargetList list.
11. Click Show Selection.
The list of items in the TargetList list is displayed in the host page.
Next Steps
Although the control that you have created is not very complex, you have seen much of the basic functionality that you can
build into a user control. Refining the control is largely a matter of revealing additional properties and methods that enhance
what you can do with the control. Additional members might include the following:
Appearance properties.
You can create user control properties that let a user set the background, list size, and so on, for the control.
Note
By default, the user control uses the current theme that applies to the child controls. For example, if you have a skin defi
ned for a Button control, the buttons in your user control are displayed with that skin.

Data properties.
You can add properties that enable the user control to use a wider variety of data to display in the SourceList list. For
example, you could add properties to set a dataset, data table, and data display field.
Functionality.
You can add more buttons and code to the user control to enable users not just to copy items from the SourceList list to
the TargetList list, but also to move items—where the item is removed from the SourceList list as it is moved to the
TargetList list. The control could then have buttons that could move the data back from the TargetList list to the
SourceList list.
See Also
Tasks
How to: Convert Web Forms Pages into ASP.NET User Controls
Concepts
ASP.NET User Controls Overview
Web Application Security Threats Overview (Visual Studio)
Visual Web Developer

Walkthrough: Editing HTML Tables in Visual Web Developer


Table editing is an important part of many Web pages because tables are used to create the page layout. This walkthrough
illustrates the table-editing features of the HTML editor in Microsoft Visual Studio. You will use tables to create the layout for a
simple entry form on the page.
Note
The table-editing features described in this walkthrough pertain to HTML tables, not to the Table Web server control (the <as
p:Table> control and its child controls).

Tasks illustrated in this walkthrough include:


Adding a table.
Selecting the table, rows, and columns.
Resizing elements.
Adding and removing table elements.
Setting cell characteristics such as background color and alignment.
Prerequisites
In order to complete this walkthrough, you will need:
Visual Web Developer and the .NET Framework.
Creating the Web Site
If you have already created a Web site in Visual Studio (for example, by following the steps in
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and skip to the next section,
"Creating the Page Layout with a Table." Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, enter the name of the folder where you want to keep the pages of your Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click the programming language you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Creating the Page Layout with a Table
You will begin by adding a table that defines the overall layout of the page.
To add a table for the page layout
1. If you do not already have a page open in the designer, add a page to the Web site.
2. Switch to Design view.
3. In the Layout menu, click Insert Table.
The Insert Table dialog box appears.
4. Select Template.
Table templates are predefined table layouts.
5. In the Template list, select Header and side.
6. Click OK.
A two-column table is added to the page that takes up the entire height and width of the page. A single cell on top spans
the columns, providing a place to put a header. The left-hand cell below the header is for navigation or side information.
The right-hand cell below the header is the main display area for the page.
Note
The borders around the cells in the table are displayed by default at design time to help you edit. Unless you explicitly s
et the table or cells to have a border, no border will appear when the table is rendered in the browser.

Creating a Form Layout with a Table


You can also use HTML tables to lay out the controls in a form. You will now create a second table inside the first one. You will
later use the second table to create the layout for some controls in a form.
To add a table for the form layout
1. From the HTML group of the Toolbox, drag a Table element into the right-hand (main) cell.
When you drag a table from the Toolbox, Visual Web Developer creates an empty table of three columns and three
rows. You need only two columns; in a moment, you will delete one of the columns.
Note
You can create tables either by using the Insert Table command, as you did earlier, or by dragging a Table element fr
om the Toolbox.

2. Move the mouse pointer over the table until the pointer changes to a move cursor (four-headed arrow), and then click to
select the table.
3. Drag the right-hand edge of the table to widen the table until it is most of the width of the page.
As you drag, the table displays its current dimensions.
4. Right-click in one of the cells in the left-most column. From the Delete sub-menu, click Columns to remove the column
of the selected cell.
The column is deleted from the table.
Note
If you see a Delete option that does not have a submenu, it indicates that the focus is not in a cell. Right-click inside a c
ell in the left-hand column.

5. Click in the bottom right-hand cell and then press the TAB key to add a fourth row to the table.
You now have a table of two columns and four rows, which can be the container for your form controls.
Setting Characteristics of the Page Layout Table
Now that you have a form layout table inside the page table, you can finish laying out the page by editing the page layout
table.
To set characteristics of the page layout table
1. In the page layout table, click in the top cell.
The thicker border around the cell indicates that it is selected and in content-edit mode.
2. In the Properties window, click the button in the Style box.
The Style Builder dialog box appears.
3. On the Text tab, in the Horizontal list, click Centered.
4. On the Background tab, in the Color list, select a color you like. You can also click the button next to the Color box to
display the Color Picker dialog box and select from additional colors.
The settings you have made set the style for the cell at the top of the layout table.
5. Type Contoso Web Site as a heading.
6. Select the text and, in the Block Format list in the Formatting toolbar, click Heading 1 <H1>.
7. Repeat steps 1 through 6 for the leftmost cell in the table, with these changes:
Change the text to This site is maintained by Contoso, Incorporated.
Do not format the text as a Heading 1.
In the Text tab of the Style Builder dialog box, in the Vertical list, click bottom.
In a production Web page, the side cell would probably be occupied by a menu of links or other content. However, for
this walkthrough it does not matter what content the cell contains.
Building the Form
You can now build the form.
To add text and controls to the form layout table
1. In the form layout table (the table inside the page layout table), click in the top left cell and type Name:.
2. Click in the left cell of the second row and type Birth year:.
3. From the Standard group of the Toolbox, drag a TextBox control into the top right cell.
4. Set the TextBox control's ID property to textName.
5. Drag another TextBox into the second row's right cell and set its ID property to textBirthYear.
6. Drag a Button control into the third cell on the right and set its Text property to Submit.
7. Drag a Label control into the bottom right cell, set its ID property to labelDisplay, and clear its Text property.
8. Place the mouse cursor over the left-hand column until you see a selection symbol (a small square) at the top of the
column, and then click the symbol.
The left column is selected.
9. In the Properties window, click the button in the Style box to display the Style Builder dialog box.
10. In the Text tab, in the Horizontal list, click Right.
The text captions in the form are right-aligned.
11. Click OK to close the style builder.
12. Select the left column again, and then drag its right edge to shrink the column until it is just wide enough to fit the
caption text.
13. Right-click in the layout table cell outside the form layout table, and then click Style.
The shortcut menu provides an alternate way to display the Style Builder dialog box.
14. In the Text tab, in the Vertical list, click top.
The form layout table is aligned at the top of the cell.
Programming the Form Controls
You can now program the form controls. The form displays the age that the user will be this year.
To program the form controls
1. Double-click the Button control in the form.
The editor creates a Click event handler.
2. Add the following highlighted code.
VB
Protected Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
Dim age As Integer
age = DateTime.Now.Year - CInt(textBirthYear.Text)
labelDisplay.Text = Server.HtmlEncode(textName.Text) & _
", this year you are " & Server.HtmlEncode(age.ToString())
End Sub

C#
protected void Button1_Click(Object sender, EventArgs e)
{
int age = DateTime.Now.Year - Int32.Parse(textBirthYear.Text);
labelDisplay.Text = Server.HtmlEncode(textName.Text) +
", this year you are " + Server.HtmlEncode(age.ToString());
}

Testing the Page


You can now test the page.
To test the page
1. Press CTRL+F5 to run the page.
When the page is displayed in the browser, note the layout that you have created. Because you did not explicitly specify
table borders, there are no lines on the form.
2. In the Name box, type your name.
3. In the Birth year box, type the year you were born, and then click the Submit button.
The age calculation is displayed in the form in the location you created with the form table.
Next Steps
In this walkthrough, you have exercised some of the capabilities of the visual table editor in Design view. You added tables in
two ways, resized a table, added a row, deleted a column, set cell styles, and added text and controls as cell contents.
Suggestions for more exploration include:
Learn more ways to work with tables. For details, see:
How to: Add and Remove HTML Table Elements in Visual Web Developer
How to: Select HTML Table Elements and Contents in Visual Web Developer
How to: Resize HTML Table Elements in Visual Web Developer
Learn some tips for editing tables in both Design view and Source view. For details, see
HTML Table Editing Tips in Visual Web Developer.
Add validation to the Birth year text box so that users can enter only valid years. For more information, see
Validating User Input in ASP.NET Web Pages.
See Also
Tasks
Walkthrough: Creating and Using ASP.NET Master Pages in Visual Web Developer
Concepts
HTML Editor Tag Navigation in Visual Web Developer
Formatting Elements in the HTML Editor in Visual Web Developer
Visual Web Developer

Walkthrough: Creating and Using ASP.NET Master Pages in


Visual Web Developer
This walkthrough illustrates how to create a master page and several content pages. Master pages allow you to create a page
layout — a template page — and then create separate pages containing content that is merged with the master page at run
time. For more information about master pages, see ASP.NET Master Pages Overview.
Tasks illustrated in this walkthrough include:
Creating a master page in Microsoft Visual Web Developer.
Creating an ASP.NET page with content that you want to display in the master page.
Running master pages to show different content.
Selecting a master page at run time.
Prerequisites
In order to complete this walkthrough, you will need:
Visual Web Developer (Visual Studio).
The .NET Framework.
Optionally, a .jpg, .gif, or other graphics file that you can use as a logo on your master page. It is recommended that the
logo be no more than 48 pixels wide. However, displaying a logo is optional and the graphic's exact size is not critical to
the walkthrough.
Creating a Web Site
If you have already created a Web site in Visual Web Developer (for example, by following the steps in
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and skip to the next section,
"Creating the Master Page." Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, enter the name of the folder where you want to keep the pages of your Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click the programming language you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Creating the Master Page
The master page is the template for how your pages will look. In this section, you will first create a master page. You will then
use a table to lay out the master page with a menu, a logo, and a footer that will appear on each page of your site. You will also
work with a content placeholder, which is a region in the master page that can be replaced with information in a content page.
To create the master page
1. In Solution Explorer, right-click the name of your Web site, and then click Add New Item.
2. Under Visual Studio installed templates, click Master Page.
3. In the Name box, type Master1.
4. Select the Place code in separate file check box.
Note
This walkthrough assumes you are using code-behind files for all pages. If you are using a single-file ASP.NET page, the
code illustrated in this walkthrough will work, but will appear in Source view, not in a separate code file.

5. In the Language list, click the programming language you prefer and then click Add.
The new master page opens in Source view.
At the top of the page is an @ Master declaration instead of the @ Page declaration normally found at the top of ASP.NET
pages. The body of the page contains an <asp:contentplaceholder> control, which is the area of the master page
where replaceable content will be merged from content pages at run time. You will work more with the content
placeholder later in this walkthrough.
Laying Out the Master Page
The master page defines how the pages in your site look. It can contain any combination of static text and controls. A master
page also contains one or more content placeholders that designate where dynamic content will appear when pages are
displayed.
In this walkthrough, you will use a table to help you position elements on the page. You will start by creating a layout table to
hold the master page elements. Later in this section you will position the content placeholder control that is already on the
page.
To create a layout table for the master page
1. With the Master1.master file selected in Source view, set the target schema for validation to Microsoft Internet Explorer
6.0. To set this value, you can use either the drop-down list on the toolbar or select Options from the Tools menu, and
then click Validation.
2. Switch to Design view.
3. From the drop-down list at the top of the Properties window, select DOCUMENT, and then set BgColor to a distinctive
color, such as blue.
The color you select is not important. Later in this walkthrough you will create a second master page without a color to
contrast with what you have selected here.
4. Click the page where you want to place the layout table.
Note
Do not put the layout table inside the ContentPlaceHolder control.

5. On the Layout menu, click Insert Table.


6. In the Insert Table dialog box, click Template. In the list click Header, footer and side, and then click OK.
The template defines the arrangement of rows and cells in the table. The template you have selected creates three rows,
and the middle row is split into two cells.
7. Make the following settings:
In the middle row, click the leftmost column, and then set its Width to 48 in the Properties window.
Click the top row, and then set its Height to 48 in the Properties window.
Click the bottom row, and then set its Height to 48 in the Properties window.
Note
You can set the width and height by dragging the table cell borders or by selecting the cell and setting values in the Pro
perties window.

8. Select all cells in the table and set BgColor to a different color than the background color, and set VAlign to top.
8. Select all cells in the table and set BgColor to a different color than the background color, and set VAlign to top.
After laying out the table, you can add content to the master page that will appear on all pages. You will add a copyright
message as a footer, and add a menu. If you have a logo graphic available, you can add that as well.
To add static content to the master page
1. Click the bottom cell, and then type footer text such as Copyright 2005 Contoso Inc.
2. In the Toolbox, from the Navigation control group, drag a Menu control into the top cell.
3. Create a menu by following these steps:
a. Set the Menu control's Orientation property to Horizontal.
b. Click the smart tag on the Menu control, and click Edit Menu Items in the Menu Tasks dialog box.
4. Under Items, click the Add a root node icon twice to add two menu items:
a. Click the first node, and then set Text to Home and NavigateUrl to Home.aspx.
b. Click the second node, and then set Text to About and NavigateUrl to About.aspx.
c. Click OK to close the Menu Item Editor dialog box.
5. If you have a graphics file available to use as a logo, follow these steps to place it on the master page:
a. In Solution Explorer, right-click the name of your Web site, and then click Add Existing Item.
b. Navigate to your graphics file, select the graphic file, and then click Add.
c. In the Toolbox, from the Standard group, drag an Image control to the middle left column of the table.
d. Set the Image control's ImageUrl property to the name of the graphics file.
You can now position the content placeholder to specify where the master page can display content at run time.
To add a content placeholder
1. Drag the ContentPlaceHolder control into the middle right cell.
The control's ID property is ContentPlaceholder1. You can leave this name or change it. If you change the name, make a
note of the name because you will need to know the name later.
2. Save the page.
Creating Content for the Master Page
The master page provides the template for your content. You define content for the master page by creating an ASP.NET page
that is associated with the master page. The content page is a specialized form of an ASP.NET page that contains only the
content to be merged with the master page. In the content page, you add the text and controls that you want to display when
users request that page.
In this walkthrough, you will add two pages with content for the master page. The first is a home page and the second is an
about page.
To create the Home page
1. In Solution Explorer, right-click the name of your Web site, and click Add New Item.
2. Under Visual Studio installed templates, click Web Form.
3. In the Name box, type Home.
4. In the Language list, click the programming language you prefer.
5. Select the Select master page check box, and then click Add.
The Select a Master Page dialog box appears.
6. Click Master1.master, and then click OK.
A new .aspx file is created. The page contains an @ Page directive that attaches the current page to the selected master
page with the MasterPageFile attribute, as shown in the following code example.
VB
<%@ Page Language="VB" MasterPageFile="~/Master1.master" ... %>

C#
<%@ Page Language="C#" MasterPageFile="~/Master1.master" ... %>

The page also contains an <asp:Content> element that you will work with next.
A content page does not have the usual elements that make up an ASP.NET page, such as html, body, or form elements.
Instead, you add only the content that you want to display on the master page by replacing the placeholder regions you
created in the master page.
To add content to the Home page
1. Switch to Design view.
The region you created as a ContentPlaceHolder control in the master page is displayed as a Content control in the
new content page. The rest of the master page content is displayed so you can see the layout, but it appears dimmed
because you cannot change it while editing a content page.
2. From the drop-down list in the Properties window, click DOCUMENT, and then set Title to Contoso Home Page.
You can set the title of each content page independently, so that the correct title is displayed in the browser when the
content is merged with the master page. The title information is stored in the content page's @ Page directive.
3. In the Content control, type Welcome to the Contoso Web Site, select the text, and then format the text as a Heading
1 by selecting the text and selecting Heading 1 from the Block Format drop-down list above the Toolbox.
4. Press ENTER to create a new blank line in the Content control, and then type Thank you for visiting our site.
The text you add here is not important; you can type any text that will help you recognize this page as the home page.
5. Save the page.
You can create the About page the same way you created the Home page.
To create the About page
1. Use the same steps that you used for the Home page to add a new content page named About.aspx.
Be sure to attach the new page to the Master1.master page as you did with the Home page.
2. Change the page's title to Contoso About Page.
3. In the content region, type About Contoso, and then format the text as a Heading 1 by selecting the text and selecting
Heading 1 from the Block Format drop-down list above the Toolbox.
4. Press ENTER to create a new line, and then type Since 1982, Contoso has provided high-quality software services.
5. Save the page.
Testing the Pages
You can test the pages by running them as you would any ASP.NET page.
To test the pages
1. Switch to the Home.aspx page, and then press CTRL+F5.
ASP.NET merges the content in the Home.aspx page with the layout in the Master1.master page into a single page and
displays the resulting page in the browser. Notice that the URL of the page is Home.aspx; there is no reference in the
browser to the master page.
2. Click the About link.
The About.aspx page is displayed. It is also merged with Master1.master page.
Referencing Master Page Members
Code in the content pages can reference members on the master page, including any public properties or methods and any
controls on the master page. In this part of the walkthrough, you will create a property on the master page, and then use the
value of the property in the content pages. The premise is that the company name for the Web site is stored as a property in
the master page, and any reference to the company name in the content pages is based on the master page property.
The first step is to add a property to the master page.
To add a property to the master page
1. Switch to or open the Master1.master page.
2. In Solution Explorer, right-click Master1.master, and then click View Code to open the code editor.
Note
By default, Visual Web Developer creates pages that use the code-behind model. If you prefer, you can create code by u
sing the single-file model. For more information, see ASP.NET Web Page Code Model.

3. Inside the class definition, type the following code.


VB
Public Property CompanyName() As String
Get
Return CType(ViewState("companyName"), String)
End Get
Set(ByVal Value As String)
ViewState("companyName") = Value
End Set
End Property

C#
public String CompanyName
{
get { return (String) ViewState["companyName"]; }
set { ViewState["companyName"] = value; }
}

The code creates a property named CompanyName for the master page. The value is stored in view state so that it is
persisted between postbacks.
4. Inside the class definition (but not inside the property code), add the following code.
VB
Sub Page_Init(ByVal sender As Object, ByVal e As EventArgs) _
Handles Me.Init
Me.CompanyName = "Contoso"
End Sub

C#
void Page_Init(Object sender, EventArgs e)
{
this.CompanyName = "Contoso";
}

For this example, you will hard-code the value of the CompanyName property into the page.
You can now modify the content page to use the master page's CompanyName property.
To reference the CompanyName property in the content page
1. Switch to or open the Home.aspx page.
2. Switch to Source view.
3. At the top of the page, underneath the @ Page directive, add the following @ MasterType directive:

<%@ MasterType virtualpath="~/Master1.master" %>

The directive binds the content page's Master property, which you will use shortly, to the Master1.master page.
4. Switch to Design view.
5. In the Content control, change the text to Welcome to the Web site of .
6. In the Toolbox, from the Standard group, drag a Label control onto the Content control, and place it after the static text
so that the text reads:
Welcome to the Web site of [Label]
7. Set the Label control's ID property to CompanyName.
8. In Solution Explorer, right-click Home.aspx, and then click View Code to open the code editor.
9. Inside the class definition, add the following code.
VB
Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) _
Handles Me.Load
CompanyName.Text = Master.CompanyName
End Sub

C#
void Page_Load(Object sender, EventArgs e)
{
CompanyName.Text = Master.CompanyName;
}

The content page's Master property returns a reference to the master page as defined in the @ MasterType directive you
added in step 3.
You can now test the content page to be sure it is referencing the master page's CompanyName property correctly.
To test the reference to the master page property
1. Switch to or open the Home.aspx page, and then press CTRL+F5 to run the page.
The page is displayed in the browser, with the text Welcome to the Web site of Contoso
2. Close the browser.
3. Switch to or open the Master1.master code-behind page.
4. Change the Page_Init handler to assign a different company name to the property, as in the following code example.
VB
Sub Page_Init(ByVal sender As Object, ByVal e As EventArgs) _
Handles Me.Init
Me.CompanyName = "New Company Name"
End Sub
C#
void Page_Init(Object sender, EventArgs e)
{
this.CompanyName = "New Company Name";
}

5. Switch to the Home.aspx page, and then press CTRL+F5 to run it again.
This time, the updated company name appears in the page.
Notes
There are several other issues you should be aware of when working with a master page:
In a real-world application, you would probably store information such as the company name in the configuration file
and read it directly in the content pages. However, the scenario outlined here provides a simple illustration of how to
reference master page members in content pages.
You can access members on the master page even without including an @ MasterType directive. However, to do so, you
must cast the System.Web.UI.Page.Master property to the appropriate master page type (the Master property is null
if a page has no master page). For more information, see Working with ASP.NET Master Pages Programmatically.
You can reference controls on the master page by using the Master.FindControls method. For more information, see
Working with ASP.NET Master Pages Programmatically.
Changing Master Pages Dynamically
Under some circumstances, you might want to be able to change master pages dynamically; that is, to use code to set the
master page for a content page. For example, you might want to let users select from several layouts and set the master page
according to their preferences.
In this part of the walkthrough, you will add a second master page to the Web site, and then create buttons that allow the user
to switch between one master page and another. Because the two master pages will be very similar, you will make a copy of
the first master page and modify it to act as the second master page.
To make a copy of the master page
1. In Solution Explorer, right-click Master1.master, and then click Copy.
2. Right-click the name of the Web site, and then click Paste.
A master page is added to the Web site with the name Copy of master1.master.
3. Right-click Copy of master1.master, click Rename, and then name the new master page Master2.master.
4. Open Master2.master and, in the @ Master directive, change Master1 to Master2.
The completed page directive will look like the following code example.
VB
<%@ Master Language="VB" CodeFile="Master2.master.vb" Inherits="Master2" %>

C#
<%@ Master Language="C#" CodeFile="Master2.master.cs" Inherits="Master2" %>

5. Switch to Design view.


6. In the Properties window, in the drop-down list at the top, click DOCUMENT.
7. Clear the BgColor property.
The new master page will look and function like Master1.master, but will have no background color.
8. Open the code file for Master2.master and change the class name in the master page's code-behind file from Master1 to
Master2 to match the value of the Inherits attribute in the page's <%@ Master %> directive.

The code will look like the following example.


VB
Partial Class Master2

C#
public partial class Master2 : System.Web.UI.MasterPage

The next step is to add a button to each master page that allows the user to select the alternate master page.
To add buttons for selecting an alternate master page
1. Switch to or open the Master2.master page.
2. In the Toolbox, from the Standard node, drag a LinkButton control onto the page and place it below the menu in the
top table cell.
3. Set the button's Text property to Colorful.
4. Double-click the button to create a handler for its Click event, and then add the following highlighted code.
VB
Protected Sub LinkButton1_Click(ByVal sender As Object, ByVal e As EventArgs)_
Handles LinkButton1.Click
Session("masterpage") = "Master1.master"
Response.Redirect(Request.Url.ToString())
End Sub

C#
void LinkButton1_Click(Object sender, EventArgs e)
{
Session["masterpage"] = "Master1.master";
Response.Redirect(Request.Url.ToString());
}

The code loads the file name of the alternate master page into a persistent session variable, and then reloads the current
page. (The Url property returns a Uri object that references the current page.) Shortly, you will create code in the content
page that will use the name of the master page.
5. Switch to or open the Master1.master page in Design view.
6. Add a LinkButton control as you did in steps 1 and 2, and set its Text property to Plain.
7. Double-click the Plain button to create a handler for its Click event, and then add the following highlighted code.
VB
Protected Sub LinkButton1_Click(ByVal sender As Object, ByVal e As EventArgs)_
Handles LinkButton1.Click
Session("masterpage") = "Master2.master"
Response.Redirect(Request.Url.ToString())
End Sub

C#
void LinkButton1_Click(Object sender, EventArgs e)
{
Session["masterpage"] = "Master2.master";
Response.Redirect(Request.Url.ToString());
}

This code is the same as that for the button in the Master2.master page, except that it loads an alternate master page.
You now write code in the content page that will dynamically load the master page that the user has selected.
To write code to dynamically select the master page
1. Switch to or open the About.aspx page.
Note
The Home page you have already created contains an @ MasterType directive that effectively binds it to a single maste
r page (Master1.master). Therefore, you will not be able to assign master pages dynamically to the Home page and will
instead work with other pages you have created.

2. In Solution Explorer, right-click About.aspx, and then click View Code to open the code editor.
3. Inside the class definition, add the following code.
VB
Sub Page_PreInit(ByVal sender As Object, ByVal e As EventArgs) _
Handles Me.PreInit
If Not Session("masterpage") Is Nothing Then
Me.MasterPageFile = CType(Session("masterpage"), String)
End If
End Sub

C#
void Page_PreInit(Object sender, EventArgs e)
{
if(Session["masterpage"] != null)
{
this.MasterPageFile = (String) Session["masterpage"];
}
}

The code sets the value of the current page's MasterPageFile property to the value in the session variable, if any. This
code must run in the Page_PreInit handler; it cannot run in a handler that occurs any later than the Page_PreInit
handler (for example, in the Page_Init handler), because the master page must be established so that the page can
create an instance of it before any further initialization can occur.
You can now test the dynamic master pages.
To test the dynamic master pages
1. In the About.aspx page, press CTRL+F5 to run the page.
The page is displayed in the browser merged with its default master page, Master1.master.
2. Click the Plain link.
The page is redisplayed, this time merged with Master2.master, which has no background color.
3. Click the Colorful link.
The page is displayed using Master1.master again.
Notes
There are several other issues you should be aware of when working with dynamic master pages:
The scenario in this section for changing master pages is simplified to keep the walkthrough focused on master pages. In
a real application, you would most likely display a choice of layouts, and then store the user's preference by using
profiles. For details, see ASP.NET Profile Properties Overview.
You can configure your Web site so that all pages use the same master page. You might have a few pages that should
use an alternate master page, which you can configure in code in a manner similar to that shown in this section of the
walkthrough. For details, see "Scoping Master Pages" in ASP.NET Master Pages Overview.
You need to add the code from the Home.aspx page to every page where you want to override the default master page.
Next Steps
This walkthrough illustrates the basic functionality of master pages. You might want to experiment with additional features of
master pages. For example, you might want to:
Create master pages that have multiple content placeholders. You can then fill one or more placeholders with content for
each page that you display.
Define content placeholders with default content. If an ASP.NET page does not supply content for the placeholder, the
master page displays the default content.
Programmatically access members of the master page from content pages. This allows you to dynamically change the
look of the master page at run time. For details, see How to: Reference ASP.NET Master Page Content.
Use device filtering with master pages to create different layouts for different devices, such as one layout for browsers
and another for a specific type of phone. For details, see ASP.NET Device Filtering Overview.
Learn how you can put master pages within master pages to create componentized pieces. For details, see
Nested ASP.NET Master Pages.
See Also
Concepts
ASP.NET Master Pages Overview
Events in ASP.NET Master and Content Pages
Visual Web Developer

Walkthrough: Creating a Basic ASP.NET Wizard Control


Building a series of forms to collect user data is a common task when developing Web sites. The ASP.NET Wizard control
simplifies many of the tasks associated with building forms and collecting user input by providing a mechanism that allows
you to easily build steps, add a new step, or reorder the steps. In this walkthrough, you will use the ASP.NET Wizard control to
simplify data collection as a series of independent steps without having to write code or making user data persist between
form steps. You will create a simple wizard that collects a user name and e-mail address, and then present it back to the user in
the completion step. Tasks illustrated in this walkthrough include:
Adding a Wizard control to your page.
Adding controls and text to a wizard step.
Accessing the wizard's data between steps.
Prerequisites
In order to complete this walkthrough, you will need:
Microsoft Visual Web Developer (Visual Studio).
The .NET Framework.
Creating the Web Site
If you have already created a Web site in Visual Web Developer (for example, by following the steps in
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and skip to "Adding a Wizard
Control" later in this walkthrough. Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, enter the name of the folder where you want to keep the pages of your Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click the programming language you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Adding a Wizard Control
To add a Wizard control
1. Switch to Design view for Default.aspx.
2. From the Standard group of the Toolbox, drag a Wizard control onto the page.
The control appears with two default steps already in place. Clicking the steps allows you to edit the text and controls
displayed during that step.
Editing Wizard Steps
When the Wizard control is dragged onto the page, it shows two predefined steps by default. For this walkthrough, you will
edit both steps, and add a completion step that shows the result of the first two steps: a user name and an e-mail address.
To edit the first wizard step
1. Drag one of the handles at the edge of the Wizard control to enlarge the control to about twice its default size.
2. Click the underlined text Step 1 in the Wizard control.
3. Click the edit area for the Wizard control.
You can now edit the step's display area.
4. Type Name:.
5. Drag a TextBox control onto the active area of the wizard, next to the text you just typed.
You can now edit the second step to collect a user's e-mail address.
To edit the second wizard step
1. Click Step 2 in the Wizard control.
2. Click the edit area for the Wizard control.
3. Type Email:.
4. Drag a TextBox control onto the active area of the wizard, next to your e-mail label.
5. Save the file.
Adding a Completion Step
You will now create a completion step that acts as the end point of your wizard. The Complete step has no navigational
options.
To add a completion step
1. Right-click the Wizard control.
2. Choose Show Smart Tag.
3. In the Wizard Tasks dialog box, choose Add/Remove Wizard Steps.
The WizardStep Collection Editor appears.
4. From the Add drop-down list on the Add button, select Wizard Step.
The Properties area now shows the new step.
5. Set the Title property to Finished.
6. Set the StepType property to Complete.
7. Click OK.
Now you can edit your new completion step. For the purposes of this walkthrough, configure the completion step to show the
data the user entered on the previous steps.
To edit the completion step
1. Right-click the Wizard control and choose Show Smart Tag.
2. In the Wizard Tasks dialog box, use the Step drop-down list to choose the Finished step.
Note
The name in the drop-down list will be the name you gave the step when you created it, Finished in this example.

3. Drag a Label control onto the wizard, leaving the default name of Label1.
4. Drag another Label control onto the wizard, leaving the default name of Label2.
5. Save the file.
The completion step will display the data entered by the user. Use the page's Load event to assign the values from the first two
steps to the labels you added to the completion step.
To show the user's data
1. Return to Default.aspx and, in Design view, double-click the design surface.
The page now contains a Page_Load method that is stubbed out for you.
2. Add the following highlighted code.
VB
Private Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles Me.Load
Label1.Text = TextBox1.Text
Label2.Text = TextBox2.Text
End Sub

C#
void Page_Load(Object sender, System.EventArgs e)
{
Label1.Text = TextBox1.Text;
Label2.Text = TextBox2.Text;
}

3. Save the file.


Testing the Wizard Control
Now you can test the Wizard control.
To test the Wizard control
1. View Default.aspx in Design view.
2. Display the Wizard Tasks menu on the control and select Step 1 from the Step drop-down list.
3. Click the Wizard control, and then press CTRL+F5.
4. Type a name in the name TextBox control for Step 1.
5. Click Next.
6. Type an e-mail address in the e-mail TextBox control for Step 2.
7. Click Finish.
Your data is displayed.
Next Steps
The Wizard control simplifies the creation of forms to gather user data. In addition to what has been covered here, you might
have other questions related to user data collection and forms use. For example, you might want to:
Learn more about authenticating users with Forms. For details, see How to: Implement Simple Forms Authentication
Use themes to enhance the appearance of your wizard. For details, see ASP.NET Themes and Skins Overview
Get an overview of the Wizard control. For details, see Wizard Web Server Control Overview
See Also
Reference
Wizard Web Server Control Overview
Visual Web Developer

Walkthrough: Creating a Web Parts Page in Visual Web


Developer
This walkthrough is a hands-on demonstration of the essential components and tasks for creating Web pages that use Web
Parts controls in a visual page design tool such as Microsoft Visual Studio.
In many Web applications it is useful to be able to change the appearance of the content, as well as to allow users to select and
arrange the content they want to see. ASP.NET Web Parts enable you to create Web pages that present modular content and
that enable users to change the appearance and content to suit their preferences. For a general introduction to Web Parts, see
ASP.NET Web Parts Overview. For an overview of the Web Parts control set, see Web Parts Control Set Overview.
During this walkthrough, you create a page that uses Web Parts controls to create a Web page that user can modify, or
personalize. Tasks illustrated in this walkthrough include:
Adding Web Parts controls to a page.
Creating a custom user control and using it as a Web Parts control.
Allowing users to personalize the layout of the Web Parts controls on the page.
Allowing users to edit the appearance of a Web Parts control.
Allowing users to select from a catalog of available Web Parts controls.
Prerequisites
In order to complete this walkthrough, you will need:
A site that can identify individual users. If you have a site already configured with ASP.NET membership, you can use that
site for this walkthrough. Otherwise, the walkthrough provides instructions on how to configure your site to identify you
by your Windows user account name.
A visual design environment for creating Web pages. This walkthrough uses Visual Studio.
A configured personalization provider and database. Web Parts personalization is enabled by default, and it uses the SQL
personalization provider (SqlPersonalizationProvider) with Microsoft SQL Server Express Edition to store personalization
data. This walkthrough uses SQL Server Express and the default SQL provider. If you have SQL Server Express installed,
no configuration is needed. SQL Server Express is available with Microsoft Visual Studio 2005 as an optional part of the
installation, or as a free download from Microsoft.com. To use a full version of SQL Server, you must install and configure
an ASP.NET application services database, and configure the SQL personalization provider to connect to that database.
For details, see Creating and Configuring the Application Services Database for SQL Server.
Creating and Configuring the Web Site
This walkthrough requires that you have a user identity, so that your Web Parts settings can be keyed to you. If you already
have a Web site configured to use membership, it is recommended that you use that site. Otherwise, you can create a new site
and use your current Windows user name as your user identity.
To create a new Web site
In Visual Studio, create a new ASP.NET Web site. For details, see
Walkthrough: Creating a Web Site with Membership and User Login (Visual Studio).
Creating a Simple Page with Web Parts
In this part of the walkthrough, you create a page that uses Web Parts controls to show static content. The first step in working
with Web Parts is to create a page with two required elements. First, a Web parts page needs a WebPartManager control to
coordinate all Web Parts controls. Second, a Web Parts page needs one or more zones, which are composite controls that
contain WebPart or other server controls and occupy a specified region of a page.
Note
You do not need to do anything to enable Web Parts personalization; it is enabled by default for the Web Parts control set. W
hen you first run a Web Parts page on a site, ASP.NET sets up a default personalization provider to store user personalization
settings. For more information about personalization, see Web Parts Personalization Overview.

To create a page for containing Web Parts controls


1. Close the default page and add a new page named WebPartsDemo.aspx.
2. Switch to Design view.
3. From the View menu, make sure that the Non-Visual Controls and Details options are selected so you can see layout
tags and controls that do not have a UI.
4. Place the insertion point before the <div> tags on the design surface, and press ENTER to add a new line.
5. Position the insertion point before the new line character. From the Block Format list in the toolbar, select Heading 1
and in the heading, add the text Web Parts Demonstration Page.
6. From the WebParts tab of the Toolbox, drag a WebPartManager control onto the page, between the new line character
and the opening <div> tag.
The WebPartManager control does not render any output, so it appears as a gray box on the designer surface.
7. Position the insertion point within the <div> tags.
8. In the Layout menu, click Insert Table, and create a new table that has one row and three columns. Click the Cell
Properties button, select top from the Vertical align drop-down list, click OK, and click OK again to create the table.
9. Drag a WebPartZone control into the left table column. Right-click the WebPartZone control, choose Properties, and
set the following properties:
ID: SidebarZone

HeaderText: Sidebar

10. Drag a second WebPartZone control into the middle table column and set the following properties:
ID: MainZone

HeaderText: Main

11. Save the file.


Your page now has two distinct zones that you can control separately. However, neither zone has any content, so creating
content is the next step. For this walkthrough, you work with Web Parts controls that display only static content.
The layout of a Web Parts zone is specified by a <zonetemplate> element. Inside the zone template, you can add any
ASP.NET control, whether it is a custom Web Parts control, a user control, or an existing server control. Notice that here you are
using the Label control, and to that you are simply adding static text. When you place a regular server control in a
WebPartZone zone, ASP.NET treats the control as a Web Parts control at run time, which enables Web Parts features on the
control.
To create content for the main zone
1. In Design view, drag a Label control from the Standard tab of the Toolbox into the contents area of the zone whose ID
property is set to MainZone.
2. Switch to Source view.
Notice that a <zonetemplate> element was added to wrap the Label control in the MainZone.
3. Add an attribute named title to the <asp:label> element, and set its value to Content. Remove the Text="Label"
attribute from the <asp:label> element. Inside the <asp:label> element, add some text such as <h2>Welcome to my
Home Page</h2>. Your code should look as follows:

<asp:webpartzone id="MainZone" runat="server" headertext="Main">


<zonetemplate>
<asp:label id="Label1" runat="server" title="Content">
<h2>Welcome to My Home Page</h2>
</asp:label>
</zonetemplate>
</asp:webpartzone>

4. Save the file.


Next, create a user control that can also be added to the page as a Web Parts control.
To create a user control
1. Add a new Web user control to your site to serve as a search control named SearchUserControl.ascx, making sure that
the Place source code in a separate file is cleared.
Note
The user control for this walkthrough does not implement actual search functionality; it is used only to demonstrate W
eb Parts features.

2. Switch to Design view.


3. From the Standard tab of the Toolbox, drag a TextBox control onto the page.
4. Place the insertion point after the text box you just added, and press ENTER to add a new line.
5. Drag a Button control onto the page on the new line below the text box you just added.
6. Switch to Source view and then ensure that the source code for the user control looks like the following example:
VB
<%@ control language="VB" classname="SearchUserControl" %>
<asp:textbox runat="server" id="TextBox1"></asp:textbox>
<br />
<asp:button runat="server" id="Button1" text="Search" />

C#
<%@ control language="C#" classname="SearchUserControl" %>
<asp:textbox runat="server" id=" TextBox1"></asp:textbox>
<br />
<asp:button runat="server" id=" Button1" text="Search" />

7. Save and close the file.


Security Note
This control has a textbox that accepts user input, which is a potential security threat. User input in a Web page can pot
entially contain malicious client script. By default, ASP.NET Web pages validate user input to ensure that the input does
not contain HTML elements or script. As long as this validation is enabled, you do not need to explicitly check for script
or HTML elements in user input. For more information, see Script Exploits Overview.

Now you can add Web Parts controls to the Sidebar zone. You are adding two controls to the Sidebar zone, one containing a
list of links and another that is the user control you created earlier in the walkthrough. The links are added as a standard Label
server control, similar to the way you created the static text for the Main zone. However, although the individual server controls
contained in the user control could be contained directly in the zone (like the label control), in this case they are not. Instead,
they are part of the user control you created in the previous procedure. This demonstrates a common way to package controls
and extra functionality you want in a user control, and then reference that control in a zone as a Web Parts control.
At run time, the Web Parts control set wraps both controls with GenericWebPart controls. When a GenericWebPart control
wraps a Web server control, the generic part control is the parent control, and you can access the server control through the
parent control's ChildControl property. Using generic part controls enables standard Web server controls to have the same
basic behavior and attributes as Web Parts controls that derive from the WebPart class.
To add Web Parts controls to the sidebar zone
1. Open the WebPartsDemo.aspx page.
2. Switch to Design view.
3. Drag the user control page you created, SearchUserControl.ascx, from Solution Explorer into the zone whose ID
property is set to SidebarZone.
4. Save the WebPartsDemo.aspx page.
5. Switch to Source view.
6. Inside the <asp:webpartzone> element for the SidebarZone, add an <asp:label> element that contains links and in the
user control tag, add a Title attribute with a value of Search, as shown in the following example:

<asp:WebPartZone id="SidebarZone" runat="server"


headertext="Sidebar">
<zonetemplate>
<asp:label runat="server" id="linksPart" title="My Links">
<a href="http://www.asp.net">ASP.NET site</a>
<br />
<a href="http://www.gotdotnet.com">GotDotNet</a>
<br />
<a href="http://www.contoso.com">Contoso.com</a>
<br />
</asp:label>
<uc1:SearchUserControl id="searchPart" runat="server"
title="Search" />
</zonetemplate>
</asp:WebPartZone>

7. Save and close the file.


Now you can test your page.
To test the page
Load the page in a browser.
The page displays the two zones. The following screen shot shows the page.
Web Parts Demo page with two zones
In the title bar of each control is a downward arrow that provides access to a verbs menu of available actions you can
perform on a control. Click the verbs menu for one of the controls, then click the Minimize verb and note that the
control is minimized. From the verbs menu, click Restore, and the control returns to its normal size.
Enabling Users to Edit Pages and Change Layout
Web Parts provides the capability for users to change the layout of Web Parts controls by dragging them from one zone to
another. In addition to allowing users to move WebPart controls from one zone to another, you can allow users to edit various
characteristics of the controls, including their appearance, layout, and behavior. The Web Parts control set provides basic
editing functionality for WebPart controls. Although you will not do so in this walkthrough, you can also create custom editor
controls that allow users to edit the features of WebPart controls. As with changing the location of a WebPart control, editing
a control's properties relies on ASP.NET personalization to save the changes that users make.
In this part of the walkthrough, you add the ability for users to edit the basic characteristics of any WebPart control on the
page. To enable these features, you add another custom user control to the page, along with an <asp:editorzone> element
and two editing controls.
To create a user control that enables changing page layout
1. In Visual Studio, on the File menu, click New, and then click File.
2. In the Add New Item dialog, select Web User Control. Name the new file DisplayModeMenu.ascx. Clear the Place
source code in separate file box.
3. Click Add to create the new control.
4. Switch to Source view.
5. Remove all the existing code in the new file, and paste in the following code. This user control code uses features of the
Web Parts control set that enable a page to change its view or display mode, and also enables you to change the physical
appearance and layout of the page while you are in certain display modes.
VB
<%@ control language="vb" classname="DisplayModeMenuVB"%>
<script runat="server">
' Use a field to reference the current WebPartManager control.
Dim _manager As WebPartManager

Sub Page_Init(ByVal sender As Object, ByVal e As EventArgs)


AddHandler Page.InitComplete, AddressOf InitComplete
End Sub

Sub InitComplete(ByVal sender As Object, ByVal e As System.EventArgs)


_manager = WebPartManager.GetCurrentWebPartManager(Page)

Dim browseModeName As String = _


WebPartManager.BrowseDisplayMode.Name
' Fill the drop-down list with the names of supported display modes.
Dim mode As WebPartDisplayMode
For Each mode In _manager.SupportedDisplayModes
Dim modeName As String = mode.Name
' Make sure a mode is enabled before adding it.
If mode.IsEnabled(_manager) Then
Dim item As New ListItem(modeName, modeName)
DisplayModeDropdown.Items.Add(item)
End If
Next mode

' If Shared scope is allowed for this user, display the


' scope-switching UI and select the appropriate radio button
' for the current user scope.
If _manager.Personalization.CanEnterSharedScope Then
Panel2.Visible = True
If _manager.Personalization.Scope = _
PersonalizationScope.User Then
RadioButton1.Checked = True
Else
RadioButton2.Checked = True
End If
End If
End Sub

' Change the page to the selected display mode.


Sub DisplayModeDropdown_SelectedIndexChanged(ByVal sender As Object, _
ByVal e As EventArgs)

Dim selectedMode As String = DisplayModeDropdown.SelectedValue


Dim mode As WebPartDisplayMode = _
_manager.SupportedDisplayModes(selectedMode)
If Not (mode Is Nothing) Then
_manager.DisplayMode = mode
End If
End Sub

' Set the selected item equal to the current display mode.
Sub Page_PreRender(ByVal sender As Object, ByVal e As EventArgs)
Dim items As ListItemCollection = DisplayModeDropdown.Items
Dim selectedIndex As Integer = _
items.IndexOf(items.FindByText(_manager.DisplayMode.Name))
DisplayModeDropdown.SelectedIndex = selectedIndex
End Sub

' Reset all of a user's personalization data for the page.


Protected Sub LinkButton1_Click(ByVal sender As Object, _
ByVal e As EventArgs)

_manager.Personalization.ResetPersonalizationState()

End Sub

' If not in User personalization scope, toggle into it.


Protected Sub RadioButton1_CheckedChanged(ByVal sender As _
Object, ByVal e As EventArgs)
If _manager.Personalization.Scope = _
PersonalizationScope.Shared Then
_manager.Personalization.ToggleScope()
End If
End Sub

' If not in Shared scope, and if user has permission, toggle the
' scope.
Protected Sub RadioButton2_CheckedChanged(ByVal sender As _
Object, ByVal e As EventArgs)
If _manager.Personalization.CanEnterSharedScope AndAlso _
_manager.Personalization.Scope = _
PersonalizationScope.User Then
_manager.Personalization.ToggleScope()
End If
End Sub

</script>
<div>
<asp:Panel ID="Panel1" runat="server"
Borderwidth="1"
Width="230"
BackColor="lightgray"
Font-Names="Verdana, Arial, Sans Serif" >
<asp:Label ID="Label1" runat="server"
Text="&nbsp;Display Mode"
Font-Bold="true"
Font-Size="8"
Width="120" />
<asp:DropDownList ID="DisplayModeDropdown" runat="server"
AutoPostBack="true"
Width="120"
OnSelectedIndexChanged="DisplayModeDropdown_SelectedIndexChanged" />
<asp:LinkButton ID="LinkButton1" runat="server"
Text="Reset User State"
ToolTip="Reset the current user's personalization data for
the page."
Font-Size="8"
OnClick="LinkButton1_Click" />
<asp:Panel ID="Panel2" runat="server"
GroupingText="Personalization Scope"
Font-Bold="true"
Font-Size="8"
Visible="false" >
<asp:RadioButton ID="RadioButton1" runat="server"
Text="User"
AutoPostBack="true"
GroupName="Scope"
OnCheckedChanged="RadioButton1_CheckedChanged" />
<asp:RadioButton ID="RadioButton2" runat="server"
Text="Shared"
AutoPostBack="true"
GroupName="Scope"
OnCheckedChanged="RadioButton2_CheckedChanged" />
</asp:Panel>
</asp:Panel>
</div>

C#
<%@ control language="C#" classname="DisplayModeMenuCS"%>
<script runat="server">

// Use a field to reference the current WebPartManager control.


WebPartManager _manager;

void Page_Init(object sender, EventArgs e)


{
Page.InitComplete += new EventHandler(InitComplete);
}

void InitComplete(object sender, System.EventArgs e)


{
_manager = WebPartManager.GetCurrentWebPartManager(Page);

String browseModeName = WebPartManager.BrowseDisplayMode.Name;

// Fill the drop-down list with the names of supported display modes.
foreach (WebPartDisplayMode mode in
_manager.SupportedDisplayModes)
{
String modeName = mode.Name;
// Make sure a mode is enabled before adding it.
if (mode.IsEnabled(_manager))
{
ListItem item = new ListItem(modeName, modeName);
DisplayModeDropdown.Items.Add(item);
}
}

// If Shared scope is allowed for this user, display the


// scope-switching UI and select the appropriate radio
// button for the current user scope.
if (_manager.Personalization.CanEnterSharedScope)
{
Panel2.Visible = true;
if (_manager.Personalization.Scope ==
PersonalizationScope.User)
RadioButton1.Checked = true;
else
RadioButton2.Checked = true;
}
}

// Change the page to the selected display mode.


void DisplayModeDropdown_SelectedIndexChanged(object sender,
EventArgs e)
{
String selectedMode = DisplayModeDropdown.SelectedValue;

WebPartDisplayMode mode =
_manager.SupportedDisplayModes[selectedMode];
if (mode != null)
_manager.DisplayMode = mode;
}

// Set the selected item equal to the current display mode.


void Page_PreRender(object sender, EventArgs e)
{
ListItemCollection items = DisplayModeDropdown.Items;
int selectedIndex =
items.IndexOf(items.FindByText(_manager.DisplayMode.Name));
DisplayModeDropdown.SelectedIndex = selectedIndex;
}

// Reset all of a user's personalization data for the page.


protected void LinkButton1_Click(object sender, EventArgs e)
{
_manager.Personalization.ResetPersonalizationState();
}

// If not in User personalization scope, toggle into it.


protected void RadioButton1_CheckedChanged(object sender, EventArgs e)
{
if (_manager.Personalization.Scope ==
PersonalizationScope.Shared)
_manager.Personalization.ToggleScope();
}

// If not in Shared scope, and if user has permission, toggle


// the scope.
protected void RadioButton2_CheckedChanged(object sender,
EventArgs e)
{
if (_manager.Personalization.CanEnterSharedScope &&
_manager.Personalization.Scope ==
PersonalizationScope.User)
_manager.Personalization.ToggleScope();
}
</script>
<div>
<asp:Panel ID="Panel1" runat="server"
Borderwidth="1"
Width="230"
BackColor="lightgray"
Font-Names="Verdana, Arial, Sans Serif" >
<asp:Label ID="Label1" runat="server"
Text="&nbsp;Display Mode"
Font-Bold="true"
Font-Size="8"
Width="120" />
<asp:DropDownList ID="DisplayModeDropdown" runat="server"
AutoPostBack="true"
Width="120"
OnSelectedIndexChanged="DisplayModeDropdown_SelectedIndexChanged" />
<asp:LinkButton ID="LinkButton1" runat="server"
Text="Reset User State"
ToolTip="Reset the current user's personalization data for
the page."
Font-Size="8"
OnClick="LinkButton1_Click" />
<asp:Panel ID="Panel2" runat="server"
GroupingText="Personalization Scope"
Font-Bold="true"
Font-Size="8"
Visible="false" >
<asp:RadioButton ID="RadioButton1" runat="server"
Text="User"
AutoPostBack="true"
GroupName="Scope"
OnCheckedChanged="RadioButton1_CheckedChanged" />
<asp:RadioButton ID="RadioButton2" runat="server"
Text="Shared"
AutoPostBack="true"
GroupName="Scope"
OnCheckedChanged="RadioButton2_CheckedChanged" />
</asp:Panel>
</asp:Panel>
</div>

6. Save the file.


Note
Although this user control can enable users of the Web Parts page to toggle between shared and user-personalization
mode, this feature requires the user to have appropriate permissions, as specified in the Web.config file. This walkthrou
gh does not illustrate how to grant these rights, so the feature is not enabled. Therefore, the user and shared radio butt
ons on the user control are hidden when you run the page. For more information on personalization, see
Web Parts Personalization.

To enable users to change the layout


1. Open the WebPartsDemo.aspx page.
2. Switch to Design view.
3. Position the insertion point just after the WebPartManager control that you added earlier. Press ENTER to create a
blank line after the WebPartManager control.
4. Drag the user control you just created (DisplayModeMenu.ascx) into the WebPartsDemo.aspx page and drop it on the
blank line.
5. Drag an EditorZone control from the WebParts tab of the Toolbox to the remaining open table cell in the
WebPartsDemo.aspx page.

6. From the WebParts tab of the Toolbox, drag an AppearanceEditorPart control and a LayoutEditorPart control into the
EditorZone control.
7. Switch to Source view.
The resulting code in the table cell will look similar to the following code.

<td valign="top">
<asp:EditorZone ID="EditorZone1" runat="server">
<ZoneTemplate>
<asp:AppearanceEditorPart ID="AppearanceEditorPart1"
runat="server" />
<asp:LayoutEditorPart ID="LayoutEditorPart1" runat="server" />
</ZoneTemplate>
</asp:EditorZone>
</td>

Note
Although the AppearanceEditorPart and LayoutEditorPart controls are used in this walkthrough, the
BehaviorEditorPart and PropertyGridEditorPart controls are not, because they require setup beyond the scope of this w
alkthrough.

8. Save the WebPartsDemo.aspx file.


You have created a user control that allows you to change display modes and change page layout, and you have referenced the
control on the primary Web page.
You can now test the capability to edit pages and change layout.
To test layout changes
1. Load the page in a browser.
2. In the Display Mode menu, click Edit.
The zone titles are displayed.
3. Drag the My Links control by its title bar from the Sidebar zone to the bottom of the Main zone.
The page will look like the following:
Web Parts Demo page with My Links control moved

4. Click Display Mode, and then click Browse.


The page is refreshed, the zone names disappear, and the My Links control remains where you positioned it.
5. To demonstrate that personalization is working, close the browser, and then load the page again. The changes you made
are saved for future browser sessions.
6. In the Display Mode menu, click Edit.
Each control on the page is now displayed with a downward arrow in its title bar, which contains the verbs drop-down
menu.
7. Click the arrow to display the verbs menu on the My Links control and then click Edit.
The EditorZone control appears, displaying the EditorPart controls you added.
8. In the Appearance section of the edit control, change the Title to My Favorites. In the Chrome Type list, select Title
Only, and then click Apply.
The following screen shot shows the page in edit mode.
Web Parts Demo page in Edit mode
9. In the Display Mode menu, click Browse to return to browse mode.
The control now has an updated title and no border, as shown in the following screen shot.
Edited Web Parts Demo page

Adding Web Parts at Run Time


You can also enable users to add Web Parts controls to their page at run time. To do so, configure the page with a Web Parts
catalog, which contains a list of Web Parts controls that you want to make available to users.
Note
In this walkthrough, you create a template containing FileUpload and Calendar controls. This will allow you to test the basic f
unctionality of the catalog, but the resulting Web Parts controls do not have any real functionality. If you have a custom Web
or user control, you can substitute it for the static content.

To allow users to add Web Parts at run time


1. Open the WebPartsDemo.aspx page.
2. Switch to Design view.
3. From the WebParts tab of the Toolbox, drag a CatalogZone control into the right column of the table, beneath the
EditorZone control.
Both controls can be in the same table cell because they will not be displayed at the same time.
4. In the Properties pane, assign the string Add Web Parts to the HeaderText property of the CatalogZone control.
5. From the WebParts tab of the Toolbox, drag a DeclarativeCatalogPart control into the content area of the CatalogZone
control.
6. Click the arrow in the upper right corner of the DeclarativeCatalogPart control to expose its Tasks menu, and then
select Edit Templates.
7. From the Standard tab of the Toolbox, drag a FileUpload control and a Calendar control into the WebPartsTemplate
section of the DeclarativeCatalogPart control.
8. Switch to Source view and inspect the source code of the <asp:catalogzone> element.
Notice that the DeclarativeCatalogPart control contains a <webpartstemplate> element with the two enclosed
server controls that you will be able to add to your page from the catalog.
Note
If you have a custom control, this is the place to substitute it for one of the server controls in the example, although this
requires steps beyond the scope of this walkthrough. For further details, see the code example in the documentation fo
r the WebPart class.

9. Add a Title property to each of the controls you added to the catalog, using the string value shown for each title in the
code example below. Even though the title is not a property you can normally set on these two server controls at design
time, when a user adds these controls to a WebPartZone zone from the catalog at run time, they are each wrapped with
a GenericWebPart control. This enables them to act as Web Parts controls, so they will be able to display titles.
The code for the two controls contained in the DeclarativeCatalogPart control will look like the following.

<asp:DeclarativeCatalogPart ID="DeclarativeCatalogPart1"
runat="server">
<WebPartsTemplate>
<asp:Calendar ID="Calendar1"
runat="server"
title="My Calendar" />
<asp:FileUpload ID="FileUpload1"
runat="server"
title="Upload Files" />
</WebPartsTemplate>
</asp:DeclarativeCatalogPart>

10. Save the page.


You can now test the catalog.
To test the Web Parts catalog
1. Load the page in a browser.
2. In the Display Mode menu, click Catalog.
The catalog titled Add Web Parts is displayed.
3. Drag the My Favorites control from the Main zone back to the top of the Sidebar zone.
4. In the Add Web Parts catalog, select both check boxes, and then select Main from the list of available zones
5. Click Add in the catalog.
The controls are added to the Main zone. If you want, you can add multiple instances of controls from the catalog to your
page. The following screen shot shows the page with the file upload control and the calendar in the Main zone:
Controls added to Main zone from the catalog
6. In the Display Mode menu, click Browse.
The catalog disappears and the page is refreshed.
7. Close the browser and then Load the page again.
The changes you made persist.
Next Steps
This walkthrough has illustrated the basic principles of using simple Web Parts controls on an ASP.NET Web page. You might
want to experiment with additional, more sophisticated Web Parts features. Suggestions for further exploration include:
Create Web Parts controls that offer more sophisticated functionality than the static Web Parts from this walkthrough.
You can create Web Parts controls as user controls or custom controls. For details, see the documentation for the
WebPart class.
See Also
Tasks
Walkthrough: Creating a Web Parts Page
Reference
Web Parts Control Set Overview
WebPart
Concepts
ASP.NET Web Parts Overview
Visual Web Developer

Customizing Web Pages


The topics in this section include step-by-step walkthroughs that illustrate how to add menus, define themes for consistent
Web site appearance, create rotating advertisements, create pages for browsers on mobile devices, create and use an ASP.NET
Web service, and create pages that can display text in different languages.
In This Section
Walkthrough: Adding Site Navigation to a Web Site
Walkthrough: Creating a Web Site with Membership and User Login (Visual Studio)
Walkthrough: Maintaining Web Site User Information with Profile Properties
Walkthrough: Customizing a Web Site Using Themes in Visual Studio
Walkthrough: Displaying and Tracking Advertisements with the AdRotator Control
Walkthrough: Creating and Using an ASP.NET Web Service in Visual Web Developer
Walkthrough: Creating Web Pages for Mobile Devices
Walkthrough: Using Resources for Localization with ASP.NET
Related Sections
Guided Tour of Creating Web Sites in Visual Web Developer
Introduces topics designed to give a guided tour of creating Web sites in Microsoft Visual Web Developer.
Visual Web Developer

Walkthrough: Adding Site Navigation to a Web Site


In any site that has more than just several pages, it can be difficult to construct a navigation system that lets users move freely
between pages, especially as you change the site. ASP.NET site navigation lets you create a centralized site map of the pages.
This walkthrough shows you how to configure a site map and how to use controls that rely on the site map to add navigation
to pages in the Web site.
During this walkthrough, you will learn how to do the following:
Create a Web site that has example pages and a site-map file that describes the layout of the pages.
Use the TreeView control as a navigation menu that lets users jump to any page in your site.
Use the SiteMapPath control to add a navigation path, also known as a breadcrumb, that enables a user to view and
move back up the site hierarchy from the current page.
Use the Menu control to add a navigation menu that lets users view one level of nodes at a time. Pausing the mouse
pointer over a node that has child nodes generates a submenu of the child nodes.
Use site navigation and controls on a master page so that you have to define the site navigation only once.
Prerequisites
In order to complete this walkthrough, you will need the following:
Microsoft Visual Web Developer Web development tool.
The .NET Framework.
This walkthrough assumes that you know how to use Visual Web Developer.
Creating a Web Site That Has Example Pages and a Site Map
If you have already created a Web site in Visual Web Developer by completing
Walkthrough: Creating a Basic Web Page in Visual Web Developer, you can use that Web site and go to the next section.
Otherwise, create a new Web site and page by following these steps.
Creating a File System Web Site

To create a file system Web site


1. Open Visual Web Developer.
2. On the File menu, click New Web Site (or on the File menu, click New, and then click Web Site).
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the left-most Location box, click File System, and then in the right-most Location box, enter the name of the folder
where you want to keep the pages of the Web site.
For example, type the folder name C:\WebSites\SiteNavigation.
5. In the Language box, click the programming language that you prefer to work in.
The programming language that you choose will be the default for the Web site, but you can set the programming
language for each page individually.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Creating a Site Map
To use site navigation, you need a way to describe how the pages in your site are laid out. The default method is to create an
.xml file that contains the site hierarchy, including the page titles and URLs.
The structure of the .xml file reflects the structure of your site. Each page is represented as a siteMapNode element in the site
map. The top-most node represents the home page, and child nodes represent pages that are deeper in the site.
To create a site map
1. In Solution Explorer, right-click the name of the Web site, and then click Add New Item.
2. In the Add New Item <Path> dialog box:
a. Under Visual Studio installed templates, click Site Map.
b. In the Name box, Make sure that the name is Web.sitemap.
Note
The file must be named Web.sitemap and must appear in the root of the Web site.

c. Click Add.
3. Copy the following XML content into the Web.sitemap file, overwriting the default contents.

<siteMap>
<siteMapNode title="Home" description="Home" url="~/home.aspx" >
<siteMapNode title="Products" description="Our products"
url="~/Products.aspx">
<siteMapNode title="Hardware"
description="Hardware we offer"
url="~/Hardware.aspx" />
<siteMapNode title="Software"
description="Software for sale"
url="~/Software.aspx" />
</siteMapNode>
<siteMapNode title="Services" description="Services we offer"
url="~/Services.aspx">
<siteMapNode title="Training" description="Training"
url="~/Training.aspx" />
<siteMapNode title="Consulting" description="Consulting"
url="~/Consulting.aspx" />
<siteMapNode title="Support" description="Support"
url="~/Support.aspx" />
</siteMapNode>
</siteMapNode>
</siteMap>

The Web.sitemap file contains a set of siteMapNode elements that are nested to three levels. The structure of each
element is the same. The only difference among them is the location within the XML hierarchy.
The URL of the pages that are defined in the sample .xml file is unqualified. This means that all pages are treated as
having URLs that are relative to the application root. However, you can specify any URL for a specific page — the logical
structure that you define in the site map does not have to correspond to the physical layout of the pages in folders.
4. Save the file, and then close it.
Creating Pages to Navigate
In this section, you will create only a few of the pages that are described in the site map that you defined in the preceding
section. (The site map is more complete so that you will be able to view a full hierarchy when testing the pages in this
walkthrough.)
To create pages to navigate
1. In Solution Explorer, right-click the name of the Web site, and then click Add New Item.
2. In the Add New Item <Path> dialog box:
a. Under Visual Studio installed templates, click Web Form.
b. In the Name box, type Home.aspx, and then click Add.
3. Switch to Design view.
4. On the Home.aspx page, type Home, and then format it as a Heading 1.
Repeat this procedure and create four additional pages named Products.aspx, Hardware.aspx, Software.aspx, and
Training.aspx. Use the name of the page (for example, Products) as the heading so that you will be able to recognize
each page when the page is displayed in the browser.
It is not important which pages you specifically create. The pages that are listed in this procedure are suggestions that
will let you see the site hierarchy nested to three levels.
Creating a Navigation Menu Using the TreeView Control
Now that you have a site map and some pages, you can add navigation to your site. You will use the TreeView control to act
as a collapsible navigation menu.

To add a tree-style navigation menu


1. Open the Home.aspx page.
2. From the Data group in the Toolbox, drag a SiteMapDataSource control onto the page.
In its default configuration, the SiteMapDataSource control retrieves its information from the Web.sitemap file that you
created in "Creating a Site Map," earlier in this walkthrough, so that you do not have to specify any additional
information for the control.
3. From the Navigation group in the Toolbox, drag a TreeView control onto the page.
4. On the TreeView Tasks menu, in the Choose Data Source box, click SiteMapDataSource1.
5. Save the page.
Testing the Tree Style Navigation Menu
You can now perform an interim test of your navigation system.
To test the navigation menu
1. Press CTRL+F5 to run the Home.aspx page.
The tree shows two levels of nodes.
2. Click Products to view the Products page.
If you did not create a Products.aspx page, click the link for a page that you did create.
In the current state of the Web site, the navigation menu appears only on the Home page. You could add the same
SiteMapDataSource and TreeView controls to each page in the application to display a navigation menu on each page.
However, later in this walkthrough, you will see how to place the navigation menu on a master page so that the navigation
menu automatically appears with every page.
Displaying Navigation History Using the SiteMapPath Control
Besides creating a navigation menu by using the TreeView control, you can add navigation on each page that displays where
the page is in the current hierarchy. This kind of navigation control is also known as a breadcrumb. ASP.NET provides the
SiteMapPath control that can automatically implement page navigation.
To display navigation history
1. Open the Products.aspx page and switch to Design view.
2. From the Navigation group in the Toolbox, drag a SiteMapPath control onto the page, place the cursor in front of the
SiteMapPath control, and then press ENTER to create a new line.
The SiteMapPath control displays the position of the current page in the page hierarchy. By default, the SiteMapPath
control represents the hierarchy that is created in the Web.sitemap file. For example, when you display the Products.aspx
page, the SiteMapPath control displays the following path:
Home > Products
3. Repeat this procedure for the other pages that you have created in this walkthrough, except the Home page.
Even if you do not put a SiteMapPath control on each page, for testing purposes you need a control on a page at each
level of the site hierarchy (for example, on the Products.aspx and Hardware.aspx pages).
Testing Navigation History
You can test page navigation by viewing pages that are at the second and third levels of the hierarchy.
To test page navigation
1. Open the Home.aspx page, and then press CTRL+F5 to run the page.
2. Use the TreeView control to move to the Products page.
At the location in the page where you put the SiteMapPath control, you see a path that is similar to the following:
Home > Products
3. Click Home to return to the Home page.
4. Use the TreeView control to move to the Hardware page.
This time you see a path that is similar to the following:
Home > Products > Hardware
All page names that are displayed by the SiteMapPath control are links, except the last one, which represents the current
page. You can make the current node into a link by setting the RenderCurrentNodeAsLink property of the SiteMapPath
control to true.
The SiteMapPath control lets users move back up the site hierarchy, but it does not allow for them to jump to a page that is
not in the current hierarchy path.
Creating a Navigation Menu Using the Menu Control
Besides creating a navigation menu by using the TreeView control, you can use the Menu control to display an expandable
navigation menu that lets users view one level of nodes at a time. Pausing the mouse pointer over a node that has child nodes
generates a submenu of the child nodes.
To add a menu-style navigation menu
1. Open the Products.aspx page and switch to Design view.
2. From the Navigation group in the Toolbox, drag a Menu control onto the page.
3. On the Menu Tasks menu, in the Choose Data Source box, click NewDataSource.
4. In the Configure Data Source — <Datasourcename> wizard, click Site Map, and then click OK.
5. Save the page.
Testing the Menu Style Navigation Menu
You can now perform an interim test of your navigation system.
You can now perform an interim test of your navigation system.
To test the navigation menu
1. Close Menu Tasks.
2. Open the Home.aspx.
3. Press CTRL+F5 to run the Home.aspx page.
The tree shows two levels of nodes.
4. Click Products to view the Products page.
If you did not create a Products.aspx page, click the link for a page that you did create.
5. On the navigation menu, rest the mouse pointer on the Home link to expand the menu.
In the current state of the Web site, the navigation menu appears only on the Home page. You could add the same
SiteMapDataSource and Menu controls to each page in the application to display a navigation menu on each page. However,
in the next section of this walkthrough, you will see how to put the navigation menu on a master page so that it automatically
appears with each page.
Combining Site Navigation with Master Pages
In the pages that you have created up to this point in this walkthrough, you have added site navigation controls individually to
each page. Doing this is not especially complex, because you do not have to configure the controls differently for each page.
However, it can add to the maintenance costs for your site. For example, to change the location of the SiteMapPath control for
pages in your site, you would have to change each page individually.
By using site navigation controls in combination with master pages, you can create a layout that contains the navigation
controls in one location. You can then display pages as content within the master page.
To create the master page for navigation
1. In Solution Explorer, right-click the name of the Web site, and then click Add New Item.
2. In the Add New Item <Path> dialog box:
a. Under Visual Studio installed templates, click Master Page.
b. In the Name box, type Navigation.master, and then click Add.
3. Switch to Design view.
The master page appears with a default ContentPlaceHolder control.
In the following procedure, you will create a master page with a simple layout for navigation controls. In a real application, you
would likely use more sophisticated formatting, but the techniques for using navigation controls on a master page will be
similar.
To add navigation controls to the master page
1. Click the title bar for the ContentPlaceHolder control, press LEFT ARROW, and then press SPACEBAR.
This inserts a blank line in front of the ContentPlaceHolder control.
2. From the Data group in the Toolbox, drag a SiteMapDataSource control onto the master page and position it above
the ContentPlaceHolder control.
Note
Do not position the SiteMapDataSource control on the ContentPlaceHolder control.

By default, the SiteMapDataSource control will use the Web.sitemap file that you created in "Creating a Site Map,"
earlier in this walkthrough.
3. Click the SiteMapDataSource control, press RIGHT ARROW, and then press SPACEBAR.
This inserts a blank line under the SiteMapDataSource control.
4. On the Layout menu, click Insert Table, and then insert a table that has one row, two columns, and a width of 100
percent.
5. From the Navigation group in the Toolbox, drag a TreeView control onto the left cell of the table.
6. On the TreeView Tasks menu, in the Choose Data Source box, click SiteMapDataSource1.
7. From the Navigation group in the Toolbox, drag a SiteMapPath control onto the right cell of the table.
8. In the right cell, click the blank area, and then press SHIFT+ENTER to create a new line.
9. Drag the ContentPlaceholder control onto the right cell of the table and position it under the SiteMapPath control.
When you are using a master page, you create the pages in your site as content pages. The content pages use Content
controls to define the text and controls that are displayed in the ContentPlaceholder control of the master page. Therefore,
you will have to re-create the Home, Products, and Hardware pages as content pages.
To create content pages for the site
1. In Solution Explorer, right-click the Home.aspx page, click Delete, and then click OK.
2. Repeat step 1 for the Products.aspx, Software.aspx, Training.aspx, and Hardware.aspx pages, and any other pages you
have created.
You will re-create the pages as content pages that use a master page.
3. In Solution Explorer, right-click the name of the Web site, and then click Add New Item.
4. In the Add New Item dialog box:
a. Under Visual Studio installed templates, click Web Form.
b. In the Name box, type Home.aspx.
c. Select the Select master page check box.
d. Click Add.
The Select a Master Page dialog box appears.
5. Under Contents of folder, click Navigation.master, and then click OK.
You have created a content page that is bound to the master page that you created in the preceding section.
6. Switch to Design view.
In Design view, you see the layout that you created for the master page, with an editable region in a Content1 control
corresponding to the ContentPlaceHolder1 control on the master page.
7. Click inside the Content window.
This is where you can add content for this specific page.
8. Type Home, and then format the text as Heading 1.
You have created the static text (specifically, the heading) for the Home page.
9. Repeat steps 3 through 8 to create a Products.aspx content page and a Hardware.aspx content page. In step 8, type
Products and Hardware, respectively, instead of Home.
Testing Navigation Controls in the Master Page
Testing with master pages and content pages is the same as testing individual pages.
To test navigation controls in the master page
1. Open the Products.aspx page, and then press CTRL+F5 to run the page.
The Products content page is merged with the master page. In the browser, you see a page that contains the Products
heading and the navigation controls that you added to the master page.
2. In the TreeView control, click Hardware.
The Hardware page is displayed with the same layout as the Products page, except that the SiteMapPath control
displays a different path.
Next Steps
This walkthrough illustrates the basic functionality of ASP.NET site navigation and the navigation controls. You might want to
experiment with additional features of navigation. For example, you might want to do the following:
Format the SiteMapPath control to customize its appearance. The control supports many options that manage how the
links are displayed. For more information, see SiteMapPath.
Customize the display of the pages in the TreeView control. For example, you might highlight the current page in the tree
view node.
Work programmatically with the site-navigation information. A SiteMapPath control is available on the current page,
which you can use to programmatically display navigation information.
Use a different data store for the site-map information. Instead of using the default XML site-map file, you might want to
use an existing site map or store site-map information in a database. ASP.NET site navigation uses a provider model. You
can create a component that manages site-map information, and then configure your application to use that component
instead of the default site-map provider. For more information, see ASP.NET Site Navigation Providers.
See Also
Tasks
Walkthrough: Creating a Basic Web Page in Visual Web Developer
Walkthrough: Creating and Using ASP.NET Master Pages in Visual Web Developer
Concepts
ASP.NET Site Navigation Overview
ASP.NET Site Maps
ASP.NET Master Pages Overview
Securing ASP.NET Site Navigation
Securing Data Access
Basic Security Practices for Web Applications (Visual Studio)
Other Resources
ASP.NET Application Security in Hosted Environments
Visual Web Developer

Walkthrough: Creating a Web Site with Membership and User


Login (Visual Studio)
A common requirement for Web sites is to allow only some members or other authenticated users to see certain pages. In that
case, the application must prompt the user for a name and password. The application must also include a way to hide
information from anonymous users (users who are not logged in). This walkthrough shows you how to use ASP.NET controls
and ASP.NET membership services to create an application that performs all these tasks. For more information, see
Introduction to Membership.
Tasks illustrated in this walkthrough include:
Configuring an application to include ASP.NET membership services, and how to define users.
Using login controls to get user credentials and to display information to logged-in users.
Protecting one or more pages in your application so that only logged-in users can view them.
Allowing new users to register at your site.
Allowing members to change and reset their passwords.
Prerequisites
In order to complete this walkthrough, you will need:
Microsoft Visual Web Developer.
Microsoft Internet Information Services (IIS) installed locally on your computer.
Microsoft Data Access Components (MDAC) version 2.7 or later. If you are using Microsoft Windows XP or Windows
Server 2003, you already have MDAC 2.7. However, if you are using Microsoft Windows 2000, you might to need to
upgrade the MDAC already installed on your computer. For more information, see the article "Microsoft Data Access
Components (MDAC) Installation" in the MSDN library.
Access to an e-mail server that can forward e-mail messages. (The server does not have to be able to receive messages.)
IIS includes the Default SMTP virtual server, a mail server that is suitable for this walkthrough. For more information
about configuring this server, see How to: Install and Configure SMTP Virtual Servers in IIS. If you are working on a local
area network, check with your network administrator for information about access to an e-mail server.
Creating the Web Site
If you have already created a Web site in Microsoft Visual Studio (for example, by working with the topic
Walkthrough: Creating a Basic Web Page in Visual Web Developer ), you can use that Web site and skip to "Configuring
Membership" later in this walkthrough. Otherwise, create a new Web site and page by following these steps.
To create a local IIS Web site
1. Open Visual Studio.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, select ASP.NET Web Site.
4. In the Location list box, select HTTP. Click Browse.
The Choose Location dialog box appears.
5. Select Local IIS.
6. Open Local Web Servers.
7. Select Default Web Site.
8. Click the Create New Web Application icon ( ) above the list of Web sites and then name the new Web site
membership.
9. Click Open.
The Choose Location dialog box closes.
10. In the Languages box, click the programming language you prefer to work in.
The programming language you choose will be the default for your Web site, but you can set the programming
languages for each page individually.
11. Click OK in the New Web Site dialog box.
Visual Web Developer creates the Web site and a new page named Default.aspx.
Configuring Membership
Later in this walkthrough you will put pages into a subdirectory that is protected. You must create the subdirectory now so that
you can configure security for it later in the walkthrough.
To add a new folder to the Web site
1. In Solution Explorer, right-click the name of your Web site and click New Folder.
2. Name the folder MemberPages.
Before you work with ASP.NET membership, you must configure your application to enable membership and to set up users.
You can use the Web Site Administration tool, which provides a wizard-like interface for making configuration settings.
For this walkthrough, you will define a single user.
To create a membership user
1. On the Website menu, click ASP.NET Configuration.
2. Select the Security tab, click the link to Use the security Setup Wizard to configure security step by step, and then
click Next.
3. Proceed to Step 2 of the wizard and select the From the Internet option.
The wizard displays a page where you can select the authentication method that your Web site will use. This option
specifies that your application will use Forms authentication, where users will log in to the application using a login page
that you will create later in this walkthrough.
4. Click Next.
The wizard displays a message stating that user information will be stored using Advanced provider settings. By
default, membership information is stored in a Microsoft SQL Server Express database file in the App_Data folder of
your Web site.
5. Click Next.
The wizard displays an option to create roles. You will perform this step separately later in the walkthrough. Therefore, do
not select the Enable roles for this web site check box.
6. Click Next.
The wizard displays a page where you can create new users.
7. Enter information that defines a user of your application. Use the following values as guidelines (you can use any values
that you like, but be sure to note your entries for later in the walkthrough):
User Name Your name (with no spaces), or a sample name.
Password A password. A strong password is required (one that includes uppercase and lowercase letters,
punctuation, and that is at least eight characters long).
E-mail Your personal e-mail address. Later in the walkthrough you will send yourself an e-mail message, so you
need a legitimate e-mail address.
Security Question and Security Answer Type a question and answer that can be used later if you need to
recover your password.
8. Click Create User.
The wizard displays a confirmation page.
Note
Leave the Web Site Administration tool open.

Earlier in the walkthrough you created a folder named MemberPages. In this part of the walkthrough, you will create a rule
that makes sure that only logged-in users can access pages in that folder.
To set up access rules for the MemberPages subdirectory
1. In the wizard, click Next.
The wizard displays a page that allows you to create access rules.
2. In the Add New Access Rule box, expand the node for your Web site.
3. Select MemberPages, the folder you created earlier.
4. Under Rule applies to, select Anonymous users.
5. Under Permission, select Deny.
The rule you are creating denies access to anonymous users — that is, users who have not logged in.
6. Click Add This Rule.
The new rule is displayed in the grid below. When users request a page from the MemberPages subdirectory, the rules
are checked to determine whether the user is allowed access to the page.
7. Click Finish.
You are now done with the wizard. The wizard closes and you are returned to the Security tab of the Web Site
Administration tool.
Configuring the Application for E-Mail
For part of this walkthrough, the application needs to be able to send e-mail messages. To send messages, your application
must have access to a Simple Mail Transport Protocol (SMTP) server, which forwards e-mail messages from your application to
an e-mail recipient.
IIS includes the Default SMTP virtual server as an optional component, which is suitable for this walkthrough. For more
information about configuring this server, see How to: Install and Configure SMTP Virtual Servers in IIS. If you are working on a
local area network, check with your network administrator for information about access to an e-mail server.
After you have set up or determined how to access an SMTP server, you must configure your application to route e-mail
messages to that server. You can do so by making an entry in your Web site's Web.config file, which contains a series of
settings that determine how your application runs.
To configure the application to use a specific SMTP server
1. In the Web Site Administration tool, click the Application tab.
2. Under SMTP Settings, click Configure SMTP e-mail settings.
The tool displays a page where you can configure e-mail.
3. If you are using the SMTP virtual server that is on your computer, enter localhost as the Server Name; otherwise, enter
the appropriate server name.
Include information for the port number and for authentication according to the requirements of your SMTP server. See
your administrator for more information on how to configure these settings.
4. In the From box, type a valid e-mail address.
5. Click Save, and in the confirmation page, click OK.
The Web Site Administration tool creates a Web.config file (if one did not already exist) with the settings you have made.
Note
The Web.config file will not appear in Solution Explorer until you refresh the view.

6. Close the Web Site Administration tool.


Logging the User In
As part of your application, you need to establish the user's identity so that the application can perform actions — such as
showing or hiding information — based on who the user is. To get the user's identity, you have the user log in.
In this walkthrough, you will add a link on the home page that takes users to a login page, and then you will create the login
page.
To create a home page with a login button
1. Open or switch to the Default.aspx page of your site. (If you do not have a Default.aspx page, you can add one or use a
different page.)
2. Switch to Design view.
3. Type static text such as Welcome to our site and, in the Formatting toolbar, use the Block Format drop-down list to
format the text as Heading 1.
4. From the Login group of the Toolbox, drag a LoginStatus control onto the page.
By default, the LoginStatus control is rendered as a link. When users click it, the application displays a login page. You can
now create the login page.
To create a login page
1. In Solution Explorer, right-click your Web application and select Add New Item. Add a Web Form named Login.aspx
to your site.
Note
For this walkthrough, the page must be named Login.aspx. By default, forms authentication is configured to work with
a page with this name. Although you will not do so in this walkthrough, you can change the default login page — the p
age to which users are redirected — in the Web.config file.

2. In the Login.aspx page, switch to Design view.


3. From the Login group of the Toolbox, drag a Login control onto the page.
The Login control is a single control that will prompt the user for credentials and validate them.
Displaying Login Errors
The Login control includes validation to help users enter correct information. For example, if a user skips the password, a
validator control displays an asterisk (*) next to the Password box. You can provide more complete information for login
errors by adding a ValidationSummary control to the page.
To display detailed login errors
1. From the Validation group of the Toolbox, drag a ValidationSummary control onto the page.
2. In the Properties window for the ValidationSummary control, set the ValidationGroup property to Login1, which is
the default ID of the Login control you added previously.
Displaying Information for Logged-In Users
You will now modify the home page to customize the display depending on whether the user is logged in. Anonymous users
will see a generic message inviting them to log in. Logged-in users will see a message that welcomes them by their logged-in
name.
To customize the display for logged-in users
1. Switch to or open the Default.aspx page.
2. From the Login group of the Toolbox, drag a LoginView control onto the page.
The LoginView control is displayed with its AnonymousTemplate template open. This template allows you to define
the content that users will see before they have logged in.
3. Click the edit area of the LoginView control to activate editing.
4. In the edit area of the LoginView control's AnonymousTemplate template, type You are not logged in. Click the
Login link to sign in.
5. On the LoginView Tasks panel, in the Views list, click LoggedInTemplate. If you do not see the LoginView Tasks
panel, right-click the heading of the LoginView control and select Show Smart Tag.
You are now defining the content that will be displayed to users who have already logged in.
6. Click the edit area of the LoginView control to activate editing, and then type You are logged in. Welcome,.
7. From the Login group of the Toolbox, drag a LoginName control into the template after the text.
Testing Login
You can now test the login capability of your application.
To test login
1. In Solution Explorer, right-click Default.aspx and click Set As Start Page.
This configures the Web site so that when you run the site, the Default.aspx page appears first.
2. Press CTRL+F5 to run the Web site.
The home page (Default.aspx) appears in the browser, showing the Login link and the generic message.
3. Click the Login link.
The login page you created is displayed.
4. Type the login name of the user you created earlier in the walkthrough, and then click Log In. (Do not yet enter a
password.)
An asterisk (*) is displayed next to the Password box, and an error message is displayed in the ValidationSummary
control.
5. Type both a user name and password and then click Log In.
If you entered correct credentials, you are returned to the home page. The page now displays a Logout link, your user
name, and the welcome message that you defined for the logged-in user.
6. Close the browser.
Limiting Access for Members-Only Pages
A typical task in many Web sites is to configure pages so that only logged-in users can view the pages. Earlier in the
walkthrough, you created the MemberPages subdirectory and created a rule that limits access to pages in the subdirectory. In
this section of the walkthrough, you will add a page to the protected subdirectory and test the access rule.
To create the members-only page
1. In Solution Explorer, right-click the MemberPages folder, click Add New Item, and add a new Web Form named
Members.aspx.
Note
Be sure to create the page in the MemberPages folder.

2. In Design view, add text to the page, such as Welcome, members! The exact text does not matter, as long as you will be
able to recognize this page when you see it in the browser.
You can now add a link to the members-only page from the home page. In a real application, you would probably put the
members-only page link in the logged-in template of the LoginView control. That way, visitors to your site would not see the
link until they were logged in. For this walkthrough, however, you will make the link available to all users so that you can see
the effect of trying to view a members-only page without first logging in.
To add a link to the members-only page
1. Switch to or open the Default.aspx page.
2. From the Standard group of the Toolbox, drag a HyperLink control onto the page.
3. In the Properties window for the HyperLink control, set the Text property to Members page and the NavigateUrl
property to ~/MemberPages/Members.aspx to point to the page that you created previously.
Testing the Members-Only Page
You can test the members-only page by accessing it both as an anonymous user and a logged-in user.
To test the members-only page
1. Press CTRL+F5 to run the Web site.
2. When the Default.aspx page appears in the browser, do not log in. Instead, click the Members page link.
You are redirected to the Login.aspx page because access to the members page is denied for anonymous users.
3. In the login page, type the user name and password that you used earlier in the walkthrough to log in.
You are redirected to the Members.aspx page because the user name you are logged in as has been authorized to access
the page.
4. Close the browser window.
Creating New Users
In the first part of the walkthrough, you created a user with the Web Site Administration tool. That strategy is useful if you are
working with a small, defined list of users; for example, if you are creating users for a small team. In many Web sites, however,
users are allowed to register themselves. ASP.NET includes the CreateUserWizard control that performs the same task you
performed earlier using the Web Site Administration tool.
In this part of the walkthrough, you will add a facility that allows users to register on your Web site. To start, you will create a
registration page.
To create a registration page
1. In Solution Explorer, right-click the name of your Web site, click Add New Item, and add a new Web Form named
Register.aspx.
Note
Be sure to create the page in the root of the Web site, not in the MemberPages folder.

2. In the Register.aspx page, switch to Design view and type static text such as Register into the page. In the Formatting
toolbar, use the Block Format drop-down list to format the text as Heading 1.
3. From the Login group of the Toolbox, drag a CreateUserWizard control onto the page.
4. In the Properties window for the CreateUserWizard control, set the ContinueDestinationPageUrl property to
~/Default.aspx.
This configures the control so that when users click Continue after creating a user, the control returns to the home page.
5. From the Standard group of the Toolbox, drag a HyperLink control onto the page. In the Properties window for the
HyperLink control, set the Text property to Home and the NavigateUrl property to ~/Default.aspx.
You can now add a link to the home page that displays the registration page. For this walkthrough, assume that you want to
display the registration link only to users who are not logged in.
To create a registration link on the home page
1. Switch to or open the Default.aspx page.
2. Right-click the LoginView control added previously, and select Show Smart Tag. In the LoginView Tasks panel, select
AnonymousTemplate from the Views list box to activate editing in the anonymous template.
3. From the Standard group of the Toolbox, drag a HyperLink control into the anonymous template. In the Properties
window for the HyperLink control, set the Text property to Register and the NavigateUrl property to Register.aspx.
The Register link will be displayed only to users who are not logged in.
You can now test the registration process.
To test registration
1. Press CTRL+F5 to run the Web site and display the Default.aspx page.
Because you are not logged in, the page containing the Register link is displayed.
2. Click the Register link.
The registration page is displayed.
3. In the text boxes, enter a new user name, a strong password, an e-mail address, and a security question and answer. (All
five pieces of information are required.)
4. Click Create User.
A confirmation message is displayed.
5. Click the Continue button.
You are returned to the home page as a logged-in user. Note that the Login link has changed to Logout and that the
information displayed in the Login control is from the LoggedInTemplate property, not from the AnonymousTemplate
property.
6. Click the Logout link.
The page changes to display the information for anonymous users.
7. Click the Login link.
8. Enter the credentials for the user you just created.
You are logged in as the new user.
9. Close the browser window.
Changing Passwords
Users sometimes might want to change their passwords, and it is often impractical to perform this task by hand. You can
therefore use another ASP.NET control to allow users to change passwords on their own. To change a password, users must
know their existing password.
In this walkthrough, you will add a page where logged-in users can change their password.
To create a password-change page
1. In Solution Explorer, right-click the MemberPages folder, click Add New Item, and add a new Web Form named
ChangePassword.aspx.
Note
Be sure to create the page in the MemberPages folder.

You are putting the page in the members-only folder because only logged-in users can change their passwords.
2. In the ChangePassword.aspx page, switch to Design view and type static text such as Change Password. In the
Formatting toolbar, use the Block Format drop-down list to format the text as Heading 1.
3. From the Login group of the Toolbox, drag a ChangePassword control onto the page.
4. In the Properties window for the ChangePassword control, set ContinueDestinationPageUrl property to
~/Default.aspx.
5. This configures the control so that when users click Continue after changing a password, the control returns to the
home page.
You can now add a link to the home page that displays the password-change page. You will make the link available only to
users who are logged in.
To create a password-change link on the home page
1. Switch to or open the Default.aspx page.
2. Right-click the LoginView control and then click Show Smart Tag. In the LoginView Tasks menu, in the Views list,
click LoggedInTemplate.
This switches the LoginView control to edit mode for the content that will appear to users who are logged in.
3. From the Standard group of the Toolbox, drag a HyperLink control into the editing region. In the Properties window
for the HyperLink control, set the Text property to Change password and the NavigateUrl property to
~/MemberPages/ChangePassword.aspx.
The Change password link will be displayed only to users who are logged in, which is the opposite of the Register link
you created earlier.
You can now test the password-change process.
To test password change
1. Press CTRL+F5 to run the Web site.
2. In the Default.aspx, page, click the Login link and log in as one of the users you have created.
When you are finished, you are returned to the home page as a logged-in user.
3. Click the Change password link.
4. In the password-change page, enter the old password and a new password, and then click Change Password.
5. Click Continue.
6. On the home page, click Logout.
7. Click the Login link.
8. Enter the new password.
You are logged in with the new password.
9. Close the browser window.
Recovering a Password
Users will occasionally forget their passwords. You can add a password recovery page to your Web site so that they can once
again log in to your site. Password recovery can take two forms:
You can send users the password they selected (or that you created for them when you set up the site). This option
requires that the site store the password using reversible encryption.
You can send users a new password, which they can change using the Change Password page you created earlier. This
option is useful if the Web site stores passwords using a non-reversible encryption scheme such as hashing.
Note
Returning a password in clear text using e-mail is not recommended for sites that require a high level of security. For high-se
curity sites, it is recommended that you return passwords using encryption, such as Secure Sockets Layer (SSL).
By default, the ASP.NET membership system secures passwords by hashing them, meaning that the passwords cannot be
recovered. Therefore, for this part of the walkthrough, your Web site will send users a new password.
Note
Password recovery requires that your Web site can send e-mail messages. If you are not able to configure your Web site to s
end e-mail (as explained under "Configuring the Application for E-Mail" earlier in this walkthrough), you will not be able to a
dd password recovery to your site.

To add password recovery


1. In Solution Explorer, right-click the name of your Web site, click Add New Item, and add a new Web Form named
RecoverPassword.aspx.
Note
Be sure to create the page in the root of the Web site, not in the MemberPages folder.

2. In the RecoverPassword.aspx page, switch to Design view and type static text such as Reset my password to a new
value. In the Formatting toolbar, use the Block Format drop-down list to format the text as Heading 1.
3. From the Login group of the Toolbox, drag a PasswordRecovery control onto the page.
4. From the Standard group of the Toolbox, drag a HyperLink control onto the page. In the Properties window for the
HyperLink control, set the Text property to Home and the NavigateUrl property to ~/Default.aspx.
5. Switch to the Default.aspx page.
6. Right-click the LoginView control and then click Show Smart Tag. In the LoginView Tasks menu, in the Views list,
click AnonymousTemplate.
This switches the LoginView control to edit mode for the content that will appear to users who are not logged in.
7. From the Standard group of the Toolbox, drag a HyperLink control into the template. In the Properties window for
the HyperLink control, set the Text property to Forgot your password? and the NavigateUrl property to
~/RecoverPassword.aspx.
Now you can test password recovery.
To test password recovery
1. Press CTRL+F5 to run the Web site.
2. By default, you are not logged in, so you see the anonymous template of the LoginView control.
3. Click the Forgot your password? link.
The RecoverPassword.aspx page appears.
4. Type your user name and click Submit.
The security question is displayed and you are prompted to type the security answer.
5. Type the answer and click Submit.
If you entered a correct answer, the Web site resets your password and sends you an e-mail message with the new
password.
Next Steps
This walkthrough has illustrated a simple but complete scenario for creating an application that prompts users for credentials,
displays information to logged-in users, allows users to recover a forgotten password, and limits access to pages. You can
create more sophisticated pages and applications using the techniques and controls illustrated in the walkthrough. For
example, you might want to:
Create additional users and define roles (groups) such as managers, sales, or members and assign users to different
roles. For details, see Walkthrough: Managing Web Site Users with Roles.
Change the membership provider from the default Access provider to a SQL provider. Storing membership information
in an Access database is suitable for small to medium-sized sites, but if your site will experience heavy traffic, you will
want to use Microsoft SQL Server as the membership store. For more information, see
Web Site Administration Tool Provider Tab and Creating the Application Services Database for SQL Server.
Change the appearance of login controls. The Login, PasswordRecovery, and CreateUserWizard controls all support
templates, which allows you to configure the text and buttons they contain as well as change the color, font, and other
appearance characteristics of the controls. For more information, see the topics in the Login ASP.NET Controls section.
Create rules that limit access to pages or folders not only for anonymous users, but for specific users or roles.
Combine membership with profile properties, which allows you to store user-specific settings for each user. For details,
see Walkthrough: Maintaining Web Site User Information with Profile Properties.
Combine login controls with master pages. Master pages allow you to define a page layout that you can use for all the
pages in your application. For details, see
Walkthrough: Creating and Using ASP.NET Master Pages in Visual Web Developer.
Add the ability to recover a forgotten password. For more information, see
How to: Enable User Password Recovery Using the ASP.NET PasswordRecovery Control.
See Also
Concepts
Introduction to Membership
Visual Web Developer

Walkthrough: Maintaining Web Site User Information with


Profile Properties
ASP.NET Profile properties allow your application to track and permanently store user-specific information. For example, users
can specify a postal code or a favorite color scheme, and your application can store that information and retrieve it from
anywhere in the application. ASP.NET automatically matches the current user — whether the user is anonymous or logged on
— with the personal information that is stored for their user account.
This walkthrough shows you how to add Profile properties to your application and use the Profile properties to create a
personalized experience for visitors to the Web site.
During this walkthrough, you will learn how to do the following:
Configure an application to use Profile properties.
Define simple and complex Profile properties that you want to maintain for users.
Set and retrieve Profile values in your application.
Use Profile properties that have both anonymous and logged-on users.
Prerequisites
In order to complete this walkthrough, you will need the following:
Microsoft Visual Web Developer.
The Microsoft .NET Framework.
Microsoft SQL Server Standard Edition.
The Profile property information that you create in the walkthrough will be stored in a SQL Server Standard Edition
database.
Cookies enabled on your browser.
Note
ASP.NET Profile properties can work without cookies, if the application is configured to work without cookies. Howeve
r, for this walkthrough you will use the default configuration settings for Profile properties, which use cookies.

Creating and Configuring the Web Site


If you have already created a Web site in Microsoft Visual Studio by completing
Walkthrough: Creating a Basic Web Page in Visual Web Developer, you can use that Web site and go to the next section.
Otherwise, create a new Web site by following these steps.
To create a file system Web site
1. Open Visual Studio.
2. On the File menu, point to New, and then click Web Site (or on the File menu, click New Web Site).
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the left-most Location list, click File System.
5. In the right-most Location list, enter the name of the folder where you want to keep the pages of the Web site.
For example, type the folder name C:\WebSites.
6. In the Language list, click the programming language that you prefer to work in.
7. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Configuring Profile Properties
Before you work with ASP.NET Profile properties, you will configure your application to enable and define the Profile
properties that you want to track for each user. To start, you will create a single PostalCode property that the Web site will
track for users. You will also configure the PostalCode property so that your site can track it for both anonymous and logged-
on users.
You will first work as an anonymous user. Behind the scenes, ASP.NET will assign you a unique, anonymous ID that is stored in
a cookie on the computer. ASP.NET can use this anonymous ID to set and get values that are unique to you.
To configure Profile properties in the Web site
1. In Solution Explorer, determine whether the Web site already has a Web.config file.
If the Web site does not have a Web.config file, follow these steps:
a. Right-click the name of the Web site.
b. Click Add New Item.
c. Under Visual Studio installed templates, click Web Configuration File.
d. Click Add.
A new file named Web.config is added to the site and is opened in the editor.
2. Add the following <profile> element to the Web.config file as a child of the <system.web> element:

<system.web>

<anonymousIdentification enabled="true" />


<profile>
<properties>
<add name="PostalCode"
type="System.String"
allowAnonymous="true" />
</properties>
</profile>

<!-- other Web.config settings here -->


</system.web>

Note
Elements in the Web.config file are case sensitive. Therefore, make sure that you copy or type the elements exactly as s
hown.

You have added the following elements:


The <anonymousIdentification> element, which specifies whether Profile properties work only with logged-on
(authenticated) users or with both logged-on and anonymous users.
In this case, you have set enabled to true. Therefore, Profile property information will be tracked for both logged-
on and anonymous users.
The <properties> element, which contains all Profile properties that you are defining.
The <add> element, which defines a new <profile> element.
In this case, you have defined a single Profile property named PostalCode.
When you define a Profile property, you specify its data type using a .NET Framework–type class name. You also
specify whether the Profile property will be tracked for anonymous users. After enabling anonymous
identification, you can additionally specify whether to track Profile properties individually for anonymous users.
You would create a new add element for each additional Profile property that you wanted to define.
Note
By default, user profile information is stored in a SQL Server Standard Edition database in the Application_Data s
ubdirectory of the Web site. This walkthrough uses the default configuration. In production applications that will s
upport a significant number of users, it is better to store Profile property data in a Microsoft SQL Server databas
e. For more information, see "Next Steps," later in this walkthrough.

Setting and Getting the PostalCode Property


After you have configured the Web site to track a Profile property, you can set and get the Profile property as you would
ordinary component properties. In this section, you will create a page that shows how to set and get the PostalCode value that
you defined in the preceding section.
To create a page to set and get the PostalCode property
1. Add a new Web page to your site named Profiles.aspx.
2. Open Profiles.aspx and switch to Design view.
3. From the Standard group in the Toolbox, drag the controls listed in the following table onto the page, and then set their
properties as noted.
Control Property settings
TextBox ID = textPostalCode

Button ID = SetPostalCode
Text = Set Postal Code

Label ID = labelPostalCode
Text = (empty)

4. Switch to Source view, and then add the following attribute to the SetPostalCode button, if the attribute does not exist.

OnClick="SetPostalCode_Click"

5. Create a Click handler for Set Postal Code, and then add the following highlighted code.
VB
Sub SetPostalCode_Click(ByVal sender As Object, _
ByVal e As System.EventArgs)
Profile.PostalCode = Server.HtmlEncode(textPostalCode.Text)
labelPostalCode.Text = Profile.PostalCode
End Sub

C#
void SetPostalCode_Click(object sender, System.EventArgs e)
{
Profile.PostalCode = Server.HtmlEncode(textPostalCode.Text);
labelPostalCode.Text = Profile.PostalCode;
}

When the user profile is enabled, ASP.NET dynamically creates a property named Profile that adds the user profile to the
current context. The individual Profile properties are then available through Profile.PostalCode.
6. Create a Page_Load handler, and then add the following highlighted code.
VB
Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
labelPostalCode.Text = Profile.PostalCode
End Sub

C#
void Page_Load(object sender, System.EventArgs e)
{
labelPostalCode.Text = Profile.PostalCode;
}

This code will display the Profile.PostalCode value every time that the page is requested.
Testing the PostalCode Profile Property
You can now test the PostalCode property that you defined in the preceding section.
Note
If you are working with an existing Web site that has membership enabled, make sure that you are logged off.

To test the PostalCode property


1. Press CTRL+F5 to run the Profiles.aspx page.
Note
If the browser displays a 502 error or an error indicating that the page cannot be displayed, you might need to configur
e your browser to bypass proxy servers for local requests. For detailed information, see
How to: Bypass a Proxy Server for Local Web Requests.

2. In the box, type a postal code, and then click Set Postal Code.
The postal code that you entered appears in the Label control.
3. Close the browser to close your current session.
4. Reopen the browser, and then request the Profiles.aspx page.
The postal code that you entered earlier appears in the Label control.
The last step in the preceding procedure illustrated that ASP.NET store the PostalCode value. When you visit the page again,
ASP.NET can read the PostalCode value based on your unique anonymous ID.
Defining Complex Properties
In "Setting and Getting the PostalCode Property," earlier in this walkthrough, you created a simple property named
PostalCode that was stored as a string. In this section, you will define a property named FavoriteURLs that is a collection.
ASP.NET can store Profile properties of any type, but you must provide additional information when you are defining the
Profile property.
To define the FavoriteURLs property
1. Open the Web.config file.
2. Add the following highlighted element to the profile element that you created in "Configuring Profile Properties," earlier
in this walkthrough:

<anonymousIdentification enabled="true" />


<profile>
<properties>
<add name="PostalCode"
type="System.String"
allowAnonymous="true" />
<add name="FavoriteURLs"
type="System.Collections.Specialized.StringCollection"
allowAnonymous="true" />
</properties>
</profile>

You have added a new Profile property named FavoriteURLs. For Profile properties that are not simple types (such as
string or integer), you must specify the fully qualified type. Here, you are specifying that the Profile property will be a
collection that will hold strings.
3. Save, and then close the Web.config file.
Setting and Getting the FavoriteURLs Property
Working with the FavoriteURLs property, which is a collection, is much like working with a collection in any context. In this
part of the walkthrough, you will update the Profiles.aspx page that you created in "Setting and Getting the PostalCode
Property," earlier in this walkthrough, by adding a TextBox control in which users can type a URL. When the user clicks Add,
the URL is added to the FavoriteURLs property. You will also display the current list of favorite URLs in a drop-down list box.
To set and get the FavoriteURLs property
1. On the Profiles.aspx page, add the following controls and set their properties as noted in the following table.
Control Property settings
TextBox ID = textFavoriteURL

Button ID = AddURL
Text = Add URL

ListBox ID = listFavoriteURLs

2. Switch to Source view, and then add the following attribute to the Add URL button, if the attribute does not exist.

OnClick="AddURL_Click"

3. Create a Click handler for Add URL, and then add the following highlighted code.
VB
Sub AddURL_Click(ByVal sender As Object, _
ByVal e As System.EventArgs)
Dim urlString As String = _
Server.HtmlEncode(textFavoriteURL.Text)
If Profile.FavoriteURLs Is Nothing Then
Profile.FavoriteURLs = New _
System.Collections.Specialized.StringCollection
End If
Profile.FavoriteURLs.Add(urlString)
DisplayFavoriteURLs()
End Sub

C#
void AddURL_Click(object sender, System.EventArgs e)
{
String urlString = Server.HtmlEncode(textFavoriteURL.Text);
if(Profile.FavoriteURLs == null)
{
Profile.FavoriteURLs = new
System.Collections.Specialized.StringCollection();
}
Profile.FavoriteURLs.Add(urlString);
DisplayFavoriteURLs();
}

4. In the Page_Load handler, add the following highlighted line of code.


VB
Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
labelPostalCode.Text = Profile.PostalCode
DisplayFavoriteURLs()
End Sub

C#
void Page_Load(object sender, System.EventArgs e)
{
labelPostalCode.Text = Profile.PostalCode;
DisplayFavoriteURLs();
}

5. Add the following subroutine to update the display of the URLs in the ListBox control.
VB
Sub DisplayFavoriteURLs()
listFavoriteURLs.DataSource = Profile.FavoriteURLs
listFavoriteURLs.DataBind()
End Sub

C#
void DisplayFavoriteURLs()
{
listFavoriteURLs.DataSource = Profile.FavoriteURLs;
listFavoriteURLs.DataBind();
}

Testing the FavoriteURLs Profile Property


You can now test the FavoriteURLs property.
To test the FavoriteURLs property
1. To run the Profiles.aspx page, press CTRL+F5.
At first there are no values in the ListBox control.
2. In the box, type a URL, and then click Add.
The URL is added to the ListBox control.
3. Repeat the preceding step to add another URL.
4. Close the browser.
5. Reopen the browser, and then open the Profiles.aspx page.
Notice that the ListBox control is populated with the URLs that you entered before closing the browser.
Migrating Profile Properties During Log On
If a user first visits your site as an anonymous user, but then logs on, you might want to preserve the property settings that the
user established when anonymous. A typical example is a shopping site where the user might browse and add items to a
shopping cart as an anonymous user, but then log on to check out. To preserve a user's values when they log on, you migrate
the user from the current anonymous user profile to the user profile that they have as a logged-on user (authenticated).
In this section, you will migrate the user's PostalCode setting. You must have a Web site that is already configured to use user
identities and that has a logon page. If the Web site that you are working with has not already been configured for
membership, use the following procedure to enable it. If your site already supports membership, you can go to the next
section.
To configure the Web site for membership
1. In Visual Studio, on the Website menu, click ASP.NET Configuration.
The Web Site Administration Tool appears.
2. Click the Security tab.
3. Click Security, and then under Users, click Select authentication type.
4. Select From the internet, and then click Done.
The From the internet option specifies that your application will use Forms authentication, where users will log on to
the application by using a logon page.
5. On the Security tab, under Users, click Create user, and then create a user account.
You can use any name and password, but make sure that you remember the name and password. For the e-mail address,
use your own. (You will not be sending e-mail messages in this walkthrough.)
6. After finishing the user account definition, close the Web Site Administration Tool.
7. From the Login group in the Toolbox, drag a Login control and a LoginName control onto the page.
The LoginName control is not required for log on, but will help you see that you are logged on.
Creating a Migrating Handler
To migrate the settings for an anonymous user to the settings for a logged-on user, you must perform the migration when the
user's identity is changing. ASP.NET provides the MigrateAnonymous event for exactly this purpose; in the handler for the
MigrateAnonymous event, you can transfer the settings that you want to preserve.
To create a migration handler
1. In Solution Explorer, right-click the name of the Web site, and then click Add New Item.
2. Under Visual Studio installed templates, click Global Application Class, and then click Add.
You do not have to enter a name, because the file is always named Global.asax.
3. Type the following code to create a new handler for the MigrateAnonymous event.
VB
Sub Profile_MigrateAnonymous(ByVal sender As Object, _
ByVal e As ProfileMigrateEventArgs)
If Profile.GetProfile(e.AnonymousID).PostalCode <> "" Then
Profile.PostalCode = _
Profile.GetProfile(e.AnonymousID).PostalCode
End If
End Sub
C#
void Profile_MigrateAnonymous(Object sender,
ProfileMigrateEventArgs e)
{
if(Profile.GetProfile(e.AnonymousID).PostalCode != String.Empty)
{
Profile.PostalCode =
Profile.GetProfile(e.AnonymousID).PostalCode;
}
}

The code gets the user profile for the anonymous user and extracts the PostalCode value. Then, it gets the profile for the
new user identity and sets the equivalent value for that identity.
Testing Migration
In order to test migration, you will first make some settings as an anonymous user. Then, you will log on and see that the
values are preserved.
To test migration
1. Open the Profiles.aspx page, and then press CTRL+F5 to run it.
The LoginName control does not display anything, because you have not yet logged on.
2. If a postal code is not displayed on the page, type a new postal code, and then click Set Postal Code.
The postal code for your current anonymous identity is displayed on the page.
3. Log on, using the user name and password that you created in "Migrating Profile Properties During Log On," earlier in
this walkthrough.
The LoginName control displays your user name. The postal code that you entered as an anonymous user is still
displayed, because the postal code settings have been migrated to your logged-on user profile.
Next Steps
This walkthrough has illustrated the basic procedures for configuring and using Profile properties in Web applications. You
can use Profile properties for many purposes in your applications. The following list suggests additional areas where you
might want to work with Profile properties:
Group Profile properties together, because it is easier to work with Profile properties as a unit.
For example, you can organize Profile properties named Street, City, and PostalCode into a group named Address.
For detailed information, see Defining ASP.NET Profile Properties.
Create custom types, such as a shopping cart, that you manage with Profile properties.
For detailed information, see Defining ASP.NET Profile Properties.
Select a different profile provider.
For this walkthrough, you stored Profile values in a SQL Server Standard Edition database. In production applications
that will support a significant number of users, it is better to store Profile property data in a SQL Server database that
uses the SqlProfileProvider class.
For more information, see Web Site Administration Tool Provider Tab and
Creating the Application Services Database for SQL Server.
Alternatively, you can create a custom profile provider that stores information in a format and storage medium that you
code yourself.
For detailed information, see Implementing a Profile Provider.
See Also
Concepts
ASP.NET Profile Properties Overview
ASP.NET Profile Providers
Visual Web Developer

Walkthrough: Customizing a Web Site Using Themes in Visual


Studio
This walkthrough illustrates how to use themes to apply a consistent look to pages and controls in your Web site. A theme can
include skin files that define a common look for individual controls, one or more style sheets, and common graphics for use
with controls, such as the TreeView control. This walkthrough shows you how to work with ASP.NET themes in your Web sites.
Tasks illustrated in this walkthrough include:
Applying predefined ASP.NET themes to individual pages and to your site as a whole.
Creating your own theme that includes skins, which are used to define the look of individual controls.
Prerequisites
In order to complete this walkthrough, you will need:
Microsoft Visual Web Developer (Visual Studio).
The .NET Framework.
Creating the Web Site
If you have already created a Web site in Visual Web Developer (for example, by following the steps in
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and go to the next section.
Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, enter the name of the folder where you want to keep the pages of your Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click the programming language you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
To begin your work with themes in this walkthrough, you will set up a Button control, a Calendar control, and a Label control,
so you can see how these controls are affected by themes.
To place controls on the page
1. Switch to Design view.
2. From the Standard group of the Toolbox, drag a Calendar control, a Button control, and a Label control to the page.
The exact layout of the page is not important.
Note
Do not apply any formatting to any of the controls. For example, do not use the AutoFormat command to set the look
of the Calendar control.

3. Switch to Source view.


4. Be sure that the <head> element of the page has the runat="server" attribute so that it reads as follows:
<head runat="server"></head>

5. Save the page.


To test the page, you will want to see the page before a theme is applied, and then with different themes.
Creating and Applying a Theme to a Page
ASP.NET makes it easy to apply a predefined theme to a page, or to create a unique theme. (For details, see
How to: Define ASP.NET Themes.) In this part of the walkthrough, you will create a theme with some simple skins, which define
the appearance of controls.
To create a new theme
1. In Visual Web Developer, right-click the name of your Web site, click Add ASP.Net Folder, and then click Theme.
The folder named App_Themes and a subfolder named Theme1 are created.
2. Rename the Theme1 folder sampleTheme.
The name of this folder will be the name of the theme that you create (here, sampleTheme). The exact name is not
important, but you must remember it when you apply your custom theme.
3. Right click the sampleTheme folder, select Add New Item, add a new text file, and name it sampleTheme.skin.
4. In the sampleTheme.skin file, add skin definitions as shown in the following code example.

<asp:Label runat="server" ForeColor="red" Font-Size="14pt" Font-Names="Verdana" />


<asp:button runat="server" Borderstyle="Solid" Borderwidth="2px" Bordercolor="Blue" Ba
ckcolor="yellow"/>

Note
The exact characteristics that you define are not important. The values in the preceding selection are suggestions that w
ill be more obvious when you test the theme later.

The skin definitions are similar to the syntax for creating a control, except that the definitions include only settings that
affect the appearance of the control. For example, the skin definitions do not include a setting for the ID property.
5. Save the skin file, and then close it.
You can now test the page before any themes are applied.
Note
If you add a cascading style sheet (CSS) file to your sampleTheme folder, it will be applied to all pages that use the theme.

To test themes
1. Press CTRL+F5 to run the page.
The controls are displayed with their default appearance.
2. Close the browser, and then return to Visual Web Developer.
3. In Source view, add the following attribute to the @ Page directive:

<%@ Page Theme="sampleTheme" ... %>

Note
You must indicate the name of an actual theme in the attribute value (in this case, the sampleTheme.skin file you define
d previously).
4. Press CTRL+F5 to run the page again.
This time, the controls are rendered with the color scheme defined in your theme.
The Label and Button controls will appear with the settings you made in the sampleTheme.skin file. Because you did not
make an entry in the sampleTheme.skin file for the Calendar control, it is displayed with its default appearance.
5. In Visual Web Developer, set the theme to the name of another theme, if available.
6. Press CTRL+F5 run the page again.
The controls change appearance again.
Style Sheet Themes vs. Customization Themes
After you have created your theme, you can tailor how it is used in your application by associating it with your page as either a
customization theme (as done in the previous section), or as a style sheet theme. A style sheet theme uses the same theme files
as a customization theme, but its precedence within the page's controls and properties is lower, equivalent to a CSS file. Within
ASP.NET, the order of precedence is:
Theme settings, including themes set in your Web.config file.
Local page settings.
Style sheet theme settings.
In this regard, if you choose to use a style sheet theme, your theme's properties will be overridden by anything declared locally
within the page. Similarly, if you use a customization theme, your theme's properties will override anything within the local
page, and anything within any style sheet theme in use.
To use a style sheet theme and see order of precedence
1. Switch to Source view.
2. Change the page declaration:

<%@ Page theme="sampleTheme" %>

to a style sheet theme declaration:

<%@ Page StyleSheetTheme="sampleTheme" %>

3. Press CTRL+F5 to run the page.


Note that the ForeColor property of the Label1 control is red.
4. Switch to Design view.
5. Select Label1 and, in Properties, set ForeColor to blue.
6. Press CTRL+F5 to run the page.
The ForeColor property of Label1 is blue.
7. Switch to Source view.
8. Change the page declaration to declare a theme, rather than a style sheet theme, by changing:

<%@ Page StyleSheetTheme="sampleTheme" %>

back to:

<%@ Page Theme="sampleTheme" %>

9. Press CTRL+F5 to run the page.


The ForeColor property of Label1 is again red.
Basing a Custom Theme on Existing Controls
An easy way to create skin definitions is to use the designer to set appearance properties, and then copy the control definition
to a skin file.
To base a custom theme on existing controls
1. In Design view, set properties of the Calendar control so that the control has a distinctive look. The following settings are
suggestions:
BackColor Cyan
BorderColor Red
BorderWidth 4
CellSpacing 8
Font-Name Arial
Font-Size Large
SelectedDayStyle-BackColor Red
SelectedDayStyle-ForeColor Yellow
TodayDayStyle-BackColor Pink
Note
The exact characteristics that you define are not important. The values in the preceding list are suggestions that will be
more obvious when you test the theme later.

2. Switch to Source view and copy the <asp:calendar> element and its attributes.
3. Switch to or open the sampleTheme.skin file.
4. Paste the Calendar control definition into the sampleTheme.skin file.
5. Remove the ID property from the definition in the sampleTheme.skin file.
6. Save the sampleTheme.skin file.
7. Switch to the Default.aspx page, and drag a second Calendar control onto the page. Do not set any of its properties.
8. Run the Default.aspx page.
Both Calendar controls will appear the same. The first Calendar control reflects the explicit property settings that you
made. The second Calendar control inherited its appearance properties from the skin definition that you made in the
sampleTheme.skin file.
Applying Themes to a Web Site
You can apply a theme to an entire Web site, which means you do not need to reapply the theme to individual pages. (If you
want, you can override the themes settings on a page.)
To set a theme for a Web site
1. Create a Web.config file if one was not automatically added to your Web site by following these steps:
a. In Solution Explorer, right-click the name of your Web site, and then click Add New Item.
b. Under Templates, select Web Configuration File, and then click Add.
Note You do not need to type a name, because the file is always named Web.config.
2. Add the <pages> element if it does not already exist. The <pages> element should appear inside the <system.web>
element.
3. Add the following attribute to the <pages> element.

<pages theme="sampleTheme" />

Note
Web.config is case-sensitive and the values are camel-cased. (For example: theme and styleSheetTheme).

4. Save and close the Web.config file.


5. Switch to Default.aspx and switch to Source view.
6. Remove the theme="themeName" attribute from your page declaration.
7. Press CTRL+F5 to run Default.aspx.
The page is now displayed with the theme you specified in the Web.config file.
If you choose to specify a theme name in your page declaration, it will override any theme specified in your Web.config file.
Next Steps
ASP.NET support for themes gives you a variety of options for tailoring the look and feel of an entire application. This
walkthrough covered some of the basics, but you might be interested in learning more. For example, you might want to learn
more about:
Using themes in general. For more information, see ASP.NET Themes and Skins Overview
Creating your own themes and skins. For more information, see How to: Define ASP.NET Themes
Using themes with code. For more information, see How to: Apply ASP.NET Themes Programmatically
See Also
Concepts
ASP.NET Themes and Skins Overview
Visual Web Developer

Walkthrough: Displaying and Tracking Advertisements with


the AdRotator Control
Web sites frequently display advertisements or similar dynamic content that invites users to visit another site. ASP.NET
provides the AdRotator control, which simplifies this task. The AdRotator control displays a graphic representing an ad,
randomly selecting the ad from a list that you create. You can then track how frequently an ad is viewed and how frequently
users click it.
This walkthrough illustrates how to use the AdRotator control to display ads and provides a simple way to track ad responses.
Tasks illustrated in this walkthrough include the following:
Creating a list of ads to display.
Displaying ads on a page.
Creating a way to track the number of times an ad is clicked.
Displaying statistics about ad clicks.
Prerequisites
In order to complete this walkthrough, you will need the following:
Microsoft Visual Web Developer Web development tool.
The .NET Framework.
A general understanding of working in Visual Web Developer. For an introduction, see
Walkthrough: Creating a Basic Web Page in Visual Web Developer.
Creating the Web Site
If you have already created a Web site in Visual Web Developer by completing
Walkthrough: Creating a Basic Web Page in Visual Web Developer, you can use that Web site and go to the next section.
Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, click File System, and then type the name of the folder where you want to keep the pages of the
Web site.
For example, type the folder name C:\WebSite.
5. In the Languages list, click the programming language that you prefer to work in.
The programming language that you choose will be the default for your Web site, but you can set the programming
language for each page individually.
6. Click OK.
Visual Studio creates the folder and a new page named Default.aspx.
Creating Advertisements
Ads are graphics that are displayed on the page with a target URL; when users click the graphic, they are redirected to the
target site. Therefore, you need graphics files to serve as advertisements.
Note
Later sections of this walkthrough assume that are you using graphics that are named according to the following procedure.
If you use existing graphics, make sure that you substitute the appropriate file names later in the walkthrough.

Start by creating a folder in the Web site to store graphics.


To create an Images folder
1. In Solution Explorer, right-click the name of the Web site, click New Folder, and then name the folder Images.
2. If you have existing graphics to use as ads, copy them to the new folder. Otherwise, follow the next procedure to create
some images.
If you already have some graphics that you can use to represent ads, you can use those. Otherwise, the following procedure
suggests one way that you can create graphics that are suited for this walkthrough.
To create graphics to serve as ads
1. In Microsoft Windows, open Paint.
2. On the Image menu, click Attributes.
3. In the Attributes dialog box, set Width to 250 and Height to 50, and then click OK.
4. From the Toolbox, drag the text tool onto the graphic, and then type some text that will help you identify the ad
5. In the <Websitename>\Images folder, save the graphic as <Websitename>\Images\Contoso_ad.gif.
6. Create a second graphic, and then save it as <Websitename>\Images\ASPNET_ad.gif.
7. Close Paint.
Creating a List of Ads
As soon as you have graphics for the ads, you must create a list of ads that the AdRotator control can read. The list is in the
form of an XML file.
To create an XML file of ads
1. In Solution Explorer, right-click App_Data, and then click Add New Item.
Note
When you put the XML file into the App_Data folder, the file automatically has the correct permissions to allow ASP.NE
T to read the file at run time. Putting the XML file in the App_Data folder helps to protect the file from being viewed in a
browser, because the App_Data folder is marked as nonbrowsable.

2. Under Visual Studio installed templates, click XML File.


3. In the Name box, type Sample.ads.
Note
Use the .ads extension.

4. Click Add.
A new XML file is created that contains only the XML directive.
5. Copy the following XML into the file, overwriting the XML directive.

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


<Advertisements>
<Ad>
<ImageUrl>~/images/Contoso_ad.gif</ImageUrl>
<NavigateUrl>http://www.contoso.com</NavigateUrl>
<AlternateText>Ad for Contoso.com</AlternateText>
</Ad>
<Ad>
<ImageUrl>~/images/ASPNET_ad.gif</ImageUrl>
<NavigateUrl>http://www.asp.net</NavigateUrl>
<AlternateText>Ad for ASP.NET Web site</AlternateText>
</Ad>
</Advertisements>

Note
If your graphics files have different file names, change the names in the <ImageUrl> elements accordingly.

This XML file contains <Ad> elements for two advertisements corresponding to the two graphics files that you have
created. In a real application, the URLs in the <NavigateUrl> elements would refer to the advertisers' Web sites.
Note
Additional elements are available for defining ads. For detailed information, see AdvertisementFile.

6. Save the file, and then close it.


Displaying Ads on the Page
You will now configure a Web page to display the ads that you have created. In the following procedure, you will bind an
AdRotator control to an XmlDataSource control. However, when using a static XML file, a data source control is not required,
because the XML file can be set directly with the AdvertisementFile property of the AdRotator control.
To display ads on the page
1. If you created a new Web site for this walkthrough, open the Default.aspx page.
2. If you are using a Web site that existed before you started this walkthrough, add a new page by following these steps:
a. In Solution Explorer, right-click the name of the Web site (for example, C:\WebSites), and then click Add New Item.
b. Under Visual Studio installed templates, click Web Form.
c. In the Name box, type TestAds.aspx.
d. Click Add.
3. Open TestAds.aspx and switch to Design view.
4. From the Standard group in the Toolbox, drag an AdRotator control onto the page.
The AdRotator Tasks shortcut menu appears.
5. In the Choose Data Source list, click New data source.
The Data Source Configuration wizard appears.
6. Under Where will the application get data from, click XML File.
7. In the Specify an ID for the data source box, leave the default, (XmlDataSource1).
8. Click OK.
The Configure Data Source dialog box appears.
9. In the Data file box, enter ~/App_Data/Sample.ads, and then click OK.
Alternatively, you can use Browse to locate the file:
a. In the Select XML File dialog box, in the Files of type list, click All Files (*.*).
b. Under Project Folders, click App_Data.
c. Under Contents of Folder, click Sample.ads, click OK, and then click OK.
10. From the Standard group in the Toolbox, drag a Button control onto the page.
Note
The exact layout of the page is not important.

The Button control is on the page only so that you have a convenient way to post back the page to the server.
Now you will test the ads.
To test the ads
1. Press CTRL+F5 to run the page.
One of the two ads appears on the page.
2. Click Button several times to cause the page to post back.
The ad that appears randomly varies.
Note
Because there are only two ads, you might have to click Button several times before you see a different ad.

3. Click an ad.
You are redirected to the target page for that ad.
4. Close the browser.
Tracking Ad Responses
At this point, your page just displays ads that users can click to jump to another page. In this part of the walkthrough, you will
add functionality to keep track of how many times users click the ads. You will change the URL of the ads in the Sample.ads file
to send the ad response to a redirection page, with information in the query string that identifies the ad and the ultimate
destination.
You will then create a second XML file to store ad counter information. In a production Web site, you should not use an XML
file to track ad clicks, because the XML file would not support much traffic. However, for purposes of this walkthrough, you will
use an XML file for convenience, so that you do not have to configure database access. Additionally, in a production application,
you would probably want more sophisticated click tracking, such as making sure that you are tracking unique visitors, tracking
time and date information about clicks, and so on. Nevertheless, the overall strategy of using a redirection page to process
clicks is the same regardless of how you choose to track the data.
Finally, you will create the redirection page, where you will accumulate counters for different ads, and then redirect again to the
target page that the ad is intended to display.
To redirect ads to a tracking page
1. Open the Sample.ads file.
2. Set NavigateUrl to include the following:
The name of your redirection page (AdRedirector.aspx).
An identifier for each ad.
The page to which the ad ultimately points.
The following code listing shows the Sample.ads XML file updated with URLs that specify the AdRedirector.aspx page.
The ad identifier and target page are specified as a query string.
Note
Because the ampersand (&) is a reserved character in XML, the query string includes the entity reference &amp; instea
d.

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


<Advertisements>
<Ad>
<ImageUrl>~/images/Contoso_ad.gif</ImageUrl>
<NavigateUrl>AdRedirector.aspx?ad=Widgets&amp;target=http://www.contoso.com/widget
s/</NavigateUrl>
<AlternateText>Ad for Contoso.com</AlternateText>
</Ad>
<Ad>
<ImageUrl>~/images/ASPNET_ad.gif</ImageUrl>
<NavigateUrl>AdRedirector.aspx?ad=ASPNET&amp;target=http://www.asp.net</NavigateUr
l>
<AlternateText>Ad for ASP.NET Web site</AlternateText>
</Ad>
</Advertisements>

3. Save the Sample.ads file, and then close it.


The next step is to create the XML file where you store counter information for the ad clicks. In a production Web site, you
would not need this step, because you would write information to a database instead. Using an XML file in this walkthrough
simplifies the steps that are required to track ad responses.
To create the XML file for tracking ad response
1. In Solution Explorer, right-click the App_Data folder, and then click Add New Item.
2. Under Templates, click XML File.
3. In the Name box, type AdResponses.xml, and then click Add.
A new XML file is created that contains only the XML directive.
4. Copy the following XML into the file, overwriting the XML directive.

<?xml version="1.0" standalone="yes"?>


<adResponses>
<ad adname="Widgets" hitCount="0" />
<ad adname="ASPNET" hitCount="0" />
</adResponses>

The file contains elements that have two pieces of information, the ID of an ad and a counter.
Note
If you assigned different IDs to the ads in the Sample.ads file in the previous procedure when you created the query stri
ngs, make sure that the IDs in the AdResponses.xml file match those.

5. Save the file, and then close it.


Note
Whether ASP.NET has Write permission for the XML file depends on which Web server you use. In this walkthrough, yo
u will use the ASP.NET Development Server, which is included with Visual Web Developer and has write access to the X
ML file. If you were using Microsoft Internet Information Services (IIS), the IIS Web server worker process may not have
write access to the XML file and you would have to explicitly set the Write permission. For more information on Web se
rvers in Visual Web Developer, see Web Servers in Visual Web Developer.
Now you will create the redirection page, which captures information about the ad that was clicked, updates the counter for the
ad, and then sends the request on to the page that is associated with the ad.
To create a Page_Load handler
1. In Solution Explorer, right-click the name of the Web site (for example, C:\WebSites), and then click Add New Item.
2. Under Visual Studio installed templates, click Web Form.
3. In the Name box, type AdRedirector.aspx, and then click Add.
This creates the page to which all ads will be directed when users click them. The page will not be displayed to users.
Therefore, you will not put any controls on it.
4. In Design view, double-click the page to create a Page_Load handler.
5. Copy the following code into the handler (do not overwrite the skeleton handler declaration).
VB
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles M
e.Load

Dim adName As String = Request.QueryString("ad")


Dim redirect As String = Request.QueryString("target")
If (adName Is Nothing Or redirect Is Nothing) Then
redirect = "TestAds.aspx"
End If

Dim doc As System.Xml.XmlDocument


Dim docPath As String = "~/App_Data/AdResponses.xml"

doc = New System.Xml.XmlDocument()


doc.Load(Server.MapPath(docPath))
Dim root As System.Xml.XmlNode = doc.DocumentElement
Dim xpathExpr As String
xpathExpr = "descendant::ad[@adname='" & adName & "']"
Dim adNode As System.Xml.XmlNode = _
root.SelectSingleNode(xpathExpr)
If adNode IsNot Nothing Then
Dim ctr As Integer = _
CInt(adNode.Attributes("hitCount").Value)
ctr += 1
Dim newAdNode As System.Xml.XmlNode = _
adNode.CloneNode(False)
newAdNode.Attributes("hitCount").Value = ctr.ToString()
root.ReplaceChild(newAdNode, adNode)
doc.Save(Server.MapPath(docPath))
End If
Response.Redirect(redirect)

End Sub

C#
protected void Page_Load(object sender, EventArgs e)
{
String adName = Request.QueryString["ad"];
String redirect = Request.QueryString["target"];
if (adName == null | redirect == null)
redirect = "TestAds.aspx";
System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
String docPath = @"~/App_Data/AdResponses.xml";
doc.Load(Server.MapPath(docPath));
System.Xml.XmlNode root = doc.DocumentElement;
System.Xml.XmlNode adNode =
root.SelectSingleNode(
@"descendant::ad[@adname='" + adName + "']");
if (adNode != null)
{
int ctr =
int.Parse(adNode.Attributes["hitCount"].Value);
ctr += 1;
System.Xml.XmlNode newAdNode = adNode.CloneNode(false);
newAdNode.Attributes["hitCount"].Value = ctr.ToString();
root.ReplaceChild(newAdNode, adNode);
doc.Save(Server.MapPath(docPath));
}
Response.Redirect(redirect);
}

The code reads the ad ID and URL from the query string. It then uses XML methods to read the AdResponse.xml file into
an XmlDocument object. The code locates the appropriate XML element using an XPath expression, extracts the
hitCounter value, and then updates the hitCounter value. Next, the code creates a copy of the XML element by cloning,
replaces the old element with the new one, and then writes the updated XML document back to disk. Finally, the code
redirects to the URL for the ad.
You will now test to confirm that the ad counters for the ads are working.
To test ad response tracking
1. Open the page that contains the AdRotator control, and then press CTRL+F5.
2. Click the ad.
You are redirected to the target page for that ad.
3. In the browser, click Back to return to the ad page.
4. Either click the ad again or click Button to display a different ad, and then click the ad.
5. Continue until you have clicked each ad at least one time, and one or more ads more than one time.
6. Close the browser.
7. In Visual Web Developer, open the AdResponse.xml file and verify that the counters for the ads reflect the number of
clicks from your test.
8. Close the AdResponse.xml file.
Displaying Ad Counter Data
For the final part of the walkthrough, you will create a page that displays the ad counter information, which is more convenient
than manually examining the XML file.
To create a page to display the ad response data
1. In Solution Explorer, right-click the name of the Web site, and then click Add New Item.
2. Under Visual Studio installed templates, click Web Form.
3. In the Name box, type ViewAdData.aspx.
4. Click Add.
5. Switch to Design view.
6. From the Data group in the Toolbox,, drag an XmlDataSource control onto the page.
7. On the XmlDataSource Tasks shortcut menu, click Configure Data Source.
The Configure Data Source <Datasourcename> dialog box appears.
8. In the Data file box, type ~/App_Data/AdResponses.xml.
Alternatively, you can use Browse to locate the file.
9. Click OK.
10. From the Data group in the Toolbox, drag a GridView control onto the page.
11. On the GridView Tasks shortcut menu, in the Choose Data Source list, click XmlDataSource1.
12. Press CTRL+F5 to run the page.
The page displays the ad response data in a grid.
13. Close the browser.
Next Steps
There are more features available in the AdRotator control than have been illustrated in this walkthrough. You might want to
explore these features in the following ways:
Use additional attributes when you create ads in the XML file.
For example, you can use the Impressions element to control how often an advertisement is selected relative to the
other advertisements in the advertisement file. The higher the value, the more likely the ad will be selected. For detailed
information, see AdvertisementFile.
Use a database to track ad responses.
Note
In a production application, do not use an XML file to track ad responses, because it will not scale to support many user
s. This walkthrough uses an XML file for ad responses only to simplify the walkthrough and to make is to that you do n
ot have to configure a database.

Track additional information about ad clicks.


You might want to make sure that you are tracking unique visitors, perhaps by writing a cookie to the browser, if the user
has clicked the ad within the last day, or by tracking the IP address of the browser when you store click information. You
might also aggregate click information by date and time, and perhaps track ad information according to other dynamic
content on the source page, which can help you analyze traffic patterns.
Bind the AdRotator control to its data using a different data source control.
For example, you can store advertisement data in a database. If you do, you can add a data source control to the page
and configure it to use a query to obtain advertisement data. You can then bind the AdRotator control to the data source
control. For detailed information, see How to: Display Ads From a Database Using the AdRotator Web Server Control.
See Also
Reference
AdRotator Web Server Control Overview
Visual Web Developer

Walkthrough: Creating and Using an ASP.NET Web Service in


Visual Web Developer
In addition to letting you create Web pages, Microsoft Visual Studio also lets you create Web services that use ASP.NET XML.
Creating a Web service in Visual Studio is similar to creating a Web page. You can also use the Microsoft Visual Web Developer
Web development tool to reference and use Web services that are in a Visual Web Developer solution, on your local computer
or in a local or external UDDI directory. In this walkthrough, you will create the Web service in one solution and use it in
another.
Tasks illustrated in this walkthrough include:
Creating a simple XML Web service in Visual Web Developer.
Creating a separate Web site that uses the Web service.
Prerequisites
In order to complete this walkthrough, you will need:
Microsoft Internet Information Services (IIS) installed locally on your computer.
Creating a Web Service Under the IIS Root
Create a new Web service and page by following these steps.
Note
You must use an IIS Web site for this walkthrough.

To create a Web service


1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Service.
4. Click Browse.
5. Click Local IIS.
6. Click Default Web Site.
7. Click Create New Web Application.
Visual Web Developer creates a new IIS Web application.
8. Type the name TemperatureWebService.
9. Click Open.
The New Web Site dialog box appears, with the name of the new Web site in the rightmost Location list. The location
includes the protocol (http://) and location (localhost). This indicates that you are working with a local IIS Web site.
10. In the Language list, click the programming language that you prefer to work in.
The programming language that you choose will be the default for the Web site. However, you can use more than one
language in the same Web application by creating pages and components in different programming languages. For
more information about how to create components using different languages, see
Shared Code Folders in ASP.NET Web Sites.
11. Click OK.
Visual Web Developer creates the new Web service and opens a new class named Service, which is the default Web
service. However, in the following procedure you will create a new Web service with a specified name and you will not
use the Service class.
12. Close the Service class.
Creating the Web Service
You will create a Web service that converts temperature from Fahrenheit to Celsius and vice versa.
To create the Web service
1. In Solution Explorer, right-click the Web site name (http://localhost/TemperatureWebService), and then click Add New
Item.
2. Under Visual Studio installed templates, click Web Service, and then in the Name box, type Convert.
3. Make sure that the Place code in separate file check box is selected, and then click Add.
Visual Web Developer creates a new Web service that is made up of two files. The Convert.asmx file is the file that can be
invoked to call Web service methods, and it points to the code for the Web service. The code itself is in a class file
(Convert.vb, Convert.cs, or Convert.jsl, depending on the programming language) in the App_Code folder. The code file
contains a template for a Web service. The code file includes some code for a Web service method.
You will create two methods in the Web service. The first method converts Fahrenheit temperatures to Celsius, and the second
method converts Celsius temperatures to Fahrenheit.
To create the conversion methods
1. Add the following code inside the class, after the HelloWorld method:
VB
<System.Web.Services.WebMethod()> _
Public Function FahrenheitToCelsius(ByVal Fahrenheit As Double) _
As Double
Return ((Fahrenheit - 32) * 5) / 9
End Function

<System.Web.Services.WebMethod()> _
Public Function CelsiusToFahrenheit(ByVal Celsius As Double) _
As Double
Return ((Celsius * 9) / 5) + 32
End Function

C#
[System.Web.Services.WebMethod()]
public double FahrenheitToCelsius(double Fahrenheit)
{
return ((Fahrenheit - 32) * 5) / 9;
}

[System.Web.Services.WebMethod()]
public double CelsiusToFahrenheit(double Celsius)
{
return ((Celsius * 9) / 5) + 32;
}

Notice that the function names are preceded with an attribute ([System.Web.Services.WebMethod()] or
<System.Web.Services.WebMethod()>) as part of the function declaration.
2. After you have entered the functions, save the file.
Now, you can test the Web service in Visual Web Developer.
To test the Web service
1. In Solution Explorer, click Convert.asmx, and then press CTRL+F5.
The Web service is invoked and a page appears in the browser that shows the methods that are exposed by the Web
service.
2. Click CelsiusToFahrenheit, which invokes that method.
A page appears that prompts you for parameter values for the CelsiusToFahrenheit method.
3. In the Celsius box, type 100, and then click Invoke.
A new window appears that displays the XML that the Web service returns when the CelsiusToFahrenheit method is
invoked. The value 212 appears in the XML.
4. Close the browser that contains the method results.
5. In the original browser, click Back to return to the list of methods.
6. Click FahrenheitToCelsius and test to make sure that the method is returning the results that you expect.
If you type 212, the FahrenheitToCelsius method will return 100.
7. Close the browser.
You have finished creating the Web service; the next step is to use it.
Using the Web Service
Now that you have a Web service, you will create a Web site where you will reference and use the Web service that you
created. For the walkthrough, you will create a separate Web site that has a page where you start the Web service methods that
you just created.
To create a Web site to use the Web service
1. On the File menu, click New Web Site.
2. Under Visual Studio installed templates, click ASP.NET Web Site.
3. Click Browse.
4. Click Local IIS.
5. Click Default Web Site.
6. Click Create New Web Application.
Visual Web Developer creates a new IIS Web application.
7. Type the name TemperatureWeb.
8. Click Open.
9. In the Language list, click the programming language that you prefer to work in.
10. Click OK.
Visual Web Developer creates a new local IIS Web site and a new page named Default.aspx.
Adding the Web Service as a Component
The Web service is a component that you can reference in your application. Therefore, you must create a reference to it.
To create a reference to the Web service
1. In Solution Explorer, right-click the name of the Web site, and then click Add Web Reference.
The Add Web Reference dialog box appears, as shown in the following screen shot.
Add Web Reference dialog box

2. In the URL list, enter the following URL for the Web service, and then click Go:
http://localhost/TemperatureWebService/Convert.asmx
When Visual Web Developer finds the Web service, information about the Web service appears in the Add Web
References dialog box.
Note
If you cannot add a reference to a Web service, it might be that the proxy server is not configured correctly. In Microsof
t Internet Explorer, on the Tools menu, click Internet Options, click Connections, and then click LAN Settings. Select
the Bypass proxy server for local addresses check box. Additionally, set the proxy server address to the exact name
of the proxy server instead of allowing Internet Explorer to detect the proxy server. For more information, contact the n
etwork administrator.

3. Click one of the method links.


The test page for the method appears.
4. Click Add Reference.
Visual Web Developer creates an App_WebReferences folder and adds a folder to it for the new Web reference. By
default, Web references are assigned a namespace corresponding to their server name (in this case, localhost). Make a
note of the name for the Web reference namespace. In the folder, Visual Web Developer adds a .wsdl file that references
the Web service. It also adds supporting files, such as discovery (.disco and .discomap) files, that include information
about where the Web service is located.
Note
If the server name for the Web service contains characters that cannot be used for a class name, such as a hyphen (-), V
isual Web Developer converts those characters to an underscore character (_). Therefore, the namespace in Visual Web
Developer for the Web service might not match the server name exactly.

You can now use the Web service. In this walkthrough, you will add controls to Default.aspx, and then program the controls to
convert a specified temperature to both Fahrenheit and Celsius. When the page is running, it will look something like the
following illustration.
Temperature conversion page
To call the Web service methods
1. Open the Default.aspx page and switch to Design view.
2. From the Standard group in the Toolbox, drag the following controls onto the page and set their properties as indicated:
Control Properties
Textbox ID: TemperatureTextbox
Text: (empty)

Button ID: ConvertButton


Text: Convert

Label ID: FahrenheitLabel


Text: (empty)

Label ID: CelsiusLabel


Text: (empty)

3. Optionally, add text to the page for captions.


For this walkthrough, the layout of the page is not important.
4. Double-click ConvertButton to create an event handler for its Click event.
5. Make sure your event handler code matches the code in the following example.
VB
Dim wsConvert As New localhost.Convert()
Dim temperature As Double
temperature = System.Convert.ToDouble(TemperatureTextbox.Text)
FahrenheitLabel.Text = "Fahrenheit To Celsius = " & _
wsConvert.FahrenheitToCelsius(temperature).ToString()
CelsiusLabel.Text = "Celsius To Fahrenheit = " & _
wsConvert.CelsiusToFahrenheit(temperature).ToString()

C#
protected void ConvertButton_Click(object sender, EventArgs e)
{
localhost.Convert wsConvert = new localhost.Convert();
double temperature =
System.Convert.ToDouble(TemperatureTextbox.Text);
FahrenheitLabel.Text = "Fahrenheit To Celsius = " +
wsConvert.FahrenheitToCelsius(temperature).ToString();
CelsiusLabel.Text = "Celsius To Fahrenheit = " +
wsConvert.CelsiusToFahrenheit(temperature).ToString();
}

6. Press CTRL+F5 to run the page.


7. In the text box, type a value, such as 100, and then click Convert.
The page displays the result of converting the temperature value into both Fahrenheit and Celsius.
Debugging the Web Service
You can debug a Web service in the same way that you debug Web pages.
Note
Visual Web Developer Express edition and Visual Studio Standard edition do not support stepping into a Web service from a
page that references it. If you are using Visual Web Developer Express edition or Visual Studio Standard edition, skip this sect
ion and the ones following. For more information about how to debug Web sites, see
Walkthrough: Debugging Web Pages in Visual Web Developer.

To start, you must configure the Web site that contains the Web service to enable debugging.
To enable debugging in the Web services Web site
1. On the File menu, click Open Web Site.
2. Click Local IIS.
3. Click TemperatureWebService, and then click Open.
4. On the Website menu, click ASP.NET Configuration to open the Web Site Administration Tool.
Note
If this is the first time that you have run the Web Site Administration Tool, there might be some delay before it appears.

5. Click Application, and then click Application Configuration.


6. Under Debugging and Tracing, click Configure debugging and tracing.
7. Select the Enable debugging check box.
The Web Site Administration Tool creates a Web.config file for the Web site and sets a configuration option to enable
debugging.
Note
To see the Web.config file in Solution Explorer, click the Web site name and then, on the Solution Explorer toolbar, click
Refresh.

8. Close the Web Site Administration Tool.


You must now enable debugging for the Web site that uses the Web service.
To enable debugging in the Web site
1. Open the TemperatureWeb site.
2. On the Website menu, click ASP.NET Configuration to open the Web Site Administration Tool.
3. Click Application, click Application Configuration, under Debugging and Tracing, click Configure debugging
and tracing, and then select the Enable debugging check box.
4. Close the Web Site Administration Tool.
Note
To see the Web.config file in Solution Explorer, select the Web site name and then, on the Solution Explorer toolbar, clic
k Refresh.

5. In Solution Explorer, right-click Default.aspx, and then click View Code.


Visual Web Developer opens the code file for the page.
6. Position the pointer in the following line:
VB
temperature = System.Convert.ToDouble(TemperatureTextbox.Text)

C#
double temperature =
System.Convert.ToDouble(TemperatureTextbox.Text);

7. Press F9 to set a breakpoint on the line.


Testing Debugging
Both the Web site and the Web service are configured for debugging, so that you can now try debugging. You will start in the
Default.aspx page and step through the code until the code invokes the Web service. The debugger will switch to the Web
service and continue stepping through the code.
To debug the page and Web service
1. Press F5 to run the Default.aspx page with debugging.
The page appears in the browser.
2. In the box, type a value, such as 100, and then click Convert.
Visual Web Developer starts running the code for the page, but stops and highlights the line with the breakpoint on it.
3. Press F11 to step to the next line.
4. Press F11 again.
Because the next line invokes the Web service, the debugger steps into the Web service, stopping on the first line of the
FahrenheitToCelsius method.
5. Continue pressing F11.
The debugger steps through the rest of the method, and then returns to the calling page. If you continue stepping, the
debugger will step back into the Web service and into the CelsiusToFahrenheit method.
6. Close the browser, which also closes the debugger.
Next Steps
This walkthrough has illustrated the basic principles of creating a very simple Web service and using it in an ASP.NET
application. You might want to experiment with additional, more complex Web service features. Suggestions for additional
exploration include the following:
Understand the processing that occurs when you make an XML Web service call.
For more information, see Anatomy of an XML Web Service Lifetime.
Understand how to use XML Web services.
For more information, see XML Web Service Scenarios.
Create XML Web services that offer more sophisticated functionality than the simple Web service from this walkthrough.
You can create and chain asynchronous Web service method calls, use transactions, secure the Web services, configure
Web services for Microsoft Windows authentication, and so on.
For more information, see XML Web Services Using ASP.NET.
Learn about language-specific and technology-specific features provided by the XML Web services.
For more information, see XML Web Services in Visual FoxPro,
Introduction to Programming XML Web Services in Managed Code, Web Services (How Do I in Visual Basic),
XML Web Services Created with ATL Server, and Creating and Accessing XML Web Services Walkthroughs.
See Also
Tasks
Walkthrough: Debugging Web Pages in Visual Web Developer
Reference
@ WebService Directive in XML Web Services
<webServices> Element
Concepts
Design Guidelines for XML Web Services Created Using ASP.NET
Securing XML Web Services Created Using ASP.NET
Other Resources
Guided Tour of Creating Web Sites in Visual Web Developer
XML Web Services Using ASP.NET
Visual Web Developer

Walkthrough: Creating Web Pages for Mobile Devices


Mobile development in ASP.NET does not differ much from traditional ASP.NET browser-based Web development. ASP.NET
exposes a System.Web.Mobile namespace devoted specifically to Web development. You can create a Web page from the
MobilePage base class and add controls from the System.Web.Mobile namespace.
Mobile development follows the standard .NET Framework event-driven model in which your application responds to user
requests, button clicks, and so on.
In this walkthrough, you will create two Web pages that inherit from the MobilePage class and that are designed for a mobile
device. The first page will have a mortgage calculator that you can use to determine loan information. The second page
displays data in a format that is easy to page through on a small device. Tasks illustrated in this walkthrough include:
Creating an ASP.NET Web page that displays output on a device such as a mobile phone.
Adding paging so that users with small devices can move effectively through long lists.
Testing pages with a device emulator.
Prerequisites
To complete this walkthrough, you will need:
Ability to run the page on a device such as a mobile phone. Alternatively, you can use one of a number of emulators. In
this walkthrough, it is assumed that you have an emulator and that it is available on the same computer as your Web
server.
Note
You can run this walkthrough even if you have only a desktop browser. However, an emulator will more directly allow
you to see the functionality of the controls you will use in this walkthrough.

Access to Microsoft Internet Information Services (IIS) and permission to create a new application in IIS. It is
recommended that you use a local copy of IIS for the pages in the application, which makes it easiest to test the
application with your emulator. However, if you cannot create an application using IIS, you might still be able to use an
emulator with the Microsoft Visual Web Developer Web server. For details, see the "Next Steps" section at the end of this
walkthrough.
Creating the Web Site
If you have already created a Web site in Visual Web Developer (for example, by following the steps in
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and skip to the next section,
"Creating the Mortgage Calculator." Otherwise, create a new Web site and page by following these steps.
To create a new local IIS Web site under the IIS root
1. Open Visual Web Developer.
2. On the File menu, choose New, and then choose Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, select ASP.NET Web Site.
4. Click Browse.
The Choose Location dialog box appears.
5. Click the Local IIS tab.
6. Select Default Web Site.
7. Click the Create New Web Application button.
A new application is added under Default Web Site.
8. In the box for the new Web site, type DeviceWalkthrough and then click Open.
You are returned to the New Web Site dialog box with the Location box filled in with
http://localhost/DeviceWalkthrough.
9. In the Language list, select the programming language you prefer to work in.
The programming language you choose will be the default for your Web site. However, you can use multiple languages
in the same Web application by creating pages and components in different programming languages.
10. Click OK.
Visual Web Developer creates the new Web site and opens a new page named Default.aspx.
Creating the Mortgage Calculator
For the walkthrough, you will create a page that inherits from the MobilePage class and that contains a simple mortgage
calculator. The calculator prompts the user to enter a loan amount, a loan term in years, and the interest rate. The calculator can
determine the monthly payment for that loan.
In this walkthrough, you will use controls from the System.Web.Mobile namespace that are specifically designed for devices
that cannot display as much information as a desktop browser. Instead, the controls present information in separate views that
users can switch between.
To begin, you will delete the Default.aspx page and create a mobile page in its place.
To add a mobile page
1. Right-click the Default.aspx page in Solution Explorer and choose Delete.
2. Click OK in the dialog box.
3. Right-click the application in Solution Explorer and choose Add New Item.
4. Choose Mobile Web Form under Visual Studio installed templates.
5. Name the mobile Web page MobileCalculator.aspx and then click Add.
A Web page that inherits from the MobilePage class is created and added to your Web site.
Now that you have a mobile page, you will add controls that allow users to enter mortgage information.
To add controls for entering mortgage information
1. In the MobileCalculator.aspx page you created in the last procedure, make sure you are in Design view.
You will see a Form control with the default name of form1.
2. From the Mobile Web Forms folder of the Toolbox, drag controls onto form1 and set their properties as noted in the
following table.
Control Property settings
Label ID = HeadingLabel
Text = Loan Calculator

TextBox ID = PrincipalText
Text = Principal

TextBox ID = TermText
Text = Term in Years

TextBox ID = RateText
Text = Annual Rate
Command ID = Calculate
Text = Calculate

After you have created the Form where users enter their loan information, you will create another Form that will show the
results.
To create a form to display mortgage calculation results
1. From the Mobile Web Forms folder of the Toolbox, drag a Form control to the design surface.
The Form control is assigned the default ID of Form2.
2. From the Mobile Web Forms folder of the Toolbox, drag controls onto Form2 and set their properties as noted in the
following table.
Control Property settings
Label ID = LoanDetailsLabel
Text = Loan Details

Label ID = PaymentLabel
Text = Payment

Command ID = ReturnToCalculator
Text = Return to Calculator

You can now create the code that will calculate the loan information and display it.
To calculate the mortgage information and display results
1. If you are using C#, add a reference to the Microsoft.VisualBasic namespace so you can use the Pmt method to calculate
the payment information. Follow these steps:
a. In Solution Explorer, right-click the Web site name and choose Property Pages.
b. Click Add Reference.
c. In the .NET tab, select Microsoft.VisualBasic.dll and then click OK.
d. In the Property Pages dialog box, click OK.
2. In the form1 control, double-click the Calculate button to create a Click event handler, and then add the following code.
VB
Protected Sub Calculate_Click(ByVal sender As Object, _
ByVal e As EventArgs)

' Get values from the form


Dim principal As Double = Convert.ToDouble(PrincipalText.Text)
Dim apr As Double = Convert.ToDouble(RateText.Text)
Dim monthlyInterest As Double = apr / (12 * 100)
Dim termInMonths As Double = Convert.ToDouble(TermText.Text) * 12
Dim monthlyPayment As Double

' Calculate the monthly payment


monthlyPayment = Microsoft.VisualBasic.Financial.Pmt( _
monthlyInterest, termInMonths, -principal, 0, _
DueDate.BegOfPeriod)

' Change to the other form


Me.ActiveForm = Me.form2

' Display the resulting details


Dim detailsSpec As String = "{0} @ {1}% for {2} years"
LoanDetailsLabel.Text = String.Format(detailsSpec, _
principal.ToString("C0"), apr.ToString(), TermText.Text)
PaymentLabel.Text = "Payment: " & monthlyPayment.ToString("C")
End Sub

C#
protected void Calculate_Click(object sender, EventArgs e)
{
// Get values from the form
Double principal = Convert.ToDouble(PrincipalText.Text);
Double apr = Convert.ToDouble(RateText.Text);
Double monthlyInterest = (Double)(apr / (12 * 100));
Double termInMonths = Convert.ToDouble(TermText.Text) * 12;
Double monthlyPayment;

// Calculate the monthly payment


monthlyPayment = Microsoft.VisualBasic.Financial.Pmt(
monthlyInterest, termInMonths, -principal, 0,
Microsoft.VisualBasic.DueDate.BegOfPeriod);

// Change to the other form


this.ActiveForm = this.form2;

// Display the resulting details


string detailsSpec = "{0} @ {1}% for {2} years";
LoanDetailsLabel.Text = String.Format(detailsSpec,
principal.ToString("C0"), apr.ToString(), TermText.Text);
PaymentLabel.Text = "Payment: " + monthlyPayment.ToString("C");
}

The code gathers the values from the text boxes, converts them to appropriate data types, and then uses them as
parameters for the Visual Basic Pmt function to calculate the monthly cost of the mortgage. (You can use the Visual Basic
function in any language as long as you fully qualify the function call with the namespace.) After calculating the monthly
amount, the code switches to the second Form control and displays the results in the respective Label controls.
3. In the Form2 control, double-click the Command control to create a Click event handler, and then add the following
highlighted code.
VB
Protected Sub ReturnToCalculator_Click(ByVal sender As Object, _
ByVal e As EventArgs)

Me.ActiveForm = Me.form1
End Sub

C#
protected void ReturnToCalculator_Click(object sender, EventArgs e)
{
this.ActiveForm = this.form1;
}
Testing the Calculator
You are now ready to test the calculator. You can test the calculator in a desktop browser. However, a more interesting test is to
use your device emulator.
To test the calculator
1. Press CTRL+F5 to see your page in the default browser, and to get the exact URL.
The first form appears on the page.
2. Start your emulator and connect to the URL for your page.
3. When the page appears in the emulator, enter a loan amount of 100000, the number of years as 30, and a percentage
rate of 5, and then click Calculate.
The calculator is replaced by the results view, with the result 534.59.
Adding Pagination
Many devices have small display areas, making it impractical to display long lists. ASP.NET provides an ObjectList control
designed for mobile devices that can automatically display an entire screen of information at one time and provide links so
that users can move forward and backward in the list.
In this section of the walkthrough, you will create a data listing that displays more information than can be shown on one
screen of even a desktop browser. By adding an ObjectList control, you will automatically add paging capability to the output,
appropriately sized to the browser the user has.
The first thing you need to do is create a mobile Web Forms page and add an ObjectList control to it.
To add a mobile Web Forms page and create an ObjectList control on it
1. Right-click the application in Solution Explorer and choose Add New Item.
2. Choose Mobile Web Form under Visual Studio installed templates.
3. Name the page MobilePaging.aspx and then click Add.
A Web page that inherits from the MobilePage class is created and added to your project. The page includes a Form
control named form1 on it. You can only use controls in the System.Web.Mobile namespace on a page that inherits
from the MobilePage class.
4. From the Mobile Web Forms folder of the Toolbox, drag an ObjectList control to the design surface and place it on
form1.
An ObjectList control is added to your page. It shows a generic set of data that gives you an idea of what the control will
look like when it is rendered on the client.
After the ObjectList control is created, you need to create data that will populate the control.
To create the data
1. In the MobilePaging.aspx page, switch to Design view and double-click the empty design surface to create an empty
event handler for the page Load event.
2. In the empty handler, add the following code.
VB
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As EventArgs)

' Create and fill an array of strings


Dim listItems(25) As String

Dim i As Integer
For i = 0 To 24
listItems(i) = _
String.Format("This is item {0}.", i)
Next

' Bind the ObjectList to the Items


Me.ObjectList1.DataSource = listItems
Me.ObjectList1.DataBind()
End Sub

C#
protected void Page_Load(object sender, EventArgs e)
{
// Create and fill an array of strings
string[] listItems = new string[25];
for (int i = 0; i < 25; i++)
listItems[i] =
String.Format("This is item {0}.", i);

// Bind the ObjectList to the Items


this.ObjectList1.DataSource = listItems;
this.ObjectList1.DataBind();
}

The code creates an array of string objects and populates it with strings. It then binds that array to the ObjectList control.
You can now test the page.
To test the page
1. Press CTRL+F5 to run the page.
The page is displayed with a long list of numbered items.
2. Start your device emulator and type in the URL of the page (http://localhost/DeviceWalkthrough/paging.aspx).
Notice that the data is displayed in a long list.
Adding Paging
Now that you have a page that displays data, you can add paging so that the display is automatically sized to the size of the
screen in the device.
To add paging
1. In the MobilePaging.aspx page, switch to Design view and then select form1.
2. In the Properties window, set the Paginate property to true.
3. Select the ObjectList control and, in the Properties window, set the ItemsPerPage property to 5.
You can now test paging.
To test paging
1. Press CTRL+F5 to run the page in Internet Explorer.
The page is displayed with a page of data and a navigation control.
2. Use the Next and Previous links to move through the data.
3. In your device emulator, enter the URL of the page.
The emulator displays a page of data (five items). If necessary, you can scroll the page up or down.
4. Use the links to move to other pages showing more items.
Next Steps
In this walkthrough, you have created a page that is tailored to devices by taking advantage of controls that are designed for
devices with limited display areas. ASP.NET and Visual Web Developer include facilities for creating applications for a wide
range of devices and browsers.
You also might want to explore the following aspects of devices:
Depending on what emulator you use, you might be able to integrate the emulator into Visual Web Developer. In
Solution Explorer, right-click the mortgage calculator page and choose Browse With. Click Add and type the information
for your emulator to add it to the list of browsers. You can then use the Browse With command to view a page in the
emulator. Note that not all emulators are supported.
See Also
Concepts
ASP.NET Mobile Web Development Overview
Architectural Overview of Adaptive Control Behavior
ASP.NET Device Filtering Overview
Visual Web Developer

Walkthrough: Using Resources for Localization with ASP.NET


An effective way to create localized Web pages is to use resources for your page's text and controls based on the user's
language and culture. By using properties placed in resource objects, ASP.NET can select the correct property at run time
according to the user's language and culture. The process is straightforward:
A resource file (.resx) stores values.
In your page, you indicate that controls should use resources for their property values.
At run time, the controls' property values are derived from the resource file.
Note
In practice, you can store values in custom resources objects, such as a database. However, in this walkthrough you will
use a .resx file to store values.

Visual Web Developer allows you to generate resources for controls, control properties, and HTML for your controls without
writing any code.
Tasks illustrated in this walkthrough include:
Enabling localization of ASP.NET pages.
Generating a resource file and implicitly associating its values with the controls in your application.
Creating localization resource files and explicitly referencing them in your pages by using declarative expressions.
Prerequisites
In order to complete this walkthrough, you will need:
Visual Web Developer (Visual Studio).
The .NET Framework.
Creating a Web Site
If you have already created a Web site in Visual Web Developer (see
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and go to the next section,
"Implicit Localization with ASP.NET." Otherwise, create a new Web site and page by using the steps in the following procedure.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, enter the name of the folder where you want to keep the pages of your Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click the programming language you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Implicit Localization with ASP.NET
In this section, you will work with implicit localization. In implicit localization, you specify that control properties should
automatically be read from a resource file, but you do not need to explicitly specify which properties are localized. Then, you
create a resource file with localized values for specific properties. At run time, ASP.NET examines the controls on the page. If
the control is marked to use implicit localization, ASP.NET looks through the resource file for the page. If it finds property
settings for the marked control, ASP.NET substitutes the values in the resource file for those in the control.
In this example of implicit localization, you use a combination of the designer and the Resource Editor to generate a default
resource file that you will use as a starting point for localization in two languages. Visual Web Developer will generate a
resource file based only on the controls on your page. For this reason, it is a good idea to generate the resource file after you
have completed your page's control layout, including simple controls such as buttons, labels, and text boxes.
To place controls on a page
1. In Solution Explorer, right-click Default.aspx, click Rename, and then type Sample.aspx.
Doing this will help avoid confusion in the rest of the walkthrough with regard to default resource files because implicit
resource file names use page names.
2. Open Sample.aspx, and then switch to Design view.
3. In the Toolbox, from the Standard section, drag a Button, a Label, and a TextBox control onto the page.
4. For each control, set Text to English Button, English Label, and English TextBox, respectively.
After creating the page and adding the controls, you can use a Visual Web Developer command to generate a local resource
file for this page. The local resource file will contain the resource strings for the controls on the page. Visual Web Developer
generates a resource string for each property that is designated internally in the control as localizable. Each control can have
different properties designated as localizable, although most text-based properties are marked that way.
To automatically generate a resource file
1. Click the designer surface or a control.
2. On the Tools menu, click Generate Local Resource.
Visual Web Developer creates a new folder named App_LocalResources, and within the App_LocalResources folder, a
new file named Sample.aspx.resx. If you named your page something other than Sample.aspx, the .resx file will reflect
whatever name you chose. When using implicit localization, resource file names are based on individual page names.
3. Switch to Source view to see the changes to your control declarations.
Visual Web Developer has added an attribute to your controls to retrieve their values from your newly created resource
file. For example, the Button control's markup has a new meta:resourcekey attribute.

<asp:Button ID="Button1" Runat="server" meta:resourcekey="ButtonResource1" Text="Engli


sh Button" />

When a browser sends a request to Web server, the request can include information about the current language and culture.
For example, a browser might send the string "en-us" to indicate it has been set to use United States English; another browser
might send the string "en-gb" to indicate it has been set to use British English.
Note
The language and culture settings in a browser request are not a completely reliable way to detect the user's preferred langu
age. The settings indicate only what the browser has been set to send or has inherited from the underlying operating system.
For this walkthrough, you will rely on the language and culture settings, but in a production application you should also inclu
de a way for users to select a language and culture manually.

The resource file is used as the default resource file for all requests. (It is the resource file for the fallback culture.) If no culture
is specified by the browser, or if the browser request includes a language or culture that you do not support, resource values
are pulled from this default file.
Now that the resource file is created, you can place localized text within it by using the Resource Editor.
To edit the resource file by using the Resource Editor
1. In Solution Explorer, open Sample.aspx.resx.
In the Resource Editor, under Value, are the Text properties for each of the controls that you placed onto your page.
Changing the value here will change the value for the default culture.
2. Set ButtonResource1.Text to Edited English Text.
3. Save the file.
Now you can test the page.
To test the page
Press CTRL+F5 to run the page.
The text you provided in the Resource Editor is shown as the label for Button1. When using implicit localization, syntax
properties in resource files will override properties specified in the page itself.
Adding Other Cultures
Each language and culture combination requires a unique resource file. To add other cultures, you can use your default file as a
starting point. You can create resource files for different cultures and locales by creating new resource files in which the ISO
language codes are part of the file name (for example, en-us, fr-ca, and en-gb). These ISO codes are placed between the page
name and the .resx file name extension, as in Sample.aspx.en-us.resx. To specify a culturally neutral language, you would
eliminate the country code, such as Sample.aspx.fr.resx for the French language.
Note
When using implicit localization syntax, you must create a separate series of resource files for each page.

To create a culturally neutral French language file


1. In Solution Explorer, right-click the Sample.aspx.resx file, and then click Copy.
2. Right-click the App_LocalResources folder, and then click Paste.
Visual Web Developer creates a file named Copy of Sample.aspx.resx.
3. Right-click the Copy of Sample.aspx.resx file, click Rename, and then type Sample.aspx.fr.resx.
Sample.aspx.fr.resx indicates a file for culturally neutral French language text.
4. Open Sample.aspx.fr.resx.
5. For the Button, Label, and TextBox controls, set Text to French Button, French Label, and French TextBox,
respectively.
6. Save the file.
Testing with an Alternate Language Setting
Before you can see if this new resource file is used by ASP.NET, you must alter your browser settings to request the desired
culture.
To change your browser's language settings
1. In Microsoft Internet Explorer, on the Tools menu, click Internet Options.
2. Click Languages.
3. In the Language Preference dialog box, click Add.
4. In the Add Language dialog box, under Languages, click French (France) [fr], and then click OK.
5. Click Add and add Spanish (Mexico) [es-mx] to the list of languages.
6. Click Add and add Arabic (Egypt) [ar-eg] to the list of languages.
You will use Spanish and Arabic for testing later in this walkthrough.
7. In the Language Preference dialog box, under Language, click French (France) [fr], click Move Up, and then click OK.
Internet Explorer is now set to pass fr as the language setting for any request. With the culture set to auto in the Sample.aspx
page, ASP.NET will attempt to locate a resource file and its corresponding values to assemble the page according to your
language and culture preferences.
To test the page
In Visual Web Developer, press CTRL+F5 to run the page.
The page is refreshed with values from the localized French language file instead of the English version.
Note
You can reset your language settings in Internet Explorer by returning to the Language Preference dialog box and m
oving your chosen language back up in the list.

Explicit Localization with ASP.NET


In the first part of this walkthrough, you used ASP.NET implicit localization to have controls display localized text. You
generated a resource file with property values in it, and in the process, you added an attribute to each control that instructed it
to fill its property values, if any, from the resource file. Implicit localization works automatically, in that you do not need to
specify property by property how to read information from a resource file.
However, at times you want to have more direct control over how properties are set. For this, instead of using implicit
localization, you can use explicit localization. With explicit localization, you set the value of a property by using an expression
pointing to a resource file. When the page runs, the expression is evaluated, the value is read from the specified resource file,
and then the value is used to set the property.
Explicit localization is useful when you have large bodies of text or custom messages you want to localize, in addition to
controls and labels. For example, you could develop a series of localized welcome and thank you messages for an e-commerce
site, and use explicit declarative expressions to place this text on your pages. Additionally, explicit localization allows you to
maintain a single set of localized resource files rather than maintaining a separate set of files for each page.
In this section, you will create resource files manually and reference them by using ASP.NET declarative expression syntax. You
will create a resource file for a simple thank you message. Unlike using the designer, a separate resource file is not required for
each ASP.NET page.
The base name of your resource file will be LocalizedText. For each language you want to localize, you will create another file
with the appropriate language code (and optionally the culture code) as part of the file name. For example, for U.S. English you
would create a file named LocalizedText.resx. For the French language in Canada, you would create a file named
LocalizedText.fr-ca.resx. Both files would be placed under the Resources directory of your Web application. Unlike the implicit
example previously, you do not need to maintain a resource file for each .aspx page; instead, you can maintain a single series of
files for each language or culture you support.
To create a resource file
1. In Solution Explorer, right-click the root of your Web site, click Add ASP.NET Folder, and then click
App_GlobalResources.
2. Right-click the App_GlobalResources folder, and then click Add New Item.
3. Under Visual Studio installed templates, click Resource File.
4. In the Name box, type LocalizedText.resx, and then click Add.
The LocalizedText.resx file will act as the resource for the fallback culture.
5. Create a second .resx file and name it LocalizedText.fr.resx.
The string "fr" identifies the file as the resource to use if the browser's language is set to French (regardless of culture).
6. Create a third .resx file and name it LocalizedText.es-mx.resx.
The string "es-mx" identifies the file as file as the resource to use if the browser's language is set to Spanish (Mexico).
7. Open the LocalizedText.resx file.
8. In the first row under the Name column type Msg1.
9. In the first row under the Value column, type Hello.
10. Save the file and close it.
11. Open the LocalizedText.fr.resx, create a resource string named Msg1, assign it the value Bon jour. When you are
finished, save and close the file.
12. Open the LocalizedText.es-mx.resx, create a resource string named Msg1, assign it the value Buenos días. When you
are finished, save and close the file.
Note
To insert the letter with acute (í), type ALT+0237 on the numeric keypad with Number Lock on.

You have created three values for the resource named Msg1. ASP.NET will read the value out of the appropriate resource
file based on what language the browser is set to.
Now that your resource file is created, you can return to the page and add controls that will reference the resource.
To add a Label control to the page
1. Switch to Sample.aspx, and then switch to Design view.
2. Drag another Label control onto the page.
3. Right-click the Label control, click Properties, and then click the ellipsis (…) button in the Expressions box.
The Expressions dialog box appears.
4. In the Bindable Properties list, click Text.
5. In the Expression Type list, select Resources.
6. Under Expression Properties, set ClassKey to LocalizedText and ResourceKey to Msg1.
7. Click OK.
8. Switch to Source view.
Your label's text attribute now has an explicit expression stating the base file from which to retrieve the resource and the
key to select.

<asp:Label ID="Label2" Runat="server" Text="<%$ Resources:LocalizedText, Msg1 %>">

Note
The LocalizedText attribute has no language indicator, culture indicator, or .resx extension because it is not the actual f
ile name. Instead, LocalizedText represents the base resource class. Depending on the culture sent by the browser, AS
P.NET will select the resource out of the file with the appropriate language or culture code within its file name, such as
LocalizedText.fr.resx, LocalizedText.es-mx.resx, or if no matching language is found, LocalizedText.resx.

With the resource file completed, and the declarative expression added, you can test the page. After the last test, your browser
was set to report French as its language preference. During the testing, you will change the browser's language several times.
To test the page
1. Press CTRL+F5 to run the page.
The French-language version of the text you provided in the Resource Editor is shown as the text for the Label control.
2. In Microsoft Internet Explorer, on the Tools menu, click Internet Options.
3. Click Languages.
4. In the Language Preference dialog box, move Spanish (Mexico) [es-mx] to the top of the list of languages. When you
are finished, click OK and close the Internet Options dialog box.
5. Press F5 to refresh the browser.
The Spanish version of the text is displayed.
6. Change the language to Arabic and then press F5 to refresh the page again.
This time, the text is displayed in the language you used in the fallback resource file. Because you did not create a file
LocalizedText.ar-eg.resx, ASP.NET was not able to locate text that matched the language and culture reported by the
browser, so it used the fallback resource file.
7. When you are finished testing the page, set the language back to the language your preferred language.
Next Steps
Localization can be a complex undertaking. This walkthrough has illustrated some of the features in Visual Web Developer that
can eliminate some of the work. You might want to learn more about localization and ASP.NET. For example, you might want
to:
Learn more about using resources in your applications. For details, see Resources in Applications.
Use classes that define culture-related information, including the language, country or region, calendars in use, format
patterns for dates, currency, numbers, and sort order for strings. For details, see System.Globalization.
Learn more about best practices to use when coding for a global audience. For details, see
Best Practices for Developing World-Ready Applications.
See Also
Concepts
Using the CultureInfo Class
Other Resources
Encoding and Localization
Globalization and Localization Namespaces in Visual Studio
Visual Web Developer

Building Professional Web Sites


The topics in this section include step-by-step walkthroughs that illustrate how to use system diagnostics with ASP.NET Web
pages and show how to deploy a Web site to a production Web server.
In This Section
Walkthrough: Integrating ASP.NET Tracing with System.Diagnostics Tracing
Walkthrough: Copying a Web Site Using the Copy Web Site Tool
Walkthrough: Publishing a Web Site
Related Sections
Guided Tour of Creating Web Sites in Visual Web Developer
Contains topics that give a guided tour of creating Web sites in Visual Web Developer.
ASP.NET

Walkthrough: Integrating ASP.NET Tracing with


System.Diagnostics Tracing
This walkthrough describes how to integrate ASP.NET tracing techniques with System.Diagnostics tracing techniques and write
all trace messages to a single tracing output.
You can use tracing to track the flow of execution for your application, to display data at critical points during a Web form's life
cycle, and to discover how the Web forms interact with various other components of your application. Using tracing, you can
examine HTTP request parameters that are submitted to your application, how much memory is being stored in view state for
a particular Web form, and other useful profiling information.
The ASP.NET tracing mechanism writes messages that are displayed on ASP.NET Web pages and on the ASP.NET Trace viewer
(Trace.axd), whereas the Trace class is used to write trace messages to the standard .NET Framework trace output (typically a
console window). To make it easier to track how the Web forms interact with business objects and other components, you can
integrate ASP.NET tracing output with System.Diagnostics tracing to route all tracing messages to one of these outputs.
Common scenarios that use both ASP.NET tracing and the Trace class include Web pages that use middle-tier business objects
to interact with data and business rules and pages that use enterprise services, such as transactions and queues. In these
situations, the business and enterprise components play key parts in the successful execution of the page and monitoring the
execution flow of the pages across the multiple tiers of your application using a single tracing output is desirable.
In this walkthrough you will work with tracing. You will modify a Web page and a business object to write trace messages, and
then route all messages to one tracing output.
Tasks illustrated in this walkthrough include the following:
Creating a custom business component that can return data to a Web page. The component reads data from an XML file.
Creating a Web page that references the custom business object as a data source.
Enabling tracing for the Web page that is referencing the business object.
Writing trace messages to the Web page that is referencing the business object.
Writing Trace messages in a custom business object.
Configuring an ASP.NET application to write all trace messages to a single output.
Reading trace output.
Prerequisites
In order to complete this walkthrough, you need the following:
The Microsoft .NET Framework and an existing ASP.NET Web site.
Note
This walkthrough does not assume that you are using a designer, such as the Microsoft Visual Web Developer Web develop
ment tool or Microsoft Visual Studio.

Creating a Web Page and Business Object


In this walkthrough you will create the Default.aspx Web page, an AuthorClass business object, and the Authors.xml XML data
file that is required for later steps in this walkthrough that involve tracing.
You can copy and paste the source code into files in your ASP.NET directory. This will create the Default.aspx Web page,
AuthorClass business object, and Authors.xml file.
To create the Default.aspx page
1. Open a text editor, such as Notepad, and create a new file.
2. Enter the following code into the file.
VB
<%@ Page Language="VB" %>
<html>
<form runat="server">
<asp:objectdatasource
id="AuthorsObjectDataSource"
runat="server"
typename="PubsClasses.AuthorClass"
selectmethod="GetAuthors"/>

<asp:gridview
id="GridView1"
runat="server"
datasourceid="AuthorsObjectDataSource" />
</form>
</html>

C#
<%@ Page Language="C#" %>
<html>
<form runat="server">
<asp:objectdatasource
id="AuthorsObjectDataSource"
runat="server"
typename="PubsClasses.AuthorClass"
selectmethod="GetAuthors"/>

<asp:gridview
id="GridView1"
runat="server"
datasourceid="AuthorsObjectDataSource" />
</form>
</html>

3. Save the file in the ASP.NET application root directory as Default.aspx.


The Default.aspx page uses a business object named AuthorClass to interact with XML data.
To create the AuthorClass business object
1. Under the application root directory, create a directory named App_Code.
2. In a text editor, such as Notepad, open a new file.
3. Enter the following code into the file.
VB
Imports Microsoft.VisualBasic
Imports System
Imports System.Web
Imports System.Data
Namespace PubsClasses
Public Class AuthorClass
Private dsAuthors As DataSet = _
New System.Data.DataSet("ds1")
Private filePath As String = _
HttpContext.Current.Server.MapPath("~/App_Data/authors.xml")
Public Sub New()
dsAuthors.ReadXml(filePath, Data.XmlReadMode.ReadSchema)
End Sub
Public Function GetAuthors() As DataSet
Return dsAuthors
End Function
End Class
End Namespace

C#
using System;
using System.Web;
using System.Data;
namespace PubsClasses
{
public class AuthorClass
{
private DataSet dsAuthors = new DataSet("ds1");
private String filePath =
HttpContext.Current.Server.MapPath("~/App_Data/authors.xml");

public AuthorClass()
{
dsAuthors.ReadXml (filePath, XmlReadMode.ReadSchema);
}

public DataSet GetAuthors ()


{
return dsAuthors;
}
}
}

4. In the App_Code directory, save the file as AuthorClass.cs (for C#) or AuthorClass.vb (for Microsoft Visual Basic).
The data file that the AuthorClass uses is Authors.xml.
To enable tracing and display ASP.NET trace messages
1. Under the application root directory, create a directory named App_Data.
2. In a text editor, such as Notepad, open a new file.
3. Enter the following XML data into the file.
The XML file includes schema information that identifies the database structure of the data. This includes a primary-key
constraint for the key.
Note
Business components can work with data in any way that is suited for your application. This walkthrough uses an XML f
ile for convenience.

<?xml version="1.0" standalone="yes"?>


<dsPubs xmlns="http://www.tempuri.org/dsPubs.xsd">
<xs:schema id="dsPubs" targetNamespace="http://www.tempuri.org/dsPubs.xsd" xmlns:mstns
="http://www.tempuri.org/dsPubs.xsd" xmlns="http://www.tempuri.org/dsPubs.xsd" xmlns:x
s="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdat
a" attributeFormDefault="qualified" elementFormDefault="qualified">
<xs:element name="dsPubs" msdata:IsDataSet="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="authors">
<xs:complexType>
<xs:sequence>
<xs:element name="au_id" type="xs:string" />
<xs:element name="au_lname" type="xs:string" />
<xs:element name="au_fname" type="xs:string" />
<xs:element name="au_phone" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
<xs:unique name="Constraint1" msdata:PrimaryKey="true">
<xs:selector xpath=".//mstns:authors" />
<xs:field xpath="mstns:au_id" />
</xs:unique>
</xs:element>
</xs:schema>
<authors>
<au_id>172-32-1176</au_id>
<au_lname>White</au_lname>
<au_fname>Gerry</au_fname>
<au_phone>408 496-7223</au_phone>
</authors>
<authors>
<au_id>213-46-8915</au_id>
<au_lname>Green</au_lname>
<au_fname>Marjorie</au_fname>
<au_phone>415 986-7020</au_phone>
</authors>
</dsPubs>

4. In the App_Data directory, save the file as Authors.xml, and then close it.
Adding Trace Messages to a Web page and Business Object
When you have created the Default.aspx page, the Authors.xml data file, and the AuthorClass business object, you can start
working with tracing. Before you add any trace messages to your code, enable tracing for the Default.aspx page.
To enable tracing and display ASP.NET trace messages
1. In a text editor, such as Notepad, open the Default.aspx page.
2. Add a Trace attribute to the @ Page directive, and then set Trace to true.
The declaration enables ASP.NET tracing for the Web page.
For more information, see How to: Enable Tracing for an ASP.NET Page.
Page tracing is now enabled and when you view the page in a Web browser, you will see that the GridView control is followed
by tracing output. The second tracing table that is displayed, Trace Information, shows you detailed information about the
execution path for the Web page.
For more information about how to read the tracing output, see the Reading ASP.NET Trace Information topic.
Writing Trace Messages
To better understand where some basic ASP.NET actions occur, such as the data binding that is performed by the GridView
control in the Default.aspx page, add trace messages to the Web page and AuthorClass business object.
To write trace messages from a Web form
In your Default.aspx Web page, enter the following code after the @ Page directive but before the <html> tag.
VB
<script runat="server">

Private Sub Page_Load(sender As Object, e As EventArgs)


Trace.WriteLine("ASP.NET TRACE","page_load called.")
Trace.WriteLine("ASP.NET TRACE","page_load finished.")
End Sub ' Page_Load

</script>

C#
<script runat="server">
private void page_load(object sender, EventArgs e) {

Trace.WriteLine("ASP.NET TRACE","page_load called.");


Trace.WriteLine("ASP.NET TRACE","page_load finished.");
}
</script>

Note
You might have to include a language attribute in your @ Page directive, depending on which language you use.

These trace messages are written to the ASP.NET trace output, and when you view the Default.aspx page again, you will see the
trace messages in the Trace Information section, between "Begin Load" and "End Load". "Begin Load" and "End Load"
are associated with the Page_Load method.
Now, you will add trace messages to the business object, AuthorClass.
To write trace messages to the AuthorClass business object
1. Enter the following code into the AuthorClass constructor.
VB
System.Diagnostics.Trace.Write("AuthorClass is created.", "AUTHORCLASS TRACE")

C#
System.Diagnostics.Trace.Write("AuthorClass is created.", "AUTHORCLASS TRACE");

2. Enter the following code into the AuthorClass.GetAuthors method.


VB
System.Diagnostics.Trace.Write("GetAuthors called.","AUTHORCLASS TRACE")

C#
System.Diagnostics.Trace.Write("GetAuthors called.","AUTHORCLASS TRACE");

Note
When you use ASP.NET System.Web.TraceContext.Write method, the trace category comes in front of the trace messag
e in the parameter list for the method. However, when you use the .NET Framework tracing Write method, the trace me
ssage comes in front of the trace category.

If you compile the business object that has the TRACE compiler option, these trace messages are written to the system trace
output. The trace messages are not written to the Default.aspx page, as the ASP.NET trace messages are. To test this, view the
Default.aspx page and verify that only the same "ASP.NET TRACE" messages appear in the Trace Information table that you
saw before.
In the next section, you will learn how to configure your ASP.NET Web application to automatically compile with the TRACE
option enabled and to route all trace messages to the Web page.
Routing All Tracing Output to the Web Form
Routing the Trace messages that are contained in the AuthorClass business object to the ASP.NET trace output can show you
when the AuthorClass is created and manipulated during request processing and give you a more holistic view of what your
application is doing. To route Trace messages to an ASP.NET Web page, you must add a WebPageTraceListener object. You
can add a trace listener either through configuration (recommended) or programmatically. For more information about adding
a trace listener through configuration, see <listeners> Element for <trace>.
For the next procedure, you will need a Web.config file. If you already have a Web.config file, skip the next procedure and go to
the following one, in which you will add a WebPageTraceListener object.
To create a Web.config file
1. Open a text editor, such as Notepad, and create a new file.
2. Enter the following text into the file.

<!-- Web.Config Configuration File -->


<configuration>
<system.web>
<customErrors mode="Off"/>
</system.web>
</configuration>

3. Save the file in the same directory as Default.aspx as Web.config.


Next, you will add a WebPageTraceListener object to your application to route Trace messages to the ASP.NET tracing
output.
To add a WebPageTraceListener for your application through configuration
1. Open the Web.config file for your application.
2. Place the following code in your Web.config file after the <system.web> section.

<system.diagnostics>
<trace>
<listeners>
<add name="WebPageTraceListener"
type="System.Web.WebPageTraceListener, System.Web, Version=2.0.3600.0, Cul
ture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
</listeners>
</trace>
</system.diagnostics>

This configuration section adds a WebPageTraceListener object to the trace listeners collection for your application.
Adding a WebPageTraceListener using the configuration file for your application is the recommended method of adding a
trace listener. However, you can also add the trace listener programmatically, which is especially useful, if you are using
complex tracing logic and different types of trace listeners to trace your application, and the WebPageTraceListener is just
one of many.
If you want to add a trace listener to your application programmatically, create a Global.asax file and add the listener by
following these steps.
To create a Global.asax file and add a trace listener programmatically
1. Open a text editor, such as Notepad, and create a new file.
2. Enter following code into the file.
VB
<%@ Application Language="VB" %>
<%@ Import Namespace="System.Web" %>

<script runat="server">
Sub Application_Start(sender As Object, e As EventArgs)
' Code that runs when the application is started.
End Sub

Sub Application_End(sender As Object, e As EventArgs)


' Code that runs when the application shuts down.
End Sub
</script>

C#
<%@ Application Language="C#" %>
<%@ Import Namespace="System.Web" %>

<script runat="server">

void Application_Start(Object sender, EventArgs e) {


// Code that runs when the application is started.
}

void Application_End(Object sender, EventArgs e) {


// Code that runs when the application shuts down.
}
</script>

3. In your application root directory, save the file as Global.asax.


This creates a basic Global.asax, which is a compiled module that contains code that runs whenever the application is
started or stopped.
4. Enter the following code into the Application_Start method of your Global.asax file.
VB
' Create a trace listener for Web forms.
Dim gbTraceListener As New WebPageTraceListener()
' Add the event log trace listener to the collection.
System.Diagnostics.Trace.Listeners.Add(gbTraceListener)

C#
// Create a trace listener for Web forms.
WebPageTraceListener gbTraceListener = new WebPageTraceListener();
// Add the event log trace listener to the collection.
System.Diagnostics.Trace.Listeners.Add(gbTraceListener);

This programmatically adds a WebPageTraceListener to the trace listeners collection for your application.
5. In the same directory as Default.aspx, save the file as Global.aspx.
With these steps, you have added a WebPageTraceListener to the trace listeners collection for the application. Although
ASP.NET displays trace messages whenever tracing is enabled for a page, System.Diagnostics trace messages are written
only when the code in which the trace messages reside is compiled by using an explicit compiler switch—the TRACE switch. In
other words, if you do not explicitly compile the AuthorClass using the TRACE switch, you will not see the trace messages,
even with the WebPageTraceListener added.
You can configure your application to automatically compile using the TRACE switch, by adding a new section to your
Web.config file.
To compile your application automatically with trace enabled
1. Open the Web.config file for your application.
2. Place the following code into your Web.config file after the <system.diagnostics> section.

<system.codedom>
<compilers>
<compiler language="c#;cs;csharp"
extension=".cs"
compilerOptions="/d:TRACE"
type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.3500.0, C
ulture=neutral, PublicKeyToken=b77a5c561934e089" warningLevel="1" />
<compiler language="VB"
extension=".vb"
compilerOptions="/d:Trace=true"
type="Microsoft.VisualBasic.VBCodeProvider, System,
Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</compilers>
</system.codedom>

By default, this configuration section makes your application compile all modules with the TRACE option.
If you view the Default.aspx page now, you will see both ASP.NET and System.Diagnostics trace messages. If the ASP.NET and
System.Diagnostics trace messages do not appear, you might have to recompile the AuthorClass object.
From the trace information, you can see the AuthorClass object is created and its GetAuthors method is called during the
PreRender method of the Web page life cycle. You can also see that there is a significant time lag when the AuthorClass
object is created; the difference in time between the "Begin PreRender" message and the "AuthorClass is created." message is
significant. This is because the AuthorClass opens the Authors.xml file and initializes its DataSet during creation, which is a
relatively costly operation.
In the next section, you will learn how to configure your ASP.NET Web application to route all trace messages to the .NET
Framework tracing output.
Routing All Tracing Output to .NET Framework Tracing
You might want to route ASP.NET tracing messages to the standard output for Trace messages, which can be a console
window, disk, the Windows Event Log, or any other trace message output. You can enable this message routing in the
Web.config configuration file.
To route all ASP.NET trace messages to the system tracing output
1. Open the Web.config file for your application.
2. Add a new attribute, writeToDiagnosticsTrace, to the trace element under <system.web>, and then set
writeToDiagnosticsTrace to true.

<system.web>
<trace writeToDiagnosticsTrace="true"/>
<customErrors mode="Off"/>
</system.web>

This configuration attribute instructs ASP.NET tracing to route ASP.NET trace messages to the standard system tracing
output mechanism.
To view the ASP.NET and System.Diagnostics trace messages in a context outside an ASP.NET page, use a
TextWriterTraceListener object to write the trace messages to a file.
The TextWriterTraceListener object must be configured to write to a specific file. You can do this using the
initializeData attribute of the <add> Element for <listeners> for <trace>.
3. Use the same steps that you followed to add the WebPageTraceListener object in the second procedure in "Routing All
Tracing Output to the Web Form," earlier in this walkthrough, to add a TextWriterTraceListener object to your
Web.config file and configure the TextWriterTraceListener to write to a file in the application root directory named
Asptesttrace.log.
Assuming that you did not add a WebPageTraceListener programmatically in the Global.asax file, the
<system.diagnostics> section of the Web.config file will look similar to the following:

<system.diagnostics>
<trace autoflush="true">
<listeners>
<add name="WebPageTraceListener"
type="System.Web.WebPageTraceListener, System.Web, Version=2.0.3600.0, Culture
=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
<add name="TestTracer"
type="System.Diagnostics.TextWriterTraceListener, System, Version=2.0.3600.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089"
initializeData="<app root directory>\Asptesttrace.log" />
</listeners>
</trace>
</system.diagnostics>

Note
The initializeData attribute in the previous step has a placeholder value for the ASP.NET application root directory. If y
ou try to a write trace messages to a file other than your application root directory, you might receive a security excepti
on. By default, ASP.NET does not allow writing files to locations on disk that are outside the application root directory, s
uch as C:\. Additionally, you might have to grant Write permission to the trace log for the ASP.NET worker process acco
unt.

By default, you must wait to fill the trace buffer before trace data is written to the target stream.
4. To see trace data in the trace log immediately after requesting your ASP.NET page, flush the buffer with every trace write
by setting the autoflush attribute set to true as you did in the preceding step.
The default value for the autoflush attribute is false.
5. To flush the buffer of trace information programmatically, call the Flush method.
Note
For the business object that you developed in this walkthrough, if you call the Flush method in the Page_Load method
and the autoflush attribute is false, the trace log will not show the trace data because the business object is rendered
after the page Load event occurs.

Next Steps
This walkthrough illustrated how to work with ASP.NET and System.Diagnostics tracing features to route all trace messages a
single output. You might want to experiment more with trace listeners and output and ASP.NET instrumentation features. For
example, you might want to do the following:
Add an EventLogTraceListener object to your application.
To do this, you would add an EventLogTraceListener object either programmatically or by using the configuration file
that uses the same procedure as for the WebPageTraceListener. You can open the Event Log to review the trace
messages that your application writes to the Event Log.
Change the business component to work with database data instead of with an XML file. You do not need to make any
change to the controls on the page.
See Also
Concepts
Reading ASP.NET Trace Information
Application-Level ASP.NET Tracing Overview
Other Resources
ASP.NET Tracing
Visual Web Developer

Walkthrough: Copying a Web Site Using the Copy Web Site


Tool
This walkthrough shows you how to use the Copy Web Site tool to copy files between your current Web site and another Web
site.
During this walkthrough, you will learn how to do the following:
Copy files between Web sites.
Synchronize two Web sites so that they have the same version of each file.
Note
If you copy an application that contains a reference to a custom component that is registered in the GAC, the compone
nt will not be copied with the application. For more information, see
How to: Add a Reference to a .NET or COM Component in a Web Site.

Prerequisites
In order to complete this walkthrough, you will need the following:
Visual Web Developer
The .NET Framework
Creating the Shared Web Site
In this walkthrough you will work with both a shared and local Web site as you might in a production environment. A typical
scenario is that the shared Web site is on another server, such as a staging server or production server. When you want to
work on the site, you create a local version of the site, and then copy the files from the shared server to your computer. When
you have finished your updates, you copy the local files back to the shared server.
This walkthrough will also let you see what it might be like to work in an environment where there is more than one developer.
If there were other developers working on the site, they might also download files, edit them locally, and then copy the files
back to the shared server. Therefore, not only must you copy files from the local Web site to the shared Web site, but you also
might have to copy updated versions of files on the shared Web site to the local Web site.
This walkthrough emulates this scenario by having you create two Web sites. Instead of residing on separate computers, the
Web sites both reside on the local computer. This lets you work with the Copy Web Site tool as you would in a production
environment but without requiring you to use a second computer. All tasks that you perform in this walkthrough work
identically when the shared Web site is on another computer. You will emulate the edits made by other developers by using
Notepad to change files.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the left-most Location list, click File System, and then in the right-most Location list, enter C:\SharedWebSite.
Note
Procedures later in the walkthrough assume that you are working with a Web site named SharedWebSite.

5. In the Language list, click the programming language that you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Creating Test Pages
For this walkthrough, you will create some simple pages with known names.
Note
To test copying Web pages, it is not important that you have specific pages. However, later in the walkthrough you will edit t
he pages that you create in the next procedure.

To create test pages


1. In Solution Explorer, right-click the name of the Web site, and then click Add New Item.
2. Under Visual Studio installed templates, click Web Form.
3. In the Name box, type Services.aspx.
4. In the Language list, click the programming language that you prefer to work in.
5. Click Add.
The new page appears in the editor.
6. Switch to Design view.
7. In the page, type Services, highlight to select the text that you just entered, and then on the Formatting toolbar, click
Heading 1 <H1>.
8. Position the pointer at the end of the text.
9. Press ENTER to create a new paragraph, and then type This page lists the services that we offer.
10. Save the page.
11. Repeat Steps 1 through 9 to create a page named Products.aspx with a heading of Products and the text This page
lists the products that we sell.
12. Open the Default.aspx page and switch to Design view.
13. In the page, type the heading Home and the text Welcome to our Web site.
Now you will add controls on the home page (Default.aspx) to link to the pages that you just created.
To add links on the Home page
1. Open the Default.aspx page and switch to Design view.
2. From the Standard group in the Toolbox, drag a Hyperlink control onto the page.
3. Set Text to Products and NavigateUrl to ~/Products.aspx.
4. Drag another Hyperlink control onto the page, and then set Text to Services and NavigateUrl to ~/Services.aspx.
5. Save your files.
Testing the Web Site
Now you will test that the Web site works as you expect.
To test the Web site
1. In Solution Explorer, right-click Default.aspx, and then click View in Browser.
The page appears in the browser.
2. Click Products and Services to confirm that the links work.
3. Close the browser.
Creating the Source Web Site
In this part of the walkthrough, you will create a second Web site that you can use to copy files to and from. As explained in
"Creating the Shared Web Site," earlier in this walkthrough, both Web sites are on your computer, but the first Web site
functions as the shared Web site. The Web site that you will create in this part of the walkthrough functions as the site that you
would use to edit files.
To create the source Web site
1. On the File menu, click Close Project to close SharedWebSite.
2. On the File menu, click New Web Site.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the left-most Location list, click File System, and then in the right-most Location list, enter C:\LocalWebSite.
5. Click OK.
Copying Files from the Shared to the Local Web Site
At this point, a shared Web site exists on your computer and you have a new Web site open. If you were a new developer on a
project, you would first want to obtain all files from the shared Web site and copy the files to your local Web site.
To copy all files from the shared Web site to the local Web site
1. On the Website menu, click Copy Web Site.
The Copy <Websitename> tool appears.
2. Click Connect.
The Open Web Site dialog box appears.
3. Click File System.
4. In the Folder box, type C:\SharedWebSite.
If the shared site were on another computer, you would type the URL of the server.
5. Click Open.
The files from the shared site are listed under Remote Web Site.
Many of the files have symbols next to them that indicate their status. The arrow symbol shows you the direction that a
file will be copied if you synchronize the sites. Currently, the Services.aspx and Products.aspx files in the Remote Web
Site list point to the Source Web Site list, because if you synchronize the Web sites, the Services.aspx and Products.aspx
files will be copied from the shared site to the local site.
The Default.aspx files have question marks (?) next to them. This indicates that the file has the same name in both sites,
but different timestamp data and no information about the last time the files were copied.
6. Under Remote Web site, highlight to select all files and folders.
In this case, you want to obtain copies of all files from the shared site. You are emulating a scenario where you are a new
developer on an existing Web site and you want to obtain the most current versions of the Web site files. Because you
have created a new local site, you do not have to copy any files from the local site to the shared site.
7. Click the left-arrow button to copy the selected files from the shared site to the local site.
The left-arrow button is not labeled unless you move the pointer over it, in which case a ToolTip appears. The arrow is
pointing to Source Web Site.
Visual Web Developer starts copying files. When it gets to the Default.aspx file, it prompts you for confirmation to
overwrite the local copy of the file with the file from the shared site.
8. In the Confirm File Overwrite dialog box, select the Apply to all check box, and then click Yes.
In this case, it is safe to overwrite all local versions of any files that have duplicated file names, because you want the file
versions from the shared site. When the copy process is finished, the lists in Source Web Site and Remote Web Site
are the same.
Note
The Copy Web Site tool does not merge files, it only overwrites files.

Copying Individual Pages


You can use the Copy Web Site tool to copy all files or individual files. In this part of the walkthrough, you will create a new
Web page in the source Web site, and then copy the new Web page file to the shared Web site.
To create and copy an individual file
1. In Solution Explorer, right-click the name of the Web site, and then click Add New Item.
2. Under Visual Studio installed templates, click Web Form.
3. In the Name box, type Extra.aspx.
4. Click Add.
You do not have to add any content to the page.
5. Close the page.
The new page is displayed in Source Web Site with arrows next to it pointing to Remote Web Site. If you synchronize
right now, the files will be copied from the local Web site to the shared Web site.
6. On the Copy Web tab, highlight to select the new page or pages.
7. Click the right/left-arrow button to copy the selected files from the local Web site to the shared Web site.
This button is not labeled unless you move the pointer over it, in which case a ToolTip appears.
The new page is copied to the shared Web site and the list in Remote Web Site is updated.
Synchronizing Web Sites
Synchronizing means copying the most current version of each file so that both Web sites have the same copies of all files. Use
synchronization, if the files on the shared Web site might be updated by someone other than you. In this part of the
walkthrough, you will first change both the local and shared Web site, and then you will synchronize the changes between the
sites.
To change the local and shared Web sites
1. On the Copy <Websitename> tab, under Source Web site, click Extra.aspx, and then click the delete button.
2. When prompted for confirmation to delete the file, click Yes.
The files for the deleted page appear in Source Web Site with a symbol next to them, which indicates that the files have
been deleted.
Note
Make sure that the Show deleted files since the last copy operation check box is selected.

3. In Windows, start Notepad, and then open C:\SharedWebSite\Products.aspx.


4. Add extra spaces or other characters to the file, save the file, and then close Notepad.
You are changing the file to emulate what would occur if another developer changed the file on the shared Web site.
5. In Visual Web Developer, on the Copy <Websitename> tab, click Refresh Remote Web Site.
An arrow appears next to the Products.aspx file pointing to Source Web Site.
6. Under Remote Web Site, highlight to select all files and folders, and then click the synchronize button to synchronize
the selected file between the same relative paths in both LocalWebSite and SharedWebSite.
This button is not labeled unless you move the pointer over it. The button has a right and left arrow to indicate both
panes.
7. When prompted to delete the Extra.aspx file in the remote Web site, which in effect is propagating the deletion to the
remote Web site, click Yes.
The Products.aspx page is copied from the remote Web site to the source Web site.
Note
If you selected all files and folders under Source Web Site and synchronized the files and folders, the results would be
the same.

Next Steps
This walkthrough has illustrated the basic tasks that you can accomplish with the Copy Web Site tool. Although the Web sites
that you worked with contained only a few files, you can apply the techniques that are used in this walkthrough to sites of any
size. You might also want to experiment with additional ways to copy files to remote computers. For example, you might want
to do the following:
Work with an FTP Web site, which lets you open and edit files directly on a server that is configured to allow FTP
connections.
For detailed information, see Walkthrough: Editing Web Sites with FTP in Visual Web Developer.
Learn how to publish Web sites, which precompiles the contents of the Web site. You can then deploy the output to your
production server.
For detailed information, see Walkthrough: Publishing a Web Site.
See Also
Concepts
Web Site Deployment in Visual Web Developer
Copying Web Sites with the Copy Web Site Tool
Visual Web Developer

Walkthrough: Publishing a Web Site


Provides step-by-step instructions for using the Publish Web Site utility of the Microsoft Visual Web Developer Web
development tool to compile a Web site, and then copy the output to an active Web site.
If you want to deploy a finished Web site to a server, you can use the Publish Web Site utility that is included with the Microsoft
Visual Web Developer Web development tool. The Publish Web Site utility precompiles the pages and code that are in the Web
site and writes the compiler output to a folder that you specify. You can then copy the output to the target Web server and run
the application from there.
Note
The Publish Web Site utility is not available in Visual Web Developer Express edition.

Tasks illustrated in this walkthrough include the following:


Using the Publish Web Site utility to create precompiled output.
Prerequisites
In order to complete this walkthrough, you will need the following:
Visual Web Developer.
The Visual Web Developer Express edition does not support the Publish Web Site utility.
Access to Microsoft Internet Information Services (IIS) so that you can test the result of publishing a Web site.
In this walkthrough, it is assumed that you have IIS running on your own computer. Alternatively, you can use any
instance of IIS for which you have permission to create a virtual directory.
Creating the Web Site
If you have already created a Web site in Visual Web Developer by completing
Walkthrough: Creating a Basic Web Page in Visual Web Developer, you can use that Web site and go to the next section.
Otherwise, create a new Web site and page by following these steps.
For this walkthrough, you will create a file system Web site.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the left-most Location list, click File System.
5. In the right-most Location list, enter the name of the folder where you want to keep the pages of the Web site.
For example, type the folder name C:\WebSites.
6. In the Language list, click the programming language that you prefer to work in.
7. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Creating a Test Page and Class
For this walkthrough, you will create a Web page with some controls. You will also create a class file that you will use in the
Web page. Creating both a Web page and a separate class will let you see how the publish process precompiles the contents of
the Web site.
You will start by creating a new page, and then adding a button and label to the page.
To create the page and add controls
1. In Solution Explorer, right-click the name of the Web site and click Add New Item.
2. Under Visual Studio installed templates, click Web Form.
3. In the Name box, type SamplePage.aspx.
4. In the Language list, click the programming language that you prefer to work in.
5. Click Add.
6. Switch to Design view.
7. From the Standard group in the Toolbox, drag a Label control onto the page.
8. From the Standard group in the Toolbox, drag a Button control onto the page and position it next to the Label control.
Next, you will create the source code for a simple class that has a single property in it. You will use the class in the code for
your page.
To create a class
1. In Solution Explorer, right-click the name of the Web site, point to Add ASP.NET Folder, and then click App_Code.
A new folder named App_Code appears in your application in Solution Explorer. The App_Code folder is a special
reserved ASP.NET application folder. For more information, see ASP.NET Web Site Layout.
2. Right-click the App_Code folder, and then click Add New Item.
3. Under Visual Studio installed templates, click Class.
4. In the Name box, type TestClass.
5. In the Language list, click the programming language that you prefer to work in.
Note
The programming language that you select does not have to be the same as the programming language that you use i
n the .aspx page.

6. Click Add.
Visual Web Developer creates a skeleton class file in the programming language that you have specified. Notice that the
extension of the class file name matches the language that you have selected. For example, if you are creating a class in
Microsoft Visual Basic, the file name extension is .vb.
7. Create a property named TestProperty.
When you are finished, the complete class file will look similar to the following:
VB
Imports Microsoft.VisualBasic
Public Class TestClass
Private TestPropertyValue As String
Public Property TestProperty() As String
Get
Return TestPropertyValue
End Get
Set(ByVal value As String)
TestPropertyValue = value
End Set
End Property
End Class

C#
using System;
public class TestClass
{
public TestClass() { }
private string TestPropertyValue;
public string TestProperty
{
get{ return TestPropertyValue; }
set{ TestPropertyValue = value; }
}
}

Now, you can use the class in the page. Notice that you do not have to compile the class file before using it.
To use the class in the page code
1. Open SamplePage.aspx and switch to Design view.
2. Double-click the Button control to create a Click handler for it.
3. In the Click handler, create an instance of the TestClass that you created in the preceding procedure, assign a value to
the TestProperty property, and then display the TestProperty value in the Label control.
The complete code will look similar to this:
VB
Protected Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs)
Dim testClass As New TestClass
testClass.TestProperty = "Hello"
Label1.Text = testClass.TestProperty
End Sub

C#
protected void Button1_Click(object sender, EventArgs e)
{
TestClass testClass = new TestClass();
testClass.TestProperty = "Hello";
Label1.Text = testClass.TestProperty;
}

Testing the Site


Before publishing the site, you can test it to make sure that the site works in the way that you expect.
To test the Web site
1. Open the SamplePage.aspx page.
2. Press CTRL+F5.
The page appears in the browser.
3. Click Button and make sure that text appears in the Label control.
4. Close the browser.
Publishing the Web Site
Now that you have a Web site, you can publish it. You can publish the Web site to any location that you have access to on the
local computer or on a network that is using any connection protocol that is supported by Visual Web Developer. You have the
following options for copying the Web site:
Use a UNC share to copy to a shared folder that is on another computer on the network.
Use FTP to copy to a server.
Use the HTTP protocol to copy to a server that supports FrontPage 2002 Server Extensions from Microsoft.
In this part of the walkthrough, you will publish the Web site to local folder.
To publish the Web site
1. On the Build menu, click Publish Web Site.
The Publish Web Site dialog box appears.
2. In the Target Location box, enter c:\CompiledSite.
Caution
All data in the target folder and its subfolders will be deleted. Make sure that you do not type the name of a folder that
contains data or contains subfolders with data.

For the purposes of this walkthrough, you are publishing to a local folder. You could also publish to a UNC share. If you
wanted to publish to a remote Web site using HTTP or FTP, the Target Location box is where you would specify the
remote server URL.
The Allow this precompiled site to be updatable option specifies that all program code is compiled into assemblies,
but that .aspx files (including single-file ASP.NET Web pages) are copied as-is to the target folder. In this walkthrough,
you will not select that option. For detailed information, see Publishing Web Sites.
3. Click OK.
Visual Web Developer precompiles the contents of the Web site and writes the output to the folder that you specified.
The Output window displays progress messages. If an error occurs during compilation, it is reported in the Output
window.
4. If errors occur during publishing, fix the errors, and then repeat step 1.
Examining the Output of the Publish Web Site Command
It is useful to examine the output of the Publish Web Site command so that you can see what Visual Web Developer has done
with your Web site files.
To examine the output of the Publish Web Site command
1. In Windows Explorer, move to the folder that you specified as the target for the Publish Web Site command.
2. Using a text editor, such as Notepad, open the SamplePage.aspx file.
Notice that the file does not contain the markup that you originally had in the file. Instead, the .aspx page is only a
placeholder that can be used as part of a URL.
3. Move to the Bin folder.
The folder contains two types of files:
.compiled files, which correspond to pages.
.dll files, which contain the executable code for the Web site, such as the class file that you created.
Remember that the page, its code, and the separate class file that you created have all been compiled into executable code.
Testing the Published Web Site
You can now test the published Web site by running it.
To test the published Web site
1. Create an IIS virtual directory that points to the target folder.
You can use the IIS administrative tools or alternatively, use the following steps:
a. In Windows Explorer, right-click the name of the target folder, and then click Sharing and Security.
b. On the Web Sharing tab, click Share this Folder.
The Edit Alias dialog box appears.
c. If you want, change the name of the alias.
The default permissions allow Read access and allow Scripts, such as ASP.NET pages, to run.
d. Click OK to close the Edit Alias dialog box, and then click OK to close the Properties dialog box.
2. Open the browser and type the following URL:
http://localhost/CompiledSite/SamplePage.aspx
The SamplePage.aspx page appears. However, this time you are viewing the version of the page that was created by the
precompiler for deployment.
Next Steps
This walkthrough has shown you the basic procedure for publishing a precompiled Web site. Suggestions for more exploration
include the following:
Experiment with using the Copy Web tool instead, which copies the Web site as-is (as source code) to a target folder.
For more information, see Copying Web Sites with the Copy Web Site Tool.
Publish the Web site to a remote IIS Web site.
See Also
Tasks
Walkthrough: Copying a Web Site Using the Copy Web Site Tool
Concepts
Web Site Deployment in Visual Web Developer
Publishing Web Sites
Visual Web Developer

How Do I in Visual Web Developer


How Do I is your gateway to key topics about creating dynamic Web sites with Visual Web Developer. The essential
information on working with Visual Web Developer is listed in this topic. The links provide pointers to important procedure-
based Help pages.
Getting Started
Overview ... Guided Tour
Development Environment
Web page designer ... editing HTML ...
Web Sites
Creating ... site navigation ... themes ... accessibility ... globalization ... more
Web Pages
Programming pages ... master pages ... themes ... Web Parts ... client script ... caching ...
Web Page Controls
Standard controls, data controls, navigation controls ...
Data
Displaying data ... editing data ... master/detail pages ...
Security
Security practices ... membership (authentication) ...
Troubleshooting
Debugging ... tracing ... error handling ...
Globalization
Resources ... encoding ... bi-directional text ...
Deployment
Copying Web sites ... compiling and publishing Web sites ...
See Also
Other Resources
Visual Web Developer
Visual Web Developer

Data (How Do I in Visual Web Developer)


This page links to help on widely used tasks for displaying and editing data in ASP.NET Web pages. To view other categories of
popular tasks covered in Help, see How Do I in Visual Web Developer.
The information in this topic is subdivided into the following sections:
Getting Started
Walkthroughs
SQL-based Databases
Business Objects
XML
Data Controls
Data Security
Getting Started
ASP.NET Data-Bound Web Server Controls Overview
Provides information on using controls to display data on ASP.NET Web pages.
Data Source Controls Overview
Provides information on using declarative controls (data source controls) on ASP.NET Web pages to connect to data sources
and read and write data.
Binding to Data Using a Data Source Control
Provides information on how to associate display controls on the page with data source controls that perform data access.
Using Parameters with Data Source Controls
Provides information on passing run-time information for search and update to data source controls.
Sorting Data with Data Source Controls
Provides information on how to configure data source controls to sort data.
Modifying Data using Data Source Controls
Provides information on how to configure data source controls to update or delete records in a data source.
Filtering Data Using Data Source Controls
Provides information on how to configure data source controls to create subsets of the data returned by the data source
control.
Caching Data Using Data Source Controls
Provides information on how to configure data source controls to store data in memory for faster performance.
Walkthroughs
Walkthrough: Basic Data Access in Web Pages
Provides a tutorial on how to use the GridView control and SqlDataSource controls to display data on an ASP.NET Web
page.
Walkthrough: Displaying Data Using a Stored Procedure in the GridView Web Server Control
Provides a tutorial on using a SQL Server stored procedure to retrieve data.
Walkthrough: Creating a Web Page to Display Access Database Data
Provides a tutorial on how to use the GridView control and AccessDataSource controls to display data from a Microsoft
Access database on an ASP.NET Web page.
Walkthrough: Creating Master/Detail Web Pages in Visual Studio
Provides a tutorial on how to use the DropDownList, GridView, DetailsView, and SqlDataSource controls to create pages
that display lists of data where the user can select an individual record to examine further.
Walkthrough: Editing and Inserting Data in Web Pages with the DetailsView Web Server Control
Provides a tutorial on using a DetailsView control to enable users to edit existing records and create new ones.
Walkthrough: Data Binding to a Custom Business Object
Provides a tutorial on how to use the ObjectDataSource control to create multi-tier data access in an ASP.NET Web
application.
Walkthrough: Data Binding Web Pages with a Visual Studio Data Component
Provides a tutorial on how to use Visual Studio tools to create a data-access object that you can use with the
ObjectDataSource control.
Walkthrough: Displaying and Formatting Data with the DataList Web Server Control
Provides a tutorial on creating a DataList control, which enables you to display data in an HTML table using a layout you
define.
Walkthrough: Displaying Formatted Data in Web Pages with the FormView Web Server Control
Provides a tutorial on using a FormView control to display a single record at a time, using free-form layout templates that
you define.
Walkthrough: Displaying a Drop-Down List While Editing in the GridView Web Server Control
Provides a tutorial on how to customize the GridView control to display a drop-down list in edit mode.
Walkthrough: Simple Sorting for the GridView Web Server Control
Provides a tutorial on how to use built-in features of the GridView control to enable users to sort the displayed data.
Walkthrough: Creating a Web Page to Display XML Data
Provides a tutorial on using the XmlDataSource control to read XML data and the GridView and DropDownList controls
to display the XML data on a page.
Walkthrough: Displaying Hierarchical Data in a TreeView Control
Provides a tutorial on using the TreeView control to display XML data.
Walkthrough: Displaying an XML Document in a Web Forms Page Using Transformations
Provides a tutorial on using the Xml control to display the contents of an XML document on a page.
Walkthrough: Using ASP.NET Output Caching with SQL Server
Provides a tutorial on caching pages that are removed from the cache only when their dependent data in SQL Server
changes.
SQL-based Databases
How to: Connect to a SQL Server Database Using the SqlDataSource Control (Visual Studio)
Provides steps for creating a connection string that can be used to access a SQL Server database.
How to: Connect to an Oracle Database Using the SqlDataSource Control (Visual Studio)
Provides steps for reading and writing data in an Oracle database.
How to: Connect to an ODBC Database Using the SqlDataSource Control (Visual Studio)
Provides steps for reading and writing data in any ODBC-compliant database.
How to: Enable Filtering for the SqlDataSource Control
Provides information on how to configure a SqlDataSource control to create subsets of the data returned by the data
source control.
Selecting Data Using the SqlDataSource Control
Provides information on how to configure a SqlDataSource control to run database queries to return data.
Modifying Data using the SqlDataSource Control
Provides information on how to configure a SqlDataSource control to update or delete in a database.
Using Parameters with the SqlDataSource Control
Provides information on passing run-time information for search and update to a SqlDataSource control.
Caching Data with the SqlDataSource Control
Provides information on how to configure a SqlDataSource control to store data in memory for faster performance.
How to: Connect to an Access Database Using the SqlDataSource Control (Visual Studio)
Provides steps for reading and writing data in a Microsoft Access database.
Retrieving Data Using the AccessDataSource Web Server Control
Provides steps for creating a connection string that can be used to open a Microsoft Access database.
Business Objects
Walkthrough: Data Binding to a Custom Business Object
Provides a tutorial on how to use the ObjectDataSource control to create multi-tier data access in an ASP.NET Web
application.
Walkthrough: Data Binding Web Pages with a Visual Studio Data Component
Provides a tutorial on how to use Visual Studio tools to create a data-access object that you can use with the
ObjectDataSource control.
Creating an ObjectDataSource Control Source Object
Provides information on creating a class that can be used as a middle-tier object accessible by the ObjectDataSource
control.
Using Parameters with the ObjectDataSource Control
Provides information on configuring parameter objects so you can pass update, delete, paging, and sorting information to an
ObjectDataSource control.
XML
Walkthrough: Creating a Web Page to Display XML Data
Provides a tutorial on using the XmlDataSource control to read XML data and the GridView and DropDownList controls
to display the XML data on a page.
Filtering Data Using the XmlDataSource Control
Provides information on using XPath queries in the XmlDataSource control to find subsets of XML data.
Binding a Tabular Control to the XmlDataSource Control
Provides information on reading XML data using the XmlDataSource control and displaying it in a control such as the
GridView control.
Walkthrough: Displaying Hierarchical Data in a TreeView Control
Provides a tutorial on using the TreeView control to display XML data.
How to: Add XML Web Server Controls to a Web Forms Page (Visual Studio)
Provides steps for creating an Xml control using the Visual Web Developer designer. This control enables you to display an
XML document on the page.
How to: Load XML Data in the XML Web Server Control
Provides steps for configuring an Xml control to display an XML document or XML stream.
How to: Transform XML Data in the XML Web Server Control
Provides steps for using a transformation with the Xml control to customize the display of XML data.
Data Controls
How to: Add DataList Web Server Controls to an ASP.NET Web Page (Visual Studio)
Provides steps for creating a DataList control, which enables you to display data in an HTML table using a layout you define.
Walkthrough: Displaying and Formatting Data with the DataList Web Server Control
Provides a tutorial on creating a DataList control, which enables you to display data in an HTML table using a layout you
define.
How to: Allow Users to Delete Items in DataList Web Server Controls
Provides steps for configuring the DataList control to enable users to delete data records.
How to: Allow Users to Edit Items in DataList Web Server Controls
Provides steps for configuring the DataList control to enable users to edit data records.
How to: Allow Users to Select Items in DataList Web Server Controls
Provides steps for configuring the DataList control to enable users to select (highlight) a specific item.
How to: Customize Items Dynamically in the DataList Web Server Control
Provides steps for how to use code to change the look or behavior of items in a DataList control at run time.
How to: Specify Flow or Table Format in DataList Web Server Controls
Provides steps for how to set the layout of a DataList control.
How to: Specify Horizontal or Vertical Layout in DataList Web Server Controls
Provides steps for how to set the layout of a DataList control.
Walkthrough: Editing and Inserting Data in Web Pages with the DetailsView Web Server Control
Provides a tutorial on using a DetailsView control to enable users to edit existing records and create new ones.
Modifying Data Using a DetailsView Web Server Control
Provides information on using the DetailsView control to enable users to edit data one record at a time.
Paging in a DetailsView Web Server Control
Provides information on configuring the DetailsView control to enable users to page through multiple records, one at a
time.
Walkthrough: Displaying Formatted Data in Web Pages with the FormView Web Server Control
Provides a tutorial on using a FormView control to display a single record at a time, using free-form layout templates that
you define.
Modifying Data Using a FormView Web Server Control
Provides steps on using a FormView control to enable users to edit data one record at a time.
Paging in a FormView Web Server Control
Provides information on configuring the FormView control to enable users to page through multiple records, one at a time.
Walkthrough: Creating Master/Detail Web Pages in Visual Studio
Provides a tutorial on how to use the DropDownList, GridView, DetailsView, and SqlDataSource controls to create pages
that display lists of data where the user can select an individual record to examine further.
Walkthrough: Simple Sorting for the GridView Web Server Control
Provides a tutorial on how to use built-in features of the GridView control to enables users to sort the displayed data.
How to: Customize Controls for Editing in the GridView Web Server Control
Provides steps on configuring the GridView control to display the controls that you choose when in edit mode.
How to: Set GridView Web Server Control Column Width Dynamically
Provides steps for setting column widths in the GridView control according to the width of the data being displayed.
How to: Respond to Button Events in Data-Bound Controls
Provides steps for how to handle events raised by button controls in list data controls such as the GridView, DataList, and
Repeater controls.
How to: Enable Default Deleting in the GridView Web Server Control
Provides steps for configuring the GridView control to enable users to delete data records.
How to: Enable Default Editing in the GridView Web Server Control
Provides steps for configuring the GridView control to enable users to edit data records.
How to: Enable Default Paging in the GridView Web Server Control
Provides steps for configuring the GridView control to enable users to page through long lists of data records.
Walkthrough: Data Binding to a Custom Business Object
Provides a tutorial on how to use the ObjectDataSource control to create multi-tier data access in an ASP.NET Web
application.
Walkthrough: Data Binding Web Pages with a Visual Studio Data Component
Provides a tutorial on how to use Visual Studio tools to create a data-access object that you can use with the
ObjectDataSource control.
How to: Add Repeater Web Server Controls to a Web Forms Page (Visual Studio)
Provides steps for creating a Repeater control, which enables you to display data on an ASP.NET Web page using free-form
layout templates that you define.
How to: Enable Filtering for SqlDataSource Controls (Visual Studio)
Provides steps for how to configure a SqlDataSource control to enable the results of a query to be further refined with
filtering.
How to: Respond to Button Events in DataList, Repeater, or GridView Items
Provides steps for how to handle events raised by button controls in list data controls such as the GridView, DataList, and
Repeater controls.
How to: Create Web Server Control Templates Using the Designer
Provides steps for using the Visual Web Developer designer to create and edit templates in the GridView, DetailsView,
FormView, DataList, and Repeater controls.
How to: Create ASP.NET Web Control Templates Declaratively
Provides steps for creating templates in the GridView, DetailsView, FormView, DataList, and Repeater controls by editing
the markup directly.
How to: Bind to Data in a Templated Control
Provides steps for adding data-bound controls to templates in controls such as the GridView, DetailsView, FormView,
DataList, and Repeater controls.
Data Security
Securing Data Access
Provides guidelines for improving the security of data access in ASP.NET Web applications.
How To: Secure Connection Strings when Using Data Source Controls (Visual Studio)
Provides steps for encrypting connection strings for database access.
How to: Access SQL Server as a Local User
Provides steps for configuring your application to log into SQL Server on the same computer as the Web server.
How to: Access SQL Server Using a Mapped Windows Domain User
Provides steps for configuring your application to log into SQL Server using a specific Windows user account.
How to: Access SQL Server Using Predetermined Credentials
Provides steps for configuring your application to log into SQL Server using a user name and password that you build into
your application.
How to: Access SQL Server Using Windows Integrated Security
Provides steps for configuring your application to log into SQL Server with the user's current Windows user account
information.
See Also
Concepts
How Do I in Visual Web Developer
Visual Web Developer

Deployment (How Do I in Visual Web Developer)


This page links to help on widely used tasks for copying a Web site from your computer to another computer such as a Web
server. To view other categories of popular tasks covered in Help, see How Do I in Visual Web Developer.
Walkthroughs
Walkthrough: Copying a Web Site Using the Copy Web Site Tool
Provides a tutorial on creating a Web site and copying the files to a production Web server.
Walkthrough: Editing Web Sites with FTP in Visual Web Developer
Provides a tutorial on using FTP to open a Web site on a remote Web server.
Walkthrough: Publishing a Web Site
Provides a tutorial on compiling a Web site into assemblies that can be deployed to a Web server.
Deploying
How to: Copy Web Site Files with the Copy Web Site Tool
Provides steps for how to copy files from your computer to a Web server or vice versa.
Web Site Deployment in Visual Web Developer
Provides an overview of options for deploying a Web site to a Web server.
How to: Publish Web Sites (Visual Studio)
Provides steps for how to create a compiled version of a Web site that can be copied to a Web server.
FTP
FTP-Deployed Web Sites
Provides an overview of what FTP is and how it is supported in Visual Studio.
How to: Create and Configure FTP Sites in IIS
Provides steps for how to set up a Web server with Internet Information Services (IIS) to accept FTP connections.
See Also
Concepts
How Do I in Visual Web Developer
Visual Web Developer

Development Environment (How Do I in Visual Web Developer)


This page links to help on widely used information pertaining to using the Visual Web Developer integrated design
environment (IDE). To view other categories of popular tasks covered in Help, see How Do I in Visual Web Developer.
What's New in Web Development for Visual Studio
Provides information on changes and enhancements in the Web development features of Visual Web Developer.
What's New in the Web Page Designer and Editors
Provides information on changes and enhancements in Visual Web Developer for creating and editing ASP.NET Web pages.
What's New in Code-Behind Support in Visual Web Developer
Provides information on changes and enhancements in Visual Web Developer to support creating page code.
Web Solution and Project File Conversion
Provides details about changes made to pages and to other files during conversion.
Visual Web Developer Settings
Provides information on the default IDE settings.
Walkthroughs
Walkthrough: Creating a Basic Web Page in Visual Web Developer
Provides a tutorial on creating and editing an ASP.NET Web page in Visual Web Developer, including an overview of the Web
development environment.
Walkthrough: Creating a Basic Web Page with Code Separation in Visual Web Developer
Provides a tutorial on how to work with ASP.NET code-behind pages in the Visual Web Developer designer.
Walkthrough: Basic HTML Editing in Visual Web Developer
Provides a tutorial on working with markup (HTML) in the Visual Web Developer designer.
Walkthrough: Advanced HTML Editing in Visual Web Developer
Provides a tutorial on additional HTML editing features in the Visual Web Developer designer.
Walkthrough: Editing HTML Tables in Visual Web Developer
Provides a tutorial on adding and editing HTML tables in the Visual Web Developer designer.
Walkthrough: Working with Cascading Style Sheet Styles in Visual Web Developer
Provides a tutorial on features in the Visual Web Developer designer that help you create styles and cascading style sheets.
Walkthrough: Code Editing in Web Pages in Visual Web Developer
Provides a tutorial on features of the code editor in the Visual Web Developer designer that help you create code quickly and
accurately.
Creating Web Sites and Pages
How to: Add ASP.NET Web Pages to a Web Site (Visual Studio)
Provides steps for creating ASP.NET Web pages using Visual Web Developer.
How to: Create Scripts and Edit Event Handlers
Provides steps for writing client script while working in Source view of the Visual Web Developer designer.
How to: Display Hidden Information in Design View
Provides steps for setting options to show or hide editing aids such as glyphs and borders around non-visible elements.
How to: Position Elements in Design View
Provides steps for setting positioning options for elements in Design view, so that you can drag them to specific locations on
the page.
How to: Test Web Pages in Visual Web Developer
Provides steps for how to run your Web pages to test them while working in the Visual Web Developer designer.
How to: Specify Start Pages for Testing Web Sites in Visual Web Developer
Provides steps for how to select a specific page to run when testing your Web site in the Visual Web Developer designer.
How to: Add Web Browsers to Visual Web Developer
Provides steps for how to configure Visual Web Developer to use alternative browsers for testing.
Editing HTML Elements and Cascading Style Sheets
How to: Create and Edit HTML Tables in Design View
Provides steps for using the Visual Web Developer designer to create HTML tables.
How to: Select HTML Table Elements and Contents in Visual Web Developer
Provides steps for using the Visual Web Developer designer to select specific rows, columns, or cells in an HTML table.
How to: Resize HTML Table Elements in Visual Web Developer
Provides steps for using the Visual Web Developer designer to resize rows, columns, or cells in HTML tables.
How to: Add and Remove HTML Table Elements in Visual Web Developer
Provides steps for using the Visual Web Developer designer to create or remove rows, columns, or cells in HTML tables.
HTML Table Editing Tips in Visual Web Developer
Provides information on common issues that arise when working with HTML tables in Design view.
How to: Navigate in the HTML Editor in Visual Web Developer
Provides steps for using editor features such as the tag navigator to quickly move to specific elements in a page.
How to: Collapse and Expand HTML Elements in Visual Web Developer
Provides steps for using editor features in Source view to make large elements (such as tables) into units you can hide or
display as required.
How to: Insert HTML Hyperlinks and Bookmarks in Design View
Provides steps for creating links (a tags) in Design view.
Markup Validation in Visual Web Developer
Provides information on how the editor can help you find markup elements that do not conform to a specific schema, such
as XHTML 1.0.
How to: Set Validation Options for HTML Editing in Visual Web Developer
Provides steps for customizing the behavior of markup validation.
How to: Select Validation Schemas for HTML Editing in Visual Web Developer
Provides steps for configuring the editor to use a specific schema, such as XHTML 1.0, when validating markup in Source
view.
XHTML in Visual Web Developer
Provides information on XHTML support in Visual Web Developer.
How to: Choose an Alternate HTML Editor in Visual Web Developer
Provides steps for selecting the HTML editor of your choice for use in Visual Web Developer.
How to: Create External Cascading Style Sheets (Visual Studio)
Provides steps for creating a .css file that you can link to pages in your Web site.
How to: Link Cascading Style Sheets to ASP.NET Web Pages (Visual Studio)
Provides steps for applying a .css file to a page.
How to: Add Cascading Style Sheet Attributes in Design View
Provides steps for adding style blocks or style attributes for individual elements.
See Also
Concepts
How Do I in Visual Web Developer
Visual Web Developer

Getting Started (How Do I in Visual Web Developer)


This page links to a selection of walkthroughs (tutorials) that provide an overview of creating Web sites and ASP.NET Web
pages using Visual Web Developer. To view other categories of popular tasks covered in Help, see
How Do I in Visual Web Developer.
What's New in Web Development for Visual Studio
Provides information on changes and enhancements in the Web development features of Visual Web Developer.
Basic Techniques
Walkthrough: Creating a Basic Web Page in Visual Web Developer
Provides a tutorial on creating and editing an ASP.NET Web page in Visual Web Developer, including an overview of the Web
development environment.
Walkthrough: Creating a Basic Web Page with Code Separation in Visual Web Developer
Provides a tutorial on how to work with ASP.NET code-behind pages in the Visual Web Developer designer.
Walkthrough: Basic HTML Editing in Visual Web Developer
Provides a tutorial on working with markup (HTML) in the Visual Web Developer designer.
Working with Data
Walkthrough: Basic Data Access in Web Pages
Provides a tutorial on how to use ASP.NET data controls to display data on an ASP.NET Web page.
Walkthrough: Editing and Inserting Data in Web Pages with the DetailsView Web Server Control
Provides a tutorial on using ASP.NET controls to enable users to edit existing records and create new ones.
Walkthrough: Creating Master/Detail Web Pages in Visual Studio
Provides a tutorial on how to use ASP.NET data controls to create pages that display lists of data where the user can select an
individual record to examine further.
Walkthrough: Data Binding to a Custom Business Object
Provides a tutorial on how to use ASP.NET data controls to create multi-tier data access in an ASP.NET Web application.
Customizing Web Sites and Pages
Walkthrough: Creating a Web Site with Membership and User Login (Visual Studio)
Provides a tutorial on adding Web site security using ASP.NET features to add a login page, authentication, and authorization.
Walkthrough: Customizing a Web Site Using Themes in Visual Studio
Provides a tutorial on creating a consistent look for pages in your Web site.
Walkthrough: Creating and Using ASP.NET Master Pages in Visual Web Developer
Provides a tutorial on creating a consistent layout for pages in your Web site.
Walkthrough: Creating a Web Parts Page in Visual Web Developer
Provides a tutorial on creating ASP.NET Web pages that users can customize using their browser.
Walkthrough: Creating Reusable Elements with ASP.NET User Controls
Provides a tutorial on using the Visual Web Developer designer to create a composite control that you can add to any
ASP.NET Web page.
Walkthrough: Adding Site Navigation to a Web Site
Provides a tutorial on using site maps and creating navigation using a menu, a tree view, and a site map path control
(sometimes referred to as a breadcrumb).
Walkthrough: Creating a Web Site with Membership and User Login (Visual Studio)
Provides a tutorial on using login controls to add a login page, authentication, and authorization.
Managing Web Sites
Walkthrough: Editing Web Sites with FTP in Visual Web Developer
Provides a tutorial on creating a Web site in a local folder on your computer and testing it using the ASP.NET Development
Server.
Walkthrough: Maintaining Web Site User Information with Profile Properties
Provides a tutorial on using ASP.NET profiles to gather information from users and store it for use each time they visit.
Walkthrough: Debugging Web Pages in Visual Web Developer
Provides a tutorial on using the integrated debugger in the Visual Web Developer designer to find errors in your code.
Walkthrough: Copying a Web Site Using the Copy Web Site Tool
Provides a tutorial on synchronizing local and remote versions of a Web site.
Walkthrough: Using Output Caching to Enhance Web Site Performance
Provides a tutorial on storing pages and application data in memory for faster performance.
Walkthrough: Using Resources for Localization with ASP.NET
Provides a tutorial on creating Web pages that can display information in different languages.
See Also
Concepts
How Do I in Visual Web Developer
Visual Web Developer

Globalization (How Do I in Visual Web Developer)


This page links to help on widely used tasks for creating Web pages that can be used with different languages and cultures. To
view other categories of popular tasks covered in Help, see How Do I in Visual Web Developer.
Walkthroughs
Walkthrough: Using Resources for Localization with ASP.NET
Provides a tutorial on creating Web pages that can display information in different languages.
Resources
ASP.NET Web Page Resources Overview
Provides information on using resource files (.resx files) to store language-specific and locale-specific text.
How to: Create Resource Files for ASP.NET Web Sites (Visual Studio)
Provides steps for creating .resx files that store text in different languages and for different cultures that can be displayed in
an ASP.NET Web page.
How to: Use Resources to Set Property Values in Web Server Controls
Provides steps for configuring controls to read property values from .resx files to dynamically display pages in different
languages.
How to: Retrieve Resource Values Programmatically
Provides steps for programmatically reading values from a language-specific and culture-specific .resx file.
Additional Globalization Techniques
How to: Localize Site-Map Data
Provides steps creating site maps that present information in different languages.
Bidirectional Support for ASP.NET Web Applications
Provides information on creating ASP.NET Web pages to be displayed in bidirectional languages.
How to: Set the Culture and UI Culture for ASP.NET Web Page Globalization
Provides steps for configuring pages and Web sites to format dates, currency, and other culture-dependent values.
How to: Select an Encoding for ASP.NET Web Page Globalization
Provides steps for encoding page content and reading encoded browser information.
How to: Display Right-to-Left Text Using HTML Tags for Globalization
Provides steps for setting attributes in HTML elements to specify the direction in which text is displayed.
See Also
Concepts
How Do I in Visual Web Developer
Visual Web Developer

Security (How Do I in Visual Web Developer)


This page links to help on important information about securing your Web site. To view other categories of popular tasks
covered in Help, see How Do I in Visual Web Developer.
Walkthroughs
Walkthrough: Creating a Web Site with Membership and User Login (Visual Studio)
Provides a tutorial on adding Web site security using ASP.NET features to add a login page, authentication, and authorization.
Walkthrough: Managing Web Site Users with Roles
Provides a tutorial on assigning users to roles and securing resources based on roles.
Walkthrough: Encrypting Configuration Information Using Protected Configuration
Provides a tutorial on encrypting a portion of the Web.config file to protect sensitive information.
Security Guidelines
Securing Membership
Provides guidelines for improving the security of ASP.NET membership to create and manage users.
Securing Standard Controls
Provides guidelines for improving the security of form controls such as the AdRotator, TextBox, and ListBox controls.
Securing Roles
Provides guidelines for improving the security of using ASP.NET roles to manage authorization.
Securing ASP.NET Site Navigation
Provides guidelines for improving the security of site maps and navigation controls.
Securing Browser Definition Files
Provides guidelines for improving the security of the .browser files in which information about capabilities of individual
browsers is stored.
Securing Data Access
Provides guidelines for improving the security of data access in ASP.NET Web applications.
Securing Login Controls
Provides guidelines for improving the security of any Login, CreateUserWizard, PasswordRecovery, and other login
controls in your Web site.
Securing Profile Properties
Provides guidelines for improving the security of using ASP.NET profiles to create and manage user-specific information.
Securing Web Parts Pages
Provides guidelines for improving the security of ASP.NET Web pages that users can customize in their browser.
Securing Session State
Provides guidelines for improving the security of storing user-specific information in server memory.
Securing View State
Provides guidelines for improving the security of information stored by the ASP.NET page framework (and optionally by
you) in ASP.NET pages.
Securing ASP.NET Configuration
Provides guidelines for improving the security of .NET Framework configuration files.
Securing ASP.NET Health Monitoring
Provides guidelines for improving the security of raising Web events and handling them with built-in or custom providers.
General Security Practices
Basic Security Practices for Web Applications (Visual Studio)
Provides general information on security issues and security practices that apply to all Web sites.
Storing Sensitive Information Using ASP.NET
Provides guidelines for helping keep passwords and other sensitive information secure.
How to: Protect Against Script Exploits in a Web Application by Applying HTML Encoding to Strings
Provides steps for preventing malicious users from forcing unwanted code to run in your Web application.
How to: Display Safe Error Messages
Provides steps for configuring your Web application for proper error handling and for displaying error messages that do not
disclose sensitive information.
Configuring ASP.NET Process Identity
Provides information about configuring your Web application to run as a specific Windows user identity.
How to: Build and Run the Protected Configuration Provider Example
Provides steps for creating a custom encryption component for encrypting configuration elements.
Identifying Users
How to: Create an ASP.NET Login Page
Provides steps for creating an ASP.NET Web page that uses the Login control to authenticate users through ASP.NET
membership.
How to: Add a Login Button to an ASP.NET Web Page
Provides steps for adding a link to pages that helps users log in and out of your Web application.
How to: Use Advanced Features of the ASP.NET Login Control
Provides steps for changing the default appearance of the Login control.
How to: Use Advanced Features of the ASP.NET Login Control
Provides steps for customizing the behavior of the Login control.
How to: Enable User Registration
Provides steps for enabling users to register on your Web site using the CreateUserWizard control and ASP.NET
membership.
How to: Display the Name of the Current User
Provides steps for using the LoginName control to display the user's logged-in name (or a login link).
How to: Display Different Information to Anonymous and Logged In Users (Visual Studio)
Provides steps for using the LoginView control to create one display for logged-in users and a different one for users who
are not yet logged in.
How to: Enable User Password Recovery Using the ASP.NET PasswordRecovery Control
Provides steps for using the PasswordRecovery control to enable users to have a new or recovered password e-mailed to
them.
How to: Customize the PasswordRecovery Control
Provides steps for changing the default appearance of the PasswordRecovery control.
How to: Implement Simple Forms Authentication
Provides steps for creating a custom authentication system where you create your own login page and authentication logic.
How to: Sample Membership Provider Implementation
Provides steps for creating a custom provider to create and manage membership information.
How to: Sample Role-Provider Implementation
Provides steps for creating a custom provider to create and manage role information.
Data Security
Securing Data Access
Provides guidelines for improving the security of data access in ASP.NET Web applications.
How To: Secure Connection Strings when Using Data Source Controls (Visual Studio)
Provides steps for encrypting connection strings for database access.
How to: Access SQL Server as a Local User
Provides steps for configuring your application to log into Microsoft SQL Server on the same computer as the Web server.
How to: Access SQL Server Using a Mapped Windows Domain User
Provides steps for configuring your application to log into SQL Server using a specific Windows user account.
How to: Access SQL Server Using Predetermined Credentials
Provides steps for configuring your application to log into SQL Server using a user name and password that you build into
your application.
How to: Access SQL Server Using Windows Integrated Security
Provides steps for configuring your application to log into SQL Server with the user's current Windows user account
information.
See Also
Concepts
How Do I in Visual Web Developer
Visual Web Developer

Troubleshooting (How Do I in Visual Web Developer)


This page links to help on widely used tasks for finding errors that can occur in your Web applications. To view other
categories of popular tasks covered in Help, see How Do I in Visual Web Developer.
Walkthroughs
Walkthrough: Debugging Web Pages in Visual Web Developer
Provides a tutorial on using the integrated debugger in the Visual Web Developer designer to find errors in your code.
Walkthrough: Using Tracing in Visual Web Developer to Help Find Web Page Errors
Provides a tutorial on displaying detailed diagnostic information about individual page requests.
Walkthrough: Listening for WMI Events in ASP.NET Health Monitoring
Provides a tutorial on creating a custom health event provider that interacts with Windows Management Instrumentation
(WMI).
Error Handling
Error Handling in ASP.NET Pages and Applications
Provides information on catching errors and on how error information is made available in pages and applications.
How to: Handle Page-Level Errors
Provides steps for catching unhandled exceptions in an ASP.NET Web page.
How to: Handle Application-Level Errors
Provides steps for creating a global error handler to catch unhandled errors anywhere in an ASP.NET Web application.
Tracing
How to: Enable Tracing for an ASP.NET Page
Provides steps for displaying diagnostic information in an ASP.NET Web page.
How to: Enable Tracing for an ASP.NET Application
Provides steps for capturing diagnostic information for all ASP.NET pages in a Web site.
How to: View ASP.NET Trace Information with the Trace Viewer
Provides steps for displaying diagnostic information for the last 10 requests.
Writing Custom ASP.NET Trace Messages
Provides information on writing custom messages into the diagnostic tracing display.
Reading ASP.NET Trace Information
Provides information on interpreting the diagnostic information displayed in pages or in the trace viewer.
Debugging
Debugging Web Pages Overview
Provides information about debugging Web applications in Visual Web Developer.
Walkthrough: Debugging Web Pages in Visual Web Developer
Provides a tutorial on how to use the debugger with Web pages.
Health Monitoring
Walkthrough: Listening for WMI Events in ASP.NET Health Monitoring
Provides a tutorial on creating a custom health event provider that interacts with WMI.
Configuring ASP.NET Health Monitoring
Provides information on ASP.NET configuration settings required to add built-in or custom health monitoring events or
providers to your application.
How to: Send E-mail for Health Monitoring Notifications
Provides steps for configuring an ASP.NET application to send an e-mail notification when an ASP.NET health-monitoring
Web event occurs.
How to: Implement and Raise Custom ASP.NET Health Monitoring Events
Provides steps for creating a custom Web event.
How to: Implement the Health Monitoring Custom Provider Example
Provides steps for creating a health monitoring example.
See Also
Concepts
How Do I in Visual Web Developer
Visual Web Developer

Web Page Controls (How Do I in Visual Web Developer)


This page links to help on widely used tasks for working with ASP.NET Web server controls. To view other categories of
popular tasks covered in Help, see How Do I in Visual Web Developer.
The information in this topic is subdivided into the following sections:
Walkthroughs
Creating and Editing Controls
Programming Controls
Standard Controls
Data Controls
Login Controls
Navigation Controls
User Controls
Validation Controls
Web Parts Controls
Walkthroughs
Walkthrough: Displaying and Tracking Advertisements with the AdRotator Control
Provides a tutorial on using the AdRotator control to display randomly selected advertisements that you create.
Walkthrough: Creating a Web Site with Membership and User Login (Visual Studio)
Provides a tutorial on using login controls to add a login page, authentication, and authorization.
Walkthrough: Displaying a Menu on Web Pages
Provides a tutorial on using the Menu control.
Walkthrough: Controlling ASP.NET Menus Programmatically
Provides a tutorial on working with the Menu control in code.
Walkthrough: Adding Site Navigation to a Web Site
Provides a tutorial on using navigation controls to create ways for users to move between pages in your Web site.
Walkthrough: Creating Reusable Elements with ASP.NET User Controls
Provides a tutorial on using the Visual Web Developer designer to create a composite control that you can add to any
ASP.NET Web page.
Walkthrough: Validating User Input in a Web Forms Page
Provides a tutorial on using the validator controls to check user input.
Walkthrough: Creating a Web Parts Page in Visual Web Developer
Provides a tutorial on using Web Parts controls to create ASP.NET Web pages that users can customize in a browser.
Walkthrough: Creating a Basic ASP.NET Wizard Control
Provides a tutorial on using the Wizard control.
Walkthrough: Advanced Use of the ASP.NET Wizard Control
Provides a tutorial on programmatically controlling the Wizard control.
Walkthrough: Displaying an XML Document in a Web Forms Page Using Transformations
Provides a tutorial on using the Xml control to display the contents of an XML document on a page.
Walkthrough: Creating Web Pages for Mobile Devices
Provides a tutorial on creating an ASP.NET Web page that uses controls designed especially for mobile devices.
Walkthrough: Creating an Accessible Web Application
Provides a tutorial on configuring Web server controls to create an ASP.NET Web page that can be accessed by people with
disabilities, including how to test accessibility.
Data (How Do I in Visual Web Developer)
Provides links to topics that describe how to use data controls to display and edit data on an ASP.NET Web page.
Creating and Editing Controls
How to: Add Web Server Controls to a Web Forms Page Using the Web Forms Designer
Provides steps for how to use designer features to create and edit Web server controls.
How to: Add Server Controls to an ASP.NET Web Page Using ASP.NET Syntax
Provides steps for adding controls to a page by editing the markup directly.
How to: Add HTML Server Controls to an ASP.NET Web Page Using the Designer
Provides steps for creating programmable HTML elements in the Visual Web Developer designer.
How to: Add HTML Server Controls to a Web Page Using ASP.NET Syntax
Provides steps for creating programmable HTML elements by editing the markup directly.
How to: Convert HTML Server Controls to HTML Elements (Visual Studio)
Provides steps for treating HTML elements as Web server controls.
How to: Specify Whether ASP.NET Web Server Controls Post to the Server
Provides steps for how to configure a control to cause the page to post back immediately when users select a value.
How to: Set ASP.NET Server Control Properties (Visual Studio)
Provides steps for how to use the Visual Web Developer designer to set control properties.
How to: Set Web Server Control Properties Based on Simple Values or Enumerations
Provides steps for how to set properties with text or integer values, or to one of a set of predefined values.
How to: Set Web Server Control Properties in Collections
Provides steps for how to set properties that contain multiple individual elements.
How to: Set Web Server Control Unit Properties
Provides steps for how to set sizes (such as height or width).
How to: Set Web Server Control Color Properties
Provides steps for how to set foreground and background colors.
How to: Set HTML Attributes for Controls in ASP.NET Web Pages
Provides steps for how to add HTML (or other markup) attributes to Web server controls, both declaratively and
programmatically.
How to: Set ASP.NET Server Control Style Properties Using ASP.NET Syntax
Provides steps for setting control properties by editing the markup directly.
How to: Set ASP.NET Server Control Style Properties in the Designer
Provides steps for using the Visual Web Developer designer to set individual style properties.
How to: Use Resources to Set Property Values in Web Server Controls (Visual Studio)
Provides steps for how to configure controls to read property values from resource (.resx) files to dynamically display pages
in different languages.
How to: Set Access Keys for ASP.NET Web Server Controls
Provides steps for how to configure controls so that users can jump to them using ALT-key combinations.
Programming Controls
How to: Create Event Handlers in ASP.NET Web Pages (Visual Studio)
Provides steps for writing code that responds to events in the page and in controls, using the Visual Web Developer
designer.
How to: Connect Multiple Events to a Single Event Handler in ASP.NET Web Pages
Provides steps for writing code that can respond to events from different controls, using the Visual Web Developer designer.
How to: Determine which Web Server Control Raised an Event
Provides steps for using event information to determine the source of an event.
How to: Read HTML Attributes for Controls in Web Forms Pages
Provides steps for reading attributes from control markup that are not exposed as properties.
How to: Set Focus on ASP.NET Web Server Controls
Provides steps for setting the focus on a control when the page runs.
How to: Respond to Button Web Server Control Events in Client Script
Provides steps for adding a client-script event handler to an ASP.NET Web server button control.
How to: Set ASP.NET Server Control Style Properties Programmatically
Provides steps for using code to work with style properties of a control.
How to: Set HTML Server Control Properties Programmatically
Provides steps for using code to set attributes of HTML elements.
How to: Add Controls to an ASP.NET Web Page Programmatically
Provides steps for using code to create control instances and add them to the page.
How to: Locate the Web Forms Controls on a Page by Walking the Controls Collection
Provides steps for using code to find a specific control on a page.
How to: Access Members of a Web Server Control's Naming Container
Provides steps for using code to find a specific control on a page.
How to: Locate Child Controls by ID in an ASP.NET Web Page
Provides steps for using code to find a specific control on a page.
Standard Controls
How to: Display Ads From an XML File Using the AdRotator Web Server Control
Provides steps for displaying advertisement information from an XML file in the AdRotator control.
How to: Display Ads From a Database Using the AdRotator Web Server Control
Provides steps for displaying advertisement information from a database in the AdRotator control.
How to: Select Ads in an AdRotator Web Server Control Programmatically
Provides steps for displaying specific ads in the AdRotator control.
How to: Add BulletedList Web Server Controls to a Web Forms Page (Visual Studio)
Provides steps for creating a BulletedList control using the Visual Web Developer designer.
How to: Respond to User Clicks in BulletedList Web Server Controls (Visual Studio)
Provides steps for running code when users select an item in a BulletedList control.
How to: Add Button Web Server Controls to a Web Forms Page (Visual Studio)
Provides steps for creating Button, LinkButton, and ImageButton controls using the Visual Web Developer designer.
How to: Respond to Button Web Server Control Events
Provides steps for running code when users click a Button, LinkButton, or ImageButton control.
How to: Determine Coordinates in an ImageButton Web Server Control
Provides steps for reading the x and y coordinates of where a user clicked in an ImageButton control.
How to: Customize Calendar Web Server Control Appearance
Provides steps for changing the default look of the Calendar control.
How to: Customize Individual Days in a Calendar Web Server Control
Provides steps for changing the default look of days in the Calendar control.
How to: Format Calendar Web Server Control Elements Using Styles
Provides steps for setting the look of days, weeks, months, weekends and other elements in a Calendar control.
How to: Control User Date Selection in a Calendar Web Server Control
Provides steps for enabling users to select single dates, weeks, or months in a Calendar control.
How to: Control Month Navigation in a Calendar Web Server Control
Provides steps for enabling users to navigate from month to month using a Calendar control.
How to: Respond to Date Selection in a Calendar Web Server Control
Provides steps for running code when users select a date in the Calendar control.
How to: Read Selected Dates in the Calendar Web Server Control
Provides steps for reading the user's selection in a Calendar control.
How to: Set Today's Date Programmatically in a Calendar Web Server Control
Provides steps for setting the current date in a Calendar control.
How to: Select Dates Programmatically in a Calendar Web Server Control
Provides steps for making a date selection in code in a Calendar control.
How to: Display Selected Dates from a Database in the Calendar Control
Provides steps for reading dates from a database and displaying them in a Calendar control.
How to: Add CheckBox Web Server Controls to a Web Forms Page (Visual Studio)
Provides steps for creating a CheckBox control using the Visual Web Developer designer.
How to: Get and Set a CheckBox Web Server Control Value Programmatically
Provides steps for reading and writing the selection in a CheckBox control.
How to: Add CheckBoxList Web Server Controls to a Web Forms Page (Visual Studio)
Provides steps for creating a CheckBoxList control using the Visual Web Developer designer. You can use this control to
display true/false choices from a database or other source.
How to: Set Layout in a CheckBoxList Web Server Control
Provides steps for specifying whether a CheckBoxList control is displayed in rows or columns.
How to: Respond to User Selection in a CheckBox Web Server Control
Provides steps for running code when users select an item in a CheckBoxList control.
How to: Set Layout in a RadioButtonList Web Server Control
Provides steps for specifying whether a CheckBoxList control is displayed in rows or columns.
How to: Add DropDownList Web Server Controls to a Web Forms Page (Visual Studio)
Provides steps for creating a DropDownList control using the Visual Web Developer designer.
How to: Upload Files with the FileUpload Web Server Control
Provides steps for creating a FileUpload control using the Visual Web Developer designer. This control enables users to
send files to the server from their computer.
How to: Add HyperLink Web Server Controls to a Web Forms Page (Visual Studio)
Provides steps for creating a Hyperlink control using the Visual Web Developer designer.
How to: Add Image Web Server Controls to a Web Forms Page (Visual Studio)
Provides steps for creating an Image control using the Visual Web Developer designer.
How to: Add ImageButton Web Server Controls to a Web Forms Page (Visual Studio)
Provides steps for creating an ImageButton control using the Visual Web Developer designer.
How to: Add ImageMap Web Server Controls to a Web Page (Visual Studio)
Provides steps for creating an ImageMap control using the Visual Web Developer designer.
How to: Respond to User Clicks in ImageMap Web Server Controls
Provides steps for running code when users click a hot spot in an ImageMap control.
How to: Add Label Web Server Controls to a Web Forms Page (Visual Studio)
Provides steps for creating a Label control using the Visual Web Developer designer.
How to: Use Label Web Server Controls as Captions
Provides steps for associating a Label control with another control and using it as a caption with an optional shortcut key.
How to: Add ListBox Web Server Controls to a Web Forms Page (Visual Studio)
Provides steps for creating a ListBox control using the Visual Web Developer designer.
How to: Add Literal Web Server Controls to a Web Forms Page (Visual Studio)
Provides steps for creating a Literal control using the Visual Web Developer designer. This is a way to add static text to the
page in code.
How to: Add MultiView Web Server Controls to a Web Forms Page (Visual Studio)
Provides steps for creating MultiView and View controls using the Visual Web Developer designer.
How to: Add Panel Controls to a Web Forms Page (Visual Studio)
Provides steps for creating a Panel control using the Visual Web Developer designer. You can use this control as the
container for other controls.
How to: Add PlaceHolder Web Server Controls to a Web Forms Page (Visual Studio)
Provides steps for creating a Placeholder control using the Visual Web Developer designer. You can use this control as the
container for other controls.
How to: Add RadioButton Web Server Controls to a Web Forms Page (Visual Studio)
Provides steps for creating a RadioButton control using the Visual Web Developer designer.
How to: Respond to a User Selection in a RadioButton Web Server Control Group
Provides steps for running code when users click a RadioButton control.
How to: Set and Get the Selection in a RadioButton Web Server Control
Provides steps for reading and writing the selection in a RadioButton control, whether singly or in a group.
How to: Add RadioButtonList Web Server Controls to a Web Forms Page (Visual Studio)
Provides steps for creating a RadioButtonList control using the Visual Web Developer designer. You can use this control to
display mutually exclusive choices from a database or other source.
How to: Add Table Web Server Controls to a Web Forms Page (Visual Studio)
Provides steps for creating a Table control, which enables you to manage tables on the page in code.
How to: Add Rows and Cells Dynamically to a Table Web Server Control
Provides steps for using code to create rows and cells in a Table control.
How to: Set a TextBox Web Server Control for Password Entry
Provides steps for configuring a TextBox control to display text as stars or dots.
How to: Specify Multiline Input for a TextBox Web Server Control
Provides steps for configuring a TextBox control to enable users to enter more than one line of text.
How to: Get and Set Values in TextBox Web Server Controls
Provides steps for reading and writing the value in a TextBox control.
How to: Respond to Changes in a TextBox Web Server Control
Provides steps for running code when users change text in a TextBox control.
How to: Add XML Web Server Controls to a Web Forms Page (Visual Studio)
Provides steps for creating an Xml control using the Visual Web Developer designer. This control enables you to display an
XML document on the page.
How to: Load XML Data in the XML Web Server Control
Provides steps for configuring an Xml control to display an XML document or XML stream.
How to: Transform XML Data in the XML Web Server Control
Provides steps for using a transformation with the Xml control to customize the display of XML data.
How to: Add Items in List Web Server Controls (Visual Studio)
Provides steps for adding elements to a BulletedList, CheckBoxList, DropDownList, ListBox, or RadioButtonList control
using the Visual Web Developer designer.
How to: Set the Selection in List Web Server Controls (Visual Studio)
Provides steps for specifying the current item in a CheckBoxList, DropDownList, ListBox, or RadioButtonList control.
How to: Determine the Selection in List Web Server Controls
Provides steps for using code to read the current element in a CheckBoxList, DropDownList, ListBox, or RadioButtonList
control.
How to: Respond to Changes in List Web Server Controls
Provides steps for running code when users select an item in a CheckBoxList, DropDownList, ListBox, or RadioButtonList
control.
How to: Populate List Web Server Controls from a Data Source (Visual Studio)
Provides steps for binding the BulletedList, CheckBoxList, DropDownList, ListBox, or RadioButtonList control to data in
a database.
Data Controls
How to: Add DataList Web Server Controls to an ASP.NET Web Page (Visual Studio)
Provides steps for creating a DataList control, which enables you to display data in an HTML table using a layout you define.
Walkthrough: Displaying and Formatting Data with the DataList Web Server Control
Provides a tutorial on creating a DataList control, which enables you to display data in an HTML table using a layout you
define.
How to: Allow Users to Delete Items in DataList Web Server Controls
Provides steps on configuring the DataList control to enable users to delete data records.
How to: Allow Users to Edit Items in DataList Web Server Controls
Provides steps on configuring the DataList control to enable users to edit data records.
How to: Allow Users to Select Items in DataList Web Server Controls
Provides steps on configuring the DataList control to enable users to select (highlight) a specific item.
How to: Customize Items Dynamically in the DataList Web Server Control
Provides steps for how to use code to change the look or behavior of items in a DataList control at run time.
How to: Specify Flow or Table Format in DataList Web Server Controls
Provides steps for how to set the layout of a DataList control.
How to: Specify Horizontal or Vertical Layout in DataList Web Server Controls
Provides steps for how to set the layout of a DataList control.
Walkthrough: Editing and Inserting Data in Web Pages with the DetailsView Web Server Control
Provides a tutorial on using a DetailsView control to enable users to edit existing records and create new ones.
Modifying Data Using a DetailsView Web Server Control
Provides information on using the DetailsView control to enable users to edit data one record at a time.
Paging in a DetailsView Web Server Control
Provides information on configuring the DetailsView control to enable users to page through multiple records, one at a
time.
Walkthrough: Displaying Formatted Data in Web Pages with the FormView Web Server Control
Provides a tutorial on using a FormView control to display a single record at a time, using free-form layout templates that
you define.
Modifying Data Using a FormView Web Server Control
Provides steps on using a FormView control to enable users to edit data one record at a time.
Paging in a FormView Web Server Control
Provides information on configuring the FormView control to enable users to page through multiple records, one at a time.
Walkthrough: Basic Data Access in Web Pages
Provides a tutorial on how to use the GridView control and SqlDataSource controls to display data on an ASP.NET Web
page.
Walkthrough: Creating a Web Page to Display Access Database Data
Provides a tutorial on how to use the GridView control and AccessDataSource controls to display data from a Microsoft
Access database on an ASP.NET Web page.
Walkthrough: Creating Master/Detail Web Pages in Visual Studio
Provides a tutorial on how to use the DropDownList, GridView, DetailsView, and SqlDataSource controls to create pages
that display lists of data where the user can select an individual record to examine further.
Walkthrough: Simple Sorting for the GridView Web Server Control
Provides a tutorial on how to use built-in features of the GridView control to enable users to sort the displayed data.
How to: Customize Controls for Editing in the GridView Web Server Control
Provides steps on configuring the GridView control to display the controls that you choose when in edit mode.
How to: Set GridView Web Server Control Column Width Dynamically
Provides steps for how to set column widths in the GridView according to the width of the data being displayed.
How to: Respond to Button Events in Data-Bound Controls
Provides steps for how to handle events raised by button controls in list data controls such as the GridView, DataList, and
Repeater controls.
How to: Enable Default Deleting in the GridView Web Server Control
Provides steps on configuring the GridView control to enable users to delete data records.
How to: Enable Default Editing in the GridView Web Server Control
Provides steps on configuring the GridView control to enable users to edit data records.
How to: Enable Default Paging in the GridView Web Server Control
Provides steps on configuring the GridView control to enable users to page through long lists of data records.
Walkthrough: Data Binding to a Custom Business Object
Provides a tutorial on how to use the ObjectDataSource control to create multi-tier data access in an ASP.NET Web
application.
Walkthrough: Data Binding Web Pages with a Visual Studio Data Component
Provides a tutorial on how to use Visual Studio tools to create a data-access object that you can use with the
ObjectDataSource control.
How to: Add Repeater Web Server Controls to a Web Forms Page (Visual Studio)
Provides steps for creating a Repeater control, which enables you to display data on an ASP.NET Web page using free-form
layout templates that you define.
How to: Enable Filtering for SqlDataSource Controls (Visual Studio)
Provides steps for how to configure a SqlDataSource control to enable the results of a query to be further refined with
filtering.
How to: Respond to Button Events in DataList, Repeater, or GridView Items
Provides steps for how to handle events raised by button controls in list data controls such as the GridView, DataList, and
Repeater controls.
Walkthrough: Displaying Hierarchical Data in a TreeView Control
Provides a tutorial on using the TreeView control to display XML data.
How to: Create ASP.NET Web Control Templates Declaratively
Provides steps for creating templates in the GridView, DetailsView, FormView, DataList, and Repeater controls by editing
the markup directly.
How to: Bind to Data in a Templated Control
Provides steps on adding data-bound controls to templates in controls such as the GridView, DetailsView, FormView,
DataList, and Repeater controls.
How To: Create ASP.NET Web Server Control Templates Dynamically
Provides steps for creating templates in the GridView, DetailsView, FormView, DataList, and Repeater controls in code.
Login Controls
Walkthrough: Creating a Web Site with Membership and User Login (Visual Studio)
Provides a tutorial on using login controls to add a login page, authentication, and authorization.
How to: Add a Login Button to an ASP.NET Web Page
Provides steps for adding a link to pages that helps users log in and out of your Web application.
How to: Use Advanced Features of the ASP.NET Login Control
Provides steps for changing the default appearance of the Login control.
How to: Customize the PasswordRecovery Control
Provides steps for changing the default appearance of the PasswordRecovery control.
How to: Create an ASP.NET Login Page
Provides steps for creating an ASP.NET Web page that uses the Login control to authenticate users through ASP.NET
membership.
How to: Enable User Registration
Provides steps for enabling users to register on your Web site using the CreateUserWizard control and ASP.NET
membership.
How to: Enable User Password Recovery Using the ASP.NET PasswordRecovery Control
Provides steps for using the PasswordRecovery control to enable users to have a new or recovered password e-mailed to
them.
How to: Use Advanced Features of the ASP.NET Login Control
Provides steps for customizing the behavior of the Login control.
How to: Display the Name of the Current User
Provides steps for using the LoginName control to display the user's logged-in name (or a login link).
How to: Display Different Information to Anonymous and Logged In Users (Visual Studio)
Provides steps for using the LoginView control to create one display for logged-in users and a different one for users who
are not yet logged in.
Navigation Controls
How to: Display Site-Map Data in Non-Hierarchical Web Server Controls
Provides steps for using a control such as a DropDownList control to work with site map data.
Walkthrough: Controlling ASP.NET Menus Programmatically
Provides a tutorial on how to work with the Menu control in code.
How to: Customize the Appearance of SiteMapPath Web Server Controls
Provides steps for changing the default appearance of the SiteMapPath control.
How to: Filter the Nodes Retrieved by SiteMapDataSource Web Server Controls
Provides steps for programmatically determining what site map information to display to users.
How to: Add or Delete TreeView Node Elements (Visual Studio)
Provides steps for populating a TreeView control with static nodes.
How to: Customize the ASP.NET CreateUserWizard Control
Provides steps for changing the default appearance of a Wizard control.
User Controls
How to: Create ASP.NET User Controls (Visual Studio)
Provides steps on using the Visual Web Developer designer to create a composite control that you can add to any ASP.NET
Web page.
How to: Convert Web Forms Pages into ASP.NET User Controls
Provides steps on configuring an existing ASP.NET Web page to be a user control.
How to: Include ASP.NET User Controls in Web Pages (Visual Studio)
Provides steps on adding a user control to an ASP.NET Web page in the Visual Web Developer designer.
How to: Create Instances of ASP.NET User Controls Programmatically
Provides steps on programmatically creating user controls and adding them to an ASP.NET Web page.
Validation Controls
How to: Validate Required Entries for ASP.NET Server Controls
Provides steps for preventing users from skipping a field in a page.
How to: Validate Against a Specific Value for ASP.NET Server Controls
Provides steps for requiring users to enter one of a specific set of values.
How to: Validate Against a Data Type for ASP.NET Server Controls
Provides steps for requiring users to enter a value that is an integer, date, or other type.
How to: Validate Against Patterns for ASP.NET Server Controls
Provides steps for requiring users to enter a value that matches a certain pattern, such as a phone number or e-mail address.
How to: Validate Against a Range of Values for ASP.NET Server Controls
Provides steps for requiring users to enter a value that is between a minimum and maximum value (numbers or text).
How to: Validate Against Values in a Database for ASP.NET Server Controls
Provides steps for using custom logic to look up values in a database to check a user's entry.
How to: Disable Validation for ASP.NET Server Controls
Provides steps for conditionally turning off validation.
How to: Validate with a Custom Function for ASP.NET Server Controls
Provides steps for creating your own logic for validating user entries.
How to: Test Validity Programmatically for ASP.NET Server Controls
Provides steps for determining in code whether validation checks have passed or failed.
How to: Validate Programmatically for ASP.NET Server Controls
Provides steps for using code to trigger the check for one or more validation controls.
How to: Display Server Side Custom Validation Messages for ASP.NET Server Controls
Provides steps for changing the appearance and text for validation errors.
How to: Control Validation Error Message Display for ASP.NET Server Controls
Provides steps for configuring validation controls to specify how and where error messages appear.
How to: Format Validation Error Messages for ASP.NET Server Controls
Provides steps for using HTML and properties to customize the look of validation error messages.
How to: Specify Layout for In-Place Messages On ASP.NET Server Controls
Provides steps for specifying whether validation controls take up space on the page when not displaying an error message.
Web Parts Controls
Web Parts Control Set Overview
Provides information on different pieces you can use to create customizable ASP.NET Web pages.
Walkthrough: Creating a Web Parts Page in Visual Web Developer
Provides a tutorial on using Web Parts controls to create ASP.NET Web pages that users can customize in a browser.
Web Parts Personalization Overview
Provides information on tracking customizations for individual users.
Walkthrough: Implementing Web Parts Personalization with a User Control
Provides a tutorial on how to create an ASP.NET user control (rather than a custom control) to track user-specific
information.
Walkthrough: Changing Display Modes on a Web Parts Page
Provides a tutorial on how to create a page where users can switch between display and edit modes to customize the page.
How to: Treat a User Control as a Web Parts Control
Provides steps for how to create an ASP.NET user control (rather than a custom control) to track user-specific information.
How to: Declare a Static Connection between Two Web Parts Controls
Provides steps for creating a static link between Web Parts controls declaratively.
How to: Enable Shared Personalization of Web Parts Pages
Provides steps for configuring Web Parts personalization so that user information is available to other users.
See Also
Concepts
How Do I in Visual Web Developer
Visual Web Developer

Web Pages (How Do I in Visual Web Developer)


This page links to help on widely used tasks for creating and programming ASP.NET Web pages using Visual Web Developer.
To view other categories of popular tasks covered in Help, see How Do I in Visual Web Developer.
Walkthroughs
Walkthrough: Creating a Basic Web Page in Visual Web Developer
Provides a tutorial on creating and editing an ASP.NET Web page in Visual Web Developer, including an overview of the Web
development environment.
Walkthrough: Creating a Basic Web Page with Code Separation in Visual Web Developer
Provides a tutorial on how to work with ASP.NET code-behind pages in the Visual Web Developer designer.
Walkthrough: Basic HTML Editing in Visual Web Developer
Provides a tutorial on working with markup (HTML) in the Visual Web Developer designer.
Walkthrough: Advanced HTML Editing in Visual Web Developer
Provides a tutorial on additional HTML editing features in the Visual Web Developer designer.
Walkthrough: Editing HTML Tables in Visual Web Developer
Provides a tutorial on adding and editing HTML tables in the Visual Web Developer designer.
Walkthrough: Working with Cascading Style Sheet Styles in Visual Web Developer
Provides a tutorial on features in the Visual Web Developer designer that help you create styles and cascading style sheets.
Walkthrough: Code Editing in Web Pages in Visual Web Developer
Provides a tutorial on features of the code editor in the Visual Web Developer designer that help you create code quickly and
accurately.
Walkthrough: Debugging Web Pages in Visual Web Developer
Provides a tutorial on using the integrated debugger in the Visual Web Developer designer to find errors in your code.
Walkthrough: Displaying a Menu on Web Pages
Provides a tutorial on creating Web page menus.
Walkthrough: Customizing a Web Site Using Themes in Visual Studio
Provides a tutorial on creating a consistent look for pages in your Web site.
Walkthrough: Creating and Using ASP.NET Master Pages in Visual Web Developer
Provides a tutorial on creating a consistent layout for pages in your Web site.
Walkthrough: Creating a Web Parts Page in Visual Web Developer
Provides a tutorial on creating ASP.NET Web pages that users can customize in a browser.
Walkthrough: Using Shared Code in Web Sites in Visual Web Developer
Provides a tutorial on creating and using components in an ASP.NET Web site without having to compile them.
Walkthrough: Creating Web Pages for Mobile Devices
Provides a tutorial on creating an ASP.NET Web page that uses controls designed especially for mobile devices.
Walkthrough: Validating User Input in a Web Forms Page
Provides a tutorial on checking user input in an ASP.NET Web page.
Walkthrough: Using Resources for Localization with ASP.NET
Provides a tutorial on creating Web pages that can display information in different languages.
Walkthrough: Creating an Accessible Web Application
Provides a tutorial on creating an ASP.NET Web page that can be accessed by people with disabilities, including how to test
accessibility.
Walkthrough: Using Output Caching to Enhance Web Site Performance
Provides a tutorial on storing pages in memory for faster performance.
Walkthrough: Using ASP.NET Output Caching with SQL Server
Provides a tutorial on caching pages that are removed from the cache only when their dependent data in SQL Server
changes.
Creating and Editing Web Pages
How to: Add ASP.NET Web Pages to a Web Site (Visual Studio)
Provides steps for creating ASP.NET Web pages using Visual Web Developer.
How to: Test Web Pages in Visual Web Developer
Provides steps for testing Web pages while working in the Visual Web Developer designer.
How to: Add Cascading Style Sheet Attributes in Design View
Provides steps for editing styles and cascading style sheets in the Visual Web Developer designer.
How to: Link Cascading Style Sheets to ASP.NET Web Pages (Visual Studio)
Provides steps for adding a cascading style sheet link to an ASP.NET Web page in the Visual Web Developer designer.
How to: Precompile ASP.NET Web Sites
Provides steps for compiling an entire Web site to check pages for errors or for deployment to a production server.
How to: Redirect Users to Another Page
Provides steps for programmatically navigating to another Web page.
Layout and Appearance
ASP.NET Master Pages Overview
Provides information on using master pages to create a consistent layout in your Web site.
How to: Create Content Pages for an ASP.NET Master Page (Visual Studio)
Provides steps for how to create content to merge with a master page using the Visual Web Developer designer.
How to: Reference ASP.NET Master Page Content
Provides steps for how to programmatically read information from a master page.
How to: Add Cascading Style Sheet Attributes in Design View
Provides steps for how to create style rules for individual elements in a Web page using the Visual Web Developer designer.
How to: Create External Cascading Style Sheets (Visual Studio)
Provides steps for creating a new cascading style sheet and adding rules to it, and steps for how to configure the Visual Web
Developer designer to validate against a specific CSS schema.
How to: Define ASP.NET Page Themes (Visual Studio)
Provides steps for how to create a collection of control properties and styles that you can apply as a unit to pages or Web
sites.
How to: Apply ASP.NET Themes
Provides steps for how to apply an existing theme to pages or to a Web site.
How to: Apply ASP.NET Themes Programmatically
Provides steps for how to apply a theme in code.
How to: Disable ASP.NET Themes
Provides steps for how to prevent a theme from being applied to an individual page or to a Web site.
Programming ASP.NET Web Pages
How to: Create Event Handlers in ASP.NET Web Pages (Visual Studio)
Provides steps for how to write code that responds to events in the page and in controls, using the Visual Web Developer
designer.
How to: Connect Multiple Events to a Single Event Handler in ASP.NET Web Pages
Provides steps for how to write code that can respond to events from different controls, using the Visual Web Developer
designer.
How to: Post ASP.NET Web Pages to a Different Page
Provides steps for how to create linked pages by posting one page to another.
How to: Detect Browser Types in ASP.NET Web Pages
Provides steps for how to read browser information to determine browser capabilities programmatically in an ASP.NET Web
page.
How to: Call a Web Service
Provides steps for how to programmatically invoke methods in an XML Web service.
Web Parts
ASP.NET Web Parts Overview
Provides information on Web Parts, which enable you to create pages that users can customize in their browsers.
Web Parts Control Set Overview
Provides information on different pieces you can use to create customizable ASP.NET Web pages.
Walkthrough: Creating a Web Parts Page in Visual Web Developer
Provides a tutorial on using Web Parts controls to create ASP.NET Web pages that users can customize in a browser.
Web Parts Personalization Overview
Provides information on tracking customizations for individual users.
Walkthrough: Implementing Web Parts Personalization with a User Control
Provides a tutorial on how to create an ASP.NET user control (rather than a custom control) to track user-specific
information.
Walkthrough: Changing Display Modes on a Web Parts Page
Provides a tutorial on how to create a page where users can switch between display and edit modes to customize the page.
How to: Treat a User Control as a Web Parts Control
Provides steps for how to create an ASP.NET user control (rather than a custom control) to track user-specific information.
How to: Declare a Static Connection between Two Web Parts Controls
Provides steps for creating a static link between Web Parts controls declaratively.
How to: Enable Shared Personalization of Web Parts Pages
Provides steps for configuring Web Parts personalization so that user information is available to other users.
State Management
How to: Write a Cookie
Provides steps for creating a cookie, which stores small amounts of data on the user's browser.
How to: Read a Cookie
Provides steps for programmatically reading a cookie stored earlier.
How to: Delete a Cookie
Provides steps for removing cookies from a user's computer.
How to: Pass Values Between ASP.NET Web Pages
Provides steps for storing values in one page that can be accessed in another page.
How to: Save Values in Application State
Provides steps for storing information in a global storage area that is available to all pages and components in a Web site.
How to: Read Values from Application State
Provides steps for reading global values.
How to: Save Values in Session State
Provides steps for storing user-specific information that is available as long as a user is working with pages in your Web site.
How to: Read Values from Session State
Provides steps for reading user-specific information that is available as long as a user is working with pages in your Web
site.
How to: Save Values in View State
Provides steps for storing information in a Web page while users are working with that page.
How to: Read Values from View State
Provides steps for reading information stored earlier in a page.
Client Script
How to: Add Client Script Events to ASP.NET Web Server Controls
Provides steps for writing client script in ASP.NET Web pages that responds to user actions such as mouse clicks.
How to: Create Scripts and Edit Event Handlers
Provides steps for writing client script while working in Source view of the Visual Web Developer designer.
How to: Respond to Button Web Server Control Events in Client Script
Provides steps for adding client-script event handling to ASP.NET button controls, even if the buttons also have server-side
event handlers.
How to: Add Client Script Dynamically to ASP.NET Web Pages
Provides steps for programmatically calling ASP.NET methods that inject client script into a page.
Performance
How to: Set the Cacheability of an ASP.NET Page Declaratively
Provides steps for setting a page's cache policy in markup.
How to: Set a Page's Cacheability Programmatically
Provides steps for setting a page's cache policy in code.
How to: Set Expiration Values for ASP.NET Page Caching
Provides steps for specifying when a page should be removed from the cache.
How to: Check the Validity of a Cached Page
Provides steps for determining whether a cached page has been invalidated.
How to: Cache Page Output with File Dependencies
Provides steps for caching different versions of a page based on changes to a file.
How to: Cache Page Output with Cache Key Dependencies
Provides steps for caching different versions of a page based on other information in the cache.
How to: Cache Versions of a Page Using Requesting Browser
Provides steps for caching different versions of a page based on information about the user's browser type.
How to: Cache Versions of a Page Using Parameters
Provides steps for caching different versions of a page based on information sent from the browser, such as query string or
post values.
How to: Cache Versions of a Page Using HTTP Headers
Provides steps for caching different versions of a page based on information sent in the browser headers, such as the
Accept-Language value.
How to: Cache Versions of a Page Using Custom Strings
Provides steps for caching different versions of a page based on a criterion that you create.
How to: Cache Multiple Versions of a User Control Based on Parameters
Provides steps for caching a portion of a page as a user control.
How to: Cache Multiple Versions of a User Control by Using Declarative Attributes
Provides steps for caching different portions of a page separately using the same user control.
Dynamically Updating Portions of a Cached Page
Provides information on caching some parts of a page while being able to update other parts of the page.
How to: Add Items to the Cache
Provides steps for storing information in the ASP.NET cache for quick retrieval.
How to: Retrieve Values of Cached Items
Provides steps for reading information stored previously in the cache.
How to: Delete Items from the Cache in ASP.NET
Provides steps for removing information you previously put in the cache.
How to: Notify an Application When an Item Is Removed from the Cache
Provides steps for raising an event when information is removed from the cache.
Caching in ASP.NET with the SqlCacheDependency Class
Provides information on caching pages that are removed from the cache only when their dependent data in SQL Server
changes.
Localization
How to: Create Resource Files for ASP.NET Web Sites
Provides steps for how to create resource (.resx) files that store text in different languages and for different cultures that can
be displayed in an ASP.NET Web page.
How to: Use Resources to Set Property Values in Web Server Controls (Visual Studio)
Provides steps for how to configure controls to read property values from .resx files to dynamically display pages in different
languages.
How to: Localize Site-Map Data
Provides steps for how to create site maps that present information in different languages.
How to: Retrieve Resource Values Programmatically
Provides steps for programmatically reading values from a language-specific and culture-specific .resx file.
Accessibility
Accessibility Support in ASP.NET
Provides information on features of ASP.NET that help you create Web sites that conform to accessibility standards.
How to: Check Accessibility of Web Pages in Visual Web Developer
Provides steps for validating in the Visual Web Developer designer that an ASP.NET Web page meets accessibility guidelines.
(This feature is not available in Visual Web Developer Express Edition.)
Devices and Browsers
Walkthrough: Creating Web Pages for Mobile Devices
Provides a tutorial on creating an ASP.NET Web page that uses controls designed especially for mobile devices.
See Also
Concepts
How Do I in Visual Web Developer
Visual Web Developer

Web Sites (How Do I in Visual Web Developer)


This page links to help on widely used information pertaining to creating and managing ASP.NET Web sites. To view other
categories of popular tasks covered in Help, see How Do I in Visual Web Developer.
Walkthroughs
Walkthrough: Creating a Basic Web Page in Visual Web Developer
Provides a tutorial on creating and editing an ASP.NET Web page in Visual Web Developer, including an overview of the Web
development environment.
Walkthrough: Creating a Basic Web Page with Code Separation in Visual Web Developer
Provides a tutorial on working with ASP.NET code-behind pages in the Visual Web Developer designer.
Walkthrough: Creating a Local IIS Web Site in Visual Web Developer
Provides a tutorial on creating a Web site under the IIS Web root on your own computer.
Walkthrough: Editing Web Sites with FTP in Visual Web Developer
Provides a tutorial on creating a Web site in a local folder on your computer and testing it using the ASP.NET Development
Server.
Walkthrough: Adding Site Navigation to a Web Site
Provides a tutorial on using site maps and creating navigation using a menu, a tree view, and a site map path control
(sometimes referred to as a breadcrumb).
Walkthrough: Creating a Web Site with Membership and User Login (Visual Studio)
Provides a tutorial on adding Web site security using ASP.NET features to add a login page, authentication, and authorization.
Walkthrough: Copying a Web Site Using the Copy Web Site Tool
Provides a tutorial on synchronizing local and remote versions of a Web site.
Walkthrough: Publishing a Web Site
Provides a tutorial on deploying your Web site to a production server.
Walkthrough: Displaying a Menu on Web Pages
Provides a tutorial on adding an application menu to pages on your site.
Walkthrough: Maintaining Web Site User Information with Profile Properties
Provides a tutorial on using ASP.NET profiles to gather information from users and store it for use each time they visit.
Walkthrough: Customizing a Web Site Using Themes in Visual Studio
Provides a tutorial on creating a consistent look for pages in your Web site.
Walkthrough: Creating and Using ASP.NET Master Pages in Visual Web Developer
Provides a tutorial on creating a consistent layout for pages in your Web site.
Walkthrough: Using Shared Code in Web Sites in Visual Web Developer
Provides a tutorial on creating and using components in an ASP.NET Web site without having to compile them.
Walkthrough: Creating and Using an ASP.NET Web Service in Visual Web Developer
Provides a tutorial on creating an XML Web service in Visual Web Developer, and a Web site that connects to the Web
service and calls its methods.
Walkthrough: Using Resources for Localization with ASP.NET
Provides a tutorial on creating Web pages that can display information in different languages.
Walkthrough: Creating an Accessible Web Application
Provides a tutorial on creating an ASP.NET Web page that can be accessed by people with disabilities, including how to test
accessibility.
Walkthrough: Using Output Caching to Enhance Web Site Performance
Provides a tutorial on storing pages in memory for faster performance.
Creating and Editing
Types of Web Sites in Visual Web Developer
Provides an overview of where you can create and edit the files for your Web sites, and what Web server or other software
you need in each case.
How to: Create File System Web Sites
Provides steps for how to create a Web site on your local computer even if you are not running Internet Information Services
(IIS).
How to: Create Local IIS Web Sites
Provides steps for how to create a Web site under the IIS Web root on your own computer.
How to: Create Remote IIS Web Sites
Provides steps for how to create a Web site under the IIS Web root on a remote computer.
How to: Create IIS Virtual Directories in Visual Web Developer
Provides steps for how to create a Web site using IIS in which files are stored in an arbitrary folder, not under the IIS Web site
root.
How to: Open Web Sites Using FTP
Provides steps for how to connect to and open a Web site on an FTP server.
How to: Add ASP.NET Web Pages to a Web Site (Visual Studio)
Provides steps for how to work with individual files in a Web site.
Navigation
ASP.NET Site Navigation Overview
Provides information on ASP.NET site maps (files that describe the site layout) and on ASP.NET controls that are designed for
adding navigation to Web pages.
How to: Add Simple Site Navigation
Provides steps for how to use a site map and navigation controls.
How to: Localize Site-Map Data
Provides steps for how to create site maps that present information in different languages.
How to: Customize the Appearance of SiteMapPath Web Server Controls
Provides steps for how to set the look and behavior of SiteMapPath controls (sometimes known as breadcrumbs).
How to: Display Site-Map Data in Non-Hierarchical Web Server Controls
Provides steps for how to use site maps with controls that do not inherently support hierarchies.
How to: Filter the Nodes Retrieved by SiteMapDataSource Web Server Controls
Provides steps for how to selectively display only some paths through your Web site.
Appearance
ASP.NET Themes and Skins Overview
Provides information on themes and skins, including what they are and how ASP.NET uses them to create a consistent look
for pages and controls.
How to: Define ASP.NET Page Themes (Visual Studio)
Provides steps for how to create a collection of control properties and styles that you can apply as a unit to pages or Web
sites.
How to: Apply ASP.NET Themes
Provides steps for how to apply an existing theme to pages or to a Web site.
How to: Apply ASP.NET Themes Programmatically
Provides steps for how to apply a theme in code.
How to: Disable ASP.NET Themes
Provides steps for how to prevent a theme from being applied to an individual page or to a Web site.
User Profiles
ASP.NET Profile Properties Overview
Provides an introduction to using ASP.NET profiles to gather information from users and store it for use each time they visit.
User Identification for ASP.NET Profile Properties
Provides information on how individual Web sites are identified, whether users visit anonymously or log in.
Defining ASP.NET Profile Properties
Provides information on how to create profile information for individual users.
Securing Profile Properties
Provides information on reducing the security vulnerability of maintaining profile properties.
Programming
How to: Create ASP.NET Application-Level Event Handlers
Provides steps for how to create code that runs each time the Web site starts or each time a page request is received.
Deploying
Web Site Deployment in Visual Web Developer
Provides information on options for making your Web site available on a production Web server.
How to: Copy Web Site Files with the Copy Web Site Tool
Provides steps for how to copy files to another server and synchronize local and remote versions of a Web site.
How to: Publish Web Sites (Visual Studio)
Provides steps for how to precompile your Web site and store the compiled version on a staging server or production server.
Accessibility
Accessibility Support in ASP.NET
Provides information on features of ASP.NET that help you create Web sites that conform to accessibility standards.
How to: Check Accessibility of Web Pages in Visual Web Developer
Provides steps for how to use a Visual Web Developer tool to review your Web pages for accessibility.
Configuring
How to: Add a Reference to a .NET or COM Component in a Web Site
Provides steps for how to make a .NET Framework or COM component available to code in your Web site.
How to: Add a Reference to a Visual Studio Project in a Web Site
Provides steps for how to make the output of another Visual Studio project (such as a component) available to code in your
Web site.
How to: Add and Remove Web References
Provides steps for how to make an XML Web service available to code in your Web site.
How to: Configure Published Web Sites
Provides steps for how to examine and change the configuration settings of a Web site after it is published.
How to: Configure ASP.NET Applications for an ASP.NET Version
Provides steps for how to set ASP.NET to use a specific version of the .NET Framework.
How to: Configure XHTML Rendering in ASP.NET Web Sites
Provides steps for how to configure ASP.NET controls so they render markup that conforms to specific XHTML standards.
Converting from Visual Studio .NET
Web Project Conversion from Visual Studio .NET
Provides an overview of converting Visual Studio .NET 2003 Web projects to Visual Web Developer.
Web Solution and Project File Conversion
Provides details about changes made to pages and to other files during conversion.
Web Project Settings Conversion
Provides information about what the conversion process does with project settings.
Troubleshooting Conversion to Visual Web Developer
Provides information about problems that might arise during conversion.
See Also
Concepts
How Do I in Visual Web Developer
Visual Web Developer

ASP.NET Web Sites (Visual Studio)


This section features content and topics related to creating ASP.NET Web sites in Visual Web Developer.
In This Section
Getting Started - Creating Web Sites
Provides essential information about how to create ASP.NET Web sites.
Learning More - Creating Web Sites
Provides in-depth information about working with ASP.NET Web sites.
Walkthrough Topics — ASP.NET Web Sites
Provides links to tutorials about creating ASP.NET Web sites in Visual Web Developer.
How-to Topics — ASP.NET Web Sites
Provides links to how-to topics about creating ASP.NET Web sites in Visual Web Developer.
Related Sections
Guided Tour of Creating Web Sites in Visual Web Developer
Provides links to tutorials on all aspects of creating ASP.NET Web sites and Web pages.
Visual Web Developer

Getting Started - Creating Web Sites


This section includes topics that provide an overview of creating different types of Web sites, working with Web servers and
Visual Web Developer, and testing Web sites.
In This Section
Types of Web Sites in Visual Web Developer
Local IIS Web Sites
File System Web Sites
FTP-Deployed Web Sites
Remote IIS Web Sites
Building Web Sites
How to: Add Files to ASP.NET Web Sites
Web Servers in Visual Web Developer
Using Visual Web Developer as a Non-Administrative User
Related Sections
ASP.NET Web Pages (Visual Studio)
Provides information about creating ASP.NET Web pages in Visual Web Developer.
Visual Web Developer

Types of Web Sites in Visual Web Developer


Describes how files are stored on your Web site, using either file-system based Web sites or those that require Internet
Information Services (IIS).
You can use Visual Studio to create and work with ASP.NET Web sites (which are also known as Web applications) in a variety
of configurations: local IIS sites, file-system sites, File Transfer Protocol (FTP)–deployed sites, and remote sites. For guidelines to
help you decide when to use each type of Web site, see the table in Choosing a Web Site Type later in this topic.
Local IIS Web Sites
Local IIS Web sites run using a copy of IIS that is installed on your computer. When you create a local IIS Web site, the pages
and folders for your site are stored in a folder under the default IIS folder for Web sites, which is located at
[drive]:\Inetpub\wwwroot. Visual Studio also creates the appropriate IIS configuration so that the Web site is recognized by IIS
as an application.
Note
To create a local IIS Web site, you need to have administrative privileges on the computer.

Alternatively, you can create an IIS virtual directory in Visual Studio. In this case, the pages and folders for your Web site can be
in any folder to which users have access, and a virtual directory in your local copy of IIS must point to the file location. For
more information, see ASP.NET Required Access Control Lists (ACLs).
Note
If you create a Web site whose name contains non-ANSI characters on IIS 5.1 or earlier, you will not be able to browse to the
site because those versions of IIS do not resolve URLs that contain non-ANSI characters.

File-System Web Sites


In a file-system Web site, you can create and edit files in any folder you like, whether on your local computer or in a folder on
another computer that you access via network share. You are not required to run IIS on your computer. Instead, you can test
pages by using the ASP.NET Development Server. For details, see Web Servers in Visual Web Developer.
Note
The ASP.NET Development Server cannot serve pages to another computer. Therefore, it is suitable only for testing pages loc
ally.

In a file-system Web site, static files, such as images and style sheets, are subject to ASP.NET authorization rules. For example,
static files in a file-system Web site will not be served to an anonymous user when anonymous access to those files is disabled.
However, when you create a Web site project in an HTTP location, IIS serves static files without using authorization rules.
You can create a file-system Web site and later create an IIS virtual directory that points to the folder containing your pages.
For details, see How to: Create IIS Virtual Directories in Visual Web Developer.
FTP-Deployed Web Sites
Visual Studio allows you to open and edit Web sites that are available on an FTP server. This is a typical scenario if your Web
site is located on a hosting site.
You can connect from within Visual Studio to any FTP server on which you have Read/Write permissions. You can then create
and edit Web pages on that server. If the FTP server is configured with ASP.NET and an IIS virtual root that points to the FTP
directory, you can also run your pages from the server to test them. For more information, see
Walkthrough: Editing Web Sites with FTP in Visual Web Developer.
Remote Web Sites
A remote Web site is a site that uses IIS but is on another computer that you can access over a local area network. The remote
computer must have IIS installed and be configured with FrontPage 2002 Server Extensions from Microsoft. When you create a
remote Web site, the pages and folders for your site are stored under the default IIS folder on the remote computer, which is
located at [drive]:\Inetpub\wwwroot. When you run the pages, they are served using IIS on the remote computer. This is the
model used in Visual Studio .NET 2002 and Visual Studio .NET 2003. For more information, see What's New in Web Projects.
Note
If you create a Web site whose name contains non-ANSI characters on IIS 5.1 or earlier, you will not be able to browse to the
site because those versions of IIS do not resolve URLs that contain non-ANSI characters.

Choosing a Web Site Type


The following table summarizes the types of Web sites that you can create in Visual Studio, which you can use when deciding
which type of Web site meets your needs.
Web site ty Summary
pe
Local IIS We Use a local IIS Web site when you want to create Web pages on your local computer and you have IIS installed.
b site
Advantages:
The site is accessible from other computers.
You can test with IIS features, such as HTTP-based authentication, application pooling, and ISAPI filters.
Disadvantages:
You must have administrative rights to create or debug an IIS Web site.
Only one user on the computer can debug an IIS Web site at one time.
By default, remote access is enabled for a local IIS Web site.

File-system Use a file-system Web site when you want to create Web pages on your local computer or on a shared drive and
Web site you do not have IIS installed.
Note
You can create a file-system Web site and later create an IIS virtual directory that points to the folder containing
your pages.

Advantages:
The site can be accessed only from the local computer, reducing security vulnerabilities.
You do not need to have IIS installed on your computer.
You do not need administrative rights to create or debug a local file-system Web site.
If the computer is configured to allow remote desktop connections, multiple users can create and debug loc
al file-system Web sites at the same time.
Disadvantages:
You cannot test a file-system Web site with IIS features, such as HTTP-based authentication, application pool
ing, and ISAPI filters.
FTP-deploy Use an FTP-deployed Web site when your site already exists on a remote computer that has been configured as a
ed Web site n FTP server. (For example, your Internet service provider (ISP) has provided space on a server.)
Advantages:
You can test the FTP-deployed Web site on the server where it will be deployed.
Disadvantages:
You do not have local copies of the FTP-deployed Web site files unless you copy them yourself.
You cannot create an FTP-deployed Web site — you can only open one.

Remote We Use a remote Web site when you want to create a Web site by using IIS running on a remote computer. The remo
b site te computer must be configured with FrontPage Server Extensions.
Advantages:
You can test the Web site on the server where it will be deployed.
Multiple developers can work with the same remote Web site at the same time.
Disadvantages:
Configuration for debugging a remote Web site can be complex.
Only one developer can debug the remote Web site at one time. All other requests are suspended while the
developer is stepping through code.

See Also
Tasks
How to: Create File System Web Sites
How to: Create IIS Virtual Directories in Visual Web Developer
Walkthrough: Creating a Basic Web Page in Visual Web Developer
Walkthrough: Creating a Local IIS Web Site in Visual Web Developer
Walkthrough: Editing Web Sites with FTP in Visual Web Developer
Concepts
File System Web Sites
Visual Web Developer

Visual Web Developer Starter Kits


The ASP.NET 2.0 Starter Kits are sample ASP.NET Web sites that provide code to accomplish common Web development tasks.
Each sample is complete and well documented so that you can use the code to quickly start your ASP.NET development
projects today. Some samples were created when Visual Studio 2005 was released and, through the support of the ASP.NET
community, more samples have been added.
Note
The ASP.NET 2.0 Starter Kits are unsupported samples. As a result, Microsoft Product Support Services cannot answer questi
ons about the starter kits. However, you can post questions about the starter kits on the ASP.NET forums Web site, where co
mmunity members who have experience with the kits can help you.

Starter Kits
The following table lists some of the many starter kits that are available on the
ASP.NET 2.0 Starter Kits for Visual Web Developer 2005 Web site.
Starter kit Description
Personal Web The Personal Web Site Starter Kit provides a typical, personal site that includes a photo album system. The kit a
Site Starter Kit lso includes static pages for a resume and additional links. The site background is available in your choice of w
hite or black; just change the theme.

Club Site Start The Club Site Starter Kit provides a starting point for creating an ASP.NET Web site for your club or organizatio
er Kit n. This kit includes news posting, calendar, member directory, and photo album systems.

Time Tracker S The Time Tracker Starter Kit demonstrates how to build a line-of-business ASP.NET application that enables yo
tarter Kit u to track the period of time spent working on projects. You can use this kit to create projects, create task categ
ories, log completed work, and track time that was spent.

PayPal-enable The PayPal-enabled eCommerce Starter Kit is an extensible, open-source ASP.NET application that makes it eas
d Ecommerce y for you to set up and manage your own e-commerce Web site.
Starter Kit

eBay Selling St The eBay Selling Starter Kit for Microsoft Visual Basic provides a full-featured ASP.NET application for eBay auc
arter Kit tion management. You can customize the application to add new features, and you can integrate the applicatio
n with your existing inventory management system.

See Also
Concepts
Types of Web Sites in Visual Web Developer
Other Resources
ASP.NET Web Sites (Visual Studio)
Visual Web Developer

Local IIS Web Sites


A local Internet Information Services (IIS) Web site is an IIS Web application on your computer. Visual Web Developer
communicates with the Web site by using the HTTP protocol.
Creating or opening a local IIS Web site is useful in the following situations:
You want to test your Web site using IIS, which closely emulates how the Web site will run on a production server. This
can have advantages over working with file system Web sites that run using the ASP.NET Development Server, because
paths are resolved as they will be on a production server.
You already have a set of Web site files in a folder and you want to test the Web site with IIS. In this case, you can create a
virtual directory in your local version of IIS.
Your local computer is also your Web server.
Requirements
To create a local IIS Web site requires the following:
Your computer must have at least IIS version 5.0 installed and running.
Your computer must be running the .NET Framework version 2.0.
ASP.NET version 2.0 must be enabled in IIS. For details, see the topic "Enabling ASP.NET" in the
IIS Product Documentation.
You must be logged in as a user with administrative privileges. This is required because working with the IIS metabase
(where information about IIS applications is stored) requires administrative privileges.
To open an existing local IIS Web site, the preceding must be true as well as the following:
The site to be opened must be configured as an IIS application. For more information, see the topic "Creating Virtual
Directories in IIS 6.0" in the IIS Product Documentation.
The site must be configured to use ASP.NET version 2.0. If it is not, when you open the site, Visual Web Developer will
prompt you to reconfigure the site to use ASP.NET 2.0. This is distinct from having ASP.NET 2.0 installed on the
computer. It is possible to have ASP.NET 2.0 installed on the computer but have the site to be opened still mapped to use
an earlier version of ASP.NET. For details, see How to: Configure ASP.NET Applications for an ASP.NET Version.

Creating or Opening Local IIS Web Sites


When you create the Web site, Visual Web Developer performs all of the tasks that are required to make the Web site function
as an IIS application. Visual Web Developer creates the folder or folders for your Web site under the Web root for IIS (for
example, under \inetpub\wwwroot). After creating folders, Visual Web Developer creates the files for the Web site template
that you selected.
Note
You can create an IIS application as a subfolder of any existing IIS folder.

Local IIS Web Site Projects


When you create or open a local IIS Web site, Visual Web Developer creates a project to manage the files. The project stores a
small amount of information, such as your choices for how to run the application and what debuggers are available. Project
information is stored on a per-user basis. For more information, see Web Site Projects and Solutions.
Running Local IIS Web Sites
By default, when you run a local IIS Web site to test it, Visual Web Developer launches a browser and runs the Web site using
the server name localhost. For example, if you have created the Web site ExampleSite, when you test it in Visual Web
Developer, the browser will request the test page from this URL:

http://localhost/ExampleSite/page
IIS resolves the application name, whether it points to a folder that is under the IIS root or to another location, and serves
pages from that folder.
For more information, see Testing Web Pages in Visual Web Developer.
Deploying Local IIS Web Sites
Local IIS Web sites are generally used only for development, so that individual developers can create and test ASP.NET Web
pages on their own computers. In most cases, you must deploy the files from a file system Web site to a production server that
is running IIS.
You can deploy the files from a local IIS Web site using the Copy Web tool and the Publish Web utility in Visual Web
Developer. For details, see Web Site Deployment in Visual Web Developer.
Note
The Publish Web utility is not available in Visual Web Developer Express Edition.

See Also
Tasks
How to: Create Local IIS Web Sites
Concepts
Types of Web Sites in Visual Web Developer
Web Servers in Visual Web Developer
Visual Web Developer

Walkthrough: Creating a Local IIS Web Site in Visual Web


Developer
In the Microsoft Visual Web Developer Web development tool, you can create and edit Web sites that keep the Web pages and
other files in different locations. Your choices for locating Web pages and other files include the following:
In a folder on the local hard disk, which is referred to as a file system Web site.
As a Web application under a local copy of Microsoft Internet Information Services (IIS), which is referred as a local IIS
Web site.
You can also work with Web sites on a remote server by creating a Microsoft SharePoint Services Web site or by connecting to
a server that uses FTP. For more information, see Types of Web Sites in Visual Web Developer.
In this walkthrough, you will work with two Web sites that run under a locally installed copy of IIS. One of the Web sites is
physically located under the root folder of IIS (typically C:\Inetpub\wwwroot). A second Web site is located in a convenient
folder on the hard disk but the second Web site is available to IIS by using a virtual directory.
You can use IIS to test the Web site. If the computer is configured to permit other users to connect to it, the Web site is
available to those users.
Note
If you cannot run IIS on the computer, you can still create and test ASP.NET Web sites by running Visual Web Developer. For
more information, see Walkthrough: Creating a Basic Web Page in Visual Web Developer.

Tasks illustrated in this walkthrough include the following:


Creating an application and page under the IIS root.
Creating an application that uses an IIS virtual root.
Using IIS to run the page.
Working with IIS in Solution Explorer.
Prerequisites
To complete this walkthrough, you must have IIS installed locally on the computer, and you must be logged in as a user with
administrative privileges. This is required because working with the IIS metabase (where information about IIS applications is
stored) requires administrative privileges.
Creating a Web Site under the IIS Root
In the first part of the walkthrough, you will create a Web site that resides under the IIS default folder (typically
\Inetpub\wwwroot).
To create a new local IIS Web site under the IIS root
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. Click Browse.
The Choose Location dialog box appears.
5. Click Local IIS.
6. Click Default Web Site.
7. Click the Create new Web program icon, which is located in the upper-right corner.
This icon is not labeled, but when you pause the mouse pointer on it, the Create New Web Application ToolTip text
appears.
A new application, named WebSite, is added under Default Web Site.
8. In the box for the new Web site, type LocalIISWebSite, and then click Open.
The New Web Site dialog box appears with the right-most Location box filled in with
http://localhost/LocalIISWebSite.
9. In the Language list, click the programming language that you prefer to work in.
The programming language that you choose will be the default for the Web site. However, you can use multiple
languages in the same Web application by creating pages and components in different programming languages.
10. Click OK.
Visual Web Developer creates the new Web site and opens a new page named Default.aspx. Keep this page open. This
initial Default.aspx page uses the Web page code-behind model. For more information, see
ASP.NET Web Page Code Model.
Visual Web Developer not only creates the folders and files for the Web site but it also interacts with IIS to create an IIS Web
application for your site. Essentially, Visual Web Developer calls IIS to create the metadata that IIS requires in order to be able
to recognize your folder and pages as a Web site.
You can examine what Visual Web Developer has performed by looking at the files and folders that have been created.
To examine the structure of the local IIS Web site
1. In Microsoft Windows, click Start, and then click Run.
In the Run dialog box, in the Open box, enter C:\Inetpub\wwwroot, and then click OK.
Note
If IIS is installed on a different drive or folder, change the path, as appropriate.

Under \wwwroot, you now see a new folder named LocalIISWebSite.


2. In the Path dialog box, double-click LocalIISWebSite.
You see the contents of the Web site, which include the following:
An App_Data folder, which is created automatically by Visual Web Developer.
A Default.aspx page.
The code-behind file, which is Default.aspx.cs or Default.aspx.vb, depending on the default language for the Web
application.
You can add pages to the Web site as you would ordinarily. However, you can also add pages to the Web site externally and
Visual Web Developer will recognize them as part of the application, although you might have to update Solution Explorer in
order to see them.
Adding and Programming Controls
In this part of the walkthrough, you will add a Button, TextBox, and Label control to the page and write code to handle the
Click event for the Button control.
To add controls to the page
1. In Visual Web Developer, open or switch to the Default.aspx page, and then switch to Design view.
2. Press SHIFT+ENTER several times to make some room.
3. From the Standard group in the Toolbox, drag three controls onto the page: a TextBox, Button, and Label.
Note
If you cannot see the Toolbox, on the View menu, click Toolbox.

4. Position the insertion pointer in front of the text box, and then type Enter your name:.
5. Click the Button control, and then in Properties, set Text to Display Name.
6. Click the Label control, and then in Properties, clear Text.
7. Double-click the Button control, which is now labeled Display Name.
Visual Web Developer opens the code file for the page in a separate window in the editor.
The file contains a skeleton Click handler for the Button control.
8. Complete the Click handler by adding the following highlighted code that will display the text string after the Button
control is clicked.
Security Note
User input in an ASP.NET Web page can include potentially malicious client script. By default, ASP.NET pages check pag
es on postback to guarantee that user input does not include script or HTML elements. For more information, see
Script Exploits Overview.

VB
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handl
es Button1.Click
Label1.Text = Textbox1.Text & ", welcome to Visual Web Developer!"
End Sub

C#
protected void Button1_Click(object sender, EventArgs e)
{
Label1.Text = TextBox1.Text + ", welcome to Visual Web Developer!";
}

9. Save the files.


You will test this Web page in "Testing the IIS Web Application," later in this walkthrough.
Updating the Web Site Outside Visual Web Developer
You can see that Visual Web Developer is reading the IIS path by adding a new file to the application from outside Visual Web
Developer.
To update the Web outside Visual Web Developer
1. Using Notepad or another text editor, create a new file that contains the following text, depending on whether you are
using Visual Basic or C#.
VB
<%@Page language="VB"%>
<script runat="server">
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handl
es Button1.Click
Button1.Text = "I was clicked!"
End Sub
</script>
<html>
<body>
<form runat="server" id="form1">
<asp:button runat="server" text="Button1" Id="Button1"
OnClick="Button1_Click"></asp:button>
</form>
</BODY>
</HTML>

C#
<%@Page language="C#"%>
<script runat="server">
protected void Button1_Click(object sender, System.EventArgs e)
{
Button1.Text = "I was clicked!";
}
</script>
<html>
<body>
<form runat="server" id="form1">
<asp:button runat="server" text="Button1" Id="Button1"
OnClick="Button1_Click"></asp:button>
</form>
</BODY>
</HTML>

2. Save the file in the path C:\inetpub\wwwroot\LocalIISWebSite under the name TestPage.aspx.
Note
If IIS is installed on a different drive or folder, change the path, as appropriate.

3. In Visual Web Developer, in Solution Explorer, click the Web site name (http://localhost/LocalIISWebSite/), and then
on the View menu, click Refresh.
The list of files that are in the Web site is updated to include the file that you added. Next, you will test the Web pages.
Testing the IIS Web Application
You can now test the Web site.
To test the local IIS Web site
1. In Visual Web Developer, open the Default.aspx page.
2. Press CTRL+F5 to run the page.
The page opens in the browser. Notice that the URL in the browser is http://localhost/LocalIISWebSite/default.aspx.
The request for the page is being made to localhost (without a port number), which is handled by IIS.
3. When the page appears in the browser, in the text box, enter your name, and then click Display Name to make sure it is
working.
4. In Visual Web Developer, open the TestPage.aspx page.
5. Press CTRL+F5 to run the page.
The page opens in the same instance of the browser.
6. When the page appears in the browser, click Button1 to make sure it is working.
7. Close the browser.
If you can connect to the computer from another computer, you can try accessing your site as if it were a public site. If you
cannot connect to the computer from another computer, you can skip this procedure.
To test your site as a public site
From a different computer, type the URL that includes the Web server computer name, Web site name, and default.aspx
as the page:
If the computer can be accessed over a local area network, use the computer name for the server that has a URL
such as the following:
http://server1/LocalIISWebSite/default.aspx
If you host a domain on the computer, you can access the page using a URL such as the following:
http://www.contoso.com/LocalIISWebSite/default.aspx
If the computer is either on a network or directly connected to the Internet, you can use the IP address for the
computer as the server name. For example:
http://172.19.195.700/LocalIISWebSite/default.aspx
Note
If you are not able to view your application from a different computer because of the Windows Firewall settings, you m
ight have to enable the Web server on port 80. You can do this on the Advanced tab of Windows firewall by clicking S
ettings. For more information, go to Security Developer Center -- .NET Framework Security and search for information
about Windows firewall settings.

Creating a Web Site as an IIS Virtual Root


As you have seen up to this point, IIS lets you create Web applications that are physically located under the default Web server
root folder (wwwroot). However, you can also create IIS virtual directories, which are IIS Web applications that point to files and
folders that can be located anywhere on the hard disk.
Note
For security reasons, IIS does not let you create virtual directories that point to folders on other computers. Virtual directories
must always point to the local computer.

In this part of the walkthrough, you will use Visual Web Developer to create a virtual directory that points to a Web site that is
stored in a local folder on the computer.
The first step is to create the virtual directory. If you have already created a file system Web site in Visual Web Developer (for
example, by completing Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site.
To create a local IIS Web site using a virtual folder
1. In Visual Web Developer, on the File menu, click New Web site.
2. Under Visual Studio Installed Templates, click ASP.NET Web Site.
3. Click Browse.
The Choose Location dialog box appears.
4. Click Local IIS.
5. Under Select the Web site you want to open, in the tree view, click Default Web Site, and then click the Create new
virtual directory icon, which is located in the upper-right corner.
This icon is not labeled, but when you pause the mouse pointer on it, the Create New Virtual Directory ToolTip text
appears.
The New Virtual Directory dialog box appears.
6. In the Alias Name box, type WebSite_vdir.
Note
You can name your virtual directory anything that you like, as long as you use a name that is valid in IIS.
7. In the Folder box, type one of the following:
The path of an existing file system Web site, if you have one. You can click Browse, and then locate the root folder
of that site, if you do not remember the exact path.
The path where you want to create a new folder to store the folders and files for the Web site.
8. Click OK.
If you specified a folder that does not exist, Visual Web Developer prompts you to create it.
Visual Web Developer then returns to the Choose Location dialog box and updates the list of IIS Web applications that
have the virtual directory that you created.
9. Select the virtual directory that you just created, click Open, and then click OK to create the Web site.
If you pointed the virtual directory to a new folder or an existing folder that does not contain a Web site, Visual Web
Developer creates the App_Data folder, a default page, and opens the page in the designer.
If your virtual folder points to an existing file system Web site, Visual Web Developer opens a Web Site Already Exists
dialog box and gives you the option to select a new folder, open the existing site, or create a new Web site in the existing
location. After you select your option and click OK, Visual Web Developer displays the contents of the folder in Solution
Explorer and opens the Default.aspx page, if it exists.
Adding Controls to the Web Page
As you did in " Testing the IIS Web Application," earlier in this walkthrough, you will use a simple ASP.NET Web page to test the
IIS Web site that you are creating. If you are working with an existing file system Web site, you do not have to create a new
page. If your virtual directory points to a new folder, you can use that page.
If this is a new Web site, you will add some controls to the default page so that you can test that the page is working correctly.
To add controls to the page
1. In Visual Web Developer, open the Default.aspx page and switch to Design view.
2. From the Standard group in the Toolbox, drag a TextBox, Button, and Label control onto the page.
3. Double-click the Button control, and then add the following highlighted code:
VB
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handl
es Button1.Click
Label1.Text = "Welcome to Visual Web Developer!"
End Sub

C#
protected void Button1_Click(object sender, System.EventArgs e)
{
Label1.Text = "Welcome to Visual Web Developer!";
}

4. Save the files.


Testing the Virtual Directory
You can now test the Web site.
To test the local IIS Web site using the virtual directory
1. In Visual Web Developer, open a page in the Web site, which can be the Default.aspx page or another page.
2. Press CTRL+F5 to run the page.
The page opens in the browser. Notice that the URL in the browser is http://localhost/Website_vdir/default.aspx.
When IIS resolves the URL, it looks up the physical path that is associated with the virtual directory named Website_vdir
and looks for the page there.
3. When the page appears in the browser, click the Button control to make sure it is working.
4. Close the browser.
If you can connect to the computer from another computer, you can try the same tests that you used in the preceding section
to try accessing the page.
Deleting a Local IIS Web Site
You can manage local IIS Web sites in Visual Web Developer by deleting ones that you no longer need. There is an important
difference in how deletion works, depending on which type of local IIS Web site that you are working with, as follows:
When you delete a Web site under the IIS root, the Web application is deleted from IIS and the files and folders for the
Web site are deleted also.
When you delete a virtual directory, the IIS information about that Web site is deleted but the files and folders in the local
file system folder are left intact.

To delete the local IIS Web site


1. On the File menu, click Close Solution or Close Project.
2. On the File menu, click Open Web site.
3. In the Open Web Site dialog box, click Local IIS.
4. Click the name of the virtual directory (Website_vdir) that you created in "Creating a Web Site as an IIS Virtual Root,"
earlier in the walkthrough.
Caution
If you select a different Web site, the files and folders for that Web site might be deleted.

5. Click the delete icon in the upper-right corner.


This icon is not labeled, but when you pause the mouse pointer on it, the Delete ToolTip text appears.
6. When you are prompted for confirmation to delete the Web site, click Yes.
7. Click Cancel to close the Open Web Site dialog box.
8. Open the browser, and then type the URL for the virtual directory:
http://localhost/Website_vdir/default.aspx
This time, the browser reports that the page cannot be found, because IIS no longer recognizes Website_vdir as a Web
site on the local computer.
Note
It is possible that the page was cached by the local browser. In that case, the page might still display until you flush the
browser cache, and then try to view the page again.

Next Steps
In this walkthrough, you have learned how to create a Web site using the local copy of IIS. You might also want to learn about
other types of Web sites that you can create in Visual Web Developer. For example, you might want to do the following:
Create a file system Web site, where the pages are stored in a folder anywhere on the hard disk.
For more information, see Walkthrough: Creating a Basic Web Page in Visual Web Developer.
Learn how to use FTP to open and edit Web sites.
For more information, see Walkthrough: Editing Web Sites with FTP in Visual Web Developer.
See Also
Concepts
Types of Web Sites in Visual Web Developer
Using Visual Web Developer as a Non-Administrative User
Visual Web Developer

How to: Create Local IIS Web Sites


A local Internet Information Services (IIS) Web site is an IIS Web application on your computer. Visual Web Developer
communicates with local Web sites by using the HTTP protocol. You can create a new local IIS Web site that uses files in the
following ways:
You can create a new IIS application, which creates a new folder and files under the IIS root.
You can create a Web site that points to an existing IIS application, and then edit the files in that application.
You can create a new virtual directory, which creates a new IIS application that points to files that are in a folder other
than the IIS root. You can either create a new folder or point to a folder that already contains files.
To create a local IIS Web site requires the following:
IIS version 5.0 or later must be installed on your computer and must be running.
You must be logged in as a user with administrative privileges. This is required because working with the IIS metabase
(where information about IIS applications is stored) requires administrative privileges.
ASP.NET 2.0 must be enabled on IIS. For details, see the topic Enabling ASP.NET in the IIS documentation at
IIS 6.0 Product Documentation.
To open an existing local IIS Web site, the preceding must be true, and in addition:
The site to be opened must be configured as an IIS application. For more information, see
Creating and Isolating Applications in IIS 6.0 in the IIS 6.0 Operations Guide.
The site must be configured to use ASP.NET 2.0. If it is not, when you open the site, Visual Web Developer will prompt
you to reconfigure the site to use ASP.NET 2.0.
Note
Static files, such as images and style sheets, are not subject to ASP.NET authorization when they are served through IIS. Use II
S security features to restrict access to static files if they are not meant for all users. If you use the ASP.NET Development Ser
ver to test your ASP.NET application, the application will behave differently. This is because static files are subject to ASP.NET
authorization and will not be served to an anonymous user when anonymous access to those files is disabled.

To create a local IIS Web site


1. In Visual Web Developer, on the File menu click New Web Site.
2. Under Visual Studio Installed Templates, select the template for the type of Web site that you want to create.
3. To create a Web site directly, do the following:
a. In the Location list, click HTTP.
b. In the location box, type the URL of the site to create in the following format: http://localhost/SiteName.
c. Click OK.
Alternatively, follow the remaining steps in this procedure to create a Web site based on an existing IIS application or to
create a site that uses a virtual directory.
4. Click Browse.
5. In the Choose Location dialog box, click the Local IIS tab.
6. In the tree, open the node for the IIS Web site where you want to create your new Web site. (Typically, this is Default
Web Site.)
7. To create a new IIS application:
a. Select the node that you want as parent of the IIS application.
b. Click the Create New Web Application button. Visual Web Developer creates a new folder.
c. Type a name for the folder.
8. To create a local IIS Web site that uses files from an existing IIS application:
a. In the tree, select the node that represents the IIS application you want to work with.
9. To create a new virtual directory:
a. Click the Create New Virtual Directory button.
b. In the New Virtual Directory dialog box, type the alias and then type or select the folder where the files will be
located. If the folder does not exist, Visual Web Developer will prompt you to create it.
10. Click Open to return to the New Web Site dialog box, and then click OK.
Note
If the path you specified already contains files, Visual Web Developer prompts you to confirm that you want to open th
e files from that application.

Visual Web Developer creates the Web site. If you are creating a new site, Visual Web Developer opens a default page in
the page designer, and displays the folder in Solution Explorer.

See Also
Concepts
Local IIS Web Sites
Visual Web Developer

File System Web Sites


Visual Web Developer allows you to keep the files for your Web site in a folder on your local hard disk or in a shared location
on your local area network. This is called a file system Web site. Using such a file system Web site means that you do not need
to create your site as an Internet Information Services (IIS) application to develop or test it.
File system Web sites are particularly useful in the following situations:
When you do not want to (or cannot) install IIS on your development computer.
When you already have a set of Web files in a folder, and you want to use Visual Web Developer to open them as a
project.
In classroom settings, where students can store files on student-specific folders on a central server.
In a team setting, where team members can access a common Web site on a central server.
Creating or Opening File System Web Sites
When you create a file system Web site, you specify a location for the application files. You can specify a folder on your hard
disk or a shared folder on another computer. Visual Web Developer will create the folder, if necessary, and populate it with the
files from the Web site template that you have selected. For example, if you create a Web site by using the ASP.NET Web Site
template, Visual Web Developer creates a default page named Default.aspx and an Application_Data folder in the location that
you specify.
Note
You must have the appropriate permissions to create folders and files in the location that you specify.

If you have a set of ASP.NET Web site files in a folder already, you can open a Web site and specify the folder as the location.
Visual Web Developer allows you to work with the folder as if you had created the Web site in Visual Web Developer.
File System Web Site Projects
In Visual Web Developer, you do not need to have a Web project file. Instead, Visual Web Developer considers all of the files
and folders that are located in a given Web folder as part of the same Web project. Some of the information that earlier
versions of Visual Studio stored in the Web project file is now stored in the Web.config file, the Vwd.webinfo file, or the
solution file for the Web project. For more information, see Web Site Projects and Solutions.
File System Web Site Layout
The layout of a file system Web site is the same as for any other ASP.NET Web site. Web pages can appear in the root folder or
in any subfolder of the application. As with other types of Web sites, ASP.NET and Visual Web Developer treat certain
subfolders as special. For example, compiled assemblies in the Bin subfolder are referenced automatically in the application,
source code in the App_Code folder is compiled and referenced automatically, and so on. For more information, see
ASP.NET Web Site Layout and Shared Code Folders in ASP.NET Web Sites.
Testing File System Web Sites
To test a Web site, you must request the application's files by using a Web server. By default, when you run (test) a file system
Web site in Visual Web Developer, Visual Web Developer uses the ASP.NET Development Server as the Web server. The
ASP.NET Development Server is a server that runs locally on your computer and can serve ASP.NET Web pages, which makes it
suitable for testing your application. For details about the ASP.NET Development Server, see
Web Servers in Visual Web Developer.
If you prefer, you can configure your file system Web site to run files using a different server. You might do this if you have an
IIS virtual directory that points to your application's folder and you want to run the pages using IIS. In some cases, running
pages using IIS provides a more accurate assessment of how the application will run on a production server.
You can specify the Web server that you want to use for testing by setting the application's start options and then specifying
the URL of the server that you want to use instead of the ASP.NET Development Server. For details, see
How to: Specify the Web Server for Web Sites.
Authorization Behavior on File System Web Sites
In a file system Web site, static files, such as images and style sheets, are subject to ASP.NET authorization. For example, static
In a file system Web site, static files, such as images and style sheets, are subject to ASP.NET authorization. For example, static
files in a file system Web site will not be served to an anonymous user when anonymous access to those files is disabled.
However, when you deploy the Web site, IIS will serve static files without using ASP.NET authorization rules. If you want to
restrict access to static files, configure access rules for those files in IIS.
Deploying File System Web Sites
File system Web sites are generally used only for development, so that individual developers can create and test ASP.NET Web
pages on their own computers. In most cases, you should deploy the files from a file system Web site to a production server
running IIS.
You can deploy the files from a file system Web site using the Copy Web or Publish Web tools in Visual Web Developer. For
details, see Web Site Deployment in Visual Web Developer.
If you are developing your file system Web site on the computer that also hosts the production Web server, you have the
option of creating an IIS virtual directory that points to your application's location, thereby exposing the files as a live Web site.
For details, see How to: Create IIS Virtual Directories in Visual Web Developer.
See Also
Tasks
How to: Create File System Web Sites
How to: Specify the Web Server for Web Sites
Concepts
Types of Web Sites in Visual Web Developer
Web Servers in Visual Web Developer
ASP.NET Web Site Layout
Web Site Deployment in Visual Web Developer
Other Resources
Web Site Projects and Solutions
Visual Web Developer

How to: Create File System Web Sites


In a file system Web site, you put the files for your application into a folder on a local computer or on a computer that is
accessible on your network. Because you do not require Internet Information Services (IIS) to create or test file system Web
sites, they are useful for developing locally on your computer.
In a file system Web site, static files, such as images and style sheets, are subject to ASP.NET authorization. For example, static
files in a file system Web site will not be served to an anonymous user when anonymous access to those files is disabled.
However, when you create a Web site project in an HTTP location, IIS serves static files without using authorization rules. For
more information, see File System Web Sites.
To create a file system Web site
1. In Visual Web Developer, on the File menu, point to New, and then click Web Site.
2. Under Visual Studio Installed Templates, select the template for the type of Web site that you want to create.
3. In the Location box, click File System, and then type the path and folder where you want to create the Web site.
Note
You can specify either a local path or a UNC path to a different computer on your network.

4. If you prefer to browse to an existing location, do the following:


a. Click Browse.
b. In the Choose Location dialog box, click the File System tab.
c. In the tree, select the folder that you want to use, or type the path in the Folder box.
d. To create a new folder, select the location, click Create New Folder, and then type a name for the new folder.
e. Click Open to return to the New Web Site dialog box.
5. Click OK.
Visual Web Developer creates the site, opens a default page in the page designer, and displays the folder in Solution
Explorer.
Note
If the path you specified already contains files, Visual Web Developer prompts you to specify a different location, open t
he existing Web site, or create the Web site anyway. In the last case, the files that are created with the Web site overwrit
e any files with the same name that are already in the folder.

See Also
Tasks
How to: Specify the Web Server for Web Sites
Concepts
Types of Web Sites in Visual Web Developer
File System Web Sites
Visual Web Developer

FTP-Deployed Web Sites


Visual Web Developer allows you to work with Web sites that you access using File Transfer Protocol (FTP). This makes it faster
to work with sites that are hosted on another server, such as the server for a commercial hosting service.
What FTP Is
FTP is a standard protocol for copying files from one computer to another across the Internet. For example, many Web hosting
sites allow users to copy files to the server using FTP.
An FTP server is similar to an HTTP server (that is, a Web server) in that you can communicate with it using an Internet
protocol. However, an FTP server does not run Web pages; it only copies files to and from the server.
FTP Location versus Browse Location
It is typical that the server computer runs both an FTP server to support file transfers and a Web server to support HTTP access
to files. These are separate servers even if they run on the same computer. Both of the servers map to the directory where the
files are located.
Although the FTP server and Web server might be working with the same files in the same physical location (or directory), the
URL for accessing the files is usually different for each of the protocols. For example, the URL for transferring files to a specific
directory on the FTP server might be something like the following:

ftp://upload.contoso.com/fred/root/

In contrast, to run the files, you need a browse location, or the URL of a Web server that points to the same location. The
browse location might look like the following:

http://contoso/fred/

Again, both of the URLs might be pointing at the same physical directory on the server.
FTP Web Sites in Visual Web Developer
In Visual Web Developer, an FTP Web site is simply a Web site that resides on a remote computer that you access using FTP.
FTP access requires that you know the URL of the site. This is often provided as a complete URL (for example,
ftp://servername/foldername). Under most circumstances, you also must have a valid user name and password to log on to
the FTP server before being allowed to read or write files.
Once you have the FTP address of the site, you can open the site in Visual Web Developer. You can then edit and create files in
the site as if they were local files. When you save the files, they are transferred via FTP to the server.
Active and Passive Mode
Visual Web Developer can establish connections to the FTP server in two modes: active mode and passive mode. In FTP, the
client (in this case, Visual Web Developer) and the server communicate using two ports. One port is used to transmit
commands, and the other is used to transmit data.
Active FTP benefits the server administrator. In active mode, the client initializes a connection to the server for the command
port and passes to the server the port address for the data. The server then initializes a connection back to the client to open
the data port.
Passive FTP benefits a client behind a firewall. If the client is behind a firewall, the server's attempt to open a port on the client
computer will likely fail. In passive mode, the client initializes the connections for both the command port and the data port.
Because the client initializes the connection for both ports, the firewall allows the connections.
For more information, see Information About the IIS File Transmission Protocol (FTP) Service.
Logon Credentials
Some FTP servers require that you pass authentication credentials to the server in order to connect. Visual Web Developer
allows you to specify a user name and password when you establish a connection to the FTP server. If you specify credentials,
they are cached in memory on your computer for the duration of your Visual Web Developer server. As a security measure,
they are not stored on disk.
Note
If you do not provide the required credentials when specifying the logon information for the FTP Web site, Visual Web Devel
oper prompts you for them when you attempt to connect. Visual Web Developer never attempts to connect to an FTP server
anonymously unless you explicitly specify anonymous logon in the FTP Site Tab, Choose Location/Open Web Site Dialog Box.

The credentials are passed to the FTP server each time they are required. When you close Visual Web Developer, the
credentials are discarded. The next time you establish a connection to the FTP server, you must specify the credentials again.
Typically, FTP credentials are passed as clear text and not encrypted for transmission. It is recommended that you use FTP with
Anonymous or Basic authentication. For more information, see the topic "Authentication Methods Supported in IIS 6.0" in the
IIS Technical Reference.
Creating FTP Web Sites
You can create FTP Web sites in Visual Web Developer the same way you create file-system sites or local IIS sites. However,
because the site is being created on a remote server, you must have permissions to create a new folder. If you have an account
on a hosted site, you generally cannot create new sites at the root level of your site, but you can usually create sites that are
child sites of your root site. If you have questions about whether you have the necessary permissions to create new FTP sites,
you should contact the administrator for the server.
Running FTP Web Sites in Visual Web Developer
You do not directly run an FTP Web site, since FTP is only a transfer protocol. Most commonly, the server computer runs both
an FTP server to support file transfers and a Web server to support HTTP access to files.
In order for you see the Web pages from your FTP Web site in the browser, the server computer must have a browse location
— that is, an HTTP URL that points to the same files as the FTP site. Although the FTP server and Web server might be working
with the same files in the same physical location (directory), the URL for accessing the files is usually different for each of the
protocols.
Check with the administrator of your site to determine the correct HTTP URL for the site. When you run an FTP Web site for the
first time, Visual Web Developer prompts you for the HTTP URL of the site. The information is stored as part of the Web site in
the startup options. For information, see Startup, Environment, Options Dialog Box.
Debugging FTP Web Sites
You can use the debugger with FTP Web sites as you would with other types of Web sites running on a remote server. Running
the debugger with FTP Web sites — setting breakpoints, launching the debugger, and so on — is the same as it is for other
Web sites. However, because the files to be debugged are on a remote site, you must configure the debugger to be able to
attach to a remote process. For more information, see the "Remote Computer Configuration" section in
Debugging Web Pages Overview.
Many commercial hosting sites do not support remote debugging. Contact the site administrator to find out whether you will
be able to debug the site remotely.
Note
Remote debugging is not available in Visual Web Developer 2005 Express Edition.

Caching Files
When you work with an FTP Web site, Visual Web Developer caches files locally. The files and any dependent resources are
read from the remote server and stored locally when you first access them. When you save a file, the file is saved locally and
written to the FTP server. When you close a Web site, the cache is deleted. Under most circumstances, the fact that files are
cached is transparent to you and to Visual Web Developer.
If two developers edit the same file at the same time, the changes from one developer might be overwritten. FTP-deployed
Web sites cannot be integrated with a source control system.
See Also
Tasks
Walkthrough: Editing Web Sites with FTP in Visual Web Developer
Visual Web Developer

Walkthrough: Editing Web Sites with FTP in Visual Web


Developer
The Microsoft Visual Web Developer Web development tool lets you read from and write to a remote server by using the File
Transfer Protocol (FTP). The most common use for FTP Web sites is to update Web pages on a hosting site, which is faster than
updating files that use an HTTP connection. After you connect to the FTP site in Visual Web Developer, you can create and edit
files in those sites. For information about FTP, see FTP-Deployed Web Sites.
Tasks illustrated in this walkthrough include the following:
Using FTP to connect to an existing Web site from within Visual Web Developer.
Creating and editing pages by using FTP.
Prerequisites
In order to complete this walkthrough, you will need the following:
Access to a folder on an FTP server that supports the .NET Framework.
If you have access to an existing FTP site, you can use that. For example, if you have an account that has a commercial
hosting service that provides ASP.NET support, you can use that account in this walkthrough. Otherwise, you can
configure a computer by running Microsoft Internet Information Services (IIS) as an FTP server. For more information
about how to configure IIS as an FTP server, see How to: Create and Configure FTP Sites in IIS.
Read and write permissions for the FTP directory on the server.
Optionally, a virtual Web root that points to the FTP location. This lets you to test the files that you work with.
For purposes of this walkthrough, you can use a local copy of IIS as an FTP server. Ordinarily, you do not have to use FTP to
communicate with the local copy of IIS.
Accessing the FTP Web Site
To start, you will connect to the FTP Web site from within Visual Web Developer. You must know the FTP address of the FTP
Web site and, if it is required, you must have a user name and password.
To access the FTP Web site
1. In Visual Web Developer, on the File menu, click New Web Site.
2. In the New Web Site dialog box, in the left-most Location list, click FTP Site, and then click Browse.
3. In the Choose Location dialog box, in the Server and Directory boxes, enter the appropriate information.
The Server field refers to the name or IP address of the FTP server. The Directory field refers to a specific directory on
the FTP server that you want to put the content in. By default, many FTP sites connect you to a home directory, although
there might still be a directory below that or a separate virtual directory where the Web content should be put. If you do
not know these values, contact the FTP site administrator.
For Port, the most common value is 21, but you should confirm that value with the FTP site administrator also.
4. Examine the following values:
Passive Mode
Leave this check box clear at first. Passive mode is sometimes required, if there is a firewall between your server
and the FTP server.
Anonymous Login
If the FTP site administrator has provided you with a user name and password, clear the Anonymous Login check
box, and then in the Username and Password boxes, enter the appropriate information.
5. Click Open.
Visual Web Developer will try to connect to the FTP server by using the information that you have provided. If the
connection is successful, Visual Web Developer displays the FTP Web site name in Solution Explorer and lists the files
that are already in the FTP Web site.
Troubleshooting
If the connection fails, examine the following:
If you have administrative rights on the server, use IIS Manager to add the Write permission to the FTP virtual directory.
Do not complete this before you have set restricted NTFS File System permissions on the virtual directory, either by
using IIS Manager or Microsoft Windows Explorer. For more information, go to Microsoft Technet and search for
information about how to help secure FTP sites.
Confirm that the server name and directory name are correct.
Use the URL of the Web site or the FTP site in the Server field and leave the Directory field blank.
Try connecting with Passive Mode enabled. This frequently lets you get through a firewall.
Make sure that the FTP Web site has the directory that you have indicated. If you are using IIS as the FTP server,
remember that the directory is typically defined under the ftproot directory, not the wwwroot directory.
Contact the FTP site administrator to determine whether anonymous log on is allowed. If not, make sure that you have
credentials for a user account that has permission to access and modify the FTP directory.
Creating and Editing Pages
Working with Web pages in an FTP Web site is the same as working with Web pages in any other Web site. The only difference
is that the files are stored on the FTP server, so that when you open or save the files, you are invoking the FTP connection.
To create a page
1. In Solution Explorer, right-click the FTP Web site name, click Add New Item, and then create a new Web Forms page.
Note
If you have access to the physical folder that is represented by the FTP Web site, you can confirm that the file is created
in that folder.

2. Switch to Design view.


3. From the Standard group in the Toolbox, drag a Button control and a Label control onto the page.
4. Double-click the Button control.
5. The file contains a skeleton Click handler for the Button control.
6. Complete the Click handler by adding the following highlighted code:
VB
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Label1.Text = "The FTP Web site is working!"
End Sub

C#
protected void Button1_Click(object sender, System.EventArgs e)
{
Label1.Text = "The FTP Web site is working!";
}

7. Save your files.


Testing the FTP Web Site
If the FTP Web site has been set up to have an equivalent Web site, you can test the Web site by displaying it in the browser.
To test the FTP Web site on the server
1. Press CTRL+F5.
Visual Web Developer prompts you for the location to go to. The location is stored as part of the Web site configuration
information.
2. Enter the HTTP URL that points to the server and the Web virtual directory that you created in "Accessing the FTP Web
Site," earlier in this walkthrough.
For example, the URL might be the following:
http://<server>/ExampleFtpFiles

Note
You can change or set the browser location at any time. To do this, in Solution Explorer, right-click the Web site name, a
nd then click Property Pages. On the Start Options tab, under Server, click Use custom server, and then in the Base
URL box, type the location.

The page is displayed in the browser.


3. Close the browser.
See Also
Concepts
What's New in Web Development for Visual Studio
Types of Web Sites in Visual Web Developer
Visual Web Developer

How to: Open Web Sites Using FTP


Microsoft Visual Web Developer allows you to work with Web sites that you access using File Transfer Protocol (FTP). This
makes it simple for you to work with sites that are hosted on another server, such as the server for a commercial hosting
service.
The site to open must be available on an FTP server and you must have the following:
The name of the FTP server where you want to open the Web site.
The name of the folder (on the FTP server) where the Web files are stored.
Appropriate permissions to work with the files on the FTP server. This typically requires Read and Write permissions as a
minimum.
You might also need the following:
A user name and password for the server.
The port number that is used to access the FTP server. This is typically port 21.
You can get the preceding information from the FTP server administrator.
To open a Web site by using FTP
1. On the File menu, click Open Web Site.
2. In the Open Web Site dialog box, click the FTP Site tab.
3. Provide the following information:
Server Type the name of the server, which can be in the format ftp://server.
Port If the FTP server administrator has given you a port number that is different from 21, change this value.
Passive mode Select this check box if there is a firewall between your computer and the FTP server.
Directory Type the name of the folder where you want to open files.
Anonymous Login Select this check box if the FTP server does not require you to log on in order to access files.
Clear the check box to enter a user name and password.
Note
If you do not provide required credentials when specifying the login information for the FTP Web site, Visual Web
Developer prompts you for them when you attempt to connect. Visual Web Developer never attempts to connect
to an FTP server anonymously unless you explicitly specify anonymous login.

User name and Password Type the credentials that were provided by the FTP server administrator.
Note
The user name and password for the FTP server might be different from your usual Windows login credentials.

4. Click Open.
Visual Web Developer connects to the FTP server and reads the files in the specified folder. You can now edit the files and
create new ones. When you save a file, it is immediately written to the FTP server.
See Also
Tasks
How to: Specify the Web Server for Web Sites
Concepts
FTP-Deployed Web Sites
ASP.NET Configuration

How to: Create and Configure FTP Sites in IIS


File Transfer Protocol (FTP) is a standard protocol for moving files from one computer to another across the Internet. The files
are stored on a server computer, which runs FTP server software. Remote computers can then connect using FTP and read files
from the server or copy files to the server. An FTP server is similar to an HTTP server (that is, a Web server) in that you can
communicate with it using an Internet protocol. However, an FTP server does not run Web pages; it only sends and receives
files from remote computers.
You can configure Internet Information Services (IIS) to function as an FTP server. This allows other computers to connect to
the server and copy files to and from the server. For example, you might configure IIS to act as an FTP server if you are hosting
Web sites on your computer and you want to allow remote users to connect to your computer and copy their files to the
server.
Note
Typically, FTP credentials are passed as clear text and not encrypted for transmission. It is recommended that you use FTP wit
h Anonymous or Basic authentication. For more information, see the topics "Securing FTP Sites" and "Authentication Method
s Supported in IIS 6.0" in the IIS Technical Reference.

IIS as an FTP Server


In addition to acting as a Web server, IIS can act as an FTP server. The FTP service is not installed by default on IIS. Therefore, to
use IIS as an FTP server, you must install the FTP service. For more information about installing and configuring IIS as an FTP
server, see the Help documentation that is included with IIS, or see the section "Configuring FTP Sites" in the
IIS Technical Reference.
Note
You will need your Windows CD.

To set up an FTP server using IIS


1. Click the Start button, click Control Panel, and then click Add or Remove Programs.
2. Click Add/Remove Windows Components.
3. In the Windows Components Wizard dialog box, if you are running at least Windows Server 2003, select Application
Server, and then click Details.
4. Select Internet Information Services (IIS) and then click Details.
5. In the Internet Information Services (IIS) dialog box, select the File Transfer Protocol (FTP) Service check box and
click OK.
6. In the Windows Components Wizard dialog box, click Next. If prompted, insert your Windows CD.
When the installation process is finished, you can use the FTP service with IIS.
Creating Folders
After setting up an FTP server, you need to create a folder structure for the server. By default, the FTP server will have a root
folder with the following path: C:\inetpub\ftproot.
The FTP root folder acts as the root for your FTP server in the same way that C:\inetpub\wwwroot is the root for your Web
server.
You must create the physical folders where the files will reside. This can either be a subfolder of the FTP root or another folder
elsewhere on the computer. Then, you create a virtual root, or alias, that the FTP server will use to point to the physical
directory in which files will reside.
To configure an FTP folder and virtual root
1. Create a new folder to hold files. You can name the folder anything you like. For example, name the new folder
ExampleFtpFiles, so that the path of the folder is C:\inetpub\ftproot\ExampleFtpFiles.
2. In Windows, from the Administrative Tools menu, select Internet Information Services.
Note
In Windows XP, you can also right-click My Computer in the Start menu or on the desktop, and then click Manage. In
the Computer Management dialog box, open the Services and Applications node.

3. Open the node for your computer, and then open the FTP Sites node.
4. Right-click the Default FTP Site node, click New, and then click Virtual Directory.
5. In the Virtual Directory Creation Wizard, specify an alias (or name) that users can use to get to the FTP folder that you
created in step 1. The name can be anything you like. It is often least confusing to use the directory name as the alias
name, so that the virtual directory might be called ExampleFtpFiles.
6. For the path, type or browse to the path of the directory from step 1, for example Inetpub\ftproot\ExampleFtpFiles.
7. For Access Permissions, specify Read, and then click Next to finish with the wizard.
Note
Do not enable Write permissions unless you understand how to secure your IIS FTP server. For more information, see t
he topic titled "Securing FTP Sites" in the IIS Technical Reference.

Configuring Permissions
You must also grant permissions to users so that they will be able to read and write to the folder.
To establish permissions for the FTP folder
1. In Windows, from the Administrative Tools menu, choose Internet Information Services.
Note
In Windows XP, you can also right-click My Computer in the Start menu or on the desktop and then select Manage. I
n the Computer Management dialog box, open the Services and Applications node.

2. Open the node for your computer, open the FTP Sites node, and then open the Default FTP Site node.
3. Right-click the virtual directory node for the FTP folder that you want (for instance ExampleFtpFiles) and click
Permissions.
4. On the Security tab, select or add your user account and assign Modify permissions.
This sets NTFS permissions. To specify IP restrictions, right-click the folder name, click Properties, and add restrictions
on the Directory Security tab. For more information, see the topics "Access Control in IIS 6.0" in the
IIS Technical Reference.
5. Close the Properties dialog box.
Creating a Web Server Virtual Directory
You typically create a virtual directory for the Web server that maps to the FTP site so that the Web server can access the files
in the FTP root. The Web virtual directory name can be the same as the FTP virtual directory name, but this is not required.
To create a Web server virtual directory
1. In the Internet Information Services dialog box, open the Web Sites node.
2. Right-click the Default Web Site node, click New, and then click Virtual Directory.
3. In the wizard, specify an alias that users will use with http:// protocol to access the files in the FTP folder. This can be the
same as the FTP alias, for instance ExampleFtpFiles.
4. For the directory path, type or browse to the path of the FTP directory, for example C:\inetpub\ftproot\ExampleFtpFiles.
5. For access permissions, select Read and Run scripts.
6. Click Finish to create the virtual directory and close the wizard.

See Also
Tasks
How to: Create and Configure Virtual Directories in IIS
How to: Create and Configure Local ASP.NET Web Sites in IIS
How to: Install and Configure SMTP Virtual Servers in IIS
Visual Web Developer

Remote IIS Web Sites


A remote Internet Information Services (IIS) Web site is an IIS Web application associated with a copy of IIS that is running on
another computer. Visual Web Developer communicates with the Web site by using the HTTP protocol and FrontPage Server
Extensions from Microsoft.
Creating or opening a remote IIS Web site is useful when you want to do the following:
You do not want to install IIS on your development computer, but you have access to IIS running on another computer.
You want to test your Web site using IIS, which closely emulates how the Web site will run on a production server. This
can have advantages over working with file system Web sites that run using the ASP.NET Development Server because
paths are resolved as they will be on a production server.
Alternatively, if you have IIS running on your computer, you can create a local IIS Web site. For more information, see
Local IIS Web Sites.
Requirements
To create or open a remote IIS Web site requires the following:
The remote computer must have at least IIS version 5.0 installed and running.
The remote computer must be running the .NET Framework version 2.0.
ASP.NET version 2.0 must be enabled in IIS on the remote computer. For details, see the topic "Enabling ASP.NET" in the
IIS Product Documentation.
FrontPage Server Extensions must be installed and enabled at the root level where you are creating the site. For details,
see the topic "Installing and Enabling FrontPage Server Extensions" in the IIS Product Documentation.
You must have FrontPage administration or author permissions to create new folders and files on the remote computer
under the root where you want to create the new site. For details, see the topic "Using Roles to Manage User Rights" in
the IIS Product Documentation.
To open an existing site on the remote computer, the preceding must be true as well as the following:
FrontPage Server Extensions must be enabled at the Web site level.
The site must be configured to use ASP.NET 2.0. If it is not, when you open the site, Visual Web Developer will prompt
you to reconfigure the site to use ASP.NET 2.0. This is distinct from having ASP.NET 2.0 installed on the remote computer.
It is possible to have ASP.NET 2.0 installed on the remote computer but have the site to be opened still mapped to use an
earlier version of ASP.NET. For details, see How to: Configure ASP.NET Applications for an ASP.NET Version.

Remote IIS Web Sites and FrontPage Server Extensions


FrontPage Server Extensions are a set of utilities that run on a Web server with IIS, which allow you to administer an IIS
application across an HTTP connection. FrontPage Server Extensions make it practical to work with a server that is not directly
accessible to you on your local computer or on a local area network.
Visual Web Developer uses FrontPage Server Extensions to manage remote Web sites. When you create or open a remote IIS
Web site and when you create, open, and save files, Visual Web Developer communicates with the remote server by sending
FrontPage Server Extension commands.
Visual Web Developer performs all of the communications tasks with FrontPage Server Extensions automatically. From your
perspective as a Web site developer, after you have successfully created or opened a remote IIS Web site, you can work with
files as you would in any Web site, such as a file system Web site or a local IIS Web site.
Note
Using FrontPage Server Extensions has some implications for how you can work with source control on a remote computer.
For details, see Web Site Source Control Overview.

Creating or Opening Remote IIS Web Sites


When you create a remote IIS Web site, Visual Web Developer performs all of the tasks on the remote computer that are
When you create a remote IIS Web site, Visual Web Developer performs all of the tasks on the remote computer that are
required to make the Web site function as an IIS application. Visual Web Developer creates the folder or folders for your Web
site in the path you specified when creating the site, and then creates the files for the Web site template that you selected.
If you have a set of ASP.NET Web site files in a folder already, you can open a Web site and specify the folder as the location.
Visual Web Developer allows you to work with the folder as if you had created the Web site in Visual Web Developer.
Setting Run Time Permissions on Remote IIS Web Sites
When Visual Web Developer creates the Web site on the remote server, it sets permissions that allow you to create and edit
pages and components in the Web site based on your FrontPage Server Extensions administration or author permissions.
However, Visual Web Developer cannot set certain permissions on folders that might be required by ASP.NET at run time.
At run time, your Web application runs in the context of the ASP.NET user account, either ASPNET (for Windows XP
Professional or Windows 2000) or NETWORK SERVICES (for Windows Server 2003). If the application writes to the Web site, it
must have Modify and Write permissions. A typical example is if your Web site has an App_Data folder for XML files or a local
database. Without the appropriate permissions, the application cannot update the data in this folder.
Therefore, if your application must write to the site, you must grant Write and Modify permissions to the folders to be updated.
If you cannot set these permissions yourself, you must have an administrator on the remote computer perform this task for
you.
Remote IIS Web Site Projects
When you create or open a remote IIS Web site, Visual Web Developer creates a project to manage the files. The project stores
a small amount of information such as your choices for how to run the application and what debuggers are available. Project
information is stored on your local computer on a per-user basis. For more information, see Web Site Projects and Solutions.
Running Remote IIS Web Sites
By default, when you run a remote IIS Web site to test it, Visual Web Developer launches a browser and runs the Web site
using the server name of the remote site. For example, if you have created the Web site ExampleSite on the server TestServer,
when you test it in Visual Web Developer, the browser will request the test page from this URL:

http://TestServer/ExampleSite/page

For more information, see Testing Web Pages in Visual Web Developer.
Deploying Remote IIS Web Sites
If the remote IIS Web site that you are working with is not already on the production server, you can deploy it using the Copy
Web tool or the Publish Web utility in Visual Web Developer. For more information, see
Web Site Deployment in Visual Web Developer.
Note
The Publish Web utility is not available in Visual Web Developer Express Edition.

See Also
Tasks
How to: Create Remote IIS Web Sites
How to: Set Up Remote Debugging
Concepts
Types of Web Sites in Visual Web Developer
Visual Web Developer

How to: Create Remote IIS Web Sites


A remote IIS Web site is an Internet Information Services (IIS) Web application that is running on another computer. Visual
Web Developer communicates with the Web site by using the HTTP protocol and FrontPage Server Extensions from Microsoft.
To create a remote IIS Web site requires the following:
The remote computer must be running the .NET Framework version 2.0.
The remote computer must have IIS version 5.0 or later installed and running.
ASP.NET must be enabled in IIS on the remote computer. For details, see the topic Enabling ASP.NET in the IIS
documentation at IIS 6.0 Product Documentation.
FrontPage Server Extensions must be installed and enabled at the root level where you are creating the new Web site. For
details, see Installing and Enabling Dynamic Content in the IIS documentation at IIS 6.0 Product Documentation.
You must have FrontPage administration or author permissions to create new folders and files on the remote computer
under the root where you want the site to be. For details, see Using Roles to Manage User Rights in the IIS
documentation at IIS 6.0 Product Documentation. You can launch the FrontPage Server Extensions administration Web
page from within Visual Web Developer by using the Web Permissions command on the Website menu.
To open an existing site on the remote computer, the preceding must be true, and in addition:
FrontPage Server Extensions must be enabled for the Web site.
The site must be configured to use ASP.NET version 2.0. If it is not, when you open the site, Visual Web Developer will
prompt you to reconfigure the site to use ASP.NET 2.0. Note that this is distinct from having ASP.NET 2.0 installed on the
remote computer. Even if ASP.NET 2.0 is installed on the remote computer, an open site might be mapped to use an
earlier version of ASP.NET. For details, see How to: Configure ASP.NET Applications for an ASP.NET Version
ASP.NET must be enabled on IIS. For details, see the topic Enabling ASP.NET in the IIS documentation at
IIS 6.0 Product Documentation.
To create a remote IIS Web site
1. In Visual Web Developer, on the File menu click New Web Site.
2. Under Visual Web Developer Installed Templates, select the template for the type of Web site you want to create.
3. In the Location list, click HTTP.
4. To create a new remote IIS Web site, in the location box, type the URL of the site that you want to create, using syntax
such as the following:

http://server/SiteName

5. To create a remote IIS Web site that points to an existing IIS application on the remote server, do the following:
a. Click Browse.
b. In the Choose Location dialog box, click the Remote Site tab.
c. Type the URL of the IIS application that you want to open.
d. Click Open to return to the New Web Site dialog box.
6. Click OK.
Note
If the path you specified already contains files, Visual Web Developer prompts you to specify a different location.

Visual Web Developer creates the site, opens a default page in the page designer, and displays the folder in Solution
Explorer.
See Also
Concepts
Remote IIS Web Sites
Visual Web Developer

Building Web Sites


You can build (validate) the current page or your entire Web site at any time to help find compile-time errors. Building
performs tasks, such as the following:
Compiles the code in all pages in the site.
Compiles the code in the App_Code folder.
Compiles code in the Global.asax file.
Resolves and, if necessary, compiles any dependent resources.
Parses the configuration file to look for invalid configuration elements.
In short, building a Web site performs the same compilation tasks that occur when a page is requested in the browser.
However, the resulting object code is not used to run the page.
Building Individual Pages
You can also build individual pages. In that case, Visual Studio compiles only the current page and its dependencies. You might
find this useful if your site contains many unfinished pages and you do not want to be notified of errors in any page but the
one you are currently working with. You can set options for what to build by setting project options. For details, see
How to: Test Web Pages in Visual Web Developer.
Building versus Precompiling
Building a page or Web site is part of developing a site, and is intended to help you find compile-time errors that might occur
anywhere in the site. Although building does compile the pages, it does not produce an assembly that you deploy. You can
deploy a site without compiling it by copying all of the files in the Web site to a production server. When users request pages
from the production server, ASP.NET will dynamically compile the site, effectively performing the same steps that the build
process does in Visual Studio. (ASP.NET caches the resulting output so that the pages do not need to be recompiled with each
request.)
If you want to compile the site into assemblies and other files that you can deploy, you can publish the site. Publishing
performs the same compilation steps that building does, but it saves the output into a folder and subfolders that you can in
turn deploy to the production server.
For more information, see Web Site Deployment in Visual Web Developer.
See Also
Tasks
How to: Test Web Pages in Visual Web Developer
Concepts
Testing Web Pages in Visual Web Developer
Visual Web Developer

How to: Add Files to ASP.NET Web Sites


You can add new and existing files to an ASP.NET Web site. Some file types can only exist in special ASP.NET subdirectories. For
example, browser definition files (.browser) can only be created in the App_Browsers application subdirectory. If you attempt to
create a browser definition file in the root of your application, Visual Web Developer will give you the option to put it in the
App_Browsers subdirectory. For a list of file types, see Web Site File Types. For details about creating special ASP.NET folders,
see the subsequent procedure.
Web sites in Visual Studio are directory based. When you open a Web site, Visual Studio treats all of the files in the folder that
you open — whether the files are in the file system, in an Internet Information Services (IIS) application, or on an FTP site — as
part of the same Web site. For more information, see How to: Create File System Web Sites.
To add a file to an ASP.NET Web site
1. In Solution Explorer, right-click the Web site project name, and then click Add New Item.
2. In the Add New Item dialog box, under Visual Studio installed templates, select the file type that you want to add.
3. If the Language list is enabled for the file type that you are adding, select the name of the programming language that
you want to use for the file.
Note
You can create files (pages) with different programming languages in the same Web site.

4. If you want the code for the page to be in a separate file, be sure the Place code in separate file check box is selected. if
you want to keep the code and markup in the same file, clear this check box.
5. In the Name box, type a name for the file, and then click Add.
The new file is created and displayed in Visual Web Developer in the Source view window.

To create a special ASP.NET subdirectory


1. In Solution Explorer, right-click the Web site project name, and then click Add ASP.NET Folder.
2. In the list of available folders, click the name of the folder that you want to create.
For information about special ASP.NET folders, see ASP.NET Web Site Layout.
To add an existing Web page to a Web site project
1. In Solution Explorer, right-click the Web site project name, and then click Add Existing Item.
2. In the Add Existing Item dialog box, navigate to the directory that contains the Web page that you want to add, select
the page, and then click Open.
The Web page is added to the Web site project.
Note
When you add an existing file, the file is copied to your project not added by reference. Thus, if you change the file in yo
ur project, the original file is left unchanged.

To change the name of a Web page using Solution Explorer


1. In Solution Explorer, right-click the file name that you want to change and then click Rename.
2. Type the new file name that you want and then press ENTER.
Note
If the code for the page is in a separate file, Visual Studio automatically renames the code file as well and changes the
@ Page directive in the .aspx page to match the renamed code file.

See Also
Concepts
Web Pages and Projects
Solutions and Web Site Source Control
Web Site File Types
How to: Enable the Properties Window in Visual Web
Developer
The Properties window enables you to view and change the design-time properties and events of selected objects that are
located in editors and designers within Visual Studio. You can also use the Properties window to modify and view file, project,
and solution properties. The Properties window is available on the View menu of Visual Web Developer.
By default, the Properties window is not enabled in Source view. You will notice an increase in display performance in Source
view when properties are not displayed. You can change whether the Properties window is displayed by setting the
appropriate option within Visual Studio.
To enable the Properties window in Visual Web Developer
1. On the Tools menu, click Options. The Options dialog box opens.
2. In the left pane, double-click (or expand) the Text Editor node, expand the HTML node, and then click Miscellaneous.
Note
Additional options can be found in the Options dialog box by selecting the Show all settings check box.

3. Select the Enable Property grid in Source view check box.


See Also
Reference
General, HTML, Text Editor, Options Dialog Box
Miscellaneous, HTML, Text Editor, Options Dialog Box
Visual Web Developer

Web Servers in Visual Web Developer


This topic describes using either Internet Information Services (IIS) or the built-in ASP.NET Development Server for testing and
running Web sites.
To test or run ASP.NET Web applications, you need a Web server. The production Web server for Microsoft operating systems
is IIS, which includes a Web server, File Transfer Protocol (FTP) server, Simple Mail Transfer Protocol (SMTP) virtual e-mail
server, and other facilities. In order to run IIS, you must be working with a version of Windows that is designed to function as a
server in a network environment. This includes the Web Edition of Windows Server 2003.
In Windows 2000 Server and previous versions of Windows server operating systems, IIS is installed by default as part of the
operating system. In Windows XP and Windows Server 2003, IIS is not installed by default; you can add it using the
Add/Remove Windows Components option of Add or Remove Programs in Control Panel. (In Windows Server 2003, you
can install IIS using the Application Server component.)
It might be impractical for you to work with IIS for reasons such as the following:
You are developing ASP.NET Web pages while working with Windows XP Home Edition, which does not support IIS.
You do not want to host a Web server on your computer (for example, on your home network) for security reasons.
Running a Web server such as IIS requires that you perform extra steps to help secure the server and that you are
vigilant about installing the latest security updates.
Corporate policy does not allow you to install certain server components such as IIS.
The ASP.NET Development Server
If you cannot or do not want to use IIS as your Web server, you can still test your ASP.NET pages by using the ASP.NET
Development Server. The ASP.NET Development Server, which is included with Visual Web Developer, is a Web server that
runs locally on Windows operating systems, including Windows XP Home Edition. It is specifically built to serve, or run,
ASP.NET Web pages under the local host scenario (browsing from the same computer as the Web server). In other words, the
ASP.NET Development Server will serve pages to browser requests on the local computer. It will not serve pages to another
computer. Additionally, it will not serve files that are outside of the application scope. The ASP.NET Development Server
provides an efficient way to test pages locally before you publish the pages to a production server running IIS.
The ASP.NET Development Server only accepts authenticated requests on the local computer. This requires that the server can
support NTLM or Basic authentication.
Note
As a best practice, do not run Visual Web Developer while you are logged on as an Administrator — run it under a more rest
rictive account. This helps prevent inadvertent access to other files on the server.

The ASP.NET Development Server works only with individual pages and does not include the extra facilities of IIS. For example,
the ASP.NET Development Server does not support an SMTP mail server. If your Web application involves sending e-mail
messages, you must have access to the IIS SMPT virtual server to test e-mail because the ASP.NET Development Server cannot
forward e-mail messages or invoke a server that does.
Running the ASP.NET Development Server
The ASP.NET Development Server is installed by default with Visual Web Developer. If you are working with a file-system Web
site, Visual Web Developer automatically uses the ASP.NET Development Server to run pages. By default, the Web server is
invoked on a randomly selected port for the local host scenario. For example, if you are testing a page called
ExamplePage.aspx, when you run it on the ASP.NET Development Server, the URL of the page might be:

http://localhost:31544/ExamplePage.aspx

When you close the browser, the ASP.NET Development Server shuts down again.
If you want to run the ASP.NET Development Server on a specific port, you can configure the server to do so. You might do this
in these scenarios:
If code in your application listens to a specific port and you want to be able to test the application using the ASP.NET
Development Server.
If your application includes a reference to a client project or Web service that is bound to a specific port.
Visual Web Developer cannot guarantee that the port you specify will be available when you run your file-system Web site. For
details, see How to: Specify a Port for the ASP.NET Development Server.
Security Context for the ASP.NET Development Server
An important difference between the ASP.NET Development Server and IIS is the security context in which the respective
servers run your ASP.NET pages. This difference can affect your testing because of differences in how the pages run.
When you run a page using the ASP.NET Development Server, the page runs in the context of your current user account. For
example, if you are running as an administrator-level user, a page running in the ASP.NET Development Server will have
administrator-level privileges. In contrast, in IIS, ASP.NET by default runs in the context of the special user (ASPNET or
NETWORK SERVICES) that typically has limited privileges. The ASPNET or NETWORK SERVICES accounts are local to the server
computer (not domain accounts), which restricts access to resources on other computers.
If you are simply reading and running the code in ASP.NET pages, this difference is not very important. However, the different
security contexts for the two Web servers can affect your testing of the following:
Access to other resources that the page requires This can include reading and writing files other than Web pages,
reading and writing the Windows registry, and so on.
Database access When working with the ASP.NET Development Server, you can typically rely on Windows Integrated
authentication to access SQL Server. However, when the same page runs in IIS under the ASPNET or NETWORK
SERVICES account, the page is running in the context of a local user, and you often have to configure the page to use a
connection string that includes information about a user and password. For details, see
Accessing SQL Server from a Web Application and ASP.NET Security Architecture.
Code access security If your page involves access to resources that are protected under different zones, the page
might run differently under the ASP.NET Development Server and IIS.
Even though you can use the ASP.NET Development Server to test that pages are functional, you should test them again after
publishing the pages to a production Web server that is running IIS.
File Authorization on the ASP.NET Development Server
In a file-system Web site, static files, such as images and style sheets, are subject to ASP.NET authorization. For example, static
files in a file-system Web site will not be served to an anonymous user when anonymous access to those files is disabled.
However, when you create a Web site project in an HTTP location, IIS serves static files without using authorization rules.
See Also
Tasks
Walkthrough: Creating a Basic Web Page in Visual Web Developer
Concepts
ASP.NET Development Requirements
File System Web Sites
Visual Web Developer

How to: Specify the Web Server for Web Sites


When you run a Web site in Visual Web Developer, project options determine which Web server Visual Web Developer uses to
run (test) the site. By default, Visual Web Developer runs file system Web sites by using the ASP.NET Development Server.
However, you might want to run the file system Web site by using an Internet Information Services (IIS) virtual directory that
points to the folder where the site files are located.
For FTP Web sites, Visual Web Developer prompts you to specify a server URL the first time that you run the site. You can
change the server URL at any time.
You cannot specify that the Web server run a local or remote IIS Web site or application because Visual Web Developer always
uses the URL where the IIS Web site or application was created.
Note
The Web server option applies only when you are running (testing) the Web application in Visual Web Developer. Production
Web applications always run under IIS.

To specify the Web server for a Web site


1. In Solution Explorer, right-click the name of the Web site for which you want to specify a Web server, and then click
Property Pages.
2. In the Property Pages dialog box, click the Start Options tab.
3. Under Server, click Use custom server.
4. In the Base URL box, type the URL that Visual Web Developer should start when running the current Web site.
Note
If you specify the URL of a remote server (for example, an IIS Web application on another computer), be sure that the re
mote server is running at least the .NET Framework version 2.0.

See Also
Concepts
Web Servers in Visual Web Developer
Types of Web Sites in Visual Web Developer
Visual Web Developer

How to: Specify a Port for the ASP.NET Development Server


When you use the ASP.NET Development Server to run a file-system Web site, by default, the Web server is invoked on a
randomly selected port for localhost. For example, if you are testing a page called MyPage.aspx, when you run the page on the
ASP.NET Development Server, the URL of the page might be the following:

http://localhost:31544/MyPage.aspx

If you want to run the ASP.NET Development Server on a specific port, you can configure the server to do so.
Note
Visual Web Developer cannot guarantee that the port you specify will be available when you run your file-system Web site. If
the port is in use when you run a page, Visual Web Developer displays an error message.

To specify a port for the ASP.NET Development Server


1. In Solution Explorer, click the name of the application.
2. In the Properties pane, click the down-arrow beside Use dynamic ports and select False from the dropdown list.
This will enable editing of the Port number property.
3. In the Properties pane, click the text box beside Port number and type in a port number.
4. Click outside of the Properties pane. This saves the property settings.
Each time you run a file-system Web site within Visual Web Developer, the ASP.NET Development Server will listen on
the specified port.
See Also
Tasks
How to: Specify the Web Server for Web Sites
Concepts
Web Servers in Visual Web Developer
Types of Web Sites in Visual Web Developer
Visual Web Developer

How to: Bypass a Proxy Server for Local Web Requests


When you are using the ASP.NET Development Server to test your ASP.NET Web pages, you might receive a 502 error or an
error indicating that the page cannot be displayed. If so, your browser might be unable to resolve a URL containing localhost
and a port number, such as the following:
http:// localhost:8080 /MyWebSite/Default.aspx

You might be able to resolve this error by bypassing the proxy server for local Web requests, as described in the following
procedure.
To bypass a proxy server for local Web requests
1. In Visual Web Developer, on the Tools menu, click Options.
2. In the Options dialog box, select the Show all settings check box.
3. Double-click Environment, click Web Browser, and then click the Internet Explorer Options button.
4. On the Connections tab of the Internet Properties property sheet, click LAN Settings.
5. On the Local Area Network (LAN) Settings property sheet, clear the Automatically detect settings check box.
6. Under Proxy server, select the Use a proxy server for your LAN (These settings will not apply to dial-up or VPN
connections) check box.
7. Specify the address and port number that match your network, and then select the Bypass proxy server for local
addresses check box.
8. Click OK, click OK, and then click OK again.
9. On the File menu, click Exit, and then re-open Visual Web Developer to apply the changes.
See Also
Concepts
Troubleshooting the ASP.NET Development Server
Visual Web Developer

Troubleshooting the ASP.NET Development Server


The ASP.NET Development Server runs automatically when you test a file-system Web site in Visual Studio. For more
information, see Web Servers in Visual Web Developer.
Under some circumstances, working with the ASP.NET Development Server can result in errors. This topic lists situations in
which the Web server can produce errors and provides possible remedies.
"Could Not Create Windows User Token" Error
This error can occur if the Web site is configured in the Web.config file to use per-application impersonation (which is
impersonation with a fixed account), and if the account running the Web server does not have the Act as Part of the Operating
System privilege (also known as the Trusted Computing Base (TCB) privilege). You can configure the Web site to impersonate a
specific account by using syntax, such as the following, in the Web.config file.

<identity impersonate="true" userName="User1" password="Pwd" />

Security Note
When storing sensitive information such as user names and passwords in a configuration file, you should encrypt the sensiti
ve values using protected configuration. For more information, see
How to: Secure Connection Strings When Using Data Source Controls.

The process that launches the ASP.NET Development Server must have the TCB privilege. Therefore, if the Web site is
configured to perform impersonation, you must grant the TCB privilege to the account that is running the Web server.
Security Note
The TCB privilege is very powerful and as a rule, you should grant the TCB privilege to as few accounts as possible. If your W
eb site is using impersonation and cannot use the ASP.NET Development Server without granting the TCB privilege to the acc
ount running the Web server, consider using Internet Information Services (IIS) to test your Web site instead, so that you do
not have to grant privileges to an account needlessly.

"Page Cannot Be Displayed" Error (502 Error)


One possible cause of a 502 error or an error indicating that the page cannot be displayed is that the browser cannot resolve a
URL containing "localhost" and a port number, such as http://localhost:8080/ExampleWebSite/Default.aspx. The ASP.NET
Development Server works exclusively with localhost, and by default, uses a randomly selected port number for each request.
You might be able to resolve this error by bypassing the proxy server for local requests. For details, see
How to: Bypass a Proxy Server for Local Web Requests.
"Connection Refused" Error
The server reports the following error.

10061 - Connection Refused


Internet Security and Acceleration Server

This can occur if the computer is running on a network that is protected with the Internet Security and Acceleration Server (ISA
Server) and if either of the following conditions is true:
The firewall client is not installed.
The Web proxy settings in Internet Explorer are configured incorrectly.
This does not occur when working with IIS, because IIS uses port 80, and access to port 80 is allowed by ISA Server and other
firewall products. However, the ASP.NET Development Server randomly selects a port, and access to most ports is blocked by
firewall products such as ISA Server.
You can avoid this issue in these ways:
Install firewall client software, such as ISA client.
Modify the Web proxy connection settings in Internet Explorer to bypass the proxy server for local addresses.
"BIOS Limit Has Been Exceeded" Error
This error might occur if you are working in a file-system Web application in which the files are on a remote computer. The
error occurs as a run-time error when you try to run a page using the ASP.NET Development Server.
You are likeliest to see the error when the remote computer is running Windows 2000 or Windows XP. If the remote computer
is running Windows 2000, you can follow the instructions in Microsoft Knowledge Base article 810886 to set the maximum
number of concurrent connections to a higher number. If you are running Windows XP, you might be able to avoid this error
by closing existing shared resources, including terminal server sessions, on the remote computer. (Windows XP is configured
with a fixed number of maximum concurrent network requests.) If practical, you can also copy the Web application files to your
local computer and test the application there.
Static Files Are Not Served
In a file-system Web site, static files, such as images and style sheets, are subject to ASP.NET authorization rules. For example,
static files in a file-system Web site will not be served to an anonymous user when anonymous access to those files is disabled.
However, when you deploy the Web site to a server running IIS, IIS will serve the static files without using authorization rules.
See Also
Concepts
Types of Web Sites in Visual Web Developer
Visual Web Developer

How to: Create IIS Virtual Directories in Visual Web Developer


If you have Internet Information Services (IIS) running on your local computer, you can create an IIS virtual root that points to
files in a location outside of the default IIS folder structure (typically \Inetpub\wwwroot). A virtual directory is useful when you
want to run pages in an existing folder or in a local file-system Web site.
To create a local IIS virtual directory in Visual Web Developer
1. In Visual Studio, on the File menu, click New and then click Web Site.
2. In the New Web Site dialog box, click Browse.
3. In the Choose Location dialog box, click the Local IIS icon.
Note
You must be a member of the Administrators group on the local computer to access the IIS metabase and create a virtu
al directory.

4. In the tree control, select Default Web Site, or the folder in which you want to create a virtual directory.
5. In the top-right corner of the Choose Location dialog box, click the Create New Virtual Directory button. (There is no
text on this button, but the text appears when you place the mouse over the button.) This creates an
IIsWebVirtualDirectory administration object in IIS.
Note
Alternatively, you can click the Create New Web Application button, which will also create a virtual directory (an IIs
WebDirectory administration object in IIS), but it will not give you the option to map the virtual directory to a different
physical directory. For more information, see the topic "Metabase Structure" in the IIS SDK.

6. In the Alias name text box, type the name for your virtual directory.
7. In the Folder text box, type the fully qualified path to the physical directory where your files are located, or click the
Browse button to browse to the location, and then click OK.
Note
If you want clients to be able to browse to your Web pages, the access control list (ACL) configured on the physical dire
ctory needs to include Read and Execute permissions for the IIS_WPG account and the Internet Guest Account. For
more information, see the topic "Access Control with IIS 6.0" in the IIS Operations Guide.

You can continue to create or delete virtual directories in the Choose Location dialog box. When you are ready to create
a Web site project, you can select the location in the tree control and click Open.
To create a remote IIS virtual directory in Visual Web Developer
1. In Visual Studio, on the File menu, click New and then click Web Site.
2. In the New Web Site dialog box, click Browse.
3. In the Choose Location dialog box, click the Remote Site icon.
4. In the Web site location text box, click New Web Site.
5. In the Web URL text box of the Create New FrontPage Web dialog box, type the URL to the remote IIS server and
append the name of the virtual directory that you want to create, for example, http://<server name>/<new virtual
directory name>.
6. Click OK.
Note
If an authentication dialog box opens, type your user name and password, and then click OK. You must use an account
that has Create permissions on the server.

7. In the Choose Location dialog box, click Open.


8. In the New Web Site dialog box, click OK.
A new Web site project is created for your new remote virtual directory. The virtual directory is created as an
IIsWebDirectory administration object in the Default Web Site of the IIS server. For more information, see the topic
"Metabase Structure" in the IIS SDK.
Depending on your connection speed and processor speed, authoring a site remotely can be slower than authoring one
locally. As an alternative, you can author your site locally as a test Web site and then publish or copy your test site to the
remote location. For more information, see Publishing Web Sites or Copying Web Sites with the Copy Web Site Tool.
See Also
Tasks
Walkthrough: Creating a Web Site with Membership and User Login (Visual Studio)
Concepts
Types of Web Sites in Visual Web Developer
Using Visual Web Developer as a Non-Administrative User
ASP.NET Configuration

How to: Install and Configure SMTP Virtual Servers in IIS


In order to send e-mail from an ASP.NET Web application, you must have the Simple Mail Transfer Protocol (SMTP) service of
Internet Information Services (IIS) installed and configured on your server. The IIS SMTP service is a simple component for
forwarding e-mail messages to an SMTP server for delivery.
Installing the SMTP Service
The SMTP service is not installed by default with IIS. You must install the SMTP service using Control Panel. Installing the
SMTP service creates a default SMTP configuration that you can then customize by using IIS Manager.
To install the SMTP service on IIS 6.0
1. On the Start menu, click Control Panel, double-click Add or Remove Programs, and then click Add/Remove
Windows Components.
2. In the Components list, click Application Server, and then click Details.
3. In the Subcomponents of Application Server list, click Internet Information Services (IIS), and then click Details.
4. In the Subcomponents of Internet Information Services (IIS) list, select the SMTP Service check box, and then click
OK.
5. Click Next. If you are prompted for the Windows CD or the network install path, follow the instructions.
6. Click Finish.
When you install the SMTP service, a default SMTP server configuration is created with a message store in C:\Inetpub\Mailroot.
When you are setting up the SMTP service, you can configure global settings for the SMTP service, as well as settings for
individual components of the virtual server. The IIS SMTP service is a relay agent only. E-mail messages are forwarded to an
SMTP server for delivery.
Configuring the SMTP Virtual Server
Installing the SMTP service will create a new node in IIS Manager. In order to configure the SMTP virtual server, you must start
IIS Manager. For more information, see the topic "SMTP Administration" in the IIS Operations Guide.
Important
You must be logged on as a member of the Administrators group on the local computer to perform the following procedure
(or procedures), or you must have been delegated the appropriate authority.

To start IIS Manager from the Run dialog box


1. On the Start menu, click Run.
2. In the Open box, type inetmgr and then click OK.
To start IIS Manager from the Administrative Services console
1. On the Start menu, click Run. In the Run text box, type control panel, and then click OK.
2. In the Control Panel window, click Administrative Tools.
3. In the Administrative Tools window, click Internet Information Services.
Default Settings
The default SMTP virtual server has the following default settings. If you create a new virtual server, you can configure default
settings using the New Virtual Server Wizard.
Name: The name of the virtual server that appears in IIS Manager.You can change the name of the virtual server in IIS
Manager. Simply right-click the virtual server and then click Rename.
IP address/TCP port: All unassigned/25.You can use the General tab in the SMTP virtual server properties dialog box
to change this setting. If you change this setting, you must specify an IP address and TCP port combination that is not
being used by another SMTP virtual server. TCP port 25 is both the default TCP port and the recommended TCP port.
More than one virtual server can use the same TCP port, but they must be configured with different IP addresses. If you
do not set a unique IP address and TCP port combination, the SMTP virtual server will not start.
Default domain: The domain name that is listed on the Computer Name tab in System Properties.The default domain is
used to stamp messages from addresses that do not have a domain. An SMTP virtual server can have only one default domain,
and it cannot be deleted. To change the name of the default domain in IIS Manager, double-click the virtual server, and then
double-click Domains. Right-click the local (or default) domain, and then click Rename.
Home directory: C:\Inetpub\Mailroot.The home directory is the root of your SMTP content directories, and it must be
local to the computer on which the SMTP service runs.
See Also
Tasks
How to: Create and Configure Local ASP.NET Web Sites in IIS
Visual Web Developer

Using Visual Web Developer as a Non-Administrative User


As a security best practice, it is recommended that you log on to your computer as a user that does not have administrative
privileges. Running as a non-administrative user can help limit the effect of a security breach, because a process that runs in
your non-administrative user context does not have unlimited access to resources.
You can run Visual Web Developer when you are logged on as a non-administrative user, but certain features are not available.
In general, these are not limitations in Visual Web Developer itself but in other processes that Visual Web Developer interacts
with.
The following table lists features in Visual Web Developer that are not available if you are logged on as a non-administrative
user.
Feature Notes
Creating a new You cannot make changes to the Internet Information Services (IIS) metabase (for example, creating new entri
local or remote es) because it requires administrative privileges. This affects your ability to configure some settings in the Web
IIS Web site .config file.

Opening a local You cannot make changes to the IIS metabase (for example, creating new entries) because it requires administ
or remote IIS rative privileges. This affects your ability to configure some settings in the Web.config file.
Web site
You cannot run your Web site unless you use the ASP.NET Development Server, which is the default Web serv
er for file-system Web sites. Alternatively, you can set project options to open the browser and point to the We
b site using IIS. For details, see How to: Specify the Web Server for Web Sites.

Debugging a lo You cannot attach to a process that is running under the IIS worker process because it requires administrative
cal or remote II privileges.
S Web site

See Also
Tasks
How to: Specify the Web Server for Web Sites
Concepts
Local IIS Web Sites
Remote IIS Web Sites
Web Servers in Visual Web Developer
Using Visual Web Developer as a Non-Administrative User
Web Application Projects Overview
The Web application project type is an alternative to the Web site project type, which is the default project type in Visual Studio
2005.
This topic contains:
Scenarios
Background
Additional Resources
What's New
Scenarios
The Web application projects model was designed to provide developers with a project model that more closely resembles the
project model for Visual Studio .NET 2003 applications and still makes available all the new features of Visual Studio 2005 and
of ASP.NET version 2.0. The new Web application project type does not replace the Web site project type introduced in Visual
Studio 2005. Instead, it is an alternative project type that you might choose depending on your requirements and your
preferred development workflow.
Note
Visual Web Developer Express Edition does not support Web application projects.

Only files that are referenced in the solution of a Web application project are part of the project. These files are also displayed
in Solution Explorer and are compiled during a build. Because there is a project file, some scenarios are more easily enabled.
For instance, you can subdivide one ASP.NET application into multiple Visual Studio projects. Also, you can easily exclude files
from the project and from source code.
Alternatively, Web site projects use the folder structure to define the contents of the project. There is no project file in this
model and all files in the folder are part of the project.
Use Web application projects when you need to do the following:
Migrate large Visual Studio .NET 2003 applications to Visual Studio 2005.
Control the names of output assemblies.
Use stand-alone classes to reference page- and user-control classes.
Build a Web application by using multiple Web projects.
Add pre-build and post-build steps during compilation.
Back to top
Background
The new Web application project model provides the same Web project semantics as Visual Studio .NET 2003 Web projects.
This includes a structure based on project files and a build model based on a single assembly. In addition, the new project type
supports all the new features of Visual Studio 2005 (such as class diagrams, test development, and generics) and of ASP.NET
2.0 (such as master pages, data controls, membership and login, role management, Web Parts, personalization, site navigation,
and themes).
The Web application project model in Visual Studio 2005 removes the following two requirements from Visual Studio .NET
2003:
Using FrontPage Server Extensions from Microsoft. These are no longer required, but they are supported if your site
already uses them.
Using a local copy of IIS. The new project model supports both IIS and the built-in Visual Studio Development Server.
Installing Web Application Projects
Adding Web application projects to Visual Studio 2005 requires you to install Visual Studio 2005 Service Pack 1 (SP1). Visual
Studio 2005 SP1 includes changes to Visual Studio 2005 that enable the Visual Studio Conversion Wizard and the designer to
correctly process Web application projects. You can download Visual Studio 2005 SP1 on the
Microsoft Visual Studio Related Service Packs and Fixes Web site.
Back to top
Compilation and Build Outputs
The compilation model for Web application projects resembles the Visual Studio .NET 2003 compilation model. All code files
(stand-alone, code-behind, and designer class files) in the project are precompiled into a single assembly that is built and
persisted by default in the Bin folder. Because this compilation model creates a single assembly, you can specify attributes,
such as assembly name and version, and the location of the output assembly. For more information, see
Compiling Web Application Projects.
Back to top
Deployment
Because all class files are compiled into a single assembly, only that assembly needs to be deployed, along with the .aspx and
.ascx files and other static content files.
In this model, .aspx files are not compiled until they are run in the browser. However, when used with
Web Deployment Projects, the .aspx files can also be compiled and included in a single assembly for deployment.
Each time you deploy the single assembly produced in this model, you replace the code for all pages in the project. For more
information, see How to: Publish Web Application Projects.
Back to top
Upgrade from Visual Studio .NET 2003
The similarities between the Web application project model in Visual Studio 2005 and the Web site model in Visual Studio .NET
2003 simplify the upgrade process and minimize any restructuring of the application. For most scenarios, it is preferable to
upgrade existing Visual Studio .NET 2003 projects to Web application projects in Visual Studio 2005. For more information, see
Walkthrough: Converting a Visual Studio .NET 2003 Web Project to a Visual Studio 2005 Web Application Project.
Back to top
How to and Walkthrough Topics
How to: Create New Web Application Projects
How to: Set Properties of Web Application Projects
How to: Publish Web Application Projects
Walkthrough: Converting a Visual Studio .NET 2003 Web Project to a Visual Studio 2005 Web Application Project
Walkthrough: Converting a Web Site Project to a Web Application Project in Visual Studio 2005
Back to top
Additional Resources
Introduction to Web Application Projects
ASP.NET Forums -- Visual Studio 2005 Web Application Projects
Back to top
See Also
Tasks
How to: Create New Web Application Projects
How to: Set Properties of Web Application Projects
How to: Publish Web Application Projects
Walkthrough: Converting a Visual Studio .NET 2003 Web Project to a Visual Studio 2005 Web Application Project
Reference
Back to top
Concepts
Compiling Web Application Projects
Walkthrough: Converting a Web Site Project to a Web Application Project in Visual Studio 2005
How to: Create New Web Application Projects
The Web application project type does not replace the Web site project type that was introduced in Visual Studio 2005. Instead,
it is an alternative project type that you might use depending on your project requirements and your preferred development
workflow.
Note
Visual Web Developer Express Edition does not support Web application projects.

The new Web application project model provides the same Web project semantics as Visual Studio .NET 2003 Web projects.
This includes a structure based on project files and a build model based on a single assembly. However, the new project type
makes available all the new features of Visual Studio 2005 and of ASP.NET 2.0. For more information, see Web Application
Projects Overview.
To create a new Web application project
1. On the File menu in Visual Studio, click New, and then click Projects.
2. Under Project types, double-click (or expand) either Visual Basic or Visual C#, and then click Web to display the
available Web templates.
3. In the Templates box, select ASP.NET Web Application.
4. In the Name box, type the name of the new application.
5. In the Location box, type the name of the folder in which you want to store the pages of your Web application, and then
click OK. Alternatively, you can select the Browse button and navigate to the File System location.Visual Studio creates
the Web application project in the specified location.
See Also
Reference
Web Page, Project Designer
New Project Dialog Box
Other Resources
Web Application Projects Overview
How to: Set Properties of Web Application Projects
ASP.NET Web application projects share the same configuration settings and behavior as standard Visual Studio 2005 class-
library projects. The Web tab contains the properties specific to Web application projects. You can use this tab to configure
how a Web application project will be run and debugged. For more information, see Web Page, Project Designer.
By default, ASP.NET Web application projects are configured to start and run using the built-in Visual Studio Development
Server on a random HTTP port. Alternatively, Visual Studio can run and debug the Web application project by using Internet
Information Services (IIS).
When you run the application, Visual Studio compiles the project into a single assembly, which follows the build semantics of
Visual Studio .NET 2003 Web projects. When the application is running, Visual Studio attaches a debugger to the Web server
process. All project settings are saved in a standard Microsoft Build Engine (MSBuild) project file.
To set a property of a Web application project
1. In Solution Explorer, right-click the Web application project that you want to modify and then click Properties.
2. Select the Web tab.
3. On the Web properties page, select configuration options in the Start Action, Servers, and Debuggers groups to
specify how the Web application project will be tested in Visual Studio.
See Also
Reference
Web Page, Project Designer
Concepts
Class Library Template
Debugging Web Pages Overview
MSBuild Overview
Other Resources
Getting Started — Deploying Web Sites
Projects, User Interface Elements
How to: Publish Web Application Projects
By publishing a Web application project, Visual Studio compiles the files of a Web application into a single assembly and then
copies the compiled assembly to a specified location. ASP.NET Web application projects share the same configuration settings
and behavior as standard Visual Studio 2005 class-library projects. You can publish the Web application to a local or shared
folder, to an FTP site, or to a Web site that you access by using a URL.
The Publish Web dialog box, which is located on the Visual Studio Build menu, enables you to build and publish Web
applications. Additionally, you can choose to remove source code from the site. This provides a measure of protection for your
intellectual property and makes it more difficult for others to access the source code of your site. For information about what
happens to your files during precompilation, see File Handling During ASP.NET Precompilation.
Note
The Publish Web dialog box only applies to projects created by using the ASP.NET Web Application template.

Before publishing your Web application, check the configuration of your original site and note the following:
Any settings that must exist at the remote location. Specifically, review settings such as connection strings, membership
settings, and other security settings and make sure that that these settings are appropriate for your production
environment.
Any settings that must be changed on the published Web site. For example, you might want to disable debugging,
tracing, and custom errors after you publish your Web site.
Because configuration settings are inherited, you might need to examine multiple files to find all the applicable settings.
Configuration settings can be located in the Machine.config file or the root Web.config file in the
SystemRoot\Microsoft.NET\Framework\version\CONFIG directory, in addition to in any Web.config files in your application. If
you do not have permission to view the root configuration files, you can output a file that contains a complete list of
configuration settings for your Web site, formatted as a standard configuration file, by using the code example in
How to: View Inherited and Local Configuration Settings Programmatically. For definitions of configuration settings, see
General Configuration Settings (ASP.NET) and ASP.NET Configuration Settings.
Note
To complete the following procedure, you must have both Create and Write permissions in the target location.

To publish a Web application project


1. On the Build menu, click the Publish ProjectName option.
2. In the Publish Web dialog box, click the ellipsis button (…) to browse to the location to which you want to publish the
Web application project.
3. Select either the Replace matching files with local copies check box or the Delete all existing files prior to
publish check box.
4. Select how you want to copy the Web application project files to the new location: Only files needed to run this
application, All project files, or All files in the source project folder. Also, you can include files from the App_Data
folder by selecting the related check box.
5. Click OK to publish your Web application project.
In the task bar, Publish succeeded displays when publishing is completed.
6. Make any configuration changes that are required for your Web application at the target location. For more information,
see How to: Configure Published Web Sites.
Note
To help increase security, you might want to encrypt specific configuration settings. For more information, see
Encrypting Configuration Information Using Protected Configuration.
See Also
Reference
Publish Web Dialog Box
Other Resources
Web Application Projects Overview
Compiling Web Application Projects
The Web application project type provides an alternative to the Web site project type that was introduced in Visual Studio
2005. This new project model, which is based on the Visual Studio .NET 2003 Web project model, was created to simplify the
conversion of Visual Studio .NET 2003 Web projects to Visual Studio 2005 and to reduce the need for code changes. Code files
in the project are precompiled into a single assembly by using the Microsoft Build Engine (MSBuild). ASP.NET Web pages
(.aspx) and user controls (.ascx) are compiled dynamically on the server by the ASP.NET compiler.
Compilation Model
The compilation model for Web application projects resembles the Visual Studio .NET 2003 compilation model. All code files
(stand-alone, code-behind, and designer class files) in the project are precompiled into a single assembly that is built and
persisted by default in the Bin folder. Because this compilation model creates a single assembly, you can specify attributes,
such as assembly name and version, and the location of the output assembly.
A Web application project is defined by a project file instead of a project folder, which is used to define a Web site project. The
project file contains the files that are included in the project as well as the assembly references and other project metadata
settings. Files contained in the project folder that are not defined in the project file will not be compiled as part of the Web
application project. Project settings that are added and changed through Visual Studio are reflected in the project file (.*proj)
that is generated for each project.
To run and debug pages, you must compile the complete Web application project. Building the complete Web application
project can be fast because Visual Studio uses an incremental build model that builds only the files that have changed.
For more information about Web application projects, see Web Application Projects Overview.
Precompilation of Class Files
Web application projects use MSBuild to precompile class files. These class files are compiled into a single assembly and put in
the Bin folder by default. The compilation process can be extended and customized using standard MSBuild extensibility rules.
For more information about MSBuild, see MSBuild Overview.
Web application projects enable you to precompile the classes of an application into a single assembly. The following table
describes the types of Web application project class files that are compiled into a single assembly.
Class File Type Description
Standalone Class files that you can create and add to the Bin folder.

Code behind User-defined code that directly relates to content files.

Designer Code that is auto-generated. You should not modify the designer file.

You can also control the build through the property pages. For example, you can name the output assembly or add pre-build
and post-build actions during the build process. Additionally, you can control which class files will be included for compilation
based on the Build Action file property.
Customizing Compilation Options
The property pages of Web application projects can be used to modify the compilation characteristics of your Web application.
You can specify the output assembly name, version, and other details by using elements of the Application property page of
the Project Designer. Use the Build page of the Project Designer to specify the project's build configuration. For instance,
you can set the way errors are handled and details about the assembly output. Also, you can add pre-build and post-build
steps during compilation by setting values of the Build Events property page of the Project Designer. For more information
about property pages, see Projects, User Interface Elements.
Setting the Build Action Property
By default, MSBuild only compiles class files of Web application projects that have the Build Action property set to Compile.
However, if a class file is located in the App_Code folder of the Web application project, it will also be compiled by the ASP.NET
compiler. This is because the ASP.NET compiler does not support the Build Action property of files that are contained in the
App_Code folder. Also, the App_Code folder is not typically included in Web application projects.
Note The App_Code folder exists for Web site projects in Visual Studio 2005. This folder is not typically included in Web
Application Projects. For more information about the App_Code folder, see Shared Code Folders in ASP.NET Web Sites.
Dynamic Compilation
Although code files in the project are precompiled into a single assembly by using MSBuild, ASP.NET Web pages (.aspx) and
user controls (.ascx) of a Web application project are compiled dynamically on the server by the ASP.NET compiler. In a Web
application project, Web pages and user controls use the CodeBehind attribute and the Inherits attribute. The CodeBehind
attribute points to the code-behind file to use. The Inherits attribute points to a namespace and class in the code-behind file.
Note
If you change the root namespace of a Web application project, be sure to update the Inherits attribute in the .aspx page to a
ppropriately match the namespace.

In Web application projects, you can make limited changes to the ASP.NET Web pages in your site after compiling and
deploying them. For example, you can change the arrangement of controls, colors, fonts, and other appearance aspects of
pages. You can also add controls, as long as they do not require event handlers or other code. When the site first runs, ASP.NET
performs additional compilation in order to create output from the markup.
If you need to customize the declaration of a control within a Web application project, you should move the control declaration
out of the designer file and into the code-behind file. Moving the declaration of a control to the code-behind file is useful in the
following situations:
When the control needs to be typed differently.
When you want a scope for the control other than the default scope.
When you need to add metadata attributes to the declaration of the control.
When you need to write specific XML comments for the declaration of the control.
For more information about adding controls, see How to: Add Controls to an ASP.NET Web Page Programmatically.
Deployment
Because all class files are compiled into a single assembly, only that assembly must be deployed, together with the .aspx and
.ascx files and other static content files. In this model, .aspx files are not compiled until they requested by the browser. However,
when it is used with Web Deployment Projects, which is a downloadable add-in to Visual Studio 2005, the .aspx files can also
be compiled and included in a single assembly for deployment. To download this add-in, see
Visual Studio 2005 Web Deployment Projects on the ASP.NET Developer Center. For more information about how to deploy
Web application projects, see How to: Publish Web Application Projects.
See Also
Reference
Build Events Page, Project Designer (C#, J#)
Build Page, Project Designer (C#)
@ Page
Concepts
MSBuild Overview
Shared Code Folders in ASP.NET Web Sites
What's New in the ASP.NET Web Page Model
Other Resources
MSBuild Concepts
Web Application Projects
Walkthrough: Converting a Web Site Project to a Web
Application Project in Visual Studio 2005
This walkthrough explains the process of converting an existing Visual Studio 2005 Web site project to a Visual Studio 2005
Web application project. The Web application project model uses the same conceptual approach as a Web project in Visual
Studio .NET 2003. This includes a project file to include and exclude files and compilation to a single assembly. For more
information about Web project conversion, see Web Project Conversion from Visual Studio .NET.
Tasks illustrated in this walkthrough include the following:
Opening and verifying your Visual Studio 2005 Web site project.
Creating a new Visual Studio 2005 Web application project.
Setting project references.
Copying files to the new Web application project.
Converting the project files.
Running the Web application project.
Adding namespace syntax.
Converting declarative typed datasets.
Converting profile object code.
Prerequisites
In order to complete this walkthrough, you will need:
Visual Studio 2005 Service Pack 1 (SP1)
The .NET Framework version 2.0
Opening and Verifying Your Visual Studio 2005 Web Site Project
Before converting a project, open your existing Visual Studio 2005 solution. Compile and run the solution to verify that
everything works the way you want.
To open and verify your Visual Studio 2005 Web project
1. On the File menu, click Open and then click Web Site.
2. In the Open Web Site dialog box, select the project folder you want to open and then click Open.
3. On the Build menu, select Build Web Site.
4. On the Debug menu, select Start Debugging. Alternatively, you can press F5.
Note
If the Debugging Not Enabled dialog box is displayed, select Add a new Web.config file with debugging enable
d.

5. Verify that your project runs as expected.


Creating a New Visual Studio 2005 Web Application Project
The best strategy for converting an existing Visual Studio 2005 Web site project is to first create a new, blank Visual Studio
2005 Web application project in a separate directory. This avoids changing any part of the existing Web site files, and will
enable you to copy already implemented functionality into the new Web application project. You can add this new project
either to your existing solution, which is ideal when you have several class-library projects that you want to use, or by starting
a new instance of Visual Studio and creating a new solution and project within it.
To create a new Visual Studio 2005 Web application project in a new solution
1. In Visual Studio 2005, close all open solutions.
2. On the File menu, click New, and then click Project.The New Project dialog box opens.
3. In the Project types section of the New Project dialog box, double-click (or expand) the language that you want to use,
and then select Web to display the Web-related templates.
4. Select the ASP.NET Web Application template.
5. Type the Name, Location, and Solution Name that you want to use, and then click OK to create the Web application
project.
6. Once the project is created, delete the Default.aspx and Web.config files.
Setting Project References
If your Visual Studio 2005 Web site project requires additional project or assembly references, you can add them to the Web
application project. You can see the list of default references with new Visual Studio 2005 Web application projects under the
References node within Solution Explorer.
Note
Before converting the project files, add references to the Web application project for assemblies that existed in the Bin folder
to help prevent errors.

For more information about references, see Project References.


To add references to a Visual Studio 2005 Web application project
1. In Solution Explorer, right-click References, and then click Add Reference.
2. In the Add Reference dialog box, select the reference that you want to add and then click OK.
3. In Solution Explorer, right-click the Web application and click Build.Visual Studio builds the project and verifies that any
project-to-project references are working.
Copying Files to the New Web Application Project
The easiest way to add your existing files is to copy the files from a Visual Studio 2005 Web site project to the Web application
project. In Solution Explorer, select all the files in the Web site project and then copy and paste the files into the new Web
application project. The directory structure should look the same as it did in the Web site project.
Note
If the Data Source Configuration Wizard is started during the copy process, click Cancel in the wizard's dialog box and allow
the rest of the files to be copied.

One difference between a Visual Studio 2005 Web site project and a Visual Studio 2005 Web application project is that the
Visual Studio 2005 Web site project model dynamically generates the tool-generated partial class and does not persist it on
disk. However, the Visual Studio 2005 Web application project model saves this partial class on disk within files that have a
.designer.cs file name extension. Also, the Web application project model compiles the partial class using the in-memory Visual
Studio compilers when a build occurs.
After copying the files from the Web site project to the Web application project, you will notice how the code-behind files for
each page and user-control are still associated with the .aspx, .master, and .ascx files. No .designer.cs files have been generated.
As part of the next step, you will be converting these pages to persist their partial class declarations on disk in a .designer.cs
file.
Converting the Project Files
Visual Studio includes an option to convert pages and classes within Web application projects to use partial class declarations.
Partial classes are used to separate designer-generated code from code-behind code. These designer-generated classes are
stored in a separate file from the code-behind file. This conversion process causes Visual Studio 2005 to recursively examine
every page, user-control, and master-page in the project, and to automatically generate a .designer.cs file for each. Visual
Studio also changes the .aspx or .ascx files to use the codeBehind attribute instead of the codeFile attribute. This command
will also rename the App_Code file to Old_App_Code.
To convert pages and classes to use partial classes in a Web application project
In Solution Explorer, right-click the root project folder that contains the pages and classes you want to convert, and then
click Convert to Web Application.
After you have converted pages and classes to use partial classes, build the project to see whether there are any compilation
errors. The two most likely causes of errors are:
A missing assembly reference that must be added to your project.
An issue with a dynamically generated type, such as the "Profile" object or a typed dataset.
If you are missing an assembly reference, you should open the reference manager and add it. If you are using a dynamically
generated type, see Converting Declarative Typed Datasets and Converting Profile Object Code later in this topic.
Note
If a Visual Basic class file contains more than one namespace, make sure to verify each namespace after conversion.

Because ASP.NET 2.0 dynamically compiles any classes it finds in the App_Code directory of an application at run time, you
should not store classes that you compile as part of your Visual Studio 2005 Web application project in the App_Code folder. If
you do, the class will get compiled two times: one time as part of the Visual Studio 2005 Web application project assembly, and
then again at run time by ASP.NET. The result will most likely be a could not load type runtime exception, which occurs
because there are duplicate type names in the application. Instead, you should store your class files in any folder of your
project other than the App_Code folder. This will be handled automatically by the Convert to Web Applicaiton command,
which will rename the folder to Old_App_Code.
Running the Web Application Project
Once you have completed the previous steps, you will be able to compile and run your application without any errors. By
default, Visual Studio will use the built-in Visual Studio Development Server to run the site. Alternatively, you can configure the
project to use Internet Information Services (IIS). To manage Web application project settings, right-click the project and then
click Properties. You can then select the Web tab to configure these runtime settings. For more information about the Web
application project Web tab, see Web Page, Project Designer.
Additional Conversion Options
There are three additional conversion options to consider when you convert your project to a Web application project. These
options are:
Adding namespace syntax.
Converting declarative typed datasets.
Converting profile object code.
Adding Namespace Syntax
By default, pages and classes built by using the Visual Studio 2005 Web site project model do not automatically include a code
namespace. However, pages, controls, and classes built by using the Visual Studio 2005 Web application project model
automatically include a code namespace. When converting the Web site project to a Web application project, you will have to
add the namespaces to the code.
You can easily add namespaces to code in existing classes within Visual Studio by using the Surround With shortcut menu
command in the C# code editor.
To add a namespace to existing classes
1. In Solution Explorer, select and open the code file that you want to modify.
2. Select a class (or multiple classes) in the source editor, right-click the selected code, and then click Surround With.
3. Select the Namespace item in the list.
Note that .aspx, .ascx, .master, .ashx, .asmx, and .asax files contain inherits or class attributes that list the class names they
should invoke. So, if you add namespaces to the code-behind files of these file types, you must also add the namespace to the
Inherits and Class declarations. For example, if you add a namespace called "WebApplication5" to the code-behind file, then
you would change the page directive of the Details.aspx page from "inherits=Details_aspx" to
"inherits=WebApplication5.Details_aspx".
Note
When converting the Web site project to a Web application project, verify that the Inherits attribute and the CodeFile attrib
ute of the Page directive contain the namespace of the class to be inherited.

If you must update the namespace multiple times in a file, you can use the Find and Replace command on the Edit menu to
avoid individually changing each instance. In the Find what text box, type the inherits=" string, and in the Replace with box,
type the inherits="WebApplicationName. string, where "WebApplicationName" is the new namespace. Make sure that you
include the trailing period (.) at the end of the replacement string because it will be prepended to the previous class name
during the replacement process.
For more information about how to use the Surround With command, see How to: Use Surround-with Code Snippets.
Converting Declarative Typed Datasets
If you have strongly typed DataSet classes in the App_Code directory in your Visual Studio 2005 Web site project, then you
must make an additional change to fix the connectionString in the Web.config file. Specifically, you must open each DataSet
in the Designer, select each TableAdapter, and then reset the connectionString for the object.
To fix the connectionString of strongly typed DataSets
1. In Solution Explorer, right-click the DataSet and then select View Designer.The Designer window opens.
Note
If the DataSet connection is configured, you can double-click the DataSet to display it in View Designer.

2. Right-click each TableAdapter and select Properties.


3. Select the Connection property and reset the connection by selecting an available drop-down option. When you update
the connection, the ConnectionString will also be updated.
Converting Profile Object Code
ASP.NET 2.0 adds support for a new feature named profile personalization. This feature enables developers to easily store and
retrieve user-profile data in a personalization database. With Visual Studio 2005 Web site projects, ASP.NET automatically adds
a strongly typed Profile object to each page in the project. This object provides a strongly typed mapping of all properties
defined in the profile section of the application's Web.config file. Developers can then get IntelliSense data for this object, and
automatically save and retrieve values from it. For example, an application's Web.config file might contain the following
section.

<profile defaultProvider="AspNetSqlProfileProvider">
<properties>
<add name="Teachers"
type="Teachers"
allowAnonymous="true" />
</properties>
</profile>

In this case, developers could add the following code to their pages to save and retrieve information about the "Teachers"
object as shown in the following code example.

public partial class _Default : System.Web.UI.Page


{
protected void Button1_Click(object sender, EventArgs e)
{
Teachers teachers = new Teachers();
teachers.Add(new Teacher("Scott"));
teachers.Add(new Teacher("Bob"));
teachers.Add(new Teacher("Paul"));
Profile.Teachers = teachers;
}
protected void Button2_Click(object sender, EventArgs e)
{
GridView1.DataSource = Profile.Teachers;
GridView1.DataBind();
}
}

With the Visual Studio 2005 Web site project option, this scenario is supported because Visual Studio is dynamically creating
and adding a ProfileCommon class named Profile to every code-behind instance.
The SP1 version of the Visual Studio 2005 Web application project does not automatically include the ProfileCommon class.
Therefore, some additional steps are required to obtain strong-typing for the Profile class. Specifically, you can create your
own ProfileCommon class that contains strongly typed properties for the items configured in the profile system. Then you
can accesses the current Profile property of the HttpContext object to get and set the properties as shown in the following
code example.

using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.Profile;

namespace WebApplication6
{
public class ProfileCommon
{
public Teachers Teachers
{
get
{
return (Teachers) HttpContext.Current.Profile.GetPropertyValue("Teachers");
}
set
{
HttpContext.Current.Profile.SetPropertyValue("Teachers",value);
}
}
}
}

You can then add an instance of the ProfileCommon class named "Profile" to the pages that must use the profile system as
shown in the following code example.

namespace WebApplication20
{
public partial class _Default : System.Web.UI.Page
{
ProfileCommon Profile = new ProfileCommon();
protected void Button1_Click(object sender, EventArgs e)
{
Teachers teachers = new Teachers();
teachers.Add(new Teacher("scott"));
teachers.Add(new Teacher("bob"));
teachers.Add(new Teacher("paul"));

Profile.Teachers = teachers;
}
protected void Button2_Click(object sender, EventArgs e)
{
GridView1.DataSource = Profile.Teachers;
GridView1.DataBind();
}
}
}
You will not have to change any other code on the page. Also, you will be able to use the profile system as you did with your
original Web site project. For more information about how to use the profile system, see ASP.NET Profile Properties Overview.
See Also
Tasks
How to: Use Surround-with Code Snippets
Reference
Web Page, Project Designer
@ Page
Concepts
Web Project Conversion from Visual Studio .NET
Project References
ASP.NET Profile Properties Overview
Visual Web Developer

Learning More - Creating Web Sites


This section contains topics and content related to learning more about varied ASP.NET and Visual Studio technology including
projects and solutions, layout, different types of sites, editing stand-alone files, and troubleshooting the Visual Studio Web
server.
In This Section
Web Site Projects and Solutions
Source Code Control for Web Sites
Referencing Additional Components in Web Sites
ASP.NET Life Cycle
Custom ASP.NET Processing with HTTP Handlers
Extending ASP.NET Processing with HTTP Modules
Related Sections
ASP.NET Web Sites (Visual Studio)
Provides information about creating Web sites.
Visual Web Developer

Web Site Projects and Solutions


This section features several categories of content explaining how to work with Web site projects and how to create your
ASP.NET Web applications using Visual Web Developer.
In This Section
What's New in Web Projects
Web Pages and Projects
ASP.NET Web Site Layout
ASP.NET Web Site Paths
Web Site File Types
Shared Code Folders in ASP.NET Web Sites
See Also
Other Resources
ASP.NET Master Pages
ASP.NET Themes and Skins
Visual Web Developer

What's New in Web Projects


This topic describes how the organization and structure of Web sites have changed from earlier versions of Microsoft Visual
Studio.
In Visual Studio .NET 2002 and Visual Studio .NET 2003, Web projects were organized using essentially the same model that
was used for client projects (Windows Forms projects). The Web project was based on a model in which the entire project was
compiled into a single executable assembly.
In Visual Web Developer, the organization of Web projects has been changed to reflect more accurately the way ASP.NET
applications are typically constructed. This topic describes the changes at a high level and provides links to topics that describe
new and changed features in more detail.
Types of Web Sites
A significant difference is that you can now create different types of Web sites. Instead of creating only Web sites that run as
Internet Information Services (IIS) applications, you can now create the following types:
File-system Web site You can store files in any folder, and you can open and work with any collection of Web pages,
no matter where they are located. An important feature is that you do not need to have IIS installed to run pages in a file-
system Web site. Instead, you can test your Web sites by using the ASP.NET Development Server, a lightweight test
server. For details, see Web Servers in Visual Web Developer.
FTP Web site You can open and edit Web site files by using the File Transfer Protocol (FTP) directly from within Visual
Web Developer.
Local IIS Web site You can continue to create Web sites that run under your local copy of IIS, as you did in earlier
versions of Visual Studio. Local IIS Web sites do not require FrontPage Server Extensions.
Remote Web site You can create Web sites that run under IIS on a different computer that is running either
FrontPage 2000 Server Extensions or FrontPage 2002 Server Extensions. For more information, see
Types of Web Sites in Visual Web Developer.
Web Site Layout
As in earlier versions of Visual Studio, you keep your Web pages in the root of the Web site and in subfolders, as required by
your application. However, your Visual Web Developer Web site can contain the following subfolders that have specific
characteristics:
App_Browsers folder Contains browser definition files that ASP.NET uses to identify individual browsers and
determine their capabilities.
App_Data folder Contains Microsoft Access databases (.mdb files), XML files, and other data stored in local files. The
user account that is used to run the application (for example, the local ASPNET account) has permissions to read, write,
and create files in this folder. Various ASP.NET application features, such as the providers for membership and roles, as
well as the Web Site Administration Tool, are configured to work with the App_Data folder specifically.
Bin folder Contains compiled code, as in earlier versions of Visual Studio. Any classes represented by code in the Bin
folder are automatically referenced in your Web site. For more information, see
Shared Code Folders in ASP.NET Web Sites.
App_LocalResources folder Contains .resx files that are bound to a specific page. You can define multiple .resx files for
each page, each .resx file representing a different language or language/culture combination. For more information, see
Localizing ASP.NET Web Pages Using Resources and
How to: Create Resource Files for ASP.NET Web Sites (Visual Studio).
App_GlobalResource folder Like the App_LocalResources folders, but contains .resx files that are not bound to a
specific page. Resource values in .resx files in the App_GlobalResource folders can be accessed programmatically from
application code.
App_Code folder Contains source code files. The code is compiled as part of your application and is referenced
automatically. The App_Code folder works much like the Bin folder, except that you can put source code in it instead of
compiled code. While you are working in Visual Web Developer, the source code in the App_Code folder is compiled
dynamically so that IntelliSense can reference any classes defined in the files. For more information, see
Shared Code Folders in ASP.NET Web Sites.
App_Themes folder Contains a collection of files that define the appearance of ASP.NET Web pages and controls. For
more information, see ASP.NET Themes and Skins Overview.
App_Browsers folder Contains .browser files that define browser capabilities.
App_WebReferences folder Contains files used to create a reference to a Web service (in the same project or external
to the project), including .disco and .wsdl files. For more information, see
How to: Add a Reference to a Visual Studio Project in a Web Site.
Visual Web Developer does not create these folders by default, except the App_Data folder. In some cases, the folders are
created by utilities. For example, running the Generate Local Resource command creates the App_LocalResources folder. In
other cases, you can create the folders manually.
Simplified Web Site Templates
When you create a new Web site, the number of files that are created by default is less than it was in earlier versions of Visual
Studio. In general, Visual Web Developer creates only the files that you need. As a consequence, a Web site does not initially
contain a Web.config file, a Global.asax file, and so on. If you need these files in your Web application, you can add them as new
items. Similarly, although ASP.NET treats certain folders specially, the folders are not created by default. Similarly, you can add
any additional folders that are required by your application.
Changes in Code-Behind and Single-File Page Models
ASP.NET version 2.0 features a new code-behind model that simplifies the relationship between the .aspx page and its
corresponding code. Visual Web Developer also includes complete support for single-file pages. For details, see
What's New in Code-Behind Support in Visual Web Developer and What's New in the ASP.NET Web Page Model.
Changed Build and Deployment Model
In earlier versions of Visual Studio, Visual Studio would build (or compile) your Web site project into a single assembly when
you ran a page. In the new project model, you do not need to compile your project before running it. Visual Web Developer
now follows the model supported by ASP.NET — pages and their dependent components are compiled individually when they
are requested, and the compiled version of the page is cached until the source is changed.
Note
By default, Visual Web Developer builds your Web site each time you test it by running it from the designer, and you can expl
icitly build individual pages or the entire Web site at any time. The purpose of this build process is to help you find compile-ti
me errors, not to produce executable code. The output of this build step is discarded after the build process, and the request c
ompiles the page as normal.

Deployment
The change in build models means that you do not deploy your site by copying a single .dll file and supporting .aspx files.
Instead, you copy the entire site, including .aspx files, class files (.vb, .cs, or .jsl files), and other files, all as source files. Deploying
sites by copying the source simplifies deployment (because you do not need to copy binary files) and maintenance (because
you do not need to recompile the entire site whenever you make a change in a class file).
Visual Web Developer offers several deployment options. You can publish your site, which precompiles the site and then
copies the output to a target location. Precompiling for publishing performs the same compilation that would normally occur
dynamically at run time, producing binary output. You can precompile the site and replace the .aspx files in your site with stubs
that point to the compiled versions of the pages. Alternatively, you can publish the site as an updateable site, which does not
compile the .aspx files into stubs, and therefore allows you to change markup and layout without recompiling and
republishing. As with building your project in Visual Studio .NET 2003, precompiling helps you catch compilation errors, and
because dynamic compilation is not required, precompiling can help reduce the startup time for your site. An important feature
of precompiling for publishing is that it can also help protect your site's source code by providing you with an object-only
version of the site that you can deploy.
Note
The Publish Web Site utility is not available in Visual Web Developer Express Edition.

An alternative to publishing your site by precompiling it is to copy your site to the production server using the Copy Web tool.
The Copy Web tool works like an FTP utility, allowing you to copy files to and from a target site and providing the option to
synchronize two sites automatically.
For more information, see Web Site Deployment in Visual Web Developer.
Programming Languages
As with Visual Studio .NET 2002, you can create the code for Web pages in a variety of the .NET Framework languages. Because
the Web site is not compiled into a single assembly, you can have pages and components that use different programming
languages in the same Web site.
Web Server Requirements
You no longer need IIS to test your Web projects. Visual Web Developer includes the ASP.NET Development Server, a Web
server that runs on your local computer and can serve (or run) pages. The ASP.NET Development Server accepts requests only
from the local computer (localhost), and is therefore both convenient for testing pages on your computer and protected
against requests from outside of your computer.
If you create a file-system Web site, when you run your project in Visual Web Developer, Visual Web Developer starts the
ASP.NET Development Server and displays the page. (If you are working with a local IIS site, remote site, or an FTP site, Visual
Web Developer runs the page by using the version of IIS that is associated with that Web site.)
Project Information Persistence
Visual Web Developer no longer requires a project (.vbproj or .csproj) file for Web sites. A significant benefit of not having a
project file is that the site is easier to develop with multiple programmers, since there is no contention for a central project file.
In addition, you can open any folder containing Web files as a Web site.
Because Web sites are now file-system based, one of the primary purposes of the project file — to track which files belonged
to the project — is no longer necessary. Other information that was tracked in a project file is now stored in the Web.config file.
For more information, see Web Project Settings Conversion.
Web sites continue to use solution (.sln and .suo) files to track user-specific configuration information for the site. Visual Web
Developer also maintains user-specific information, such as debug information, in the local user folders. For more information,
see File Types and File Extensions in Visual Studio.
See Also
Concepts
What's New in Web Development for Visual Studio
What's New in the ASP.NET Web Page Model
What's New in Code-Behind Support in Visual Web Developer
Visual Web Developer

Web Pages and Projects


Web Forms pages are one way to create the user interface of an ASP.NET–based Web application. You can add Web Forms
pages to several types of Visual Studio projects. Most often, when you want to work with Web Forms pages, you will use the
ASP.NET Web Application project template. For more information about Web project templates, see "Simplified Web Site
Templates" in What's New in Web Projects. For general information about ASP.NET Web applications, see
Types of Web Sites in Visual Web Developer.
To work with a Web Forms page in Visual Studio, you use the Web Forms Designer. The designer includes a WYSIWYG view,
called Design view, for laying out the elements of the page. Alternatively, you can switch the designer to an HTML view, called
Source view, which gives you direct access to the ASP.NET syntax of the elements on the page. Finally, the designer includes a
code editor with IntelliSense that you can use to create the page initialization and event-handler code for your page. For more
information, see ASP.NET Web Pages Introduction (Visual Studio).
Project Files Created With Web Forms
When you create a Web project, Visual Studio constructs a Web application directory structure on the target Web server, and a
project structure on your local computer. The following table describes the files that relate to your Web Forms pages.
Note
You need to have appropriate privileges on the Web server computer to create and manage Web application files. For details,
see ASP.NET Web Site Security (Visual Studio).

File Created Description


WebForm1.aspx an These two files make up a single Web Forms page. The .aspx file contains the visual elements of the Web F
d WebForm1.aspx. orms page, for example HTML elements and Web Forms controls. The WebForm1.aspx.vb class file is a hid
vb files for Visual B den, dependent file of WebForm1.aspx. It contains the code-behind class for the Web Forms page, containi
asic Web applicatio ng event-handler code and the like. For more information, see Web Forms Code Model.
ns
—or—
WebForm1.aspx.cs
files for Visual C#
Web applications

AssemblyInfo.vb fil A project information file (AssemblyInfo.vb or AssemblyInfo.cs file) that contains metadata about the
es for Visual Basic assemblies in a project, such as name, version, and culture information. For details on data contained in th
projects e assembly file, see Assembly Manifest.
—or—
AssemblyInfo.cs fo
r C# projects

Web.config file An XML-based file that contains configuration data on each unique URL resource used in the project. For
more information, see Application Configuration Files.

Global.asax and Gl An optional file for handling application-level events. This file resides in the root directory of an ASP.NET a
obal.asax.vb files pplication. The Global.asax.vb class file is a hidden, dependent file of the Global.asax file. It contains the cod
e for handling application events such as the Application_OnError event. At run time, this file is parsed a
—or— nd compiled. For more information about Global.asax file usage, see
Global.asax and Gl How to: Handle Application-Level Errors.
obal.asax.cs files

Styles.css file A cascading style sheet (CSS) file to be used within the project. For more information, see
Cascading Style Sheets Overview.

Deployment
The server on which you create your Web Forms pages is typically not the server on which you will deploy the pages and their
associated files for production. To deploy a Web project containing Web Forms pages, you may follow one of two approaches:
Copy your project to the Web server.
Create a deployment project.
For more information about these options, see Deployment of a Web Setup Project.
See Also
Concepts
Using Solution Explorer
ASP.NET Authorization
Introduction to Solutions, Projects, and Items
Deployment of a Web Setup Project
Other Resources
Web Site Projects and Solutions
ASP.NET

ASP.NET Web Site Layout


You can keep your Web site's files in any folder structure that is convenient for your application. To make it easier to work with
your application, ASP.NET reserves certain file and folder names that you can use for specific types of content.
Default Pages
You can establish default pages for your application, which can make it simpler for users to navigate to your site. The default
page is the page that is served when users navigate to your site without specifying a particular page. For example, you can
create a page named Default.aspx and keep it in your site's root folder. When users navigate to your site without specifying a
particular page (for example, http://www.contoso.com/) you can configure your application so that the Default.aspx page is
requested automatically. You can use a default page as the home page for your site, or you can write code in the page to
redirect users to other pages.
Note
In Internet Information Services (IIS), default pages are established as properties of your Web site.

Application Folders
ASP.NET recognizes certain folder names that you can use for specific types of content. The table below lists the reserved folder
names and the type of files that the folders typically contain.
Note
The content of application folders, except for the App_Themes folder, is not served in response to Web requests, but it can be
accessed from application code.

Folder Description
App_B Contains browser definitions (.browser files) that ASP.NET uses to identify individual browsers and determine their cap
rowser abilities. For more information, see Browser Definition File Schema (browsers Element) and
s How to: Detect Browser Types in ASP.NET Web Pages.

App_C Contains source code for utility classes and business objects (for example, .cs, .vb, and .jsl files) that you want to compil
ode e as part of your application. In a dynamically compiled application, ASP.NET compiles the code in the App_Code folder
on the initial request to your application. Items in this folder are then recompiled when any changes are detected.
Note
Arbitrary file types can be placed in the App_Code folder to create strongly typed objects. For example, placing Web s
ervice files (.wsdl and .xsd files) in the App_Code folder creates strongly typed proxies.

Code in the App_Code folder is referenced automatically in your application. In addition, the App_Code folder can cont
ain subdirectories of files that need to be compiled at run time. For more information, see
Shared Code Folders in ASP.NET Web Sites and
codeSubDirectories Element for compilation (ASP.NET Settings Schema).

App_D Contains application data files including MDF files, XML files, as well as other data store files. The App_Data folder is us
ata ed by ASP.NET 2.0 to store an application's local database, which can be used for maintaining membership and role inf
ormation. For more information, see Introduction to Membership and Understanding Role Management.

App_G Contains resources (.resx and .resources files) that are compiled into assemblies with global scope. Resources in the Ap
lobalR p_GlobalResources folder are strongly typed and can be accessed programmatically. For more information, see
esourc ASP.NET Web Page Resources Overview.
es
App_L Contains resources (.resx and .resources files) that are associated with a specific page, user control, or master page in a
ocalRe n application For more information, see ASP.NET Web Page Resources Overview.
source
s

App_T Contains a collection of files (.skin and .css files, as well as image files and generic resources) that define the appearanc
hemes e of ASP.NET Web pages and controls. For more information, see ASP.NET Themes and Skins Overview.

App_ Contains reference contract files (.wsdl files), schemas (.xsd files), and discovery document files (.disco and .discomap fil
WebR es) defining a Web reference for use in an application. For more information about generating code for XML Web servi
eferen ces, see Web Services Description Language Tool (Wsdl.exe).
ces

Bin Contains compiled assemblies (.dll files) for controls, components, or other code that you want to reference in your ap
plication. Any classes represented by code in the Bin folder are automatically referenced in your application. For more i
nformation, see Shared Code Folders in ASP.NET Web Sites.

Managing Subfolders
Configuration settings for your site are managed in a Web.config file that is located in the site's root folder. If you have files in
subfolders, you can maintain separate configuration settings for those files by creating a Web.config file in that folder.
Note
You cannot set or override configuration settings at the subfolder level if they apply to the site as a whole.

For more information, see Configuring ASP.NET Applications.


Restricting Access to Site Content
As part of the site's configuration, you can configure settings that restrict access to either individual files or subfolders. You can
restrict content by individuals or by roles (groups). For details, see Managing Authorization Using Roles.
See Also
Tasks
How to: Create Web.config Files (Visual Studio)
Concepts
Shared Code Folders in ASP.NET Web Sites
ASP.NET Web Site Paths
ASP.NET Themes and Skins Overview
ASP.NET Web Page Resources Overview
ASP.NET

ASP.NET Web Site Paths


When working with resources in a Web site, you must often specify a path for the resource. For example, you might use a URL
path to reference an image file in a page or the URL of a page elsewhere in the Web site. Similarly, code in your Web
application might use a physical file path to a server-based file to read or write the file. ASP.NET provides facilities for referring
to resources and for determining the paths of pages or other resources in the application.
Specifying Paths for Resources
In many cases, elements or controls on your page must refer to an external resource such as a file. ASP.NET supports various
methods for referencing external resources. The reference method you choose depends on whether you are working with a
client-side element or a Web server control.
Client Elements
Elements that are not Web server controls on a page—client elements—are passed through as-is to the browser. Therefore,
when referring to a resource from a client element, you construct paths according to standard rules for URLs in HTML. You can
use a fully qualified (which is also known as absolute) URL path or various types of relative paths. For example, if your page
contains an img element, you can set its src attribute using one of the following paths:
An absolute URL path. An absolute URL path is useful if you are referencing resources in another location, such as an
external Web site.

<img src="http://www.contoso.com/MyApplication/Images/SampleImage.jpg" />

A site-root relative path, which is resolved against the site root (not the application root). Site-root relative paths are
useful if you keep cross-application resources, such as images or client script files, in a folder that is located under the
Web site root.
This example path assumes that an Images folder is located under the Web site root.

<img src="/Images/SampleImage.jpg" />

If your Web site is http://www.contoso.com, the path would resolve to the following.

http://www.contoso.com/Images/SampleImage.jpg

A relative path that is resolved against the current page path.

<img src="Images/SampleImage.jpg" />

A relative path that is resolved as a peer of the current page path.

<img src="../Images/SampleImage.jpg" />

Note
By default, browsers resolve relative paths by using the current page URL as the base. However, you can include an HT
ML base element in a page to specify an alternate base path.

Server Controls
In ASP.NET server controls that reference resources, you can use absolute or relative paths as you do for client elements. If you
use relative paths, they are resolved relative to the path of the page, user control, or theme in which the control is contained.
For example, imagine that you have a user control in a Controls folder. The user control contains an Image Web server control
whose ImageUrl property is set to the following path: Images/SampleImage.jpg.
When the user control runs, the path will resolve to the following: /Controls/Images/SampleImage.jpg. This is true no matter
the location of the page that hosts the user control.
Note
In master pages, paths to resources are resolved based on the path of the content page. For more information, see
ASP.NET Master Pages Overview.

Absolute and relative path references in a server control have the following disadvantages:
Absolute paths are not portable between applications. If you move the application that the absolute path points to, the
links will break.
Relative paths in the style of client elements can be difficult to maintain if you move resources or pages to different
folders.
To overcome these disadvantages, ASP.NET includes the Web application root operator (~), which you can use when specifying
a path in server controls. ASP.NET resolves the ~ operator to the root of the current application. You can use the ~ operator in
conjunction with folders to specify a path that is based on the current root.
The following example shows the ~ operator used to specify a root-relative path for an image when using the Image server
control In this example, the image file is read from the Images folder that is located directly under the root of the Web
application, regardless of where in the Web site the page is located.

<asp:image runat="server" id="Image1"


ImageUrl="~/Images/SampleImage.jpg" />

You can use the ~ operator in any path-related property in server controls. The ~ operator is recognized only for server
controls and in server code. You cannot use the ~ operator for client elements.
Note
For mobile pages only, if your application relies on cookieless sessions or might receive requests from mobile devices that re
quire cookieless sessions, using a tilde ("~") in a path can result in inadvertently creating a new session and potentially losing
session data. To set a property on a mobile control with a path that includes a tilde (such as "~/path"), resolve the path using
the ResolveUrl method before assigning it to the property.

Determining Physical File Paths for the Current Web Site


In your application, you might need to determine the path of a file or other resource on the server. For example, if your
application reads or writes a text file programmatically, you must supply the file's complete physical path to the methods used
for reading and writing.
It is not a good practice to hard-code physical file paths (such as C:\Website\MyApplication) into your application because the
paths can change if you move or deploy your application. However, ASP.NET provides you with ways to get any physical file
path within your application programmatically. You can then use the base file path to create a full path to the resource you
need. The two most commonly used ASP.NET features for determining a file path are properties of the HttpRequest object that
return path information, and the MapPath method.
Note
Physical file paths should not be sent to the client because they could be used by a malicious user to gain information about
your application.

Determining the Path from Request Properties


The following table lists properties of the HttpRequest object that help you determine the paths of resources in your
application.
The examples listed in the table are based on the following assumptions:
A browser request was made using the following URL:
http://www.contoso.com/MyApplication/MyPages/Default.aspx.

The term "virtual path" refers to the portion of the request URL that follows the server identifier; in this case, the virtual
path is the following: /MyApplication/MyPages/Default.aspx.
The physical path for the root of the Web site is the following: C:\inetpub\wwwroot\MyApplication\.
The physical path contains a folder named MyPages.
Property Description
ApplicationPath Gets the root path of the current application, regardless of where in the application you request it. Fo
r the example, the property returns the following: /

CurrentExecutionFilePath Gets the virtual path of the current request. Differs from the FilePath property in that CurrentExecu
tionFilePath is correct if the request has been redirected in server code. For the example, the proper
ty returns the following: /MyApplication/MyPages/Default.aspx
If you get the property in code that is running as a result of a call to Transfer or Execute, the path refl
ects the location of the code.

FilePath Gets the virtual path of the current request. For the example, the property returns the following: /MyA
pplication/MyPages/Default.aspx

Unlike the CurrentExecutionFilePath property, FilePath does not reflect server-side transfers.

Path Gets the virtual path of the current request. For the example, the property returns the following: /MyA
pplication/MyPages/default.aspx

PhysicalApplicationPath Gets the physical file system path of the currently executing application's root directory. For the exa
mple, the property returns the following: C:\inetpub\wwwroot\

PhysicalPath Gets the physical file-system path that corresponds to the requested URL. For the example, the prope
rty returns the following: C:\inetpub\wwwroot\MyApplication\MyPages\default.aspx
Using the MapPath Method
The MapPath method returns the complete physical path for a virtual path that you pass to the method. For example, the
following code returns the file path for the root of your Web site:
VB
Dim rootPath As String = Server.MapPath("~")

C#
String rootPath = Server.MapPath("~");

Note
The path passed to the MapPath method must be an application-relative path rather than an absolute path.

See Also
Concepts
ASP.NET Web Site Layout
Page and Application Context in ASP.NET Web Applications
ASP.NET

Web Site File Types


Web site applications can contain a number of file types, some supported and managed by ASP.NET, and others supported and
managed by the IIS server.
Most of the ASP.NET file types can be automatically generated using the Add New Item menu item in Visual Web Developer.
For more information, see How to: Add ASP.NET Web Forms Page to a Web Project and
How to: Add ASP.NET Web Pages to a Web Site and How to: Add ASP.NET Web Pages to a Web Site and
How to: Add ASP.NET Web Pages to a Web Site (Visual Studio).
File types are mapped to applications using application mappings. For example, if you use double-click a .txt file in Windows
Explorer, Notepad will probably open, because in Windows, .txt file types are mapped by default to Notepad.exe. In Web
applications, file types are mapped to application extensions in IIS. For more information, see Setting Application Mappings in
IIS Help.
File Types Managed by ASP.NET
File types that are managed by ASP.NET are mapped to the Aspnet_isapi.dll in IIS.
File ty Location Description
pe
.asax Application root. Typically a Global.asax file that contains code that derives from the
HttpApplication class. This file represents the application and contains optional
methods that run at the start or end of the application lifetime.
For more information, see Global.asax Syntax.

.ascx Application root or a subdirectory. A Web user control file that defines a custom, reusable control.
For more information, see ASP.NET User Controls.

.ashx Application root or a subdirectory. A generic handler file that contains code that implements the IHttpHandler inter
face.
For more information, see Introduction to HTTP Handlers.

.asmx Application root or a subdirectory. An XML Web services file that contains classes and methods that are available t
o other Web applications by way of SOAP.
For more information, see XML Web Services Publishing and Deployment.

.aspx Application root or a subdirectory. An ASP.NET Web forms file (page) that can contain Web controls and presentati
on and business logic.
For more information, see ASP.NET Web Pages and
ASP.NET Web Server Controls.

.axd Application root. A handler file used to manage Web site administration requests, typically Trace.
axd.
For more information, see ASP.NET Tracing.

.brows App_Browsers subdirectory. A browser definition file used to identify the features of client browsers.
er
For more information, see
ASP.NET Web Server Controls and Browser Capabilities.
.cd Application root or a subdirectory. A class diagram file.
For more information, see Working with Class Diagrams and
Working with Class Diagrams and
Working with Class Diagrams (Class Designer) and
Working with Class Diagrams (Class Designer) and
Working with Class Diagrams (Class Designer).

.compi Bin subdirectory. A precompiled stub file that points to an assembly representing a compiled We
le b site file. Executable file types (.aspx, ascx, .master, theme files) are precompiled
and put in the Bin subdirectory.
For more information, see ASP.NET Web Site Precompilation Overview.

.config Application root or a subdirectory. A configuration file (typically Web.config) containing XML elements that represe
nt settings for ASP.NET features.
For more information, see ASP.NET Configuration Files.

.cs, .jsl, App_Code subdirectory, or in the case Class source-code file that is compiled at run time. The class can be an
.vb of a code-behind file for an ASP.NET p HTTP Module, an HTTP Handler, a code-behind file for an ASP.NET page, or a sta
age, in the same directory as the Web nd-alone class file containing application logic.
page.

.csproj, Visual Studio project directory. A project file for a Visual Studio client-application project.
.vbproj
, vjspr For more information, see Projects and Solutions and Projects and Solutions.
oj

.disco, App_WebReferences subdirectory. An XML Web services discovery file used to help locate available Web services.
.vsdisc
o For more information, see XML Web Services Publishing and Deployment.

.dsdg Application root or a subdirectory. A distributed service diagram (DSD) file that can be added to any Visual Studio
m, .ds solution that provides or consumes Web services to reverse-engineer an archite
protot ctural view of the Web service interactions.
ype
For more information, see XML Web Services Publishing and Deployment.

.dll Bin subdirectory. A compiled class library file (assembly). Note that instead of placing compiled a
ssemblies in the Bin subdirectory, you can put source code for classes in the Ap
p_Code subdirectory.
For more information, see Shared Code Folders in ASP.NET Web Sites.

.licx, .w Application root or a subdirectory. A license file. Licensing allows control authors to help protect intellectual proper
ebinfo ty by checking that a user is authorized to use the control.
For more information, see How to: License Components and Controls.

.maste Application root or subdirectory. A master page that defines the layout for other Web pages in the application.
r
For more information, see ASP.NET Master Pages.

.mdb, . App_Data subdirectory. An Access database file.


ldb
For more information, see Accessing Data with ASP.NET.
.mdf App_Data subdirectory. SQL database file for use with SQL Server Express.
For more information, see Accessing Data with ASP.NET.

.msgx, Application root or a subdirectory. An Indigo Messaging Framework (MFx) service file.
.svc

.rem Application root or a subdirectory. A remoting handler file.


For more information, see SOAP Message Modification Using SOAP Extensions.

.resour App_GlobalResources or App_LocalRe A resource file that contains resource strings that refer to images, localizable tex
ces, .re sources subdirectory. t, or other data.
sx
For more information, see Resources in Applications or
How to: Create Resource Files for ASP.NET Web Sites.

.sdm, . Application root or a subdirectory. A system definition model (SDM) file.


sdmD
ocume For more information, see Overview of the System Definition Model (SDM) and
nt Overview of the System Definition Model (SDM).

.sitem Application root. A site-map file that contains the structure of the Web site. ASP.NET comes with
ap a default site-map provider that uses site-map files to easily display a navigatio
nal control in a Web page.
For more information, see ASP.NET Site Navigation.

.skin App_Themes subdirectory. A skin file containing property settings to apply to Web controls for consistent f
ormatting.
For more information, see ASP.NET Themes and Skins.

.sln Visual Web Developer project director A solution file for a Visual Web Developer project.
y.
For more information, see Projects and Solutions and Projects and Solutions.

.soap Application root or a subdirectory. A SOAP extension file.


For more information, see SOAP Message Modification Using SOAP Extensions.

File Types Managed by IIS


File types that are managed by ASP.NET are usually mapped to the asp.dll handler in IIS.
File type Location Description
.asa Application root. Typically a Global.asa file that contains optional methods that run at the start or end of the
ASP session or application lifetime.
For more information, see Global.asa Syntax in the IIS SDK.

.asp Application root or a s An ASP Web page that contains @ directives and script code that uses the ASP built-in obje
ubdirectory. cts.
For more information, see IIS ASP Scripting Reference in the IIS SDK.

.cdx App_Data subdirector A compound index file structure file for Visual FoxPro.
y.
For more information, see Compound Index File Structure in MSDN.
.cer Application root or a s A certificate file used to authenticate a Web site.
ubdirectory.
For more information, see Certificates in the IIS Operations Guide.

.idc Application root or a s An Internet Database Connector file mapped to httpodbc.dll.


ubdirectory.
Note
IDC has been deprecated because it does not provide enough security for data connection
s. IIS 6.0 will be the last version to include IDC.

.shtm, .sht Application root or a s Mapped to ssinc.dll.


ml, .stm ubdirectory.
For more information, see IIS Server-Side Include Directives in the IIS SDK.

Static File Types


IIS serves static files only if their file-name extensions are registered in the MIME types list. This list is stored in the MimeMap
IIS metabase property for an application. If a file type is mapped to an application extension, it does not need to be included in
the MIME types list unless you want the file to be treated like a static file. Typically, ASP.NET source code file types should not
be in the MIME types list because that might allow browsers to view the source code.
The following table lists only a few of the registered file types.
File typ Location Description
e
.css Application root or subdirectory, or App_Themes subdi Style sheet files used to determine the formatting of HTML el
rectory. ements.

.htm, .ht Application root or subdirectory. Static Web files written in HTML code.
ml

See Also
Concepts
File Handling During ASP.NET Precompilation
ASP.NET

Shared Code Folders in ASP.NET Web Sites


If your Web application includes code that you want to share between pages, you can keep the code in one of two special
folders underneath the root of your Web application, the Bin folder and the App_Code folder. When you create these folders
and store particular types of files in them, ASP.NET handles the files in special ways.
Bin Folder
You can store compiled assemblies in the Bin folder, and other code anywhere in the Web application (such as code for pages)
automatically references it. A typical example is that you have the compiled code for a custom class. You can copy the compiled
assembly to the Bin folder of your Web application and the class is then available to all pages.
Assemblies in the Bin folder do not need to be registered. The presence of a .dll file in the Bin folder is sufficient for ASP.NET to
recognize it. If you change the .dll and write a new version of it to the Bin folder, ASP.NET detects the update and uses the new
version of the .dll for new page requests from then on.
Security with the Bin Folder
Putting compiled assemblies into the Bin folder can represent a security risk. If you wrote the code yourself and compiled it,
then you know what the code does. However, you should treat compiled code in the Bin folder as you would treat any
executable code. Be wary of compiled code until you have tested it and are confident that you understand what it does.
Note these security aspects of putting compiled code into the Bin folder:
Assemblies in Bin folder are scoped to the current application. Therefore, they cannot access resources or invoke code
outside the current Web application.
At run time, the access levels of an assembly are established by the trust level specified on the local computer. For more
information, see ASP.NET Trust Levels and Policy Files.
If you are working in a designer such as Visual Studio, code in the Bin folder runs in a different context than at run time.
For example, the code might be running with full trust.
App_Code Folder
You can store source code in the App_Code folder, and it will be automatically compiled at run time. The resulting assembly is
accessible to any other code in the Web application. The App_Code folder therefore works much like the Bin folder, except that
you can store source code in it instead of compiled code. The App_Code folder and its special status in an ASP.NET Web
application makes it possible to create custom classes and other source-code-only files and use them in your Web application
without having to compile them independently.
The App_Code folder can contain source code files written as traditional class files — that is, files with a .vb extension, .cs
extension, and so on. However, it can also include files that are not explicitly in a specific programming language. Examples
include .wsdl (Web service description language) files and XML schema (.xsd) files. ASP.NET can compile these files into
assemblies.
The App_Code folder can contain as many files and subfolders as you need. You can organize your source code in any way that
you find convenient, and ASP.NET will still compile all of the code into a single assembly that is accessible to other code
anywhere in the Web application.
Note
User controls are not allowed in the App_Code folder. This includes both single-file user controls and user controls that use t
he code-behind model. Putting a user control .in the App_Code directory causes the user control's code to be compiled out of
its required sequence and therefore is not allowed. Note that user controls do not need to be in the App_Code folder; they ar
e already available to pages anywhere in the application.

Inferring the Programming Language of the App_Code Folder


The App_Code folder is not explicitly marked as containing files written in any one programming language. Instead, the
ASP.NET infers which compiler to invoke for the App_Code folder based on the files it contains. If the App_Code folder contains
.vb files, ASP.NET uses the Visual Basic compiler; if it contains .cs files, ASP.NET uses the C# compiler, and so on.
If the App_Code folder contains only files where the programming language is ambiguous, such as a .wsdl file, ASP.NET uses
the default compiler for Web applications, as established in the compilation element of the Web application or machine
configuration file.
Multiple Programming Languages in the App_Code Folder
Because the source code in the App_Code folder is compiled into a single assembly, all the files in the App_Code folder must be
in the same programming language. For example, the App_Code folder cannot include source code in both Visual Basic and C#.
However, you can configure your Web application to treat subfolders of the App_Code folder as separate compilable units.
Each folder can then contain source code in a different programming language. The configuration is specified by creating a
codeSubDirectories element in the compilation element of the Web.config file and adding a reference to the subfolder. The
following example illustrates how you would configure subfolders named VBCode and CSCode to compile into separate
assemblies:

<compilation debug="false">
<codeSubDirectories>
<add directoryName="VBCode" />
<add directoryName="CSCode" />
</codeSubDirectories>
</compilation>

The references to the VBCode and CSCode subfolders do not need to include any information about what programming
language is contained in the subfolder. As with the App_Code folder itself, ASP.NET infers the compiler to use based on the files
in the subfolder.
Security with the App_Code Folder
Security issues with code in the App_Code folder are essentially the same as those with code in the Bin folder—the code is
compiled into an assembly at runtime. A mitigating factor is that you can read the source code for files in the App_Code folder.
However, if you do not fully understand the code, it can still represent a security risk. Therefore, treat source code in the
App_Code folder as you would treat compiled code from the same source.
See Also
Concepts
ASP.NET Web Site Layout
Visual Web Developer

Walkthrough: Using Shared Code in Web Sites in Visual Web


Developer
When you are creating Web sites, Visual Web Developer lets you easily create shared code in class files, which can then be
used by pages in your application, even without compiling the class files.
Note
If you have existing assemblies (.dll files), you can add them to the Bin directory of the Web site, and then the assemblies are
automatically referenced by the Web site.

In this walkthrough, you will create a simple class and then use it in an ASP.NET Web page.
Tasks illustrated in this walkthrough include the following:
Adding a class to a Web site.
Having Visual Web Developer reference the component automatically.
Prerequisites
In order to complete this walkthrough, you will need the following:
Visual Web Developer (Visual Studio).
The .NET Framework.
This walkthrough assumes that you have a general understanding of working in Visual Web Developer. For an introduction,
see Walkthrough: Creating a Basic Web Page in Visual Web Developer.
Creating the Web Site and Page
If you have already created a Web site in Visual Web Developer (for example, by completing either
Walkthrough: Creating a Basic Web Page in Visual Web Developer or
Walkthrough: Creating a Local IIS Web Site in Visual Web Developer), you can use that Web site and go to the next section.
Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site. (In Visual Web Developer Express Edition, on the File menu, click New, and then
click Web Site.)
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, enter the name of the folder where you want to keep the pages of the Web site.
For example:
If you are creating a file system Web site, type C:\SampleSite.
If you have IIS installed and you are creating an HTTP Web site, type http://localhost/SampleSite.
5. In the Language list, select the programming language that you prefer to work in.
6. Click OK.
Visual Web Developer creates the Web site and opens a new page named Default.aspx.
Creating a Shared Class
You can create reusable classes by keeping them in a folder named App_Code. Visual Web Developer monitors the App_Code
folder and when new class files are added, makes the components available to the rest of the code in your application. By
default, the classes in the App_Code folder are compiled into a single assembly at run time.
Note
You should put only classes (and other supported shared types) into the App_Code folder. Do not put pages, Web user contr
ols, or other files that contain non-code elements into the App_Code folder.

To create an App_Code folder


In Solution Explorer, right-click the name of the Web site, click Add Folder, and then click App_Code Folder.
You can now add the component to your site.
To create a shared class in the App_Code folder
1. In Solution Explorer, right-click App_Code, and then click Add New Item.
Note
Be sure to create the new item in the App_Code folder, not in the root folder of the Web site.

2. Under Visual Studio installed templates, click Class.


3. In the Name box, type SampleClass1.
4. In the Language list, select the language that is used by the Web page that will use the shared class.
5. Click Add.
Visual Web Developer opens the new class file in the editor.
6. Create a class that has a single property named testString by copying the following code into the class file:
VB
Public Class SampleClass1
private testStringValue As String
Public Property testString as String
Get
return testStringValue
End Get
Set (Value as String)
testStringValue = value
End Set
End Property
End Class

C#
using System;
public class SampleClass1
{
public SampleClass1()
{
}
private string testStringValue;
public string testString
{
get
{
return testStringValue;
}
set
{
testStringValue = value;
}
}
}

7. Save the file and then close it.


Note that the file is not stored as a compiled file.
Note
When you work with shared classes in the App_Code folder, you do not have to save the components in order for Visu
al Web Developer to maintain a reference to the components. If the Web page and component are in the same progra
mming language, Visual Web Developer maintains a reference to the component in memory. In this case, you are closi
ng the file because you are finished with it.

Using the Shared Class


The next step is to use the shared class in an ASP.NET Web page. You can use the Default.aspx page that was created when you
created the Web site.
To use the shared class
1. Open or switch to the Default.aspx page, and then switch to Design view.
Note
If you do not have a Default.aspx page, you can use another page. Alternatively, you can add a new page to the Web sit
e. To do this, in Solution Explorer, right-click the name of the Web site, click Add New Item, and then click Web Form.
In the Language list, enter the same programming language that you used for the component, and then click OK.

2. From the Standard folder in the Toolbox, drag a TextBox control, Label control, and Button control onto the page.
Note
For this walkthrough, the layout of the page is not important.

3. Double-click the Button control to create a Click handler for it.


The click handler code might look similar to the following:
VB
Protected Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Button1.Click

End Sub

C#
protected void Button1_Click(object sender, EventArgs e)
{

4. In the handler, type the following:


VB
Dim sc As New
C#
SampleClass1 sc = new

When you press SPACEBAR after typing New or new, Visual Web Developer displays a list of the available classes. The
class that you created in the preceding section, SampleClass1, is included in the list.
5. Finish the statement by typing SampleClass1 or by double-clicking it in the list, so that the statement reads as follows:
VB
Dim sc As New SampleClass1

C#
SampleClass1 sc = new SampleClass1();

6. Press ENTER, and then type the following:

sc.

As soon as you type the period, Visual Web Developer again displays a list of members to help you select a member
from the sample class.
7. Finish the statement and the handler in the following manner:
VB
sc.testString = TextBox1.Text
Label1.Text = sc.testString

C#
sc.testString = TextBox1.Text;
Label1.Text = sc.testString;

8. Save your files.


Testing the Page and Class
You can run the Web site to see that the shared class is working.
To test the page and component
1. Open the Default.aspx page.
2. Press CTRL+F5 to run the page.
3. When the page appears in the browser, type something in the text box, and then click the button.
Doing this sets a property in your simple class, which is then displayed in the Label control.
If you use Microsoft Windows Explorer to examine the directory where the Web site is located, you will see your page and the
App_Code folder. Note that there is no .dll or other executable code in the App_Code folder or anywhere under the root of the
Web site. Instead, Visual Web Developer has compiled the page and the shared class dynamically.
Next Steps
This walkthrough illustrates how to add shared classes to a Web site without compiling the components. You might want to
use shared classes in different ways. For example, you might want to:
Work with a compiled component.
If you have an assembly that you can use in the Web site, create a Bin folder, and then copy the .dll to Bin. You can then
reference the assembly in your page in the same way that you referenced the component that you created in this
walkthrough.
Create a component for data access.
For more information, see Walkthrough: Data Binding to a Custom Business Object.
Create a Web service.
For more information, see Walkthrough: Creating and Using an ASP.NET Web Service in Visual Web Developer.
See Also
Concepts
ASP.NET Web Site Layout
Shared Code Folders in ASP.NET Web Sites
Walkthrough: Developing Web Sites Using Multiple
Programming Languages
By default, the App_Code folder does not allow multiple programming languages. However, you can modify your Web
application structure and configuration settings to support multiple programming languages such as Visual Basic and C#. This
allows ASP.NET to create multiple assemblies, one for each language. For more information, see
Shared Code Folders in ASP.NET Web Sites. Developers commonly include multiple programming languages in Web
applications to support multiple development teams that operate independently and prefer different programming languages.
This walkthrough explains the how to add multiple programming languages to an ASP.NET application.
Creating the Web Site
If you have already created a Web site in Visual Web Developer by completing
Walkthrough: Creating a Basic Web Page in Visual Web Developer, you can use that Web site and go to the next section.
Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New, and then click Web Site. If you are using Visual Web Developer Express, on the File menu,
click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the first Location box, select File System; in the second, enter the name of the folder where you want to keep the
pages of your Web site.
For example, type the folder name C:\WebSites\BulkUpdate.
5. In the Language list, click the programming language you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Creating Language-specific Classes
In this part of the walkthrough, you will create simple class files in two languages, Visual Basic and C#.
To add language specific class files to the App_Code folder
1. If your Web site does not already have an App_Code folder, do the following:
a. In Solution Explorer, select the name of the Web site.
b. In the Website menu, click Add ASP.NET Folder, and then click App_Code.
2. In Solution Explorer, right-click the App_Code folder and then click New Folder.
3. Name the new folder "CSCode".
4. Select the CSCode folder.
5. In the Website menu, click Add New Item.
The Add New Item dialog box is displayed.
6. In the Add New Item dialog box, choose the Class template, name the class "CSExample", select C# as the language, and
click Add.
7. In Solution Explorer double-click the CSExample.cs file to open it.
8. Add the following code to the CSExample.cs file, overwriting the existing CSExample class already in the file:
C#
public class CSExample
{
private string teamString;
public cSharpExample()
{
TeamString = "C# Code";
}
public string TeamString
{
get {
return teamString;
}
set {
teamString = value;
}
}
}

9. Create a folder and class for Visual Basic code by repeating steps 2-7 using the following values:
New folder: VBCode
New class file: VBExample
Note
Be sure to set the language to Visual Basic when creating the new Visual Basic class file.

10. Add the following code to the VBExample.vb file, overwriting the existing VBExample class already in the file:
VB
Public Class VBExample
Private teamStr As String
Public Sub New()
TeamString = "Visual Basic Code"
End Sub
Public Property TeamString() As String
Get
Return teamStr
End Get
Set(ByVal Value As String)
teamStr = Value
End Set
End Property
End Class

Modifying the Web.config File


After creating separate subfolders for each programming language, you must change the Web site configuration so that
ASP.NET will compile the subfolders separately.
To modify the Web.config file to support multiple programming languages
1. In Solution Explorer, select the name of the Web site.
2. If your Web site does not already have a Web.config file, do the following:
a. In the Website menu, click Add New Item.
b. Choose Web Configuration File and then click Add.
3. Double-click the Web.config file to open it.
4. Modify the <compilation> section to include a <codeSubDirectories> node by copying the following section and
pasting it as a child node of the <compilation> section:

<codeSubDirectories>
<add directoryName="CSCode"/>
<add directoryName="VBCode"/>
</codeSubDirectories>

Note
Any definition of this section in Machine.config is overridden by the settings in the Web.config file. Also, the order of th
e configuration entries is the order that these entries will be created and linked.

Testing the Classes


You can now test that your Web site can use classes in both programming languages.
To see the results of using multiple programming languages
1. If your Web site does not already have a Default.aspx page, do the following:
a. In Solution Explorer, right-click the Web site name and then click Add New Item.
b. Select Web Form, name the page "Default.aspx" and then click Add.
2. In Solution Explorer double-click the Default.aspx page.
3. Add a Button control to the Default.aspx page.
4. Set the Button control's text to "Class Language" and the ID of the button to "classLanguage".
5. Add a Label control to the Default.aspx page, set its ID property to "classLabel", and clear its Text property.
6. In Design view, double-click the Button control to create an event handler for its Click event.
7. Add the following code to the classLanguage_Click handler:
C#
CSExample CSCode = new CSExample();
VBExample VBCode = new VBExample();
if (classLabel.Text == CSCode.TeamString.ToString())
{
classLabel.Text = VBCode.TeamString.ToString();
}
else
{
classLabel.Text = CSCode.TeamString.ToString();
}

VB
Dim CSCode As CSExample = New CSExample()
Dim VBCode As VBExample = New VBExample()
If classLabel.Text = CSCode.TeamString.ToString() Then
classLabel.Text = VBCode.TeamString.ToString()
Else
classLabel.Text = CSCode.TeamString.ToString()
End If

8. In Solution Explorer, right-click Default.aspx and select Set As Start Page.


9. Run the Web site and press the "Class Language" button to toggle between the two different language classes.
See Also
Reference
compilation Element (ASP.NET Settings Schema)
Concepts
Shared Code Folders in ASP.NET Web Sites
ASP.NET Application Life Cycle Overview
ASP.NET Web Site Precompilation Overview
Visual Web Developer

Source Code Control for Web Sites


If you have a source code control system installed on your computer that is compatible with Visual Web Developer, you can
use the source code control commands that are included with Visual Web Developer to check files in and out of source control,
merge files, view file history, and accomplish other source code control tasks with your Web site.
The topics in this section provide information on how to use the source control features in Visual Web Developer to help you
manage Web site files.
In This Section
Web Site Source Control Overview
Web Site Files under Source Control
Solutions and Web Site Source Control
Visual SourceSafe for Web Site Source Control
See Also
Other Resources
ASP.NET Web Sites (Visual Studio)
Visual Web Developer

Web Site Source Control Overview


If you have a source code control system installed on your computer that is compatible with Visual Web Developer, you can
use the source code control commands that are included with Visual Web Developer to check files in and out of source control,
merge files, view file history, and accomplish other source code control tasks with your Web site. For example, if you have
Microsoft Visual SourceSafe (VSS) installed, you can perform VSS tasks directly in Visual Web Developer. Other providers can
integrate with Visual Web Developer if they follow Visual Studio Industry Partner (VSIP) standards.
The exact behavior of source code control in Visual Web Developer depends on what source code control system you are
using. All VSIP-compliant source code control systems support the base commands that are required to perform check in,
check out, and other tasks. The Visual Web Developer commands and user interface for these functions are the same no matter
what source code control system you are using. However, for some functions, such as merging files, Visual Web Developer
simply hosts the source code control provider's own user interface, which can vary from one provider to another.
Enabling Source Control in Visual Web Developer
Source code control commands in Visual Web Developer are automatically enabled if Visual Web Developer is configured to
use a compatible source code control provider that is installed on your computer. You might need to enable source code
control functionality in Visual Web Developer by clicking Tools, Options, Source Control, Plug-In Selection and selecting
the correct source control plug-in.
Source Code Control and Visual Web Developer Web Application Types
Source code control works with two Web application types: file system Web applications and local IIS Web applications. In both
cases, you (and other developers) are generally working with copies of files in a location that you specify. When you check out
a file, a copy of the file is moved from the source code control repository to your specified location.
Note
Source code control exposes limited functionality when used with FrontPage Server Extension Web sites. Source code control
does not work with FTP-deployed Web sites at all.

For remote Web applications, you cannot use source control from within the Visual Web Developer environment. Remote Web
applications require FrontPage Server Extensions (FPSE) from Microsoft on the remote server, which provides limited support
for source code control functionality. Therefore, to use source control with remote Web sites, your Web site project must be
configured to use the source control system on the server where the files are located.
FTP Web applications do not support source control. In an FTP Web application, all files are stored on a central server and are
read and written using the FTP protocol, which does not support check-in and checkout functionality.
Checking Files Out and In
When you want to edit a file, you check the file out of the source control system. Checking out a file puts a read-write copy of it
on your computer. When you are done editing, you check the file back into the source control system. To be able to check files
out or in, you must be able to log into the source control system. For information about login credentials, contact your source
code control administrator.
Visual Web Developer allows you to check files out explicitly or implicitly. For explicit checkout, you select the files to work with
and issue an explicit command to check them out using the source control mechanism. For implicit checkout, you simply open
a file in Visual Web Developer.
If the file has not been checked out, it is in read-only mode. When you make a change to the file, Visual Web Developer checks
out the file so that you can save your changes. By default, Visual Web Developer does not prompt you before checking out the
file. To enable prompts, click Tools, Options, Source Control, Environment, and then under Checked-in item behavior,
select Prompt for check out in the list boxes beside On Save and On Edit. The default is Check out automatically.
You can configure Visual Web Developer not to perform implicit checkouts. Click Tools, Options, Source Control,
Environment, and then under Checked-in item behavior, select Do nothing in the list boxes beside On Save and On Edit.
In this case, files are opened in read-only mode. If you want to be able to save changes, you must first explicitly check out the
file.
Merging Files During Check-In
Most source code control systems allow multiple developers to check the same file out at the same time, which means that two
or more developers might edit a file at the same time. Therefore, when you check in a file, the source code control system
determines whether the file has been changed by someone else since you checked it out. If the file has not changed, it is
checked in as usual. However, if the file has changed since you checked out your version, the source code control system
attempts to merge your changes with the other changes it finds in the file.
The procedure used to perform the merge depends on what your source code control provider is. A typical scenario is as
follows:
1. You check in a file.
2. The source code control system detects that the file has been changed by someone else since you last checked it out and
merges your changes with the file in the repository.
3. The source code control system displays a dialog box highlighting the two sets of changes.
4. You accept or reject the changes. If you accept them, the file is checked in with the merged changes.
Adding New Files
When you initially add a new file to the Web application, the file exists only locally on your computer. When source code
control is enabled in Visual Web Developer, new files are marked with an icon in Solution Explorer indicating that the file is
new. To add the file to the source code control repository, you can check it in individually. Alternatively, you can check in the
file as part of the entire Web application, which will check in all checked-out files, including your new file.
Moving, Renaming, and Deleting Files
While working with a Web site that is under source control, you might want to move, rename, or delete a file. It is
recommended that you move, rename, or delete files using the source control mechanism while the files are checked in. The
next time another developer checks out the changed file, Visual Web Developer applies the changes on their computer.
Adding a New Developer to a Project
If you are a developer just joining a team and want to work with a Web site that is already under source control, you can
retrieve a copy of the Web site from the repository. In source control terminology, this is sometimes referred to as
synchronizing or enlisting. Synchronizing is also useful when setting up new computers or creating a backup of the files under
source control.
Rather than creating a new Web application, you open the existing project from source control. After providing appropriate
credentials if required, you specify a location on your local computer. Visual Web Developer then puts read-only copies of the
application's files in the specified location. From that point, you can work with the files, checking them out, editing them, and
checking them back in.
Opening a Web Site from Source Control
If a site has already been put under source control, you open it from source control rather than opening it directly on your local
computer.
If you are enlisting in an individual Web site for the first time, in Visual Web Developer, click File, Open Web Site, and click the
Source Control tab to enter your credentials and select a local location for the site. After you have enlisted in a Web site,
Visual Web Developer works with the source control mechanism when you edit files. Enlisting stores the binding information
in the local Visual Web Developer cache, indexed by the Web site name.
See Also
Other Resources
Source Code Control for Web Sites
Visual Studio Extensibility Center
Visual Web Developer

Web Site Files under Source Control


Some of the files that you work with in a Web site require special consideration when working with source code control.
Web.config File
Because the Web.config file is a central store for application-wide configuration settings, it is more likely than individual pages
to be checked out to multiple developers at the same time. As long as different developers are not changing the same settings
at the same time, the merge functionality of the source control system can incorporate the changes during the check-in
process.
You can open the Web.config file manually to edit it. In that case, you can explicitly check the file out first or rely on implicit
checkout when you make edits to the file, as you would with an ASP.NET page. In addition, a number of utilities in Visual Web
Developer make changes to the Web.config file. For example, if you use the Visual Web Developer Add Reference dialog box
to create a reference to a client project, a Web service, or an assembly in the Global Assembly Cache (GAC), the new reference
is stored in the Web.config file. In most cases, Visual Web Developer will automatically check out the Web.config file as needed.
For example, if you add a new reference to your Web application, and if you do not have the Web.config file checked out, the
Add Reference command will check Web.config out and add the reference.
However, not every process that affects the Web.config file automatically checks it out. The following is a list of utilities that
require you to check out the Web.config file before editing your application's configuration:
The Web Site Administration Tool (ASP.NET Configuration command on the Web site menu) does not check out the
Web.config file automatically. If you try to save changes in the Web Site Administration Tool without first checking out
the Web.config file, the tool displays an error indicating that the Web.config file is read-only. The solution is to explicitly
check out the Web.config file before using the Web Site Administration Tool.
The ASP.NET MMC snap-in does not check out the Web.config file automatically, and it will display an error if you try to
save configuration changes before checking out the file.
Encrypted Sections of the Web.config File
If you have configured the Web.config file with encrypted sections, merging is no longer possible. Unencrypt configuration
settings before merging.
For details about encrypting sections of the Web.config file, see
Encrypting Configuration Information Using Protected Configuration.
Global.asax File
Like Web.config, the Global.asax file stores information that applies to the entire Web site and is located in the root of the Web
site. Specifically, the Global.asax file contains event-handling code for events that are raised for the application or session. In
general, multiple developers can safely check out the Global.asax file and rely on the source control provider's merge facility to
resolve conflicts at check-in.
Resource Files
Resource (.resx) files store information in XML format. Resource files can be either local to a page or global to the Web
application. A local page resource file is stored in the App_LocalResources file using a name that is based on the name of the
page with which it is associated. For example, the page Default.aspx will have a corresponding local resource file named
Default.aspx.resx. Global resource files are stored in the App_GlobalResources file. You can assign any name to these files as
long as they contain the .resx file name extension.
Local resource files are not automatically checked out when you check out a page. Therefore, you must check out the
corresponding resource file, either explicitly or implicitly, before editing it. Working with global resource files is similar, except
that the likelihood of contention between developers can be higher. Before checking out a page that relies on a global resource
file, check source control to see if someone else has the global resource file checked out.
In both cases, because the resource file is in XML format, conflicts during check in can be resolved by merging.
Application Services Database
If you use ASP.NET membership, role management, or profiles, application information for these services is stored in a
database. By default, the database is local to the Web application, and it is stored as a database file in the App_Data folder of
your Web application. The services also require entries in the Web.config file. For more information, see
Creating and Configuring the Application Services Database for SQL Server.
Storing application data in a local database can cause problems if your Web site is under source control for these reasons:
Each developer must check out the database file when locally debugging the application. You cannot debug your
application with a read-only version of the database file; a read-only database file results in run-time errors.
The database is stored in the source control repository as a binary file. Consequently, the source control system cannot
merge changes if multiple developers have the database file checked out. Instead, each developer's check-in overwrites
the previous version.
When working with a Web application that is under source control, it is best to use a shared database file that is not under
source control to store application services data. For example, you can use a central server running Microsoft SQL Server for
application data. All developers are then working with the current, live data. You can then also use the database's backup
facilities to manage the application data. For details about selecting a database for application data, see
Creating and Configuring the Application Services Database for SQL Server.
Assembly Files
You can add assemblies (.dll files) to your Web site's Bin folder and then reference the assemblies in your code. You do not
need to check out a .dll file unless you want to overwrite it with a newer version.
Source control systems cannot merge changes if two or more developers change the binary .dll file at the same time.
Therefore, as a best practice you should not allow multiple checkouts on a .dll file if you intend to update the file and check it
back in. You can set an option during checkout to prevent others from checking the file out while you have it.
References to Client or Class Library Projects
While working with your Web application, you can add a client or class library project to the solution and create compilable
components in the library project. You can then create a project-to-project reference in your Web application to reference the
compiled output of the library project. For example, when creating a class library project, you might create an assembly with
utility classes or custom controls within the project and then reference those assemblies in your Web application.
When you create a reference to another project, Visual Web Developer copies compiled output from that project if it exists. For
that reason, you need to build a project before you can create a reference to it from another project. Compiled output from
client projects is not under source control; therefore, developers do not need to worry about deleting old versions of binaries,
or building and overwriting source controlled versions.
See Also
Concepts
Web Site Source Control Overview
Other Resources
Creating and Configuring the Application Services Database for SQL Server
Visual Web Developer

Solutions and Web Site Source Control


If you are working in a solution that contains multiple Web sites, you can put the entire solution under source control as a unit.
Working with a multiple Web site project solution is much the same as working with a single Web site project. The same
functions are available, including the ability to check in or out an entire solution at once.
Repository Structure When Adding a Solution with Multiple Web Sites to Source Control
If you are adding a solution with more than one Web site to source control, the Microsoft Visual Web Developer Web
development tool creates a different structure in the source control repository than it does for a single Web site project. For
solutions that contain Web sites in a path that is relative to the solution file, Visual Web Developer creates a nested project
structure in your source control repository. For example, if you have a solution file in C:\WebSites\SampleSolution.sln, and you
have a Web site in C:\WebSites\SampleWebs\Web1, these paths are considered relative. Visual Web Developer attempts to
maintain the relative structure. Any additional Web sites that are in the solution are created as separate child projects using the
name that you assigned to the Web site.
Visual Web Developer initially creates a project with the extension .root. This project acts as the parent project for the
individual Web site project. Within the parent project, Visual Web Developer creates a structure that looks similar to the
following:
<SolutionName> .root
<SolutionName>\<relative path to the solution file>
Stores the .sln file with the solution and project configuration settings.
<SolutionName>\<relative path to file system Web site>
Stores the files for a Web site in the solution. In Visual Web Developer, the first Web site that you create in a
solution has the same name as the solution. Thus, Visual Web Developer assigns the suffix _1 to the source
control project for the Web site, which distinguishes it from the source control project that stores solution
settings.
<name of non-relative file system Web site>
Stores files for an additional Web site in the solution.
<name of client project>
Stores client project files.
Enlisting
When you use Visual Web Developer to retrieve a copy of the solution from source control for the first time, Visual Web
Developer creates the correct structure on your computer.
If you enlist in a solution that contains a Microsoft Internet Information Services (IIS) Web site that does not already exist on
the local computer, Visual Web Developer creates the Web site beside the solution structure and points your virtual directory
to that location.
If you enlist in a solution that contains an IIS Web site, and the virtual directory for the Web site already exists on your local
computer, Visual Web Developer displays a dialog box asking if you want to add the files from source control to the existing
Web site instead of creating a new folder. If you click Yes, Visual Web Developer uses the existing location. If you click No,
Visual Web Developer creates a new folder with an underscore and a 1 (_1) appended to the name.
Checking Out Files
When you check out files in Visual Web Developer, your local version of the file is checked out in source control.
See Also
Other Resources
Source Code Control for Web Sites
Visual Web Developer

Visual SourceSafe for Web Site Source Control


If you are using Microsoft Visual SourceSafe (VSS) as your source control system, Visual Web Developer exposes some
additional functionality that is not available for all source control providers. The following table lists additional commands that
are available in Visual Web Developer if VSS is your source control provider.
Functionality Description
Opening a Web sit You can open the Web site from source code control directly from the Open Web Site dialog box, much as
e you would open any local Web site. VSS adds a tab named Source Control to the Open Web Site dialog b
ox. The tab displays a button that enables you to select a VSS project to open.

Starting Visual So You can start VSS directly from Visual Web Developer. VSS adds a command named Launch Microsoft Vi
urceSafe (Source sual SourceSafe to the Source Control menu, making it easier to manage your source control projects.
Control menu)

History (Source C The History command provides a convenient way for you to examine, within Visual Web Developer, the ch
ontrol menu) eck-in history of any file under source control.

Compare (Source The Compare command reads a file on your computer and a file in the source control repository and repor
Control menu) ts the differences between the files in a two-pane window similar to WinDiff.exe.

See Also
Other Resources
Source Code Control for Web Sites
Visual Web Developer

Referencing Additional Components in Web Sites


You can use components that are not part of your Web application by referencing them. Referencing a component adds
information to your Web application that helps ASP.NET find the referenced component at compilation time.
In This Section
How to: Add a Reference to a .NET or COM Component in a Web Site
How to: Add a Reference to a Visual Studio Project in a Web Site
Related Sections
How to: Add and Remove Web References
Visual Web Developer

How to: Add a Reference to a .NET or COM Component in a


Web Site
You can reference .NET components that are in the global assembly cache (GAC) or COM components registered on your
computer. You can also reference components that are located on your hard drive but not in the GAC. Referencing a
component makes it available to use in your code.
Note
If you deploy an application that contains a reference to a custom component that is registered in the GAC, the component w
ill not be deployed with the application. In previous versions of Visual Studio.NET, you could set the Copy Local property for
a reference, which ensured that the assembly would be deployed. In ASP.NET 2.0, to deploy any assembly with your applicati
on, you must manually add the assembly to the application's Bin folder. Doing so reduces the risk of publishing custom code
that you are not familiar with. For more information, see Working with Assemblies and the Global Assembly Cache and
Deployment and the Global Assembly Cache.

To add references to registered COM components


1. On the Website menu, choose Add Reference and then click the COM tab.
2. Select the component you want to use from the list of COM components and then click OK.
Visual Basic automatically creates an interop assembly, which is a specialized .NET assembly that contains metadata to
define COM types and that enables .NET compilers to resolve calls to COM objects.
If you don't see the component you want, click the Browse tab and look for the component file on your hard drive.
To add references to .NET components that are already registered with the .NET Framework
1. On the Website menu, choose Add Reference and then click the .NET tab in the dialog box.
2. Select the component you want to use from the list of .NET components and then click OK.
If you don't see the component you want, click the Browse tab and look for the assembly file on your hard drive.
Referencing Components
After you add a reference to a component in your project, you can use it in your code.
To use a referenced component
Add an Imports (Visual Basic) statement or using (C#) statement to the top of the class or module that identifies the
namespace to reference. For more information, see Imports Statement or using Statement (C# Reference).
You can then use member names without fully qualifying the name (prefxing the member name with the namespace
name). For example, if you add a reference to the System.Web namespace and you include an Imports (Visual Basic)
statement or using (C#) statement for the System.Web.UI.WebControls namespace, you can reference the
SiteMapNodeItem class without using its fully qualified name, as in the following example:
[Visual Basic]

Imports System.Web.UI.WebControls
Public Class SampleClass
Dim smni As SiteMapNodeItem = _
New SiteMapNodeItem(0, SiteMapNodeItemType.Parent)
End Class

C#
using System.Web.UI.WebControls;
public class SampleClass
{
SiteMapNodeItem smni = new
SiteMapNodeItem(0, SiteMapNodeItemType.Parent);
}

If you do not use a Visual Basic .NET Import statement or the C# using statement for the System.Web.UI.WebControls
namespace, you still reference the SiteMapNodeItem class, but you must use its fully qualified name, as in the
following example.
[Visual Basic]

Public Class SampleClass


Dim smni As System.Web.UI.WebControls.SiteMapNodeItem = _
New System.Web.UI.WebControls.SiteMapNodeItem(0, _
System.Web.UI.WebControls.SiteMapNodeItemType.Parent)
End Class

C#
public class SampleClass
{
System.Web.UI.WebControls.SiteMapNodeItem smni =
new System.Web.UI.WebControls.SiteMapNodeItem(0,
System.Web.UI.WebControls.SiteMapNodeItemType.Parent);
}

See Also
Tasks
How to: Add or Remove References in Visual Studio
How to: Reference COM Objects from Visual Basic
Other Resources
COM Interop
Visual Web Developer

How to: Add a Reference to a Visual Studio Project in a Web


Site
A project contains the files that make up your Web site, including pages, configuration files, code files, and binary (compiled
code) files. In Visual Studio, you can create multiple projects per solution to address different application requirements.
Solution definitions include the dependency relationships among projects. They also include information about how to deploy
the projects that make up your solution. Between them, the projects in your solution make up an application.
Keeping projects modularized helps you organize your code better. For example, you might create a component in one project
that you want to include in a separate Web site project.
To add a reference to your component project in your Web site solution, you first add the project, and then add a reference to
the new project's classes. Only projects that build a DLL can be referenced. Project references are updated automatically when
the project builds, whereas assembly references need to be statically updated by the user.
Note
In Visual Web Developer Express Edition, you can have multiple Web site projects in the same solution, but you cannot add cl
ient projects to a solution. For an alternative, see
Adding References to a Project in a Web Site in Visual Web Developer Express Edition later in this topic.

Adding Projects to a Solution in Visual Studio


You can add either a new project or an existing project to a solution.
To add a new project to a solution
1. In Solution Explorer, select the solution or the solution folder that you want to add a project to.
2. On the File menu, choose Add, and then choose New Project.
3. Select a project type and template and then click OK.
You can add an existing project to a solution and then edit that project to meet the requirements of the current solution.
However, this changes the project settings of the project in the original location.
To add an existing project to a solution
1. In Solution Explorer, select the solution or the solution folder that you want to add a project to.
2. On the File menu, choose Add and then choose Existing Project.
3. Select the project you want to add to the solution and then click Open.
Adding a Project Reference to a Web Site in Visual Studio
After you have added a project to your solution, you can reference the project from your Web site project.
To reference another project in a Web site
1. In Solution Explorer, select the Web site project that you want to add the project reference to.
2. On the Website menu, choose Add Reference. Alternatively, you can right-click your Web site project and then click
Add Reference.
The Add Reference dialog box is displayed.
3. Click the Projects tab.
4. From the list of available projects, select the one to which you want a reference and then click OK.
The following are added to your Web site's Bin folder:
A copy of the assembly created from the added project.
Copies of dependent assemblies, XML document files, license files, resource files, and so on.
The program database (.pdb) file, which holds debugging and project state information for the debug version of the
added assembly. This file is copied if present in the original location, regardless of the build settings.
Adding References to a Project in a Web Site in Visual Web Developer Express Edition
In Visual Web Developer Express Edition, you can have many Web site projects in the same solution, but you can not add client
projects to a solution. Therefore, you cannot populate the Projects tab of the Add Reference dialog box. However, you can
add the assembly DLL or the source code file to your Web site project manually.
To add an assembly DLL to your Web site project
1. In Solution Explorer, select your Web site.
2. On the Website menu, choose Add Reference. Alternatively, you can right-click the name of your Web site and then
select Add Reference.
The Add Reference dialog box is displayed.
3. Select the Browse tab.
4. Navigate to the folder containing the assembly you want to reference, select the assembly, and then click OK.
Adding a reference in this way ensures that all file dependencies (debug files, XML document files, and so on) are copied.

To add a source code file to your Web site project


1. In Solution Explorer, select your Web site's App_Code folder.
2. On the Website menu, click Add Existing Item.
The Add Existing Item dialog box is displayed.
3. In the Files of type dropdown list, select Class Files.
4. Browse to the project you want to add, select the source code file, and then click Add.
A static copy of the selected file is added to your project. These copies are not automatically updated. You can now use
the classes in the source code file in your Web site files. Files in the App_Code folder are compiled at run-time.

See Also
Tasks
How to: Create Multi-Project Solutions
Reference
Add Reference Dialog Box
Add New Project Dialog Box
ASP.NET

ASP.NET Life Cycle


The topics in this section provide background information on how ASP.NET processes pages to produce dynamic output.
Included is information on how the application itself and individual pages are instantiated and processed, and information
about how ASP.NET compiles pages dynamically.
In This Section
ASP.NET Application Life Cycle Overview
ASP.NET Page Life Cycle Overview
ASP.NET Compilation Overview
How to: Create ASP.NET Application-Level Event Handlers
Related Sections
ASP.NET Web Applications
Provides information on creating and programming ASP.NET Web applications.
ASP.NET

ASP.NET Application Life Cycle Overview


This topic outlines the application life cycle, listing important life-cycle events and describing how code that you write can fit
into the application life cycle. Within ASP.NET, several processing steps must occur for an ASP.NET application to be initialized
and process requests. Additionally, ASP.NET is only one piece of the Web server architecture that services requests made by
browsers. It is important for you to understand the application life cycle so that you can write code at the appropriate life cycle
stage for the effect you intend.
Application Life Cycle in General
The following table describes the stages of the ASP.NET application life cycle.
Stage Description
User requests a The life cycle of an ASP.NET application starts with a request sent by a browser to the Web server (for ASP.NET
n application re applications, typically IIS). ASP.NET is an ISAPI extension under the Web server. When a Web server receives a
source from th request, it examines the file name extension of the requested file, determines which ISAPI extension should ha
e Web server. ndle the request, and then passes the request to the appropriate ISAPI extension. ASP.NET handles file name e
xtensions that have been mapped to it, such as .aspx, .ascx, .ashx, and .asmx.
Note
If a file name extension has not been mapped to ASP.NET, then ASP.NET will not receive the request. This is i
mportant to understand for applications that use ASP.NET authentication. For example, because .htm files are
typically not mapped to ASP.NET, ASP.NET will not perform authentication or authorization checks on reques
ts for .htm files. Therefore, even if a file contains only static content, if you want ASP.NET to check authenticati
on, create the file using a file name extension mapped to ASP.NET, such as .aspx.
Note
If you create a custom handler to service a particular file name extension, you must map the extension to ASP
.NET in IIS and also register the handler in your application's Web.config file. For more information, see
Introduction to HTTP Handlers.

ASP.NET receiv When ASP.NET receives the first request for any resource in an application, a class named ApplicationManager
es the first requ creates an application domain. Application domains provide isolation between applications for global variable
est for the appli s and allow each application to be unloaded separately. Within an application domain, an instance of the class
cation. named HostingEnvironment is created, which provides access to information about the application such as the
name of the folder where the application is stored.
The following diagram illustrates this relationship:

ASP.NET also compiles the top-level items in the application if required, including application code in the App_
Code folder. For more information, see "Compilation Life Cycle" later in this topic.
ASP.NET core o After the application domain has been created and the HostingEnvironment object instantiated, ASP.NET cre
bjects are creat ates and initializes core objects such as HttpContext, HttpRequest, and HttpResponse. The HttpContext class c
ed for each req ontains objects that are specific to the current application request, such as the HttpRequest and HttpRespon
uest. se objects. The HttpRequest object contains information about the current request, including cookies and bro
wser information. The HttpResponse object contains the response that is sent to the client, including all rende
red output and cookies.

An After all core application objects have been initialized, the application is started by creating an instance of the
HttpApplication HttpApplication class. If the application has a Global.asax file, ASP.NET instead creates an instance of the Glo
object is assign bal.asax class that is derived from the HttpApplication class and uses the derived class to represent the appli
ed to the reque cation.
st
Note
The first time an ASP.NET page or process is requested in an application, a new instance of HttpApplication
is created. However, to maximize performance, HttpApplication instances might be reused for multiple req
uests.

When an instance of HttpApplication is created, any configured modules are also created. For instance, if the
application is configured to do so, ASP.NET creates a SessionStateModule module. After all configured module
s are created, the HttpApplication class's Init method is called.
The following diagram illustrates this relationship:
The request is The following events are executed by the HttpApplication class while the request is processed. The events ar
processed by t e of particular interest to developers who want to extend the HttpApplication class.
he HttpApplic
ation pipeline. 1. Validate the request, which examines the information sent by the browser and determines whether it co
ntains potentially malicious markup. For more information, see ValidateRequest and
Script Exploits Overview.
2. Perform URL mapping, if any URLs have been configured in the UrlMappingsSection section of the Web.
config file.
3. Raise the BeginRequest event.
4. Raise the AuthenticateRequest event.
5. Raise the PostAuthenticateRequest event.
6. Raise the AuthorizeRequest event.
7. Raise the PostAuthorizeRequest event.
8. Raise the ResolveRequestCache event.
9. Raise the PostResolveRequestCache event.
10. Based on the file name extension of the requested resource (mapped in the application's configuration fi
le), select a class that implements IHttpHandler to process the request. If the request is for an object (pag
e) derived from the Page class and the page needs to be compiled, ASP.NET compiles the page before cr
eating an instance of it.
11. Raise the PostMapRequestHandler event.
12. Raise the AcquireRequestState event.
13. Raise the PostAcquireRequestState event.
14. Raise the PreRequestHandlerExecute event.
15. Call the ProcessRequest method (or the asynchronous version BeginProcessRequest) of the appropriate
IHttpHandler class for the request. For example, if the request is for a page, the current page instance h
andles the request.
16. Raise the PostRequestHandlerExecute event.
17. Raise the ReleaseRequestState event.
18. Raise the PostReleaseRequestState event.
19. Perform response filtering if the Filter property is defined.
20. Raise the UpdateRequestCache event.
21. Raise the PostUpdateRequestCache event.
22. Raise the EndRequest event.

Life Cycle Events and the Global.asax file


During the application life cycle, the application raises events that you can handle and calls particular methods that you can
override. To handle application events or methods, you can create a file named Global.asax in the root directory of your
application.
If you create a Global.asax file, ASP.NET compiles it into a class derived from the HttpApplication class, and then uses the
derived class to represent the application.
An instance of HttpApplication processes only one request at a time. This simplifies application event handling because you
do not need to lock non-static members in the application class when you access them. This also allows you to store request-
specific data in non-static members of the application class. For example, you can define a property in the Global.asax file and
assign it a request-specific value.
ASP.NET automatically binds application events to handlers in the Global.asax file using the naming convention
Application_event, such as Application_BeginRequest. This is similar to the way that ASP.NET page methods are
automatically bound to events, such as the page's Page_Load event. For details, see ASP.NET Page Life Cycle Overview.
The Application_Start and Application_End methods are special methods that do not represent HttpApplication events.
ASP.NET calls them once for the lifetime of the application domain, not for each HttpApplication instance.
The following table lists some of the events and methods that are used during the application life cycle. There are many more
events than those listed, but they are not commonly used.
Event Description
or met
hod
Applic Called when the first resource (such as a page) in an ASP.NET application is requested. The Application_Start metho
ation_ d is called only one time during the life cycle of an application. You can use this method to perform startup tasks such
Start as loading data into the cache and initializing static values.
You should set only static data during application start. Do not set any instance data because it will be available only t
o the first instance of the HttpApplication class that is created.

Applic Raised at the appropriate time in the application life cycle, as listed in the application life cycle table earlier in this topic
ation_e .
vent
Application_Error can be raised at any phase in the application life cycle.
Application_EndRequest is the only event that is guaranteed to be raised in every request, because a request can be
short-circuited. For example, if two modules handle the Application_BeginRequest event and the first one throws a
n exception, the Application_BeginRequest event will not be called for the second module. However, the Applicati
on_EndRequest method is always called to allow the application to clean up resources.

HttpAp Called once for every instance of the HttpApplication class after all modules have been created.
plicatio
n.Init

Dispose Called before the application instance is destroyed. You can use this method to manually release any unmanaged reso
urces. For more information, see Cleaning Up Unmanaged Resources.

Applic Called once per lifetime of the application before the application is unloaded.
ation_
End

Compilation Life Cycle


When the first request is made to an application, ASP.NET compiles application items in a specific order. The first items to be
compiled are referred to as the top-level items. After the first request, the top-level items are recompiled only if a dependency
changes. The following table describes the order in which ASP.NET top-level items are compiled.
Item Description
App_GlobalResources The application's global resources are compiled and a resource assembly is built. Any assemblies in
the application's Bin folder are linked to the resource assembly.

App_WebResources Proxy types for Web services are created and compiled. The resulting Web references assembly is li
nked to the resource assembly if it exists.

Profile properties defined If profile properties are defined in the application's Web.config file, an assembly is generated that c
in the Web.config file ontains a profile object.

App_Code Source code files are built and one or more assemblies are created. All code assemblies and the pro
file assembly are linked to the resources and Web references assemblies if any.
Global.asax The application object is compiled and linked to all of the previously generated assemblies.

Once the application's top level items have been compiled, ASP.NET compiles folders, pages, and other items as needed. The
following table describes the order in which ASP.NET folders and items are compiled.
Item Description
App_LocalResources If the folder containing the requested item contains an App_LocalResources f
older, the contents of the local resources folder are compiled and linked to t
he global resources assembly.

Individual Web pages (.aspx files), user controls (. Compiled as needed and linked to the local resources assembly and the top-
ascx files), HTTP handlers (.ashx files), and HTTP level assemblies.
modules (.asmx files)

Themes, master pages, other source files Skin files for individual themes, master pages, and other source code files ref
erenced by pages are compiled when the referencing page is compiled.

Compiled assemblies are cached on the server and reused on subsequent requests and are preserved across application
restarts as long as the source code is unchanged.
Because the application is compiled on the first request, the initial request to an application can take significantly longer than
subsequent requests. You can precompile your application to reduce the time required for the first request. For more
information, see How to: Precompile ASP.NET Web Sites.
Application Restarts
Modifying the source code of your Web application will cause ASP.NET to recompile source files into assemblies. When you
modify the top-level items in your application, all other assemblies in the application that reference the top-level assemblies
are recompiled as well.
In addition, modifying, adding, or deleting certain types of files within the application's known folders will cause the application
to restart. The following actions will cause an application restart:
Adding, modifying, or deleting assemblies from the application's Bin folder.
Adding, modifying, or deleting localization resources from the App_GlobalResources or App_LocalResources folders.
Adding, modifying, or deleting the application's Global.asax file.
Adding, modifying, or deleting source code files in the App_Code directory.
Adding, modifying, or deleting Profile configuration.
Adding, modifying, or deleting Web service references in the App_WebReferences directory.
Adding, modifying, or deleting the application's Web.config file.
When an application restart is required, ASP.NET will serve all pending requests from the existing application domain and the
old assemblies before restarting the application domain and loading the new assemblies.
HTTP Modules
The ASP.NET application life cycle is extensible through IHttpModule classes. ASP.NET includes several classes that implement
IHttpModule, such as the SessionStateModule class. You can also create your own classes that implement IHttpModule.
If you add modules to your application, the modules themselves can raise events. The application can subscribe to in these
events in the Global.asax file by using the convention modulename_eventname. For example, to handle the Authenticate event
raised by a FormsAuthenticationModule object, you can create a handler named FormsAuthentication_Authenticate.
The SessionStateModule class is enabled by default in ASP.NET. All session events are automatically wired up as
Session_event, such as Session_Start. The Start event is raised each time a new session is created. For more information, see
Session State Overview.
See Also
Concepts
ASP.NET Page Life Cycle Overview
ASP.NET Overview
ASP.NET Compilation Overview
Other Resources
ASP.NET and IIS Configuration
ASP.NET

ASP.NET Compilation Overview


In order for application code to service requests by users, ASP.NET must first compile the code into one or more assemblies.
Assemblies are files that have the file name extension .dll. You can write ASP.NET code in many different languages, such as
Visual Basic, C#, J#, and others. When the code is compiled, it is translated into a language-independent and CPU-independent
representation called Microsoft Intermediate Language (MSIL). At run time, MSIL runs in the context of the .NET Framework,
which translates MSIL into CPU-specific instructions for the processor on the computer running the application.
There are many benefits to compiling application code including:
Performance Compiled code is much faster than scripting languages such as ECMAScript or VBScript because it is a
closer representation to machine code and does not require additional parsing.
Security Compiled code is more difficult to reverse engineer than non-compiled source code because it lacks the
readability and abstraction of a high-level language. Additionally, there are obfuscation tools that make compiled code
even more resistant to reverse engineering.
Stability Code is checked at compile time for syntax errors, type safety, and other problems. By catching these errors at
build-time you can eliminate many errors in your code.
Interoperability Because MSIL code supports any .NET language, you can use assemblies that were originally written
in other languages in your code. For example, if you are writing an ASP.NET Web page in C#, you can add a reference to a
.dll file that was written in Visual Basic.
The ASP.NET compilation architecture includes a number of features including:
Multiple language support.
Automatic compilation.
Flexible deployment.
Extensible build system.
The following sections describe each of these features.
Multiple Language Support
In ASP.NET 2.0 you can use different languages such as Visual Basic and C# in the same application because ASP.NET will
create multiple assemblies, one for each language. For code stored in the App_Code folder, you can specify a subfolder for
each language. For more information on the App_Code folder, see Shared Code Folders in ASP.NET Web Sites.
Automatic Compilation
ASP.NET automatically compiles your application code and any dependent resources the first time a user requests a resource
from the Web site. In general, ASP.NET creates an assembly for each application directory (such as App_Code) and one for the
main directory. (If files in a directory are in different programming languages, then separate assemblies will be created for each
language.) You can specify which directories are compiled into single assemblies in the Compilation section of the Web.config
file.
Flexible Deployment
Because ASP.NET compiles your Web site on first user request, you can simply copy your application's source code to the
production Web server. However, ASP.NET also provides precompilation options that allow you to compile your Web site
before it has been deployed, or to compile it after it has been deployed but before a user requests it. Precompilation has
several advantages. It can improve the performance of your Web site on first request because there will be no lag time while
ASP.NET compiles the site. Precompiling can also help you find errors that might otherwise be found only when a user
requests a page. Finally, if you precompile the Web site before you deploy it, you can deploy the assemblies instead of the
source code.
You can precompile a Web site using the ASP.NET compiler tool (ASPNET_Compiler.exe). The tool that provides the following
precompilation options:
In-place compilation This option performs the same compilation that occurs during dynamic compilation. Use this
option to compile a Web site that has already been deployed to a production server.
Non-updateable full precompilation Use this to compile an application and then copy the compiled output to the
production server. All application code, markup, and UI code is compiled into assemblies. Placeholder files such as .aspx
pages still exist so that you can perform file-specific tasks such as configure permissions, but the files contain no
updateable code. In order to update any page or any code you must precompile the Web site again and deploy it again.
Updateable precompilation This is similar to non-updateable full precompilation, except that UI elements such as
.aspx pages and .ascx controls retain all their markup, UI code, and inline code, if any. You can update code in the file after
it has been deployed; ASP.NET will detect changes to the file and recompile it. Note that code in a code-behind file (.vb or
.cs file) built into assemblies during precompilation, and you therefore cannot change it without going through the
precompilation and deployment steps again.
For more information, see ASP.NET Web Site Precompilation Overview.
Extensible Build System
ASP.NET uses BuildProvider classes to build items such as .aspx pages, .ascx files, and global resources. You can extend and
customize the ASP.NET build system to compile custom resources by creating classes that inherit from the BuildProvider
class. For example, you could add a new file type and then write a BuildProvider that builds that particular type.
See Also
Reference
compilation Element (ASP.NET Settings Schema)
Other Resources
ASP.NET Web Site Precompilation
Understanding ASP.NET Dynamic Compilation
In order for your Web application to service requests, ASP.NET must first parse and compile the code of your Web application
into one or more assemblies. When the code is compiled, it is translated into a language-independent and CPU-independent
representation called Microsoft Intermediate Language (MSIL). At run time, MSIL runs in the context of the .NET Framework,
which translates MSIL into CPU-specific instructions for the processor on the computer running the application.
Compiling on First Request
By default, ASP.NET Web pages and code files are compiled dynamically when users first request a resource, such as an
ASP.NET page (.aspx file), from a Web site. After pages and code files have been compiled the first time, the compiled resources
are cached, so that subsequent requests to the same page are extremely efficient.
ASP.NET supports the dynamic compilation of ASP.NET pages (.aspx files), ASP.NET Web services (.asmx files), ASP.NET HTTP
handlers (.ashx files) and ASP.NET application files (Global.asax), as well as other files, such as source code and class files. For
more information about ASP.NET file types, see Web Site File Types. For more information about the ASP.NET compilation
process, see the "Compilation Life Cycle" section of ASP.NET Application Life Cycle Overview.
Recompiling on Change
Any changes to a dynamically compiled file will automatically invalidate the file's cached compiled assembly and trigger
recompilation of all affected resources. The next time a request to the code is made, ASP.NET recognizes that the code has
changed and recompiles the affected resources of the Web application. This system enables you to quickly develop
applications with a minimum of compilation processing overhead. (Note that depending on the change to the resources, the
result can range from recompiling a single page to recompiling the entire Web site.)
Compilation Dependencies
When the first request is made to an application, ASP.NET compiles files in a specific order. The first items to be compiled are
referred to as the top-level items. After the first request, the top-level items are recompiled only if a dependency changes.
Top-level items include the App_GlobalResources folder, the App_WebResources folder, profile properties, the App_Code
folder, and the Global.asax file. After the top-level items are compiled, ASP.NET compiles additional items. These items include
the App_LocalResources folder, individual ASP.NET pages (.aspx files), ASP.NET user controls (.ascx files), ASP.NET HTTP
Handlers (.ashx files), and ASP.NET HTTP modules (.asmx files), as well as themes, master pages, and other source files.
For more information, see ASP.NET Web Site Layout and the "Compilation Life Cycle" section of
ASP.NET Application Life Cycle Overview.
Compilation Output
When your code is compiled, the resulting assemblies are cached in a folder on the server. This folder requires appropriate
permissions so that your code compiles and runs correctly. You can configure both the compilation folder location and the
permissions under which your code compiles and operates.
Compilation Folder Location
By default, when you compile a Web application the compiled code is placed in the Temporary ASP.NET Files folder. This folder
is a subdirectory of the location where you installed the .NET framework. Typically, the location is the following:

%SystemRoot%\Microsoft.NET\Framework\versionNumber\Temporary ASP.NET Files

Compilation Folder Required Permissions


The .NET installation process creates the Temporary ASP.NET Files folder and assigns access permissions to the ASP.NET local
user account, which has the high-trust permissions needed to access your compiled code. If you modify your configuration or
account settings, you must make sure that the account you use has high-trust permissions to the Temporary ASP.NET Files
folder. For additional details, see How to: Run aspnet_wp.exe Under a User Account.
Compilation Folder Configurability
ASP.NET creates a discrete subfolder under the Temporary ASP.NET File folder for each application. You can configure the root
location using the tempDirectory attribute of the compilation section of the configuration file. This optional attribute enables
you to specify the directory to use for temporary file storage during compilation. The default is an empty string (""). In the case
of an empty string, and if the current process has the required access permissions, the files are stored in the following
directory:

%FrameworkInstallLocation%\Temporary ASP.NET Files

For more information, see compilation Element (ASP.NET Settings Schema) and the TempDirectory property of the
CompilationSection.
Multiple Language Support
ASP.NET 2.0 supports multiple programming languages in the same Web application. In the App_Code directory, you can
specify a subfolder for each language, such as C# and Visual Basic. ASP.NET will create a separate assembly for each subfolder.
For more information, see Shared Code Folders in ASP.NET Web Sites and
Walkthrough: Developing Web Sites Using Multiple Programming Languages.
Dynamic Compilation Advantages and Disadvantages
ASP.NET dynamic compilation enables you to modify your source code without having to explicitly compile your code before
deploying your Web application. If you modify a source file, ASP.NET automatically recompiles the file and updates all linked
resources. The IIS server does not have to be restarted for the changes to take effect unless the <processModel> section has
been changed. Additionally, you can extend the ASP.NET build system by creating custom build providers for new file types
that are called during compilation. The dynamic compilation benefits of the ASP.NET build system are backward compatible
with older ASP.NET application structures and types as well.
There are certain capabilities that dynamic compilation does not offer. Dynamic compilation can mean slower initial response
time for users, because pages and code files must be compiled the first time they are requested. This may be an issue
particularly on large sites that are updated frequently. Dynamic compilation does not offer a means to identify compile-time
bugs before users access a site. Also, dynamic compilation does not provide the ability to create a compiled version of the site
that can be deployed to a production server without source code. If any of these issues are concerns for your Web applications,
you can precompile your Web site. For details information, see ASP.NET Web Site Precompilation Overview.
See Also
Tasks
How To: Secure an ASP.NET Application on a Shared Server
Reference
CodeGenDir
Concepts
ASP.NET Impersonation
ASP.NET Required Access Control Lists (ACLs)
ASP.NET Web Site Precompilation Overview
Web Site File Types
ASP.NET Web Site Layout
ASP.NET

How to: Create ASP.NET Application-Level Event Handlers


ASP.NET automatically binds application events to event-handler methods in the Global.asax file using a naming convention of
Application_event, such as Application_BeginRequest and Application_Error. For more information, see
ASP.NET Application Life Cycle Overview.
This code example handles the application-level Error event and writes error information to the system event log. The Error
event is raised whenever an application error or unhandled page error occurs.
To create an Asp.NET application-level event handler
1. If your Web site does not already have a Global.asax file, create one in the root of the site.
2. Create an event-handler method whose name follows the pattern Application_event. For example, to handle an
application Error event, create a handler named Application_Error that takes an Object parameter and an EventArgs
parameter.

Example
The following code example shows a handler in the Global.asax file for the Error event. The handler in the example is called
whenever an unhandled exception occurs anywhere in the application. If an exception is caught in a try/catch block or by a
page object's Error event, the application does not raise the Error error.
VB
Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
' check to see if the ASPNETApplication log exists
If Not System.Diagnostics.EventLog. _
SourceExists("ASPNETApplication") Then
System.Diagnostics.EventLog. _
CreateEventSource("ASPNETApplication", "Application")
End If
System.Diagnostics.EventLog. _
WriteEntry("ASPNETApplication",
Server.GetLastError().Message)
End Sub

C#
void Application_Error(Object sender, EventArgs e)
{
if(!System.Diagnostics.EventLog.SourceExists
("ASPNETApplication"))
{
System.Diagnostics.EventLog.CreateEventSource
("ASPNETApplication", "Application");
}
System.Diagnostics.EventLog.WriteEntry
("ASPNETApplication",
Server.GetLastError().Message);
}

The code writes an entry to the system event log. It checks first to determine whether the event log entry named
ASPNETApplication exists; if not, the code creates it. The code gets the error message associated with the error by calling the
GetLastError method, and then writes the error message to the log.
Compiling the Code
Security
This code example requires that the application have permission to access the system event log. For more information about
using the system event log, see How to: Write to an Application Event Log.
See Also
Concepts
ASP.NET Application Life Cycle Overview
Other Resources
Error Handling in ASP.NET Pages and Applications
ASP.NET

Custom ASP.NET Processing with HTTP Handlers


HTTP handlers are ASP.NET components that run when they are requested in a browser and that return dynamically created
information. (An ASP.NET Web page is an example of one type of HTTP handler.) You can use HTTP handlers to create any type
of process that needs to return information to users that is not an HTML page. This section describes how to create and register
HTTP handlers and provides examples of a synchronous handler, an asynchronous handler, and a handler factory.
In This Section
Introduction to HTTP Handlers
How to: Register HTTP Handlers
How to: Create Synchronous HTTP Handlers
How to: Create an Asynchronous HTTP Handler
How to: Create HTTP Handler Factories
Related Sections
ASP.NET Life Cycle
Provides information on the steps that occur as an ASP.NET Web application accepts requests and processes them.
Extending ASP.NET Processing with HTTP Modules
Provides information on extending ASP.NET processing using HTTP modules.
ASP.NET

Introduction to HTTP Handlers


An ASP.NET HTTP handler is the process (frequently referred to as the "endpoint") that runs in response to a request made to
an ASP.NET Web application. The most common handler is an ASP.NET page handler that processes .aspx files. When users
request an .aspx file, the request is processed by the page via the page handler.
The ASP.NET page handler is only one type of handler. ASP.NET comes with several other built-in handlers such as the Web
service handler for .asmx files.
You can create custom HTTP handlers when you want special handling that you can identify using file name extensions in your
application. For example, the following scenarios would be good uses of custom HTTP handlers:
RSS feeds To create an RSS feed for a site, you can create a handler that emits RSS-formatted XML. You can then bind
the .rss extension (for example) in your application to the custom handler. When users send a request to your site that
ends in .rss, ASP.NET will call your handler to process the request.
Image server If you want your Web application to serve images in a variety of sizes, you can write a custom handler to
resize images and then send them back to the user as the handler's response.
HTTP handlers have access to the application context, including the requesting user's identity (if known), application state, and
session information. When an HTTP handler is requested, ASP.NET calls the ProcessRequest method on the appropriate
handler. The handler's ProcessRequest method creates a response, which is sent back to the requesting browser. As with any
page request, the response goes through any HTTP modules that have subscribed to events that occur after the handler has
run. For more information about the processing of Web server requests, see ASP.NET Application Life Cycle Overview.
An HTTP handler can be either synchronous or asynchronous. A synchronous handler does not return until it finishes
processing the HTTP request for which it is called. An asynchronous handler runs a process independently of sending a
response to the user. Asynchronous handlers are useful when you need to start an application process that might be lengthy
and the user does not need to wait until it finishes before getting a response from the server.
Built-in HTTP Handlers in ASP.NET
ASP.NET maps HTTP requests to HTTP handlers based on a file name extension. Each HTTP handler enables processing of
individual HTTP URLs or groups of URL extensions within an application. ASP.NET includes several built-in HTTP handlers, as
listed in the following table.
Handler Description
ASP.NET Page Handler (*.a The default HTTP handler for all ASP.NET pages.
spx)

Web service handler (*.as The default HTTP handler for Web service pages created using ASP.NET.
mx)

ASP.NET user control hand The default HTTP handler for all ASP.NET user control pages.
ler (*.ascx)

Trace handler (trace.axd) A handler that displays current page trace information. For details, see
How to: View ASP.NET Trace Information with the Trace Viewer.

Creating a Custom HTTP Handler


To create a custom HTTP handler, you create a class that implements the IHttpHandler interface to create a synchronous
handler or the IHttpAsyncHandler to create an asynchronous handler. Both handler interfaces require you to implement the
IsReusable property and the ProcessRequest method. The IsReusable property specifies whether the IHttpHandlerFactory
object (the object that actually calls the appropriate handler) can place your handlers in a pool and reuse them to increase
performance, or whether it must create new instances every time the handler is needed. The ProcessRequest method is
responsible for actually processing the individual HTTP requests.
Creating a File Name Extension
When you create a class file as your HTTP handler, you can have your handler respond to any file name extension that is not
already mapped in IIS and in ASP.NET. For example, if you are creating an HTTP handler for generating an RSS feed, you can
map your handler to the extension .rss. In order for ASP.NET to know which handler to use for your custom file name
extension, the extension of the handler's class file must be mapped in IIS to ASP.NET, and in your application to your custom
handler.
By default, ASP.NET maps the file name extension .ashx for custom HTTP handlers, in the same way that it maps the .aspx
extension to the ASP.NET page handler. Therefore, if you create an HTTP handler class with the file name extension .ashx, the
handler is automatically registered with IIS and ASP.NET.
If you want to create a custom file name extension for your handler, you must explicitly register the extension with IIS and
ASP.NET. The advantage of not using the .ashx file name extension is that your handler is then reusable for different extension
mappings. For example, in one application your custom handler might respond to requests that end in .rss, and in another
application it might respond to requests that end in .feed. As another example, your handler might be mapped to both file
name extensions in the same application, but might create different responses based on the extension.
Asynchronous HTTP Handlers
Asynchronous HTTP handlers allow you to start an external process, such as a method call to a remote server, and then
continue the processing of the handler without waiting for the external process to finish. During the processing of an
asynchronous HTTP handler, ASP.NET places the thread that would ordinarily be used for the external process back into the
thread pool until the handler receives a callback from the external process. This can prevent thread blocking and greatly
improve performance, because only a limited number of threads can be executed at once. If a number of users request
synchronous HTTP handlers that rely on external processes, the operating system can quickly run out of threads because many
threads are blocked and waiting for an external process.
When you create an asynchronous handler, in addition to implementing the IHttpAsyncHandler interface, you must
implement the BeginProcessRequest to initiate an asynchronous call for processing individual HTTP requests. You must also
implement the EndProcessRequest method to run cleanup code when the process ends.
Custom IHttpHandlerFactory Classes
The IHttpHandlerFactory class receives requests and is responsible for forwarding a request to an appropriate HTTP handler.
You can create a custom HTTP handler factory by creating a class that implements the IHttpHandlerFactory interface.
Creating a custom handler factory can allow finer control over the processing of an HTTP request by creating different handlers
based on run-time conditions. For example, with a custom HTTP handler factory, you can instantiate one HTTP handler for a file
type if the HTTP request method is PUT, and another if the method is GET.
See Also
Tasks
How to: Create Synchronous HTTP Handlers
How to: Create an Asynchronous HTTP Handler
How to: Create HTTP Handler Factories
Concepts
ASP.NET Application Life Cycle Overview
ASP.NET

How to: Register HTTP Handlers


After you have created a custom HTTP handler class, you must register it in the Web.config file. This allows ASP.NET to call the
handler to service requests made to resources with the file name extension that you want the HTTP handler to process.
Register an HTTP Handler in the Web.config File
In order for ASP.NET to send requests to a custom HTTP handler, you must register the file name extension with the custom
HTTP handler. You do this in your application's Web.config file.
To register an HTTP handler
1. Compile the .NET class for the HTTP handler and copy the resulting assembly to the Bin directory under the application's
virtual root, or put the source code for the handler into your application's App_Code folder.
For one example of an HTTP handler, see How to: Create Synchronous HTTP Handlers.
2. Register the HTTP handler in the application's Web.config file by creating an
httpHandlers Element (ASP.NET Settings Schema) section.
The following code example shows how to register an HTTP handler that responds to requests for the
SampleHandler.new resource. The handler is defined as the class SampleHandler in the assembly
SampleHandlerAssembly.

<configuration>
<system.web>
<httpHandlers>
<add verb="*" path="SampleHandler.new"
type="SampleHandler, SampleHandlerAssembly" />
</httpHandlers>
<system.web>
</configuration>

The following code example maps all HTTP requests to files with the file name extension of SampleFileExtension to the
SampleHandler2 custom HTTP handler class. In this case, the handler code is in the App_Code directory, so you do not
need to specify an assembly.

<configuration>
<system.web>
<httpHandlers>
<add verb="*" path="*.SampleFileExtension"
type="SampleHandler2 " />
</httpHandlers>
<system.web>
</configuration>

Configuring IIS for an HTTP Handler Extension


Internet Information Services (IIS) will only pass requests for certain file types to ASP.NET to service. By default, files with file
name extensions, such as .aspx, .ascx, .asmx, and .ashx are already mapped to the ASP.NET ISAPI extension (Aspnet_isapi.dll).
However, to have IIS pass custom file name extensions to ASP.NET, you must register the extensions in IIS. For more
information, see ASP.NET Application Life Cycle Overview.
To map a file name extension in IIS
1. In Windows, open Internet Information Services (IIS) Manager.
2. Open the node for your computer, open the Web Sites node, and then open the Default Web Site node.
3. Right-click the name of your application, and then click Properties.
4. Click the Directory tab (or the Virtual Directory tab in IIS 6.0), and then click Configuration.
5. On the Mappings tab, click Add and create a new association for the file name extension that you want IIS to forward to
ASP.NET.
Note
Click the Edit button to view an existing association to determine what value to use for the executable file.

6. If you want your handler to run regardless of whether a file exists with the requested file name extension, clear the
Verify that file exists check box.
See Also
Tasks
How to: Create an Asynchronous HTTP Handler
How to: Create Synchronous HTTP Handlers
Concepts
Introduction to HTTP Handlers
ASP.NET Application Life Cycle Overview
ASP.NET

How to: Create Synchronous HTTP Handlers


This topic illustrates the code for an HTTP handler that performs synchronous processing of requests for resources in an
ASP.NET application whose URL ends with .sample. The code example illustrates the following:
The code for an HTTP handler class. The class must implement the ProcessRequest method and the IsReusable property.
The elements that are required in a Web.config file to register the handler and map the .sample file name extension to it.
In Internet Information Services (IIS), how to map the .sample file name extension to ASP.NET.
Note
The ASP.NET Development Server will serve the request for the new resource after the configuration file is changed to includ
e a reference to the new handler. To enable IIS to serve the request, see the procedure below.

When users request a resource whose URL ends in .sample, the Web server forwards the request to ASP.NET. ASP.NET then
calls the HTTP handler, which returns a response. The response is created dynamically by the handler; there is no need for a file
with the file name extension .sample to exist. For more information about how ASP.NET interacts with the Web server, see
ASP.NET Life Cycle.
To create the custom HelloWorldHandler HTTP handler class
1. In your Web site's App_Code directory, create a class named HelloWorldHandler.
2. Add the following code to your class file.
VB
Imports System.Web

Public Class HelloWorldHandler


Implements IHttpHandler

Public Sub ProcessRequest(ByVal context As _


System.Web.HttpContext) Implements _
System.Web.IHttpHandler.ProcessRequest
Dim request As HttpRequest = context.Request
Dim response As HttpResponse = context.Response
' This handler is called whenever a file ending
' in .sample is requested. A file with that extension
' does not need to exist.
response.Write("<html>")
response.Write("<body>")
response.Write("<h1>Hello from a synchronous custom HTTP handler.</h1>")
response.Write("</body>")
response.Write("</html>")
End Sub

Public ReadOnly Property IsReusable() As Boolean _


Implements System.Web.IHttpHandler.IsReusable
Get
Return False
End Get
End Property
End Class

C#
using System.Web;
public class HelloWorldHandler : IHttpHandler
{
public HelloWorldHandler()
{
}
public void ProcessRequest(HttpContext context)
{
HttpRequest Request = context.Request;
HttpResponse Response = context.Response;
// This handler is called whenever a file ending
// in .sample is requested. A file with that extension
// does not need to exist.
Response.Write("<html>");
Response.Write("<body>");
Response.Write("<h1>Hello from a synchronous custom HTTP handler.</h1>");
Response.Write("</body>");
Response.Write("</html>");
}
public bool IsReusable
{
// To enable pooling, return true here.
// This keeps the handler in memory.
get { return false; }
}
}

The code implements the ProcessRequest method and writes out a string to the Response property of the current
HttpContext object.

Registering a Custom HTTP Handler


After you have created the custom HTTP handler class, you must register it in the application's Web.config file. This allows
ASP.NET to find the handler when ASP.NET receives requests made to resources whose URL ends with .sample.
To register a custom HTTP handler in the Web.config file
1. Add a Web.config file to your Web site if one does not already exist.
2. Add the following highlighted element to your Web.config file.

<configuration>
<system.web>
<httpHandlers>
<add verb="*" path="*.sample"
type="HelloWorldHandler"/>
</httpHandlers>
</system.web>
</configuration>

The code registers your custom handler by class name and maps the .sample file name extension to that handler.
Configuring IIS 6.0 for an HTTP Handler Extension
IIS passes requests for only certain file types to ASP.NET to service. By default, files with file name extensions such as .aspx,
.ascx, .asmx, are already mapped in IIS 6.0 to the ASP.NET ISAPI extension (Aspnet_isapi.dll). However, if you want ASP.NET to
handle custom URL extensions, you must map the extensions in IIS. For more information, see ASP.NET Life Cycle.
To map the .sample file name extension to ASP.NET in IIS 6.0
1. Open Internet Information Services (IIS) Manager.
2. Right-click the name of your application, and then click Properties.
Note
For instructions for creating an ASP.NET application, see How to: Create and Configure Local ASP.NET Web Sites in IIS.

3. Click the Virtual Directory tab, and then click Configuration.


4. On the Mappings tab, click Add.
The Add/Edit Application Extension Mapping dialog box is displayed.
5. In the Executable box, type or browse to the file Aspnet_isapi.dll. By default, the file is in the following location.

%windows%\Microsoft.NET\Framework\version\

Note
You can get the complete path and file name from other mappings, such as the mapping to .aspx files.

6. In the Extension box, type .sample.


7. Clear the Verify that file exists check box.
8. Click OK and then close IIS Manager.
Testing the Custom HTTP Handler
After you have created and registered your custom HTTP handler, you can test it by requesting a resource that has a .sample
file name extension.
To test your custom HTTP handler
In your browser, enter a URL that points to your Web application and that ends in .sample, such as the following:

http://localhost/SampleApplication/test.sample

The text defined in the HelloWorldHandler class is displayed.

See Also
Tasks
How to: Create an Asynchronous HTTP Handler
Concepts
Introduction to HTTP Handlers
ASP.NET Application Life Cycle Overview
Other Resources
ASP.NET Life Cycle
ASP.NET

How to: Create an Asynchronous HTTP Handler


Asynchronous HTTP handlers enable you to start an external process, such as a method call to a remote server, while the
handler continues processing without waiting for the external process to finish. During the processing of an asynchronous
HTTP handler, ASP.NET places the thread that would ordinarily be used for the external process back into the thread pool until
the handler receives a callback from the external process. This can prevent thread blocking and improve performance, because
only a limited number of threads can be executed at once. If a number of users request synchronous HTTP handlers that rely
on external processes, the operating system can quickly run out of threads because many threads are blocked and waiting for
an external process.
The following code example demonstrates an asynchronous HTTP handler that processes requests for files with the file name
extension .SampleAsync within an ASP.NET application. The example shows the code for the handler, and then how to map the
.SampleAsync extension to the handler in ASP.NET. Finally, the example shows how to map the .SampleAsync extension to
ASP.NET in IIS, so that IIS forwards requests that end in .SampleAsync to ASP.NET.
For more information on how the ASP.NET runtime interacts with IIS, see ASP.NET Application Life Cycle Overview.
To create the HelloWorldAsyncHandler HTTP handler class
Create a class named HelloWorldAsyncHandler in your App_Code directory and add the following code to the class file:
VB
Imports Microsoft.VisualBasic
Imports System.Web
Imports System.Threading

Public Class HelloWorldAsyncHandler


Implements IHttpAsyncHandler

Public ReadOnly Property IsReusable() As Boolean Implements System.Web.IHttpHandle


r.IsReusable
Get
Return False
End Get
End Property

Public Function BeginProcessRequest( _


ByVal context As System.Web.HttpContext, _
ByVal cb As System.AsyncCallback, _
ByVal extraData As Object) _
As System.IAsyncResult _
Implements System.Web.IHttpAsyncHandler.BeginProcessRequest
context.Response.Write("<p>Begin IsThreadPoolThread is " _
& Thread.CurrentThread.IsThreadPoolThread & "</p>" & vbCrLf)
Dim asynch As New AsynchOperation(cb, context, extraData)
asynch.StartAsyncWork()
Return asynch
End Function

Public Sub EndProcessRequest(ByVal result As _


System.IAsyncResult) _
Implements System.Web.IHttpAsyncHandler.EndProcessRequest
End Sub

Public Sub ProcessRequest(ByVal context _


As System.Web.HttpContext) _
Implements System.Web.IHttpHandler.ProcessRequest
Throw New InvalidOperationException()
End Sub
End Class

Class AsynchOperation
Implements IAsyncResult
Private _completed As Boolean
Private _state As [Object]
Private _callback As AsyncCallback
Private _context As HttpContext

ReadOnly Property IsCompleted() As Boolean _


Implements IAsyncResult.IsCompleted
Get
Return _completed
End Get
End Property

ReadOnly Property AsyncWaitHandle() As WaitHandle _


Implements IAsyncResult.AsyncWaitHandle
Get
Return Nothing
End Get
End Property

ReadOnly Property AsyncState() As [Object] _


Implements IAsyncResult.AsyncState
Get
Return _state
End Get
End Property

ReadOnly Property CompletedSynchronously() As Boolean _


Implements IAsyncResult.CompletedSynchronously
Get
Return False
End Get
End Property

Public Sub New(ByVal callback As AsyncCallback, _


ByVal context As HttpContext, _
ByVal state As [Object])
_callback = callback
_context = context
_state = state
_completed = False
End Sub

Public Sub StartAsyncWork()


ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf StartAsyncTask), Nothi
ng)

End Sub

Private Sub StartAsyncTask(ByVal workItemState As [Object])


_context.Response.Write("<p>Completion IsThreadPoolThread is " & Thread.Curren
tThread.IsThreadPoolThread & "</p>" & vbCrLf)

_context.Response.Write("Hello World from Async Handler!")


_completed = True
_callback(Me)
End Sub 'StartAsyncTask
End Class 'AsynchOperation

C#
using System;
using System.Web;
using System.Threading;

class HelloWorldAsyncHandler : IHttpAsyncHandler


{
public bool IsReusable { get { return false; } }

public HelloWorldAsyncHandler()
{
}
public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, Obj
ect extraData)
{
context.Response.Write("<p>Begin IsThreadPoolThread is " + Thread.CurrentThrea
d.IsThreadPoolThread + "</p>\r\n");
AsynchOperation asynch = new AsynchOperation(cb, context, extraData);
asynch.StartAsyncWork();
return asynch;
}

public void EndProcessRequest(IAsyncResult result)


{
}

public void ProcessRequest(HttpContext context)


{
throw new InvalidOperationException();
}
}

class AsynchOperation : IAsyncResult


{
private bool _completed;
private Object _state;
private AsyncCallback _callback;
private HttpContext _context;

bool IAsyncResult.IsCompleted { get { return _completed; } }


WaitHandle IAsyncResult.AsyncWaitHandle { get { return null; } }
Object IAsyncResult.AsyncState { get { return _state; } }
bool IAsyncResult.CompletedSynchronously { get { return false; } }

public AsynchOperation(AsyncCallback callback, HttpContext context, Object state)


{
_callback = callback;
_context = context;
_state = state;
_completed = false;
}

public void StartAsyncWork()


{
ThreadPool.QueueUserWorkItem(new WaitCallback(StartAsyncTask), null);
}

private void StartAsyncTask(Object workItemState)


{

_context.Response.Write("<p>Completion IsThreadPoolThread is " + Thread.Curren


tThread.IsThreadPoolThread + "</p>\r\n");

_context.Response.Write("Hello World from Async Handler!");


_completed = true;
_callback(this);
}
}

The code implements the BeginProcessRequest method. The method writes a string to the Response property of the
current HttpContext object, creates a new instance of the AsyncOperation class, and calls the StartAsyncWork method.
The StartAsyncWork method then adds the StartAsyncTask delegate to the ThreadPool object. When a thread becomes
available, the StartAsyncTask method is called, which writes out another string to the Response property, and then the
task finishes by invoking the AsyncCallback delegate.

Registering the Custom HTTP Handler


Once you have created the custom HTTP handler class, you must register it in the Web.config file so that ASP.NET will service
requests made to files with the .SampleAsync extension.
To register the custom HTTP handler in the Web.config file
1. If your Web site does not already have a Web.config file, create one.
2. Add the following code to your Web.config file:

<configuration>
<system.web>
<httpHandlers>
<add verb="*" path="*.SampleAsync"
type="HelloWorldAsyncHandler"/>
</httpHandlers>
</system.web>
</configuration>

The code registers the HelloWorldAsyncHandler handler as the handler for requests that end with .SampleAsync.

Configuring IIS for the HTTP Handler Extension


IIS pass requests only for certain file types to ASP.NET to service. By default, files with extensions such as .aspx, .ascx, .asmx, are
already mapped to the ASP.NET. However, if you want file name extensions that you have defined to be handled by ASP.NET,
you must register them in IIS. For more information, see ASP.NET Application Life Cycle Overview.
To map the extension in IIS
1. Open Internet Services Manager.
2. Right-click your application and choose Properties.
3. In the Directory tab, click Configuration.
4. Select the Mappings tab.
5. Add a new association that maps .SampleAsync to the version of the Aspnet_isapi.dll you wish to use.
6. If you want your handler to run regardless of whether a file exists with the name that the user requests, clear the Check
if the file exists check box.
Testing the Custom HTTP Handler
Once you have created and registered your custom HTTP handler, you can test it by requesting a resource with the
.SampleAsync extension from the application.
To test your custom HTTP handler
Browse to your application and enter a URL in the browser that ends in .SampleAsync.

See Also
Tasks
How to: Create Synchronous HTTP Handlers
Concepts
Introduction to HTTP Handlers
ASP.NET Application Life Cycle Overview
ASP.NET

How to: Create HTTP Handler Factories


The IHttpHandlerFactory interface creates and manages HTTP handlers for processing requests. It is possible, therefore, to
create a class that implements the IHttpHandlerFactory interface, and then use that class as an HTTP handler. This can allow
finer control over the processing of an HTTP request by mapping a URL to an HTTP handler factory that creates different
handlers based on a complex set of conditions. For example, with an HTTP handler factory you can create a limited number of
HTTP handler objects that access expensive or limited resources, such as database connections, and then reuse those handler
objects in future requests.
In the following example, an HTTP handler factory is used to create two handlers for resources that are identified with the
extension .sample — one for an HTTP GET request and one for an HTTP POST request. The first is an instance of the handler
created in How to: Create Synchronous HTTP Handlers; the second is an instance of the handler created in
How to: Create an Asynchronous HTTP Handler.
Creating a Custom HTTP Handler Factory
To create a HandlerFactory HTTP handler factory class
1. Create a class called HelloWorldHandler in your Web site's App_Code directory.
2. Add the following code to your class file.
VB
Imports System
Imports System.Web

Class HandlerFactory
Implements IHttpHandlerFactory

Public Function GetHandler(ByVal context As HttpContext, _


ByVal requestType As String, ByVal url As [String],_
ByVal pathTranslated As [String]) As IHttpHandler _
Implements IHttpHandlerFactory.GetHandler
Dim handlerToReturn As IHttpHandler
Dim requestType as String = _
context.Request.RequestType.ToLower()
If "get" = requestType Then
handlerToReturn = New HelloWorldHandler()
Else
If "post" = requestType Then
handlerToReturn = New HelloWorldAsyncHandler()
Else
handlerToReturn = Nothing
End If
End If
Return handlerToReturn
End Function

Public Sub ReleaseHandler(ByVal handler As IHttpHandler) _


Implements IHttpHandlerFactory.ReleaseHandler
End Sub

Public ReadOnly Property IsReusable() As Boolean


Get
Return False
End Get
End Property
End Class
C#
using System;
using System.Web;

class HandlerFactory : IHttpHandlerFactory


{
public IHttpHandler GetHandler(HttpContext context,
string requestType, String url, String pathTranslated)
{
IHttpHandler handlerToReturn;
if ("get" == context.Request.RequestType.ToLower())
{
handlerToReturn = new HelloWorldHandler();
}
else if ("post" == context.Request.RequestType.ToLower())
{
handlerToReturn = new HelloWorldAsyncHandler();
}
else
{
handlerToReturn = null;
}
return handlerToReturn;
}
public void ReleaseHandler(IHttpHandler handler)
{
}
public bool IsReusable
{
get
{
return false;
}
}
}

The code implements the GetHandler method of the IHttpHandlerFactory interface and returns the synchronous
handler created if the request is a GET request. If the request is a POST request, it returns the asynchronous handler
interface.

Creating Custom HTTP Handlers


The custom HTTP handler factory returns either the synchronous handler created in
How to: Create Synchronous HTTP Handlers, or the asynchronous handler created in
How to: Create an Asynchronous HTTP Handler. You must create both the synchronous HelloWorldHandler class and the
asynchronous HelloWorldAsyncHandler class in order for the custom HTTP handler factory to be able to return those handlers.
To create the HelloWorldHandler and the HelloWorldAsyncHandler classes
1. Create a class named HelloWorldHandler in your Web site's App_Code directory.
2. Add the code from How to: Create Synchronous HTTP Handlers to the class file.
3. Create a class named HelloWorldAsyncHandler in your Web site's App_Code directory.
4. Add the code from How to: Create an Asynchronous HTTP Handler to the class file.
Registering a Custom HTTP Handler Factory
After you have created the custom HTTP handler factory class, you must register it in your Web site's Web.config file. This
allows ASP.NET to use the handler factory class to service requests made to resources with the .sample file name extension.
To register a custom HTTP handler in the Web.config file
1. Add a Web.config file to your Web site if one does not already exist.
2. Add the following highlighted element to the Web.config file.

<configuration>
<system.web>
<httpHandlers>
<add verb="GET,POST" path="*.sample"
type="HandlerFactory" />
</httpHandlers>
</system.web>
</configuration>

The code registers the handler with the class name and the handler name of HandlerFactory.

Configuring IIS 6.0 for an HTTP Handler Extension


Internet Information Services (IIS) passes requests for only certain file types to ASP.NET to service. By default, files with file
name extensions such as .aspx, .ascx, .asmx, are already mapped in IIS 6.0 to the ASP.NET ISAPI extension (Aspnet_isapi.dll).
However, if you want ASP.NET to handle custom URL extensions, you must map the extensions in IIS. For more information,
see ASP.NET Life Cycle.
To map the .sample file name extension to ASP.NET in IIS 6.0
1. Open Internet Information Services (IIS) Manager.
2. Right-click the name of your application, and then click Properties.
Note
For instructions for creating an ASP.NET application, see How to: Create and Configure Local ASP.NET Web Sites in IIS.

3. Click the Virtual Directory tab, and then click Configuration.


4. On the Mappings tab, click Add.
The Add/Edit Application Extension Mapping dialog box is displayed.
5. In the Executable box, type or browse to the file Aspnet_isapi.dll. By default, the file is in the following location.

%windows%\Microsoft.NET\Framework\version\

Note
You can get the complete path and file name from other mappings, such as the mapping to .aspx files.

6. In the Extension box, type .sample.


7. Clear the Verify that file exists check box.
8. Click OK and then close IIS Manager.

Testing the Custom HTTP Handler Factory


After you have created and registered your custom HTTP handler factory, you can test it by creating an HTML page that can
request a resource that has a .sample file name extension.
To test your custom HTTP handler factory
1. Create an HTML page (with a file name extension of .htm) in your application.
2. In the body section of the page, add the following code.

<form action="Sample.sample" method="get">


<input type="submit" value="Submit to Sample.sample via Get" />
</form>
<br />
<form action="Sample.sample" method="post">
<input type="submit" value="Submit to Sample.sample via Post" />
</form>

3. Request the HTML page in your browser.


4. Click one of the buttons.
If you click the first button the HTTP handler factory will respond to the request by creating and calling a synchronous
HTTP handler. If you click the second button the HTTP handler factory will respond to the request by creating and calling
an asynchronous HTTP handler.

See Also
Tasks
How to: Create an Asynchronous HTTP Handler
How to: Create Synchronous HTTP Handlers
Concepts
Introduction to HTTP Handlers
ASP.NET Application Life Cycle Overview
ASP.NET

Extending ASP.NET Processing with HTTP Modules


An HTTP module is an assembly that is called on every request made to your application. HTTP modules are called as part of
the ASP.NET request pipeline and have access to life cycle events throughout the request. HTTP modules therefore give you the
opportunity to examine incoming and outgoing requests and take action based on the request. The topics in this section
provide information on how HTTP modules work and how to create them.
In This Section
Introduction to HTTP Modules
How to: Create Custom HTTP Modules
Related Sections
Custom ASP.NET Processing with HTTP Handlers
Describes how to create an ASP.NET component that users can invoke using a request.
ASP.NET Web Applications
Provides information on how to create, customize, and manage an ASP.NET Web application (sometimes referred to as a
Web site).
ASP.NET

Introduction to HTTP Modules


An HTTP module is an assembly that is called on every request made to your application. HTTP modules are called as part of
the ASP.NET request pipeline and have access to life cycle events throughout the request. HTTP modules therefore give you the
opportunity to examine incoming requests and take action based on the request. They also give you the opportunity to
examine the outbound response and modify it.
ASP.NET HTTP modules are similar to ISAPI filters in that they run for all requests. However, they are written in managed code
and are fully integrated with the life cycle of an ASP.NET application.
Typical uses for HTTP modules include:
Security. Because you can examine incoming requests, your HTTP module can perform custom authentication or other
security checks before the requested page, XML Web service, or handler is called.
Statistics and logging. Because HTTP modules are called on every request, you can gather request statistics and logging
information in a centralized module, rather than in individual pages.
Custom headers or footers. Because you can modify the outbound response, you can inject content such as custom
header information into every page or XML Web service response.
ASP.NET uses modules to implement various application features, including forms authentication, caching, session state, and
client script services. In each case, when those services are enabled, the module is called as part of a request and performs
tasks that are outside the scope of any single page request. Modules can consume application events and can raise events that
can be handled in the Global.asax file. For more information about application events, see
ASP.NET Application Life Cycle Overview.
Note
HTTP modules differ from HTTP handlers. HTTP modules are called for all requests and responses, whereas HTTP handlers ru
n only in response to specific requests. For more information, see Introduction to HTTP Handlers.

How HTTP Modules Work


You register a custom HTTP modules in your application's Web.config file. When ASP.NET creates an instance of the
HttpApplication class that represents your application, instances of any modules that have been registered are created. When a
module is created, its Init method is called and the module initializes itself. For more information, see
ASP.NET Application Life Cycle Overview.
In a module's Init method, you can subscribe to various application events such as BeginRequest or EndRequest by binding
the events to methods you have created in the module. When these events are raised, the appropriate method in your module
is called and the module can perform whatever logic is required, such as an authentication check or logging request
information. During event handling, the module has access to the Context property of the current request. This enables you to
redirect the request to an alternative page, modify the request, or perform any other request manipulation. For example, if your
module includes an authentication check, the module might check for credentials and redirect to a login or error page if the
credentials were not correct. Otherwise, when the module's event handler has finished running, ASP.NET calls the next process
in the pipeline, which might be another module or might be the appropriate HTTP handler (such as an .aspx file) for the
request.
HTTP Modules versus Global.asax Files
You can implement much of the functionality of a module in the application's Global.asax file, which enables you to respond to
application events. However, modules have an advantage over the Global.asax file in that they are encapsulated and can be
created once and used in many different applications. By adding them to the Global Assembly Cache (GAC) and registering
them in the Machine.config file, you can reuse them across applications. For more information, see Global Assembly Cache.
However, the advantage to using the Global.asax file is that you can place code in other registered module events such as
Session_Start and Session_End methods. In addition, the Global.asax file enables you to instantiate global objects that are
available throughout the application.
You should use a module whenever you need to create code that depends on application events and you either wish to reuse
the module in other applications or you don't want to place complex code in the Global.asax file. You should place code in the
Global.asax file whenever you need to create code that depends on application events and you do not need to reuse it across
applications, or when you need to subscribe to events such as Session_Start that are not available to modules.
Creating an HTTP Module
You can create a custom HTTP module by creating a class that implements the IHttpModule interface and then registering it in
the Web.config file. The general process for writing an HTTP module is:
Create a class that implements the IHttpModule frlrfSystemWebIHttpModuleClassTopic interface.
Write a handler for the InitfrlrfSystemWebIHttpModuleClassInitTopic method. Your init method should initialize your
module and subscribe to any application events you need. For example, you might subscribe to the EndRequest event if
you want to append something to responses, or you might subscribe to the AuthenticateRequest event if you wish to
perform custom authentication logic. For more information on application events, see
ASP.NET Application Life Cycle Overview.
Write code for the events you have subscribed to.
Optionally implement the Dispose method if your module requires cleanup.
Register the module in the Web.config file.
For more information, see How to: Create Custom HTTP Modules.
See Also
Tasks
How to: Create Custom HTTP Modules
Concepts
ASP.NET Application Life Cycle Overview
ASP.NET

How to: Create Custom HTTP Modules


The custom HTTP module described in this topic illustrates the basic functionality of an HTTP module. The module is called in
response to two events: the BeginRequest event and the EndRequest event. This enables the module to run before and after a
page request is processed. In this case, the module adds a message to the requested ASP.NET Web page at the beginning of
any HTTP request and another message after the request has been processed.
Note
The BeginRequest and EndRequest events are only two of the events that occur during page processing. For more informa
tion about the events raised while processing a page, see Server Event Handling in ASP.NET Web Pages.

Each handler is written as a private method of the module. When the registered events are raised, ASP.NET calls the
appropriate handler method in the module, which writes information to the ASP.NET Web page.
To create a custom HTTP module class
1. If your Web site does not already have an App_Code folder, create one under the root of the site.
2. Create a class file named HelloWorldModule.vb (for Visual Basic) or HelloWorldModule.cs (for C#) in the App_Code
directory.
Note
Alternatively, you can compile the HelloWorldModule class into a library and place the resulting .dll file in the Web applicatio
n's Bin directory.

1. Add the following code to your class file:


VB
Imports Microsoft.VisualBasic

Public Class HelloWorldModule


Implements IHttpModule

Public ReadOnly Property ModuleName() As [String]


Get
Return "HelloWorldModule"
End Get
End Property

' In the Init function, register for HttpApplication


' events by adding your handlers.
Public Sub Init(ByVal application As HttpApplication) _
Implements IHttpModule.Init
AddHandler application.BeginRequest, _
AddressOf Me.Application_BeginRequest
AddHandler application.EndRequest, _
AddressOf Me.Application_EndRequest
End Sub

Private Sub Application_BeginRequest(ByVal source As Object, _


ByVal e As EventArgs)
' Create HttpApplication and HttpContext objects to access
' request and response properties.
Dim application As HttpApplication = CType(source, _
HttpApplication)
Dim context As HttpContext = application.Context
context.Response.Write _
("<h1><font color=red>HelloWorldModule: " & _
"Beginning of Request</font></h1><hr>")
End Sub

Private Sub Application_EndRequest(ByVal source As Object, _


ByVal e As EventArgs)
Dim application As HttpApplication = CType(source, _
HttpApplication)
Dim context As HttpContext = application.Context
context.Response.Write _
("<hr><h1><font color=red>HelloWorldModule: " & _
"End of Request</font></h1>")
End Sub

Public Sub Dispose() Implements IHttpModule.Dispose


End Sub
End Class

C#
public class HelloWorldModule : IHttpModule
{
public HelloWorldModule()
{
}

public String ModuleName


{
get { return "HelloWorldModule"; }
}

// In the Init function, register for HttpApplication


// events by adding your handlers.
public void Init(HttpApplication application)
{
application.BeginRequest +=
(new EventHandler(this.Application_BeginRequest));
application.EndRequest +=
(new EventHandler(this.Application_EndRequest));
}

private void Application_BeginRequest(Object source,


EventArgs e)
{
// Create HttpApplication and HttpContext objects to access
// request and response properties.
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
context.Response.Write("<h1><font color=red>
HelloWorldModule: Beginning of Request
</font></h1><hr>");
}

private void Application_EndRequest(Object source, EventArgs e)


{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
context.Response.Write("<hr><h1><font color=red>
HelloWorldModule: End of Request</font></h1>");
}

public void Dispose()


{
}
}

Registering the HTTP Module


When you have finished creating the HelloWorldModule class, you can register the module by creating an entry in the
Web.config file.
To register the module in the Web.config file
1. If your Web site does not already have a Web.config file, create one under the root of the site.
2. Add the following highlighted code to the Web.config file:

<configuration>
<system.web>
<httpModules>
<add name="HelloWorldModule" type="HelloWorldModule"/>
</httpModules>
</system.web>
</configuration>

The code registers the module with the class name and the module name of HelloWorldModule.

Testing the Custom HTTP Module


After you have created and registered your custom HTTP module you can test it.
To test the custom HTTP module
1. Create a Default.aspx page in your application.
2. Request the Default.aspx page in a browser.
The HTTP module appends a string to the beginning and end of the response. The module will automatically run on any
request to a file whose extension is assigned to ASP.NET. For more information, see Introduction to HTTP Modules.
See Also
Concepts
Introduction to HTTP Modules
ASP.NET Application Life Cycle Overview
Visual Web Developer

Walkthrough Topics — ASP.NET Web Sites


The following walkthrough topics demonstrate how to create ASP.NET Web sites and how to use code in ASP.NET Web sites.
Walkthrough Topics
Walkthrough: Creating a Local IIS Web Site in Visual Web Developer
Walkthrough: Editing Web Sites with FTP in Visual Web Developer
Walkthrough: Using Shared Code in Web Sites in Visual Web Developer
See Also
Other Resources
ASP.NET Web Sites (Visual Studio)
Visual Web Developer

How-to Topics — ASP.NET Web Sites


The following procedures describe how to create Web sites and how to work with ASP.NET Web pages.
How-to Topics
How to: Create Local IIS Web Sites
How to: Create File System Web Sites
How to: Open Web Sites Using FTP
How to: Create and Configure FTP Sites in IIS
How to: Create Remote IIS Web Sites
How to: Add Files to ASP.NET Web Sites
How to: Specify the Web Server for Web Sites
How to: Specify a Port for the ASP.NET Development Server
How to: Bypass a Proxy Server for Local Web Requests
How to: Create IIS Virtual Directories in Visual Web Developer
How to: Install and Configure SMTP Virtual Servers in IIS
How to: Add a Reference to a .NET or COM Component in a Web Site
How to: Add a Reference to a Visual Studio Project in a Web Site
How to: Create ASP.NET Application-Level Event Handlers
How to: Register HTTP Handlers
How to: Create Synchronous HTTP Handlers
How to: Create an Asynchronous HTTP Handler
How to: Create HTTP Handler Factories
How to: Create Custom HTTP Modules

See Also
Other Resources
ASP.NET Web Sites (Visual Studio)
Visual Web Developer

ASP.NET Web Pages (Visual Studio)


The topics in this section provide information about creating and editing Web pages in Visual Web Developer.
In This Section
ASP.NET Web Pages Introduction (Visual Studio)
Provides an overview of ASP.NET Web pages, including a tutorial on creating pages and other files.
Web Page Designer
Provides information about how to use the editors in Visual Studio to create and edit ASP.NET Web pages and other files.
Programming ASP.NET Web Pages (Visual Studio)
Provides information about how to create event handlers in ASP.NET pages.
Programming ASP.NET Web Pages with Client Script
Provides information about to raise and handle events in client script and how to add client script to ASP.NET Web pages.
ASP.NET Master Pages in Visual Studio
Provides information about how to create a consistent page layout for your Web site by using a template (master page) and
separate content pages.
ASP.NET Themes in Visual Studio
Provides information on how to create a consistent appearance for pages and controls by setting properties and CSS styles.
ASP.NET Web Parts in Visual Studio
Provides information on how to create pages with application features that users can select and customize in a browser.
Saving ASP.NET Page Values (Visual Studio)
Provides information on how to store information between page requests.
ASP.NET Caching (Visual Studio)
Provides information on how to store page output and frequently used application information in server memory for
improved performance.
Related Sections
Guided Tour of Creating Web Sites in Visual Web Developer
Provides links to tutorials on all aspects of creating ASP.NET Web sites and ASP.NET Web pages.
Visual Web Developer

ASP.NET Web Pages Introduction (Visual Studio)


The topics in this section provide an overview of creating and editing ASP.NET Web pages using the tools in Visual Studio.
In This Section
Getting Started - Creating Web Pages
Learning More - Creating Web Pages
Walkthrough Topics — Creating Web Pages
How-to Topics — Creating Web Pages
See Also
Other Resources
ASP.NET Web Sites (Visual Studio)
ASP.NET Web Server Controls (Visual Studio)
Visual Web Developer

Getting Started - Creating Web Pages


The topics in this section provide essential information on working with ASP.NET Web pages, including information on page
processing, code-behind, and the page code model.
In This Section
Introduction to ASP.NET Web Pages
What's New in ASP.NET Web Pages
Walkthrough: Creating a Basic Web Page in Visual Web Developer
Walkthrough: Creating a Basic Web Page with Code Separation in Visual Web Developer
Walkthrough: Code Editing in Web Pages in Visual Web Developer
How to: Add ASP.NET Web Pages to a Web Site (Visual Studio)
Testing Web Pages in Visual Web Developer
See Also
Other Resources
ASP.NET Web Sites (Visual Studio)
ASP.NET Web Pages (Visual Studio)
ASP.NET Web Server Controls (Visual Studio)
ASP.NET

Introduction to ASP.NET Web Pages


ASP.NET Web pages allow you to create dynamic content for your Web site. With a static HTML page (.htm or .html file), the
server fulfills a Web request by reading the file and sending it as-is to the browser. In contrast, when someone requests an
ASP.NET Web page (.aspx file), the page runs as a program on the Web server. While the page is running, it can perform any
task that your Web site requires, including calculating values, reading or writing database information, or calling other
programs. As its output, the page dynamically produces markup (elements in HTML or another markup language) and sends
this dynamic output to the browser.
This topic provides an overview of the fundamental characteristics of how ASP.NET Web pages work in Web applications.
Postbacks and Round Trips
ASP.NET pages run as code on the server. Therefore, for the page to be processed, the page is configured to submit to the
server when users click buttons (or optionally, when users select check boxes or interact with other controls in the page). Each
time, the page is submitted back to itself so it can run its server code again and then render a new version of itself back to the
user.
The processing cycle for an ASP.NET Web page is this:
1. The user requests the page. (The page is requested using an HTTP GET method.) The page runs for the first time,
performing preliminary processing if you have programmed it to do so.
2. The page dynamically renders markup to the browser, which the user sees as a Web page similar to any other page.
3. The user types information or selects from available choices and then clicks a button. (If users click a link instead of a
button, the page might simply navigate to another page, and no further processing takes place on the first page.)
4. The page is posted to the Web server. (The browser performs an HTTP POST method, which in ASP.NET is referred to as
a postback.) Specifically, the page is posted back to itself. For example, if the user is working with the page Default.aspx,
clicking a button on the page posts the page back to the server with a target of Default.aspx.
5. On the Web server, the page runs again. The information that the user typed or selected is available to the page.
6. The page performs the processing that you have programmed it to do.
7. The page renders itself back to the browser.
This cycle continues as long as the user is working in the page. Each time the user clicks a button, the information in the page is
posted to the Web server and the page runs again. Each cycle is referred to as a round trip. Because page processing occurs on
the Web server, each action that the page can do requires a round trip to the server.
Note
An ASP.NET Web page can run client script, which does not require a round trip to the server, and which is useful for user inp
ut validation and for some types of UI programming. For more information, see
Programming ASP.NET Web Pages with Client Script.

Cross-Page Posting
Under some circumstances, you might want a page to post to a different page, not to itself. This is referred to as cross-page
posting. For example, you might be creating a series of pages that process a customer order. Each page can post to the next
page in the sequence. For more information, see Cross-Page Posting in ASP.NET Web Pages.
Page Lifetime
Unlike forms in desktop applications, an ASP.NET Web page does not start up, run while the user works with the form, and
then unload only when the user clicks a Close button. This is because the Web is inherently disconnected. When a browser
requests a page from a Web server, the browser and the server are connected only long enough to process the request. After
the Web server has rendered a page to the browser, the connection is terminated. If the browser makes another request to the
same Web server, even for the same page, this request is processed as a new request.
The disconnected nature of the Web dictates the way an ASP.NET page runs. When a user requests an ASP.NET Web page, a
new instance of the page is created. The page performs its processing, renders markup to the browser, and is then discarded. If
the user clicks a button to perform a postback, a new instance of the page is created, the page performs its processing, and is
again discarded. Thus, each postback and round trip results in a new instance of the page.
For more information, see ASP.NET Web Pages.
Preserving Page State
In normal HTTP protocol, the only information that the server has about a page is the information that the user has specified
using controls on the page, because the browser sends only that information to the server when the page is posted. Other
information, such as variable values and property settings, is discarded. ASP.NET helps preserve other page information in the
following ways:
ASP.NET saves control settings (properties) between round trips, which is called saving control state.
ASP.NET provides state management capabilities so you can save your own variables and application-specific or session-
specific information between round trips.
ASP.NET can detect when a page is requested for the first time and when the page is posted, which allows you to
program accordingly. For instance, you might want to read information from a database the first time a page is
displayed, but not on every postback.
Note
The server can be configured to cache page information to optimize the pages, but for purposes of application progra
mming, it is clearest to think of pages as being disposed of as soon as the server has finished processing them.

For more information, see ASP.NET State Management Overview.


Programming ASP.NET Web Pages
You can create the server code for your ASP.NET Web pages using a variety of languages in the .NET Framework, including
Visual Basic, C#, and J#. ASP.NET Web pages can contain client script that runs within the browser. Some ASP.NET functions
generate client script and inject it into the page. In that case, ASP.NET always generates ECMAScript (JavaScript) for best cross-
browser functionality. In addition, you can add your own client script for custom functionality. If you do, you can use any client
script language that is compatible with the browsers you are targeting.
Server Controls
Like any Web page, ASP.NET Web pages can contain static text. Most often, however, you will add controls to the page, such as
text boxes, check boxes, and buttons. These controls allow the user to interact with the page and send information to the server
when the page is posted back.
ASP.NET provides a collection of controls known as Web server controls. ASP.NET server controls can be similar to
corresponding HTML form elements. For example, the ASP.NET TextBox control is similar to an HTML <input type="text">
tag. However, ASP.NET server controls offer a richer programming experience than HTML elements. There are also ASP.NET
server controls for a much wider range of functions than what is offered by HTML elements. Among the server controls you
can use on an ASP.NET Web page are a calendar control, data-bound controls that display lists or grids, a login control to add
security to your site, and many more.
For more information, see ASP.NET Web Server Controls.
Page and Server Control Events
An ASP.NET Web page and the controls on it support an event model like that found in Windows Forms. For example, when
users click a Button server control on an ASP.NET Web page, the page is posted back to the server, the page is recreated, and a
click event is raised. You can add code to the page that responds to this click event.
The page itself raises life cycle events when it is initialized, such as the Page_Init and Page_Load events, which gives you an
opportunity to run code when the page starts up. (Remember that the page is created and reinitialized with each round trip.)
Individual controls can raise their own events. Button controls raise a Click event, check box and radio button controls raise a
CheckedChanged event, and list box and drop-down list controls raise a SelectedIndexChanged event. Some controls, such
as the Calendar control, raise events that are more abstract than simple click events. For example, the Calendar control raises a
VisibleMonthChanged event when users navigate to a different month.
Most ASP.NET server controls support only a few events that you can handle in server code. To process an event, the page
must perform a round trip so that the user's choice can be sent to the page for processing. Server controls do not expose high-
frequency events such as onmouseover, because each time such an event is raised, another round trip to the server would
occur, which would considerably affect response time in the page. However, you can configure ASP.NET server controls to raise
client-side events such as onmouseover. In that case, the controls do not post back to the server, and you create client script
to respond to the events.
For more information about creating and using events and event handlers, see Server Event Handling in ASP.NET Web Pages.
Browser Compatibility
Because ASP.NET Web page processing occurs on the Web server, ASP.NET Web pages are compatible with any browser or
mobile device. A Web page automatically renders the correct browser-compliant markup (XHTML or other markup language)
for features such as styles and layout. Alternatively, you can create Web pages with controls that are specifically designed to
render output for specific devices, such as mobile phones. For more information, see Creating ASP.NET Mobile Web Pages.
See Also
Other Resources
ASP.NET Web Server Controls
ASP.NET

What's New in ASP.NET Web Pages


This topic describes important changes and new features added to ASP.NET Web pages for version 2.0 of the .NET Framework.
Page Appearance
ASP.NET pages have been enhanced to provide you with more options to control their appearance.
Master Pages
You can create consistent layout for multiple pages by creating a master page and individual content pages. The master page
defines the layout, navigation, and controls that you want to share among the pages in your Web application. The master page
can also contain code that applies to all pages. You can then define content pages that reference the master page and merge
their content with the master page at run time. For more information, see ASP.NET Master Pages Overview.
Themes
You can now use ASP.NET themes to style Web pages. A theme is a collection of control property settings (referred to as skins),
style sheets, and graphics that you can apply as a unit to a page or Web site. Themes enable you to define styling that can be
applied to a set of pages, and can be changed as a group. For more information, see ASP.NET Themes and Skins Overview.
Page Behavior
ASP.NET Web pages have been enhanced with new features that give you improved control over how the page functions.
New Code-Behind Model
ASP.NET continues to support the single-file model in which code is embedded in a script block in the .aspx page. In addition, a
new code-behind model has been introduced, which is simpler than the code-behind model that was used in earlier versions of
ASP.NET. The new code-behind model is based on partial classes, which enables you to define a portion of a class, such as the
event handlers, and keep the code in a separate file. The partial-class file is compiled as part of the .aspx page.
Note
The new code-behind model is available only with .NET languages that support partial classes. Some languages, such as J#, d
o not support partial classes.

For more information, see What's New in the ASP.NET Web Page Model.
View State and Control State
In version 1.1 of ASP.NET, view state is used to store control state information, the content of controls, and application data.
Developers sometimes want to disable view state to reduce the amount of data sent during a round trip. However, in ASP.NET
1.1, disabling view state causes some controls to stop functioning properly.
In ASP.NET version 2.0 you can disable view state without breaking control behavior. Controls that require state persistence
across postbacks store their own data in a private store, which is referred to as control state. Control state does not store the
entire content of the control. For example, the GridView control does not store the contents of all rows in control state. Instead,
control state is used only to store the minimal information that is required by the control to function across postbacks, which
reduces the size of the page.
As in earlier versions of ASP.NET, if you disable view state, you must regenerate control content that is generated dynamically.
For example, if you are binding controls to data, when you disable view state, you must rebind the controls to data on each
postback.
For more information, see ASP.NET View State.
Managing View State Size
By default, all view state information is stored in a single hidden field in the page. If a hidden field becomes too large, some
proxies and firewalls will prevent the page from being posted. To prevent this problem, you can specify the maximum amount
of data to store in a view state hidden field. If the view state information exceeds the specified limit, the page automatically
creates additional view state hidden fields and splits the information across the fields. The split and reassembly of the view
state fields is done automatically by the page.
Persisting Page State
In ASP.NET version 2.0, you can now create your own classes to persist page state. By default, pages will invoke instances of the
PageStatePersister class that store information in a hidden field on the page, as in version 1.1 of ASP.NET. Pages that are used
with mobile devices instead store page state in session state to reduce page size even further. By creating a class based on the
abstract PageStatePersister class, you can create your own mechanism for saving page state.
Rendering XHTML
By default, ASP.NET pages and controls render markup that conforms to XHTML standards. You can disable XHTML rendering
if it would cause your existing applications to stop functioning properly. For details, see ASP.NET and XHTML.
Cross-Page Posting
As in earlier versions of ASP.NET, Web pages post back to themselves when users click a button or other control that posts.
You can now configure pages to post to another ASP.NET Web page, which is useful for creating multi-page forms. On the
target page, you can get information from the source page, such as the values of controls. For more information, see
Cross-Page Posting in ASP.NET Web Pages.
New Page Life Cycle Stages
In order to accommodate new features, such as master pages and themes, the Page class supports new methods and events
that are available during the life cycle of a page. For example, the Page class now supports a PreInit event that you can use to
set themes or master pages dynamically. For more information, see Page.
Access to the Page Header
You can now access the page header directly from server code. The Page object exposes a Header property that gives you an
easy way to manipulate linked style sheets, the style element, metadata elements, and the page title.
Control Focus
Using new methods on the Page class (SetFocus or on individual controls (Focus), you can manage which control in the
browser has the focus when the page renders. ASP.NET Web pages utilize this new functionality to provide an enhanced
capability for maintaining scroll position after a postback. For details, see How to: Set Focus on ASP.NET Web Server Controls.
Creating Client Script
The methods for injecting client script into a page (for example, RegisterStartupScript) have been moved from the Page class
to a new ClientScriptManager class and have been enhanced. The methods on the Page class are still available for backward
compatibility, but they are deprecated. The new versions of these methods include a parameter that enables you to designate
the type with which the script is associated. This enables you to create separate script blocks for the page and user controls.
For more information, see Programming ASP.NET Web Pages with Client Script.
Browser-Specific Property Filtering
You can now create browser filters for property values. This enables you to specify different property values on the same
control for different browsers. For example, you can specify that the Text property of a Label control has one value for Internet
Explorer and a different value (perhaps a shorter string) for other browsers. You can filter property values based on classes of
browsers (for example, Mozilla-class browsers, Ericksson, or Nokia) or by specific major browser release or major and minor
browser releases (for example, Internet Explorer version 4, or Ericksson P800 and P800R101). For more information, see
ASP.NET for Mobile Devices.
Client Callbacks
You can perform server processing in a page without requiring a full round trip. This enables you to request server-based
information from client script. For more information, see
Implementing Client Callbacks Without Postbacks in ASP.NET Web Pages.
See Also
Concepts
What's New in ASP.NET
What's New in ASP.NET Caching
What's New in ASP.NET Data Access
What's New in the ASP.NET Web Page Model
What's New in ASP.NET State Management
What's New in ASP.NET Tracing
What's New in ASP.NET Configuration
ASP.NET

What's New in the ASP.NET Web Page Model


ASP.NET 2.0 features significant changes in the model for creating ASP.NET Web pages with code-behind files.
ASP.NET version 1.1 supports two models for writing the code for an ASP.NET Web page: the single-file model and the code-
behind model. In the single-file model, the code is inserted into the page in a script block that has the attribute
runat="server". The single-file model continues to be supported in version 2.0.

In the code-behind model, the page's markup is in an .aspx page and the programming code is in a separate file. In version 2.0,
there have been significant improvements to the code-behind model to make it easier to work with and more robust.
Note
For an introduction to the single-file model and code-behind model in the ASP.NET version 2.0, see
ASP.NET Web Page Code Model.

Changes to the Code-Behind Model


In ASP.NET 1.1, a code-behind file for an ASP.NET page defines a class that derives from the Page class. The .aspx page in turn
represents another class that derives from the code-behind class. The code-behind class is a complete class definition; it
contains instance variables for all controls on the page, explicit event binding using delegates, and so on. ASP.NET also
supported a code-behind model that was used primarily in designer-based tools such as Visual Studio 2005.
In the code-behind model for ASP.NET 1.1, the markup for the page is maintained in an .aspx page, and the code is maintained
in a separate class file. The link between the .aspx page and its corresponding class file is made the @ Page directive. A typical
directive looks like the following:
VB
<%@ Page Language="vb" AutoEventWireup="false" Codebehind="SamplePage.aspx.vb" Inherits="Sa
mpleProject.SamplePage"%>

C#
<%@ Page Language="c#" AutoEventWireup="false" Codebehind="SamplePage.aspx.cs" Inherits="Sa
mpleProject.SamplePage"%>

ASP.NET version 1.1 also supports a variant form of the code-behind model in which the Codebehind attribute of the @ Page
directive was replaced with a Src attribute.
Code-Behind Model for ASP.NET version 2.0
The code-behind model for ASP.NET version 2.0 takes advantage of a new language feature known as partial classes. The code-
behind file for a page is not a complete class definition. Instead, it includes only the application code you need, such as event
handlers. The code-behind partial class does not need to include instance variables or explicit event binding. ASP.NET can infer
the control instances and derive event bindings from the markup during compilation.
Note
ASP.NET pages that use Visual Basic as their programming language can use the Handles keyword on methods to explicitly
bind the method to an event; doing so can result in slightly faster performance.

A code-behind file might look like the following:


VB
Partial Class SamplePage
Inherits System.Web.UI.Page
Protected Sub Button1_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles Button1.Click
Label1.Text = "Clicked at " & DateTime.Now.ToString()
End Sub
End Class
C#
using System;
public partial class SamplePage : System.Web.UI.Page
{
protected void Button1_Click(Object sender, EventArgs e)
{
Label1.Text = "Clicked at " + DateTime.Now.ToString();
}
}

The linkage between the .aspx page and the code-behind page is similar to the linkage used with the earlier code-behind
model. However, the @ Page directive uses a new CodeFile attribute instead of the Codebehind or Src attribute. In addition,
the directive also includes an Inherits attribute to specify a class name for the page, as in the following example:
VB
<%@ Page language="VB" CodeFile="SamplePage.aspx.vb"
Inherits="SamplePage" AutoEventWireup="false" %>

C#
<%@ Page language="C#" CodeFile="SamplePage.aspx.cs"
Inherits="SamplePage" AutoEventWireup="true" %>

The new code-behind model uses a different inheritance model than the code-behind model from previous versions. For
details, see ASP.NET Web Page Code Model.
Improvements in the Code-Behind Model
The code-behind model introduced in ASP.NET version 2.0 offers the following improvements over the previous version:
The code-behind file is simpler. It includes only the code you write yourself.
You can include controls on a page without having to explicitly create instance variables for them in the code-behind
class. The code-behind page cannot be out of synch with the controls declared in the markup.
Because event binding can be inferred from the declarative controls, you do not need to explicitly bind delegates in the
reserved InitializeComponent method.
Note
If you are creating controls and adding them to the page programmatically, you must still explicitly create event bindin
gs. The code-behind model creates control instances and event bindings only for controls that are declared in markup.

Better Separation of Code and Content


The new code-behind model makes it easier to separate development of the markup and the code. In the older code-behind
model, it was not practical to add controls in the markup without having access to the code-behind to add the instance variable
at the same time. In the new model, you can create the page layout without needing to have access to the code-behind page.
See Also
Concepts
ASP.NET Web Page Code Model
Visual Web Developer

What's New in Code-Behind Support in Visual Web Developer


This topic describes changes in how single-file and code-behind Web pages are supported in Visual Web Developer, which is
the Web site development tool (Web page designer) that is included with Visual Studio 2005.
In Visual Studio .NET version 2003, the default for writing code was the code-behind model. When you created a new Web
Forms page, Visual Studio created an .aspx page with the markup and a separate .vb or .cs file (the code-behind file) for the
page's code. The code-behind file defined a complete class derived from the Page class.
The Visual Studio Web page designer kept the .aspx page and the code-behind page in synch. For example, if you added a Web
server control to the .aspx page, the designer created a corresponding instance variable in the code-behind page for that
control.
In Visual Studio .NET 2003, the Web page designer offered only limited support for single-file pages. You could edit pages in
the designer, but the full array of designer features was not available unless you were working with code-behind pages.
Changes in Support for Code
In Visual Studio 2005, support for creating the code for your page has been improved. The following table summarizes the
improvements and provides links to more information about each feature.
Feature Description
Improve The code-behind model now uses a partial class that provides a cleaner, more robust way to integrate code with the
d code-b page. For details, see ASP.NET Web Page Code Model.
ehind m
odel.

Support f The designer provides equal support for code-behind and single-file pages, including IntelliSense. For information a
or single bout choosing a model, see ASP.NET Web Page Code Model.
-file page
s.

Dynamic The designer no longer compiles all of the page code into a single assembly on your computer. Instead, by default, t
compilati he pages are compiled dynamically into multiple assemblies on the server when requested. You still have the option
on on ser to precompile your Web site into a layout on your computer and then deploy it to a production server.
ver.
For details, see Deploying ASP.NET Web Sites (Visual Studio).
Note
You can compile a Web site into a set of assemblies that can be deployed without source code or in a format that a
llows limited changes. For more information, see What's New in Publishing Web Sites in Visual Studio.

No desig The new model eliminates the need for the designer to include markup and code that exists only to support the desi
ner-only gner. For example, the designer no longer requires the reserved InitializeComponent() method to remember cont
features. rol state across form loads at design time and to initialize controls for run-time execution. For more information, see
Visual Studio Extensibility Center.

Expande IntelliSense is now supported throughout the designer, including code (both code-behind and single-file pages), mar
d IntelliS kup, directives, and more. For more information, see Using IntelliSense and
ense sup How to: Select Validation Schemas for HTML Editing in Visual Web Developer.
port.

See Also
Concepts
What's New in the ASP.NET Web Page Model
Visual Web Developer

Walkthrough: Creating a Basic Web Page in Visual Web


Developer
This walkthrough provides you with an introduction to Microsoft Visual Web Developer. It guides you through creating a
simple page by using Visual Web Developer, illustrating the basic techniques of creating a new page, adding controls, and
writing code.
Tasks illustrated in this walkthrough include:
Creating a file system Web site.
Familiarizing yourself with Visual Web Developer.
Creating a single-file ASP.NET page in Visual Web Developer.
Adding controls.
Adding event handlers.
Running pages with the Web Servers in Visual Web Developer.
Prerequisites
In order to complete this walkthrough, you will need:
Visual Web Developer
The .NET Framework
Creating a Web Site and Page
In this part of the walkthrough, you will create a Web site and add a new page to it. You will also add HTML text and run the
page in your Web browser.
For this walkthrough, you will create a file system Web site that does not require that you work with Microsoft Internet
Information Services (IIS). Instead, you will create and run your page in the local file system.
A file system Web site is one that stores pages and other files in a folder that you choose somewhere on your local computer.
Other Web site options include a local IIS Web site, which stores your files in a subfolder of the local IIS root (typically,
\Inetpub\Wwwroot\). An FTP site stores files on a remote server that you gain access to across the Internet by using File
Transfer Protocol (FTP). A remote site stores files on a remote server that you can access across a local network. For more
information, see Walkthrough: Editing Web Sites with FTP in Visual Web Developer. Also, Web site files can be stored in a
source control system such as Visual SourceSafe. For more information, see Introducing Source Control.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears, as shown in the following screen shot.
New Web Site dialog box
3. Under Visual Studio installed templates, click ASP.NET Web Site.
When you create a Web site, you specify a template. Each template creates a Web application that contains different files
and folders. In this walkthrough, you are creating a Web site based on the ASP.NET Web Site template, which creates
some folders and a few default files.
4. In the Location box, select the File System box, and then enter the name of the folder where you want to keep the pages
of your Web site.
For example, type the folder name C:\BasicWebSite.
5. In the Language list, click Visual Basic or Visual C#.
The programming language you choose will be the default for your Web site. However, you can use multiple languages
in the same Web application by creating pages and components in different programming languages.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx. When a new page is created, by default
Visual Web Developer displays the page in Source view, where you can see the page's HTML elements. The following
screen shot shows the Source view of a default Web page.
Source view of default page
A Tour of Visual Web Developer
Before you proceed with working on the page, it is useful to familiarize yourself with the Visual Web Developer development
environment. The following illustration shows you the windows and tools that are available in Visual Web Developer.
Diagram of Visual Web Developer environment

To familiarize yourself with the Web designer in Visual Web Developer


Examine the preceding illustration and match the text to the following list, which describes the most commonly used
windows and tools. (Not all windows and tools that you see are listed here, only those marked in the preceding
illustration.)
Toolbars. Provide commands for formatting text, finding text, and so on. Some toolbars are available only when
you are working in Design view.
Solution Explorer. Displays the files and folders in your Web site.
Document window. Displays the documents you are working on in tabbed windows. You can switch between
documents by clicking tabs.
Properties window. Allows you to change settings for the page, HTML elements, controls, and other objects.
View tabs. Present you with different views of the same document. Design view is a near-WYSIWYG editing
surface. Source view is the HTML editor for the page. You will work with these views later in this walkthrough. If
you prefer to open Web pages in Design view, on the Tools menu, click Options, select the HTML Designer
node, and change the Start Pages In option.
Toolbox. Provides controls and HTML elements that you can drag onto your page. Toolbox elements are grouped
by common function.
Server Explorer/Database Explorer. Displays database connections. If Server Explorer is not visible in Visual Web
Developer, on the View menu, click Other Windows, and then click Server Explorer.
Note
You can rearrange and resize the windows to suit your preferences. The View menu allows you to display addit
ional windows.

Creating a New Web Forms Page


When you create a new Web site, Visual Web Developer adds an ASP.NET page (Web Forms page) named Default.aspx. You
can use the Default.aspx page as the home page for your Web site. However, for this walkthrough, you will create and work
with a new page.
To add a page to the Web site
1. Close the Default.aspx page. To do this, right-click the tab containing the file name and select Close.
2. In Solution Explorer, right-click the Web site (for example, C:\BasicWebSite), and then click Add New Item.
3. Under Visual Studio installed templates, click Web Form.
4. In the Name box, type FirstWebPage.
5. In the Language list, choose the programming language you prefer to use (Visual Basic, C#, or J#).
When you created the Web site, you specified a default language. However, each time you create a new page or
component for your Web site, you can change the language from the default. You can use different programming
languages in the same Web site.
6. Clear the Place code in separate file check box. The following screen shot shows the Add New Item dialog box.
Add New Item dialog box

In this walkthrough, you are creating a single-file page with the code and HTML in the same page. The code for ASP.NET
pages can be located either in the page or in a separate class file. To learn more about keeping the code in a separate file,
see Walkthrough: Creating a Basic Web Page with Code Separation in Visual Web Developer.
7. Click Add.
Visual Web Developer creates the new page and opens it in Source view.
Adding HTML to the Page
In this part of the walkthrough, you will add some static text to the page.
To add text to the page
1. At the bottom of the document window, click the Design tab to switch to Design view.
Design view displays the page that you are working on in a WYSIWYG-like way. At this point, you do not have any text or
controls on the page, so the page is blank.
2. On the page, type Welcome to Visual Web Developer.
The following screen shot shows the text you typed in Design view.
Welcome text as seen in Design view

3. Switch to Source view.


You can see the HTML that you created by typing in Design view, as shown in the following screen shot.
Welcome text as seen in Source view

Running the Page


Before you proceed with adding controls to the page, you can try running it. To run a page, you need a Web server. In a
production Web site, you use IIS as your Web server. However, to test a page, you can use the ASP.NET Development Server,
which runs locally and does not require IIS. For file system Web sites, the default Web server in Visual Web Developer is the
ASP.NET Development Server.
To run the page
1. Press CTRL+F5 to run the page.
Visual Web Developer starts the ASP.NET Development Server. An icon appears on the toolbar to indicate that the Visual
Web Developer Web server is running, as shown in the following screen shot.
Visual Web Developer Web server icon

The page is displayed in the browser. Although the page you created has an extension of .aspx, it currently runs like any
HTML page.
Note
If the browser displays a 502 error or an error indicating that the page cannot be displayed, you might need to configur
e your browser to bypass proxy servers for local requests. For details, see
How to: Bypass a Proxy Server for Local Web Requests.

2. Close the browser.


Adding and Programming Controls
In this part of the walkthrough, you will add a Button, a TextBox, and a Label control to the page and write code to handle the
Click event for the Button control.
You will now add server controls to the page. Server controls, which include buttons, labels, text boxes, and other familiar
controls, provide typical form-processing capabilities for your ASP.NET Web pages. However, you can program the controls
with code that runs on the server, not the client.
To add controls to the page
1. Click the Design tab to switch to Design view.
2. Press SHIFT+ENTER a few times to make some room.
3. In the Toolbox, from the Standard group, drag three controls onto the page: a TextBox control, a Button control, and a
Label control.
4. Put the insertion point above the TextBox control, and then type Enter your name:.
This static HTML text is the caption for the TextBox control. You can mix static HTML and server controls on the same
page. The following screen shot shows how the three controls appear in Design view.
Controls in Design View

Setting Control Properties


Visual Web Developer offers you various ways to set the properties of controls on the page. In this part of the walkthrough,
you will set properties in both Design view and Source view.
To set control properties
1. Select the Button control, and then in the Properties window, set Text to Display Name, as shown in the following
screen shot.
Changed Button control text

2. Switch to Source view.


Source view displays the HTML for the page, including the elements that Visual Web Developer has created for the server
controls. Controls are declared using HTML-like syntax, except that the tags use the prefix asp: and include the attribute
runat="server".
Control properties are declared as attributes. For example, when you set the Text property for the Button control, in step
1, you were actually setting the Text attribute in the control's markup.
Note that all the controls are inside a <form> element, which also has the attribute runat="server". The
runat="server" attribute and the asp: prefix for control tags mark the controls so that they are processed by ASP.NET
on the server side when the page runs. Code outside of <form runat="server"> and <script runat="server">
elements is interpreted by the browser as client-side code, which is why the ASP.NET code must be inside.
3. Put the insertion point in a space within the <asp:label> tag, and then press SPACEBAR.
A drop-down list appears that displays the list of properties you can set for a Label control. This feature, referred to as
IntelliSense, helps you in Source view with the syntax of server controls, HTML elements, and other items on the page.
The following screen shot shows the IntelliSense drop-down list for the Label control.
IntelliSense for Label control

4. Select ForeColor and then type an equal sign (=). IntelliSense displays a list of colors.
Note
You can display an IntelliSense drop-down list at any time by pressing CTRL+J.

5. Select a color for the Label control's text.


The ForeColor attribute is completed with the color that you have selected.
Programming the Button Control
For this walkthrough, you will write code that reads the name that the user enters into the text box and then displays the name
in the Label control.
To add a default button event handler
1. Switch to Design view.
2. Double-click the Button control.
Visual Web Developer switches to Source view and creates a skeleton event handler for the Button control's default
event, the Click event.
Note
Double-clicking a control in Design view is just one of several ways you can create event handlers.

3. Inside the handler, type the following:


Label1.
Visual Web Developer displays a list of available members for the Label control, as shown in the following screen shot.
Available Label control members

4. Finish the Click event handler for the button so that it reads as shown in the following code example.
VB
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Label1.Text = Textbox1.Text & ", welcome to Visual Web Developer!"
End Sub

C#
protected void Button1_Click(object sender, System.EventArgs e)
{
Label1.Text = TextBox1.Text + ", welcome to Visual Web Developer!";
}

5. Scroll down to the <asp:Button> element. Note that the <asp:Button> element now has the attribute
OnClick="Button1_Click". This attribute binds the button's Click event to the handler method you coded in step 4.
Event handler methods can have any name; the name you see is the default name created by Visual Web Developer. The
important point is that the name used for the OnClick attribute must match the name of a method in the page.
Note
If you are using Visual Basic with code separation, Visual Web Developer does not add an explicit OnClick attribute. Ins
tead, the event is bound to the handler method using a Handles keyword on the handler declaration itself.

Running the Page


You can now test the server controls on the page.
To run the page
1. Press CTRL+F5 to run the page in the browser.
The page again runs using the ASP.NET Development Server.
2. Enter a name into the text box and click the button.
The name you entered is displayed in the Label control. Note that when you click the button, the page is posted to the
Web server. ASP.NET then recreates the page, runs your code (in this case, the Button control's Click event handler
runs), and then sends the new page to the browser. If you watch the status bar in the browser, you can see that the page
is making a round trip to the Web server each time you click the button.
3. In the browser, view the source of the page you are running.
In the page source code, you see only ordinary HTML; you do not see the <asp:> elements that you were working with in
Source view. When the page runs, ASP.NET processes the server controls and renders HTML elements to the page that
perform the functions that represent the control. For example, the <asp:Button> control is rendered as the HTML
element <input type="submit">.
4. Close the browser.
Working with Additional Controls
In this part of the walkthrough, you will work with the Calendar control, which displays dates a month at a time. The Calendar
control is a more complex control than the button, text box, and label you have been working with and illustrates some further
capabilities of server controls.
In this section, you will add a Calendar control to the page and format it.
To add a Calendar control
1. In Visual Web Developer, switch to Design view.
2. From the Standard section of the Toolbox, drag a Calendar control onto the page:
The calendar's smart tag panel is displayed. The panel displays commands that make it easy for you to perform the most
common tasks for the selected control. The following screen shot shows the Calendar control as rendered in the Design
view.
Calendar control in Design view
3. In the smart tag panel, choose Auto Format.
The Auto Format dialog box is displayed, which allows you to select a formatting scheme for the calendar. The following
screen shot shows the Auto Format dialog box for the Calendar control.
Auto Format dialog box for the Calendar control

4. From the Select a scheme list, select Simple and then click OK.
5. Switch to Source view.
You can see the <asp:Calendar> element. This element is much longer than the elements for the simple controls you
created earlier. It also includes subelements, such as <WeekEndDayStyle>, which represent various formatting settings.
The following screen shot shows the Calendar control in Source view.
Calendar control in Source view
Programming the Calendar Control
In this section, you will program the Calendar control to display the currently selected date.
To program the Calendar control
1. From the left-hand drop-down list at the top of Source view, select Calendar1.
The drop-down list displays a list of all the objects you can write code for.
2. From the right-hand drop-down list, select SelectionChanged.
Visual Web Developer creates a skeleton event handler for the Calendar control's SelectionChanged event.
You have now seen two ways to create an event handler for a control. The first was to double-click the control in Design
view. The second is to use the drop-down lists in Source view to select an object and the event to write code for.
3. Finish the SelectionChanged event handler with the following highlighted code.
VB
Protected Sub Calendar1_SelectionChanged(ByVal sender As Object, ByVal e As System.Eve
ntArgs)
Label1.Text = Calendar1.SelectedDate.ToString()
End Sub

C#
protected void Calendar1_SelectionChanged(object sender, System.EventArgs e)
{
Label1.Text = Calendar1.SelectedDate.ToString();
}

Running the Page


You can now test the calendar.
To run the page
1. Press CTRL+F5 to run the page in the browser.
2. Click a date in the calendar.
The date you clicked is displayed in the Label control.
3. In the browser, view the source code for the page.
Note that the Calendar control has been rendered to the page as a table, with each day as a <td> element containing an
<a> element.
4. Close the browser.
Next Steps
This walkthrough has illustrated the basic features of the Visual Web Developer page designer. Now that you understand how
to create and edit a Web page in Visual Web Developer, you might want to explore other features. For example, you might
want to:
Learn more about how to edit HTML in Visual Web Developer. For details, see
Walkthrough: Basic HTML Editing in Visual Web Developer.
Add data access to Web pages. For details, see Walkthrough: Basic Data Access in Web Pages.
Learn about the debugger for Web pages. For details, see Walkthrough: Debugging Web Pages in Visual Web Developer.
Create Web pages that are specifically designed for mobile phones and other devices. For details, see
Walkthrough: Creating Web Pages for Mobile Devices.
Create a consistent site layout using master pages. For details, see
Walkthrough: Creating and Using ASP.NET Master Pages in Visual Web Developer.
Add navigation to your site so users can easily move between pages. For details, see
Walkthrough: Adding Site Navigation to a Web Site.
See Also
Tasks
Walkthrough: Creating a Local IIS Web Site in Visual Web Developer
Walkthrough: Editing Web Sites with FTP in Visual Web Developer
Concepts
Introduction to Visual Web Developer
Other Resources
Welcome
Visual Web Developer

Walkthrough: Creating a Basic Web Page with Code Separation


in Visual Web Developer
When you create ASP.NET Web pages and write code in them, you can choose from two models for how to manage the visible
elements (controls, text) and your programming code. In the single-file model, the visible elements and code are kept together
in the same file. In the alternative model, called "code separation," the visible elements are in one file and the code is in another
file, referred to as the "code-behind" file. This walkthrough introduces you to Web pages that use code separation.
The single-file model is introduced in Walkthrough: Creating a Basic Web Page in Visual Web Developer. The walkthrough you
are reading now shows you how to create a Web page with the same functionality as the page in the single-file walkthrough,
but with a focus on using code separation.
The choice between using single-file pages and pages with code separation is primarily one of convenience and personal
preference. Working with both models in Microsoft Visual Web Developer is similar; both models have approximately equal
support in the editor. Both models have equivalent performance when the page runs. The page with code separation makes it
more practical to let a Web designer work on the layout of a page while a programmer creates the code for the page, because
the two pages can be edited separately. For more information on the differences between these models, see
ASP.NET Web Page Code Model.
Tasks illustrated in this walkthrough include:
Using Visual Web Developer to create an ASP.NET page with code separation.
Adding controls.
Adding event handlers.
Running pages with the ASP.NET Development Server.
Prerequisites
In order to complete this walkthrough, you will need:
Visual Web Developer and the .NET Framework.
Creating a Web Site and Page
In this part of the walkthrough, you will create a Web site and add a new page to it. You will also add HTML text and run the
page in your Web browser.
If you have already created a Web site in Visual Web Developer (for example, by following the steps in
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and skip to "Creating a New
Page" later in this walkthrough. Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, select File System and enter the name of the folder where you want to keep the pages of your Web
site.
For example, type the folder name C:\BasicWebSite.
5. In the Language list, click Visual Basic or Visual C#.
Note
Visual Web Developer currently does not support creating code-behind pages in Visual J#.

The programming language you choose will be the default for your Web site, but you can set the programming language
for each page individually.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Creating a New Page
When you create a new Web site, Visual Web Developer adds a page named Default.aspx. By default, Visual Web Developer
creates a page with code separation.
To add a page with code separation to the Web site
1. Close the Default.aspx page. To do this, right-click the tab with the file name in it and select Close.
2. In Solution Explorer, right-click the Web site (for example, C:\WebSites) and choose Add New Item.
3. Under Visual Studio installed templates, choose Web Form.
4. In the Name box, type WebPageSeparated.
5. From the Language list, choose the programming language you prefer to use (Visual Basic or C#).
6. Verify that the Place code in separate file check box is selected.
By default, this check box is selected.
7. Click Add.
Visual Web Developer creates two files. The first file, WebPageSeparated.aspx, will contain the page's text and controls,
and is opened in the editor. A second file, WebPageSeparated.aspx.vb or WebPageSeparated.aspx.cs (depending on what
programming language you selected), is the code file. You can see both files in Solution Explorer by clicking the plus sign
(+) next to the WebPageSeparated.aspx file; the code file has been created but is not open. You will open it later in the
walkthrough when you write code.
Adding HTML to the Page
In this part of the walkthrough, you will add some static HTML text to the WebPageSeparated.aspx page.
To add text to the page
1. Click the Design tab at the bottom of the document window to switch to Design view.
Design view displays the page you are working on in a WYSIWYG-like way. At this point, you do not have any text or
controls on the page, so the page is blank.
2. Type the words Welcome to Visual Web Developer Using Code Separation.
3. Switch to Source view.
You can see the HTML that you created by typing in Design view. At this stage, the page looks like an ordinary HTML
page. The only difference is in the <%@ page %> directive at the top of the page.
Adding and Programming Controls
In this part of the walkthrough, you will add a button, text box, and label control to the page and write code to handle the
button's Click event. Server controls, which include buttons, labels, text boxes, and other familiar controls, provide typical form-
processing capabilities for your ASP.NET Web pages. However, you can program the controls with code that runs on the server,
not the client.
To add controls to the page
1. Click the Design tab to switch to Design view.
2. Press ENTER a few times to make some room.
3. From the Standard group in the Toolbox, drag three controls onto the page: a TextBox control, a Button control, and a
Label control.
4. Put the insertion pointer in front of the text box and type Enter your name:.
This static HTML text is the caption for the TextBox control. You can mix static HTML and server controls on the same
page.
Setting Control Properties
Visual Web Developer offers you various ways to set the properties of controls on the page. In this part of the walkthrough,
you will work with properties in both Design view and Source view.
To set control properties
1. Select the Button control and, in the Properties window, set its Text property to Display Name.
2. Switch to Source view.
Source view displays the HTML for the page, including the elements that Visual Web Developer has created for the server
controls. Controls are declared using HTML-like syntax, except that the tags use the prefix asp: and include the attribute
runat="server".
Control properties are declared as attributes. For example, when you set the button's Text property in Step 1, you were
actually setting the Text attribute in the control's markup.
Note that all the controls are inside a <form> element that also has the attribute runat="server". The runat="server"
attribute and the asp: prefix for control tags mark the controls so that they are processed by ASP.NET when the page
runs.
Programming the Button Control
For this walkthrough, you will write code that reads the name that the user enters in the text box and then displays it in the
Label control.
To add a default button event handler
1. Switch to Design view
2. Double-click the Button control.
Visual Web Developer opens the WebPageSeparated.aspx.vb or WebPageSeparated.aspx.cs file in a separate window in
the editor. The file contains a skeleton Click event handler for the button.
3. Complete the Click event handler by adding the following highlighted code.
VB
Protected Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Label1.Text = Textbox1.Text & ", welcome to Visual Web Developer!"
End Sub

C#
protected void Button1_Click(object sender, System.EventArgs e)
{
Label1.Text = TextBox1.Text + ", welcome to Visual Web Developer!";
}

Notice that as you type, IntelliSense helps you with context-sensitive choices. This is identical to the behavior when you
are coding in a single-file page.
Examining the Page and Code File
You now have two files that make up the complete WebPageSeparated page: WebPageSeparated.aspx and
WebPageSeparated.aspx.vb or WebPageSeparated.aspx.cs. In this section of the walkthrough, you will examine how these files
are structured and how they relate to each other.
To examine the page and code file
1. Click the WebPageSeparated.aspx tab at the top of the editor window to switch to the page file.
2. Switch to Source view.
At the top of the page is an @ page directive that binds this page to the code file. The directive looks like the following
code.
VB
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="WebPageSeparated.aspx.vb" Inh
erits="WebPageSeparated" %>

C#
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="WebPageSeparated.aspx.cs" Inhe
rits="WebPageSeparated" %>

(The line does not wrap in the editor, and the language attribute and file name extensions will match the programming
language you selected.)
When the page runs, ASP.NET dynamically creates an instance of a class representing the page. The Inherits attribute
identifies the class defined in the code-behind file from which the .aspx page is derived. By default, Visual Web Developer
uses the page name as the basis for the class name in the code-behind file.
The CodeFile attribute identifies the code file for this page. In simple terms, the code-behind file contains the event-
handling code for your page.
3. Click the WebPageSeparated.aspx.vb or WebPageSeparated.aspx.cs tab to switch to the code file.
The code file contains code that is similar to a class definition. However, it is not a complete class definition; instead, it is a
"partial class" that contains only a portion of the complete class that will make up the page. Specifically, the partial class
defined in the code file contains the event handlers and other custom code that you write. At run time, ASP.NET
generates another partial class containing your user code. This complete class is then used as the base class that is used
to render the page. For more information, see ASP.NET Page Class Overview.
Note
If you are familiar with the code-behind model used in Microsoft Visual Studio .NET 2003, you will notice that in the ne
w model, the code-behind class does not contain any generated code beyond the class definition itself. For example, th
e class does not contain instance variables for controls on the page. This type of generated code is no longer required.

Running the Page


You can now test the page.
To run the page
1. Press CTRL+F5 to run the page in the browser.
The page runs using the ASP.NET Development Server.
Note
If the browser displays a 502 error or an error indicating that the page cannot be displayed, you might need to configur
e your browser to bypass proxy servers for local requests. For details, see
How to: Bypass a Proxy Server for Local Web Requests.

2. Enter a name in the text box and click the button.


The name you entered is displayed in the Label control.
3. In the browser, view the source of the page you are running.
4. Close the browser.
The page works exactly the same as it would if it were a single-file page. (If you followed the steps in
Walkthrough: Creating a Basic Web Page in Visual Web Developer to create a single-file page, you can compare the two
pages to see that they are the same when running.)
Next Steps
This walkthrough has illustrated how to create and edit a Web page that uses code separation. From the perspective of creating
and running the page, there is not a significant difference between a single-file page and a page with code separation.
You might want to explore other features. For example, you might want to:
Create different types of Web sites. In addition to creating a file-system Web site as you did in this walkthrough, you can
work with Web sites using Microsoft Internet Information Services (IIS), SharePoint, and FTP. For details, see
Types of Web Sites in Visual Web Developer.
Learn more about how to edit HTML in Visual Web Developer. For details, see
Walkthrough: Basic HTML Editing in Visual Web Developer.
Add data access to Web pages. For details, see Walkthrough: Basic Data Access in Web Pages.
Learn about the debugger for Web pages. For details, see Walkthrough: Debugging Web Pages in Visual Web Developer.
Create a consistent site layout using master pages. For details, see
Walkthrough: Creating and Using ASP.NET Master Pages in Visual Web Developer.
See Also
Tasks
Walkthrough: Creating a Basic Web Page in Visual Web Developer
Concepts
Types of Web Sites in Visual Web Developer
Visual Web Developer

Walkthrough: Code Editing in Web Pages in Visual Web


Developer
Many ASP.NET Web pages involve writing code in Visual Basic, C#, or another language. The code editor in the Microsoft Visual
Web Developer Web site development tool can help you write code quickly while helping you avoid errors. In addition, the
editor provides ways for you to create reusable code to help reduce the amount of work you need to do.
This walkthrough illustrates various features of the code editor. Some of the features of the code editor depend on what
language you are coding in. Therefore, in this walkthrough you will create two pages, one that uses Visual Basic as its
programming language and another that uses C#.
During this walkthrough, you will learn how to:
Correct errors (in Visual Basic).
Refactor and rename code (in C#).
Rename symbols.
Insert code snippets (in Visual Basic and C#).
Prerequisites
In order to complete this walkthrough, you will need:
A general understanding of working in Visual Web Developer.
For an introduction to Visual Web Developer, see Walkthrough: Creating a Basic Web Page in Visual Web Developer.
Creating the Web Site and Page
If you have already created a Web site in Visual Web Developer (for example, by following the steps in
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and skip to the next section.
Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, point to New, and then click Web Site.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, select File System, and then enter the name of the folder where you want to keep the pages of your
Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click Visual Basic.
Note
Visual Web Developer currently does not support creating code-behind pages in the Microsoft Visual J# development t
ool.

The programming language you choose will be the default for your Web site, but you can set the programming language
for each page individually.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Correcting Errors in Visual Basic
The code editor in Visual Web Developer helps you to avoid errors as you code, and if you have made an error, the code editor
helps you to correct the error. In this part of the walkthrough, you will write a few lines of code that illustrate the error
correction features in the editor.
The behavior of the code editor depends on which language you are coding in. In general, the code editor for Microsoft Visual
Basic 2005 provides more detailed error information as you code.
To test error correction in Visual Basic
1. In Design view, double-click the blank page to create a handler for the Load event for the page.
You are using the event handler only as a place to write some code.
2. Inside the handler, type the following line that contains an error:

dim var1 as inger

When you press ENTER, the code editor underlines the word inger, indicating that the word is not recognized. Note that
part of the underline is a small underscore.
3. Hold the mouse pointer over the word inger to see a ToolTip that tells you what the error is.
4. Hold the mouse pointer over the underscore in the underline.
The underscore expands into an icon.
5. Click the icon.
A list of possible corrections for the word inger is displayed.
6. Select Change 'inger' to Integer.
Refactoring and Renaming in C#
Refactoring is a software methodology that involves restructuring your code to make it easier to understand and to maintain,
while preserving its functionality. A simple example might be that you write code in an event handler to get data from a
database. As you develop your page, you discover that you need to access the data from several different handlers. Therefore,
you refactor the page's code by creating a data-access function in the page and inserting calls to the function in the handlers.
The code editor includes tools to help you perform various refactoring tasks. In this walkthrough, you will work with two
refactoring techniques: renaming symbols and extracting a method. Other refactoring options include encapsulating fields,
promoting local variables to method parameters, and managing method parameters. The availability of these refactoring
options depends upon the location in the code. For example, if you highlight code that is not a field declaration, you can not
select the Encapsulate Field option. If you highlight a variable in an event method, you can not select Promote Local
Variable to Parameter because event handler signatures are constant.
Refactoring Code
A common refactoring scenario is to create (extract) a method from code that is inside another member. This reduces the size
of the original member and makes the extracted code reusable.
In this part of the walkthrough, you will write some simple code, and then extract a method from it. Refactoring is supported
for C#, so you will create a page that uses C# as its programming language.
To create a C# page
1. In Solution Explorer, right-click the name of your Web site, and then click Add New Item.
2. Under Visual Studio installed templates, click Web Form.
3. In the Language list, click C#.
Note
You can leave the name Default2.aspx.

4. Click Add to create and open the new page.

To extract a method in a C# page


1. Switch to Design view.
2. In the Toolbox, from the Standard group, drag a Button control onto the page.
3. Double-click the Button control to create a handler for its Click event, and then add the following highlighted code.
C#
protected void Button1_Click(object sender, EventArgs e)
{
System.Collections.ArrayList alist =
new System.Collections.ArrayList();
int i;
string arrayValue;
for(i=0; i<5; i++)
{
arrayValue = "i = " + i.ToString();
alist.Add(arrayValue);
}
for(i=0; i<alist.Count; i++)
{
Response.Write("<br>" + alist[i]);
}
}

The code creates an ArrayList object, uses a loop to load it with values, and then uses another loop to display the contents
of the ArrayList object.
4. Press CTRL+F5 to run the page, and then click the Button control to be sure that you see the following output:

i = 0
i = 1
i = 2
i = 3
i = 4

5. Return to the code editor, and then select the following lines in the event handler.
C#

for(i=0; i<alist.Count; i++)


{
Response.Write("<br>" + alist[i]);
}

6. Right-click the selection, click Refactor, and then choose Extract Method.
The Extract Method dialog box appears.
7. In the New Method Name box, type DisplayArray, and then click OK.
The code editor creates a new method named DisplayArray, and puts a call to the new method in the Click handler
where the loop was originally.
C#
protected void Button1_Click(object sender, EventArgs e)
{
System.Collections.ArrayList alist =
new System.Collections.ArrayList();
int i;
string arrayValue;
for(i=0; i<5; i++)
{
arrayValue = "i = " + i.ToString();
alist.Add(arrayValue);
}
i = DisplayArray(alist, i);
}

8. Press CTRL+F5 to run the page again, and click the Button control.
The page functions the same as it did before.
Renaming Symbols
When working with variables and objects (both are also known as symbols), you might want to be able to rename the symbols
after they are already referenced in your code. However, renaming the symbol can potentially cause the code to break if you
miss renaming one of the references to the symbol. Therefore, you can use refactoring to perform the renaming.
To use refactoring to rename symbols
1. In the Click event handler, locate the following line:
C#
System.Collections.ArrayList alist =
new System.Collections.ArrayList;

2. Right-click the variable name alist, choose Refactor, and choose Rename.
The Rename dialog box appears.
3. In the New name box, type ArrayList1, and then press ENTER.
The Preview Changes dialog box appears, and displays a tree containing all references to the symbol that you are
renaming.
4. Click Apply to close the Preview Changes dialog box.
The variables that refer specifically to the instance that you selected are renamed. Note, however, that the variable alist
in the following line is not renamed.
C#
private int DisplayArray(System.Collections.ArrayList alist,
int i)

The variable alist in this line is not renamed because it does not represent the same value as the specific variable alist
that you renamed. The variable alist in the DisplayArray declaration is a local variable for that method. This illustrates
that using refactoring to rename symbols is different than simply performing a find-and-replace action in the editor;
refactoring renames symbols with knowledge of the semantics of the symbol that it is working with.
Inserting Snippets
Because there are many coding tasks that Web page developers frequently need to perform, the code editor provides a library
of snippets, or blocks of prewritten code. You can insert these snippets into your page.
Each Visual Studio language has slight differences in the way you insert code snippets. For information on inserting snippets in
Visual Basic, see How to: Insert Snippets Into Your Code (Visual Basic). For information on inserting snippets in Visual J# and
Visual C#, see How to: Use Code Snippets (C#).
Next Steps
This walkthrough has illustrated the basic IntelliSense features of the Visual Studio IDE for correcting errors in your code,
refactoring code, renaming symbols, and inserting code snippets into your code. There is more to these IntelliSense features
that make application development fast and easy. For example, you might want to:
Learn more about the features of IntelliSense, such as modifying IntelliSense options, managing code snippets, and
searching for code snippets online. For more information, see Using IntelliSense.
Learn how to create your own code snippets. For more information, see Creating and Using IntelliSense Code Snippets.
Learn more about the Visual Basic-specific features of IntelliSense code snippets, such as customizing the snippets and
troubleshooting. For more information, see Visual Basic IntelliSense Code Snippets.
Learn more about the C#-specific features of IntelliSense, such as refactoring and code snippets. For more information,
see Visual C# Code Editor Features.
See Also
Concepts
Visual Basic IntelliSense Code Snippets
Refactoring
Code Snippets (C#)
Other Resources
Editing Text, Code, and Markup
Using IntelliSense
Visual Web Developer

How to: Add ASP.NET Web Pages to a Web Site (Visual Studio)
You can add new and existing Web pages to a Web site. For information about creating an ASP.NET Web site, see
How to: Create File System Web Sites.
Web sites in Visual Studio are directory based. When you open a Web site, Visual Studio treats all of the files in the folder you
open — whether the files are in the file system, in an Internet Information Services (IIS) application, or on an FTP site — as part
of the same Web site.
To add a new ASP.NET Web page to a Web site
1. In Solution Explorer, right-click the project name, and then click Add New Item.
2. In the Add New Item dialog box, under Visual Studio installed templates, click Web Form.
3. In the Language list, select the programming language that you want to use for the new Web page.
Note
You can create pages with different programming languages in the same Web site.

4. If you want the code for the page to be in a separate file, be sure that the Place code in separate file check box is
selected. If you want to keep the code and markup in the same file, clear this check box.
5. In the Name box, type a name for the new Web page, and then click Add.
The new ASP.NET Web page is created and displayed in the Visual Web Developer.
To add an existing ASP.NET Web page to a Web site project
1. In Solution Explorer, right-click the project name, and then click Add Existing Item.
2. In the Add Existing Item dialog box, navigate to the directory containing the Web page that you want to add, select the
page, and then click Open.
The ASP.NET Web page is added to the Web site project.
Note
When you add an existing file to a Web site, the file is copied to your project not added by reference. Thus, if you chang
e the file in your project, the original file is left unchanged.

Changing the Name of ASP.NET Web Pages


After creating a new ASP.NET Web page or adding an existing page to a Web site project, you might want to change the name
of the page file. You can easily rename pages in Solution Explorer.
To change the name of an ASP.NET Web page using Solution Explorer
1. In Solution Explorer, right-click the file that you want to change and then click Rename.
2. Type the new file name that you want and then press ENTER.
Note
If the code for the page is in a separate file, Visual Studio renames the code file as well and changes the @ Page directiv
e in the .aspx page to match the renamed code file.

See Also
Concepts
Web Pages and Projects
Visual Web Developer

Testing Web Pages in Visual Web Developer


Visual Web Developer provides you with a variety of ways to test Web pages as you are developing them. You have the
following choices:
Run the Web site with debugging This option runs the Web site in the browser and allows you to perform ordinary
debugging tasks such as stepping through code and stopping at breakpoints.
Run the Web site without debugging This option runs the Web site in the browser without using the debugger. It
approximates the experience that the user will have.
View individual pages in a browser This option runs a selected page in the browser. Debugging breakpoints are not
in effect even if debugging is enabled.
Browser Options
By default, Visual Studio 2005 uses Internet Explorer 6 to test pages in all of the above situations. If you want to test pages
using a different browser, you can right-click the page in Solution Explorer and then click Browse With. A dialog box opens
where you can select a browser from the Browsers list, add new browsers to the list, and set the one you select as the default
browser. The default browser will then be used when you choose to run the Web site with or without debugging, or to view an
individual file in the browser.
Build Options
By default, Visual Web Developer builds the Web site when you run a page. This helps you find compile-time errors before the
page is displayed in the browser. You can set options to specify whether you want to build the entire site, the current page, or
not build at all.
For more information, see How to: Test Web Pages in Visual Web Developer and Building Web Sites.
Running with a Startup Page
By default, when you run a Web site, Visual Web Developer runs the page that is currently open. However, in some cases you
might always want to start your Web site with a specific page. For example, your Web site might have a home page where
users make a selection that is required for other pages in the site. In this case, you can configure your Web site to first display
the home page when you test so that you begin at the correct point in the application. Setting a start page also allows you to
specify what Visual Web Developer should do if you run a non-executable page such as Web.config.
To specify a start page, right-click the page in Solution Explorer and then click Set As Start Page.
Note
Setting a start page in Visual Web Developer affects only your testing. It does not set the start page for the Web site when it i
s published. To specify a default page for your Web site, use Internet Information Services (IIS) Manager to enable a default d
ocument in a Web site or virtual directory, and then select the page that you want. For more information, see the topic "Settin
g Up Default Documents" in the IIS Operations Guide.

Running on a Specific Web Server


When you run a page, Visual Web Developer launches the Web server, launches the browser, and loads the specified page into
the browser. In effect, Visual Web Developer passes the URL of the current page to the Web server and runs the page as if it
had been requested using that URL.
The Web server that is used to run the page depends on the type of Web site you are working with:
For File system Web sites, Visual Web Developer launches its own Web server and runs the page locally. However, you
can also specify a start URL that indicates the URL to use when testing a Web page. This is useful if the file system Web
site is on another computer — for example, if you are accessing the site using a mapped drive — and you want to test
the page using IIS on the other computer. For more information about the ASP.NET Development Server, see
Web Servers in Visual Web Developer.
For local IIS and remote IIS sites, Visual Web Developer runs the page in the corresponding instance of IIS. For example,
for a local IIS site, the page runs in your local copy of IIS. For more information, see
Web Servers in Visual Web Developer.
For FTP-deployed Web sites, Visual Web Developer runs the page using the start URL that you provide as part of the FTP
Web site properties. If you have not provided one, Visual Web Developer prompts you for the start URL when it is
required. For more information, see FTP-Deployed Web Sites.
In the case of a remote Web site or an FTP site, the remote computer must be running the .NET Framework version 2.0,
because the page is running in the context of the remote server.
Running with the Debugger
Running your page with the debugger enables you to perform ordinary debugging tasks, such as stepping through code and
stopping at breakpoints. For more information, see ASP.NET Debugging Overview.
Running with the debugger requires the following:
The page or Web site must be configured to enable debugging, which causes the page to be compiled with extra
information (debugging symbols) that the debugger requires. Visual Web Developer checks to see if debugging is
enabled, and if not, it sets the compilation options in the local Web.config file to include debugging, creating the
Web.config file if necessary.
The Web server must be configured with adequate permissions to allow the current user account to debug. If you are
debugging a page running under IIS 6.0, you must be an administrator on the computer. If that is not practical, you can
use the ASP.NET Development Server to debug applications without special permissions. For details, see
Web Servers in Visual Web Developer and How to: Specify the Web Server for Web Sites.
If these conditions cannot be met, you can run the page in Visual Web Developer without enabling debugging.
Note
You should configure your pages or Web site to run without debugging before you deploy the site to a production server. De
bugging options add overhead to the page and can affect server performance.

See Also
Tasks
How to: Test Web Pages in Visual Web Developer
Visual Web Developer

How to: Test Web Pages in Visual Web Developer


While creating pages and Web sites in Visual Web Developer, you can run pages to test them. For more information, see
Testing Web Pages in Visual Web Developer.
To run a Web page in order to test it
Perform one of the actions listed in the following table. All of the actions run the specified page in the default browser.
To Do this
Run the current page or startup page in the debugger. For information ab On the Debug menu, click Start, or press F5.
out the startup page, see
How to: Specify Start Pages for Testing Web Sites in Visual Web Developer If the page or the Web site has not previously been c
. onfigured to enable debugging, Visual Studio promp
ts you to enable debugging. If you choose not to ena
ble debugging, the page runs in the default browser
but does not allow you to attach a debugger to it.
Note
Before publishing a Web site, you should disable de
bugging because it adds overhead to performance a
nd in the event of an error might display informatio
n to the user that you do not want to show. For deta
ils, see
How to: Enable Debugging for ASP.NET Applications

Run the current page or startup page without the debugger. For informati On the Debug menu, click Start Without Debuggi
on about the startup page, see ng, or press CTRL+F5.
How to: Specify Start Pages for Testing Web Sites in Visual Web Developer
.

Run the current page in a browser instance inside of Visual Studio. Right-click a blank area of the page and then click Vi
ew in Browser.
Note
The View in Browser command is not available fo
r files that do not render in a browser (such as the
Web.config file).

Testing with an Alternate Browser


When you run a page, Visual Studio invokes the current default browser. You can also test a page using an alternate browser, as
described in the following procedure.
To test a Web page with an alternate browser
1. In Solution Explorer, right-click the page you that want to test and then click Browse With.
2. In the Browse With dialog box, select an alternate browser.
3. If the browser that you want to use is not listed, click Add, type the name of or browse to the alternate browser program, and
then click OK.
Note
You can set the alternate browser as the default browser for Visual Studio by clicking Set as Default. This sets the default br
owser only for testing Web pages in the current Web site. It does not affect the default browser setting in Windows.

4. When you have selected a browser, click Browse.


Setting Build Options for Testing a Page
Visual Studio can build the current page or the entire Web site when you run a page. This helps you find compile-time errors before
the page appears in the browser. You can set options to specify whether you want to build the entire site, the current page, or to not
build at all.
To specify build behavior when running a page
1. In Solution Explorer, right-click the name of the Web site that you want to run, and then click Property Pages.
2. Click the Build tab.
3. In the Before running the startup page list, select the build option that you want before running pages.
If you have configured the Web site to build before running a page, you can further specify what happens if the page or Web site has
errors.
To specify run behavior if build errors occur
1. On the Tools menu, click Options.
2. Select the Show all settings check box if it is not already selected.
3. Expand the Projects and Solutions node, and then click Build and Run.
4. Under On Run, when build or deployment errors occur, select the option for behavior that you want if the build process
encounters an error.

See Also
Tasks
How to: Specify Start Pages for Testing Web Sites in Visual Web Developer
Concepts
Testing Web Pages in Visual Web Developer
Building Web Sites
Visual Web Developer

How to: Specify Start Pages for Testing Web Sites in Visual
Web Developer
When you use the Start or Start Without Debugging commands to run a Web site, by default Visual Web Developer runs
the page that currently has the focus in the designer. However, you can also set a start page, which is useful if you always want
to start at the same point in your Web site. If you set a start page, using the Start or Start Without Debugging commands
always runs the start page that you specified instead of the current page.
Note
Setting a start page in Visual Web Developer affects only your testing. It does not set the start page for the Web site when it i
s published. To specify a default start page for your Web site, use Internet Information Services (IIS) to enable a default docu
ment and select the page. For details, see the IIS documentation.

To specify a start page for testing a Web site in Visual Web Developer
1. In Solution Explorer, right-click the name of the Web site that you want to specify as the start page, and then click
Property Pages.
2. In the Start Options tab, select the Specific page check box and then type or browse to the name of the page that you
want to use as the start page.
-or-
In Solution Explorer, right-click the page that you want to specify as the start page, and then click Set As Start Page.
See Also
Tasks
How to: Test Web Pages in Visual Web Developer
Concepts
Testing Web Pages in Visual Web Developer
Visual Web Developer

Learning More - Creating Web Pages


The topics in this section provide in-depth information on working with ASP.NET Web pages.
In This Section
Page and Application Context in ASP.NET Web Applications
See Also
Other Resources
ASP.NET Web Sites (Visual Studio)
ASP.NET Web Pages (Visual Studio)
ASP.NET Web Server Controls (Visual Studio)
ASP.NET

Page and Application Context in ASP.NET Web Applications


When a Web application runs, ASP.NET maintains information about the current application, each user session, the current
HTTP request, the requested page, and so on. ASP.NET contains a series of classes to encapsulate this context information.
ASP.NET makes instances of these classes available as intrinsic objects that you can access from your code. The following table
lists these intrinsic objects and the classes they are instances of.
Obje Description ASP.NET Class
ct Na
me
Resp Provides access to the output stream for the current page. You can use this class to inject text into t HttpResponse
onse he page, to write cookies, and more. For details, see System.Web.UI.Page.Response property.

Requ Provides access to the current page request, including the request headers, cookies, client certificat HttpRequest
est e, query string, and so on. You can use this class to read what the browser has sent. For details, see
System.Web.UI.Page.Request property.

Cont Provides access to the entire current context (including the request object). You can use this class t HttpContext
ext o share information between pages. For details, see System.Web.UI.Page.Context property.

Serv Exposes utility methods that you can use to transfer control between pages, get information about HttpServerUtility
er the most recent error, encode and decode HTML text, and more. For details, see
System.Web.UI.Page.Server property.

Appl Provides access to application-wide methods and events for all sessions. Also provides access to an HttpApplicationState
icati application-wide cache you can use to store information. For details, see ASP.NET Application State.
on

Sessi Provides information to the current user session. Also provides access to a session-wide cache you HttpSessionState
on can use to store information, along with the means to control how the session is managed. For det
ails, see ASP.NET Session State.

Trac Provides a way to display both system and custom trace diagnostic messages in the HTTP page out TraceContext
e put. For details, see ASP.NET Tracing.

The following topics show examples of how the intrinsic objects can be used.
Object Example topics
Application How to: Read Values from Application State
How to: Save Values in Application State

Request How to: Read a Cookie


How to: Write a Cookie

Server How to: Handle Application-Level Errors


How to: Handle Page-Level Errors

Session How to: Save Values in Session State


How to: Read Values from Session State

See Also
Other Resources
ASP.NET State Management
Visual Web Developer

Walkthrough Topics — Creating Web Pages


The following walkthrough topics describe how to create Web sites and how to work with ASP.NET Web pages.
Walkthrough Topics
Walkthrough: Creating a Basic Web Page in Visual Web Developer
Walkthrough: Creating a Basic Web Page with Code Separation in Visual Web Developer
Walkthrough: Code Editing in Web Pages in Visual Web Developer
See Also
Other Resources
ASP.NET Web Pages Introduction (Visual Studio)
Visual Web Developer

How-to Topics — Creating Web Pages


The following procedures describe how to create ASP.NET Web pages in the Visual Web Developer designer.
How-to Topics
How to: Add ASP.NET Web Pages to a Web Site (Visual Studio)
How to: Test Web Pages in Visual Web Developer
How to: Specify Start Pages for Testing Web Sites in Visual Web Developer
See Also
Other Resources
ASP.NET Web Pages Introduction (Visual Studio)
Visual Web Developer

Web Page Designer


The topics in this section provide information on using the Web page designer in Visual Web Developer to create and edit
ASP.NET Web pages and other files.
In This Section
Getting Started — HTML Editing in Visual Studio
Learning More — HTML Editing in Visual Web Developer
Walkthrough Topics — Web Page Designer
How-to Topics — Web Page Designer
See Also
Other Resources
ASP.NET Web Sites (Visual Studio)
ASP.NET Web Pages (Visual Studio)
ASP.NET Web Server Controls (Visual Studio)
Visual Web Developer

Getting Started — HTML Editing in Visual Studio


The topics in this section provide essential information on using the Web page designer in Visual Web Developer to create and
edit ASP.NET Web pages.
In This Section
Editing ASP.NET Web Pages in Visual Web Developer Overview
Design View, Web Page Designer
Source View, Web Page Designer
Web Page Designer Keyboard Shortcuts
Paste Operations in the HTML Designer of Visual Web Developer
How to: Navigate in the HTML Editor in Visual Web Developer
Cascading Style Sheet Editing (Visual Studio)
HTML Table Editing in Visual Web Developer
See Also
Other Resources
ASP.NET Web Sites (Visual Studio)
ASP.NET Web Pages (Visual Studio)
ASP.NET Web Server Controls (Visual Studio)
Visual Web Developer

Editing ASP.NET Web Pages in Visual Web Developer Overview


You can create and edit Web pages — both HTML pages and ASP.NET Web pages — using the Visual Web Developer page
designer. The designer provides you with two views of your page: Design view, which displays the page in much the way it will
appear in a browser, and Source view, which shows you the markup (such as HTML) for the page.
Design View
Design view provides a what-you-see-is-what-you-get (WYSIWYG) editor. You can type text directly into the editor and format
it using menu and toolbar commands. You can also drag elements from the toolbox, and if you want, position them two-
dimensionally using x- and y-coordinates.
Controls that require complex configuration display Smart Tags, which are menus that allow you to quickly perform the most
commonly required tasks.
Source View
Source view displays the markup (the text, HTML elements, and control elements) for your page, which you edit directly. In
Source view, the designer offers the following features:
Validation The designer checks the syntax of your markup and underlines errors, similar to the way Microsoft Word
performs spell checking. You can configure the designer to check validity against different schemas or browser
definitions. For more information, see Markup Validation in Visual Web Developer.
IntelliSense As you type, the designer offers you options that are appropriate to the context in which you are working.
For example, if you are typing an HTML tag, the designer offers you a list of valid attributes for that tag.
Outlining You can mark sections of the page as regions, and then collapse and expand them. For example, if you have a
very long table element in your page, you can mark it as a region and collapse it when you are not working on it. For
details, see How to: Collapse and Expand HTML Elements in Visual Web Developer.
Tag formatting You can set options for how the editor formats your markup as you type and when you reformat the
document. For details, see Format, HTML, Text Editor, Options Dialog Box and Tag Specific Options.
Page Templates
When you create a Web page in Visual Web Developer, the new page contains markup that includes the most commonly used
elements for that page. For example, when you create a new ASP.NET Web page, the new page includes a @ Page directive,
html and body elements, and so on.
By default, the templates for new pages include markup that is compliant with XHTML standards. For more information, see
ASP.NET and XHTML and XHTML in Visual Web Developer.
See Also
Other Resources
Design View, Web Page Designer
Source View, Web Page Designer
Visual Web Developer

What's New in the Web Page Designer and Editors


Microsoft Visual Studio 2005 includes improvements over previous versions of Visual Studio in Web page designer features
for editing ASP.NET pages, user controls, HTML pages, cascading style sheets, configuration files, and other documents.
General
This section describes general enhancements and changes that have been made to the Web page designer and other editors.
New Tab Names
The Web page designer now offers two tabs:
Design view, which includes a number of enhancements from previous versions of Visual Studio.
Source view, which is the replacement for HTML view that was used in previous versions of Visual Studio.
Enhancements to both views are described later in this topic.
Adding Controls
In the Web page designer, you can drag controls from the Toolbox in both Design view and Source view.
Formatting Preservation
The Web page designer preserves your formatting when you switch between Design view and Source view. The document is
no longer reformatted each time you switch views. If you edit elements in Design view, the editor performs the minimal
reformatting required to reflect the change.
Note
If the Web page designer cannot switch from Source view to Design view because of syntax errors or other problems that wo
uld require reformatting content, the designer displays an error and blocks the switch.

XHTML Pages
By default, when you create a new Web page in Visual Studio, the page includes skeleton markup that conforms to XHTML
standards. Content that is generated by the HTML editor also conforms to XHTML standards. For details, see
XHTML in Visual Web Developer.
Navigation
In the Web page designer, Document Outline displays the current element, along with the hierarchy of parent tags to which it
belongs. You can use Document Outline to determine which element has the focus and to move between elements. In addition,
in Source view, the tag navigator displays the current tag in its immediate context, enabling you to navigate or select the tags.
For details, see HTML Editor Tag Navigation in Visual Web Developer.
Working in Design View
The changes described in this section are new for working in Design view in the Web page designer.
Layout
The Web page designer now assumes flow-based layout in vsprvslong. The FlowLayout and GridLayout elements that were
used in previous versions of Visual Studio are no longer in the Toolbox. Instead, you can establish absolute positioning for
individual controls. For details, see Positioning Elements in Design View.
In Design view, the positioning grid is now always invisible. However, you can still snap elements to the grid. For details, see
CSS Positioning, HTML Designer, Options Dialog Box.
The commands for inserting and editing new HTML tables are improved. For details, see
What's New in HTML Table Editing in Visual Studio.
Smart Tags
In Design view, ASP.NET server controls display a Smart Tag menu that offers quick access to the settings and actions that are
used most often to configure the control. By default, the Smart Tag menu is displayed when you first drag a control onto the
page from the Toolbox. You can display and hide the Smart Tag menu at any time.
Working in Source View and Text Editors
The changes discussed in this section are new for working in text-editing mode for Web pages and other types of Web files.
This includes Source view in the Web page designer.
Validation
All Web page designer source editors, including Source view for Web pages, automatically check the syntax in the document,
and then mark tags, attributes, and values that are not valid. Validation covers almost all types of markup, including HTML,
server controls, and page directives. Validation can also check that references to external resources such as image files are
valid.
You can select a validation schema to work with either by browser (for example, Internet Explorer 6.0) or by standard (for
example, XHTML 1.1). For details, see Markup Validation in Visual Web Developer.
Markup errors are displayed in a number of ways:
Marked with squiggly lines, which is similar to the way a word processor, such as Microsoft Word, marks errors.
As a ToolTip, which provides details about each error.
In the Error List window, which displays details about each error.
IntelliSense
In Source view of the Web page designer, the editor displays Microsoft IntelliSense technology for virtually all elements,
including ASP.NET server controls, markup, page directives, cascading style sheet and in-line styles, and client script. Because
the IntelliSense technology that is offered by the editor is controlled by the current validation schema, the editor does not
present IntelliSense technology for tags, attributes, and values that are not valid for the current schema.
The IntelliSense technology is also available for editing in the following files:
Configuration.
.css for creating style definitions.
Server-side code.
Client script in script elements.
Formatting
In the Web page designer, Source view offers a full set of options for formatting the document and individual tags:
Dragging or pasting elements.
When you drag elements from the Toolbox or paste them from the Clipboard, the editor can either create them exactly as
they were formatted before or it can reformat them according to options that you specify. For details, see
Miscellaneous, HTML, Text Editor, Options Dialog Box.
Matching tags.
When you select an opening or closing tag, the editor highlights the matching tag to make it easier for you to identify
blocks.
Adding quotation marks or closing tags.
You can set options that cause the editor to insert quotation marks around attribute values and create an end tag when
you finish a start tag. For details, see Format, HTML, Text Editor, Options Dialog Box.
Formatting per tag.
You can specify rules for how the editor formats tags as you create elements. Options include how to capitalize tags and
attributes, colorization, and where to put line breaks. For details, see Tag Specific Options.
Formatting elements or documents.
You can apply the current formatting rules to a selected section or the entire document.
Outlining tags.
You can collapse and expand elements to create more working space in the editor. For example, you can collapse a table
element to hide its rows and cells, and then expand it when you want to edit it. You can collapse and expand elements
manually, and you can specify rules for how large an element is before the editor automatically applies outlining to an
element.
Note
Outlining is available in other editors as well, such as the code editor. For general information about outlining,
seeOutlining (Managed Package Framework).

See Also
Concepts
Editing ASP.NET Web Pages in Visual Web Developer Overview
What's New in Code-Behind Support in Visual Web Developer
Visual Web Developer

Design View, Web Page Designer


The topics in this section provide information on using Design view in the Visual Web Developer, which provides a WYSIWYG
editor for creating and editing Web pages.
In This Section
Design View
Positioning Elements in Design View
How to: Position Elements in Design View
How to: Insert HTML Hyperlinks and Bookmarks in Design View
How to: Display Hidden Information in Design View
See Also
Other Resources
Source View, Web Page Designer
Web Page Designer
ASP.NET Web Sites (Visual Studio)
ASP.NET Web Pages (Visual Studio)
ASP.NET Web Server Controls (Visual Studio)
Visual Web Developer

Design View
Design view displays ASP.NET Web pages, master pages, content pages, HTML pages, and user controls using a near-
WYSIWYG view. Design view allows you to add text and elements and then position and size them and set their properties
using special menus or the Properties window.
When you add elements to the page, Visual Web Developer creates corresponding markup that you can also edit in Source
view. For details, see Source View.
To switch to Design view, click the Design tab at the bottom of the HTML Designer window.
Note
Design view displays only the body of a document — the portion between the <body> and </body> tags. Although you ca
n edit some properties of the <head> element, such as the document's title, by using the Document Properties window, y
ou must switch to Source view to edit properties of elements not inside the <body> element.

How Design View Differs from Viewing in a Web Browser


Design view gives you a near-WYSIWYG editing view of what your page will look like in a browser. However, Design view is
not an exact match for how the page will be rendered, and you should always test the page in a browser (or in multiple
browsers) to be sure the page will appear as you have designed it.
A document displayed in Design view differs from one displayed in a Web browser in these ways:
The design surface is editable.
Some elements are displayed in Design view for editing purposes but are not rendered in the browser, such as data
source controls. Most controls that appear only while being edited are rendered as gray boxes in Design view.
Some character and paragraph formatting might appear differently than in a specific browser (if the Web browser
implements formatting differently than Design view).
Optionally, you can have the editor display boxes, symbols, and icons to mark server controls. For details, see
Display, HTML Designer, Options Dialog Box.
Hyperlinks are not functional.
Client scripts do not run.
Server code does not run.
Elements that support alternate text (such as images) do not display this alternate text in ToolTips when the pointer
passes over them.
Displaying Non-Visible Elements
To help you edit a page, Design view displays certain elements, such as hidden fields, that would normally not be visible in the
browser. Design view also displays gray boxes or other representations of ASP.NET server controls, such as data source
controls, that do not render markup at run time.
In addition, you can choose to display borders and symbols that can help you work with elements and tags on the page. For
details, see How to: Display Hidden Information in Design View.
Displaying Null Characters
In Design view, when a template is used that contains a null character, the characters following the null character are truncated.
No data is lost, but the Design view does not show characters in a template that follow a null character.
Positioning Elements in Design View
Elements in the page are physically laid out top to bottom. By default, when the page is rendered to the browser, the elements
are rendered in the same top-to-bottom order. You can also lay out elements two-dimensionally, positioning elements with
horizontal and vertical coordinates anywhere on the page. This layout option takes advantage of the positioning options
available through styles. For details, see Positioning Elements in Design View.
Navigating in Design View
To help you move between elements and select them, Design view provides these options:
Tag navigator. The tag navigator displays the current element, along with the hierarchy of parent tags to which it belongs.
You can use the tag navigator to see which element has the focus, and to move from the current element to an element
higher in the hierarchy. For details, see HTML Editor Tag Navigation in Visual Web Developer.
Document outline. The Document Outline window makes it possible for you to locate and select all elements within a
document, including those that are not displayed. For details, see
How to: Navigate in the HTML Editor in Visual Web Developer.
Properties window. When you select an element from the drop-down list at the top of the Properties window, the
editor selects that element in the document.
Adding Elements
You can add elements to a page in Design view in these ways:
Drag them from the Toolbox.
Double-click the element in the Toolbox, which inserts the element at the current location of the insertion point in the
document.
Drag them from another document open in Visual Web Developer.
Drag them from Solution Explorer. This is primarily useful for adding user controls and style sheet references to the
page.
Type text directly into the page.
Smart Tags in Design View
In Design view, many ASP.NET server controls display a smart tag that offers quick access to the settings and actions most
often used to configure the control. By default, the smart tag is displayed when you first add a control to the page. You can also
display the smart tag at any time using the shortcut menu or by clicking its symbol.
Expressions in Design View
In Design view, you cannot use the Property Grid to change expression values. For example, if you assign an expression to a
control in Source view, you cannot change the value of that expression in the Design view. Since the expression value is
calculated, you should use the Source view to change the expression.
Refreshing the Designer
When you switch from Source view to Design view, you might need to refresh the designer to see certain types of file changes.
For example, theme code is parsed, not compiled; therefore, any changes made to theme code in Source view require a refresh
before you can see them in the designer.
To refresh the designer, you can do one of the following:
Right-click the Design window and click Refresh.
On the View menu, click Refresh.

See Also
Tasks
Walkthrough: Creating a Basic Web Page in Visual Web Developer
How to: Navigate in the HTML Editor in Visual Web Developer
Reference
Source View
Display, HTML Designer, Options Dialog Box
Concepts
Paste Operations in the HTML Designer of Visual Web Developer
HTML Editor Tag Navigation in Visual Web Developer
Positioning Elements in Design View
Other Resources
ASP.NET Web Site Security (Visual Studio)
Visual Web Developer

Positioning Elements in Design View


When you create HTML pages or ASP.NET Web pages in the HTML designer, the elements are physically laid out from top to
bottom. By default, when the page is rendered to the browser, the elements are rendered in the same top-to-bottom order.
This is sometimes referred to as flow layout.
You can also lay out elements two-dimensionally, by positioning elements with horizontal and vertical coordinates anywhere
on the page. This layout option takes advantage of the positioning options that are available through styles.
In Design view, you can drag elements to position them on the page and you can select elements and apply positioning
options to them. The page displays the elements at the location you position then. In Source view, you can set positioning
options in the markup for individual elements.
When the page is rendered, the browser displays the elements using the positioning information that you specify.
Flow Layout
If elements do not have any positioning style properties, they flow from top to bottom within the page, and either from left to
right or right to left, depending on the setting of the dir attribute of the page or the element's container element or of the
language setting for the browser. Any Web browser can display HTML documents that use this layout. Elements are sometimes
be repositioned when the page is resized.
If you use flow layout for your page, you can align elements inside a table element, or use a div element with positioning style
or text-align properties. However, elements cannot overlap. The elements might move as the page is resized, according to
whether you use absolute units or percentages for the table and cell widths.
Two-Dimensional Positioning
You can apply positioning options to individual elements, which allows you to place elements at precise locations on the page.
You can also specify positioning options for any new elements you add to the page.
The Microsoft Visual Web Developer Web development tool allows you to specify positioning options that correspond to those
that are defined in the W3C specification for cascading style sheets. The positioning options are valid in any browser that
implements the W3C HTML 4.0 standard, including those that support XHTML 1.1.
The options are as follows:
absolute
The element is rendered to a location in the page defined by any combination of the left, right, top, and bottom style
properties. The 0,0 position is defined based on the parent of the current element. The parent is the first container
element that has positioning information. For example, if the current element is inside a div element with positioning
information, absolute positioning is calculated based on the position for the div element. If the current element has no
container element with positioning, the positioning information is calculated based on the body element.
relative
The element is rendered to a location in the page that is defined by the left and top style properties. This option differs
from absolute in that the 0,0 position is defined with respect to where the element is in the flow of the page. An element
with relative positioning and top and left both set to 0 appears in the flow as normal.
Note
Elements that use absolute or relative positioning can appear on the page out of order with respect to their declaration
in the markup of the page, which can be confusing. For example, in Source view you might define a button as the first e
lement in the markup, but after you set its positioning, the button might appear as the last element in the rendered pag
e or in Design view.

static
The element is rendered using flow layout; that is, the element does not use two-dimensional positioning. You might
select this option if you want to set a positioning option on an individual control that overrides a setting that is inherited
from a theme or style sheet.
Visual Web Developer also offers the positioning option Not Set, which allows you to remove any existing positioning
information from an individual control or from controls that may be added in future.
Positioning Static Text or Groups of Elements
To enable you to creating floating static text or groups of elements as a unit, you can add a layer to the page. A layer is a div
element with positioning information included, which allows you to drag it around in the page. You can then type text or drag
elements into the div element. Visual Web Developer includes a command on the Layout menu to add a layer, or you can
create the div element yourself and add positioning information to it manually.
Constraining Positions to a Grid
If you are using absolute or relative positioning, and if you are using pixels as the basis for positioning (that is, the units for the
left and top properties are pixels), you can set an option to snap elements to an invisible grid. This helps you align elements
on the page. For details, see CSS Positioning, HTML Designer, Options Dialog Box.
Layering Elements
If you are using absolute or relative positioning, you can overlap elements, and then they will be rendered in the browser as
overlapped. If you position elements using a table, you cannot overlap objects.
Elements with absolute or relative positioning can include a z-index property that specifies the order, back to front, of the
element in a third dimension. If two elements share the same space, the element with the higher z-index attribute value is
displayed in front. If you use commands in Design view to set positioning, the z-index property is set automatically, starting
with 100 for the back-most element. If you add positioning properties in Source view, you must add the z-index property
manually.
See Also
Tasks
How to: Position Elements in Design View
Reference
CSS Positioning, HTML Designer, Options Dialog Box
Validation, HTML, Text Editor, Options Dialog Box
Visual Web Developer

How to: Position Elements in Design View


By default, elements in an HTML page or ASP.NET Web page are rendered in the order that they appear in the markup, which is
sometimes referred to as flow layout. You can also lay out elements two-dimensionally, positioning elements with horizontal
and vertical coordinates anywhere on the page. This layout option takes advantage of the positioning options that are available
through styles.
To help you work with static text or to position elements as a group, you can create a layer, which is a div element with
positioning information.
You can set positioning for individual elements on the page. You can also set an option to set positioning automatically for all
of the elements that you add to the page by dragging or by pasting from the Clipboard.
To position an element with horizontal and vertical coordinates
1. In Design view, select the element that you want to position.
2. On the Layout menu, click Position, and then click Absolute or Relative.
3. Drag the control to where you want it.
Note
If the element is set to use pixels for positioning units, which is the default in Visual Web Developer, you can constrain
dragging to an invisible grid. For details, see CSS Positioning, HTML Designer, Options Dialog Box.

To position static text or groups of elements


1. On the Layout menu, click Insert Layer.
Visual Web Developer inserts a div element with positioning information set.
2. To move the div element, click the selection symbol, and then drag it to a new position.
3. To resize the div element, click the selection symbol, and then drag the resize handles.
4. To add text, click inside the div element, and then type the text.
5. To add elements, drag them from the Toolbox to the div element.

To reset elements to flow layout


1. In Design view, select the element that you want to reset to flow layout.
2. On the Layout menu, click Position, and then click Static or Not Set:
Static sets positioning to static, which retains the cascading style sheet (CSS) positioning property but explicitly
puts the element into flow layout.
Not Set removes all of the positioning information.
To set positioning options for new elements
1. On the Tools menu, click Options.
2. Open the HTML Designer node, and then click CSS Positioning.
3. Under Positioning Options, select the check box.
4. From the list, select the positioning option that you want to apply to all elements that you drag to the page or paste from
the Clipboard.
For details on what each option means, see CSS Positioning, HTML Designer, Options Dialog Box.
See Also
Concepts
Positioning Elements in Design View
Visual Web Developer

How to: Insert HTML Hyperlinks and Bookmarks in Design View


Hyperlinks and bookmarks are important tools for helping users to navigate quickly within and across Web pages to the
content that they need.
When clicked, a hyperlink attempts to find an HTML document and open it in the Web browser. It locates this new document
using a Uniform Resource Locator (URL) string. For example, the hyperlink <A HREF="mypage.htm"> looks in the current folder
for a page named mypage.htm, and then displays this page in the current frame.
To insert a hyperlink
1. In Design view, open your Web page for editing.
2. Select the text or image to use as a hyperlink.
3. On the Format menu, click Convert to Hyperlink.
The Hyperlink dialog box appears.
4. In the URL box, type the path to the resource or click the Browse button and navigate to the target page or file, and then
click OK.
The target attribute specifies the browser window in which the hyperlink is displayed. You can enter the actual name of the
target window or use special terms, such as parent or top, to express the position of the target window relative to the current
one. If the target attribute is not set, the hyperlink displays the target page in the current browser window.
To set the target window of a hyperlink
1. Select the hyperlink
2. In the Properties window, in the Target box enter the name of the target window or select a special term.
A bookmark creates a location within an HTML document to which a hyperlink can jump (for example, <a name="anchor">).

To insert a bookmark
1. In Design view, place the cursor on the page at the location that you want to bookmark.
2. On the Format menu, click Insert Bookmark.
The Bookmark dialog box appears.
3. Type a name for the bookmark, and then click OK.
Now you can make this bookmark the target of a hyperlink.
You can create a hyperlink that scrolls the current HTML document to a location that was previously marked by an anchor. The
Web browser locates this anchor using an abbreviated URL (for example, <a href="#anchor">).
To insert a hyperlink to a bookmark
1. Select the text or image for the user to use as a hyperlink.
2. On the Format menu, click Convert to Hyperlink.
The Hyperlink dialog box appears.
3. In the Type list, select (other).
4. In the URL box, type a pound sign (#) and the bookmark name (for example, #anchor), and then click OK.
See Also
Reference
Hyperlink Dialog Box
Visual Web Developer

How to: Display Hidden Information in Design View


To help you edit, Design view in Visual Web Developer can display glyphs and borders to mark elements on the page. In
addition to helping you see where the elements are, using these features can help you avoid inadvertently deleting non-
graphic elements (such as div, span, form, and script elements) from your page while editing.
Note
You can also use the Document Outline window to select items that are not displayed in Design view. For details, see
How to: Navigate in the HTML Editor in Visual Web Developer.

To toggle markers on and off for non-graphic HTML elements in Design view
1. On the View menu, click Details.
2. To set markers to display whenever you open a Web page in Design view, do the following:
a. On the Tools menu, click Options.
b. Under HTML Designer, select the Display check box.
c. Under Display Options, select the Show details for non-visible elements check box.
To display or conceal table borders in Design view
1. On the View menu, click Visible Borders.
This displays edges around tables and frames that would otherwise not appear.
2. To set borders to display whenever you open a Web page in Design view, do the following:
a. On the Tools menu, click Options.
b. Under HTML Designer, select the Display check box.
c. Under Display Options, select the Show details for non-visible elements check box.
To mark ASP.NET server controls
1. On the Tools menu, click Options.
2. Under HTML Designer, select the Display check box.
3. Under Display Options, select the Show glyphs for server controls check box.
See Also
Concepts
Design View
Visual Web Developer

Troubleshooting Design View Rendering


Several common issues can arise when you attempt to open a file in the Web Forms designer that cannot be rendered
correctly in the designer. Design-view rendering issues occur most frequently when you are working with a file that was
originally created as a code-behind Web Forms page outside of Visual Studio. However, these issues can occur under a variety
of circumstances. Typically, the problem involves attributes of the @ Page directive in a Web Forms page, or of the @ Control
directive in a Web Forms user control.
Note
The Web Forms designer is the registered editor for files with an extension that matches that of the file you are working with.
If you do not want to use the Web Forms designer to work with a file, change the file's extension. Alternatively, in Solution Ex
plorer you can right-click the file, choose Open With, and select a different editor.

Issues with the Src Attribute


An error might occur if you have a Src attribute in the @ Page or @ Control directive. This attribute is not supported in the
Web Forms designer. To fix this error:
Remove the Src attribute. In its place, add:
A CodeBehind attribute that references the name of a code-behind file in the project.
An Inherits attribute that references the class name represented by the code-behind file. (This class should in
turn inherit from the System.Web.UI.Page class.)
Note
If there is not already a code-behind file and class, you can have the Web Forms designer generate one. After removing
the Src attribute, set the Inherits attribute to an empty string ("") and the CodeBehind attribute to the name of the co
de-behind file to generate (formname.aspx.vb or formname.aspx.cs). Save the file and close it. In Solution Explorer, righ
t-click the .aspx file and choose View Code. When you save the code-behind file, the designer will generate an appropr
iate class file. Open the file again. Perform any gesture that generates code in the code-behind file (such as adding a co
ntrol or double-clicking a control to create an event handler) and then save the file. The designer sets the Inherits attri
bute of the Web Forms page appropriately.

Alternatively, you can remove the Src, CodeBehind, and Inherits attributes and treat the file as a single-file Web Forms page.
For more information, see Working with Single-File Web Forms Pages in Visual Studio .NET.
Issues with the CodeBehind Attribute
The CodeBehind attribute in the @ Page or @ Control directive references the name of a file that contains the class for the
page. For example, if you create a Web Forms page in Visual Studio named WebForm1, the CodeBehind attribute will point to
WebForm1.aspx.vb or WebForm1.aspx.cs.

The CodeBehind attribute is used only at design time; it tells the Web Forms designer where to find the page class so that the
designer can create an instance of it for you to work with.
Problems associated with the CodeBehind attribute can include:
The referenced file is not available. Either the file does not exist or it has a different name.
The class in the referenced file is inherited from a base class that is not referenced in the project. Normally, the class for
your Web Forms page is inherited from the System.Web.UI.Page class, but if you are working with a user control or a
Web Forms page for another platform, such as a mobile device, the base class might be different.
The class in the referenced file inherits from a base class in the project that has not been compiled.
Issues with the Inherits Attribute
The Inherits attribute in the @ Page or @ Control directive references the name of a class (not a file) from which the page
inherits at run time. For more information about the inheritance model for Web Forms pages, see Web Forms Code Model.
Problems with the Inherits attribute arise only if there is not also a CodeBehind attribute. This might be true, for example, in a
single-file Web Forms page. If there is no CodeBehind attribute, only then does the designer use the class referenced in the
Inherits attribute to create an instance of the page at design time.
Note
If there is a CodeBehind attribute, the designer will ignore the Inherits attribute, even if the Inherits attribute is pointing to
a class that is not available. In that case, you can work with the page in the designer, but it will not run.

The most common problem associated with the Inherits attribute is that it points to a class that is not available in the project
or in a referenced assembly.
See Also
Concepts
Design View
Visual Web Developer

Source View, Web Page Designer


The topics in this section provide information on using Source view in the Visual Web Developer, which enables you to edit the
markup of your Web pages directly, and which provides a variety of features that help you create valid markup.
In This Section
Source View
Walkthrough: Basic HTML Editing in Visual Web Developer
Walkthrough: Advanced HTML Editing in Visual Web Developer
Formatting Elements in the HTML Editor in Visual Web Developer
How to: Collapse and Expand HTML Elements in Visual Web Developer
How to: Create Scripts and Edit Event Handlers
How to: Choose an Alternate HTML Editor in Visual Web Developer
See Also
Other Resources
Design View, Web Page Designer
Web Page Designer
ASP.NET Web Sites (Visual Studio)
ASP.NET Web Pages (Visual Studio)
ASP.NET Web Server Controls (Visual Studio)
Visual Web Developer

Source View
Source view displays the HTML markup for your Web page, which you can edit. By default, all HTML elements and scripts are
displayed when you initially select Source view. You can drag elements from the Toolbox, just as you do when you are editing
a Web page in Design view, and then see their markup inserted into the document.
To select Source view, click the Source tab at the bottom of the HTML Designer window.
Source view provides the following advantages over Design view:
You can fine-tune the markup for your elements and controls.
You can format the document to your liking.
You can edit elements that are not in the body. Design view only displays elements that are located between body
elements. For example, you can directly edit the head element when you are working in Source view.
You can edit page directives.
You can create and edit client script.
You can edit the server code for the page when you are working with a single-file page (as opposed to a page with a
code-behind file).
When you switch to Design view, any changes that you have made in Source view are reflected immediately.
Note
Some markup errors can prevent you from switching to Design view because the errors would cause problems for the editor
, including possible data loss. For example, if a tag is not properly closed, the editor displays an error and stops the view switc
h. Details about the error are displayed in the Error List Window. You can preview your page by running it, even if you cannot
switch to Design view.

Navigating in Source View


To help you move between elements and select them, Source view provides the following options:
Tag navigator The tag navigator displays the current element, along with the hierarchy of parent elements to which it
belongs. You can use the tag navigator to see which element has the focus, and to move from the current element to an
element that is located higher in the hierarchy. For details, see HTML Editor Tag Navigation in Visual Web Developer.
Document outline The Document Outline window makes it possible for you to locate and select all of the elements
within a document, including those elements that are not displayed. For details, see
How to: Navigate in the HTML Editor in Visual Web Developer.
Validation
In Source view, the editor automatically checks the document's syntax and marks tags, attributes, or values that are not valid.
You can select a validation schema to work with, either by browser (for example, Microsoft Internet Explorer) or by standard
(for example, XHTML 1.1 Strict). For details, see Markup Validation in Visual Web Developer.
IntelliSense
IntelliSense is the feature of Visual Studio that displays a drop-down list of possible keywords that would complete what you
are typing. For example, if you type the beginning of a class name, IntelliSense displays a drop-down list that contains all of the
class names that begin with the characters that you have typed so far.
In Source view, the editor displays IntelliSense for virtually all elements, including ASP.NET Web server controls, markup, page
directives, and client script. The IntelliSense offered by the editor is controlled by the current validation schema, so that the
editor does not offer you IntelliSense for tags, attributes, or values that are not valid for the current schema.
Note
You can turn off statement completion. For details, see General, HTML, Text Editor, Options Dialog Box.
Formatting
The editor offers the following options for formatting the document and individual tags:
Dragging or pasting elements When you drag elements from the Toolbox or paste them from the Clipboard, the
editor can either create the elements exactly as they were formatted before or reformat the elements, according to
options that you specify. For details, see Miscellaneous, HTML, Text Editor, Options Dialog Box.
Adding quotation marks or closing tags You can set options that cause the editor to automatically insert quotation
marks around attribute values and automatically create an end tag when you finish a start tag. For details, see
Format, HTML, Text Editor, Options Dialog Box.
Formatting per tag You can specify rules for how the editor formats tags as you create elements. Options include how
to capitalize tags and attributes, and where to put line breaks. For details, see Tag Specific Options.
Formatting elements or documents You can apply the current formatting rules to a selected section or to the
document as a whole.
Outlining documents You can collapse and expand elements to create more working space in the editor. For example,
you can collapse a table element to hide all of its rows and cells, and then expand it when you want to edit it. You can
collapse and expand elements manually, and you can specify rules for how large an element is before the editor
automatically adds outlining to an element. For details, see
How to: Collapse and Expand HTML Elements in Visual Web Developer.

Writing Client Script and Server Code


In Source view, you can create client script that runs in the browser. If you are working with a single-file ASP.NET Web page,
you can also edit the page's server code in Source view. For information about client script in ASP.NET pages, see
Programming ASP.NET Web Pages with Client Script. For information about single-file ASP.NET pages, see
ASP.NET Web Page Code Model.
Client Script
You can write client script as you would in any editor, including it either as part of an element or in its own <script> block.
Inside a script block, the editor offers IntelliSense that is keyed to the object model of the current document and to the client
scripting language you specify for the script block. If you do not specify a language, the editor assumes that it is ECMAScript.
Note
The editor does not validate client script.

The editor displays two drop-down lists at the top of the window. For client scripting, the drop-down list on the left side
displays a list of document objects for which you can write event handlers; the drop-down list on the right side displays events
for the selected object. You can create a new handler by selecting the object and then selecting the event. Events that already
have handlers are displayed in bold.
To help with navigating client script, the drop-down list on the left side also displays the Client Script option. When you select
Client Script, the drop-down list on the right side displays a list of the client-script event handlers. You can select a handler
and jump directly to it.
Server Code
If you are working in an ASP.NET Web page that uses the single-file code model, Source view displays the page's server code
in a script block that includes the attribute runat="server".
Note
Server code does not require a language attribute; the page's server code language is established in the @ Page directive.

For server code, the drop-down list at the top-left of the page displays the server controls for which you can write code. The
drop-down list on the right side displays a list of events for the control that is currently selected. You can create a new event
handler by selecting the object and then selecting the event. Events that already have handlers are displayed in bold.
See Also
Concepts
Design View
Visual Web Developer

Walkthrough: Basic HTML Editing in Visual Web Developer


The Microsoft Visual Web Developer Web development tool provides a rich HTML editing experience that lets you work in
WYSIWYG mode for visualizing Web pages and also lets you work directly with HTML markup for finer control. This
walkthrough introduces you to the HTML editing features of Visual Web Developer.
Tasks illustrated in this walkthrough include the following:
Creating and editing HTML in Design view.
Creating and editing HTML in Source view.
Using navigation tools to move quickly through your HTML tags.
Prerequisites
In order to complete this walkthrough, you will need the following:
A general understanding of Visual Web Developer.
For an introduction to creating Web pages in Visual Web Developer, see
Walkthrough: Creating a Basic Web Page in Visual Web Developer.
In this walkthrough, you will work with a Web site and a single ASP.NET Web page that is similar to the one that is created in
Walkthrough: Creating a Basic Web Page in Visual Web Developer. If you have completed that walkthrough, you can use that
Web site and page.
Creating the Web Site and Page
If you have already created a Web site in Visual Web Developer (for example, by completing
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and go to the next section.
Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, enter the name of the folder where you want to keep the pages of the Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click the programming language that you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Working in Design View
In this part of the walkthrough, you will learn how to work in Design view, which provides a WYSIWYG-like view of the page.
You can add text by typing, as you would in a word processing program. You can format text directly with formatting
commands or by creating in-line styles.
Design view displays your page in a way that is similar to how it will appear in a browser, with some differences. The first
difference is that in Design view, the text and elements are editable. The second difference is that to help you edit your pages,
Design view displays some elements and controls that will not appear in the browser. Additionally, some elements, such as
HTML tables, have a special Design view rendering that adds additional space for the editor. Overall, Design view helps you
visualize your page, but it is not an exact representation of how the page will render in a browser.
To add and format static HTML in Design view
1. If you are not in Design view, click Design, which is located at the lower left of the window.
2. At the top of the page, type ASP.NET Web Page.
3. Highlight the text to format to select it, and then on the Format toolbar, in the left-most list, click Heading 1.
4. Position the insertion pointer below ASP.NET Web Page, and then type This page is powered by ASP.NET.
5. Right-click This page is powered by ASP.NET., and then click Style.
The Style Builder dialog box appears.
6. Click Font, and then in Family, click the ellipsis (…) button.
The Font Picker dialog box appears.
7. Under Installed fonts, click Verdana, and then click the add (>>) button.
8. Click OK to close the Font Picker dialog box.
9. Click Text, and then in the Horizontal list, click Centered.
10. Click OK.
Viewing Tag Information
When you are working in Design view, you might find it useful to see the design surface tags, such as div and span, and others
that do not have a visual rendering.
To see HTML design surface tags in Design view
On the View menu, click Details.
The designer displays symbols for paragraphs, line breaks, and other tags that do not render text.
Adding Controls and Elements
In Design view, you can drag controls from the Toolbox onto the page. You can add some elements, such as HTML tables, using
a dialog box. In this section, you will add some controls and a table so that you have elements to work with later in the
walkthrough.
To add controls and a table
1. Position the insertion pointer to the right of the closing paragraph mark for This page is powered by ASP.NET., and
then press ENTER.
2. From the Standard group in the Toolbox, drag a TextBox control onto the page.
Note
You can also add a control by double-clicking it.

3. Drag a Button control onto the page.


The TextBox and Button controls are ASP.NET Web server controls, not HTML elements.
4. On the Layout menu, click Insert Table.
The Insert Table dialog box appears.
5. Click OK.
The Insert Table dialog box provides options for configuring the table that you are creating. However, for this
walkthrough, you can use a default table layout.
Creating Hyperlinks
Design view provides builders and other tools to help you create HTML elements that require property settings.
To create a hyperlink
1. In the text This page is powered by ASP.NET., highlight ASP.NET to select it.
2. On the Format menu, click Convert to Hyperlink.
The Hyperlink dialog box appears.
3. In the URL box, type http://www.asp.net.
4. Click OK.
Setting Properties in the Properties Window
You can change the look and behavior of the elements on the page by setting values in Properties.
To set properties by using the Properties window
1. Click the Button control that you added in "Adding Controls and Elements," earlier in this walkthrough.
2. In Properties, set Text to Click Here, ForeColor to a different color, and Bold to true.
3. Place the insertion point in the ASP.NET hyperlink that you created in the preceding section.
Notice that in Properties, the HRef property for the a element is set to the URL that you provided for the hyperlink.
Testing the Page
You can see the results of your editing by viewing the page in the browser.
To start the page in the browser externally
Right-click the page, and then click View in Browser.
If you are prompted to save your changes, click Yes.
Visual Web Developer starts the Visual Web Developer Web server, which is a local Web server that you can use to test
pages without using IIS.
Changing the Default View
By default, Visual Web Developer opens new pages in Source view.
To change the default page view to Design view
1. On the Tools menu, click Options
2. In the Options dialog box, click HTML Designer, and then under Start Pages in, click Design view.
Note
You can run pages in several ways. If you press CTRL+F5, Visual Web Developer performs the start action that is configured
on the property page for Start Options. The default start option for CTRL+F5 is to run the current page; that is, the page that
is currently active in Source or Design view. You can also run pages in the debugger. For more information, see
Walkthrough: Debugging Web Pages in Visual Web Developer.

Working in Source View


Source view lets you edit the markup of the page directly. The Source view editor gives you many features that help you as you
create HTML and ASP.NET controls. You can use the Toolbox in Source view just as you do in Design view to add new elements
to the page.
To add elements in Source view
1. Switch to Source view by clicking Source, which is located at the lower left of the window.
The controls that you have added are created as <asp:> elements. For example, the Button control is the <asp:button>
element. The property settings that you made are preserved as attribute settings in the <asp:button> tag.
2. From the HTML group in the Toolbox (not the Standard group), drag a Table control onto the page and place it just
above the closing </form> tag.
The editor also helps you when you type markup manually. For example, the editor provides context sensitive choices finishing
HTML tags and attributes as you type. The editor also provides error and warning information on markup by underlining
questionable markup with a wavy line. The error or warning information is available by positioning the mouse over the
markup text.
To edit HTML in Source view
1. Position the insertion point above the closing </form> tag, and then type a left angle bracket (<).
Notice that the editor offers you a list of tags that are appropriate in the current context.
2. Highlight a to select it, and then press the SPACEBAR.
The editor displays a list of attributes that are appropriate for an anchor tag.
3. In the list, click href, and then type an equal sign and a double quotation mark (=").
The editor offers you a list of currently available pages to link to and an option to open the Homepicker dialog box.
4. In file list, double-click Default.aspx, press the SPACEBAR, and then type a right angle bracket (>) to close the tag.
The editor inserts a closing </a> tag.
5. Finish the anchor element so that it links to the Default.aspx page using the link text Home and reads as follows:

<a href="Default.aspx">Home</a>

6. Position the insertion point in the a tag.


Notice that Properties displays the attributes for the tag.
7. In Properties, for the HRef property, click the ellipsis (…) button.
The Select Project Item dialog box appears.
Now, you can select a page in the current Web site as the target page. If you do not have other pages in the Web site to
choose from, close the Select Project Item dialog box and type a favorite URL into the Href box of the Properties
window.
8. Position the insertion point just above the closing </form> tag, and then type <invalid>.
The editor underlines the tag with a wavy line, indicating that the tag is not a recognized HTML tag.
9. Remove the tag that you created in the preceding step.
Examining HTML Formatting
An important feature of the page designer is that it preserves the HTML formatting that you apply to the page unless you
explicitly specify that the editor reformat the document.
To examine HTML formatting
1. Reformat the attributes for the Button control by aligning the attributes so that the declarative syntax looks like the
following:

<asp:Button
id="Button1"
runat="server"
Font-Bold="True"
ForeColor="Blue"
Text="Click Here" />

Notice that after you indent the first attribute, if you press ENTER in the tag, subsequent lines are indented to match.
2. Switch to Design view.
3. Right-click the new Button control, and then click Copy.
4. Position the insertion point below the new Button control, right-click, and then click Paste.
This creates a button with the ID of Button2.
5. From the Standard group in the Toolbox, drag a third Button control onto the page, which creates <Button3>.
6. Switch to Source view.
Notice that <Button2> is formatted exactly the way that you formatted <Button1>. On the other hand, <Button3> is
formatted using the default formatting for asp:button elements.
Note
For more information on how to customize the formatting of individual elements, see
Walkthrough: Advanced HTML Editing in Visual Web Developer.

7. Edit the document so that <Button1> and <Button2> are on the same line without a space between them:

<asp:Button ID="Button1" runat="server" Font-Bold="True"


ForeColor="Blue" Text="Click Here" /><asp:Button ID="Button2"
runat="server" Font-Bold="True" ForeColor="Blue" Text="Click Here"/>

The elements can wrap, but the end of <Button1> (that is, />) must be followed immediately by the beginning of
<Button2> (that is <asp:Button ID=).

8. Switch to Design view.


Notice that <Button1> and <Button2> are right next to each other without a space between them.
9. Switch to Source view
10. On the Edit menu, point to Advanced, and then click Format Document.
The document is reformatted, but <Button1> and <Button2> remain on the same line. If the editor were to separate the
buttons, it would introduce a space during rendering. Therefore, the editor does not change the formatting that you have
created.
Navigating Between Elements
As pages become larger and more complex, it is useful to be able to find tags quickly and to reduce the clutter in the page.
Visual Web Developer provides the following tools to help you with these tasks when you are working in Source view:
Document Outline, which provides a complete view of the document.
Tag navigator, which provides information about the currently selected tag and where it is in the page hierarchy.
To start, add more elements to the page so that you will be able to examine navigation features.
To add elements
1. Switch to Design view.
2. From the HTML group in the Toolbox, drag a Table control into a cell of the table that you created in "Working in Source
View," earlier in this walkthrough.
3. From the Standard group in the Toolbox, drag a Button control into the middle cell of the nested table.
With several nested elements on the page, you can see how Document Outline provides quick navigation to any tag in the
page.
To navigate with Document Outline
1. Switch to Source view.
2. On the View menu, point to Other Windows, and then click Document Outline.
3. In Document Outline, click Button4.
In the editor, the <Button4> control that you added in the preceding procedure is selected.
4. Right-click the <table> tag of the outer table, and then click Synchronize Document Outline.
The selection in Document Outline is moved to the outer table tag.
The tag navigator provides information about the currently selected tag and where it is in the page hierarchy.
To navigate with tag navigator
1. Position the insertion point in the <asp:button> tag.
Notice the tag navigator at the bottom of the window, which shows the <asp:button> tag and its parent tags. The tag
navigator includes the ID of the element, if any, so that you can identify which element is being displayed. The tag
navigator also displays the assigned cascading style sheet, if any, that was set with the Class attribute.
2. In the tag navigator, click the <table> tag that is closest to the <asp:button#Button4> tag.
The tag navigator moves to the inner <table> element and selects it.
3. In the tag navigator, click the <td> tag to the left of the selected <table>.
The whole cell that contains the nested table is selected.
Note
You can click to select either the tag or its contents by using the drop-down list in the tag navigator tag. By default, click
ing a tag in the tag navigator selects the tag and its contents.

You can also use the tag navigator to help you move or copy elements.
To move or copy elements using the tag navigator
1. Using the tag navigator, select the <tr> tag that contains <Button4>.
2. Press CTRL+C to copy the tag.
3. Use the tag navigator to move to the outer table.
4. In Source view, place the insertion pointer between the <table> tag and the first <tr> tag.
5. Press CTRL+V to paste the copied row into the table.
6. Switch to Design view.
Notice that the new row has been added, including a Button control.
Formatting Text
The Formatting toolbar applies inline styles for most settings. Bold and italic formatting is applied by using the b and i
tags. Paragraph formatting is applied a block tag, such as p (for normal), pre (for formatted), and so on. Paragraph
alignment is applied by using inline styles to conform with XHTML 1.1 standards.
The designer also lets you create a style block and a link to a cascading style sheet. For more information, see
Walkthrough: Working with Cascading Style Sheet Styles in Visual Web Developer.
By default, the editor creates markup that is compatible with the XHTML 1.1 standard and converts all HTML tag names
to lowercase, even if you type them in uppercase. The editor also encloses attribute (property) values in quotation marks.
For more information, see Walkthrough: Advanced HTML Editing in Visual Web Developer.

To change the default markup validation


1. In Source view, right-click the page, and then click Formatting and Validation.
2. In the Options dialog box, expand Text Editor, expand HTML, and then click Validation.
3. In the Target list, enter a validation type.
Next Steps
This walkthrough has given you an overview of the HTML capabilities of the Web page editor. This includes how to create
HTML in Design view and Source view, basic formatting, and navigation. You might want to learn more about the editing
facilities in Visual Web Developer. For example, you might want to do the following:
Learn about the additional capabilities of the HTML editor, including custom formatting options, outlining, and HTML
validation. For more information, see Walkthrough: Advanced HTML Editing in Visual Web Developer.
Learn how to work with cascading style sheet styles. For more information, see
Walkthrough: Working with Cascading Style Sheet Styles in Visual Web Developer .
See Also
Tasks
Walkthrough: Advanced HTML Editing in Visual Web Developer
Reference
Source View
Concepts
Design View
Visual Web Developer

Walkthrough: Advanced HTML Editing in Visual Web


Developer
The Microsoft Visual Web Developer Web development tool provides a rich HTML editing experience for creating Web pages.
This walkthrough introduces some of the more advanced HTML editing features of Visual Web Developer.
Note
For an introduction to HTML editing, see Walkthrough: Basic HTML Editing in Visual Web Developer.

Tasks illustrated in this walkthrough include the following:


Specifying options for how the HTML editor formats elements in the page.
Selecting options so that the HTML editor that you create is compatible with specific browsers.
Outlining your page — that is, creating collapsible regions in the editor to reduce clutter.
Prerequisites
In order to complete this walkthrough, you will need:
A general understanding of working in Visual Web Developer.
For an introduction to Visual Web Developer, see Walkthrough: Basic HTML Editing in Visual Web Developer.
Creating the Web Site and Page
If you have already created a Web site in Visual Web Developer (by completing
Walkthrough: Basic HTML Editing in Visual Web Developer), go to the next section. Otherwise, create a new Web site and page
by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, enter the name of the folder where you want to keep the pages of the Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click the programming language that you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Note
By default, Visual Web Developer creates ASP.NET Web pages using the code-behind model. For more information, see
ASP.NET Web Page Code Model. In this walkthrough, you will not be using the code-behind page.

Formatting Markup
The HTML editor provides a variety of options to help you format the markup in your pages according to your own
preferences. Formatting options include the following:
Whether tag and attribute names are in uppercase or lowercase letters. You can specify options separately for HTML tags
and ASP.NET Web server controls.
Whether attributes are added by enclosing them in quotation marks.
Whether elements are closed automatically by the editor. Choices include creating self-closing tags (for example, <br />),
creating opening and closing tags (<p></p>), and automatically inserting closing tags.
How child elements of a tag are indented.
Where line breaks are positioned around tags.
Regardless of what formatting options you set, an important feature of HTML formatting is that you have ultimate control over
the layout and appearance of the markup in the page. You can format elements manually (for example, by indenting them),
and the editor leaves your formatting as is unless you explicitly make a request to have the markup reformatted.
In this part of the walkthrough, you will explore different formatting options and see the effect of different settings. You will
also learn how to apply formatting to the whole page or to a selection within the page.
Note
This walkthrough reviews only the formatting features that are unique to working with HTML. As a Visual Web Developer tex
t editor, the HTML editor also supports various options that apply to all text editing, such as setting tab size and line wrap. For
information about general text editing options, see Editing Text, Code, and Markup.

In this part of the walkthrough, you will add some simple HTML to the page, change formatting options, and then add more
HTML. This illustrates how changing the settings affects how the HTML is formatted.
To add HTML elements that have default formatting options
1. Switch to Design view.
2. On the Layout menu, click Insert Table, and then click OK.
Do not change any one of the default settings in the dialog box.
The designer creates an HTML table with three columns and three rows.
3. Below the table, click the page.
4. Press ENTER several times to create some blank space, and then from the HTML group in the Toolbox, drag an Image
control onto the page.
5. Switch to Source view.
You will see that the <table> and <img> elements have been inserted in the page.
By default, the designer creates elements in which the tag and attribute names are lowercase and attributes are enclosed
in quotation marks.
You can now change the formatting options.
To change formatting and validation options
1. On the Tools menu, click Options.
2. Click Validation, and then in the Target list, click Internet Explorer 6.0.
3. Click Format.
You can set some options separately for server tags (ASP.NET server controls) and client tags (HTML elements).
4. In the Client tag list, click Uppercase.
5. Clear the Insert attribute value quotes when formatting and Insert attribute value quotes when typing check
boxes.
6. Click OK to return the editor.
Notice that although you changed formatting options, the existing markup in the page does not change.
You can now add new elements.
To add HTML elements using the new formatting options
1. Scroll to the bottom of the page.
2. From the HTML group in the Toolbox, drag a Table control onto the page and position it above the </form> tag.
This time, the tags in the <TABLE> element are in uppercase letters.
3. Below the table that you just created, position the insertion point, and then type a right angle bracket (<) to start a new
tag.
A list appears in which all the tag names are offered in uppercase, because that is the option that you have set for
formatting.
4. In the list, double-click IMG, and then press the SPACEBAR.
A list of attributes for the <img> tag appears. The attributes are in lowercase, because when you set formatting options,
you left Client attributes as the default setting for Lowercase.
5. In Properties, set Src to graphic.gif, which is an invented graphic file name, and make sure that the tag now looks
similar to the following:

<IMG src=graphic.gif

Because you disable the Insert attribute value quotes when typing option in the preceding procedure, the editor does
not automatically enclose the attribute in quotation marks.
Note
The editor inserts quotation marks, regardless of the options setting, if the attribute requires them, such as when an att
ribute value contains a space.

6. Type a slash mark (/) and a right angle bracket (>) to close the <img> tag.
As noted earlier in this section, the formatting options that you set were not applied to existing markup in the page. However, if
you want, you can apply formatting settings to the page or to individual elements in the page.
To apply formatting to existing elements
1. In Source view, highlight to select the first table that you created.
2. On the Edit menu, click Format Selection.
The tag names are changed to uppercase.
Note
The editor does not remove quotation marks, even if you change the option setting. Similarly, the editor does not chan
ge the termination of existing tags, even if you change the option for how to close tags.

You can see from this example how formatting works in the HTML editor. When you use editing tools, such as Toolbox or
Properties, to edit elements, the editor uses the current set of formatting options to generate the markup. However, the editor
does not change any existing markup. If you want to apply new formatting options to existing markup, you can apply it
manually by using the Edit menu commands.
Setting Tag Formatting Options
The formatting options that you have worked with up to this point apply to all elements in the page. If you want, you can
specify formatting options for individual tags also. This is useful if you frequently use certain tags and want to use non-default
formatting for those tags. Per-tag formatting lets you set the following formatting options:
How the tags are closed—that is, not closed, self-terminated, or with a separate closing tag.
How line breaks are used around and within tags.
How child elements of a tag are indented.
Note
Tag-specific formatting rules that you specify can be overridden by the rule that the HTML editor will not change the re
ndering of tags. If a tag formatting rule would change the way a tag is rendered, the rule is ignored.

In this part of the walkthrough, you will set several tag formatting options and see how the editor works with them. Up to this
point, you have worked with HTML elements, such as the <table> element. Now, you will work with some ASP.NET server
controls, so that you can see that formatting options apply equally to controls and elements.
You will start by setting some options that apply to all tags of a certain type. You can set options for the following types of
elements:
HTML elements that do not have content, such as br and input.
HTML elements that can have content, such as table and span.
Server elements (asp:) that cannot have content, such as asp:image.
Server elements that can have content, such as asp:textbox.
Security Note
A TextBox control accepts user input, which is a potential security threat. By default, ASP.NET Web pages validate that user in
put does not include script or HTML elements. For more information, see Script Exploits Overview.

For the first part of this section, you will add an HTML table. You will then change the tag formatting rules for table elements
and reformat the document to see the effect of changing the formatting rule.
To set tag-formatting rules for an HTML table
1. In Source view, in a blank part of the window, right-click, and then click Formatting and Validation.
The Options dialog box appears with the options for formatting that you set in the preceding section.
2. In the Client Tag list, click Lowercase to reset the formatting for client tags.
3. Click OK to close the Options dialog box.
4. From the HTML group in the Toolbox, drag a Table control onto the page.
The editor creates a <table> element that has three rows (<tr> elements) and three cells (<td> elements) in each row.
Each tag is on a separate line:

<table>
<tr>
<td>
</td>
</tr>

5. In a blank part of the window, right-click, and then click Formatting and Validation.
6. Click Tag specific options.
7. Expand Default Settings.
A list of tag types appears, starting with Client tag does not support contents. By selecting an item in the list, you can
set different options for client and server elements, for elements that have content (such as a table element), and for
elements that do not (such as an img element).
8. Click Client tag supports contents.
Notice that the default setting is that tags use a separate closing tag and that the tags have line breaks before, within, and
after the tag.
9. Expand Client HTML tags.
10. Click td.
You will set options to change how td tags are formatted.
11. In the Line breaks list, click None.
12. Click OK to close the Tag Specific Options dialog box, and then click OK to close the Options dialog box.
13. On the Edit menu, click Format Document.
The document is reformatted. The <td> tags in the table that you added are placed in a single line:

<table>
<tr>
<td></td><td></td><td></td>

You can work with tag-specific options for an ASP.NET server control.
To set formatting options for an ASP.NET server control
1. Switch to Design view.
2. From the Standard group in the Toolbox, drag a ListBox control onto the page.
3. Right-click the ListBox control, and then click Show Smart Tag.
4. In the ListBox Tasks dialog box, click Edit Items.
The ListItem Collection Editor dialog box appears.
5. Click Add two times to add two items.
6. Under Members, click the first ListItem, and then under ListItem properties, set Text to Item 1.
7. Under Members, click the first ListItem, and then under ListItem properties,, set Text to Item 2.
8. Click OK to close the ListItem Collection Editor dialog box.
9. Switch to Source view.
Notice that the control has been formatted in the following manner:

<asp:Listbox ID="ListBox1" runat="server">


<asp:ListItem>Item 1</asp:Listitem>
<asp:ListItem>Item 2</asp:Listitem>
</asp:Listbox>

10. In a blank part of the window, right-click, and then click Formatting and Validation.
11. Click Tag specific options.
12. In the Tag Specific Options dialog box, click ASP.NET Controls, and then click New Tag.
13. In the Tag name box, type asp:listitem.
Do not type the right and left angle brackets (< and >) as part of the tag name.
You are setting options for the asp:ListItem element that is used inside a ListBox control. You are not setting options for
the asp:ListBox element, because you want to control how the contents (children) of the asp:ListBox element are
formatted.
14. Click OK to close the New Tag dialog box.
15. In the Line breaks list, click None.
This will cause the control to have no line breaks in it.
16. Click OK to close the Tag Specific Options dialog box, and then click OK to close the Options dialog box.
You can now see the effect of your new formatting options.
To add an ASP.NET server control using the new formatting options
1. Switch to Design view.
2. From the Standard group in the Toolbox, drag a second ListBox control onto the page.
3. Right-click ListBox, and then click Show Smart Tag.
4. On the ListBox Tasks menu, click Edit Items.
5. For the ListBox control, create two items as you did in the preceding procedure.
6. Switch to Source view.
Notice that the <asp:ListItem> elements are all on one line. The </asp:ListBox> element appears on the next line
because tag wrapping is set to 80 characters. You can modify this value in the Options dialog box.
Although you worked with only two controls and changed only one formatting option (line breaks), you can see how to apply
options to any element that you typically work with.
Outlining Elements
In Source view, you can outline elements (collapse and expand them) so that they are out of your way when you are not
working with them. This is particularly useful for elements such as tables, which often take up a lot of space. You can also use
the collapse feature for any elements in the page.
To outline elements
1. Switch to Source view.
2. Select one of the tables that you added earlier.
If you no longer have the tables, from the HTML group in the Toolbox, drag one onto the page.
3. On the Edit menu, point to Outlining, and then click Hide Selection.
The <table> tag is collapsed and a plus sign (+) is displayed in the margin.
4. Click the plus sign to expand the table element.
You can also configure elements so that the plus (+) and minus (-) signs appear automatically in the margin when the
elements exceed a certain size.
To configure how elements are outlined automatically
1. Right-click the page, click Formatting and Validation, click Format, and then click Tag specific options.
2. In the Tab Specific Options dialog box, expand Client HTML tags, and then click table.
3. Under Outlining in code editor, in the Minimum lines box, enter 5.
4. Click OK, and then click OK.
For existing tables and any new tables that are added, outlining appears automatically, if the table exceeds five lines.
Validating HTML
The HTML editor can validate your HTML or make sure that it complies with the rules for specific browsers or standards, such
as XHTML. For example, the editor can find tags and attributes that are not accepted by Netscape Navigator 4.0 or that do not
comply with XHTML standards.
In this part of the walkthrough, you will work with different schemas (browser types or standards) and introduce various types
of small errors to see how the editor flags the errors.
To test validation in the editor
1. In Source view, open or switch to the Default.aspx page.
2. On the HTML Source Editing toolbar, in the list, click Internet Explorer 3.02/Netscape Navigator 3.0.
3. Scroll to the bottom of the page.
4. Inside the </form> tag, type the following HTML:

<font face=arial>
<a href=Default.aspx >Default Page </a>
</font>

As you type, Microsoft IntelliSense technology provides assistance in completing the tags.
5. On the HTML Source Editing toolbar, in the list, click XHTML 1.0 Transitional (Netscape 7, Opera 7, Internet Explorer
6).
After a short pause (because validation is performed as a background task), you see red squiggly lines underneath
various parts of the tags. Like a spell checker, the HTML validation feature finds markup in your page that is not
acceptable for the currently selected browser.
6. In the <font> tag, rest the mouse pointer over the word font.
A ToolTip informs you that the font element is considered outdated. Current standards now recommend that you use
cascading style sheet styles for text formatting. For example, <span style="font-name:Arial;">.
7. In the href attribute of the <a> tag, rest the mouse pointer over Default.aspx.
A ToolTip informs you that in the current schema, attributes must be enclosed in quotation marks.
8. Enclose Default.aspx in quotation marks.
The value for the href attribute is no longer underlined. If you use relative references for anchor tags or other tags that
require a URL, validation determines whether the target element is available.
9. In the line below the HTML you are working with, type a right angle bracket (<).
The IntelliSense drop-down list appears, but this time it does not offer font, because the font element is not valid in
XHTML schemas.
10. Delete the right angle bracket (<).
Setting Validation Options
You can control the types of errors that validation shows you. This is useful if you want validation to find certain types of
errors, even if the errors would be allowed in a particular schema.
To set validation options
1. Right-click anywhere in the page, and then click Formatting and Validation.
Note
The Formatting and Validation command is available only in Source view.

2. In the Options dialog box, click Validation.


Notice that regardless of whether you select or clear the Show errors check box, the error display for check boxes is not
enabled. This is because the current schema is XHTML, which already shows you all possible validation errors.
3. In the Target list, click Internet Explorer 6.
4. Make sure that the Show errors check box is selected, and then under Show errors, select all check boxes.
5. Click OK to return to the editor.
6. Select the HTML that you entered in the preceding procedure, and then on the Edit menu, click Make Uppercase.
After a brief pause, the tag names are underlined. When you rest the mouse pointer over a tag name, a ToolTip indicates
that the name contains uppercase letters. Generally, Internet Explorer 6 allows for uppercase tag names, but you now see
this validation error because you have changed the validation options for that schema.
Validation can find many other types of errors also, such as duplicated control IDs, crossed opening and closing tags (for
example, <b><i></b></i>), and so on. However, validation in the editor does not prevent you from creating any HTML code
that you want. Validation just identifies markup that does not comply with the rules for the specified browser.
You should understand that when an ASP.NET page runs, the resulting output consists not only of the HTML elements that you
create, but also of the HTML that is rendered by ASP.NET server controls and any code that writes to the page. Validation
cannot examine the output of those dynamic elements; that is, the editor cannot examine the validity of generated output. By
default, ASP.NET controls generate output that complies with XHTML 1.1 standards. This means that the output is suited for
most browsers. For more information about the markup that is generated by ASP.NET controls, see ASP.NET and XHTML.
Next Steps
This walkthrough has introduced you to some of the more advanced features of the HTML editor. Although the walkthrough
did not illustrate every feature, you have seen how formatting options, outlining, and validation can help you produce well-
formed, custom-formatted markup, although still giving you final control over the markup.
See Also
Concepts
XHTML in Visual Web Developer
Markup Validation in Visual Web Developer
Other Resources
Editing Text, Code, and Markup
Product Support and Accessibility
Visual Web Developer

Formatting Elements in the HTML Editor in Visual Web


Developer
When you are working in the HTML designer, the editor can assist you with formatting elements. This topic describes the
formatting facilities of the editor for working with markup elements.
Default Formatting
By default, the HTML editor allows you to format markup any way you like, retaining line breaks and indentation exactly as you
type them. The editor includes features that assist you in formatting your elements. For example, if you indent a line by
pressing TAB, subsequent lines are indented as well. You can remove a line indentation using SHIFT+TAB. The formatting you
apply to your page is retained as you switch between Source view and Design view.
You can set basic options for how the editor in Source view treats tabs. For details, see
Tabs, HTML, Text Editor, Options Dialog Box.
In addition, you can set options that cause the editor to automatically insert quotation marks and closing tags as you type. For
details, see Format, HTML, Text Editor, Options Dialog Box.
Formatting and the Current Schema
Certain formatting options, such as capitalization and the use of quotation marks around attributes, can be overridden by the
schema you select for the editor. For example, if you select the schema XHTML 1.1 Strict, the editor converts uppercase tag and
attribute names to lowercase, because the schema allows only lowercase names.
Specifying Formatting Options
When you create elements, the designer formats the new element using certain options that you can set. For example, by
default client elements (such as HTML tags) are created with lowercase tag names. The formatting options are applied when:
You drag controls from the Toolbox onto the page.
You use IntelliSense to create tags in Source view.
You set values in the Properties window or in property builders.
You paste an element from the Clipboard.
You generate markup using a dialog box such as the Insert Table Dialog Box in Design view.
You manually format the selection or document.
For details on how to set formatting options, see Format, HTML, Text Editor, Options Dialog Box and
Miscellaneous, HTML, Text Editor, Options Dialog Box.
Formatting Options for Individual Tags
You can also set formatting options for tags individually, which allows you to customize how the HTML designer formats
markup for individual tags. Tag-specific formatting allows you to set:
How the tags are closed (not closed, self-terminated, or with a separate closing tag).
Line breaks around and within tags.
How tags are indented.
Outlining options.
Colorization of tags in the editor.
For details, see Tag Specific Options.
Formatting on Demand
You can format the document or a selection at any time using the Format Document command on the Edit menu or shortcut
menu. Other options available on this menu for formatting include options to convert selections to uppercase or lowercase and
to convert spaces to tabs (Tabify Selection) or tabs to spaces (Untabify Selection). When you manually format, the editor
uses the formatting options you have set (unless you are explicitly overriding a rule, such as when converting case). If you
change the formatting options, you can apply them to existing markup by reformatting the document.
Rules for Preserving White Space
The editor's formatting process is careful to respect how HTML should render white space in the browser. The editor will
therefore not change the formatting of an element if that would result in a change to how the page is rendered. You will notice
this behavior in the editor particularly when working with markup that does not include spaces between tags.
For example, your page might include the following markup for two HTML buttons:

<input type="button" id="b1"><input type="button" id="b2">

When the page is rendered, the two buttons appear without any space between them. If you format the document in the editor,
you might expect the two tags to be placed on their own lines. However, placing the tags on two lines would result in a space
appearing between the buttons when the page renders, so the editor does not move the tags. If you manually put a space
between the tags, then the formatting can change that to a line break, because the reformatting then does not affect how the
buttons render in the browser.
Another common case where white-space rules override formatting is between content and the end tag. For example, your
document might contain the following table element, all on one line:

<table><tr><td>Hello, World</td></tr></table>

If you reformat the document manually, the result is the following:

<table>
<tr>
<td>
Hello, World</td>
</tr>
</table>

The closing </td> tag is not moved to the next line, because that would affect how the cell is rendered. If you insert a space
manually between "Hello, World" and the </td> tag and then reformat the document, the editor will move the closing tag to
the next line.
Formatting Code Inline
As a rule, client script and server code in ASP.NET Web pages are formatted according to the rules for the language editor.
Carriage-return behavior, new line generation, indenting, and so on are all dictated by the respective language formatter. For
example, the Visual Basic language formatter automatically indents the line following a Function declaration.
In Source view, script blocks are indented one level with respect to their parent element. Inline expressions — those beginning
with <%#, <%$, or <%= — are not formatted; they are left as you type them. However, if you type a block of statements
individually delimited with <% %> delimiters, the editor will format the block as if it were one block using the indentation rules
of the appropriate language.
See Also
Reference
Source View
Visual Web Developer

How to: Collapse and Expand HTML Elements in Visual Web


Developer
To help you work with large pages, Source view allows you to create outline regions. You can then collapse and expand the
regions when you want to hide or show them.
By default, the editor is configured to treat certain HTML elements as collapsible regions. You can set options to change which
elements are collapsible and how many lines the element must contain before it is automatically treated as a collapsible region.
For details, see Tag Specific Options.
To create or remove a collapsible region
1. Select the text you want to treat as a collapsible region.
2. To create a collapsible region, on the Edit menu, point to Outlining, and then click Hide Selection.
The editor turns the selection into a region, collapses it, and displays a box with an ellipsis (...) to indicate that the area
contains a collapsed area. You can hold the mouse pointer over the box to see its contents.
3. To remove a collapsible region, collapse it, and then click it to select it.
4. On the Edit menu, point to Outlining, and then click Stop Hiding Current.
To collapse and expand a single region
1. To collapse a region, click the minus sign (-) in the margin of the editor.
2. To expand a collapsed region, click the plus sign (+) in the margin.
To collapse and expand all regions
On the Edit menu, point to Outlining, and then click Toggle All Outlining.
See Also
Other Resources
Source View, Web Page Designer
Visual Web Developer

How to: Create Scripts and Edit Event Handlers


As you edit an HTML document in Visual Studio 2005, you can create client-script functions that cause elements on the page to
respond to user actions. For example, if your page contains an HTML button (an <input type="button"> element, not an
ASP.NET Button server control), you can select a button and then add a client-script event handler for its click event. The
DefaultClientScript Property of an HTML document or ASP.NET Web page sets the default scripting language that is used for
new client-side script elements. You can set the DefaultClientScript Property in the Properties window. For more information,
see How to: Set the DefaultClientScript Property of a Web Page.
Note
You can add client script to ASP.NET server controls so that the controls respond to user actions in both client script and serv
er code. For more information, see Client Script in ASP.NET Web Pages.

In Visual Studio 2005, you can create event handlers for HTML controls (input elements) and for the document and window
objects. In addition, you can create handlers and scripts for all elements by coding them manually.
Note
The shortcut key combination CTRL + F2 places the mouse pointer focus in the Object drop-down list where you can specify
which object you want to insert an event for. What the Object list displays depends on whether you are using a code-behind
page model or single-file page model for your Web page. For the code-behind page model, you can insert events for Client
Objects & Events and Client Script. For the single-file page model, you can insert events for Server Objects & Events, Se
rver Code, Client Objects & Events, and Client Script.

Security Note
Always encode and validate user input in your Web application before using it. This helps protect against script exploit attack
s. For more information, see Basic Security Practices for Web Applications and Validating User Input in ASP.NET Web Pages.

To create a client-script event handler


1. In Source view, open the HTML or ASP.NET Web page that you want to work on.
2. In the Client Objects & Events box, click the control that you want to write a handler for.
3. In the upper-right box, click the event.
The editor creates a skeleton event handler, and if necessary, a script block to contain it. The script block uses the client-
script language that is set as the DefaultClientScript Property for the document.
4. Fill in the script.
The editor provides Microsoft IntelliSense technology to assist you.
See Also
Reference
HTML Designer Shortcut Keys, General Development Settings
Concepts
Client Script in ASP.NET Web Pages
ASP.NET Web Page Code Model
Visual Web Developer

How to: Choose an Alternate HTML Editor in Visual Web


Developer
The default editor for HTML documents and ASP.NET pages is the Microsoft Visual Web Developer Web development tool.
However, you can specify any installed text editor as your Visual Studio 2005 editor for viewing and editing HTML documents.
To open a document in another editor
1. In Solution Explorer, right-click the document, and then click Open With.
2. In the Open With <Filename> dialog box, click an editor, and then click OK.
Note
The Open With dialog box also includes the Set as Default option. Choose the Set as Default button to designate an
other available editor as your default editor for HTML documents.

To add an editor
1. In the Open With dialog box, click Add.
The Add Program dialog box appears.
2. In the Program name box, type the path to your editor or click the ellipsis (…) button to browse to the program.
3. In the Friendly name box, type a friendly name for the editor.
See Also
Other Resources
Web Page Designer
Visual Web Developer

Web Page Designer Keyboard Shortcuts


The Web page designer in Visual Web Developer provides keyboard shortcuts that help save time and effort, as well as provide
an essential tool for people with limited dexterity and other disabilities.
Keyboard Shortcuts
The following table lists the keyboard shortcuts that are available in the Web page designer.
Note
You can view all of the keyboard shortcuts for Visual Web Developer by doing the following: on the Tools menu, select Opti
ons; and in the Options dialog box, select Environment and then Keyboard.

Shortcut Description
CTRL+B Switches the selected text between bold and normal.

CTRL+I Switches the font style of the selected text between italic and roman.

CTRL+U Switches the font style of the selected text between underline and roman.

CTRL+SHIFT+L Displays the Bookmark dialog box.

CTRL+L When text is selected, displays the Hyperlink dialog box.

CTRL+SHIFT+W Displays your Web page in the default browser.

CTRL+ALT+UP A Inserts one row above the selected row in the table.
RROW

CTRL+ALT+DO Inserts one row below the selected row in the table.
WN ARROW

CTRL+ALT+LEFT Inserts one column to the left of the selected column in the table.
ARROW

CTRL+ALT+RIGH Inserts one column to the right of the selected column in the table.
T ARROW

CTRL+SHIFT+Q Switches the display of marker icons for HTML elements that do not have a visual representation, such as co
mments, scripts, and anchors for absolutely positioned elements.

CTRL+PAGE DO Switches from Design view to Source view and vice versa.
WN
CTRL+PAGE UP

CTRL+Q Displays a 1-pixel border around HTML elements that support a border attribute and have it set to zero, suc
h as tables, table cells, and divisions.

See Also
Tasks
Walkthrough: Basic HTML Editing in Visual Web Developer
Concepts
How-to Topics — Web Page Designer
Walkthrough Topics — Web Page Designer
What's New in the Web Page Designer and Editors
Other Resources
Web Page Designer
Design View, Web Page Designer
Visual Web Developer

Paste Operations in the HTML Designer of Visual Web


Developer
When you are copying text from other applications into the HTML designer, the behavior that you want to achieve went
pasting depends on how you want the text to appear. To accommodate different possibilities, the HTML designer offers two
paste commands that are accessible from the Edit menu: Paste and Paste Alternate.
In general, the goal is to allow you to paste the text so that either:
The text looks as much as possible as it did in your source application. For example, if the original text is
<b>Example</b>, it is pasted so that when the page is rendered, it looks like <b>Example</b>.
The text is interpreted as markup. For example, if the original text is <b>Example</b>, it is pasted so that when the page
is rendered, it looks like Example.
You can paste in both Design view and Source view, so paste behavior depends on the view in which you are working.
Text can be on the Windows Clipboard in a variety of formats, including plain text, HTML, rich-text format (RTF), and others.
When pasting text, therefore, the effect of pasting depends on how rich the formatting information is for the text on the
Clipboard.
If the text is on the Clipboard as plain text — for example, the text was copied from Notepad or another text editor — the Paste
command pastes it as-is. The Paste Alternate command encodes HTML characters.
If the text is on the Clipboard in a rich format (for example, HTML or RTF):
In Design view, the Paste command pastes the text so that it looks like the original. The Paste Alternate command turns
formatting information into HTML markup (that is, it encodes the string).
In Source view, the Paste command pastes the text as an unformatted string. The Paste Alternate command encodes
the string.
The following table lists the behavior of the two Paste commands under different circumstances. The table takes into account
the source of the text (plain text or rich text), where you are pasting the text, and which paste command you use.
Source Destin Resulting view in the Designer using Paste Resulting view in the Designer usin
ation g Paste Alternate
Plain text(for example, Design text <b>text</b>
Notepad) view
Note Note
Original: <b>text</b>
In Source view, this text is converted to <strong>tex In Source view, this text is converted to
t</strong>. &lt;b&gt;text&lt;/b&gt;.

Plain text(for example, Source <b>text</b> &lt;b&gt;text&lt;b&gt;


Notepad) view
Original: <b>text</b>

Rich text(for example, Design text <b>text</b> text text


browser or Help) view
Note Note
Original: text <b>text
</b> In Source view, this text is converted to <strong>tex In Source view, this text is converted to
t</strong> &lt;b&gt;text&lt;b&gt;. text <b>text</b>.

Rich text(for example, Source text <b>text</b> <b>text</b> &lt;b&gt;text&lt;/b&gt


;
browser or Help) view
Original: text <b>text
</b>
See Also
Reference
Source View
Concepts
Design View
Visual Web Developer

How to: Navigate in the HTML Editor in Visual Web Developer


The HTML designer provides you with a number of ways to navigate in your document. The navigation facilities are particularly
useful if you are working with a long document or one with deeply nested elements. You can use the following:
The Document Outline window, which presents a tree view of your document.
The tag navigator, which displays the currently selected tag in the context of its parent, child, and peer tags.
Tag matching to identify the opening and closing tags for an element. Tag matching can help you distinguish the current
element from others, which is especially useful when you have many nested elements on the page.

To navigate by using the Document Outline window


1. On the View menu, click Document Outline. If you are in Source view, right-click the document and then click
Synchronize Document Outline.
The Document Outline displays a tree view of the elements in your document. The exact elements that are displayed
depend on which view you are in:
In Design view, the outline displays elements in the body of the document.
In Source view, the outline shows the body element as well as elements in the head, the page directive, and script
and code elements, if any.
2. In the Document Outline window, expand or collapse sections, as needed.
3. Click an element to navigate to it.
The element you click is selected in the designer.
To navigate by using the tag navigator
1. At the bottom of the designer window, click the tag to which you want to move.
2. To move higher in the tag hierarchy, click the left arrow button in the navigator. To move deeper in the tag hierarchy,
click the right arrow button.
Note
If you have a deep hierarchy, the tree view might not fit into the space available. To scroll higher in the tag hierarchy, cli
ck the left arrow button in the navigator. To scroll deeper in the tag hierarchy, click the right arrow button.

To identify matching tags by using tag highlighting


In Source view, place the insertion point anywhere within an element.
The element's opening and closing tags are displayed. Because tag highlighting is performed as a background task, there
might be a small delay before the tags are highlighted.
See Also
Tasks
How to: Collapse and Expand HTML Elements in Visual Web Developer
Reference
Document Outline Window
Concepts
HTML Editor Tag Navigation in Visual Web Developer
Visual Web Developer

Cascading Style Sheet Editing (Visual Studio)


The topics in this section provide information on creating cascading style sheets (CSS) in Visual Web Developer.
In This Section
Cascading Style Sheets Overview
Walkthrough: Working with Cascading Style Sheet Styles in Visual Web Developer
How to: Create External Cascading Style Sheets (Visual Studio)
How to: Link Cascading Style Sheets to ASP.NET Web Pages (Visual Studio)
How to: Add Cascading Style Sheet Attributes in Design View
See Also
Other Resources
Source View, Web Page Designer
Web Page Designer
ASP.NET Web Sites (Visual Studio)
ASP.NET Web Pages (Visual Studio)
ASP.NET Web Server Controls (Visual Studio)
Visual Web Developer

Cascading Style Sheets Overview


A cascading style sheet (CSS) contains style rules that are applied to elements in a Web page. CSS styles define how elements
are displayed and where they are positioned on the page. Instead of assigning attributes to each element on your page
individually, you can create a general rule that applies attributes whenever a Web browser encounters an instance of an
element or an element that is assigned to a certain style class.
CSS styles can be placed inline within a single HTML element, grouped in a style block within the head section of a Web page,
or imported from a separate style sheet. If styles are created in a separate style sheet, you can link multiple Web pages to the
style sheet, thus giving a common appearance to an entire Web site. If you are using CSS to style web controls, you should use
the CssClass property to define a CSS class name to be associated with the control or control elements and then reference that
class name when assigning styles to the control or control elements in the style sheet.
Note
CSS styles are not supported in all browsers. Older Web browsers that support only HTML 3.2 or earlier will ignore CSS style
s, and support for browsers on mobile devices varies. You can select a browser schema in Visual Studio .NET that will validat
e the styles you are using and provide IntelliSense for styles in Source view. For details, see
How to: Select Validation Schemas for HTML Editing in Visual Web Developer.

Defining CSS Style Rules in Style Blocks


Each CSS style rule has two main parts — a selector (such as h1) and a declaration (such as color:red). The declaration
includes a property (color) and its value (red). The syntax is as follows:

Selector { property : value ; property2 : value2}

A simple CSS style rule, which specifies that any text contained within <h1></h1> tags be centered and the font color formatted
as red is written as follows:

H1 {text-align:center; color:red;}

CSS style rules can be defined in a style block within the head element of your Web page. The following code example defines
and applies a CSS style rule to all of the h1 elements on a Web page:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">


<html>
<head>
<title>HTML 4.0 CSS Element Style Example</title>
<style type="text/css">
h1{text-align:center; color:red;}
</style>
</head>
<body>
<h1>This text is centered and red</h1>
</body>
</html>

On this Web page, any text that appears between the <h1></h1> tags will be centered and red. You do not need to reassign
these style attributes for each <h1> tag that occurs in the document. If you want to change the color (or any other property) of
all text between the <h1></h1> tags, you can do so by editing one style rule.
Precedence of CSS Style Rules
CSS style rules cascade in the sense that global style rules continue to apply to HTML elements unless local style rules override
them. In general, local style rules take precedence over general style rules. This means, for example, that a style defined in a
style block in a Web page overrides a style defined in an external style sheet. Similarly, an inline style that is defined within a
single HTML element on the page overrides any styles that are defined for that same element elsewhere.
Portions of global style rules not overridden by local CSS style rules continue to apply to elements even after local styles are
applied. In the code example in the previous section, the local CSS styles governing text in the h1 element replace some of the
Web browser's global style rules for h1 text (center h1 text and make it red), but they do not change all of the available styles,
such as font characteristics. Both global and local style rules are applied, in that order, making all the h1 text on this page
display in a larger font that is formatted as bold, centered, and colored red.
CSS Styles and ASP.NET Themes
ASP.NET allows you to define themes, which are a combination of property settings for Web server controls, style sheet rules,
and images. By applying a theme to a Web site, you can specify a consistent look across all of the pages in the site.
Themes are similar to styles in that they define a global set of characteristics for elements on a page. However, unlike styles in
a style block or style sheet, you can control the precedence of settings. By default, when you apply a theme to a page or a Web
site, the styles and other properties in the theme take precedence over the locally defined styles. This is the opposite behavior
from the way styles are normally applied. This behavior was designed to allow themes to be applied to existing pages
(including those with locally defined styles) and establish the same look for different pages.
You can also apply a theme as a style sheet theme. In that case, the styles and properties defined in the theme are applied in
the same way that CSS styles are — local styles take precedence over styles that are defined in the theme. For more
information, see ASP.NET Themes and Skins Overview.
Assigning HTML Elements to a CSS Style Class
You can define styles to apply to tags by tag name, such as h1. To allow you to create different styles for the same element, or
the same style for different elements, you can create CSS classes. A class defines styles in the same way as any other style
definition. However, you give the style a name. To apply the style to an element, you specify the style name as the class
attribute of the tag. For instance, the following code example is a style definition for the class head2:

.head2 {font-size:14pt; text-align:center; color:red; font-weight:bold; font-style:italic;}

To apply this type of style inline, add a class attribute to a tag that supports inline styles as shown in the following code
example.

<div class="head2">

What makes head2 a class is the period (.) character. You could have made head2 a class for h1 tags only by declaring it as
follows:

H1.head2 {font-size:14pt; text-align:center; color:red; font-weight:bold; font-style:italic


;}

External Cascading Style Sheets


An external style sheet is a plaintext file with a .css file name extension that contains only style rules. You can link a style sheet
to a Web page by using a link element, as shown in the following code example.

<link rel="stylesheet" type="text/css" href="Mystyles.css" />

This link element applies the style rules in the external style sheet Mystyles.css to the page.
Style rules listed in an external style sheet are written just as they are when placed within a style block, but without <style>
</style> tags enclosing them, as shown in the following code example

h1 { text-align:center; color:red; }
.head2 { font-size:14pt; text-align:center; color:red; font-weight:bold; font-style:italic;
}

You can link multiple HTML pages to an external style sheet, which will apply consistent styles across an entire Web site. Style
sheets separate formatting rules from content, making it much easier to locate and edit style rules.
See Also
Tasks
Walkthrough: Working with Cascading Style Sheet Styles in Visual Web Developer
How to: Create External Cascading Style Sheets (Visual Studio)
How to: Add Cascading Style Sheet Attributes in Design View
Visual Web Developer

Walkthrough: Working with Cascading Style Sheet Styles in


Visual Web Developer
The Visual Web Developer Web development tool gives you complete support for creating and applying styles to the text,
elements, and controls on Web pages.
Tasks illustrated in this walkthrough include the following:
Setting inline styles for individual elements.
Creating a style block for a page.
Creating a cascading style sheet (.css file), and then applying the .css file to one or more pages in your site.
Changing style sheet references programmatically.
Note
In addition to explicitly setting styles and style sheet references in a page, you can use ASP.NET themes to set the overal
l appearance of the pages in your site. For more information, see ASP.NET Themes and Skins Overview.

Prerequisites
In order to complete this walkthrough, you will need the following:
Visual Web Developer and the .NET Framework.
A general understanding of working in Microsoft Visual Studio.
For an introduction to Visual Studio, see Walkthrough: Creating a Basic Web Page in Visual Web Developer.
Creating the Web Site and Page
In the first part of the walkthrough, you will create a Web site and a page where you can work with styles.
If you have already created a Web site in Visual Studio by completing
Walkthrough: Creating a Basic Web Page in Visual Web Developer, you can use that Web site and go to the next section.
Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. In the Language list, click the programming language that you prefer to work in.
The programming language that you choose will be the default for the Web site, but you can set the programming
language for each page individually.
4. Under Visual Studio installed templates, click ASP.NET Web Site.
5. In the right-most Location box, type the name of the folder where you want to keep the pages of the Web site.
For example, type the folder name C:\WebSites.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Adding Controls
The next step is to add some controls to the page. The code will be simple, but enough to let you add breakpoints later.
To add controls
1. Switch to Design view.
2. From the Standard group in the Toolbox, drag the following controls onto the page and set their properties as shown.

a. Control a. Properties

Label ID: CaptionLabel


Text: (empty)

TextBox ID: NumberTextbox


Text: (empty)

Button ID: SquareButton


Text: Square

Label ID: ResultLabel


Text: (empty)
Note
For this walkthrough, the layout of the page is not important.

Setting Inline Styles


You set inline styles when you want to apply formatting to a single element on the page. Visual Web Developer gives you a
rich editor for editing inline styles for elements on the page. In this section of the walkthrough, you will set styles in both
Design view and Source view.
To set inline styles in Design view
1. Switch to Design view.
2. Right-click CaptionLabel, and then click Style.
The Style Builder dialog box appears.
The Style Builder helps you set style information by organizing style information into logical categories and offering
you appropriate values and options for each style setting.
3. Click Font, click Family, and then click the ellipsis (...) that is located to the right of the text box.
The Font Picker dialog box appears.
Under Installed fonts, click Arial, and then click add (>>).
Arial appears under Selected fonts.
4. Repeat the preceding step to add Times New Roman and Verdana to the list of selected fonts, and then click OK.
When you return to the Style Builder dialog box, the three font names are in the Family box. You have created the list
of fonts that will be used to render the contents of the Label control in order of preference.
5. Under Size, click Specific, in the box, type 1.2, and then in the list, enter em.
By setting the size to 1.2 ems, you are indicating that the text will appear 1.2 times larger than the current font size
setting in the user's browser. At the bottom of the dialog box, you can see a preview of what the text will look similar to.
6. Click Background, click the ellipsis (…) that is located to the right of the Color box, and in the Color Picker dialog box,
click a color.
7. Click OK to close the Style Builder dialog box.
The text in the label now reflects the style settings that you made.
From these few steps, you can see that the Style Builder lets you set any inline style for any element without requiring that you
know the syntax.
If you prefer working directly with HTML, you can also set styles in Source view.
To set inline styles in Source view
1. Switch to Source view.
The <asp:label> element for the CaptionLabel control now has a style attribute that reflects the settings that you
made in the Style Builder.
2. Position the insertion pointer on a space in the <asp:button> element, and then type style=.
Note
The editor always puts quotation marks around the style attribute, regardless of the formatting options that you have s
et. For more information, see Walkthrough: Advanced HTML Editing in Visual Web Developer.

3. Double-click background-color, and then type a colon (:).


Microsoft IntelliSense functionality displays a list of color names. A ToolTip displays the syntax for the background-
color style setting.
4. Double-click Blue, type a semicolon (;), which is the delimiter between style settings, and then press SPACEBAR to
display IntelliSense functionality.
5. Double-click color, type a colon (:), and then double-click a contrasting color, such as Yellow or White.
6. To see the effect of your choices, switch to Design view.
Creating and Applying a CSS Style Sheet
Besides setting inline styles for individual elements, you can also create and apply cascading style sheet (CSS) files. A cascading
style sheet lets you define styles that can be applied to multiple controls and pages without having to edit elements
individually.
In this section of the walkthrough, you will create a style sheet, which lets you use the same tools that you used to set inline
styles. You will then apply the style sheet to the page that you have been editing.
To create a style sheet
1. In Solution Explorer, right-click the name of the Web site (for example, C:\WebSites), and then click Add New Item.
2. Under Visual Studio installed templates, click Style Sheet.
3. In the Name box, type dark.css, and then click Add.
The editor opens with a new style sheet that contains a body style element.
4. Position the insertion pointer between the opening and closing braces ({ }), and then on the Styles menu, click Build
Style.
The Style Builder - body dialog box appears.
5. Click Font, under Font Attributes, click the ellipsis (…) that is located to the right Color box, in the Color Picker dialog
box, click a light color, and then click OK.
Note
Be sure to select a color that is different from the default color of the pages in the Web site.

6. Click Background, click a dark color, such as Maroon, that contrasts with the font color you selected in the preceding
step, and then click OK to close the Style Builder- body dialog box.
7. Position the insertion pointer after the closing brace of the body element, right-click, and then click Add Style Rule.
The Add Style Rule dialog box appears.
The Add Style Rule dialog box lets you create new styles that are bound to a particular HTML element type, to a style
class name, or to a specific element.
8. Click Class name, and then in the box, type reverse.
This will create a new style class named reverse. You will be able to apply the style settings that you defined for the
reverse class to any element on your page. You could optionally create the class so that it applies to only specific types of
elements (anchors, buttons, and so on), but in this walkthrough you will create a simple style class.
9. Click OK to close the Add Style Rule dialog box.
10. Use the style builder or IntelliSense functionality to set the colors for the reverse style to the opposite of the styles for
the body. The element will look similar to the following:

.reverse
{
background-color:white;
color:maroon;
}

Now that you have a style sheet, you can reference it in the page you have been editing.
To reference the style sheet on the Web page
1. Open Default.aspx page and switch to Design view.
2. From Solution Explorer, drag the dark.css file onto the page.
The page is updated, displaying the effect of the style sheet.
3. Click ResultLabel, and then in Properties, set CssClass reverse.
This applies the reverse style to ResultLabel.
4. Switch to Source view.
In the <head> element, you can see that the editor has added a <link> element that references the style sheet. You can
also see that the cssclass attribute of the second <asp:label> element has been set to reverse.
5. Right-click the page, and then click View in Browser.
The page appears in the browser with the style sheet applied.
Changing Style Sheets Programmatically
Sometimes, you might want to be able to dynamically change the style sheet that is referenced by a page. In this part of the
walkthrough, you will create a second style sheet, and then in your page, write several lines of code that switch style sheets
programmatically.
To create a new style sheet
1. In Solution Explorer, right-click the Web site name, and then click Add New Item.
2. Under Visual Studio installed templates, click Style Sheet, in the Name box, type light.css, and then click Add.
3. In the new style sheet, use the Style Builder or IntelliSense functionality to create the following styles:

body
{
background-color:white;
color:Black;
}
.reverse
{
background-color:Black;
color:White;
}

4. Save the new style sheet.


In your original page, you can now add the ability to switch style sheets. You will add two radio buttons that let the user select
between a dark look and a light look.
To let users change style sheets
1. Open the Default.aspx page and switch to Source view.
2. In the <link> element, which is in the <head> element, add the attribute ID="stylesheet".
The tag will look similar to the following:

<link href="dark.css" type="text/css" rel="stylesheet" id="stylesheet" />

Adding these two attributes makes the <link> element a server control that you can program using server-based code.
3. Switch to Design view, and then from the Standard group in the Toolbox, drag two RadioButton controls onto the
page.
Note
The layout of the RadioButton controls is not important for this walkthrough.

4. Set the following properties for the RadioButton controls.

a. Control a. Properties

RadioButton1 ID: radioDark


AutoPostBack: true
Checked: true
GroupName: grpSelectStylesheet
Text: Dark

RadioButton2 ID: radioLight


AutoPostBack: true
Checked: false
GroupName: grpSelectStylesheet
Text: Light

5. Click radioDark and on the Properties toolbar, click the events icon to display available events.
6. In the CheckedChanged box, type SwitchStylesheets, and then press ENTER.
The editor creates a handler for the CheckedChanged event of the radioDark control.
7. Type or copy the following code, which switches the Href attribute of the <link>.
VB
Protected Sub SwitchStylesheets(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles radioDark.CheckedChanged
If radioDark.Checked Then
stylesheet.Href = "dark.css"
ElseIf radioLight.Checked Then
stylesheet.Href = "light.css"
End If
End Sub

C#
protected void SwitchStylesheets(Object sender, EventArgs e)
{
if (radioDark.Checked)
stylesheet.Href = "dark.css";
if (radioLight.Checked)
stylesheet.Href = "light.css";
}

The code determines which option button is selected and sets the Href attribute of the <link> element, which you
named stylesheet, appropriately.
8. Switch to Design view.
9. Click radioLight, and in Properties, click the events icon.
10. In the CheckedChanged box, click SwitchStylesheets.
This binds the CheckedChanged event of the radioLight control to the handler that you have already written to switch
style sheets. Both radio buttons will call the same handler when they are clicked.
You can now test your page.
To test the page
1. Press Ctrl+F5 to run the page.
2. Click Light.
The appearance of the page changes.
3. Click Dark to make sure that both option buttons work.
Next Steps
This walkthrough has illustrated the basic techniques for working with CSS styles in your ASP.NET Web pages. You might also
want to explore the following ways you can control the appearance of the Web pages:
Setting style information programmatically for HTML elements.
For more information, see How to: Set HTML Server Control Properties Programmatically.
Creating styles programmatically and applying the styles to ASP.NET server controls.
Creating themes and skins, which let you specify not only CSS styles, but virtually any property of an ASP.NET control.
For details, see ASP.NET Themes and Skins Overview.
Visual Web Developer

How to: Create External Cascading Style Sheets (Visual Studio)


An external cascading style sheet (CSS) contains CSS style attributes that can be applied to multiple Web pages. For
information about CSS styles, see Cascading Style Sheets Overview.
To add an external style sheet to a Web site project
1. In Solution Explorer, right-click the name of the Web site project to which you want to add a style sheet, and then click
Add New Item.
2. Under Visual Studio installed templates, click Style Sheet.
3. In the Name box, type a name for the external style sheet and then click Add.
To add style rules to an external style sheet
1. On the Styles menu, click Add Style Rule.
The Add Style Rule dialog box appears.
2. In the Add Style Rule dialog box, select one of the following CSS selectors and then click OK:
a. Element Defines a rule for an element by tag name. For example, you might select the h2 element to define the
background color, font family, and link colors for all of the h2 elements on your Web page.
b. Class name Defines a rule for a CSS class. For example, you might define a .txtIndent style to indent the text
enclosed within all <p class="txtIndent"> tags).
c. Element ID Defines a rule for an element with a specific ID. For example, you might define a #txtPop style to
reveal and position just one of the div elements on your page.
3. Find the new style selector and then place the cursor between the braces ( { } ).
4. On the Styles menu, click Build Style.
5. In the Style Builder dialog box, define the style attributes that you want the element to have, and then click OK.
The Style Builder dialog box inserts CSS style attributes within the braces ( { } ) of the style selector.
Selecting a CSS Schema for Validation
The style editor can validate that the style attributes you are creating are valid, and it provides IntelliSense to help you create
style attributes as you type. Validation and IntelliSense are controlled by a CSS schema; you can select from several CSS
schemas.
To set a CSS schema
1. On the View menu, click Toolbars, and then click Style Sheet.
2. On the Style Sheet toolbar, in the Cascading Style Sheet Version for Validation list, click the CSS schema that you
want to use for validation and IntelliSense.
After creating the style sheet, you might want to apply it to Web pages. For more information, see
How to: Link Cascading Style Sheets to ASP.NET Web Pages (Visual Studio).
See Also
Tasks
Walkthrough: Working with Cascading Style Sheet Styles in Visual Web Developer
Concepts
Cascading Style Sheets Overview
Visual Web Developer

How to: Link Cascading Style Sheets to ASP.NET Web Pages


(Visual Studio)
After you have defined an external cascading style sheet (CSS), perhaps using the procedure in
How to: Create External Cascading Style Sheets (Visual Studio), you can link the style sheet to individual ASP.NET Web pages to
apply the styles to the elements on the page. Style sheets allow you to specify formatting styles for HTML elements.
To link a cascading style sheet to an ASP.NET Web page
In Design view, from Solution Explorer, drag the style sheet file (.css file) and drop it anywhere on the Web page.
—or—
In Source view, from Solution Explorer, drag the style sheet file (.css file) and drop it within the <head></head> tags on
the Web page.
A new link element is inserted inside the <head> tags, which might look like the following code example.

<link href="MyStyles.css" rel="stylesheet" type="text/css" />

See Also
Tasks
Walkthrough: Working with Cascading Style Sheet Styles in Visual Web Developer
How to: Create External Cascading Style Sheets (Visual Studio)
Concepts
Cascading Style Sheets Overview
Visual Web Developer

How to: Add Cascading Style Sheet Attributes in Design View


As you edit a Web page in Design view of the HTML Designer in Visual Web Developer, you can add cascading style sheets
(CSS) style attributes to controls or to HTML elements.
To add CSS style attributes to an HTML element
1. In Design view, right-click the control or HTML element to which you want to add a style attribute, and then click Style.
Note
The Style command is available only if the currently selected browser schema is set to a browser that supports styles.

2. In the Style Builder dialog box, add values for the CSS style attributes that you want.
CSS attribute:value pairs are added to a style="" declaration, which is inserted into the opening tag of the selected
HTML element. The following code example shows inline style attributes that are applied to an <h3> heading:

<h3 style="text-decoration:underline; color:red;">Important</h3>

Note
When you apply an inline CSS style to one HTML element, you have not changed the style for all such elements. In the
preceding example, the added CSS style attributes apply to just one h3 element. Other h3 headings will continue to dis
play the default style.

To apply an existing CSS style class to an HTML element


1. In Design view, select the control or HTML element to which you want to apply an existing style class.
2. In the Properties window for the selected element, type the class name in the CssClass box.
A class attribute is added to the opening tag of the selected element.
See Also
Tasks
Walkthrough: Working with Cascading Style Sheet Styles in Visual Web Developer
Concepts
Cascading Style Sheets Overview
Visual Web Developer

HTML Table Editing in Visual Web Developer


The topics in this section provide information on creating and editing HTML tables in Design view of Visual Web Developer.
In This Section
Introduction to Editing HTML Tables in Visual Web Developer
Walkthrough: Editing HTML Tables in Visual Web Developer
How to: Create and Edit HTML Tables in Design View
How to: Add and Remove HTML Table Elements in Visual Web Developer
How to: Select HTML Table Elements and Contents in Visual Web Developer
How to: Resize HTML Table Elements in Visual Web Developer
HTML Table Editing Tips in Visual Web Developer
See Also
Other Resources
Design View, Web Page Designer
Web Page Designer
ASP.NET Web Pages (Visual Studio)
Visual Web Developer

Introduction to Editing HTML Tables in Visual Web Developer


You can use HTML tables in your Web pages to define page layout and to display content in column format. Visual Studio
allows you to edit HTML tables visually in Design view, or as markup in Source view.
Table Editing in Design View
In Design view, the Web page designer provides a table editor that allows you to edit HTML tables visually. You can add a table
to a page either from the Toolbox or using a dialog box that offers options for setting table and cell properties. The table is
displayed in the designer as it will appear in the browser. (By default, the designer adds visible borders around the table to
make it easier to edit, even if your table is not set to display borders.)
Note
As with all elements in the Web page designer, the table editor creates XHTML-compatible markup. For more information, se
e XHTML in Visual Web Developer.

The table editor allows you to select rows, columns, or individual cells and set their properties. You can also use the editor to
resize columns, rows, or cells.
Note
The table editor allows you to edit HTML tables (table elements and their child elements), but not the ASP.NET Table control
(asp:table elements). ASP.NET Table controls are most often used programmatically to create tabular display and are theref
ore not typically used for layout in the page.

Table Layout Templates


Because HTML tables are often used to define the layout of elements in the page, the table editor provides a set of predefined
layout templates. When you create a table, you have the option of selecting common layouts, including tables that define the
following:
A cell for a header and another cell for the main content.
A cell for the main content and another cell for side content.
A cell for the header, a cell for side content, a cell for the footer, and one cell for the main content.
Note
When you first create a table that is based on a predefined template, the table does not contain content, so it might render dif
ferently than you expect. Test your table layout by adding content.

After creating a table using a layout template, you can customize the template to suit your particular layout needs.
Table Editing in Source View
You can edit HTML tables in Source view as you would edit any HTML elements. For example, the editor provides IntelliSense
and validation for table elements just as it does for other elements. The following editor features are particularly useful when
working with tables in Source view:
The HTML editor tag navigator, which displays the currently selected element and its location within the tag hierarchy of
the page. For details, see HTML Editor Tag Navigation in Visual Web Developer.
Tag outlining, which allows you to collapse blocks of markup, such as an entire table. For details, see
How to: Collapse and Expand HTML Elements in Visual Web Developer.
See Also
Tasks
How to: Add and Remove HTML Table Elements in Visual Web Developer
How to: Select HTML Table Elements and Contents in Visual Web Developer
How to: Resize HTML Table Elements in Visual Web Developer
Visual Web Developer

What's New in HTML Table Editing in Visual Studio


The HTML table editing tools have been improved over those available in Visual Studio .NET 2003. This topic summarizes the
improvements.
Editing in Design View
The HTML table editor in Design view has been substantially improved to provide an easier, more intuitive way to edit tables
visually. Specific improvements include the following:
A redesigned Insert Table dialog box enables you to select from predefined table layout templates.
Table, row, and cell dimensions are set using XHTML-compatible styles rather than HTML width and height attributes.
A more intuitive selection model makes it easier to select the table itself, as well as columns, rows, and individual cells.
Visual cues make it more obvious how to select elements, and they clearly mark the elements that are selected.
Resizing table elements is easier, and the editor displays the actual dimensions of the elements as you resize them. The
editor also provides you with an easy way to remove size values (rather than forcing you to edit the table markup in
Source view).
The TAB key now enables you to navigate between table cells, which is a common feature in other table editing tools.
You can easily add rows by simply pressing the TAB key at the end of the last cell in a table.
The current selected element in the table is indicated in the tag navigator. For more information, see
HTML Editor Tag Navigation in Visual Web Developer.
Editing in Source View
The overall improvements in HTML editing in Source view have also made it easier to work with table markup. Specific
features that improve table editing include the following:
Source view does not reformat markup when switching to Design view and back.
Validation checks that the markup is compatible with the browser schema that you have selected.
IntelliSense provides complete, context-sensitive assistance for building tags, and it provides the attributes that are
appropriate for the currently selected browser schema.
Tag outlining enables you to collapse sections of a file to reduce clutter. By default, elements such as table, tr, p, and
others display with a button next to the line number that, when clicked, will expand or collapse the contents of the tag.
Note
The Insert Table command no longer works in Source view.

See Also
Concepts
Introduction to Editing HTML Tables in Visual Web Developer
HTML Editor Tag Navigation in Visual Web Developer
Markup Validation in Visual Web Developer
Visual Web Developer

Walkthrough: Editing HTML Tables in Visual Web Developer


Table editing is an important part of many Web pages because tables are used to create the page layout. This walkthrough
illustrates the table-editing features of the HTML editor in Microsoft Visual Studio. You will use tables to create the layout for a
simple entry form on the page.
Note
The table-editing features described in this walkthrough pertain to HTML tables, not to the Table Web server control (the <as
p:Table> control and its child controls).

Tasks illustrated in this walkthrough include:


Adding a table.
Selecting the table, rows, and columns.
Resizing elements.
Adding and removing table elements.
Setting cell characteristics such as background color and alignment.
Prerequisites
In order to complete this walkthrough, you will need:
Visual Web Developer and the .NET Framework.
Creating the Web Site
If you have already created a Web site in Visual Studio (for example, by following the steps in
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and skip to the next section,
"Creating the Page Layout with a Table." Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, enter the name of the folder where you want to keep the pages of your Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click the programming language you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Creating the Page Layout with a Table
You will begin by adding a table that defines the overall layout of the page.
To add a table for the page layout
1. If you do not already have a page open in the designer, add a page to the Web site.
2. Switch to Design view.
3. In the Layout menu, click Insert Table.
The Insert Table dialog box appears.
4. Select Template.
Table templates are predefined table layouts.
5. In the Template list, select Header and side.
6. Click OK.
A two-column table is added to the page that takes up the entire height and width of the page. A single cell on top spans
the columns, providing a place to put a header. The left-hand cell below the header is for navigation or side information.
The right-hand cell below the header is the main display area for the page.
Note
The borders around the cells in the table are displayed by default at design time to help you edit. Unless you explicitly s
et the table or cells to have a border, no border will appear when the table is rendered in the browser.

Creating a Form Layout with a Table


You can also use HTML tables to lay out the controls in a form. You will now create a second table inside the first one. You will
later use the second table to create the layout for some controls in a form.
To add a table for the form layout
1. From the HTML group of the Toolbox, drag a Table element into the right-hand (main) cell.
When you drag a table from the Toolbox, Visual Web Developer creates an empty table of three columns and three
rows. You need only two columns; in a moment, you will delete one of the columns.
Note
You can create tables either by using the Insert Table command, as you did earlier, or by dragging a Table element fr
om the Toolbox.

2. Move the mouse pointer over the table until the pointer changes to a move cursor (four-headed arrow), and then click to
select the table.
3. Drag the right-hand edge of the table to widen the table until it is most of the width of the page.
As you drag, the table displays its current dimensions.
4. Right-click in one of the cells in the left-most column. From the Delete sub-menu, click Columns to remove the column
of the selected cell.
The column is deleted from the table.
Note
If you see a Delete option that does not have a submenu, it indicates that the focus is not in a cell. Right-click inside a c
ell in the left-hand column.

5. Click in the bottom right-hand cell and then press the TAB key to add a fourth row to the table.
You now have a table of two columns and four rows, which can be the container for your form controls.
Setting Characteristics of the Page Layout Table
Now that you have a form layout table inside the page table, you can finish laying out the page by editing the page layout
table.
To set characteristics of the page layout table
1. In the page layout table, click in the top cell.
The thicker border around the cell indicates that it is selected and in content-edit mode.
2. In the Properties window, click the button in the Style box.
The Style Builder dialog box appears.
3. On the Text tab, in the Horizontal list, click Centered.
4. On the Background tab, in the Color list, select a color you like. You can also click the button next to the Color box to
display the Color Picker dialog box and select from additional colors.
The settings you have made set the style for the cell at the top of the layout table.
5. Type Contoso Web Site as a heading.
6. Select the text and, in the Block Format list in the Formatting toolbar, click Heading 1 <H1>.
7. Repeat steps 1 through 6 for the leftmost cell in the table, with these changes:
Change the text to This site is maintained by Contoso, Incorporated.
Do not format the text as a Heading 1.
In the Text tab of the Style Builder dialog box, in the Vertical list, click bottom.
In a production Web page, the side cell would probably be occupied by a menu of links or other content. However, for
this walkthrough it does not matter what content the cell contains.
Building the Form
You can now build the form.
To add text and controls to the form layout table
1. In the form layout table (the table inside the page layout table), click in the top left cell and type Name:.
2. Click in the left cell of the second row and type Birth year:.
3. From the Standard group of the Toolbox, drag a TextBox control into the top right cell.
4. Set the TextBox control's ID property to textName.
5. Drag another TextBox into the second row's right cell and set its ID property to textBirthYear.
6. Drag a Button control into the third cell on the right and set its Text property to Submit.
7. Drag a Label control into the bottom right cell, set its ID property to labelDisplay, and clear its Text property.
8. Place the mouse cursor over the left-hand column until you see a selection symbol (a small square) at the top of the
column, and then click the symbol.
The left column is selected.
9. In the Properties window, click the button in the Style box to display the Style Builder dialog box.
10. In the Text tab, in the Horizontal list, click Right.
The text captions in the form are right-aligned.
11. Click OK to close the style builder.
12. Select the left column again, and then drag its right edge to shrink the column until it is just wide enough to fit the
caption text.
13. Right-click in the layout table cell outside the form layout table, and then click Style.
The shortcut menu provides an alternate way to display the Style Builder dialog box.
14. In the Text tab, in the Vertical list, click top.
The form layout table is aligned at the top of the cell.
Programming the Form Controls
You can now program the form controls. The form displays the age that the user will be this year.
To program the form controls
1. Double-click the Button control in the form.
The editor creates a Click event handler.
2. Add the following highlighted code.
VB
Protected Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
Dim age As Integer
age = DateTime.Now.Year - CInt(textBirthYear.Text)
labelDisplay.Text = Server.HtmlEncode(textName.Text) & _
", this year you are " & Server.HtmlEncode(age.ToString())
End Sub

C#
protected void Button1_Click(Object sender, EventArgs e)
{
int age = DateTime.Now.Year - Int32.Parse(textBirthYear.Text);
labelDisplay.Text = Server.HtmlEncode(textName.Text) +
", this year you are " + Server.HtmlEncode(age.ToString());
}

Testing the Page


You can now test the page.
To test the page
1. Press CTRL+F5 to run the page.
When the page is displayed in the browser, note the layout that you have created. Because you did not explicitly specify
table borders, there are no lines on the form.
2. In the Name box, type your name.
3. In the Birth year box, type the year you were born, and then click the Submit button.
The age calculation is displayed in the form in the location you created with the form table.
Next Steps
In this walkthrough, you have exercised some of the capabilities of the visual table editor in Design view. You added tables in
two ways, resized a table, added a row, deleted a column, set cell styles, and added text and controls as cell contents.
Suggestions for more exploration include:
Learn more ways to work with tables. For details, see:
How to: Add and Remove HTML Table Elements in Visual Web Developer
How to: Select HTML Table Elements and Contents in Visual Web Developer
How to: Resize HTML Table Elements in Visual Web Developer
Learn some tips for editing tables in both Design view and Source view. For details, see
HTML Table Editing Tips in Visual Web Developer.
Add validation to the Birth year text box so that users can enter only valid years. For more information, see
Validating User Input in ASP.NET Web Pages.
See Also
Tasks
Walkthrough: Creating and Using ASP.NET Master Pages in Visual Web Developer
Concepts
HTML Editor Tag Navigation in Visual Web Developer
Formatting Elements in the HTML Editor in Visual Web Developer
Visual Web Developer

How to: Create and Edit HTML Tables in Design View


The HTML Designer provides tools that make it easy to create and edit tables in your Web pages.
Note
This topic discusses the HTML table element, which is frequently used to create page layouts and to display data in columns.
To create tables dynamically, use the Table ASP.NET Web server control. For details, see
Table, TableRow, and TableCell Web Server Controls (Visual Studio).

Procedures
To create a table from the Toolbox window
In the Toolbox, from the HTML group, drag a Table element onto the page.
To create a table from the Layout menu
1. On the Layout menu, click Insert Table.
2. In the Insert Table dialog box, specify the table properties, and then click OK.
Note
If the table does not have a border, you can choose Visible Borders on the View menu to display border outlines.

To add content to a table cell


In Design view, place the insertion point in the cell in which you want to add content, and then type the text.
To add columns, rows, and cells to a table
1. Place the insertion point in a cell in the column or row next to where you want to insert the new column, row, or cell.
Note
Placing the cursor inside a cell is sufficient. You do not have to select the entire column, row, or cell.

2. On the Layout menu, click Insert, and then click the appropriate command to insert a column, row, or cell.
Note
You can also right-click the column or row, click Insert, and then click the appropriate command.

To select tables, columns, rows, or cells


1. Place the insertion point in a cell in the table, column, or row that you want to select.
2. On the Layout menu, click Select, and then click Table, Column, Rows, or Cell.
To merge cells
1. Select the cells that you want to merge.
Note
Press the CTRL key while clicking adjoining cells to select them.

2. Right-click the selected cells, and then on the shortcut menu, click Merge Cells.
The cells are merged into a single cell that spans the width of the original cells.
To resize table elements
1. Right-click the row or column, click Select, and then click the element that you want to resize.
2. Drag the element's borders it is the desired size.
The table displays the size of the element that you are resizing.
Note
If the selection includes elements that use different size units (for example, percentage and pixels), resizing the element
changes the size units of all elements to pixels.

See Also
Reference
Insert Table Dialog Box
Visual Web Developer

How to: Add and Remove HTML Table Elements in Visual Web
Developer
After creating a table, you can add new elements, such as rows, columns, and cells. You can also remove existing elements.
To add a table
Perform one of the steps listed in the following table.
Table type Steps
A table with no content and no attrib From the HTML group of the Toolbox, drag a Table element onto the page.
utes set
Visual Studio creates a table with three rows and three columns.

A table with attributes that you speci In the Layout menu, click Insert Table, and then specify the table and cell
fy as you create it options in the Insert Table dialog box.

To add rows, columns, or cells to a table


Perform one of the steps listed in the following table.
Table element Steps
A row inside the table Place the insertion point in the row next to where you
want to insert the new row; in the Layout menu, click
Insert, and then click Row Above or Row Below.
-or-
Right-click anywhere in the row where you want to in
sert the new row, click Insert, and then click Row Ab
ove or Row Below.

A row at the end of the table Press the TAB key in the last cell of the table.

A column Place the insertion point in a cell in the column next t


o where you want to insert the new column; in the La
yout menu, click Insert, and then click Column to th
e Right or Column to the Left.
-or-
Right-click anywhere in the column where you want t
o add the new column, click Insert, and then click Col
umn to the Left or Column to the Right.

A cell Place the insertion point in the cell next to where you
want to insert the new cell; in the Layout menu, click
Note Insert, and then click Cell to the Left or Cell to the
The editor does not prevent you from creating a table wit Right.
h uneven numbers of cells in rows. The editor will not aut -or-
omatically span a cell to accommodate uneven numbers
of cells in other rows Right-click anywhere in the column where you want t
o insert the new cell, click Insert, and then click Cell t
o the Left or Cell to the Right.

To add a table caption


1. Select the table to which you want to add a caption.
2. In the Layout menu, click Insert, and then click Caption.
Merging Table Cells
You can combine, or merge, cells to form columns or rows that span other columns. For example, in a three-column table, you
can combine the cells in the top row to form a single row that spans all three columns.
To merge table cells
1. Select the table cells that you want to merge. For details, see
How to: Select HTML Table Elements and Contents in Visual Web Developer.
Note
You can merge table cells only if the selected cells form a rectangle.

2. In the Layout menu, click Merge Cells.


-or-
Right-click the selected table cells and then click Merge Cells.
The cells are merged into a single cell with a colspan or rowspan attribute added to the markup, as appropriate.

Removing Table Elements


Removing any table element permanently deletes it from the page.
To remove a table
In the Layout menu, click Delete, and then click Table.
-or-
Select the table and then press the DELETE key.

To remove a row or column from a table


1. Place the insertion point in the row or column that you want to remove. If you are deleting cells, select the cell or cells
that you want to delete. For details, see How to: Select HTML Table Elements and Contents in Visual Web Developer.
2. In the Layout menu, click Delete, and then click Row or Column.
-or-
Alternatively, select the table row or column that you want to delete and press BACKSPACE.

To remove table cells


1. Click the table cell or cells that you want to delete. For details, see
How to: Select HTML Table Elements and Contents in Visual Web Developer.
2. In the Layout menu, click Delete, and then click Cells.
-or-
Alternatively, select the table cell or cells that you want to delete and press BACKSPACE.
See Also
Tasks
How to: Select HTML Table Elements and Contents in Visual Web Developer
How to: Resize HTML Table Elements in Visual Web Developer
Visual Web Developer

How to: Select HTML Table Elements and Contents in Visual


Web Developer
Before editing or removing a table element, you must select it. The Web page HTML table editor provides multiple ways to
select both table elements and the contents of table cells.
To select an HTML table element
Perform the steps listed in the following table:
Table element Steps
Table Click anywhere in the table that you want to select, and the
n click the four-sided arrow that appears on the top-left co
rner of the table.
Note
If the page or table dir property is set to rtl, the four-side
d arrow appears over the top-right corner of the table.

-or-
In the Layout menu, click Select, and then click Table.
-or-
Right-click the table that you want to select, click Select, a
nd then click Table.

Column Click the selection symbol at the top of the column that yo
u want to select.
Note
-or-
If the column includes a cell that spans multiple colu
mns, the entire cell is selected when you select any c Click anywhere in the column that you want to select, and
olumn that the cell spans. then in the Layout menu, click Select and then click Colu
mn.
-or-
Right-click anywhere in the column that you want to select
, click Select, and then click Column.

Row Click the selection symbol to the left of the row that you w
ant to select.
Note
Note
If the row includes a cell that spans multiple rows, th
e entire cell is selected when you select any row that If the document's dir property is set to rtl, the selection g
the cell spans. lyph is on the right.

-or-
Click anywhere in the row that you want to select, and the
n in the Layout menu, click Select and then click Row.
-or-
Right-click anywhere in the row that you wan to select, clic
k Select, and then click Row.
Cell Click anywhere in the cell that you want to select, which se
lects the cell contents, and then press the ESC key , which
moves the selection to the container.

Cell contents Click anywhere in the cell that you want to select. The cell i
s displayed with a border to indicate that it is in content-ed
iting mode.

Extending the Selection to Additional Table Elements


You can also extend the current selection to include additional table elements.
To extend the selection to additional table elements
Select an element and then perform one of the steps listed in the following table.
Table element Steps
Adjacent eleme Press the SHIFT key and hold it while you click the additional cell or cells that you want to select.
nts
-or-
Press the SHIFT key and hold it while you drag the mouse pointer over the additional elements t
hat you want to select.
-or-
Press the SHIFT key and hold it while you press the UP ARROW key or the DOWN ARROW key t
o select the additional elements that you want.
Note
If a cell is in content-editing mode, using SHIFT+ARROW first selects the cell; using SHIFT+ARROW th
ereafter selects adjacent cells.

Non-adjacent el Press the CTRL key and hold it while clicking the additional element or elements that you want t
ements o select.

See Also
Tasks
How to: Add and Remove HTML Table Elements in Visual Web Developer
How to: Resize HTML Table Elements in Visual Web Developer
Visual Web Developer

How to: Resize HTML Table Elements in Visual Web Developer


After creating a table or adding elements to it, you can resize the elements or the table itself.
Note
If you are resizing a row or column and the td elements use different units for height or width, the table editor normalizes th
e units into pixels.

To resize table elements


Perform the steps listed in the following table.
As you drag the border for the table, row, column, or cell, the watermark displays the size of the element that you are
resizing.
Table Size adjustment Steps
eleme
nt
Table Adjust overall table size Select the table that you want to resize and then dra
g its resize handles.

Row Adjust row height In the Layout menu, click Resize, and then click Res
ize Row to open the Resize HTML Table Row dial
Resizing the row changes the height style of the affe
cted td element. og box.
The dialog box provides an option to apply the heig
ht only to the first cell in the row.

Row Clear row's height setting 1. In the Layout menu, click Resize, and then click Resiz
After you clear the height setting of a row, the row's e Row to open the Resize HTML Table Row dialog b
height is determined by the overall table dimensions ox.
. 2. Select the Clear All Heights check box.

Colum Adjust column width In the Layout menu, click Resize, and then click Res
n ize Column to open the Resize HTML Table Colu
By default, resizing the column changes the width st
yle of all affected td elements. mn dialog box.
The dialog box provides an option to apply the widt
h only to the first cell in the column.

Colum Clear column's width setting 1. In the Layout menu, click Resize, and then click Resiz
n e Column to open the Resize HTML Table Column
After you clear the width setting of a column, the col
umn's width is determined by the overall table dime dialog box.
nsions. 2. Select the Clear All Widths check box.

Cell Adjust size of an individual cell Select the cell that you want to resize, and then pres
s the SHIFT key and hold it while dragging the cell's
border.
Note
If you do not hold down the SHIFT key, you will res
ize the entire row, not the cell.
See Also
Tasks
How to: Add and Remove HTML Table Elements in Visual Web Developer
How to: Select HTML Table Elements and Contents in Visual Web Developer
Visual Web Developer

HTML Table Editing Tips in Visual Web Developer


The Visual Studio HTML table editor is a powerful tool for manipulating HTML tables to define the layout of your Web pages
and to display content in column format. The following tips will help you make the best use of the HTML table editor.
Editing HTML Tables
The following points describe general table-editing behavior:
The HTML table editor is a visual way to edit HTML table elements, such as the table, tr, and td elements. While the
HTML table editor provides a convenient way to edit those elements, it cannot provide editing facilities for any
capabilities that are not supported by HTML tables.
The table editor works with HTML tables (table elements and their child elements), but it does not with the ASP.NET
Table control (asp:table element). The ASP.NET Table control is designed primarily to be used programmatically rather
than for static layout, the way HTML tables are often used.
Design view renders the table in a manner similar to how it will appear in a browser. It does this by interpreting the
table's HTML elements in much the same way a browser will. For more information, see the "Sizing and Resizing
Behavior" section later in this topic.

Scope of Edits
It is helpful to understand how edits you make in Design view are applied to table elements. Note the following:
Each cell in the table is considered a member of the row or column that it starts in, as displayed in Design view. An
operation on a row or column affects all of the members of that row or column. Mapping a cell in Design view to a
corresponding td element in Source view might not always work as expected if cells contain colspan or rowspan
attributes.
Row operations affect each of the td elements in that row. They do not affect the tr element.
Selecting and modifying a column affects any th elements that are in the column.
Sizing and Resizing Behavior
The table editor can sometimes work in unexpected ways when you initially specify table, row, or column dimensions, or when
you are resizing these elements. The behavior of table element dimensions reflects the behavior that the table will have in the
browser. For example, columns that do not have a specific width setting will grow or shrink according to the overall width of
the table, the width of the other columns in the table, and the content that all of the columns contain.
Content Takes Precedence
In general, the size of content in a cell takes precedence over width or height settings on cells or rows. For example, if a table
cell contains a graphic, or img element, the size of the graphic takes precedence over the width of the cell or even of the table.
This is true also for controls in table cells.
If cells contain text, and if the cell's nowrap attribute is not set, the text will wrap within the cell's width. However, if the text
does not contain white space, such as spaces or punctuation, there is no place for the text to wrap and the cell width will be
readjusted to accommodate the text.
Content also takes precedence for row height. If text wraps within a cell, it can cause a row to be higher than the height setting
specified for the tr element that represents the row.
Guidelines for Table Sizing and Resizing
Because of the way HTML is designed, it is possible to assign conflicting dimension settings to a table and the elements it
contains. For example, a two-column table might be assigned a width of 100%, but the two columns might each be assigned a
width of 100 pixels.
The following table summarizes how sizing is handled in the table editor. In all cases, the width of content takes precedence.
Dimensions specified Behavior
Width is specified for the table and for all of the table's columns, Table dimensions take precedence; the table calculates colu
or height is specified for the table and for all of the table's rows. mn or row sizes proportionally.
Width is specified for the table and for some of the table's colum The sized elements are rendered using exact dimensions, an
ns, or height is specified for the table and for some of the table's d the remaining elements are resized to fill out the full dime
rows. nsions of the table.
Note
The table editor displays the width of unsized table elemen
ts as "auto."

Width is specified for each of the table's columns but not for the t The table width or height is calculated by adding the width o
able itself, or height is specified for each of the table's rows but n f all of the table's columns or the height of all of the table's r
ot for the table itself. ows.

No width or height is specified for the table or any of the table's e The width or height is calculated solely on cell content and t
lements. he space required for borders.
Note
If you are resizing a row or column and the td elements use different units for height or width, the table editor normalizes th
e units into pixels.

See Also
Concepts
Introduction to Editing HTML Tables in Visual Web Developer
How to: Create and Edit HTML Tables in Design View
Visual Web Developer

Learning More — HTML Editing in Visual Web Developer


The topics in this section provide in-depth information on working with HTML and XHTML in the Visual Web Developer Web
page designer.
In This Section
ASP.NET and XHTML
Markup Validation in Visual Web Developer
HTML Editor Tag Navigation in Visual Web Developer
How to: Add Web Browsers to Visual Web Developer
See Also
Other Resources
Source View, Web Page Designer
Design View, Web Page Designer
Web Page Designer
ASP.NET Web Pages (Visual Studio)
ASP.NET

ASP.NET and XHTML


ASP.NET allows you to create Web pages that are conformant with XHTML standards. XHTML is a World Wide Web
Consortium (W3C) standard that defines HTML as an XML document. Creating Web pages that are conformant with XHTML
standards has several advantages:
It guarantees that the elements in the pages are well formed.
Because many browsers are increasingly moving toward supporting XHTML, creating pages that conform to XHTML
standards helps ensure that your pages render consistently in all browsers.
Using XHTML helps to make pages conform more readily to accessibility standards.
XHTML is extensible, allowing the definition of new elements.
An XHTML page is much easier to read programmatically for situations in which the Web page is processed by a
computer instead of being read by users, and the document can be manipulated using transformations.
The W3C has identified several levels of XHTML conformance: XHTML 1.0 Transitional, XHTML 1.0 Frameset, XHTML 1.0 Strict,
and XHTML 1.1. The XHTML 1.1 specification is the strictest of these levels. The XHTML 1.0 Frameset and Transitional
specifications define XML-based HTML markup, but allow certain widely used constructs. Many existing Web pages can be
made conformant with XHTML 1.0 Frameset or Transitional specifications, but cannot meet XHTML 1.0 Strict or XHTML 1.1
specifications without requiring substantial revision to replace functionality implemented using constructs that are not allowed
in the specifications.
For more information about the XHTML standard, see the specification for the Second Edition of XHTML 1.0 on the
W3C Web site.
ASP.NET Features for XHTML Conformance
XHTML defines elements and attributes more strictly than HTML. By default, all markup that is produced by ASP.NET and Web
server controls included with ASP.NET now conforms to the XHTML 1.0 Transitional standard. In many cases, the markup
produced by ASP.NET conforms to XHTML 1.1 standards as well. Unless noted otherwise, references to the XHTML standard in
this topic mean both XHTML 1.0 and XHTML 1.1.
Some of the XHTML rules that differ from HTML include the following:
All elements either include an explicit closing tag or are self-closing (with />).
Tag and attribute names are rendered in lowercase, and attribute values are included in double quotation marks. For
example, if you use a GridView control on your page, when the page is rendered, the GridView control emits HTML that
is conformant with XHTML standards. All generated elements use explicit opening and closing tags (or self-closing tags),
and attribute values are included in double quotation marks.
Formatting information is rendered using only cascading style sheet styles. To support this standard, if the page includes
an XHTML DOCTYPE element, ASP.NET controls do not render font elements or attributes, such as bgcolor, that would
not conform to XHTML standards.
In ASP.NET, if controls generate IDs, as occurs in the Repeater, GridView, and other controls, the format of the IDs match
XHTML 1.0 Transitional guidelines.
ASP.NET dynamically adds an action attribute to the form element. By default, form elements include a name attribute,
which is allowed in the XHTML 1.0 Transitional specification. This helps maintain backward compatibility with existing
applications which rely on client script that addresses form elements using the form name.
Note
The name attribute on the form element is not allowed in XHTML 1.1 guidelines. You can configure your application n
ot to render a name attribute. For details, see "Controlling XHTML Rendering of ASP.NET Pages and Controls" later in t
his topic.

Because XHTML requires all elements to be enclosed in a container element, ASP.NET controls, such as input elements,
are rendered in div elements. This includes the HTML markup rendered for controls, such as the TextBox, CheckBox, and
RadioButton controls. It also includes hidden fields, such as the element that is used to store view-state data.
ASP.NET encodes characters, such as & (for example, as &amp;). This includes URLs that are generated to reference
ECMAScript and the contents of encoded values, such as view state.
Any script elements that are rendered into the page use the appropriate type attribute (for example,
type="type/javascript") and do not include a language attribute. This pertains to scripts that are created by the page
or controls that require client script to perform a postback — such as the HyperLink, LinkButton, Calendar, and TreeView
controls, as well as validator controls — and by the RegisterHiddenField, RegisterStartupScript, and
RegisterClientScriptBlock methods. Script blocks that you create are not automatically amended with a type attribute.
If ASP.NET renders script blocks, the content of the script blocks is rendered inside an XML (HTML) comment.
Controlling XHTML Rendering of ASP.NET Pages and Controls
Under some circumstances, you might want ASP.NET controls to render markup in the stricter format specified by the
XHTML 1.1 specification. The default rendering includes some markup that does not conform to the XHTML 1.1 specification.
For example, XHTML 1.1 standards prohibit the use of a name attribute in an HTML form element.
Conversely, you might want ASP.NET to render markup that does not conform to XHTML 1.0 Transitional specifications. This is
typically true when you have existing pages that rely on tags or attributes that were supported in earlier versions of ASP.NET
but do not conform to XHTML standards.
You can configure your Web site to render markup in three ways:
Legacy (which is similar to how markup was rendered in previous versions of ASP.NET)
Transitional (XHTML 1.0 Transitional)
Strict (XHTML 1.0 Strict)
For more information, see How to: Configure XHTML Rendering in ASP.NET Web Sites.
Note
The option to render legacy markup is provided primarily to assist you in migrating existing pages to the current version of A
SP.NET, and might not be supported in future versions of ASP.NET.

Legacy Rendering
When rendering is set to legacy, ASP.NET pages and controls change their rendering to the behavior of earlier versions of
ASP.NET. Changes include the following:
The form element is rendered with a name attribute.
ASP.NET does not automatically render a div element inside the form element as a container for controls.
Validator controls are rendered as span elements with custom attributes, such as controltovalidate.
The img element does not render alt and src attributes unless you explicitly include them.
If required to support auto-postback behavior, controls will render a language attribute (for example,
language="javascript").
The nowrap attribute is included for controls that render a div element (such as the Panel control) if the control's Wrap
property is set to false.
ImageButton controls render a border attribute.
Any br elements rendered into the page are rendered as <br>. However, if you explicitly include a <br /> tag, the page
renders it as-is.
The DataGrid and Calendar controls include a bordercolor attribute in the rendered table elements if its BackColor
property is set.
Specifying the DOCTYPE Element and XHTML Namespace
Valid XHTML Web pages must contain a DOCTYPE declaration that identifies the page as an XHTML page and references the
XHTML schema to which it conforms. The page must also include attributes on the HTML tag that reference the XHTML
namespace. ASP.NET does not automatically create a DOCTYPE declaration when the page is rendered. Instead, you should
create the DOCTYPE declaration with the appropriate XML namespace references.
Note
Visual designers, such as Visual Studio, generally include default page templates that include a DOCTYPE declaration. If you
are using a visual designer, check that it creates new pages with the DOCTYPE declaration you require. For more informatio
n, see XHTML in Visual Web Developer and XHTML in Visual Web Developer and XHTML in Visual Web Developer.

The following code example shows a DOCTYPE declaration that you might add to your page.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1


/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >

By not automatically generating the DOCTYPE declaration, ASP.NET retains greater rendering flexibility for browsers that have
differing levels of compliance with the differing HTML standards that can be specified in a DOCTYPE declaration.
Note
If the DOCTYPE declaration is removed, XHTML compliance will not be met. The page will not be considered an XHTML page
and will not reference the XHTML schema.

Many browsers will also change their rendering based on the presence or absence of the DOCTYPE declaration and an XML
namespace declaration. If those elements are present, browsers typically use a standards-based rendering. When the elements
are not present, many browsers render using browser-specific rules that vary among browser types (which is sometimes
referred to as rendering in "quirks mode"), and can therefore result in unpredictable rendering.
Similarly, you can control the MIME type of the page. By default, a page sets the MIME type to text/html. However, you can
override the page's MIME type by setting the ContentType attribute in the @ Page directive, as shown in the following code
example.
VB
<%@ Page Language="VB" ContentType="application/xhtml+xml" %>

C#
<%@ Page Language="C#" ContentType="application/xhtml+xml" %>

Example ASP.NET Page with Required XHTML Elements


The following code example shows a simple ASP.NET page that is XHTML conformant.
VB
<%@ Page Language="VB" AutoEventWireup="false" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<script runat="server">
Sub Button1_Click(sender As Object, e As EventArgs)
Label1.Text = "Built at " & DateTime.Now.ToString()
End Sub

Sub listFruit_SelectedIndexChanged(sender As Object, e As EventArgs)


Label1.Text = "You selected " & listFruit.SelectedItem.Text
End Sub
</script>

<head runat="server">
<title>ASP.NET XHTML Page</title>
</head>

<body>
<form id="Form1" runat="server">
<div>
<h1>ASP.NET Sample Page for XHTML</h1>
<p>
<asp:listbox runat="server" id="listFruit" AutoPostBack="true"
onselectedindexchanged="listFruit_SelectedIndexChanged">
<asp:listitem>Apple</asp:listitem>
<asp:listitem>Banana</asp:listitem>
<asp:listitem>Orange</asp:listitem>
</asp:listbox>
</p>
<asp:label runat="server" id="Label1" ForeColor="white"
BackColor="black" />
<br />
<asp:button runat="server" id="Button1" onclick="Button1_Click"
Text="Click me"/>
</div>
</form>
</body>
</html>

C#
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">

<script runat="server">
void Button1_Click(Object sender, EventArgs e)
{
Label1.Text = "Built at " + DateTime.Now.ToString();
}
void listFruit_SelectedIndexChanged(Object sender, EventArgs e)
{
Label1.Text = "You selected " + listFruit.SelectedItem.Text;
}
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>ASP.NET XHTML Page</title>
</head>
<body>
<form id="Form1" runat="server">
<div>
<h1>ASP.NET Sample Page for XHTML</h1>
<p>
<asp:listbox runat="server" id="listFruit" AutoPostBack="true"
onselectedindexchanged="listFruit_SelectedIndexChanged">
<asp:listitem>Apple</asp:listitem>
<asp:listitem>Banana</asp:listitem>
<asp:listitem>Orange</asp:listitem>
</asp:listbox>
</p>
<asp:label runat="server" id="Label1" ForeColor="white"
BackColor="black" />
<br />
<asp:button runat="server" id="Button1" onclick="Button1_Click"
Text="Click me"/>
</div>
</form>
</body>
</html>

Note the following:


The form element does not contain an action attribute because the action attribute is added when the page is rendered.
The formatting properties of the Label control will render as style attributes.
Because the script element containing server script is not rendered to the browser, it does not require a type attribute.
The page renders client script at runtime to enable the auto-postback behavior of the ListBox control, but the page
renders the script in an XHTML-compatible manner.

XHTML Conformance of Static Text and HTML Elements


ASP.NET does not alter static text or non-server HTML elements that you put into a page. For example, an ASP.NET Web page
might include the TextBox and Button controls as well as some static text that you add inside <p></p> tags. ASP.NET can
render XHTML for the TextBox and Button controls, but it cannot correct XHTML errors that occur between the <p></p> tags.
If you create static text or HTML elements, make sure that they are XHTML conformant. You can check your pages by validating
them, as explained in the next section.
Unknown attributes of HTML controls are passed through to the rendered control output and will not validate as valid XHTML
markup. For example, specifying the ID attribute for the HtmlHead control will result in markup that is not XHTML 1.0 Strict-
compliant. To validate your markup, use a markup validator such as the
World Wide Web Consortium (W3C) Validation Markup Service.
Checking XHTML Conformance of ASP.NET Web Pages
After creating your ASP.NET Web pages, you might want to check whether they will render correct XHTML. If the page contains
ASP.NET Web server controls, there is no way to check the page while writing it because the controls render XHTML only when
the page runs.
Note
Some visual designers, such as Visual Studio, can provide design-time XHTML validation of the page's markup.

To check the validity of the XHTML for your pages, you must use a service that runs the page and checks its output. A typical
strategy is to deploy your pages to a publicly available server. The server can be a test server; it does not have to be a
production server. However, it must be open to the Internet. You can then use a validation service that can read your pages
programmatically.
A popular service is the W3C Markup Validation Service, which is maintained by the World Wide Web Consortium. To use this
validator, enter the URL of the page that you want the service to check. The validation site requests the page and produces a
report of any errors that it finds. Alternatively, you can save the source for a Web page and submit it as a file to the validation
service. For more information about this validation service, see the W3C Web site.
If the page that you are checking contains dynamic content, or if users can personalize Web pages in your site, you must be
sure to test pages with different content to be sure all possible content in the page is valid. In some cases, this can be difficult
because the variation in possible page output is too great to be able to test effectively.
Configuring Browser Capabilities for Markup Validation
When a page is processed, ASP.NET examines information in the request about the current browser, and based on the browser
type (user agent string), renders markup that is appropriate for that browser. For more information, see
ASP.NET Web Server Controls and Browser Capabilities.
If you submit an ASP.NET Web page to a validation service such as the W3C Markup Validation Service, ASP.NET might render
a version of the page that does not conform to XHTML standards. This is because the validator service does not report itself as
a browser type that ASP.NET recognizes, such as Internet Explorer or Mozilla. When ASP.NET cannot recognize the browser
type, it defaults to rendering downlevel markup, which does not include XHTML-conformant elements and attributes, or
features such as cascading style sheet styles.
You can configure your application to send the correct XHTML-conformant markup to the validation service by creating a
browser definition for the validation service's user agent string. For example, the W3C Markup Validation Service reports a
user agent that begins with "W3C_Validator". To create a browser definition for the W3C validator, you can create a .browser
file in your application's App_Browsers folder (you can name the .browsers file anything you like) and then add the following
browsers element.

<browsers>
<browser id="W3C_Validator" parentID="default">
<identification>
<userAgent match="^W3C_Validator" />
</identification>
<capabilities>
<capability name="browser" value="W3C Validator" />
<capability name="ecmaScriptVersion" value="1.2" />
<capability name="javascript" value="true" />
<capability name="supportsCss" value="true" />
<capability name="tables" value="true" />
<capability name="tagWriter"
value="System.Web.UI.HtmlTextWriter" />
<capability name="w3cdomversion" value="1.0" />
</capabilities>
</browser>
</browsers>

For more information about creating browser definitions, see Browser Definition File Schema (browsers Element).
Exceptions to XHTML Conformance
Although ASP.NET generates XHTML–conformant markup, some controls support optional functionality that, if used, might
result in non-compliant markup.
Note
Each control renders its own markup. Custom controls created by other parties might not be written to produce XHTML-conf
ormant output. If you are using a custom control, check with the control vendor to determine which standards the control su
pports.

Target Attribute
Examples of controls that might result in non compliant markup are controls that allow you to include a target attribute to
specify their client-side behavior:
AdRotator
BulletedList
HyperLink
HyperLinkColumn
ImageMap
MenuItem
TreeNode
Pages that include the controls with their target attribute set will not validate against XHTML 1.1. If it is critical for you to create
pages that are 100% conformant with XHTML 1.1 standards, you should avoid using options, such as the target attribute, that
result in non-conformant markup.
Select Element
A DropDownList or ListBox control can be used to create a single-item or multiple-item selection. The DropDownList and the
ListBox control each render an HTML select element. If the DropDownList or the ListBox control does not contain at least
one ListItem control, then the rendered select element contains no child option elements and will not validate against XHTML
1.1.
See Also
Tasks
How to: Configure XHTML Rendering in ASP.NET Web Sites
Visual Web Developer

XHTML in Visual Web Developer


XHTML is a World Wide Web Consortium (W3C) standard that defines HTML as an XML document. If you want to produce
Web pages that render using XHTML-compatible markup, Visual Web Developer can help you create conformant pages in a
variety of ways.
For more information about XHTML and the XHTML standards, see the HTML/XHTML topic page on the W3C Web site.
Creating XHTML-Conformant Pages in Visual Web Developer
By default, the Web page designer in Visual Web Developer always generates markup that is compatible with the XHTML 1.0
Transitional specification. When you create a new ASP.NET Web page, the new page contains the basic elements that are
required for XHTML, including a DOCTYPE declaration, such as the one shown in the following example.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

The document will also contain an html element that includes a reference to the XHTML namespace, as shown in the following
example.

<html xmlns="http://www.w3.org/1999/xhtml" >

Generating Tags
When you use the Web page designer to create markup in the page, the HTML elements and attributes that are generated by
the Web page designer are XHTML compatible. For example, tag and attribute names are created using lowercase letters, and
all attribute values are enclosed in quotation marks. Elements are properly closed, and the Web page designer recognizes and
implements the rules for required attributes and those attributes disallowed in the XHTML standard.
The Web page designer generates markup when you do the following:
Drag a control onto the page from the Toolbox.
Set character or paragraph formatting options in Design view. Formatting options are set using styles. Formatting
options for ASP.NET server controls are set by using properties that render styles at run time.
Use the Properties windows to set a control or element property.
Set a property by using a dialog box, such as inserting a table in the Insert Table dialog box.
Validating XHTML Compliance
In Source view, the Web page designer validates that the markup in the page conforms to the schema for a specified browser
or standard. For XHTML compliance, you can use the XHTML 1.0 Transitional, XHTML 1.0 Frameset, or XHTML 1.1 schema. For
details, see Markup Validation in Visual Web Developer.
Note
Validation will mark a form element that contains the runat="server" attribute as missing a required action attribute. This i
s expected behavior. The action attribute is generated at run time automatically, populating the name of the current page as
the attribute's value.

XHTML Output at Run Time


When an ASP.NET page is requested in the browser, ASP.NET processes the page, which causes the page and its controls to
render markup, styles, and script. The page and its controls will render XHTML 1.0 Transitional markup unless the page is
requested by a browser that uses a non-XHTML protocol, or if you have configured your Web site to render XHTML 1.1 or
legacy markup.
During page processing, ASP.NET performs other processing tasks that are required to make the page conform to XHTML
standards, including these tasks:
Adding an action attribute to the form element.
Rendering an HTTP header that includes information about the current character set, encoding, and so on.
ASP.NET will not perform the following tasks during page processing:
It will not add a DOCTYPE declaration if one is missing, unless the page is being rendered for a browser that supports
the XHTML Mobile Profile (XHTML MP) protocol.
It does not make any changes to your markup. Any errors in static markup are passed as-is to the browser.
It will not add the namespace attribute to the html element unless the browser uses the XHTML MP protocol.
For more information, see ASP.NET and XHTML.
Working with Existing Pages
You can open and edit any Web page in Visual Web Developer. If the page does not already contain XHTML-compatible
markup, validation will flag all of the elements in the page that do not conform to XHTML standards. Visual Studio does not
add any missing elements, and it makes only minor corrections to elements, such as adding a closing slash (/) to elements that
should be self-closed. For example, the Format Selection and Format Document menu commands can fix casing and
quotation-mark problems, but they will not change the structure of the document.
If you want to make a page conformant to XHTML standards, you should do all of the following:
Set the browser schema to XHTML 1.0 Transitional, XHTML 1.0 Frameset, or XHTML 1.1. For details, see
How to: Select Validation Schemas for HTML Editing in Visual Web Developer.
Be sure that validation is enabled so that you can see errors in Source view. For details, see
How to: Set Validation Options for HTML Editing in Visual Web Developer.
Test your document by using an XHTML validator, such as the free W3C Markup Validation Service, which is maintained
by the World Wide Web Consortium and can be obtained on the W3C Web site.
See Also
Concepts
ASP.NET and XHTML
Markup Validation in Visual Web Developer
ASP.NET

How to: Configure XHTML Rendering in ASP.NET Web Sites


By default, when you are working with browsers that support at least HTML 4.0, ASP.NET pages and controls render markup
that conforms to the XHTML 1.0 Transitional standard. However, you might want ASP.NET to render markup that conforms to
the stricter XHTML 1.0 Strict specification. Conversely, you might want ASP.NET to render markup that does not conform to
XHTML 1.0 Transitional specifications. This is typically true when you have existing pages that rely on tags or attributes that
were supported in earlier versions of ASP.NET but do not conform to XHTML standards, such as rendering a name attribute in
the form tag.
You can configure your Web site to render markup in three ways:
Legacy (which is similar to how markup was rendered in previous versions of ASP.NET)
Transitional (XHTML 1.0 Transitional)
Strict (XHTML 1.0 Strict)
For details, see ASP.NET and XHTML.
To configure XHTML rendering in an ASP.NET Web site
Under the system.web element in your application's Web.config file, add an xhtmlConformance element, and then set
the mode attribute to Legacy, Transitional, or Strict. If no xhtmlConformance element is defined in the Web.config
file, the default setting mode is transitional.
The following code example shows part of a Web.config file in which XHTML rendering is disabled.

<system.web>
<!-- other elements here -->
<xhtmlConformance
mode="Legacy" />
</system.web>

The following code example shows part of a Web.config file in which XHTML 1.0 Strict rendering is specified.

<system.web>
<!-- other elements here -->
<xhtmlConformance
mode="Strict" />
</system.web>

See Also
Concepts
ASP.NET and XHTML
Visual Web Developer

Markup Validation in Visual Web Developer


When you edit markup in Source view of the Visual Studio Web designer, the editor continually checks that the markup you
are creating is valid. Markup validation works like the spelling checker in a word processing program. The editor examines the
markup and adds wavy red lines under the elements or attributes that are not valid.
The editor determines what is valid based on the currently selected validation schema. For example, if you have set the current
browser to Internet Explorer 6, the editor compares the markup in your page against a schema that defines what Internet
Explorer 6 considers valid HTML. Internet Explorer 6 does not require tag attributes to have quotation marks around them.
Therefore, the editor does not mark the text attribute in the following code example.

<asp:button runat="server" id="button1" text=Button1 />

In contrast, if you change the current browser schema to XHTML 1.0 Transitional, the editor marks the value of the text
attribute, because XHTML requires that all attributes be within quotation marks.
A validation error does not prevent the page from running. It simply provides you with feedback that the markup in the page
does not conform to the current browser schema.
Selecting a Browser Schema
Visual Studio includes schemas for commonly used browsers (such as Netscape Navigator and Internet Explorer) and for
common standards (such as XHTML Transitional 1.0). You can select a schema from the drop-down list in the HTML Source
Editing toolbar. Alternatively, you can select a validation schema in the Options dialog box. For details, see
How to: Select Validation Schemas for HTML Editing in Visual Web Developer.
Viewing Validation Errors
The editor shows you validation errors in the following ways:
Underlined elements Elements or attributes that are invalid are underlined with wavy red lines.
ToolTips If you hold the mouse pointer over an underlined element, a ToolTip displays details about the error.
Error List If you have the Error List window open, you can see a list of all the validation errors. Double-clicking an error
in the Error List window takes you directly to the error in the editor.
What Validation Checks
Markup validation checks for the following:
Allowed tags Some browser schemas support tags that are not allowed in others. For example, the <blink> tag is
supported only in Netscape browsers, so this tag is marked as invalid in other schemas.
Allowed attributes Validation checks that the attributes in an element are allowed for that element.
Required attributes Validation checks that any required attributes are included. For example, in XHTML, the <script>
tag must have a type attribute.
Allowed attribute values If an attribute supports only certain enumerated values, such as true or false, validation
marks any values that do not conform to the allowed values.
Allowed CSS values Validation checks that the cascading style sheet (CSS) values for the style attribute are allowed.
Allowed child elements Validation checks that child elements are allowed for a given parent element.
Proper use of quotation marks around attribute values Depending on the schema, quotation marks around
attribute values might be required. For schemas where quotation marks are not required, validation checks that if a value
is enclosed in quotation marks, they are balanced. For schemas where quotation marks are optional, validation checks
them according to the validation options you set. See "Customizing Validation" later in this topic.
Casing rules Depending on the schema, element and attributes names might need to be in lowercase letters. If the
schema allows uppercase or lowercase letters in names, validation checks them according to the validation options you
set. See "Customizing Validation" later in this topic.
Unique element IDs Validation ensures that element IDs are unique throughout the page.
Well-formed elements Validation confirms that all opening tags have corresponding closing tags, if the schema
requires it.
Element opening and closing order Validation checks that you do not have crossed opening and closing elements,
such as <b><i>text</b></i>.
Outdated tags or attributes A schema such as XHTML 1.0 Transitional will mark tags such as <font> with an error
that tells you that the tag is no longer recommended.
Valid targets for relative hyperlinks and graphics Validation confirms the validity of any targets that are relative to
the current site, but it does not check the validity of fully qualified URLs.
Validation and Generation
Validation is a distinct operation from generation. When you work in the designer, Visual Studio adds, or generates, markup to
your page. The markup created by the designer is not determined by the current browser schema. Instead, the Web page
designer in Visual Studio always generates XHTML 1.1–compatible markup. For details, see XHTML in Visual Web Developer.
Validating Page Output
Validation checks the markup of the page in the designer. It cannot guarantee that when the page runs in the browser, the
output of the page will validate against a specific schema. Individual ASP.NET server controls and the page itself render
markup, and sometimes script, into the page when the page is processed. That output is not accessible to validation in the
designer.
The markup and scripts that are created at run time will be valid for most browsers. ASP.NET pages and server controls render
markup that is XHTML 1.1–compatible. Most browsers now target standards rather than supporting browser-specific tags,
specifically XHTML. Because XHTML output is compatible with most browsers, the markup rendered at run time by the page
and controls will be valid.
For more information, see ASP.NET and XHTML.
Validation and IntelliSense
Specifying a target browser controls not just validation, but the list of tags and attributes that are available in IntelliSense. For
example, the Internet Explorer 3.02 schema does not offer style attributes because Internet Explorer 3.02 does not support
them. Similarly, the XHTML 1.0 Transitional schema does not offer the <font> tag because <font> tags are deprecated in
XHTML.
Customizing Validation
Depending on the browser schema that you are using, you might be able to specify additional validation options. For example,
if you are using the Internet Explorer 6 schema, you can select whether validation marks element and attribute names that are
not in lowercase letters. For details, see How to: Set Validation Options for HTML Editing in Visual Web Developer.
Disabling Validation
If you do not want to use validation, you can turn it off. For details, see
How to: Set Validation Options for HTML Editing in Visual Web Developer.
Validating Multiple Namespaces
In a Web page, it is possible to include blocks of markup that are declared with their own namespace. For example, an ASP.NET
Web page might include a block of embedded XML that includes a declaration for the namespace in which the XML elements
are defined. In that case, validation is based on a union of the current page schema and the namespace for the embedded
block.
See Also
Tasks
How to: Select Validation Schemas for HTML Editing in Visual Web Developer
Concepts
ASP.NET and XHTML
Visual Web Developer

How to: Select Validation Schemas for HTML Editing in Visual


Web Developer
The Visual Studio HTML editor can check the markup in your page and indicate when elements, attributes, or values are not
valid. The editor determines what is valid based on the currently selected browser schema. For example, if you have set the
browser to Internet Explorer 6, the editor compares the markup in your page against a schema that defines what Internet
Explorer 6 considers valid HTML. For more information, see Markup Validation in Visual Web Developer.
To select a validation schema for HTML editing using the HTML Source Editing toolbar
In the HTML Source Editing toolbar, select a schema from the Target Schema for Validation drop-down list. The
default is Internet Explorer 6.0.
To select a validation schema for HTML editing using the Options dialog box
1. On the Tools menu, click Options.
2. In the Options dialog box, expand the Text Editor node and the HTML node, and then click Validation.
3. From the Target list, select the schema that you want to use for validation and then click OK.
See Also
Tasks
How to: Set Validation Options for HTML Editing in Visual Web Developer
Concepts
Markup Validation in Visual Web Developer
Visual Web Developer

How to: Set Validation Options for HTML Editing in Visual Web
Developer
You can customize markup validation in the HTML editor to specify whether validation checks certain types of constructions.
You can select whether validation ignores uppercase letters in tag and attribute names and whether quotation marks are
required. Also, you can set validation options to disable HTML validation.
To set validation options for HTML editing
1. On the Tools menu, click Options.
2. In the Options dialog box, click Validation.
3. In the Options dialog box, expand the Text Editor node and the HTML node, and then click Validation.
Note
Validation options depend on which validation schema is selected in the Target drop-down list. For example, if the curr
ent validation schema does not allow mixed-case letters in element or attribute names, that option does not apply to th
e current validation schema.

To disable validation for HTML editing


1. On the Tools menu, click Options.
2. In the Options dialog box, click Validation.
3. To disable validation, clear the Show errors check box and then click OK.
See Also
Tasks
How to: Select Validation Schemas for HTML Editing in Visual Web Developer
Concepts
Markup Validation in Visual Web Developer
Visual Web Developer

HTML Editor Tag Navigation in Visual Web Developer


The tag navigator is a representation of the element that is currently selected in the document, along with the hierarchy of
parent tags to which it belongs. You can use the tag navigator to determine which element in the document has the focus. In
addition, you can use the tag navigator to move from the current element to an element that is located higher in the current
hierarchy. For example, you can move from a <td> tag to its parent <table> tag. The tag navigator is particularly useful for
working with deeply nested structures such as tables within tables.
Displaying the Current Path
The tag navigator is displayed at the bottom of the Web page editor. The tag hierarchy is presented as a navigation path (also
known as a breadcrumb) that shows the path from the currently selected tag to the outermost tag available. In Design view, the
outermost tag is the <body> tag because Design view allows you to edit only the contents of the document body. In Source
view, the outermost tag is the <html> tag.
The tag navigator displays all elements in the current document, including both HTML (or other) markup tags and ASP.NET
Web server controls (<asp:> elements). If the element is a Web server control and has an ID attribute or Cascading Style Sheet
(CSS) class, the ID or CSS class value is displayed in the tag navigator to help you distinguish it from other elements. If the tag
path exceeds the width of the designer window, the list is truncated toward the parent tag, and a button is displayed that allows
you to display more parent tags.
Note
The tag navigator does not display all of the elements in the current document. Instead, it shows the path from the current el
ement to the outermost parent. To see all of the elements in the document, use the Document Outline. For details, see
Document Outline Window.

Selecting Elements with the Tag Navigator


You can click a tag in the navigator to select the element that it represents. If the tag can contain content, the tag displays a
drop-down list that allows you to select either the entire element or just its contents. For example, if the tag navigator displays
a <td> tag, you can use the drop-down list on the tag navigator to select either the <td> element (which allows you to set
properties of the element) or the content of the <td> element (which allows you to edit the contents).
The selection feature of the tag navigator is useful when performing block editing operations such as the following:
Editing tables in Source view The tag navigator makes it easy to copy the markup for a table cell (<td> element) and
then copy it, move it, or delete it.
Converting ASP.NET pages into content pages for use with master pages You can use the tag navigator to select
existing markup, and then copy and paste it into a Content control.
See Also
Tasks
How to: Navigate in the HTML Editor in Visual Web Developer
How to: Collapse and Expand HTML Elements in Visual Web Developer
Reference
Source View
Document Outline Window
Concepts
Design View
HTML Editor Tag Navigation in Visual Web Developer
Visual Web Developer

How to: Add Web Browsers to Visual Web Developer


In Visual Web Developer, you can use any Web browser to view your Web pages. If the Browse With dialog box does not list a
browser that is installed on your computer, you can add this browser to the list and then use it to view files within Visual Web
Developer.
To add a Web browser to Visual Web Developer
1. In Solution Explorer, right-click the file that you want to view in a Web browser and then click Browse With.
2. In the Browse With dialog box, click Add.
3. In the Program name text box, type the path to the browser that you want to add. Alternatively, click the ellipses button
and browse to the program.
4. In the Friendly name text box, type a name for this Web browser, and then click OK.
5. If you want to make the new Web browser the default for browsing all files within Visual Web Developer, click Set as
Default.
See Also
Concepts
Testing Web Pages in Visual Web Developer
Visual Web Developer

Walkthrough Topics — Web Page Designer


The following walkthrough topics demonstrate how to use the Visual Web Developer page designer to create and edit ASP.NET
Web pages.
Walkthrough Topics
Walkthrough: Basic HTML Editing in Visual Web Developer
Walkthrough: Advanced HTML Editing in Visual Web Developer
Walkthrough: Working with Cascading Style Sheet Styles in Visual Web Developer
Walkthrough: Editing HTML Tables in Visual Web Developer
See Also
Other Resources
Web Page Designer
Visual Web Developer

How-to Topics — Web Page Designer


The following procedures describe how to use the Visual Web Developer page designer to create and edit ASP.NET Web pages.
How-to Topics
How to: Position Elements in Design View
How to: Insert HTML Hyperlinks and Bookmarks in Design View
How to: Display Hidden Information in Design View
How to: Collapse and Expand HTML Elements in Visual Web Developer
How to: Create Scripts and Edit Event Handlers
How to: Choose an Alternate HTML Editor in Visual Web Developer
How to: Navigate in the HTML Editor in Visual Web Developer
How to: Create External Cascading Style Sheets (Visual Studio)
How to: Link Cascading Style Sheets to ASP.NET Web Pages (Visual Studio)
How to: Add Cascading Style Sheet Attributes in Design View
How to: Create and Edit HTML Tables in Design View
How to: Add and Remove HTML Table Elements in Visual Web Developer
How to: Select HTML Table Elements and Contents in Visual Web Developer
How to: Resize HTML Table Elements in Visual Web Developer
How to: Configure XHTML Rendering in ASP.NET Web Sites
How to: Select Validation Schemas for HTML Editing in Visual Web Developer
How to: Set Validation Options for HTML Editing in Visual Web Developer
How to: Add Web Browsers to Visual Web Developer
See Also
Other Resources
Web Page Designer
Visual Web Developer

Programming ASP.NET Web Pages (Visual Studio)


The topics in this section provide information on how ASP.NET Web pages function as classes and on how to write code in
ASP.NET Web pages.
In This Section
Getting Started — Programming ASP.NET Web Pages
Learning More — Programming ASP.NET Web Pages
See Also
Other Resources
ASP.NET Web Sites (Visual Studio)
ASP.NET Web Pages (Visual Studio)
ASP.NET Web Server Controls (Visual Studio)
Visual Web Developer

Getting Started — Programming ASP.NET Web Pages


The topics in this section provide essential information on ASP.NET Web syntax, how pages function as classes, and on
handling events.
In This Section
ASP.NET Web Page Syntax Overview
ASP.NET Web Page Code Model
Server Event Handling in ASP.NET Web Pages (Visual Studio)
See Also
Other Resources
Programming ASP.NET Web Pages (Visual Studio)
Web Page Designer
ASP.NET Web Sites (Visual Studio)
ASP.NET Web Pages (Visual Studio)
ASP.NET Web Server Controls (Visual Studio)
ASP.NET

ASP.NET Web Page Syntax Overview


ASP.NET Web pages are created in a manner similar to static HTML Web pages (pages that do not include server-based
processing), but they include extra elements that ASP.NET recognizes and processes when the page runs. The characteristics
that distinguish ASP.NET Web pages from static HTML (or other) pages are as follows:
A file name extension of .aspx instead of .htm, .html, or other file name extensions. The .aspx file name extension causes
the page to be processed by ASP.NET.
Note
The mapping of file name extensions to ASP.NET is done in Internet Information Services (IIS). By default, .aspx pages ar
e run by ASP.NET and .htm and .html pages are not.

An optional @ Page directive or other directive, as appropriate to the type of page that you are creating.
A form element that is configured correctly for ASP.NET. The form element is required only if the page contains controls
whose values you want to use during page processing.
Web server controls.
Server code, if you add your own code to the page.
Note
If you want your pages to conform to XHTML standards, you must include additional elements, such as a DOCTYPE elem
ent. For details, see ASP.NET and XHTML.

The sections below provide more details on each of these elements.


You can rename any HTML page with the .aspx file name extension and it will run as an ASP.NET Web page. However, if a page
does not involve server processing, you do not need to add the .aspx file name extension to it because doing so adds overhead
to page processing.
Example ASP.NET Web Page
The following code example shows a page that includes the basic elements that constitute an ASP.NET Web page. The page
contains static text as you might have in an HTML page, along with elements that are specific to ASP.NET. The elements that are
specific to ASP.NET are highlighted.
Note
For clarity, this example page is not configured for XHTML compliance. For details, see ASP.NET and XHTML.

Security Note
This example page contains a text box that accepts user input, which is a potential security threat. By default, ASP.NET Web pa
ges validate that user input does not include script or HTML elements. For more information, see Script Exploits Overview.

VB
<%@ Page Language="VB" %>
<html>
<script runat="server">
Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs)
Label1.Text = "Welcome, " & TextBox1.Text
End Sub
</script>
<head runat="server">
<title>Basic ASP.NET Web Page</title>
</head>
<body>
<form id="form1" runat="server">
<h1>Welcome to ASP.NET</h1>
<p>Type your name and click the button.</p>
<p>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server"
Text="Click" OnClick="Button1_Click" />
</p>
<p>
<asp:Label ID="Label1" runat="server"></asp:Label>
</p>
</form>
</body>
</html>

C#
<%@ Page Language="C#" %>
<html>
<script runat="server">
void Button1_Click(Object sender, EventArgs e)
Label1.Text = "Welcome, " + TextBox1.Text;
End Sub
</script>
<head runat="server">
<title>Basic ASP.NET Web Page</title>
</head>
<body>
<form id="form1" runat="server">
<h1>Welcome to ASP.NET</h1>
<p>Type your name and click the button.</p>
<p>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server"
Text="Click" OnClick="Button1_Click" />
</p>
<p>
<asp:Label ID="Label1" runat="server"></asp:Label>
</p>
</form>
</body>
</html>

@ Directives
ASP.NET pages usually contain directives that allow you to specify page properties and configuration information for the page.
The directives are used by ASP.NET as instructions for how to process the page, but they are not rendered as part of the
markup that is sent to the browser.
The most commonly used directive is the @ Page directive, which allows you to specify many configuration options for the
page, including the following:
The server programming language for code in the page.
Whether the page is a page with server code directly in the page, which is called a single-file page, or whether it is a page
with code in a separate class file, which is called a code-behind page. In the previous example, the page is a single-file
page; the code is directly in the page, and the @ Page directive does not include information about linked class files. For
more information, see the "Server Code" section later in this topic, and see ASP.NET Web Page Code Model.
Debugging and tracing options.
Whether the page has an associated master page and should therefore be treated as a content page.
If you do not include an @ Page directive in the page, or if the directive does not include a specific setting, settings are
inherited the from the configuration file for the Web application (the Web.config file) or from the site configuration file (the
Machine.config file).
In addition to including an @ Page directive, you can include other directives that support additional page-specific options.
Other common directives include the following:
@ Import This directive allows you to specify namespaces that you want to reference in your code.
@ OutputCache This directive allows you to specify that the page should be cached, along with parameters for when
and how long to cache the page.
@ Implements This directive allows you to specify that the page implement a .NET interface.
@ Register This directive allows you to register additional controls for use on the page. The @ Register directive
declares the control's tag prefix and the location of the control's assembly. You must use this directive if you want to add
user controls or custom ASP.NET controls to a page.
Certain types of ASP.NET files use a directive other than @ Page. For example, ASP.NET master pages use an @ Master
directive, and ASP.NET user controls use an @ Control directive. Each directive allows you to specify different options that are
appropriate for the file.
For details, see ASP.NET Master Pages Overview and ASP.NET User Controls.
Form Elements
If your page includes controls that allow users to interact with the page and submit it, the page must include a form element.
You use the standard HTML form element, but certain rules apply. The rules for using the form element are as follows:
The page can contain only one form element.
The form element must contain the runat attribute with the value set to server. This attribute allows you to refer to the
form and the controls on the page programmatically in server code.
Server controls that can perform a postback must be inside the form element.
The opening tag must not contain an action attribute. ASP.NET sets these attributes dynamically when the page is
processed, overriding any settings that you might make.

Web Server Controls


In most ASP.NET pages, you will add controls that allow the user to interact with the page, including buttons, text boxes, lists,
and so on. These Web server controls are similar to HTML buttons and input elements. However, they are processed on the
server, allowing you to use server code to set their properties. These controls also raise events that you can handle in server
code.
Server controls use a special syntax that ASP.NET recognizes when the page runs. The following code example shows some
typical Web server controls.
Security Note
A TextBox accepts user input, which is a potential security threat. By default, ASP.NET Web pages validate that user input does
not include script or HTML elements. For more information, see Script Exploits Overview.

<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>


<asp:Button ID="Button1" runat="server"
Text="Click" OnClick="Button1_Click" />

The tag name for ASP.NET server controls starts with a prefix — in this case, asp:. The prefix might be different if the control is
not part of the .NET Framework. ASP.NET server controls also include the runat="server" attribute and, optionally, an ID that
you can use to reference the control in server code.
When the page runs, it identifies the server controls and runs the code that is associated with those controls. Many controls
render some HTML or other markup into the page. For example, the asp:textbox control renders an input element with the
type="text" attribute into a page. However, there is not necessarily a one-to-one mapping between a Web server control and
an HTML element. For example, the asp:calendar control renders an HTML table. Some controls do not render anything to the
browser; instead, they are processed on the server only, and they provide information to other controls.
HTML Elements as Server Controls
Instead of, or in addition to, using ASP.NET server controls, you can use ordinary HTML elements as server controls. You can
add the runat="server" attribute and an ID attribute to any HTML element in the page. When the page runs, ASP.NET
identifies the element as a server control and makes it available to server code. For example, you can add the required
elements to an HTML body element, as shown in the following code example.

<body runat="server" id="body">

You can then reference the body element in server code — for example, to set the body background color at run time in
response to user input or to information from a database.
For more information, see ASP.NET Web Server Controls.
Server Code
Most ASP.NET pages include code that runs on the server when the page is processed. ASP.NET supports many languages
including C#, Visual Basic, J#, Jscript, and others.
ASP.NET supports two models for writing server code for a Web page. In the single-file model, the code for the page is in a
script element where the opening tag includes the runat="server" attribute. The example earlier in this topic shows the
single-file model.
Alternatively, you can create the code for the page in a separate class file, which is referred to as the code-behind model. In this
case, the ASP.NET Web page generally contains no server code. Instead, the @ Page directive includes information that links
the .aspx page with its associated code-behind file. The following code example shows a typical @ Page directive for a page
with a code-behind file.
VB
<%@ Page Language="VB" CodeFile="Default.aspx.vb" Inherits="Default" %>

C#
<%@ Page Language="C#" CodeFile="Default.aspx.cs" Inherits="Default" %>

The CodeFile attribute specifies the name of the separate class file, and the Inherits attribute specifies the name of the class
within the code-behind file that corresponds to the page.
For more information, see ASP.NET Web Page Code Model.
Note
ASP.NET Web pages can also include client script that runs in the browser in response to client-side events. An ASP.NET page
can include both client script and server code. For details, see Programming ASP.NET Web Pages with Client Script.

See Also
Concepts
ASP.NET Web Pages Overview
Introduction to ASP.NET Web Pages
ASP.NET Expressions Overview
Other Resources
ASP.NET Configuration File Syntax
Programming ASP.NET Web Pages
ASP.NET

Directives for ASP.NET Web Pages


Directives specify settings that are used by the page and user-control compilers when the compilers process ASP.NET Web
Forms pages (.aspx files) and user control (.ascx) files.
ASP.NET treats any directive block (<%@ %>) that does not contain an explicit directive name as an @ Page directive (for a page)
or as an @ Control directive (for a user control).
For syntax information and descriptions of the attributes that are available for each directive, use the links that are listed in the
following table.
Directive Description
@ Assembly Links an assembly to the current page or user control declaratively.

@ Control Defines control-specific attributes used by the ASP.NET page parser and compiler and can be included o
nly in .ascx files (user controls).

@ Implements Indicates that a page or user control implements a specified .NET Framework interface declaratively.

@ Import Imports a namespace into a page or user control explicitly.

@ Master Identifies a page as a master page and defines attributes used by the ASP.NET page parser and compiler
and can be included only in .master files.

@ MasterType Defines the class or virtual path used to type the Master property of a page.

@ OutputCache Controls the output caching policies of a page or user control declaratively.

@ Page Defines page-specific attributes used by the ASP.NET page parser and compiler and can be included only
in .aspx files.

@ PreviousPageType Creates a strongly typed reference to the source page from the target of a cross-page posting.

@ Reference Links a page, user control, or COM control to the current page or user control declaratively.

@ Register Associates aliases with namespaces and classes, which allow user controls and custom server controls to
be rendered when included in a requested page or user control.
See Also
Reference
Application Directives
Concepts
ASP.NET Web Page Syntax Overview
ASP.NET

ASP.NET Web Page Code Model


An ASP.NET Web page consists of two parts:
Visual elements, which include markup, server controls, and static text.
Programming logic for the page, which includes event handlers and other code.
ASP.NET provides two models for managing the visual elements and code — the single-file page model and the code-behind
page model. The two models function the same, and you can use the same controls and code for both models.
This topic explains how each model functions and provides suggestions for when to choose one model or the other.
Note
The code-behind model for ASP.NET version 2.0 is different than that used in previous versions of ASP.NET. For more inform
ation, see What's New in the ASP.NET Web Page Model.

The Single-File Page Model


In the single-file page model, the page's markup and its programming code are in the same physical .aspx file. The
programming code is in a script block that contains the attribute runat="server" to mark it as code that ASP.NET should
execute.
The following code example shows a single-file page containing a Button control and a Label control. The highlighted portion
shows the Click event handler for the Button control inside a script block.
VB
<%@ Page Language="VB" %>
<script runat="server">
Protected Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs)
Label1.Text = "Clicked at " & DateTime.Now.ToString()
End Sub
</script>

<html>
<head id="Head1" runat="server">
<title>Single-File Page Model</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="Label1"
runat="server" Text="Label">
</asp:Label>
<asp:Button ID="Button1"
runat="server" OnClick="Button1_Click" Text="Button">
</asp:Button>
</div>
</form>
</body>
</html>

C#
<%@ Page Language="C#" %>
<script runat="server">
void Button1_Click(Object sender, EventArgs e)
{
Label1.Text = "Clicked at " + DateTime.Now.ToString();
}
</script>
<html>
<head>
<title>Single-File Page Model</title>
</head>
<body>
<form runat="server">
<div>
<asp:Label id="Label1"
runat="server" Text="Label">
</asp:Label>
<br />
<asp:Button id="Button1"
runat="server"
onclick="Button1_Click"
Text="Button">
</asp:Button>
</div>
</form>
</body>
</html>

The script block can contain as much code as the page requires. The code can consist of event handlers for controls on the
page (as in the example), methods, properties, and any other code that you would normally use in a class file. At run time, a
single-file page is treated as a class that derives from the Page class. The page does not contain an explicit class declaration.
Instead, the compiler generates a new class that contains the controls as members. (Not all controls are exposed as page
members; some are children of other controls.) The code in the page becomes part of the class; for example, event handlers
that you create become members of the derived Page class.
For more information, see ASP.NET Page Class Overview.
The Code-Behind Page Model
The code-behind page model allows you to keep the markup in one file—the .aspx file—and the programming code in another
file. The name of the code file varies according to what programming language you are using.
Note
Not all .NET programming languages allow you to create code-behind files for ASP.NET Web pages. Languages must support
partial classes. For example, J# does not support partial classes, and therefore does not support creating code-behind files for
ASP.NET pages.

For example, if you are working with a page named SamplePage, the markup is in the file SamplePage.aspx and the code is in a
file named SamplePage.aspx.vb (for Visual Basic), SamplePage.aspx.cs (for C#), and so on.
Note
The code-behind model used in the .NET Framework version 2.0 is different than the one used in earlier versions. For more i
nformation, see What's New in the ASP.NET Web Page Model.

In the code-behind model, the example used in the preceding section for the single-file page would be in two parts. The
markup would be in one file (in this example, SamplePage.aspx) and would be similar to the single-file page, as shown in the
following code example.
VB
<%@ Page Language="VB" CodeFile="SamplePage.aspx.vb"
Inherits="SamplePage" AutoEventWire="false" %>
<html>
<head runat="server" >
<title>Code-Behind Page Model</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label id="Label1"
runat="server" Text="Label" >
</asp:Label>
<br />
<asp:Button id="Button1"
runat="server"
onclick="Button1_Click"
Text="Button" >
</asp:Button>
</div>
</form>
</body>
</html>

C#
<%@ Page Language="C#" CodeFile="SamplePage.aspx.cs"
Inherits="SamplePage" AutoEventWireup="true" %>
<html>
<head runat="server" >
<title>Code-Behind Page Model</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label id="Label1"
runat="server" Text="Label" >
</asp:Label>
<br />
<asp:Button id="Button1"
runat="server"
onclick="Button1_Click"
Text="Button" >
</asp:Button>
</div>
</form>
</body>
</html>

There are two differences in the .aspx page between the single-file and the code-behind models. In the code-behind model,
there is no script block with the runat="server" attribute. (The page can contain script blocks without the runat="server"
attribute if you want to write client-side script in the page.) The second difference is that the @ Page directive in the code-
behind model contains attributes that reference an external file (SamplePage.aspx.vb or SamplePage.aspx.cs) and a class. These
attributes link the .aspx page to its code.
The code is in a separate file. The following code example shows a code-behind file that contains the same Click event handler
as the example for the single-file page.
VB
Partial Class SamplePage
Inherits System.Web.UI.Page
Protected Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Label1.Text = "Clicked at " & DateTime.Now.ToString()
End Sub
End Class

C#
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class SamplePage : System.Web.UI.Page
{
protected void Button1_Click(object sender, EventArgs e)
{
Label1.Text = "Clicked at " + DateTime.Now.ToString();
}
}

The code-behind file contains the complete class declarations in the default namespace. However, the class is declared with the
partial keyword, which indicates that the class is not contained entirely in one file. Instead, when the page runs, the compiler
reads the .aspx page and the file it references in the @ Page directive, assembles them into a single class, and then compiles
them as a unit into a single class.
The partial class file inherits from the page Page class. For more information, see ASP.NET Page Class Overview.
Choosing a Page Model
The single-file and code-behind page models are functionally the same. At run time, the models execute the same way, and
there is no performance difference between them. Choosing a page model therefore depends on other factors, such as how
you want to organize the code in your application, whether it is important to separate page design from coding, and so on.
Note
Examples you read in the documentation are often presented as single-file pages. This is primarily as a convenience for the r
eader, because it avoids having to illustrate two files for each example. The fact that you find single-file examples in the docu
mentation should not be interpreted to mean that single-file pages are favored over code-behind pages or that there is some
other inherent benefit to single-file pages.

Advantages of Single-File Pages


As a rule, the single-file model is suitable for pages in which the code consists primarily of event handlers for the controls on
the page.
Advantages of the single-file page model include the following:
In pages where there is not very much code, the convenience of keeping the code and markup in the same file can
outweigh other advantages of the code-behind model. For example, it can be easier to study a single-file page because
you can see the code and the markup in one place.
Pages written using the single-file model are slightly easier to deploy or to send to another programmer because there is
only one file.
Because there is no dependency between files, a single-file page is easier to rename.
Managing files in a source code control system is slightly easier, because the page is self-contained in a single file.
Advantages of Code-Behind Pages
Code-behind pages offer advantages that make them suitable for Web applications with significant code or in which multiple
developers are creating a Web site.
Advantages of the code-behind model include the following:
Code-behind pages offer a clean separation of the markup (user interface) and code. It is practical to have a designer
working on the markup while a programmer writes code.
Code is not exposed to page designers or others who are working only with the page markup.
Code can be reused for multiple pages.

Compilation and Deployment


Compilation and deployment of both single-file and code-behind pages is similar. At its simplest, you copy the page to the
target server. If you are working with code-behind pages, you copy both the .aspx page and the code file. When the page is first
requested, ASP.NET compiles the page and runs it. Note that in both scenarios you deploy source code with the markup.
Alternatively, you can precompile your Web site. In that case, ASP.NET produces object code for your pages that you can copy
to the target server. Precompilation works for both single-file and code-behind models, and the output is the same for both
models. For more information, see ASP.NET Web Site Precompilation Overview.
See Also
Concepts
ASP.NET Page Life Cycle Overview
ASP.NET Compilation Overview
Visual Web Developer

Server Event Handling in ASP.NET Web Pages (Visual Studio)


When you work with server controls on an ASP.NET Web page, much of the page's logic involves responding to events raised
by controls. However, events work somewhat differently in ASP.NET Web pages than in client-based forms such as Windows
Forms.
The following topics explain the event-handling model for ASP.NET Web pages and provide instructions on how to create
event handlers.
In This Section
ASP.NET Web Server Control Event Model
How to: Create Event Handlers in ASP.NET Web Pages (Visual Studio)
How to: Connect Multiple Events to a Single Event Handler in ASP.NET Web Pages
How to: Dynamically Bind Event Handlers at Run Time in ASP.NET Web Pages
How to: Determine which Web Server Control Raised an Event
Related Sections
Handling and Raising Events
Links to detailed discussions of how events and event handlers function in ASP.NET.
ASP.NET Web Server Controls (Visual Studio)
Describes the controls available for use on ASP.NET Web pages.
Learning More - Creating Web Pages
Provides content about varied topics including page syntax, page lifecycle, ASP.NET intrinsic objects, ASP.NET expressions
syntax, and much more.
See Also
Other Resources
Programming ASP.NET Web Pages (Visual Studio)
Web Page Designer
ASP.NET Web Sites (Visual Studio)
ASP.NET Web Pages (Visual Studio)
ASP.NET Web Server Controls (Visual Studio)
ASP.NET

ASP.NET Web Server Control Event Model


An important feature of ASP.NET is that it allows you to program Web pages using an event-based model that is similar to that
in client applications. As a simple example, you can add a button to an ASP.NET Web page and then write an event handler for
the button's click event. Although this is common in Web pages that work exclusively with client script (by handling the
button's onclick event in dynamic HTML), ASP.NET brings this model to server-based processing.
Events raised by ASP.NET server controls work somewhat differently than events in traditional HTML pages or in client-based
Web applications. The difference arises primarily because of the separation of the event itself from where the event is handled.
In client-based applications, events are raised and handled on the client. In ASP.NET Web pages, however, events associated
with server controls originate on the client (browser) but are handled on the Web server by the ASP.NET page.
For events raised on the client, the ASP.NET Web control event model requires that the event information be captured on the
client and an event message transmitted to the server, through an HTTP post. The page must interpret the post to determine
what event occurred and then call the appropriate method in your code on the server to handle the event.
ASP.NET handles the task of capturing, transmitting, and interpreting the event. When you create event handlers in an ASP.NET
Web page, you can typically do so without thinking about how the event information is captured and made available to your
code. Instead, you can create event handlers in much the same way you would in a traditional client form. However, there are
some aspects of event handling in ASP.NET Web pages that you should be aware of.
Event Set for Server Controls and Pages
Because most ASP.NET server control events require a round trip to the server for processing, they can affect the performance
of a page. Therefore, server controls offer a limited set of events, usually only click-type events. Some server controls support
change events. For example, the CheckBox Web server control raises a CheckedChanged event in server code when the user
clicks the box. Some server controls support more abstract events. For example, the Calendar Web server control raises a
SelectionChanged event that is a more abstract version of a click event.
Events that occur often (and can be raised without the user knowing it), such as an onmouseover event, are not supported for
server controls. ASP.NET server controls can still call client-side handlers for those events, as explained later under
ASP.NET Web Server Control Event Model.
Controls and the page itself also raise life-cycle events at each processing step, such as Init, Load, and PreRender. You can
take advantage of these life-cycle events in your application. For example, in a page's Load event, you can set default values for
controls.
Event Arguments
Server-based ASP.NET page and control events follow a standard .NET Framework pattern for event-handler methods. All
events pass two arguments: an object representing the object that raised the event, and an event object containing any event-
specific information. The second argument is usually of type EventArgs, but for some controls is of a type specific to that
control. For example, for an ImageButton Web server control, the second argument is of type ImageClickEventArgs, which
includes information about the coordinates where the user has clicked.
Note
Events for the page (for example, the page's Load event) can accept the standard two arguments, but no values are passed in
these arguments.

Postback and Non-Postback Events in Server Controls


In server controls, certain events, typically click events, cause the page to be posted back immediately to the server. Change
events in HTML server controls and Web server controls, such as the TextBox control, do not immediately cause a post. Instead,
they are raised the next time a post occurs.
Note
If the browser supports it, validation controls can check user input using client script, without a round trip to the server. For d
etails, see Validating User Input in ASP.NET Web Pages.

After a page has been posted back, the page's initialization events (Page_Init and Page_Load) are raised, and then control
events are processed. You should not create application logic that relies on the change events being raised in a specific order
unless you have detailed knowledge of page event processing. For details, see ASP.NET Page Life Cycle Overview.
If it useful for your application, you can specify that change events cause the page to post. Web server controls that support a
change event include an AutoPostBack property. When this property is true, the control's change event causes the page to
post immediately, without waiting for a click event. For example, by default, a CheckBox control's CheckedChanged event
does not cause the page to be submitted. However, if you set the control's AutoPostBack property to true, as soon as a user
clicks the check box, the page is sent to the server for processing.
Note
For the AutoPostBack property to work properly, the user's browser must be set to allow scripting. This is the default in mo
st cases. However, some users disable scripting for security reasons. For details, see Client Script in ASP.NET Web Pages.

Forwarded Events
Web server controls such as the Repeater, DataList, GridView, FormView, and DetailsView controls can contain button controls
that themselves raise events. For example, each row in a GridView control can contain one or more buttons created
dynamically by templates.
Rather than each button raising an event individually, events from the nested controls are forwarded to the container control.
The container in turn raises a generic ItemCommand event with parameters that allow you to discover which individual
control raised the original event. By responding to this single event, you can avoid having to write individual event handlers for
child controls.
The ItemCommand event includes the two standard event arguments, an object referencing the source of the event and an
event object containing event-specific information.
Note
The GridView, DataList, and other data controls support additional events, such as EditCommand, DeleteCommand, and
UpdateCommand, that are special cases of forwarded events.

With buttons, you can use the CommandArgument property to pass a user-specified string to the event handler to help you
identify what button raised the event. For example, in a DataList control, buttons raise the ItemCommand event. You can set
the CommandArgument property of each button to a different value—perhaps one button's value is "ShowDetails" and
another button's value is "AddToShoppingCart"—and then capture those values in the event handler later.
Binding Events to Methods
An event is a message like "a button has been clicked". In your application, the message must be translated into a method call
in your code. The binding between the event message and a specific method—that is, an event handler—is done using an
event delegate. For more information, see Events and Delegates.
In ASP.NET Web pages, you do not need to explicitly code delegates if the control is created declaratively (in markup) on the
page. Event binding can be accomplished in various ways, depending on what event you are binding and what programming
language you are using. For details, see How to: Create Event Handlers in ASP.NET Web Pages.
Binding Control Events
For controls declared on the page, you can bind an event to a method by setting an attribute (property) in the control's
markup. The following code example shows how to bind the Click event of an ASP.NET Button control to a method named
ButtonClick.

<asp:button id="SampleButton" runat="server"


text="Submit" onclick="ButtonClick" />

When the page is compiled, ASP.NET looks for a method named ButtonClick and confirms that the method has the
appropriate signature (it accepts two arguments, one of type Object and another of type EventArgs). ASP.NET then
automatically binds the event to the method.
In Visual Basic, you can alternatively bind events to methods using the Handles keyword in the event handler declaration, as in
the following code example:
VB
Private Sub ButtonClick(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles SampleButton.Click

Binding Page Events


ASP.NET pages raise life-cycle events such as Init, Load, PreRender, and others. By default, you can bind page events to
methods using a naming convention of Page_eventname. For example, to create a handler for the page's Load event, you can
create a method named Page_Load. At compilation time, ASP.NET will find methods based on this naming convention and
automatically perform the binding between the event and the method. You can use the convention of Page_eventname for
any event exposed by the Page class.
Note
Page event-handling methods do not require any arguments.

If you prefer, you can create handlers explicitly. The automatic binding of page events based on the method naming convention
is controlled by a page property named AutoEventWireup. By default, this property is set to true, and ASP.NET performs the
automatic lookup and binding described earlier. Alternatively, you can set this property to false by adding the attribute
AutoEventWireup=false in the @ Page directive. You can then create methods with any name and bind them to page events
explicitly. In Visual Basic, you can use the Handles keyword, as in the following code example:
VB
Sub MyPageLoad(sender As Object, e As EventArgs) Handles MyBase.Load

The disadvantage of the AutoEventWireup attribute is that it requires that the page event handlers have specific, predictable
names. This limits your flexibility in how you name your event handlers.
Note
If you include explicit binding for page events, be sure that the AutoEventWireup property is set to false so that the metho
d is not inadvertently called twice.

Explicit Binding for Dynamic Controls


If you create controls by declaring them in markup, you can bind events to methods using an attribute (for example, onclick)
or in Visual Basic, by using the Handles keyword. If you create controls dynamically (in code), you cannot use either of these
methods, because the compiler does not have a reference to the control at compilation time.
In that case, you must use explicit event binding. In Visual Basic, you can use the AddHandler statement to bind an event in a
dynamically created control to an existing method. In C#, you create a delegate and associate it with the control's event. The
following code example shows how you can bind a method named ButtonClick to a button's Click event:
VB
Dim b As New Button
b.Text = "Click"
AddHandler b.Click, AddressOf ButtonClick
Placeholder1.Controls.Add(b)

C#
Button b = new Button;
b.Text = "Click";
b.Click += new System.EventHandler(ButtonClick);
Placeholder1.Controls.Add(b);

Responding to Both Client and Server Events in ASP.NET Server Controls


This topic has discussed how to work with events raised in server code. Controls render elements to the browser, and those
elements can also raise client-side events that you can handle in client script. Using client script, you can add mouse and
keyboard event handling to ASP.NET server controls. For more information, see Client Script in ASP.NET Web Pages and
How to: Add Client Script Events to ASP.NET Web Server Controls.
Application and Session Events
In addition to page and control events, ASP.NET provides ways for you to work with life-cycle events that are raised when your
application starts or stops or when an individual user's session starts or stops, including the following:
Application events are raised for all requests to an application. For example, the BeginRequest event of the
HttpApplication object (Application_BeginRequest) is raised when any ASP.NET Web page or XML Web service in your
application is requested. This event allows you to initialize resources that will be used for each request to the application.
A corresponding event, the EndRequest event of the HttpApplication object (Application_EndRequest), provides you
with an opportunity to close or otherwise dispose of resources used for the request.
Session events are similar to application events (there is a Start and an End event), but are raised with each unique
session within the application. A session begins when a user requests a page for the first time from your application and
ends either when your application explicitly closes the session or when the session times out.
Note
The Session_End event is not raised under all circumstances. For details, see End.

You can create handlers for these types of events in the Global.asax file. For details, see
ASP.NET Application Life Cycle Overview and Global.asax Syntax.
See Also
Tasks
How to: Create Event Handlers in ASP.NET Web Pages
Concepts
ASP.NET State Management Overview
Other Resources
Server Event Handling in ASP.NET Web Pages
Visual Web Developer

How to: Create Event Handlers in ASP.NET Web Pages (Visual


Studio)
When you are editing an ASP.NET Web page in Visual Studio, you can create server event handlers for controls and for the
page in a variety of ways. Some of the ways depend on which programming language you are working in. You can create
handlers by using the facilities in Visual Web Developer, or you can create them declaratively or in code.
Note
You can also add events for client script, which execute when the control is running in the browser as an element in the page.
For details, see How to: Add Client Script Events to ASP.NET Web Server Controls.

If a control supports more than one event, it is usually configured so that one event is the default. For example, for the Button
control, the default event is the Click event.
Creating Event Handlers in Visual Web Developer
To create an event handler for the default event
In Design view, double-click the page or double-click the control for which you want to create a default event handler.
Visual Web Developer creates a handler for the default event and opens the code editor with the insertion point in the
event handler.
To create an event handler in the Properties window
1. In Design view, select the control for which you want to create an event handler.
Note
You cannot select the page in Design view, so you cannot create a page-level event using this procedure. Use the previ
ous procedure instead.

2. In Properties, click the events symbol .


The Properties window displays a list of events for the selected control.
3. In the box next to an event name, do one of the following:
Double-click to create a new event handler for that event. The designer will name the handler using the convention
controlID_event.
Type the name of the handler to create.
In the drop-down list, select the name of an existing handler.
The drop-down list displays a list of methods that have the correct signature for the event.
When you are finished, Visual Web Developer switches to the code editor and puts the insertion point in the handler.
To create an event handler in the code editor
1. Switch to the code editor by using one of the following techniques:
For a single-file Web page, switch to Source view.
For a code-behind page, in Solution Explorer, right-click the name of the page, and then click View Code.
Note
In code-behind pages that use C#, this technique will not work because the control name will not appear in the drop-do
wn list in the last step. Use one of the other procedures instead.

2. At the top of the code editor window, select the control from the drop-down list located on the left side, and then select
the event from the drop-down list located on the right side.
Note
Events for which methods already exist are displayed in bold text.

Creating Event Handlers Declaratively


When you use Visual Web Developer to create a handler, Visual Web Developer creates the skeleton handler and configures
the control to call the handler. You can do the same yourself without using Visual Web Developer.
To create a handler for page events
In the code editor, create a method with the name Page_event.
For example, to create a handler for the page's Load event, create a method named Page_Load.
Note
Page event handlers are not required to take parameters the way that other controls event handlers are.

ASP.NET pages automatically bind page events to methods that have the name Page_event. This automatic binding is
configured by the AutoEventWireup attribute in the @ Page directive, which is set to true by default. If you set
AutoEventWireup to false, the page does not automatically search for methods that use the Page_event naming
convention.
The following code example shows a handler for the page's Load event.
VB
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles M
e.Load
If Page.IsPostBack Then
Response.Write("<br>Page has been posted back.")
End If
End Sub

C#
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
Response.Write("<br>Page has been posted back.");
}
}

To add a handler declaratively for a control


1. In the code editor, create an event-handling method with the appropriate signature.
The method can be named anything you like.
2. In the markup of the control, use the attributes that are named On<event name> to hook up the event handler. Use the
event handler method name as the value.
The following code example shows the markup for a TextBox control for which the TextChanged event is bound to the
event handler method named NameChange:
Security Note
This example contains a text box that accepts user input, which is a potential security threat. By default, ASP.NET Web p
ages validate that user input does not include script or HTML elements. For more information, see
Script Exploits Overview.

VB
Protected Sub NameChange(ByVal sender As Object, ByVal e As System.EventArgs) Handles
textbox1.TextChanged
'Sub for the OnTextChanged event
End Sub

C#
<asp:TextBox ID="textbox1" Runat="server"
Text=""
OnTextChanged="NameChange" />

3. Add the event method to your code. For example, the following code example shows the code for the event handler
method named NameChange:
C#
protected void NameChange(object sender, EventArgs e)
{
//Method for the OnTextChanged event.
}

To add an even handler implicitly in Visual Basic


1. In the code editor, create an event-handling method with the appropriate signature.
The method can be named anything you like.
2. Use the Handles keyword, specifying the control and event to which the method should bind.
The following code example shows an event handler for the Click event of a button named SampleButton. The method in
the example is named Clicked.
VB
Protected Sub SampleButton_Click(ByVal sender As Object, ByVal e As System.EventArgs)
_
Handles SampleButton.Click
' Code goes here.
End Sub

Note
If you use the Handles keyword, do not include an event attribute in the control markup. If you do, the handler will be
called twice.
3. If the method handles multiple events, add the names of the additional events to the Handles clause, separated by a
comma.
The following code example shows a method that handles the Click event for several buttons. In the handler, the code
tests the sender argument to determine which button was clicked.
VB
Protected Sub AnyClicked(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles Button1.Click, Button2.Click, Button3.Click
Dim b As Button = CType(sender, Button)
Response.Write("You clicked the button labeled " & b.ID)
End Sub

See Also
Tasks
How to: Dynamically Bind Event Handlers at Run Time in ASP.NET Web Pages
Other Resources
Handling and Raising Events
Server Event Handling in ASP.NET Web Pages (Visual Studio)
ASP.NET Web Server Controls
ASP.NET

How to: Connect Multiple Events to a Single Event Handler in


ASP.NET Web Pages
If you already have an event handler, you can bind several control events to it. These multiple events can be from the same
control or one event from several different controls, as long as the events all have the same method signature. For example,
you might want to bind the Click events of several Button server controls on an ASP.NET page to a single event handler. When
your handler is called, you can determine which control caused the event.
To connect multiple events to a single event handler
In the page markup, add the same event name and method name to each control, as in the following code example.

<asp:Button ID="Button1" onclick="Button_Click" runat="server"


Text="Button1" />
<br />
<asp:Button ID="Button2" onclick="Button_Click" runat="server"
Text="Button2" />

Note
You must make sure that the method has the correct signature for the event that it is handling.

To connect multiple events to a single event handler in Visual Basic


Modify the Handles clause of a method by adding the names of the events that the method should handle. Separate the
event names with commas.
The following code example shows how you can bind the Button_Click method to events raised by three Button
controls.
VB
Sub Button_Click (ByVal sender as System.Object, _
ByVal e as System.EventArgs) _
Handles Button1.Click, Button2.Click, Button3.Click

Note
If you use a Handles clause to bind an event and method, do not also include the event attribute in the markup. For exa
mple, do not include an onClick attribute in the markup for a Button control. If you do, the method will be called twice
.

To determine which control raised the event


1. In the event handler, declare a variable whose type matches the controls that raise the event.
2. Assign the first argument of the event handler to the variable, casting it to the appropriate type.
The following code example shows the handler for a Button control's Click event that is called by several different
buttons. The handler displays the ID property of the button that caused the event.
VB
Private Sub Button_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click, Button2.Click, Button3.Click
Dim b As Button = CType(sender, Button)
Label1.Text = b.ID
End Sub

C#
private void Button_Click(object sender, System.EventArgs e)
{
Button b = (Button) sender;
Label1.Text = b.ID;
}

See Also
Other Resources
Server Event Handling in ASP.NET Web Pages
ASP.NET

How to: Dynamically Bind Event Handlers at Run Time in


ASP.NET Web Pages
If a page already contains an event-handling method with the appropriate signature, you can bind a control event to it at run
time. You commonly do this when you are creating controls programmatically.
To create an event handler at run time by using Visual Basic
Include an AddHandler Statement, passing it the event to bind and the address of the method to call.
Be sure that the statement is executed before the event can be raised. Typically, you add handlers during page
initialization.
The following code example shows how to bind the Click event of the Button1 control to a method named
myEventHandler:

VB
AddHandler Button1.Click, AddressOf myEventHandler

To create an event handler at run time by using Visual C#


1. Create an instance of the EventHandler delegate, passing to it the address of the method to bind to.
2. Add the delegate object to the list of methods that are called when the event is raised.
The following code example shows how to bind the Click event of the Button1 control to a method named
myEventHandler:

C#
Button1.Click += new System.EventHandler(this.myEventHandler);

See Also
Concepts
ASP.NET Web Server Control Event Model
Other Resources
Server Event Handling in ASP.NET Web Pages
Adding ASP.NET Controls Programmatically
ASP.NET

How to: Determine which Web Server Control Raised an Event


When an event handler is called, you can determine which control caused the event.
To determine which control caused the event
1. In the event handler, declare a variable whose type matches the control that raised the event.
2. Assign the sender argument of the event handler to the variable, casting it to the appropriate type.
The following example shows the handler for a Button-control click event that is called by several different buttons. The
handler displays information about which button was clicked.
VB
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click, Button2.Click, Button3.Click

Dim b As Button
b = CType(sender, Button)

Select Case b.ID


Case "Button1"
Label1.Text = "You clicked the first button"
Case "Button2"
Label1.Text = "You clicked the second button"
Case "Button3"
Label1.Text = "You clicked the third button"
End Select
End Sub

C#
private void Button_Click(object sender, System.EventArgs e)
{
Button b;
b = (Button)sender;
switch (b.ID)
{
case "Button1":
Label1.Text = "You clicked the first button";
break;
case "Button2":
Label1.Text = "You clicked the second button";
break;
case "Button3":
Label1.Text = "You clicked the third button";
break;
}
}

See Also
Concepts
ASP.NET Web Server Control Event Model
Other Resources
Server Event Handling in Web Forms Pages (Visual Studio)
Handling and Raising Events
Visual Web Developer

Learning More — Programming ASP.NET Web Pages


The topics in this section provide in-depth information on ASP.NET Web syntax, on how pages function as classes, and on
handling events.
In This Section
ASP.NET Page Class Overview
ASP.NET Page Life Cycle Overview
Redirecting Users to Another Page
How to: Detect Browser Types in ASP.NET Web Pages
Embedded Code Blocks in ASP.NET Web Pages
See Also
Other Resources
Programming ASP.NET Web Pages (Visual Studio)
Web Page Designer
ASP.NET Web Sites (Visual Studio)
ASP.NET Web Pages (Visual Studio)
ASP.NET Web Server Controls (Visual Studio)
ASP.NET

ASP.NET Page Class Overview


When an ASP.NET page is requested and renders markup to a browser, the code that runs is not solely the code that you
created for your page. Instead, at run time, ASP.NET generates and compiles one or more classes that actually perform the
tasks required to run the page. This topic provides an overview of the code that is generated at run time.
Generating and Running the Page Class Code
An ASP.NET page runs as a unit, combining the server-side elements in a page, such as controls, with the event-handling code
you have written. You do not have to precompile pages into assemblies. ASP.NET dynamically compiles pages and runs them
the first time they are requested by a user. If there are any changes to the page or resources the page depends on, the page is
automatically recompiled. The class or classes that the compiler creates depends on whether the page uses the single-file
model or the code-behind model.
ASP.NET also supports precompilation of a Web site to enhance performance and perform error checking as well as to support
site deployment. For more information, see ASP.NET Web Site Precompilation Overview. Precompilation works for both single-
file and code-behind page models, and the compiler output is the same for both models.
Single-File Pages
In a single-file page, the markup, server-side elements, and event-handling code are all in a single .aspx file. When the page is
compiled, the compiler generates and compiles a new class that derives from the base Page class or a custom base class
defined with the Inherits attribute of the @ Page directive. For example, if you create a new ASP.NET Web page named
SamplePage1 in your application's root directory then a new class named ASP.SamplePage1_aspx is derived from the Page
class. For pages inside of application subfolders, the subfolder name is used as part of the generated class. The generated class
contains declarations for the controls in the .aspx page and contains your event handlers and other custom code.
After page generation, the generated class is compiled into an assembly, the assembly is loaded into the application domain,
and then the page class is instantiated and executed to render output to the browser. If you make changes to the page that
would affect the generated class—whether by adding controls or modifying your code—the compiled class code is invalidated
and a new class is generated. For more information on compilation in ASP.NET, see ASP.NET Compilation Overview.
The following illustration shows the inheritance model for the page class in a single-file ASP.NET Web page:

Code-Behind Pages
In the code-behind model, the page's markup and server-side elements, including control declarations, are in an .aspx file,
while your page code is in a separate code file. The code file contains a partial class—that is, a class declaration with the
keyword partial (Partial in Visual Basic) indicating that it contains only some of the total code that makes up the full class for
the page. In the partial class, you add the code that your application requires for the page. This typically consists of event
handlers, but can include any methods or properties that you need.
The inheritance model for code-behind pages is slightly more complex than that for single-file pages. The model is this:
1. The code-behind file contains a partial class that inherits from a base page class. The base page class can be the Page
class, or it can be another class that derives from Page.
2. The .aspx file contains an Inherits attribute in the @ Page directive that points to the code-behind partial class.
3. When the page is compiled, ASP.NET generates a partial class based on the .aspx file; this class is a partial class of the
code-behind class file. The generated partial class file contains declarations for the page's controls. This partial class
enables your code-behind file to be used as part of a complete class without requiring you to declare the controls
explicitly.
4. Finally, ASP.NET generates another class that inherits from the class generated in Step 3. This second generated class
contains the code required to build the page. The second generated class and the code-behind class are compiled into an
assembly that runs to render output to the browser.
The following illustration shows the inheritance model for the page class in a code-behind ASP.NET Web page:

See Also
Concepts
ASP.NET Web Page Code Model
ASP.NET

ASP.NET Page Life Cycle Overview


When an ASP.NET page runs, the page goes through a life cycle in which it performs a series of processing steps. These include
initialization, instantiating controls, restoring and maintaining state, running event handler code, and rendering. It is important
for you to understand the page life cycle so that you can write code at the appropriate life-cycle stage for the effect you intend.
Additionally, if you develop custom controls, you must be familiar with the page life cycle in order to correctly initialize
controls, populate control properties with view-state data, and run any control behavior code. (The life cycle of a control is
based on the page life cycle, but the page raises more events for a control than are available for an ASP.NET page alone.)
General Page Life-cycle Stages
In general terms, the page goes through the stages outlined in the following table. In addition to the page life-cycle stages,
there are application stages that occur before and after a request but are not specific to a page. For more information, see
ASP.NET Application Life Cycle Overview.
Stage Description
Page req The page request occurs before the page life cycle begins. When the page is requested by a user, ASP.NET determine
uest s whether the page needs to be parsed and compiled (therefore beginning the life of a page), or whether a cached ve
rsion of the page can be sent in response without running the page.

Start In the start step, page properties such as Request and Response are set. At this stage, the page also determines whet
her the request is a postback or a new request and sets the IsPostBack property. Additionally, during the start step, th
e page's UICulture property is set.

Page init During page initialization, controls on the page are available and each control's UniqueID property is set. Any themes
ialization are also applied to the page. If the current request is a postback, the postback data has not yet been loaded and contr
ol property values have not been restored to the values from view state.

Load During load, if the current request is a postback, control properties are loaded with information recovered from view
state and control state.

Validatio During validation, the Validate method of all validator controls is called, which sets the IsValid property of individual
n validator controls and of the page.

Postback If the request is a postback, any event handlers are called.


event ha
ndling

Renderi Before rendering, view state is saved for the page and all controls. During the rendering phase, the page calls the
ng Render method for each control, providing a text writer that writes its output to the OutputStream of the page's Res
ponse property.

Unload Unload is called after the page has been fully rendered, sent to the client, and is ready to be discarded. At this point, p
age properties such as Response and Request are unloaded and any cleanup is performed.

Life-cycle Events
Within each stage of the life cycle of a page, the page raises events that you can handle to run your own code. For control
events, you bind the event handler to the event, either declaratively using attributes such as onclick, or in code.
Pages also support automatic event wire-up, meaning that ASP.NET looks for methods with particular names and
automatically runs those methods when certain events are raised. If the AutoEventWireup attribute of the @ Page directive is
set to true (or if it is not defined, since by default it is true), page events are automatically bound to methods that use the
naming convention of Page_event, such as Page_Load and Page_Init. For more information on automatic event wire-up, see
ASP.NET Web Server Control Event Model.
The following table lists the page life-cycle events that you will use most frequently. There are more events than those listed;
however, they are not used for most page processing scenarios. Instead, they are primarily used by server controls on the
ASP.NET Web page to initialize and render themselves. If you want to write your own ASP.NET server controls, you need to
understand more about these stages. For information about creating custom controls, see
Developing Custom ASP.NET Server Controls.
Page Event Typical Use
PreInit Use this event for the following:
Check the IsPostBack property to determine whether this is the first time the page is being processe
d.
Create or re-create dynamic controls.
Set a master page dynamically.
Set the Theme property dynamically.
Read or set profile property values.
Note
If the request is a postback, the values of the controls have not yet been restored from view state. If
you set a control property at this stage, its value might be overwritten in the next event.

Init Raised after all controls have been initialized and any skin settings have been applied. Use this event to rea
d or initialize control properties.

InitComplete Raised by the Page object. Use this event for processing tasks that require all initialization be complete.

PreLoad Use this event if you need to perform processing on your page or control before the Load event.
After the Page raises this event, it loads view state for itself and all controls, and then processes any postb
ack data included with the Request instance.

Load The Page calls the OnLoad event method on the Page, then recursively does the same for each child contr
ol, which does the same for each of its child controls until the page and all controls are loaded.
Use the OnLoad event method to set properties in controls and establish database connections.

Control events Use these events to handle specific control events, such as a Button control's Click event or a TextBox contr
ol's TextChanged event.
Note
In a postback request, if the page contains validator controls, check the IsValid property of the Page and
of individual validation controls before performing any processing.

LoadComplete Use this event for tasks that require that all other controls on the page be loaded.

PreRender Before this event occurs:


The Page object calls EnsureChildControls for each control and for the page.
Each data bound control whose DataSourceID property is set calls its DataBind method. For more inf
ormation, see Data Binding Events for Data-Bound Controls below.
The PreRender event occurs for each control on the page. Use the event to make final changes to the cont
ents of the page or its controls.

SaveStateComplete Before this event occurs, ViewState has been saved for the page and for all controls. Any changes to the pa
ge or controls at this point will be ignored.
Use this event perform tasks that require view state to be saved, but that do not make any changes to cont
rols.
Render This is not an event; instead, at this stage of processing, the Page object calls this method on each control.
All ASP.NET Web server controls have a Render method that writes out the control's markup that is sent t
o the browser.
If you create a custom control, you typically override this method to output the control's markup. However
, if your custom control incorporates only standard ASP.NET Web server controls and no custom markup,
you do not need to override the Render method. For more information, see
Developing Custom ASP.NET Server Controls.
A user control (an .ascx file) automatically incorporates rendering, so you do not need to explicitly render t
he control in code.
Unload This event occurs for each control and then for the page. In controls, use this event to do final cleanup for s
pecific controls, such as closing control-specific database connections.
For the page itself, use this event to do final cleanup work, such as closing open files and database connect
ions, or finishing up logging or other request-specific tasks.
Note
During the unload stage, the page and its controls have been rendered, so you cannot make further chan
ges to the response stream. If you attempt to call a method such as the Response.Write method, the pa
ge will throw an exception.

Additional Page Life Cycle Considerations


Individual ASP.NET server controls have their own life cycle that is similar to the page life cycle. For example, a control's Init
and Load events occur during the corresponding page events.
Although both Init and Load recursively occur on each control, they happen in reverse order. The Init event (and also the
Unload event) for each child control occur before the corresponding event is raised for its container (bottom-up). However the
Load event for a container occurs before the Load events for its child controls (top-down).
You can customize the appearance or content of a control by handling the events for the control, such as the Click event for
the Button control and the SelectedIndexChanged event for the ListBox control. Under some circumstances, you might also
handle a control's DataBinding or DataBound events. For more information, see the class reference topics for individual
controls and Developing Custom ASP.NET Server Controls.
When inheriting a class from the Page class, in addition to handling events raised by the page, you can override methods from
the page's base class. For example, you can override the page's InitializeCulture method to dynamically set culture information.
Note that when creating an event handler using the Page_event syntax, the base implementation is implicitly called and
therefore you do not need to call it in your method. For example, the base page class's OnLoad method is always called,
whether you create a Page_Load method or not. However, if you override the page OnLoad method with the override
keyword (Overrides in Visual Basic), you must explicitly call the base method. For example, if you override the OnLoad
method on the page, you must call base.Load (MyBase.Load in Visual Basic) in order for the base implementation to be run.
Catch-up Events for Added Controls
If controls are created dynamically at run time or are authored declaratively within templates of data-bound controls, their
events are initially not synchronized with those of other controls on the page. For example, for a control that is added at run
time, the Init and Load events might occur much later in the page life cycle than the same events for controls created
declaratively. Therefore, from the time that they are instantiated, dynamically added controls and controls in templates raise
their events one after the other until they have caught up to the event during which it was added to the Controls collection.
In general, you do not need to be concerned about this unless you have nested data-bound controls. If a child control has been
data bound, but its container control has not yet been data bound, the data in the child control and the data in its container
control can be out of sync. This is true particularly if the data in the child control performs processing based on a data-bound
value in the container control.
For example, suppose you have a GridView that displays a company record in each row along with a list of the company
officers in a ListBox control. To fill the list of officers, you would bind the ListBox control to a data source control (such as
SqlDataSource) that retrieves the company officer data using the CompanyID in a query.
If the ListBox control's data-binding properties, such as DataSourceID and DataMember, are set declaratively, the ListBox
control will try to bind to its data source during the containing row's DataBinding event. However, the CompanyID field of the
row does not contain a value until the GridView control's RowDataBound event occurs. In this case, the child control (the
ListBox control) is bound before the containing control (the GridView control) is bound, so their data-binding stages are out
of sync.
To avoid this condition, put the data source control for the ListBox control in the same template item as the ListBox control
itself, and do not set the data binding properties of the ListBox declaratively. Instead, set them programmatically at run time
during the RowDataBound event, so that the ListBox control does not bind to its data until the CompanyID information is
available.
For more information, see Binding to Data Using a Data Source Control.
Data Binding Events for Data-Bound Controls
To help you understand the relationship between the page life cycle and data binding events, the following table lists data-
related events in data-bound controls such as the GridView, DetailsView, and FormView controls.
Control Event Typical Use
DataBinding This event is raised by data-bound controls before the PreRender event of the
containing control (or of the Page object) and marks the beginning of binding t
he control to the data.
Use this event to manually open database connections, if required. (The data so
urce controls often make this unnecessary.)

RowCreated (GridView only) or ItemCreated Use this event to manipulate content that is not dependent on data binding. For
(DataList, DetailsView, SiteMapPath, example, at run time, you might programmatically add formatting to a header o
DataGrid, FormView, and Repeater controls) r footer row in a GridView control.

RowDataBound (GridView only) or When this event occurs, data is available in the row or item, so you can format
ItemDataBound (DataList, SiteMapPath, Dat data or set the FilterExpression property on child data source controls for displa
aGrid, and Repeater controls) ying related data within the row or item.

DataBound This event marks the end of data-binding operations in a data-bound control. In
a GridView control, data binding is complete for all rows and any child control
s.
Use this event to format data bound content or to initiate data binding in other
controls that depend on values from the current control's content. (For details, s
ee "Catch-up Events for Added Controls" earlier in this topic.)

Login Control Events


The Login control can use settings in the Web.config file to manage membership authentication automatically. However, if your
application requires you to customize how the control works, or if you want to understand how Login control events relate to
the page life cycle, you can use the events listed in the following table.
Control Ev Typical Use
ent
LoggingIn This event is raised during a postback, after the page's LoadComplete event has occurred. It marks the beginnin
g of the login process.
Use this event for tasks that must occur prior to beginning the authentication process.

Authenticate This event is raised after the LoggingIn event.


Use this event to override or enhance the default authentication behavior of a Login control.

LoggedIn This event is raised after the user name and password have been authenticated.
Use this event to redirect to another page or to dynamically set the text in the control. This event does not occur if
there is an error or if authentication fails.

LoginError This event is raised if authentication was not successful.


Use this event to set text in the control that explains the problem or to direct the user to a different page.
See Also
Reference
Validating User Input in ASP.NET Web Pages
ASP.NET Login Controls Overview
Concepts
ASP.NET Web Server Control Event Model
Page and Application Context in ASP.NET Web Applications
View State Overview
Binding to Data Using a Data Source Control
Other Resources
Developing Custom ASP.NET Server Controls
ASP.NET Page Syntax
Server Event Handling in ASP.NET Web Pages
ASP.NET

Redirecting Users to Another Page


You will often want to redirect users to other pages as part of your Web application. ASP.NET provides the following ways for
you to build redirection into your Web pages:
Using hyperlinks on pages.
Configuring cross-page posting, which enables you to specify an alternate target page when the current page is
submitted.
Redirecting programmatically by forcing the browser to request a different page.
Redirecting programmatically by transferring control to a different page in the same Web application.
Each of these options is described below. A table at the end of the topic summarizes the options and provides guidelines to
help you decide when to use each option.
Hyperlinks
You can use an HTML anchor tag (<a>) on an ASP.NET Web page to create static links, or you can programmatically control
the link text and target URL of hyperlinks using the HyperLink control. In this scenario, the user explicitly clicks a link and the
browser transfers to the target page. The target page is invoked using an HTTP GET command. Therefore, no information about
the source page is passed to the target page unless you specify a query string on the URL of the target page. If the source and
target page are in the same Web application, they can share information using session state or application state.
Cross-Page Posting
By default, buttons in an ASP.NET Web page post the page to itself. Cross-page posting enables you to configure a button on
an ASP.NET Web page to post the current page to a different page. A typical example is when creating a multi-page form. You
can configure buttons on the page to move to the next and previous pages of the form.
Cross-page posting is similar to hyperlinks in that the transfer is initiated by a user action. However, in cross-page posting, the
target page is invoked using an HTTP POST command, which sends the values of controls on the source page to the target
page. In addition, if the source and target page are in the same Web application, the target page can access public properties of
the source page. As always, all of the pages in the application can share information stored in session state or application state.
For more information, see Cross-Page Posting in ASP.NET Web Pages and
How to: Post ASP.NET Web Pages to a Different Page.
Redirecting Programmatically Using the Browser
You can redirect users to another page using the capabilities of the user's browser. In a browser redirect, the browser issues a
new request to the target server in the form of an HTTP GET request.
You can trigger the redirect programmatically in client script or server code. In client script, you can call the form.submit
method, provided the <form> element's method attribute value is get. In that case, if the current page contains form data, it
is passed to the target server by appending it as a query string onto the requested URL.
In server code, you can programmatically redirect by calling the Redirect method. The method sends a command to the user's
browser that causes the browser to issue an HTTP GET command for the target page. Calling the server Redirect method is the
programmatic equivalent of clicking a hyperlink, in that it results in a new request for the target page. Because you are calling
the methods from your own code, you can dynamically define the target URL, including any query-string information. If the
source and target pages are in the same Web application, you can share data between the source and target pages by adding
server code to store the data in session state.
Note
Internet Explorer through version 6.0 can process only up to 2,048 characters in the URL, including data in the query string. If
the URL exceeds 2,048 characters, an error may result, or data in the query string might be truncated or not sent with the req
uest. In ASP.NET Web pages, a GET request that includes post data can easily exceed 2,048 characters if view state informatio
n (which is stored in a hidden field) is part of the request, resulting in errors. Other browsers may not have this limitation. For
more information, see article 208247, "Maximum URL Length Is 2,083 Characters in Internet Explorer" in the Microsoft Know
ledge Base at http://support.microsoft.com. To work around this limitation when you are trying to share information among
pages, you can redirect users by using HTTP POST requests as discussed in this topic. If your application requires an HTTP GE
T request, you can store information in an alternative way, without using a query string, such as in session state.
Redirecting Programmatically on the Server
You can also redirect programmatically to a target page on the server by calling the Transfer method. In this scenario, the
server simply transfers the current source page context to the target page. The target page then renders in place of the source
page. The source and target pages must be in the same Web application. As with cross-page posting, the Transfer method has
the advantage that it enables the source page to read control values and public property values from the source page.
Because the transfer between source and target pages happens on the server, the browser has no information about the
changed page, and it retains information about the original (source) URL. For example, the Address box in Internet Explorer
does not change after a transfer, and instead continues to show the URL of the page it most recently requested (which is
usually the source page). The browser's history is not updated to reflect the transfer. This can result in unexpected behavior if
the user refreshes the page in the browser or clicks the browser's back button. Therefore, calling the Transfer method is a
strategy that is best used in applications where you are presenting pages to the user with the URL hidden.
Selecting a Redirect Option
The following table summarizes the possible ways to redirect between pages.
Strat Characteristics Usage
egy
Hype Performs new request on the target page. For navigation without any additional processing, as in menus
rlink or lists of links.
s Does not pass current page information to th
e target page. When navigation should be under user control.
Requires user initiation.
Redirects to any page, not just pages in the s
ame Web application.
Enables you to share information between pa
ges using query string or session state. (The
HyperLink control enables you to create UR
L and query strings programmatically.)

Cros Posts current page information to the target To pass current page information to the target page (as in mult
s-pa page. i-page forms).
ge p
ostin Makes post information available in the targe When navigation should be under user control.
g t page.
Requires user initiation.
Redirects to any page, not just pages in the s
ame Web application.
Enables the target page to read public proper
ties of the source page if the pages are in the
same Web application.
Brow Performs a new HTTP GET request on the tar For conditional navigation, when you want to control the target
ser r get page. URL and control when navigation takes place. For example, use
edire this option if the application must determine which page to nav
ct Passes the query string (if any) to the target igate to based on data provided by the user.
page. In Internet Explorer, the size of the quer
y string is limited to 2,048 characters.
Provides programmatic and dynamic control
over the target URL and query string.
Enables you to redirect to any page, not just
pages in the same Web application.
Enables you to share information between so
urce and target pages using session state.

Serv Transfers control to a new page that renders For conditional navigation, when you want to control when nav
er tr in place of the source page. igation takes place and you want access to the context of the so
ansf urce page.
er Redirects only to target pages that are in the
same Web application as the source page. Best used in situations where the URL is hidden from the user.
Enables you to read values and public proper
ties from source page.
Does not update browser information with in
formation about the target page. Pressing th
e refresh or back buttons in the browser can
result in unexpected behavior.

See Also
Tasks
How to: Pass Values Between ASP.NET Web Pages
How to: Post ASP.NET Web Pages to a Different Page
How to: Determine How ASP.NET Web Pages Were Invoked
Concepts
ASP.NET State Management Overview
ASP.NET

How to: Redirect Users to Another Page


You might want to redirect users from one ASP.NET Web page to another Web page. For example, you might do this as part of
a multi-page form.
There are a number of ways to redirect pages, such as the following:
By configuring the page to post to another page In this scenario, the user clicks a button that you have configured
to post to a different page. This scenario is useful for multi-page forms. However, it requires user interaction. For details,
see Cross-Page Posting in ASP.NET Web Pages.
By dynamically using the browser In this scenario, you send a command to the user's browser that causes the
browser to retrieve a different page. This allows you to programmatically redirect to another page. However, the
redirection causes a new request (an HTTP GET), and any post data from the source page is lost.
By dynamically using a server-side method In this scenario, the server simply transfers the context to another page. The
advantage is that you can share page context information between pages. The disadvantage is that the user's browser does not
know about the transfer, so the browser's history is not updated. If the user refreshes the page, unexpected results can occur.
For details about sharing page context during a server transfer, see How to: Pass Values Between ASP.NET Web Pages.
To redirect a user to another page by using the browser
1. Set the Response object's BufferOutput property to true.
2. Call the Response object's Redirect method, passing it the URL of the page to which you want to redirect users.
The following code example shows how to redirect a page based on the contents of a local variable, UserLanguage, which
is set elsewhere.
VB
Response.BufferOutput = True
If UserLanguage = "English" Then
Response.Redirect("http://www.microsoft.com/gohere/look.htm")
ElseIf UserLanguage = "Deutsch" Then
Response.Redirect("http://www.microsoft.com/gohere/look_deu.htm")
ElseIf UserLanguage = "Español" Then
Response.Redirect("http://www.microsoft.com/gohere/look_esp.htm")
End If

C#
Response.BufferOutput = true;
if (UserLanguage == "English")
{
Response.Redirect("http://www.microsoft.com/gohere/look.htm");
}
else if (UserLanguage == "Deutsch")
{
Response.Redirect("http://www.microsoft.com/gohere/look_deu.htm");
}
else if (UserLanguage == "Español")
{
Response.Redirect("http://www.microsoft.com/gohere/look_esp.htm");
}

To redirect users to another page by using a server-side method


Call the Transfer method, passing it the name of the page to which you want to redirect users.
The following code example shows how to redirect to another page.
VB
Protected Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Server.Transfer("Page2.aspx", True)
End Sub

C#
protected void Button1_Click(object sender, System.EventArgs e)
{
Server.Transfer("Page2.aspx", true);
}

See Also
Tasks
How to: Pass Values Between ASP.NET Web Pages
ASP.NET

Cross-Page Posting in ASP.NET Web Pages


By default, buttons and other controls that cause a postback on an ASP.NET Web page submit the page back to itself. This is
part of the round-trip cycle that ASP.NET Web pages go through as part of their normal processing. For details, see
Introduction to ASP.NET Web Pages.
Under some circumstances, you might want to post one page to another page. For example, you might be creating a multi-
page form that collects different information on each page. In that case, you can configure certain controls (those that
implement the IButtonControl interface, such as the Button control) on the page to post to a different target page. This is
referred to as cross-page posting. Cross-page posting provides some advantages over using the Transfer method to redirect to
another page. For details, see Redirecting Users to Another Page.
Note
You can also use the Wizard control to create multi-view forms. For details, see Wizard Web Server Control Overview.

Because cross-page posting is configured for individual controls, you can create a page that posts to different pages depending
on which button the user clicks.
Getting Information from the Source Page
When you configure a page for cross-page posting, you frequently want to get information from the source page. This might
include the information from controls on the page—that is, the information being posted by the browser—as well as public
properties of the source page.
Getting Control Values
The Page class exposes a property named PreviousPage. If the source page and target page are in the same ASP.NET
application, the PreviousPage property in the target page contains a reference to the source page. (If the page is not the target
of a cross-page posting, or if the pages are in different applications, the PreviousPage property is not initialized.) By default,
the PreviousPage property is typed as Page.
Note
If the source and target page are in different applications, you cannot directly get the values of controls on the page, but you
can read the posted data from the Form dictionary. You cannot read view state from the source page, because it is hashed. If
you want to store values in the source page and make them available in a target page in another application, you can store th
e values as strings inside hidden fields on the source page and access them through Request.Form on the target page.

Using the reference in the PreviousPage property, you can search for controls on the source page and extract their value. You
typically do this with the FindControl method.
Note
If you are coding the source page specifically to be able to share information with target pages, an easier way to make contro
l values available to the target page is to expose them as public properties. For details, see
Getting Public Property Values from the Source Page later in this topic.

The following code example shows how you can get the value of the TextBox1 control on the source page.
VB
If Not Page.PreviousPage Is Nothing Then
Dim SourceTextBox As TextBox
SourceTextBox = CType(PreviousPage.FindControl("TextBox1"), _
TextBox)
If Not SourceTextBox Is Nothing Then
Label1.Text = SourceTextBox.Text
End If
End If

C#
if (Page.PreviousPage != null)
{
TextBox SourceTextBox =
(TextBox)Page.PreviousPage.FindControl("TextBox1");
if (SourceTextBox != null)
{
Label1.Text = SourceTextBox.Text;
}
}

The FindControl method finds controls in the current naming container. If the control you are looking for is inside another
control (typically, inside a template), you must first get a reference to the container and then search the container to find the
control you want to get. In the following code example, the source page contains a Login control with a LayoutTemplate
container that in turn contains a TextBox control named UserName. The code gets the value of the UserName control.
VB
Dim LoginControl As Login
LoginControl = CType(PreviousPage.FindControl("Login1"), Login)
If Not LoginControl Is Nothing Then
Dim UserName As TextBox
UserName = CType(LoginControl.FindControl("UserName"), TextBox)
If Not UserName Is Nothing Then
Label1.Text = UserName.Text
End If
Else
Label1.Text = "Cannot find user name in Login control."
End If

C#
Login LoginControl = (Login)PreviousPage.FindControl("Login1");
if (LoginControl != null)
{
TextBox UserName = (TextBox)LoginControl.FindControl("UserName");
if (UserName != null)
{
Label1.Text = UserName.Text;
}
}
else
{
Label1.Text = "Cannot find user name in Login control.";
}

Getting Public Property Values from the Source Page


In the target page of a cross-page posting, you can also get the values of public members of the source page. The most
common scenario is that the source page defines public properties and you want to get their values on the target page.
Security Note
It is recommended that you expose only the information you need as public properties to reduce the amount of information
available to potentially malicious users.

To get public members of the source page, you must first get a strongly typed reference to the source page.
You can do so in a number of ways. The first is to include an @ PreviousPageType directive in the target page, which allows
you to specify the source page, as in this example:

<%@ PreviousPageType VirtualPath="~/SourcePage.aspx" %>

When this directive is included, the PreviousPage property is strongly typed to the class of the referenced source page. As a
consequence, you can directly reference public members of the source page. You can specify the type of the source page either
directly, using a type attribute, or indirectly by explicitly referencing the source page in a VirtualPath attribute, as shown in
the example.
The following code example shows a portion of a source page containing a public property named CurrentCity that exposes
the value of a TextBox control named textCity.
VB
Public ReadOnly Property CurrentCity() As String
Get
Return textCity.Text
End Get
End Property

C#
public String CurrentCity
{
get
{
return textCity.Text;
}
}

Note
Properties on the source page that are created primarily to expose values for cross-page posting are usually read-only prope
rties. Although the source page can contain public read/write properties, setting a source page property from the target page
property generally has no purpose, because the value will not be persisted.

If the target page contains a PreviousPageType directive that points to the source page, you can access the source page's
CurrentCity property using code such as the following.

VB
Label1.Text = PreviousPage.CurrentCity;

C#
Label1.Text = PreviousPage.CurrentCity;

Another way to get a strongly typed reference to the source page is to include an @ Reference directive in the target page that
references the source page, as you would reference any type that you wanted to use in your page. In that case, in the target
page you can get the target page's PreviousPage property and cast it to the source page type, as in the following code
example.
VB
Dim sourcePage As SourcePage_aspx
sourcePage = CType(PreviousPage, SourcePage_aspx)
Label1.Text = p.CurrentCity

C#
SourcePage_aspx sourcePage;
sourcePage = (SourcePage_aspx) PreviousPage;
Label1.Text = sourcePage.CurrentCity;

Checking for Postbacks in the Target Page


During a cross-page postback, the contents of the source page's controls are posted to the target page, and the browser
executes an HTTP POST operation (not a GET operation). However, in the target page, the IsPostBack property is false
immediately after a cross-page post. Although the behavior is that of a POST, the cross-posting is not a postback to the target
page. Therefore, IsPostBack is set to false and the target page can go through its first-time code.
If it is useful in your application, you can determine whether the target page is running as the result of a cross-page post. To do
so, you can test the IsCrossPagePostBack property of the page reference returned by the target page's PreviousPage
property, as in the following code example.
VB
If PreviousPage IsNot Nothing Then
If PreviousPage.IsCrossPagePostBack = True Then
Label1.Text = "Cross-page post."
End If
Else
Label1.Text = "Not a cross-page post."
End If

C#
if(PreviousPage != null)
{
if(PreviousPage.IsCrossPagePostBack == true)
{
Label1.Text = "Cross-page post.";
}
}
else
{
Label1.Text = "Not a cross-page post.";
}

Note that if the current page is not the target of a cross-page post, the PreviousPage property returns null (Nothing in
Visual Basic).
For more information, see How to: Determine How ASP.NET Web Pages Were Invoked.
Cross-Page Posting versus Server.Transfer
The PreviousPage property and the PreviousPageType directive are useful in two situations where you invoke the target
page: in a cross-page postback, which is a client-based transfer, and with the Transfer method, which is a server-based
operation. In both operations, code in the target page can get a reference to the source page using the PreviousPage
property.
It might be important in the target page to determine whether the page was invoked from a cross-page posting or a
Server.Transfer operation. To help you do this, the Page class exposes a property named IsCrossPagePostBack. For details,
see How to: Determine How ASP.NET Web Pages Were Invoked.
See Also
Tasks
How to: Post ASP.NET Web Pages to a Different Page
How to: Determine How ASP.NET Web Pages Were Invoked
ASP.NET

How to: Post ASP.NET Web Pages to a Different Page


By default, controls on ASP.NET Web pages that cause a postback, such as the Button control, post back to the page for
processing. However, you can configure controls to post to a different page. For example, you might be creating a multi-page
form that collects different information on each page.
On the target page, you can read the values of controls or public properties from the source page. For more information, see
Cross-Page Posting in ASP.NET Web Pages.
To post an ASP.NET Web page to another page
1. Add a button control to your Web page, such as a Button, LinkButton, or ImageButton control.
2. Set the PostBackUrl property for the control to the URL of the page to which you want to post the ASP.NET Web page.
The following code example illustrates a Button control that is configured to post to a page named TargetPage in the
root of the Web site.

<asp:Button
ID="Button1"
PostBackUrl="~/TargetPage.aspx"
runat="server"
Text="Submit" />

For more information, see How to: Pass Values Between ASP.NET Web Pages.
See Also
Tasks
How to: Pass Values Between ASP.NET Web Pages
How to: Determine How ASP.NET Web Pages Were Invoked
Concepts
Cross-Page Posting in ASP.NET Web Pages
ASP.NET

How to: Pass Values Between ASP.NET Web Pages


If your application redirects (navigates) from one ASP.NET Web page to another, you will frequently want to pass information
from the source page to the target page. For example, you might have a page where users can select items to purchase. When
users submit the page, you want to call another page that can process the information that the user has entered.
You can pass information between pages in various ways, some of which depend on how the redirection occurs. Options
include the following:
Use a query string, which appends information onto the URL of the target page. You can use a query string when using a
HyperLink control to build navigation into a page or when you are programmatically redirecting to another page using
the Redirect method.
Passing values in a query string works even if the pages are not in the same Web application; it also works if you want to
pass information to a page that is not an ASP.NET Web page. If the target page is an ASP.NET Web page, you can read the
value of the query string out of the QueryString property of the HttpRequest object.
Note
Never pass sensitive data using a query string, because the information is visible to users and can easily be modified, t
hus representing a potential security risk.

Use session state to store information that is then accessible to all ASP.NET Web pages in the current application.
However, this takes server memory, and the information is stored until the session expires, which can be more overhead
than you want for simply passing information to the next page. For details, see ASP.NET State Management Overview.
On the target page, read control values and public property values directly out of the source page. This strategy works in
two situations: when the source page cross-posts to the target page (for more information, see
How to: Post ASP.NET Web Pages to a Different Page), and when you call the Transfer method to transfer execution from
the source to the target page on the server. The strategy of reading values directly from the source page is described in
this topic.
Getting Public Property Values from the Source Page
If you are designing the source page specifically for sharing information with target pages, and both pages are ASP.NET Web
pages, in the source page you can add public properties that expose information you want to share between pages. You can
then read the values of the properties in the target pages.
Note
You can read source page properties in the target page only if both pages are in the same Web application.

To get public property values from the source page


1. On the source page, create one or more public properties.
The following code example shows a property named CurrentCity that exposes the value of a TextBox control named
textCity.

VB
Public ReadOnly Property CurrentCity() As String
Get
Return textCity.Text
End Get
End Property

C#
public String CurrentCity
{
get
{
return textCity.Text;
}
}

Note
Properties on the source page that are created primarily to expose values for cross-page posting are usually read-only
properties. Although the source page can contain public read/write properties, setting a source page property from the
target page property generally has no purpose, because the value will not be persisted.

2. On the target page, add an @ PreviousPageType page directive that points to the source page.
The following code example shows a PreviousPageType directive that references a source page named
SourcePage.aspx.

<%@ PreviousPageType VirtualPath="~/SourcePage.aspx" %>

The PreviousPageType directive causes the page's PreviousPage property to be typed to the source page class.
3. In target page code, use strongly typed members of the PreviousPage property to read the source code properties.
The following code example reads the value of the CurrentCity property that is defined in the source page.
VB
Label1.Text = PreviousPage.CurrentCity

C#
Label1.Text = PreviousPage.CurrentCity;

Getting Control Information from the Source Page in the Same Application
If the source and target pages are both ASP.NET Web pages and in the same Web application, you can read the values of
controls on the source page while in the target page. You might use this strategy if the source page does not expose public
properties containing the information you need.
To get the values of controls from the source page in the same application
On the target page, get a reference to the source page by using the target page's PreviousPage property, and then call
the FindControl method to get a reference to the control you want.
The following code example gets the value of the source page's TextBox1 control and displays it in the control named
Label1:

VB
If Not Page.PreviousPage Is Nothing Then
Dim SourceTextBox As TextBox
SourceTextBox = CType(PreviousPage.FindControl("TextBox1"), _
TextBox)
If Not SourceTextBox Is Nothing Then
Label1.Text = SourceTextBox.Text
End If
End If

C#
if (Page.PreviousPage != null)
{
TextBox SourceTextBox =
(TextBox)Page.PreviousPage.FindControl("TextBox1");
if (SourceTextBox != null)
{
Label1.Text = SourceTextBox.Text;
}
}

Note
The FindControl method finds controls in the current naming container. If the control you are looking for is inside ano
ther control (typically, inside a template), you must first get a reference to the container, and then search the container t
o find the control that you want to get.

Getting Post Information from the Source Page in Another Application


If the source and target pages are not in the same Web application, you can read the posted values of the source page in the
target page. This technique also works if the target page is an ASP.NET Web page but the source page is not. Note that you can
get only the post values; you cannot read the values of arbitrary controls on the page.
To get the values of controls from the source page in another application
On the target page, read the Form collection, which returns a dictionary of name/value pairs, one pair for each posted
value.
The following code example displays the ID and value of every posted control in the source page and displays the posted
values in a label named Label1.
Note
Post information from an ASP.NET Web pages includes the values of hidden fields, such as __VIEWSTATE, __EVENTTA
RGET, and __EVENTARGUMENT, which are used for internal processing in the page. The following code example exclu
des the values of posted fields that are named with a leading double underscore (__).

VB
Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles Me.Load
Dim displayValues As New StringBuilder()
Dim postedValues As NameValueCollection = Request.Form
Dim nextKey As String
For i As Integer = 0 To postedValues.AllKeys.Length - 1
nextKey = postedValues.AllKeys(i)
If nextKey.Substring(0, 2) <> "__" Then
displayValues.Append("<br>")
displayValues.Append(nextKey)
displayValues.Append(" = ")
displayValues.Append(postedValues(i))
End If
Next
Label1.Text = displayValues.ToString()
End Sub

C#
void Page_Load(object sender, EventArgs e)
{
System.Text.StringBuilder displayValues =
new System.Text.StringBuilder();
System.Collections.Specialized.NameValueCollection
postedValues = Request.Form;
String nextKey;
for(int i = 0; i < postedValues.AllKeys.Length - 1; i++)
{
nextKey = postedValues.AllKeys[i];
if(nextKey.Substring(0, 2) != "__")
{
displayValues.Append("<br>");
displayValues.Append(nextKey);
displayValues.Append(" = ");
displayValues.Append(postedValues[i]);
}
}
Label1.Text = displayValues.ToString();
}

See Also
Tasks
How to: Determine How ASP.NET Web Pages Were Invoked
Concepts
Cross-Page Posting in ASP.NET Web Pages
ASP.NET State Management Overview
ASP.NET

How to: Determine How ASP.NET Web Pages Were Invoked


It is often useful to know how an ASP.NET Web page was invoked: whether by an original request (an HTTP GET), a postback
(an HTTP POST), a cross-page post from another page (an HTTP POST), or a transfer from another page using the Transfer
method or using a callback from the browser. The Page class exposes a set of properties that you can use to determine how a
page was invoked.
To determine how an ASP.NET Web page was invoked
Examine the values of the following Page class properties, and then refer the table to determine how the page was
invoked:
IsPostBack
PreviousPage
IsCrossPagePostBack
IsCallback
The following table lists ways in which a page can be invoked and the corresponding Page property values.
Invocation method Property values
Original request IsPostBack is set to false.
PreviousPage is set to null (Nothing in Visual Basic).
IsCallback is set to false.

Postback IsPostBack is set to true.


PreviousPage is set to null (Nothing in Visual Basic).
IsCallback is set to false.

Cross-page posting IsPostBack is set to false.


PreviousPage references the source page.
IsCrossPagePostBack is set to true.
IsCallback is set to false.

Server transfer IsPostBack is set to false.


PreviousPage references the source page.
IsCrossPagePostBack that is referenced in the PreviousPage is set to false.
IsCallback is set to false.

Callback IsPostBack is set to false.


PreviousPage is set to null (Nothing in Visual Basic).
IsCallback is set to true.
Note
Be sure you test the IsCrossPagePostBack property of the page that is referenced in PreviousPage. The IsCrossPage
PostBack property of the current page always returns false.

See Also
Concepts
Cross-Page Posting in ASP.NET Web Pages
Implementing Client Callbacks Without Postbacks in ASP.NET Web Pages
ASP.NET

How to: Detect Browser Types in ASP.NET Web Pages


Different browsers and different versions of the same browsers support different features. In your application, you might need
to determine what type of browser a user is viewing pages with, and perhaps determine if the browser supports certain
features.
Note
ASP.NET can automatically determine browser capabilities and use this information to render appropriate HTML markup for
ASP.NET server controls. For details, see ASP.NET Server Controls and Browser Capabilities.

To detect browser types in an ASP.NET page


Query the Browser property, which contains an HttpBrowserCapabilities object. This object gets information from the
browser or client device during an HTTP request, telling your application the type and level of support the browser or
client device offers. The object in turn exposes information about browser capabilities using strongly typed properties
and a generic name-value dictionary.
The following code example shows how you can displays browser information the information in a text box on the page.
Note
The properties exposed by the HttpBrowserCapabilities object indicate inherent capabilities of the browser, but do n
ot necessarily reflect current browser settings. For example, the Cookies property indicates whether a browser inherent
ly supports cookies, but it does not indicate whether the browser that made the request has cookies enabled. For more
information, see ASP.NET Cookies Overview.

VB
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim s As String = ""
With Request.Browser
s &= "Browser Capabilities" & vbCrLf
s &= "Type = " & .Type & vbCrLf
s &= "Name = " & .Browser & vbCrLf
s &= "Version = " & .Version & vbCrLf
s &= "Major Version = " & .MajorVersion & vbCrLf
s &= "Minor Version = " & .MinorVersion & vbCrLf
s &= "Platform = " & .Platform & vbCrLf
s &= "Is Beta = " & .Beta & vbCrLf
s &= "Is Crawler = " & .Crawler & vbCrLf
s &= "Is AOL = " & .AOL & vbCrLf
s &= "Is Win16 = " & .Win16 & vbCrLf
s &= "Is Win32 = " & .Win32 & vbCrLf
s &= "Supports Frames = " & .Frames & vbCrLf
s &= "Supports Tables = " & .Tables & vbCrLf
s &= "Supports Cookies = " & .Cookies & vbCrLf
s &= "Supports VBScript = " & .VBScript & vbCrLf
s &= "Supports JavaScript = " & _
.EcmaScriptVersion.ToString() & vbCrLf
s &= "Supports Java Applets = " & .JavaApplets & vbCrLf
s &= "Supports ActiveX Controls = " & .ActiveXControls & _
vbCrLf
End With
TextBox1.Text = s
End Sub
C#
private void Button1_Click(object sender, System.EventArgs e)
{
System.Web.HttpBrowserCapabilities browser = Request.Browser;
string s = "Browser Capabilities\n"
+ "Type = " + browser.Type + "\n"
+ "Name = " + browser.Browser + "\n"
+ "Version = " + browser.Version + "\n"
+ "Major Version = " + browser.MajorVersion + "\n"
+ "Minor Version = " + browser.MinorVersion + "\n"
+ "Platform = " + browser.Platform + "\n"
+ "Is Beta = " + browser.Beta + "\n"
+ "Is Crawler = " + browser.Crawler + "\n"
+ "Is AOL = " + browser.AOL + "\n"
+ "Is Win16 = " + browser.Win16 + "\n"
+ "Is Win32 = " + browser.Win32 + "\n"
+ "Supports Frames = " + browser.Frames + "\n"
+ "Supports Tables = " + browser.Tables + "\n"
+ "Supports Cookies = " + browser.Cookies + "\n"
+ "Supports VBScript = " + browser.VBScript + "\n"
+ "Supports JavaScript = " +
browser.EcmaScriptVersion.ToString() + "\n"
+ "Supports Java Applets = " + browser.JavaApplets + "\n"
+ "Supports ActiveX Controls = " + browser.ActiveXControls
+ "\n";
TextBox1.Text = s;
}

See Also
Concepts
ASP.NET Web Server Controls and Browser Capabilities
ASP.NET

Embedded Code Blocks in ASP.NET Web Pages


The default model for adding code to an ASP.NET Web page is to either create a code-behind class file (a code-behind page) or
to write the page's code in a script block with the attribute runat="server" (a single-file page). The code you write typically
interacts with controls on the page. For example, you can display information on the page from code by setting the Text (or
other) properties of controls.
Another possibility is to embed code directly into the page using an embedded code block.
Embedded Code Blocks
An embedded code block is server code that executes during the page's render phase. The code in the block can execute
programming statements and call functions in the current page class.
The following code example shows an ASP.NET page with an embedded code block that displays the results of a loop.
VB
<%@ Page Language="VB" %>
<html>
<body>
<form id="form1" runat="server">
<% For i As Integer = 0 To 5 %>
<% Response.Write("<br>" & i.ToString())%>
<% Next%>
</form>
</body>
</html>

C#
<%@ Page Language="C#" %>
<html>
<body>
<form id="form1" runat="server">
<% for(int i = 0; i < 6; i++) %>
<% { Response.Write("<br>" + i.ToString()); }%>
</form>
</body>
</html>

The following code example shows an embedded code block that displays the value of a public GetTime() function inside a
span element. In embedded code blocks, the syntax <% = expression %> is used to resolve an expression and return its value
into the block.
VB
<%@ Page Language="VB" %>
<script runat=server>
Protected Function GetTime() As String
Return DateTime.Now.ToString("t")
End Function
</script>
<html>
<body>
<form id="form1" runat="server">
Current server time is <% =GetTime()%>.
</form>
</body>
</html>

C#
<%@ Page Language="C#" %>
<script runat=server>
protected String GetTime()
{
return DateTime.Now.ToString("t");
}
</script>
<html>
<body>
<form id="form1" runat="server">
Current server time is <% =GetTime()%>.
</form>
</body>
</html>

Embedded code blocks must be written in the page's default language. For example, if the page's @ Page directive contains the
attribute language="VB", the page will use the Visual Basic compiler to compile code in any script block marked with
runat="server" and any in-line code in <% %> delimiters.

Uses for Embedded Code Blocks


Embedded code blocks are supported in ASP.NET Web pages primarily to preserve backward compatibility with older ASP
technology. In general, using embedded code blocks for complex programming logic is not a best practice, because when the
code is mixed on the page with markup, it can be difficult to debug and maintain. In addition, because the code is executed only
during the page's render phase, you have substantially less flexibility than with code-behind or script-block code in scoping
your code to the appropriate stage of page processing.
Some uses for embedded code blocks include:
Setting the value of a control or markup element to a value returned by a function, as illustrated in the preceding
example.
Embedding a calculation directly into the markup or control property.

See Also
Concepts
ASP.NET Web Page Code Model
ASP.NET Web Page Syntax Overview
ASP.NET

Programming ASP.NET Web Pages with Client Script


You can include client side script in your ASP.NET Web page for operations that manipulate the look of the page and require
quick response time. This section presents topics discussing client side script and how to add it to your ASP.NET Web pages.
In This Section
Client Script in ASP.NET Web Pages
ASP.NET Web Server Controls that Use Client Script
How to: Add Client Script Events to ASP.NET Web Server Controls
How to: Add Client Script Dynamically to ASP.NET Web Pages
Implementing Client Callbacks Without Postbacks in ASP.NET Web Pages
Related Sections
Programming ASP.NET Web Pages
Provides links to topics about programming ASP.NET Web pages.
ASP.NET

Client Script in ASP.NET Web Pages


ASP.NET is a server-based technology, and therefore does not directly interact with the browser. For example, there are no
ASP.NET methods to get keyboard input from the browser, respond to mouse events, or perform other tasks that involve user
interaction with the browser. ASP.NET can get the results of such actions after the page has been posted, but cannot directly
respond to browser actions.
These types of browser-interaction tasks are best handled using client script written in ECMAScript (JavaScript or JScript).
Client script running in the browser can respond immediately to user actions. For example, using client script, you can create
"rollover" effects to change a button or a menu item as the user passes the mouse pointer over it. Similarly, you can use client
script to check keyboard entry in a text box character by character, change the appearance of the page dynamically, or perform
any other task that is primarily oriented to the user interface (UI) and that requires immediate response.
ASP.NET Server Controls and Client Script
A few ASP.NET server controls depend on client script for their functionality. For example, the LinkButton control requires client
script to support its postback behavior. The client script required for ASP.NET Web server controls is added automatically to the
page when the page is rendered. The client script generated for these controls is independent of any client script that you
create yourself.
For more information, see ASP.NET Web Server Controls that Use Client Script.
Including Your Own Client Script in ASP.NET Pages
Because ASP.NET Web pages are ultimately just Web pages, you can add your own client script to ASP.NET pages. Client script
is supported in ASP.NET pages to the extent that the browser requesting the page supports client script. For example, if your
ASP.NET Web page is running in Microsoft Internet Explorer or Mozilla, you can add client script to a page that uses dynamic
HTML to manipulate any element on the page. If the page is running in a browser on a mobile phone or other device, the
degree of support for client script varies, depending on the browser.
Your pages can include client script in the same way that any HTML (or other markup) pages can. You can add script blocks to
the page to manipulate elements in the page, just as you would for any HTML page. You can use client script to write event
handlers for client events such as the page's onload event. When an ASP.NET page is running in the browser, the markup
elements on the page are addressable in client script and raise all the client-side events that they would in an HTML page.
Working with client script in ASP.NET Web pages differs from working in an HTML page in these areas:
Adding client script event handling to ASP.NET server controls.
Referencing server controls from client script.
Adding client script to the page dynamically.
Raising client click events for server controls.
Sharing information between client script and server code.
Calling server code from client script without postback.
Adding Client Script Events to ASP.NET Server Controls
ASP.NET controls render as elements in the page (the exact elements rendered by a control depends on the markup language
for the page, whether HTML, XHTML, or another language). You can therefore add client-script event handling to controls as
you would with any elements on the page. In some cases, however, you must be aware of how the control renders its output
and what attributes the control reserves for itself.
Adding Client Event Handlers Declaratively
In the markup for ASP.NET server controls, you set property values by using attributes. For example, to set the Text property of
a TextBox control, you can create markup like this:

<asp:textbox id="TextBox1" runat="server" text="Sample Text" />

If you include an attribute that does not map to a property of the control, ASP.NET ignores the attribute during server
processing and passes it as-is on the markup generated by the control to the browser. For example, the TextBox control has
no property named onkeyup. Therefore, if you include an onkeyup attribute in the markup for a TextBox control, the
attribute will be passed through to the browser. This behavior allows you to add event bindings to server controls by declaring
them in the markup. For example, the following markup for a TextBox control causes the text box to display the current text
length in a span element named spanCounter any time the user presses a key in the text box:
Security Note
A TextBox accepts user input, which is a potential security threat. By default, ASP.NET Web pages validate that user input do
es not include script or HTML elements. For more information, see Script Exploits Overview.

<asp:textbox id="TextBox1" runat="server" text="Sample Text" onkeyup="spanCounter.innerText


=this.value.length;" />

Alternatively, the event could call a method defined in client script elsewhere in the page:

<asp:textbox id="TextBox1" runat="server" text="Sample Text" onkeyup="DisplayCount(this);"


/>

Note that the language you use for server code (Visual Basic or C#) has no effect on client script, which is always written in
ECMAScript.
For details, see How to: Add Client Script Events to ASP.NET Web Server Controls.
Adding Attributes in Server Code
In addition to adding pass-through attributes to a control declaratively, you can add attributes programmatically using server
code. This is useful if the value of the attribute to add is dynamic. For details, see
How to: Set HTML Attributes for Controls in ASP.NET Web Pages.
Identifying Server Controls in Client Script
When an ASP.NET server control is rendered, the control's ClientID property is rendered to the page as both the id attribute
and the name attribute of the resulting element. (The ClientID property is automatically generated from the ID property that
you set.) For example, you might create the following ASP.NET server control:
Security Note
A TextBox accepts user input, which is a potential security threat. By default, ASP.NET Web pages validate that user input do
es not include script or HTML elements. For more information, see Script Exploits Overview.

<asp:textbox id="TextBox1" runat="server" text="Sample Text" />

The ClientID property is set to TextBox1, and the resulting element in an HTML-based browser would look like the following:

<input name="TextBox1" type="text" value="Sample Text" id="TextBox1" />

Note
The form element renders only an ID attribute, not a name attribute.

You can therefore reference the server control in client script using these attributes. You must typically address the control
using a fully qualified reference in client script; if the control is a child of the form element in the page, you generally reference
the control in client script using syntax as shown in the following code example.

document.forms[0].TextBox1.value = "New value";

The second example assumes that the form element on the page has had its id attribute set to form1.
The exact syntax required to reference a server control depends on what control you are using and whether it is a child of
another control. If you are not sure how to reference a control, it can be helpful to run the page, view its source, and determine
how the control has been rendered.
Referencing Controls Rendered Inside Other Controls
Some controls render child controls into the page. This includes data list controls such as the GridView, DetailsView, FormView,
DataList and Repeater controls, as well as user controls and Web Parts controls.
In these cases, the child controls might not have unique IDs, either because the child controls are defined in a template that
generates new control instances for every data row (data list controls), or because the parent control can be added to the page
from an external source (user controls and Web Parts controls). These parent controls are therefore naming containers (that is,
they implement INamingContainer). A naming container guarantees that its child controls have unique IDs on the page.
For example, you might create an ItemTemplate property in the DataList control and add a CheckBox control whose ID you set
to checkEnabled. When the DataList control is rendered, a new checkEnabled control is rendered for each data item. The
rendered page must not contain multiple instances of an element named checkEnabled, so the DataList control creates a
unique identity for each of its child controls.
Unique identities for child controls of a naming container are generated by rendering two properties. For each child control:
The control's UniqueID property is rendered as the name attribute.
The control's ClientID property is rendered as the id attribute.
Both the ClientID and UniqueID properties are based on the original ID property, amended with enough information to
guarantee that the result is unique in the page. The value of ClientID—that is, of the id attribute in the rendered element—can
be referenced in client script.
If you display a page with a naming container in your browser, you can view the page's source to see the unique IDs generated
as the name and id attributes for the naming container's child controls. However, it is recommended that you do not rely on
directly referencing the IDs as you see them in the browser. The formula used to generate unique IDs for child controls can
change. Instead, get the value of the child control's ClientID property and use that value to reference the child control. For
example, you might create client script dynamically in your page. If your client script references a child control, get the child
control's ClientID property and build it into your dynamic script.
Adding Client Script to a Page Dynamically
In many cases, you can create the client script for your page declaratively, usually as a script block. However, at times you
might want to create client script dynamically. This is useful if the script, or values in it, depends on information that is available
only on the server. For example, you might inject client script into a page that addresses a server control whose name (ID) is
not known until the application runs.
You can also inject a client script include statement that references a file. This is useful if you keep your client script in .js files
rather than in the pages themselves, and can be particularly useful if your application is being used with browsers that do not
allow script directly.
You can inject client script or a client script include statement into a page by calling methods of the ClientScriptManager class,
such as RegisterClientScriptBlock and RegisterStartupScript. For details, see
How to: Add Client Script Dynamically to ASP.NET Web Pages.
For all the methods, you provide a type with which the script block is associated and you give the script block a key. Providing
a type helps avoid collisions if both a page and any controls (custom controls or user controls) add script blocks into the same
page. Using a key helps avoid duplication; if you call one of the methods to add script, and a script with the same key and the
same type already exists, the script is not added again.
The type and key you provide help avoid unnecessary duplication, so you generally do not need to determine explicitly
whether a script block already exists. However, if it is useful in your application to check for an existing script block, you can call
the following methods:
IsClientScriptBlockRegistered
IsClientScriptIncludeRegistered
IsOnSubmitStatementRegistered
IsStartupScriptRegistered

Raising Client Click Events for Server Controls


As noted earlier in this topic, you can add a client click event to most ASP.NET server controls by adding the onclick attribute
to the control's markup. However, some controls reserve the onclick attribute to define binding to the server event. These
include the Button, LinkButton, and ImageButton controls. In these controls, you cannot use the onclick attribute declaratively
to add a client-script handler to the control.
You can add a client-script handler for the click event in two ways:
Set the control's OnClientClick property to the script to execute. When the button control renders, the OnClientClick
value is turned into an onclick attribute.
Add an onclick attribute programmatically by calling the Add method of the control's Attributes collection.
The following code example shows a Button control that raises both client-side and server Click events:

<asp:button id="Button1" runat="server" OnClientClick="return confirm('Ok to post?')" oncli


ck="Button1_Click" Text="Click!" />

Sharing Information Between Client Script and Server Code


As a rule, client script and server code cannot directly communicate. For example, a client script function cannot pass a value
directly to server code during a postback event.
Note
Client script can call server code directly if you implement client callbacks. For details, see
Implementing Client Callbacks Without Postbacks in ASP.NET Web Pages.

However, you can have client script and server code interact indirectly. One way is to add a HiddenField control to the page.
You can then reference the hidden field in client script by its ID, and also in server code, storing values in either code block and
reading them in the other. To pass information from server code to client script, you can create a hidden field
programmatically using the RegisterHiddenField method. This method allows you to specify an ID and value for the field,
which allows you to store dynamic values in the page in a way that client script can read them.
You can also share values between server code and client code using cookies. For details about writing and reading cookies in
server code, see How to: Write a Cookie and How to: Read a Cookie.
Calling Server Code from Client Script Without Postback
In the usual sequence for ASP.NET Web pages, each user action that runs server code requires a postback. However, you can
also write code that implements a client callback. In this scenario, client script sends a request to the server to execute a page
without performing a complete postback cycle. The page can run a method and return the results of the method to a client
function in the browser. A client callback is useful when you want to retain client state such as local variables while getting
information from the server.
For details, see Implementing Client Callbacks Without Postbacks in ASP.NET Web Pages.
See Also
Concepts
ASP.NET Web Server Controls and Browser Capabilities
ASP.NET Web Server Control Event Model
ASP.NET

ASP.NET Web Server Controls that Use Client Script


Some ASP.NET server controls depend on client script for their functionality. In addition, some functionality of ASP.NET pages
relies on client script. It is useful to know how ASP.NET controls and pages use client script so that you understand how your
Web pages might be affected by differences in how browsers support client script.
Element List
The following table lists controls or control properties that take advantage of client script and what functionality is provided by
client script.
Control Client script functionality
Page, HtmlForm, Panel The following properties require client script:
DefaultFocus
DefaultButton
MaintainScrollPositionOnPostback

LinkButton, ImageButton, and Client script is used to support postback events.


HtmlButton
Note
This does not include either the Button
Web server control or the
HtmlInputButton and HtmlInputImage
controls, which do not require client sc
ript.

Calendar This control uses LinkButton controls to implement day, week, and month navigation;
the LinkButton control uses client script for postback events. If you use the Calendar
control simply to display a single month with no selection or navigation, the control do
es not require client script.

DetailsView If the control includes buttons configured as LinkButton controls (for editing, paging,
and so on), those functions require client script.
Client script can be used to paginate if the associated data source control supports this
functionality.
If the EnablePagingCallbacks property is true, client script is used to manage the callba
ck.

GridView If the control includes buttons configured as LinkButton controls (for editing, paging,
and so on), those functions require client script.
Client script can be used to sort and paginate if the associated data source control sup
ports this functionality.
If the EnableSortingAndPagingCallbacks property is true, client script is used to manag
e the callback.

Label The AssociatedControlID property, in conjunction with the AccessKey property, generat
es client script to set the focus on the appropriate control in response to a keyboard sh
ortcut. If these properties are not set, client script is not required for this control.

Menu Client script is used to open and close menu items, display pop-out panels, and control
the display when users position the mouse pointer over menu items.
TreeView Client script is used to open and close nodes. It is also used when the TreeView contro
l is configured to populate nodes on demand.
Client script can be disabled for the TreeView control, in which case the selection beha
vior is performed in server code after a postback. However, the nodes themselves are r
endered as links that use client script to perform a postback, so if the browser does not
support client script, the TreeView cannot perform a postback.

Any Web server control with its The AutoPostBack property behavior for non-button controls is implemented using cl
AutoPostBack property set to true. ient script.

Web Parts controls Client script is used to support drag-and-drop behavior, adding Web Parts controls to
zones, verbs, and import and export functionality.

Validator controls: Client script is used to provide immediate validation feedback. If the client does not su
pport script, validation will run on the server only.
CompareValidator
CustomValidator
RangeValidator
RegularExpressionValidator
RequiredFieldValidator
ValidationSummary

Any methods or properties that set foc Client script is used to set focus on the specified control.
us on controls, such as the Focus meth
od on controls and the page's
SetFocus method.

The client script required for these controls and members is automatically generated and sent as part of the page. It is
compatible with all types of browsers that support ECMAScript (JScript, JavaScript) — that is, it does not depend on the
advanced scripting capabilities of dynamic HTML (DHTML). An exception is the Web Parts control set, which requires Microsoft
Internet Explorer version 5.5 or later to implement full capabilities.
Note
Some validation features can take advantage of DHTML if it is available in the browser, but DHMTL is not required.

Users sometimes disable script in a browser as a security measure. If they have done so, the functionality provided by client
script is lost. This disables some controls, such as the LinkButton control, entirely, and disables the functionality of the
AutoPostBack property. Validation is only partially affected; validation is still performed on the server, but users do not get
the immediacy and performance of client-side validation.
See Also
Concepts
Client Script in ASP.NET Web Pages
Tab Order, Focus, and Access Keys in ASP.NET Web Server Controls
Visual Web Developer

DefaultClientScript Property
The DefaultClientScript property of an HTML document sets the default scripting language used by client-side <SCRIPT>
elements.
You can set the DefaultClientScript property from either the Properties window or the DOCUMENT Property Pages dialog
box. For more information, see How to: Set the DefaultClientScript Property of a Web Page.
Changing the DefaultClientScript property of a page adds a <meta> element to the <head> element that specifies the
default scripting language. The element looks like the following:
<meta content="text/JScript" http-equiv="content-script-type" />

or:
<meta content="text/VBScript" http-equiv="content-script-type" />

You also can specify the scripting language of a particular HTML script block by defining the type (for Web browsers that
support HTML 4.0 and later) and language (for older HTML 3.2 browsers) attributes of the <SCRIPT> element:

<SCRIPT TYPE="text/VBScript" LANGUAGE="VBScript">

See Also
Tasks
How to: Create Scripts and Edit Event Handlers
Reference
Properties Window
Visual Web Developer

How to: Set the DefaultClientScript Property of a Web Page


The DefaultClientScript property of an HTML document sets the default scripting language that is used by its client-side
Script elements. Setting the DefaultClientScript property in Visual Studio version 2005 inserts a <meta
content="vs_DefaultClientScript"> tag into the head element of the active HTML document, as shown in the following
code example.

<meta content="text/VBScript" http-equiv="content-script-type" />


<meta content="text/JScript" http-equiv="content-script-type" />

For more information, see DefaultClientScript Property.


To set the DefaultClientScript property in the Properties window
1. Open the page for which you want to set the DefaultClientScript property.
2. In the drop-down list at the top of the Properties window, select DOCUMENT.
3. In the Document section of the Properties window, click the DefaultClientScript property, and then select the
scripting language that you want to use for client event handlers.
See Also
Other Resources
Programming ASP.NET Web Pages with Client Script
ASP.NET

How to: Add Client Script Events to ASP.NET Web Server


Controls
You can add client script to controls on an ASP.NET Web page declaratively, as you would to HTML elements. Alternatively, you
can add client script events to an ASP.NET Web server control programmatically, which is useful if the event or the code relies
on information that is available only at run time.
Note
You can reference controls by ID in client script. For more information, see Client Script in ASP.NET Web Pages.

Adding a client script onclick event to buttons requires a special procedure, which is provided later in this topic.
Note
Support for client script depends on the browser. For example, Internet Explorer, Mozilla, and browsers for mobile devices mi
ght provide different types of support for client script.

To add a client event handler to an ASP.NET server control declaratively


In the control's markup, add an attribute for the event, for example, onmouseover or onkeyup. For the attribute's value,
add the client script that you want to execute.
Note
Always add a semicolon (;) after the client script in the attribute. This is required so that if ASP.NET generates client scri
pt for the control (for example, if the control's AutoPostBack property is set to true), your code will run first.

Any attribute/value pairs in the control's markup that do not correspond to control properties are passed through to the
browser as is.
The following code example shows an ASP.NET Web page that includes client script that changes the button text color
when the user passes the mouse over it.
VB
<%@ Page Language="VB"%>
<html>
<head runat="server">
<title>Untitled Page</title>
<script type="text/javascript">
var previousColor;
function MakeRed()
{
previousColor = window.event.srcElement.style.color;
window.event.srcElement.style.color = "#FF0000";
}
function RestoreColor()
{
window.event.srcElement.style.color = previousColor;
}
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:button id="Button1" runat="server"
text="Button1"
onmouseover="MakeRed();"
onmouseout="RestoreColor();" />
</form>
</body>
</html>

C#
<%@ Page Language="C#" %>
<html>
<head runat="server">
<title>Untitled Page</title>
<script type="text/javascript">
var previousColor;
function MakeRed()
{
previousColor = window.event.srcElement.style.color;
window.event.srcElement.style.color = "#FF0000";
}
function RestoreColor()
{
window.event.srcElement.style.color = previousColor;
}
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:button id="Button1" runat="server"
text="Button1"
onmouseover="MakeRed();"
onmouseout="RestoreColor();" />
</form>
</body>
</html>

To add a client event handler to an ASP.NET control programmatically


In the page's Init or Load event, call the Add method of the control's Attributes collection.
The following code example shows how to add client script to a TextBox control. The client script displays the length of
the text in the TextBox control. The script assumes that the page contains a span element named spanCounter.
VB
Protected Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs)
Dim displayControlName As String = "spanCounter"
TextBox1.Attributes.Add("onkeyup", _
displayControlName & ".innerText=this.value.length;")
End Sub

C#
protected void Page_Load(object sender, EventArgs e)
{
String displayControlName = "spanCounter";
TextBox1.Attributes.Add("onkeyup", displayControlName +
".innerText=this.value.length;");
}

To add a client onclick event to a button control


In the button control (Button, LinkButton, and ImageButton controls), set the OnClientClick property to the client script
to execute.
The following code example shows how to add a client script click event to a Button control.
VB
<%@ Page Language="VB" %>
<script runat="server">
Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs)
Label1.Text = "Server click handler called."
End Sub
</script>

<body>
<form id="form1" runat="server">
<asp:Button ID="Button1" Runat="server"
OnClick="Button1_Click"
OnClientClick="return confirm('Ready to submit.')"
Text="Test Client Click" />
<br />
<asp:Label ID="Label1" Runat="server" text="" />
</form>
</body>
</html>

C#
<%@ Page Language="C#" %>
<script runat="server">
protected void Button1_Click(Object sender, EventArgs e)
{
Label1.Text = "Server click handler called.";
}
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >


<body>
<form id="form1" runat="server">
<asp:Button ID="Button1" Runat="server"
OnClick="Button1_Click"
OnClientClick="return confirm('Ready to submit.')"
Text="Test Client Click" />
<br />
<asp:Label ID="Label1" Runat="server" text="" />
</form>
</body>
</html>

Security
Client script can perform potentially malicious functions on the client computer. Be extremely careful about the script that you
write into a page, especially if the script is generated or altered in response to user input. For more information, see
Script Exploits Overview.
See Also
Tasks
How to: Set HTML Attributes for Controls in ASP.NET Web Pages
How to: Add Client Script Dynamically to ASP.NET Web Pages
Concepts
Client Script in ASP.NET Web Pages
ASP.NET

How to: Add Client Script Dynamically to ASP.NET Web Pages


Using server code, you can add client script to a page. Creating client script in server code is useful when the contents of the
client script depend on information that is not available until run time. Adding client script to the page dynamically is also
useful when you want the client script to execute in the following situations:
When the page has finished loading
When users submit the page
Note
You can also add client events, such as onmouseover and onkeyup, to individual controls. For details, see
How to: Add Client Script Events to ASP.NET Web Server Controls.

To add client script to an ASP.NET Web page dynamically


In server code, call one of the methods listed in the following table.
Method Description
RegisterClientScriptBlock Adds a script block to the top of the page. You create the script as a string, and then pass it
to the method, which adds it to the page. You can use this method to insert any script into t
he page. Note that the script might be rendered into the page before all the elements are fi
nished; therefore, you might not be able to reference all the elements on the page from the
script.

RegisterClientScriptInclude Similar to the RegisterClientScriptBlock method, but adds a script block that references a
n external .js file. The include file is added before any other dynamically added script; theref
ore, you might not be able to reference some elements on the page.

RegisterStartupScript Adds a script block into the page that executes when the page finishes loading but before t
he page's onload event is raised. The script is typically not created as an event handler or f
unction; it generally includes only the statements you want to execute once.

RegisterOnSubmitStatement Adds script that executes in response to the page's onsubmit event. The script is executed
before the page is submitted, and gives you an opportunity to cancel the submission.

The following code example shows how to add client script to a page that executes when the user clicks a button that
posts the page back to the server. The client script displays a pop-up window requesting the user to confirm the
postback.
VB
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs)
Dim scriptText As String
scriptText = "return confirm('Do you want to submit the page?')"
ClientScript.RegisterOnSubmitStatement(Me.GetType(), _
"ConfirmSubmit", scriptText)
End Sub

C#
protected void Page_Load(Object sender, EventArgs e)
{
String scriptText =
"return confirm('Do you want to submit the page?')";
ClientScript.RegisterOnSubmitStatement(this.GetType(),
"ConfirmSubmit", scriptText);
}

See Also
Tasks
How to: Add Client Script Events to ASP.NET Web Server Controls
Concepts
Client Script in ASP.NET Web Pages
Implementing Client Callbacks Without Postbacks in ASP.NET Web Pages
ASP.NET

Implementing Client Callbacks Without Postbacks in ASP.NET


Web Pages
In the default model for ASP.NET Web pages, the user interacts with a page and clicks a button or performs some other action
that results in a postback. The page and its controls are re-created, the page code runs on the server, and a new version of the
page is rendered to the browser. However, in some situations, it is useful to run server code from the client without performing
a postback. If the client script in the page is maintaining some state information (for example, local variable values), posting the
page and getting a new copy of it destroys that state. Additionally, page postbacks introduce processing overhead that can
decrease performance and force the user to wait for the page to be processed and re-created.
To avoid losing client state and not incur the processing overhead of a server roundtrip, you can code an ASP.NET Web page so
that it can perform client callbacks. In a client callback, a client script function sends a request to an ASP.NET Web page. The
Web page runs a modified version of its normal life cycle — the page is initiated and its controls and other members are
created, and then a specially marked method is invoked. The method performs the processing that you have coded and then
returns a value to the browser that can be read by another client script function. Throughout this process, the page is live in the
browser.
Several Web server controls use client callbacks. For example, the TreeView control uses client callbacks to implement its
populate on demand functionality. For more information see TreeView Web Server Control Overview.
Components of Client Callbacks
Creating an ASP.NET page that implements client callbacks is similar to creating any ASP.NET page, with a few these
differences. The page's server code must:
Implement the ICallbackEventHandler interface. You can add this interface declaration to any ASP.NET Web page.
Provide an implementation for the RaiseCallbackEvent method. This method will be invoked to perform the callback on
the server.
Provide an implementation for the GetCallbackResult method. This method will return the callback result to the client.
In addition, the page must contain three client script functions that perform the following actions:
One function calls a helper method that performs the actual request to the server. In this function, you can perform
custom logic to prepare the event arguments first, and then you can send a string as a parameter to the server-side
callback event handler.
Another function receives (is called by) the result from the server code that processed the callback event, accepting a
string that represents the results. This is called the client callback function.
A third function is the helper function that performs the actual request to the server, which is generated automatically by
ASP.NET when you generate a reference to this function using the GetCallbackEventReference method in server code.
Both client callbacks and postbacks are requests for the originating page, thus, client callbacks and postbacks are recorded in
Web server logs as a page request.
Implementing the Appropriate Interfaces in Server Code
To successfully run server code from the client without performing a postback, you must implement the appropriate interfaces
in server code.
Declaring the ICallbackEventHandler Interface
You can declare the ICallbackEventHandler interface as part of the class declaration for the page. If you are creating a code-
behind page, you can declare the interface by using syntax such as the following.
VB
Partial Class CallBack_DB_aspx
Inherits System.Web.UI.Page
Implements System.Web.UI.ICallbackEventHandler

C#
public partial class CallBack_DB_aspx :
System.Web.UI.Page, System.Web.UI.ICallbackEventHandler

If you are working in a single-file page or user control, you can add the declaration by using an @ Implements directive in the
page, as in the following code examples:
VB
<%@ Page Language="VB" %>
<%@ Implements Interface="System.Web.UI.ICallbackEventHandler" %>

C#
<%@ Page Language="C#" %>
<%@ Implements Interface="System.Web.UI.ICallbackEventHandler" %>

Note
The interface name is case-sensitive.

Creating a Server Callback Method


In server code, you must create a method that implements the RaiseCallbackEvent method and a method that implements
the GetCallbackResult method. The RaiseCallbackEvent method takes a single string argument instead of the usual two
arguments that are typically used with event handlers. A portion of the method might look like the following code example.
VB
Public Sub RaiseCallbackEvent(ByVal eventArgument As String) _
Implements System.Web.UI.ICallbackEventHandler.RaiseCallbackEvent

End Sub

C#
public void RaiseCallbackEvent(String eventArgument)
{
}

The GetCallbackResult method takes no arguments and returns a string. A portion of the method might look like the
following code example:
VB
Public Function GetCallbackResult() As String Implements _
System.Web.UI.ICallbackEventHandler.GetCallbackResult
Return aStringValue
End Function

C#
public string GetCallbackResult()
{
return aStringValue;
}

Creating Client Script Functions


You must add client script functions to the page to perform two functions: send the callback to the server page and receive the
results. Both client script functions are written in ECMAScript (JavaScript).
Sending the Callback
The function to send the callback is generated in server code. The actual callback is performed by a library function that is
available to any page that implements the ICallbackEventHandler interface. You can get a reference to the library function by
calling the page's GetCallbackEventReference method which is accessible through the ClientScript property of the page. You
then build a client function dynamically that includes a call to the return value from the GetCallbackEventReference method.
You pass to that method a reference to the page (this in C# or Me in Visual Basic), the name of the argument by which you will
pass data, the name of the client script function that will receive the callback data, and an argument that passes any context you
want.
When you have built the function, you inject it into the page by calling the RegisterClientScriptBlock method.
The following code example shows how to dynamically create a function named CallServer that invokes the callback.
VB
Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles Me.Load
Dim cm As ClientScriptManager = Page.ClientScript
Dim cbReference As String
cbReference = cm.GetCallbackEventReference(Me, "arg", _
"ReceiveServerData", "")
Dim callbackScript As String = ""
callbackScript &= "function CallServer(arg, context)" & _
"{" & cbReference & "; }"
cm.RegisterClientScriptBlock(Me.GetType(), _
"CallServer", callbackScript, True)End Sub

C#
void Page_Load(object sender, EventArgs e)
{
ClientScriptManager cm = Page.ClientScript;
String cbReference = cm.GetCallbackEventReference(this, "arg",
"ReceiveServerData", "");
String callbackScript = "function CallServer(arg, context) {" +
cbReference + "; }";
cm.RegisterClientScriptBlock(this.GetType(),
"CallServer", callbackScript, true);
}

The names of the arguments that are accepted by the function you are generating must match the names of the values that
you pass to the GetCallbackEventReference method.
The following code example shows some markup that could be used to invoke the callback and process its return value:
VB
<input type="button" value="Callback"
onclick="CallServer(1, alert('Callback'))"/>
<br />
<span id="Message"></span>

C#
<input type="button" value="Callback"
onclick="CallServer(1, alert('Callback'))"/>
<br />
<span id="Message"></span>

Receiving the Callback


You can write the client function that receives callbacks statically in the page. The function must be named to match the name
that you pass in the call to the GetCallbackEventReference method. The receiving function accepts two string values: one for
the return value and an optional second value for the context value that is passed back from the server.
The function might look like the following code example:

<script type="text/javascript">
function ReceiveServerData(arg, context)
{
Message.innerText = 'Processed callback.';
}
</script>

See Also
Reference
ClientScriptManager
Concepts
Client-Callback Implementation (Visual Basic) Example
Client-Callback Implementation (C#) Example
How to: Implement Callbacks in ASP.NET Web Pages
In a client callback, a client script function sends a request to the ASP.NET Web page, which then runs an abbreviated version of
its normal life cycle to process the callback. To ensure that callback events originate from the expected user interface (UI), you
can validate callbacks. In callback validation, you register an event for validation during the Web page rendering and then
validate the event during the callback. For an overview of callbacks, see
Implementing Client Callbacks Without Postbacks in ASP.NET Web Pages.
To implement the ICallBackEventHandler interface
1. For a single-file page or user control, implement the ICallbackEventHandler interface using an @ Implements directive in
the page, as shown in the following example.
VB
<%@ Page Language="VB" %>
<%@ Implements Interface="System.Web.UI.ICallbackEventHandler" %>

C#
<%@ Page Language="C#" %>
<%@ Implements Interface="System.Web.UI.ICallbackEventHandler" %>

Note
If you are using a code-behind page model, implement the ICallbackEventHandler interface for your partial class.

2. Implement the RaiseCallbackEvent method of the ICallbackEventHandler interface. The RaiseCallbackEvent method
takes a single argument that represents the event arguments, as shown in the following example.
VB
Public Sub RaiseCallbackEvent(ByVal eventArgument As String) _
Implements System.Web.UI.ICallbackEventHandler.RaiseCallbackEvent

End Sub

C#
public void RaiseCallbackEvent(String eventArgument)
{

3. Implement the GetCallbackResult method of the ICallbackEventHandler interface. The GetCallbackResult method
takes no arguments and returns a string that represents the result of the callback. In the following example, a string
called returnValue is returned.
VB
Public Function GetCallbackResult() _
As String Implements _
System.Web.UI.ICallbackEventHandler.GetCallbackResult

Return returnValue
End Function

C#
public String GetCallbackResult()
{
return returnValue;
}

To register the callback for event validation


Override the Render method of the Page class and use the RegisterForEventValidation method of the
ClientScriptManager class to register an event for validation. You can get a reference to the ClientScriptManager class
by using the ClientScript property of the Page class. In the following example, a callback named Callback1 is registered
for event validation.
VB
Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)

Page.ClientScript.RegisterForEventValidation("ClientCallback1")
MyBase.Render(writer)

End Sub

C#
protected override void Render(HtmlTextWriter writer)
{
Page.ClientScript.RegisterForEventValidation("ClientCallback1");
base.Render(writer);
}

To validate the callback and return the callback result


In the RaiseCallbackEvent method, use the ValidateEvent method of the ClientScriptManager class to validate the
event. Use the same method signature as the one used when registering the event for validation. In the following
example, the method signature that takes one argument is used.
VB
Public Sub RaiseCallbackEvent(ByVal eventArgument As String) _
Implements System.Web.UI.ICallbackEventHandler.RaiseCallbackEvent
Try
Page.ClientScript.ValidateEvent("ClientCallback1")
' Callback logic goes here.
returnValue = "callback result"

Catch
' Failed callback validation logic.
End Try

End Sub
C#
public void RaiseCallbackEvent(String eventArgument)
{
try
{
Page.ClientScript.ValidateEvent("ClientCallback1");
// Callback logic goes here.
returnValue = "callback result";
}
catch
{
// Failed callback validation logic.
}
}

If validation passes, your code should proceed with the callback event logic. After the RaiseCallbackEvent method has
completed, the GetCallbackResult method is invoked to return the callback result as a string to a client script function.
For more information about creating and implementing the client script functions to support client callbacks, see
Implementing Client Callbacks Without Postbacks in ASP.NET Web Pages and
Client Callback with Validation Implementation Example.

See Also
Concepts
Implementing Client Callbacks Without Postbacks in ASP.NET Web Pages
Client Callback with Validation Implementation Example
ASP.NET

Client-Callback Implementation (Visual Basic) Example


Demonstrates an ASP.NET Web page that implements a client callback. For more information, see
Implementing Client Callbacks Without Postbacks in ASP.NET Web Pages.
Example
The following code example is in two parts. The first part of the example shows an ASP.NET Web page (the .aspx page). The
second part shows the corresponding code-behind file (the .aspx.vb file).
VB
<%@ Page Language="VB" AutoEventWireup="true"
CodeFile="ClientCallback.aspx.vb" Inherits="ClientCallback" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"


"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title>Client Callback Example</title>
<script type="text/javascript">
function LookUpStock()
{
var lb = document.getElementById("ListBox1");
var product = lb.options[lb.selectedIndex].text;
CallServer(product, "");
}

function ReceiveServerData(rValue)
{
document.getElementById("ResultsSpan").innerHTML = rValue;
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ListBox ID="ListBox1" Runat="server"></asp:ListBox>
<br />
<br />
<button type="Button" onclick="LookUpStock()">Look Up Stock</button>
<br />
<br />
Items in stock: <span id="ResultsSpan" runat="server"></span>
<br />
</div>
</form>
</body>
</html>

VB
Partial Class ClientCallback
Inherits System.Web.UI.Page
Implements System.Web.UI.ICallbackEventHandler
Protected catalog As ListDictionary
Protected returnValue As String
Sub Page_Load(ByVal sender As Object, ByVal e As _
System.EventArgs) Handles Me.Load
Dim cbReference As String
cbReference = Page.ClientScript.GetCallbackEventReference(Me, _
"arg", "ReceiveServerData", "context")
Dim callbackScript As String = ""
callbackScript &= "function CallServer(arg, context) { " & _
cbReference & "} ;"
Page.ClientScript.RegisterClientScriptBlock(Me.GetType(), _
"CallServer", callbackScript, True)

' Populate List Dictionary with invented database data


catalog = New ListDictionary()
catalog.Add("monitor", 12)
catalog.Add("laptop", 10)
catalog.Add("keyboard", 23)
catalog.Add("mouse", 17)

ListBox1.DataSource = catalog
ListBox1.DataTextField = "key"
ListBox1.DataBind()
End Sub

Public Sub RaiseCallbackEvent(ByVal eventArgument As String) _


Implements System.Web.UI.ICallbackEventHandler.RaiseCallbackEvent
If catalog(eventArgument) Is Nothing Then
returnValue = "-1"
Else
returnValue = catalog(eventArgument).ToString()
End If

End Sub

Public Function GetCallbackResult() _


As String Implements _
System.Web.UI.ICallbackEventHandler.GetCallbackResult

Return returnValue

End Function

End Class

The Web page emulates a database lookup to determine the number of items that are available, or in stock, for a series of
products (monitors, keyboards, and so on). To simplify this code example, the database is represented by a dictionary list that
contains a small set of items. For each item in the table, the key is the item name (such as monitor) and the value is the number
of items that are in stock. In a production application, a database would be used instead.
When the page runs, a ListBox control is bound to the hash table so that the ListBox control displays the list of products. The
page also contains a button element (not a button Web server control), whose onclick event is bound to a client function
named LookUpStock. When users click the button, the button executes the LookUpStock function, which gets the current
selection from the list box and then performs the client callback by calling the CallServer function.
The code-behind page adds client-side script to the page via the RegisterClientScriptBlock method. The script that is added to
the page includes a function called CallServer, which gets the name of the method that will post back to the server from the
GetCallbackEventReference method.
The client callback invokes the RaiseCallbackEvent method, which determines the available stock for the product passed to it.
The GetCallbackResult method returns the value. Note that the arguments sent between the client script and the server code
can only be strings. To pass in or to receive multiple values, you can concatenate values in the input or return string,
respectively.
Security Note
When you use this feature, there are potential security threats. Callback arguments are not validated and therefore should be
considered unsafe. You should always check the contents of the arguments before using them. For details, see
Script Exploits Overview.

See Also
Tasks
How to: Implement Callbacks in ASP.NET Web Pages
Concepts
Implementing Client Callbacks Without Postbacks in ASP.NET Web Pages
Client Callback with Validation Implementation Example
ASP.NET

Client-Callback Implementation (C#) Example


Demonstrates an ASP.NET Web page that implements a client callback. For more information, see
Implementing Client Callbacks Without Postbacks in ASP.NET Web Pages.
Example
The following code example is in two parts. The first part of the example shows an ASP.NET Web page (the .aspx page). The
second part shows the corresponding code-behind file (the .aspx.cs file).
C#
<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="ClientCallback.aspx.cs" Inherits="ClientCallback" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML


1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<head id="Head1" runat="server">
<title>Client Callback Example</title>
<script type="text/ecmascript">
function LookUpStock()
{
var lb = document.getElementById("ListBox1");
var product = lb.options[lb.selectedIndex].text;
CallServer(product, "");
}

function ReceiveServerData(rValue)
{
document.getElementById("ResultsSpan").innerHTML = rValue;

}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ListBox ID="ListBox1" Runat="server"></asp:ListBox>
<br />
<br />
<button type="Button" onclick="LookUpStock()">Look Up Stock</button>
<br />
<br />
Items in stock: <span id="ResultsSpan" runat="server"></span>
<br />
</div>
</form>
</body>
</html>

C#
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class ClientCallback : System.Web.UI.Page,
System.Web.UI.ICallbackEventHandler
{
protected System.Collections.Specialized.ListDictionary catalog;
protected String returnValue;
protected void Page_Load(object sender, EventArgs e)
{
String cbReference =
Page.ClientScript.GetCallbackEventReference(this,
"arg", "ReceiveServerData", "context");
String callbackScript;
callbackScript = "function CallServer(arg, context)" +
"{ " + cbReference + ";}";
Page.ClientScript.RegisterClientScriptBlock(this.GetType(),
"CallServer", callbackScript, true);

catalog = new System.Collections.Specialized.ListDictionary();


catalog.Add("monitor", 12);
catalog.Add("laptop", 10);
catalog.Add("keyboard", 23);
catalog.Add("mouse", 17);
ListBox1.DataSource = catalog;
ListBox1.DataTextField = "key";
ListBox1.DataBind();

}
public void RaiseCallbackEvent(String eventArgument)
{
if (catalog[eventArgument] == null)
{
returnValue = "-1";
}
else
{
returnValue = catalog[eventArgument].ToString();
}
}
public String GetCallbackResult()
{
return returnValue;
}
}

The Web page emulates a database lookup to determine the number of items that are available, or in stock, for a series of
products (monitors, keyboards, and so on). To simplify this code example, the database is represented by a dictionary list that
contains a small set of items. For each item in the table, the key is the item name (such as monitor) and the value is the number
of items that are in stock. In a production application, a database would be used instead.
When the page runs, a ListBox control is bound to the hash table so that the ListBox control displays the list of products. The
page also contains a button element (not a Button Web server control), whose onclick event is bound to a client function
named LookUpStock. When users click the button, the button executes the LookUpStock function, which gets the current
selection from the list box and then performs the client callback by calling the CallServer function.
The code-behind page adds client-side script to the page via the RegisterClientScriptBlock method. The script that is added to
the page includes a function called CallServer, which gets the name of the method that will post back to the server from the
GetCallbackEventReference method.
The client callback invokes the RaiseCallbackEvent method, to determine the available stock for the product passed to it. The
GetCallbackResult method returns the value. Note that the arguments sent between the client script and the server code can
only be strings. To pass in or to receive multiple values, you can concatenate values in the input or return string, respectively.
Security Note
When you use this feature, there are potential security threats. Callback arguments are not validated and therefore should be
considered unsafe. You should always check the contents of the arguments before using them. For details, see
Script Exploits Overview.

See Also
Tasks
How to: Implement Callbacks in ASP.NET Web Pages
Concepts
Implementing Client Callbacks Without Postbacks in ASP.NET Web Pages
Client Callback with Validation Implementation Example
Client Callback with Validation Implementation Example
In a client callback, a client script function sends a request to the ASP.NET Web page, which then runs an abbreviated version of
its normal life cycle to process the callback. To ensure that callback events originate from the expected user interface (UI), you
can validate callbacks. Callback validation involves registering an event for validation during the Web page rendering and then
validating the event during the callback.
Note
Event validation helps secure your Web application against forged postbacks but does not protect against replay attacks. A m
ore comprehensive event validation scheme should take into account the specifics of your Web application and the permissi
ons of the user accessing its resources. For more information, see ASP.NET Web Application Security.

The example discussed here extends the Client-Callback Implementation (C#) Example and the
Client-Callback Implementation (Visual Basic) Example. In those examples, a ListBox control named ListBox1 is a server-side
control that displays a list of products. An HTML <button> element (not a Button server control) performs a callback to get
product inventory information. The example is extended to introduce additional information about whether a product is on sale
and to allow this information to be viewed by authenticated users only. A LoginView control is used with the
LoggedInTemplate property set to display additional content. Anonymous users of the Web page are allowed to execute a
callback to get inventory information, whereas logged-in users are also allowed to execute a callback to get sale information.
The callback for the sale information is registered for event validation only if the user is authenticated. This prevents execution
of the callback by users who are not authenticated.
Example
In the following example, a Web page emulates a database lookup to determine the number of items that are available and
whether an item is on sale. To simplify the example, the data store is represented by two dictionary lists. In a production
application, a database would be used instead. The example demonstrates a scenario where validating client callbacks prevents
an anonymous user from executing a callback that is intended for authenticated users only.
VB
<%@ Page Language="VB" AutoEventWireup="false"
CodeFile="ClientCallback.aspx.vb" Inherits="ClientCallback" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title>ASP.NET Example</title>
<script type="text/javascript">
function ReceiveServerData(rValue)
{
Results.innerText = rValue;
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ListBox id="ListBox1" runat="server"></asp:ListBox>
<br />
<br />
<button id="LookUpStockButton" onclick="LookUpStock()">Look Up Stock</button>
<asp:LoginView id="LoginView1" runat="server">
<LoggedInTemplate>
<button id="LookUpSaleButton" onclick="LookUpSale()">Look Up Back Order</button>
</LoggedInTemplate>
</asp:LoginView>
<br />
Item status: <span id="Results"></span>
</div>
</form>
</body>
</html>

C#
<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="ClientCallback.aspx.cs" Inherits="ClientCallback" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML


1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title>ASP.NET Example</title>
<script type="text/javascript">
function ReceiveServerData(rValue)
{
Results.innerText = rValue;
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ListBox id="ListBox1" runat="server"></asp:ListBox>
<br />
<br />
<button id="LookUpStockButton" onclick="LookUpStock()">Look Up Stock</button>
<asp:LoginView id="LoginView1" runat="server">
<LoggedInTemplate>
<button id="LookUpSaleButton" onclick="LookUpSale()">Look Up Back Order</button>
</LoggedInTemplate>
</asp:LoginView>
<br />
Item status: <span id="Results"></span>
</div>
</form>
</body>
</html>

VB
Partial Class ClientCallback
Inherits System.Web.UI.Page
Implements System.Web.UI.ICallbackEventHandler

Protected catalog As ListDictionary


Protected saleitem As ListDictionary
Protected returnValue As String
Protected validationLookUpStock As String = "LookUpStock"
Protected validationLookUpSale As String = "LookUpSale"
Sub Page_Load(ByVal sender As Object, ByVal e As _
System.EventArgs) Handles Me.Load

Page.ClientScript.RegisterClientScriptBlock(Me.GetType(), _
validationLookUpStock, "function LookUpStock() { " & _
"var lb = document.forms[0].ListBox1; " & _
"var product = lb.options[lb.selectedIndex].text; " & _
"CallServer(product, ""LookUpStock"");} ", True)
If (User.Identity.IsAuthenticated) Then
Page.ClientScript.RegisterClientScriptBlock(Me.GetType(), _
validationLookUpSale, "function LookUpSale() { " & _
"var lb = document.forms[0].ListBox1; " & _
"var product = lb.options[lb.selectedIndex].text; " & _
"CallServer(product, ""LookUpSale"");} ", True)
End If
Dim cbReference As String
cbReference = "var param = arg + '|' + context;" & _
Page.ClientScript.GetCallbackEventReference(Me, _
"param", "ReceiveServerData", "context")
Dim callbackScript As String = ""
callbackScript &= "function CallServer(arg, context) { " & _
cbReference & "} ;"
Page.ClientScript.RegisterClientScriptBlock(Me.GetType(), _
"CallServer", callbackScript, True)
' Populate List Dictionary with invented database data
catalog = New ListDictionary()
saleitem = New ListDictionary()
catalog.Add("monitor", 12)
catalog.Add("laptop", 10)
catalog.Add("keyboard", 23)
catalog.Add("mouse", 17)
saleitem.Add("monitor", 1)
saleitem.Add("laptop", 0)
saleitem.Add("keyboard", 0)
saleitem.Add("mouse", 1)

ListBox1.DataSource = catalog
ListBox1.DataTextField = "key"
ListBox1.DataBind()
End Sub

Public Sub RaiseCallbackEvent(ByVal eventArgument As String) _


Implements System.Web.UI.ICallbackEventHandler.RaiseCallbackEvent

Dim argParts() As String = eventArgument.Split("|"c)


If ((argParts Is Nothing) OrElse (argParts.Length <> 2)) Then
returnValue = "A problem occurred trying to retrieve stock count."
Return
End If

Dim product As String = argParts(0)


Dim validationaction = argParts(1)
Select Case validationaction
Case "LookUpStock"
Try
Page.ClientScript.ValidateEvent("LookUpStockButton", validationaction)
If (catalog(product) Is Nothing) Then
returnValue = "Item not found."
Else
returnValue = catalog(product).ToString() & " in stock."
End If
Catch
returnValue = "Can not retrieve stock count."
End Try
Case "LookUpSale"
Try
Page.ClientScript.ValidateEvent("LookUpSaleButton", validationaction)
If (saleitem(product) Is Nothing) Then
returnValue = "Item not found."
Else
If (Convert.ToBoolean(saleitem(product))) Then
returnValue = "Item is on sale."
Else
returnValue = "Item is not on sale."
End If
End If
Catch
returnValue = "Can not retrieve sale status."
End Try

End Select
End Sub

Public Function GetCallbackResult() _


As String Implements _
System.Web.UI.ICallbackEventHandler.GetCallbackResult

Return returnValue

End Function

Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)


Page.ClientScript.RegisterForEventValidation("LookUpStockButton", _
validationLookUpStock)
If (User.Identity.IsAuthenticated) Then
Page.ClientScript.RegisterForEventValidation("LookUpSaleButton", _
validationLookUpSale)
End If
MyBase.Render(writer)
End Sub
End Class

C#
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class ClientCallback : System.Web.UI.Page,


System.Web.UI.ICallbackEventHandler
{
protected System.Collections.Specialized.ListDictionary catalog;
protected System.Collections.Specialized.ListDictionary saleitem;
protected String returnValue;
protected String validationLookUpStock = "LookUpStock";
protected String validationLookUpSale = "LookUpSale";
protected void Page_Load(object sender, EventArgs e)
{
Page.ClientScript.RegisterClientScriptBlock(this.GetType(),
validationLookUpStock, "function LookUpStock() { " +
"var lb = document.forms[0].ListBox1; " +
"var product = lb.options[lb.selectedIndex].text; " +
@"CallServer(product, ""LookUpStock"");} ", true);
if (User.Identity.IsAuthenticated)
{
Page.ClientScript.RegisterClientScriptBlock(this.GetType(),
validationLookUpSale, "function LookUpSale() { " +
"var lb = document.forms[0].ListBox1; " +
"var product = lb.options[lb.selectedIndex].text; " +
@"CallServer(product, ""LookUpSale"");} ", true);
}

String cbReference = "var param = arg + '|' + context;" +


Page.ClientScript.GetCallbackEventReference(this,
"param", "ReceiveServerData", "context");
String callbackScript;
callbackScript = "function CallServer(arg, context)" +
"{ " + cbReference + "} ;";
Page.ClientScript.RegisterClientScriptBlock(this.GetType(),
"CallServer", callbackScript, true);
catalog = new System.Collections.Specialized.ListDictionary();
saleitem = new System.Collections.Specialized.ListDictionary();
catalog.Add("monitor", 12);
catalog.Add("laptop", 10);
catalog.Add("keyboard", 23);
catalog.Add("mouse", 17);
saleitem.Add("monitor", 1);
saleitem.Add("laptop", 0);
saleitem.Add("keyboard", 0);
saleitem.Add("mouse", 1);

ListBox1.DataSource = catalog;
ListBox1.DataTextField = "key";
ListBox1.DataBind();
}
public void RaiseCallbackEvent(String eventArgument)
{
string[] argParts = eventArgument.Split('|');
if ((argParts == null) || (argParts.Length != 2))
{
returnValue = "A problem occurred trying to retrieve stock count.";
return;
}
string product = argParts[0];
string validationaction = argParts[1];
switch (validationaction)
{
case "LookUpStock":
try
{
Page.ClientScript.ValidateEvent("LookUpStockButton", validationaction);
if (catalog[product] == null)
{
returnValue = "Item not found.";
}
else
{
returnValue = catalog[product].ToString() + " in stock.";
}
}
catch
{
returnValue = "Can not retrieve stock count.";
}
break;
case "LookUpSale":
try
{
Page.ClientScript.ValidateEvent("LookUpSaleButton", validationaction);
if (saleitem[product] == null)
{
returnValue = "Item not found.";
}
else
{
if (Convert.ToBoolean(saleitem[product]))
returnValue = "Item is on sale.";
else
returnValue = "Item is not on sale.";
}
}
catch
{
returnValue = "Can not retrieve sale status.";
}
break;
}
}
public String GetCallbackResult()
{
return returnValue;
}
protected override void Render(HtmlTextWriter writer)
{
Page.ClientScript.RegisterForEventValidation("LookUpStockButton",
validationLookUpStock);
if (User.Identity.IsAuthenticated)
{
Page.ClientScript.RegisterForEventValidation("LookUpSaleButton",
validationLookUpSale);
}
base.Render(writer);
}
}

The Web page emulates a database lookup to determine the number of items that are available, or in stock, for a series of
products (monitors, keyboards, and so on). To simplify this code example, the database is represented by a dictionary list that
contains a small set of items. For each item in the table, the key is the item name (such as monitor) and the value is the number
of items that are in stock. In a production application, a database would be used instead.
When the page runs, a ListBox control is bound to the hash table so that the ListBox control displays the list of products. For
authenticated users, the page is rendered with two HTML <button> elements whose onclick events are bound to a client
function named LookUpStock and a client function named LookUpSale, respectively. For anonymous users, the page is rendered
with only one HTML <button> element, whose onclick event is bound to LookUpStock. A LoginView control is used to
specify which buttons are shown. In an overridden Render event for the page, the buttons are registered for validation. If the
user is not authenticated, the button that initiates the callback for LookUpSale is not registered and the callback will fail if it is
attempted.
The code-behind page adds client-side script to the page through the RegisterClientScriptBlock method. The script that is
added to the page includes a function named CallServer, which gets the name of the method that will post back to the server
from the GetCallbackEventReference method.
The client callback invokes the RaiseCallbackEvent method, to determine the available stock for the product passed to it. The
GetCallbackResult method returns the value. Note that the arguments sent between the client script and the server code can
only be strings. To pass in or to receive multiple values, you can concatenate values in the input or return string, respectively.
Security Note
If your Web page and client callbacks deal with the display of sensitive data or operations that insert, update, or delete data, it
is recommended that you validate callbacks to ensure that the intended user interface element is executing the callback.

See Also
Tasks
How to: Implement Callbacks in ASP.NET Web Pages
Reference
ClientScriptManager
RegisterForEventValidation
ValidateEvent
Concepts
Implementing Client Callbacks Without Postbacks in ASP.NET Web Pages
Client-Callback Implementation (C#) Example
Client-Callback Implementation (Visual Basic) Example
Visual Web Developer

ASP.NET Master Pages in Visual Studio


ASP.NET master pages allow you to create a page layout (a master page) that you can use with selected or all pages (content
pages) in your Web site. Master pages can greatly simplify the task of creating a consistent look for your site. The topics in this
section introduce master pages and describe how to create and manage them.
In This Section
ASP.NET Master Pages Overview
Walkthrough: Creating and Using ASP.NET Master Pages in Visual Web Developer
Editing Master Pages in the Visual Web Developer Designer
Nested ASP.NET Master Pages
Sharing Master Pages in Visual Studio
Working with ASP.NET Master Pages Programmatically
Reference
MasterPage
Provides details on the master page class.
See Also
Other Resources
ASP.NET Web Sites (Visual Studio)
ASP.NET Web Pages (Visual Studio)
Web Page Designer
ASP.NET

ASP.NET Master Pages Overview


ASP.NET master pages allow you to create a consistent layout for the pages in your application. A single master page defines
the look and feel and standard behavior that you want for all of the pages (or a group of pages) in your application. You can
then create individual content pages that contain the content you want to display. When users request the content pages, they
merge with the master page to produce output that combines the layout of the master page with the content from the content
page.
How Master Pages Work
Master pages actually consist of two pieces, the master page itself and one or more content pages.
Note
You can also nest master pages. For details, see Nested ASP.NET Master Pages.

Master Pages
A master page is an ASP.NET file with the extension .master (for example, MySite.master) with a predefined layout that can
include static text, HTML elements, and server controls. The master page is identified by a special @ Master directive that
replaces the @ Page directive that is used for ordinary .aspx pages. The directive looks like the following.
VB
<%@ Master Language="VB" %>

C#
<%@ Master Language="C#" %>

The @ Master directive can contain most of the same directives that a @ Control directive can contain. For example, the
following master-page directive includes the name of a code-behind file, and assigns a class name to the master page.
VB
<%@ Master Language="VB" CodeFile="MasterPage.master.vb" Inherits="MasterPage" %>

C#
<%@ Master Language="C#" CodeFile="MasterPage.master.cs" Inherits="MasterPage" %>

In addition to the @ Master directive, the master page also contains all of the top-level HTML elements for a page, such as
html, head, and form. For example, on a master page you might use an HTML table for the layout, an img element for your
company logo, static text for the copyright notice, and server controls to create standard navigation for your site. You can use
any HTML and any ASP.NET elements as part of your master page.
Replaceable Content Placeholders
In addition to static text and controls that will appear on all pages, the master page also includes one or more
ContentPlaceHolder controls. These placeholder controls define regions where replaceable content will appear. In turn, the
replaceable content is defined in content pages. After you have defined the ContentPlaceHolder controls, a master page
might look like the following.
VB
<% @ Master Language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML


1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server" >
<title>Master page title</title>
</head>
<body>
<form id="form1" runat="server">
<table>
<tr>
<td><asp:contentplaceholder id="Main" runat="server" /></td>
<td><asp:contentplaceholder id="Footer" runat="server" /></td>
</tr>
</table>
</form>
</body>
</html>

C#
<%@ Master Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML
1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server" >
<title>Master page title</title>
</head>
<body>
<form id="form1" runat="server">
<table>
<tr>
<td><asp:contentplaceholder id="Main" runat="server" /></td>
<td><asp:contentplaceholder id="Footer" runat="server" /></td>
</tr>
</table>
</form>
</body>
</html>

Content Pages
You define the content for the master page's placeholder controls by creating individual content pages, which are ASP.NET
pages (.aspx files and, optionally, code-behind files) that are bound to a specific master page. The binding is established in the
content page's @ Page directive by including a MasterPageFile attribute that points to the master page to be used. For
example, a content page might have the following @ Page directive, which binds it to the Master1.master page.
VB
<%@ Page Language="VB" MasterPageFile="~/MasterPages/Master1.master" Title="Content Page" %
>

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

In the content page, you create the content by adding Content controls and mapping them to ContentPlaceHolder controls
on the master page. For example, the master page might have content placeholders called Main and Footer. In the content
page, you can create two Content controls, one that is mapped to the ContentPlaceHolder control Main and the other
mapped to the ContentPlaceHolder control Footer, as shown in the following figure.
Replacing placeholder content
After creating Content controls, you add text and controls to them. In a content page, anything that is not inside the Content
controls (except script blocks for server code) results in an error. You can perform any tasks in a content page that you do in an
ASP.NET page. For example, you can generate content for a Content control using server controls and database queries or
other dynamic mechanisms.
A content page might look like the following.
VB
<% @ Page Language="VB" MasterPageFile="~/Master.master" Title="Content Page 1" %>
<asp:Content ID="Content1" ContentPlaceHolderID="Main" Runat="Server">
Main content.
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="Footer" Runat="Server" >


Footer content.
</asp:content>

[C#]

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


<asp:Content ID="Content1" ContentPlaceHolderID="Main" Runat="Server">
Main content.
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="Footer" Runat="Server" >


Footer content.
</asp:content>

The @ Page directive binds the content page to a specific master page, and it defines a title for the page that will be merged
into the master page. Note that the content page contains no other markup outside of the Content controls. (The master page
must contain a head element with the attribute runat="server" so that the title setting can be merged at run time.)
You can create multiple master pages to define different layouts for different parts of your site, and a different set of content
pages for each master page.
Advantages of Master Pages
Master pages provide functionality that developers have traditionally created by copying existing code, text, and control
elements repeatedly; using framesets; using include files for common elements; using ASP.NET user controls; and so on.
Advantages of master pages include the following:
They allow you to centralize the common functionality of your pages so that you can make updates in just one place.
They 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 give you fine-grained control over the layout of the final page by allowing you to control how the placeholder
controls are rendered.
They provide an object model that allows you to customize the master page from individual content pages.
Run-time Behavior of Master Pages
At run time, master pages are handled in the following sequence:
1. Users request a page by typing the URL of the content page.
2. When the page is fetched, the @ Page directive is read. If the directive references a master page, the master page is read
as well. If this is the first time the pages have been requested, both pages are compiled.
3. The master page with the updated content is merged into the control tree of the content page.
4. The content of individual Content controls is merged into the corresponding ContentPlaceHolder control in the
master page.
5. The resulting merged page is rendered to the browser.
The process is illustrated in the following diagram.
Master pages at run time

From the user's perspective, the combined master and content pages are a single, discrete page. The URL of the page is that of
the content page.
From a programming perspective, the two pages act as separate containers for their respective controls. The content page acts
as a container for the master page. However, you can reference public master-page members from code in the content page,
as described in the next section.
Note that the master page becomes a part of the content page. In effect, the master page acts in much the same way a user
control acts — as a child of the content page and as a container within that page. In this case, however, the master page is the
container for all of the server controls that are rendered to the browser. The control tree for a merged master and content page
looks something like this:

Page
Master Page
(Master page markup and controls)
ContentPlaceHolder
Content page markup and server controls
(Master page markup and controls)
ContentPlaceHolder
Content page markup and server controls
(Master page markup and controls)

This diagram is simplified; if the content page does not have corresponding Content controls, the master page might also
have markup and controls in the ContentPlaceholder controls.
In general, this structure has no effect on how you construct your pages or program them. However, in some cases, if you set a
page-wide property on the master page, it can affect the behavior of the content page, because the master page is the closest
parent for the controls on the page. For example, if you set the EnableViewState property on the content page to true but set
the same property to false in the master page, view state will effectively be disabled because the setting on the master page
will take priority.
Master Page and Content Page Paths
When a content page is requested, its content is merged with the master page, and the page runs in the context of the content
page. For example, if you get the CurrentExecutionFilePath property of the HttpRequest object, whether in content page code
or in master page code, the path represents the location of the content page.
The master page and content page do not have to be in the same folder. As long as the MasterPageFile attribute in the
content page's @ Page directive resolves to a .master page, ASP.NET can merge the content and master pages into a single
rendered page.
Referencing External Resources
Both the content page and master page can contain controls and elements that reference external resources. For example, both
might contain image controls that reference image files, or they might contain anchors that reference other pages.
The context for the merged content and master pages is that of the content page. This can affect how you specify URLs for
resources, such as image files and target pages, in anchors.
Server Controls
In server controls on master pages, ASP.NET dynamically modifies the URLs of properties that reference external resources. For
example, you might put an Image control on a master page and set its ImageUrl property to be relative to the master page. At
run time, ASP.NET will modify the URL so that it resolves correctly in the context of the content page.
ASP.NET can modify URLs in the following cases:
The URL is a property of an ASP.NET server control.
The property is marked internally in the control as being a URL. (The property is marked with the attribute
UrlPropertyAttribute.) In practical terms, ASP.NET server control properties that are commonly used to reference external
resources are marked in this way.
Other Elements
ASP.NET cannot modify URLs on elements that are not server controls. For example, if you use an img element on a master
page and set its src attribute to a URL, ASP.NET will not modify the URL. In that case, the URL will be resolved in the context of
the content page and create the URL accordingly.
In general, when working with elements on master pages, it is recommended that you use a server control, even for elements
that do not require server code. For example, instead of using an img element, use an Image server control. That way,
ASP.NET can resolve URLs correctly and you can avoid maintenance issues that might arise if you move the master or content
page.
For more information about specifying paths for ASP.NET server controls, see ASP.NET Web Site Paths.
Master Pages and Themes
You cannot directly apply an ASP.NET theme to a master page. If you add a theme attribute to the @ Master directive, the page
will raise an error when it runs.
However, themes are applied to master pages under these circumstances:
If a theme is defined in the content page. Master pages are resolved in the context of content pages, so the content page's
theme is applied to the master page as well.
If the site as a whole is configured to use a theme by including a theme definition in the
pages Element (ASP.NET Settings Schema) element.
For more information, see ASP.NET Themes and Skins Overview.
Scoping Master Pages
You can attach content pages to a master page at three levels:
At the page level You can use a page directive in each content page to bind it to a master page, as in the following
code example.
VB
<%@ Page Language="VB" MasterPageFile="MySite.Master" %>
C#
<%@ Page Language="C#" MasterPageFile="MySite.Master" %>

At the application level By making a setting in the pages element of the application's configuration file (Web.config),
you can specify that all ASP.NET pages (.aspx files) in the application automatically bind to a master page. The element
might look like the following.

<pages masterPageFile="MySite.Master" />

If you use this strategy, all ASP.NET pages in the application that have Content controls are merged with the specified
master page. (If an ASP.NET page does not contain Content controls, the master page is not applied.)
At the folder level This strategy is like binding at the application level, except that you make the setting in a
Web.config file in one folder only. The master-page bindings then apply to the ASP.NET pages in that folder.

See Also
Tasks
How to: Reference ASP.NET Master Page Content
How to: Reference ASP.NET Master Page Content
Concepts
Events in ASP.NET Master and Content Pages
Nested ASP.NET Master Pages
Visual Web Developer

Walkthrough: Creating and Using ASP.NET Master Pages in


Visual Web Developer
This walkthrough illustrates how to create a master page and several content pages. Master pages allow you to create a page
layout — a template page — and then create separate pages containing content that is merged with the master page at run
time. For more information about master pages, see ASP.NET Master Pages Overview.
Tasks illustrated in this walkthrough include:
Creating a master page in Microsoft Visual Web Developer.
Creating an ASP.NET page with content that you want to display in the master page.
Running master pages to show different content.
Selecting a master page at run time.
Prerequisites
In order to complete this walkthrough, you will need:
Visual Web Developer (Visual Studio).
The .NET Framework.
Optionally, a .jpg, .gif, or other graphics file that you can use as a logo on your master page. It is recommended that the
logo be no more than 48 pixels wide. However, displaying a logo is optional and the graphic's exact size is not critical to
the walkthrough.
Creating a Web Site
If you have already created a Web site in Visual Web Developer (for example, by following the steps in
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and skip to the next section,
"Creating the Master Page." Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, enter the name of the folder where you want to keep the pages of your Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click the programming language you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Creating the Master Page
The master page is the template for how your pages will look. In this section, you will first create a master page. You will then
use a table to lay out the master page with a menu, a logo, and a footer that will appear on each page of your site. You will also
work with a content placeholder, which is a region in the master page that can be replaced with information in a content page.
To create the master page
1. In Solution Explorer, right-click the name of your Web site, and then click Add New Item.
2. Under Visual Studio installed templates, click Master Page.
3. In the Name box, type Master1.
4. Select the Place code in separate file check box.
Note
This walkthrough assumes you are using code-behind files for all pages. If you are using a single-file ASP.NET page, the
code illustrated in this walkthrough will work, but will appear in Source view, not in a separate code file.

5. In the Language list, click the programming language you prefer and then click Add.
The new master page opens in Source view.
At the top of the page is an @ Master declaration instead of the @ Page declaration normally found at the top of ASP.NET
pages. The body of the page contains an <asp:contentplaceholder> control, which is the area of the master page
where replaceable content will be merged from content pages at run time. You will work more with the content
placeholder later in this walkthrough.
Laying Out the Master Page
The master page defines how the pages in your site look. It can contain any combination of static text and controls. A master
page also contains one or more content placeholders that designate where dynamic content will appear when pages are
displayed.
In this walkthrough, you will use a table to help you position elements on the page. You will start by creating a layout table to
hold the master page elements. Later in this section you will position the content placeholder control that is already on the
page.
To create a layout table for the master page
1. With the Master1.master file selected in Source view, set the target schema for validation to Microsoft Internet Explorer
6.0. To set this value, you can use either the drop-down list on the toolbar or select Options from the Tools menu, and
then click Validation.
2. Switch to Design view.
3. From the drop-down list at the top of the Properties window, select DOCUMENT, and then set BgColor to a distinctive
color, such as blue.
The color you select is not important. Later in this walkthrough you will create a second master page without a color to
contrast with what you have selected here.
4. Click the page where you want to place the layout table.
Note
Do not put the layout table inside the ContentPlaceHolder control.

5. On the Layout menu, click Insert Table.


6. In the Insert Table dialog box, click Template. In the list click Header, footer and side, and then click OK.
The template defines the arrangement of rows and cells in the table. The template you have selected creates three rows,
and the middle row is split into two cells.
7. Make the following settings:
In the middle row, click the leftmost column, and then set its Width to 48 in the Properties window.
Click the top row, and then set its Height to 48 in the Properties window.
Click the bottom row, and then set its Height to 48 in the Properties window.
Note
You can set the width and height by dragging the table cell borders or by selecting the cell and setting values in the Pro
perties window.

8. Select all cells in the table and set BgColor to a different color than the background color, and set VAlign to top.
8. Select all cells in the table and set BgColor to a different color than the background color, and set VAlign to top.
After laying out the table, you can add content to the master page that will appear on all pages. You will add a copyright
message as a footer, and add a menu. If you have a logo graphic available, you can add that as well.
To add static content to the master page
1. Click the bottom cell, and then type footer text such as Copyright 2005 Contoso Inc.
2. In the Toolbox, from the Navigation control group, drag a Menu control into the top cell.
3. Create a menu by following these steps:
a. Set the Menu control's Orientation property to Horizontal.
b. Click the smart tag on the Menu control, and click Edit Menu Items in the Menu Tasks dialog box.
4. Under Items, click the Add a root node icon twice to add two menu items:
a. Click the first node, and then set Text to Home and NavigateUrl to Home.aspx.
b. Click the second node, and then set Text to About and NavigateUrl to About.aspx.
c. Click OK to close the Menu Item Editor dialog box.
5. If you have a graphics file available to use as a logo, follow these steps to place it on the master page:
a. In Solution Explorer, right-click the name of your Web site, and then click Add Existing Item.
b. Navigate to your graphics file, select the graphic file, and then click Add.
c. In the Toolbox, from the Standard group, drag an Image control to the middle left column of the table.
d. Set the Image control's ImageUrl property to the name of the graphics file.
You can now position the content placeholder to specify where the master page can display content at run time.
To add a content placeholder
1. Drag the ContentPlaceHolder control into the middle right cell.
The control's ID property is ContentPlaceholder1. You can leave this name or change it. If you change the name, make a
note of the name because you will need to know the name later.
2. Save the page.
Creating Content for the Master Page
The master page provides the template for your content. You define content for the master page by creating an ASP.NET page
that is associated with the master page. The content page is a specialized form of an ASP.NET page that contains only the
content to be merged with the master page. In the content page, you add the text and controls that you want to display when
users request that page.
In this walkthrough, you will add two pages with content for the master page. The first is a home page and the second is an
about page.
To create the Home page
1. In Solution Explorer, right-click the name of your Web site, and click Add New Item.
2. Under Visual Studio installed templates, click Web Form.
3. In the Name box, type Home.
4. In the Language list, click the programming language you prefer.
5. Select the Select master page check box, and then click Add.
The Select a Master Page dialog box appears.
6. Click Master1.master, and then click OK.
A new .aspx file is created. The page contains an @ Page directive that attaches the current page to the selected master
page with the MasterPageFile attribute, as shown in the following code example.
VB
<%@ Page Language="VB" MasterPageFile="~/Master1.master" ... %>

C#
<%@ Page Language="C#" MasterPageFile="~/Master1.master" ... %>

The page also contains an <asp:Content> element that you will work with next.
A content page does not have the usual elements that make up an ASP.NET page, such as html, body, or form elements.
Instead, you add only the content that you want to display on the master page by replacing the placeholder regions you
created in the master page.
To add content to the Home page
1. Switch to Design view.
The region you created as a ContentPlaceHolder control in the master page is displayed as a Content control in the
new content page. The rest of the master page content is displayed so you can see the layout, but it appears dimmed
because you cannot change it while editing a content page.
2. From the drop-down list in the Properties window, click DOCUMENT, and then set Title to Contoso Home Page.
You can set the title of each content page independently, so that the correct title is displayed in the browser when the
content is merged with the master page. The title information is stored in the content page's @ Page directive.
3. In the Content control, type Welcome to the Contoso Web Site, select the text, and then format the text as a Heading
1 by selecting the text and selecting Heading 1 from the Block Format drop-down list above the Toolbox.
4. Press ENTER to create a new blank line in the Content control, and then type Thank you for visiting our site.
The text you add here is not important; you can type any text that will help you recognize this page as the home page.
5. Save the page.
You can create the About page the same way you created the Home page.
To create the About page
1. Use the same steps that you used for the Home page to add a new content page named About.aspx.
Be sure to attach the new page to the Master1.master page as you did with the Home page.
2. Change the page's title to Contoso About Page.
3. In the content region, type About Contoso, and then format the text as a Heading 1 by selecting the text and selecting
Heading 1 from the Block Format drop-down list above the Toolbox.
4. Press ENTER to create a new line, and then type Since 1982, Contoso has provided high-quality software services.
5. Save the page.
Testing the Pages
You can test the pages by running them as you would any ASP.NET page.
To test the pages
1. Switch to the Home.aspx page, and then press CTRL+F5.
ASP.NET merges the content in the Home.aspx page with the layout in the Master1.master page into a single page and
displays the resulting page in the browser. Notice that the URL of the page is Home.aspx; there is no reference in the
browser to the master page.
2. Click the About link.
The About.aspx page is displayed. It is also merged with Master1.master page.
Referencing Master Page Members
Code in the content pages can reference members on the master page, including any public properties or methods and any
controls on the master page. In this part of the walkthrough, you will create a property on the master page, and then use the
value of the property in the content pages. The premise is that the company name for the Web site is stored as a property in
the master page, and any reference to the company name in the content pages is based on the master page property.
The first step is to add a property to the master page.
To add a property to the master page
1. Switch to or open the Master1.master page.
2. In Solution Explorer, right-click Master1.master, and then click View Code to open the code editor.
Note
By default, Visual Web Developer creates pages that use the code-behind model. If you prefer, you can create code by u
sing the single-file model. For more information, see ASP.NET Web Page Code Model.

3. Inside the class definition, type the following code.


VB
Public Property CompanyName() As String
Get
Return CType(ViewState("companyName"), String)
End Get
Set(ByVal Value As String)
ViewState("companyName") = Value
End Set
End Property

C#
public String CompanyName
{
get { return (String) ViewState["companyName"]; }
set { ViewState["companyName"] = value; }
}

The code creates a property named CompanyName for the master page. The value is stored in view state so that it is
persisted between postbacks.
4. Inside the class definition (but not inside the property code), add the following code.
VB
Sub Page_Init(ByVal sender As Object, ByVal e As EventArgs) _
Handles Me.Init
Me.CompanyName = "Contoso"
End Sub

C#
void Page_Init(Object sender, EventArgs e)
{
this.CompanyName = "Contoso";
}

For this example, you will hard-code the value of the CompanyName property into the page.
You can now modify the content page to use the master page's CompanyName property.
To reference the CompanyName property in the content page
1. Switch to or open the Home.aspx page.
2. Switch to Source view.
3. At the top of the page, underneath the @ Page directive, add the following @ MasterType directive:

<%@ MasterType virtualpath="~/Master1.master" %>

The directive binds the content page's Master property, which you will use shortly, to the Master1.master page.
4. Switch to Design view.
5. In the Content control, change the text to Welcome to the Web site of .
6. In the Toolbox, from the Standard group, drag a Label control onto the Content control, and place it after the static text
so that the text reads:
Welcome to the Web site of [Label]
7. Set the Label control's ID property to CompanyName.
8. In Solution Explorer, right-click Home.aspx, and then click View Code to open the code editor.
9. Inside the class definition, add the following code.
VB
Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) _
Handles Me.Load
CompanyName.Text = Master.CompanyName
End Sub

C#
void Page_Load(Object sender, EventArgs e)
{
CompanyName.Text = Master.CompanyName;
}

The content page's Master property returns a reference to the master page as defined in the @ MasterType directive you
added in step 3.
You can now test the content page to be sure it is referencing the master page's CompanyName property correctly.
To test the reference to the master page property
1. Switch to or open the Home.aspx page, and then press CTRL+F5 to run the page.
The page is displayed in the browser, with the text Welcome to the Web site of Contoso
2. Close the browser.
3. Switch to or open the Master1.master code-behind page.
4. Change the Page_Init handler to assign a different company name to the property, as in the following code example.
VB
Sub Page_Init(ByVal sender As Object, ByVal e As EventArgs) _
Handles Me.Init
Me.CompanyName = "New Company Name"
End Sub
C#
void Page_Init(Object sender, EventArgs e)
{
this.CompanyName = "New Company Name";
}

5. Switch to the Home.aspx page, and then press CTRL+F5 to run it again.
This time, the updated company name appears in the page.
Notes
There are several other issues you should be aware of when working with a master page:
In a real-world application, you would probably store information such as the company name in the configuration file
and read it directly in the content pages. However, the scenario outlined here provides a simple illustration of how to
reference master page members in content pages.
You can access members on the master page even without including an @ MasterType directive. However, to do so, you
must cast the System.Web.UI.Page.Master property to the appropriate master page type (the Master property is null
if a page has no master page). For more information, see Working with ASP.NET Master Pages Programmatically.
You can reference controls on the master page by using the Master.FindControls method. For more information, see
Working with ASP.NET Master Pages Programmatically.
Changing Master Pages Dynamically
Under some circumstances, you might want to be able to change master pages dynamically; that is, to use code to set the
master page for a content page. For example, you might want to let users select from several layouts and set the master page
according to their preferences.
In this part of the walkthrough, you will add a second master page to the Web site, and then create buttons that allow the user
to switch between one master page and another. Because the two master pages will be very similar, you will make a copy of
the first master page and modify it to act as the second master page.
To make a copy of the master page
1. In Solution Explorer, right-click Master1.master, and then click Copy.
2. Right-click the name of the Web site, and then click Paste.
A master page is added to the Web site with the name Copy of master1.master.
3. Right-click Copy of master1.master, click Rename, and then name the new master page Master2.master.
4. Open Master2.master and, in the @ Master directive, change Master1 to Master2.
The completed page directive will look like the following code example.
VB
<%@ Master Language="VB" CodeFile="Master2.master.vb" Inherits="Master2" %>

C#
<%@ Master Language="C#" CodeFile="Master2.master.cs" Inherits="Master2" %>

5. Switch to Design view.


6. In the Properties window, in the drop-down list at the top, click DOCUMENT.
7. Clear the BgColor property.
The new master page will look and function like Master1.master, but will have no background color.
8. Open the code file for Master2.master and change the class name in the master page's code-behind file from Master1 to
Master2 to match the value of the Inherits attribute in the page's <%@ Master %> directive.

The code will look like the following example.


VB
Partial Class Master2

C#
public partial class Master2 : System.Web.UI.MasterPage

The next step is to add a button to each master page that allows the user to select the alternate master page.
To add buttons for selecting an alternate master page
1. Switch to or open the Master2.master page.
2. In the Toolbox, from the Standard node, drag a LinkButton control onto the page and place it below the menu in the
top table cell.
3. Set the button's Text property to Colorful.
4. Double-click the button to create a handler for its Click event, and then add the following highlighted code.
VB
Protected Sub LinkButton1_Click(ByVal sender As Object, ByVal e As EventArgs)_
Handles LinkButton1.Click
Session("masterpage") = "Master1.master"
Response.Redirect(Request.Url.ToString())
End Sub

C#
void LinkButton1_Click(Object sender, EventArgs e)
{
Session["masterpage"] = "Master1.master";
Response.Redirect(Request.Url.ToString());
}

The code loads the file name of the alternate master page into a persistent session variable, and then reloads the current
page. (The Url property returns a Uri object that references the current page.) Shortly, you will create code in the content
page that will use the name of the master page.
5. Switch to or open the Master1.master page in Design view.
6. Add a LinkButton control as you did in steps 1 and 2, and set its Text property to Plain.
7. Double-click the Plain button to create a handler for its Click event, and then add the following highlighted code.
VB
Protected Sub LinkButton1_Click(ByVal sender As Object, ByVal e As EventArgs)_
Handles LinkButton1.Click
Session("masterpage") = "Master2.master"
Response.Redirect(Request.Url.ToString())
End Sub

C#
void LinkButton1_Click(Object sender, EventArgs e)
{
Session["masterpage"] = "Master2.master";
Response.Redirect(Request.Url.ToString());
}

This code is the same as that for the button in the Master2.master page, except that it loads an alternate master page.
You now write code in the content page that will dynamically load the master page that the user has selected.
To write code to dynamically select the master page
1. Switch to or open the About.aspx page.
Note
The Home page you have already created contains an @ MasterType directive that effectively binds it to a single maste
r page (Master1.master). Therefore, you will not be able to assign master pages dynamically to the Home page and will
instead work with other pages you have created.

2. In Solution Explorer, right-click About.aspx, and then click View Code to open the code editor.
3. Inside the class definition, add the following code.
VB
Sub Page_PreInit(ByVal sender As Object, ByVal e As EventArgs) _
Handles Me.PreInit
If Not Session("masterpage") Is Nothing Then
Me.MasterPageFile = CType(Session("masterpage"), String)
End If
End Sub

C#
void Page_PreInit(Object sender, EventArgs e)
{
if(Session["masterpage"] != null)
{
this.MasterPageFile = (String) Session["masterpage"];
}
}

The code sets the value of the current page's MasterPageFile property to the value in the session variable, if any. This
code must run in the Page_PreInit handler; it cannot run in a handler that occurs any later than the Page_PreInit
handler (for example, in the Page_Init handler), because the master page must be established so that the page can
create an instance of it before any further initialization can occur.
You can now test the dynamic master pages.
To test the dynamic master pages
1. In the About.aspx page, press CTRL+F5 to run the page.
The page is displayed in the browser merged with its default master page, Master1.master.
2. Click the Plain link.
The page is redisplayed, this time merged with Master2.master, which has no background color.
3. Click the Colorful link.
The page is displayed using Master1.master again.
Notes
There are several other issues you should be aware of when working with dynamic master pages:
The scenario in this section for changing master pages is simplified to keep the walkthrough focused on master pages. In
a real application, you would most likely display a choice of layouts, and then store the user's preference by using
profiles. For details, see ASP.NET Profile Properties Overview.
You can configure your Web site so that all pages use the same master page. You might have a few pages that should
use an alternate master page, which you can configure in code in a manner similar to that shown in this section of the
walkthrough. For details, see "Scoping Master Pages" in ASP.NET Master Pages Overview.
You need to add the code from the Home.aspx page to every page where you want to override the default master page.
Next Steps
This walkthrough illustrates the basic functionality of master pages. You might want to experiment with additional features of
master pages. For example, you might want to:
Create master pages that have multiple content placeholders. You can then fill one or more placeholders with content for
each page that you display.
Define content placeholders with default content. If an ASP.NET page does not supply content for the placeholder, the
master page displays the default content.
Programmatically access members of the master page from content pages. This allows you to dynamically change the
look of the master page at run time. For details, see How to: Reference ASP.NET Master Page Content.
Use device filtering with master pages to create different layouts for different devices, such as one layout for browsers
and another for a specific type of phone. For details, see ASP.NET Device Filtering Overview.
Learn how you can put master pages within master pages to create componentized pieces. For details, see
Nested ASP.NET Master Pages.
See Also
Concepts
ASP.NET Master Pages Overview
Events in ASP.NET Master and Content Pages
Visual Web Developer

Editing Master Pages in the Visual Web Developer Designer


Visual Web Developer helps you design master pages and content pages by providing visual representations and markup
validation for master and content pages.
Editing Master Pages
When you use Visual Web Developer commands to create a new master page, the master page template contains the
@ Master directive that defines the page as a master page. Any page with the @ Master directive and with the extension
.master will be recognized as a master page by the Web page designer.
When you are editing a master page, the designer assists you in these ways:
By default, the master page contains a single ContentPlaceHolder control. You can add as many additional
ContentPlaceHolder controls as you need.
In Source view, the editor checks the page markup to be sure that you do not add elements or attributes that are not
valid in master pages. For example, if you add a Content control to a master page in Source view, the editor will mark the
control because Content controls are not allowed in master pages.
When you are editing a master page in the designer, the Web site menu and right-click menu contain the command
Add Content Page, which creates a new page that is already linked to the current master page.
Editing Content Pages
Content pages can contain only Content controls with page-specific content. The designer enforces this schema to help you
avoid run-time errors.
If you associate a content page with a master page when first creating the content page in Visual Web Developer, the designer
infers Content controls based on the ContentPlaceHolder controls in the linked master page. For example, if the master
page has two ContentPlaceHolder controls, the designer creates two Content controls in the new content page.
Note
The Content control does not appear in the Toolbox. It cannot be added to master pages, and in content pages, the designer
automatically infers Content controls. If you remove an automatically added Content control, you must replace it in Source
view.

When you add markup or controls to the Content controls in the content page, you are overriding the default master content
in the corresponding ContentPlaceHolder control. If you want to use the default master page content instead, in Design view
you can right-click the Content control and click Default to Master's Content. The designer removes the Content control,
which has the effect of allowing the corresponding ContentPlaceHolder control on the master page to provide the content.
In Design view, you can determine whether the text and controls displayed in a Content controls are default master page
content by looking at the control's title bar. If the title bar includes the word (Master), the control is displaying default content.
If the title bar includes the word (Custom), the control is displaying the text and controls that were added in the content page.
In Source view, the editor checks your markup to be sure you do not add text or controls outside of Content controls.
Theme Display in the Designer
You cannot add themes to master pages. However, you can add themes to content pages or specify a site-wide theme in the
Web.config file.
In Design view, the designer will display themed controls differently depending on a number of factors:
If a theme is applied to the content page as a style-sheet theme, master pages and content pages are displayed in Design
view with skin definitions from the theme. If the style-sheet theme is applied in the Web.config file, the designer also
displays themed controls when you edit the master page. Whether the style sheet theme is applied in the content page or
in the Web.config file, the designer displays themed controls when you edit content pages.
If the theme is defined as a theme (not a style-sheet theme) in the content page, the designer does not apply the theme in
Design view. Any controls with skin definitions are displayed using their default appearance.
For more information, see ASP.NET Themes and Skins Overview.
See Also
Concepts
ASP.NET Master Pages Overview
Visual Web Developer

How to: Create Content Pages for an ASP.NET Master Page


(Visual Studio)
A content page is an ASP.NET Web page that is associated with a master page. The master page establishes a layout and
includes one or more ContentPlaceHolder controls for replaceable text and controls. The content page includes only the text
and controls that are merged at run time with the master page's ContentPlaceHolder controls. For more information, see
ASP.NET Master Pages Overview.
Visual Web Developer provides a number of ways to create a content page, including a shortcut if you are editing a master
page. You can also create a content page by starting with a blank page and adding the appropriate directive.
After creating a content page, you can create custom content that corresponds to each ContentPlaceHolder on the master
page. Alternatively, you can explicitly choose to allow the master page's default content to be displayed.
To add a content page in Visual Web Developer
1. In Solution Explorer, right-click the name of the Web site and then click Add New Item.
2. In the Visual Studio installed templates list, click Web Form.
3. Select the Select master page check box, and then click Add.
The Select a Master Page dialog box appears.
4. In the Contents of Folder box, click the master page that you want to associate with the page you are creating, and then
click OK.
To create a content page while editing a master page
With the master page open in the editor, right-click anywhere on the page and click Add Content Page.
Visual Web Developer creates a new content page named Defaultx.aspx, where x is a sequential number.
Note
To assign a different name to the content page, close it, right-click the name in Solution Explorer, and click Rename.

To create a content page declaratively


1. Create a new ASP.NET Web page.
2. Switch to Source view.
3. Remove everything from the page except the @ Page directive.
4. Add a MasterPageFile attribute to the @ Page directive that references the master page, as shown in the following code
example.
VB
<%@ Page Language="VB" MasterPageFile="~/Master1.master" %>

C#
<%@ Page Language="C#" MasterPageFile="~/Master1.master" %>

Note
The @ Page directive might include additional attributes, such as CodeFile and Inherits, which are not shown here.

5. Add Content controls to the page that correspond to ContentPlaceHolder controls on the master page.
Note
A content page can contain only the @ Page directive and Content controls.

Creating Content in the HTML Designer


When you create a content page in Visual Web Developer, the designer creates, by default, a Content control for each
ContentPlaceHolder control defined in the master page. You can add custom content to each Content control or explicitly
revert to the default content, if any, that is defined in the master page.
To add content to the page in Design view
In Design view, drag controls or elements onto the Content control, or click the control and begin typing.
To display default master page content in Design view
1. Right-click the Content control and click Show Smart Tag.
2. Click Default to Master's Content.
Visual Web Developer displays the Content control with the default content defined in the master page. The title bar of
the Content control includes the term (Master) to indicate that it is displaying information from the master page, not
the content page.
In this mode, you cannot edit the contents displayed in the Content control.
3. To create custom content, right-click the control, click Show Smart Tag, and then click Create Custom Control to put
the control back into edit mode.
The designer removes the Content control from the content page's markup.
Note
A Content control is required in the content page only to override the corresponding ContentPlaceHolder control fr
om the master page.

See Also
Tasks
Walkthrough: Creating and Using ASP.NET Master Pages in Visual Web Developer
Concepts
ASP.NET Master Pages Overview
ASP.NET

Nested ASP.NET Master Pages


Master pages can be nested, with one master page referencing another as its master. Nested master pages allow you to create
componentized master pages. For example, a large site might contain an overall master page that defines the look of the site.
Different site content partners can then define their own child master pages that reference the site master and that in turn
define the look for that partner's content.
A child master page has the file name extension .master, as with any master page. The child master page typically contains
content controls that are mapped to content placeholders on the parent master page. In this respect, the child master page is
laid out like any content page. However, the child master page also has content placeholders of its own to display content
supplied by its own child pages. The following three page listings show a simple nested master page configuration.
This is the parent master file:
VB
<% @ Master Language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"


"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<body>
<head runat="server">
<title>Untitled Page</title>
</head>
<form id="Form1" runat="server">
<div>
<h1>Parent Master</h1>
<p style="font:color=red">This is parent master content.</p>
<asp:ContentPlaceHolder ID="MainContent" runat="server" />
</div>
</form>
</body>
</html>

C#
<% @ Master Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML
1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="Form1" runat="server">
<div>
<h1>Parent Master</h1>
<p style="font:color=red">This is parent master content.</p>
<asp:ContentPlaceHolder ID="MainContent" runat="server" />
</div>
</form>
</body>
</html>

This is the child master file:


VB
<%@ Master Language="VB" MasterPageFile="~/Parent.master"%>
<asp:Content id="Content1" ContentPlaceholderID="MainContent" runat="server">
<asp:panel runat="server" id="panelMain" backcolor="lightyellow">
<h2>Child master</h2>
<asp:panel runat="server" id="panel1" backcolor="lightblue">
<p>This is childmaster content.</p>
<asp:ContentPlaceHolder ID="ChildContent1" runat="server" />
</asp:panel>
<asp:panel runat="server" id="panel2" backcolor="pink">
<p>This is childmaster content.</p>
<asp:ContentPlaceHolder ID="ChildContent2" runat="server" />
</asp:panel>
<br />
</asp:panel>
</asp:Content>

C#
<%@ Master Language="C#" MasterPageFile="~/Parent.master"%>
<asp:Content id="Content1" ContentPlaceholderID="MainContent" runat="server">
<asp:panel runat="server" id="panelMain" backcolor="lightyellow">
<h2>Child master</h2>
<asp:panel runat="server" id="panel1" backcolor="lightblue">
<p>This is child master content.</p>
<asp:ContentPlaceHolder ID="ChildContent1" runat="server" />
</asp:panel>
<asp:panel runat="server" id="panel2" backcolor="pink">
<p>This is child master content.</p>
<asp:ContentPlaceHolder ID="ChildContent2" runat="server" />
</asp:panel>
<br />
</asp:panel>
</asp:Content>

This is a child file that references the child master page:


VB
<%@ Page Language="VB" MasterPageFile="~/Child.master"%>
<asp:Content id="Content1" ContentPlaceholderID="ChildContent1" runat="server">
<asp:Label runat="server" id="Label1"
text="Child label1" font-bold="true" />
<br>
</asp:Content>
<asp:Content id="Content2" ContentPlaceholderID="ChildContent2" runat="server">
<asp:Label runat="server" id="Label2"
text="Child label2" font-bold="true"/>
</asp:Content>

C#
<%@ Page Language="C#" MasterPageFile="~/Child.master"%>
<asp:Content id="Content1" ContentPlaceholderID="ChildContent1" runat="server">
<asp:Label runat="server" id="Label1"
text="Child label1" font-bold="true" />
<br />
</asp:Content>
<asp:Content id="Content2" ContentPlaceholderID="ChildContent2" runat="server">
<asp:Label runat="server" id="Label2"
text="Child label2" font-bold="true"/>
</asp:Content>

See Also
Concepts
ASP.NET Master Pages Overview
ASP.NET

Sharing Master Pages in Visual Studio


After you have created a set of master pages, you might want to make them available to others, such as other developers
creating Web applications in your company. In most cases, you probably do not want other developers to change the master
pages. There are several ways you can make your master pages available for reuse.
The simplest solution is to copy the master pages to a file directory that other projects can then reference. Developers could
navigate to the directory that contains the master pages and then add them to a Web application project. If you want to control
who can modify the master pages, you can set security permissions on the directory that contains the master pages. The
additional solutions outlined below allow greater flexibility in where you store the master pages intended for reuse.
Use Virtual Directories
Another solution would be to store the master pages in a virtual directory. Virtual directories are a convenient way to set up a
site for local Web development work because they do not require a unique site identity. This means that a virtual directory
requires fewer steps than it would to create a unique site to store your master pages. Virtual directories are maps to the
physical location of files that a Web application can use. The files do not have to be under the root of the Web application. This
approach enables you to maintain one set of master pages in one location that various Web applications residing on remote
machines can use.
To use master pages in a virtual directory, a developer would navigate to the directory and add the master pages to the current
Web application project. For more information about virtual directories, see
How to: Create IIS Virtual Directories in Visual Web Developer or How to: Create and Configure Virtual Directories in IIS.
Use Virtual Paths
You can use virtual paths to provide content from locations other than the file system. If, for example, you store your master
pages in a Microsoft SQL Server database, you can create a virtual path provider to dynamically retrieve content from the
database. You can also use virtual paths to provide content from a compressed .zip file.
To create a virtual path provider that can be used to provide content and files for compilation in another ASP.NET version 2.0
Web application, the developer must:
Create a VirtualPathProvider class and implement all the required methods to handle the master page file requests.
Register the virtual path provider to let the ASP.NET hosting environment know where the master pages are located.
Create VirtualFile and VirtualDirectory objects to stream the content.
For more information on creating a virtual path provider or using virtual paths to provide content, see article 910441, "How to
use virtual path providers to dynamically load and compile content from virtual paths in ASP.NET 2.0" in the
Microsoft Kn o wledg e Base and Virtualizing Ac c ess to Content: Serving Your Web Site from a ZIP File.
Precompile the Code Used in a Master Page
If you are concerned about code in your master pages being visible to others reusing the pages, you can precompile the
master pages' code into a library. In this library, you can include code-behind pages as well as user or custom controls.
Compiling master pages does not remove the declarative code for the master files or any server controls used, but you can
compile the master files to remove the code for controls or code-behind pages used by the master pages.
If you choose to compile the master pages into a library, you must use the "updatable" build option that allows for later
modification of the markup. This option is determined by the Allow the precompiled site to be updatable check box in the
Publish Web Site dialog box. For more information about precompiling pages into a library that can be reused, see Building
Re-Usable ASP.NET User Control and Page Libraries with VS 2005http://go.microsoft.com/fwlink/?LinkId=53279.
See Also
Tasks
Walkthrough: Creating and Using ASP.NET Master Pages in Visual Web Developer
Reference
VirtualPathProvider
Concepts
ASP.NET Master Pages Overview
ASP.NET

Working with ASP.NET Master Pages Programmatically


You can perform a number of common tasks programmatically with master pages, including the following:
Accessing members that are defined on the master page, which can consist of public properties and methods or controls.
Attaching master pages to a content page dynamically.
Accessing Members on the Master Page
To provide access to members of the master page, the Page class exposes a Master property. To access members of a specific
master page from a content page, you can create a strongly typed reference to the master page by creating a @ MasterType
directive. The directive allows you to point to a specific master page. When the page creates its Master property, the property
is typed to the referenced master page.
For example, you might have a master page named MasterPage.master that is the class name MasterPage_master. You might
create @ Page and @ MasterType directives that look like the following:
<%@ Page masterPageFile="~/MasterPage.master"%>
<%@ MasterType virtualPath="~/MasterPage.master"%>

When you use a @ MasterType directive, such as the one in the example, you can reference members on the master page as
in the following example:
VB
CompanyName.Text = Master.CompanyName

C#
CompanyName.Text = Master.CompanyName;

The Master property of the page is already typed to MasterPage_master.


Getting the Values of Controls on the Master Page
At run time, the master page is merged with the content page, so the controls on the master page are accessible to content
page code. (If the master page contains controls in a ContentPlaceHolder control, those controls are not accessible if
overridden by a Content control from the content page.) The controls are not directly accessible as master-page members
because they are protected. However, you can use the FindControl method to locate specific controls on the master page. If the
control that you want to access is inside a ContentPlaceHolder control on the master page, you must first get a reference to
the ContentPlaceHolder control, and then call its FindControl method to get a reference to the control.
The following example shows how you can get a reference to controls on the master page. One of the controls being
referenced is in a ContentPlaceHolder control and the other is not.
VB
' Gets a reference to a TextBox control inside a ContentPlaceHolder
Dim mpContentPlaceHolder As ContentPlaceHolder
Dim mpTextBox As TextBox
mpContentPlaceHolder = _
CType(Master.FindControl("ContentPlaceHolder1"), _
ContentPlaceHolder)
If Not mpContentPlaceHolder Is Nothing Then
mpTextBox = CType(mpContentPlaceHolder.FindControl("TextBox1"), _
TextBox)
If Not mpTextBox Is Nothing Then
mpTextBox.Text = "TextBox found!"
End If
End If
' Gets a reference to a Label control that is not in a
' ContentPlaceHolder control
Dim mpLabel As Label
mpLabel = CType(Master.FindControl("masterPageLabel"), Label)
If Not mpLabel Is Nothing Then
Label1.Text = "Master page label = " + mpLabel.Text
End If

C#
// Gets a reference to a TextBox control inside a ContentPlaceHolder
ContentPlaceHolder mpContentPlaceHolder;
TextBox mpTextBox;
mpContentPlaceHolder =
(ContentPlaceHolder)Master.FindControl("ContentPlaceHolder1");
if(mpContentPlaceHolder != null)
{
mpTextBox = (TextBox) mpContentPlaceHolder.FindControl("TextBox1");
if(mpTextBox != null)
{
mpTextBox.Text = "TextBox found!";
}
}

// Gets a reference to a Label control that is not in a


// ContentPlaceHolder control
Label mpLabel = (Label) Master.FindControl("masterPageLabel");
if(mpLabel != null)
{
Label1.Text = "Master page label = " + mpLabel.Text;
}

You can access the contents of the master page's ContentPlaceHolder controls by using the FindControl method, as shown
above. If the ContentPlaceHolder control has been merged with content from a Content control, the ContentPlaceHolder
control will not contain its default content. Instead, it will contain the text and controls that are defined in the content page.
Attaching Master Pages Dynamically
In addition to specifying a master page declaratively (in the @ Page directive or in the configuration file), you can attach a
master page dynamically to a content page. Because the master page and content page are merged during the initialization
stage of page processing, a master page must be assigned before then. Typically, you assign a master page dynamically during
the PreInit stage, as in the following example:
VB
Sub Page_PreInit(ByVal sender As Object, ByVal e As EventArgs) _
Handles Me.PreInit
Me.MasterPageFile = "~/NewMaster.master"
End Sub

C#
void Page_PreInit(Object sender, EventArgs e)
{
this.MasterPageFile = "~/NewMaster.master";
}

Strong Typing for Dynamic Master Pages


If the content page assigns a strong type to the master page by using a @ MasterType directive, the type must apply to any
master page that you assign dynamically. If you intend to select a master page dynamically, it is recommended that you create
a base class from which your master pages derive. The base master-page class can then define the properties and methods
that the master pages have in common. In the content page, when you assign a strong type to the master page by using a
@ MasterType directive, you can assign it to the base class instead of to an individual master page.
The following examples show how to create a base master-page type that can be used by multiple master pages. The examples
consist of a base type that is derived from the MasterPage control, two master pages that inherit from the base type, and a
content page that allows users to select a master page dynamically by using a query string (?color=green). The base master
type defines a property named MyTitle. One of the master pages overrides the MyTitle property, and the other one does not.
The content page displays the MyTitle property as the page's title. The title of the page will therefore vary depending on which
master page has been selected.
This is the base master-page type. It belongs in the App_Code directory.
VB
Public Class BaseMaster
Inherits MasterPage
Public Overridable ReadOnly Property MyTitle() As String
Get
Return "BaseMaster Title"
End Get
End Property
End Class

C#
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public class BaseMaster : System.Web.UI.MasterPage
{
public virtual String MyTitle
{
get { return "BaseMaster Title"; }
}
}

This is the first master page, which displays a blue background. Notice that the Inherits attribute in the @ Master directive
references the base type.
VB
<%@ Master Language="VB" Inherits="BaseMaster"
ClassName="MasterBlue" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<script runat="server">
' No property here that overrrides the MyTitle property of the base master.
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>No title</title>
</head>
<body>
<form id="form1" runat="server">
<div style="background-color:LightBlue">
<asp:contentplaceholder id="ContentPlaceHolder1"
runat="server">
Content from MasterBlue.
</asp:contentplaceholder>
</div>
</form>
</body>
</html>

C#
<%@ Master Language="C#" Inherits="BaseMaster"
ClassName="MasterBlue" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<script runat="server">
// No property here that overrrides the MyTitle property of the base master.
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >


<head id="Head1" runat="server">
<title>No title</title>
</head>
<body>
<form id="form1" runat="server">
<div style="background-color:LightBlue">
<asp:contentplaceholder id="ContentPlaceHolder1"
runat="server">
Content from MasterBlue.
</asp:contentplaceholder>
</div>
</form>
</body>
</html>

This is the second master page. It is the same as the first master page, except that it displays a green background, and it
overrides the MyTitle property that is defined in the base type.
VB
<%@ Master Language="VB" Inherits="BaseMaster"
ClassName="MasterGreen" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<script runat="server">
Public Overrides ReadOnly Property MyTitle() As String
Get
Return "MasterGreen Title"
End Get
End Property
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>No title</title>
</head>
<body>
<form id="form1" runat="server">
<div style="background-color:LightGreen">
<asp:contentplaceholder id="ContentPlaceHolder1" runat="server">
Content from MasterGreen.
</asp:contentplaceholder>
</div>
</form>
</body>
</html>

C#
<%@ Master Language="C#" Inherits="BaseMaster"
ClassName="MasterGreen" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<script runat="server">
public override String MyTitle
{
get { return "MasterGreen Title"; }
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title>No title</title>
</head>
<body>
<form id="form1" runat="server">
<div style="background-color:LightGreen">
<asp:contentplaceholder id="ContentPlaceHolder1"
runat="server">
Content from MasterGreen.
</asp:contentplaceholder>
</div>
</form>
</body>
</html>

This is the content page, which allows users to select a master page based on a query string provided with the request. The
@ MasterType directive, which assigns a strong type to the page's Master property, references the base type.
VB
<%@ Page Language="VB" Title="Content Page" MasterPageFile="~/MasterBlue.master"%>
<%@ MasterType TypeName="BaseMaster" %>
<script runat="server">

Protected Sub Page_PreInit(ByVal sender As Object,


ByVal e As System.EventArgs)
Me.MasterPageFile = "MasterBlue.master"
If Request.QueryString("color") = "green" Then
Me.MasterPageFile = "MasterGreen.master"
End If
Me.Title = Master.MyTitle
End Sub
</script>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
Content from Content page.
</asp:Content>

C#
<%@ Page Language="C#" Title="Content Page" MasterPageFile="~/MasterBlue.master"%>
<%@ MasterType TypeName="BaseMaster" %>
<script runat="server">
protected void Page_PreInit(Object sender, EventArgs e)
{
this.MasterPageFile = "MasterBlue.master";
if(Request.QueryString["color"] == "green")
{
this.MasterPageFile = "MasterGreen.master";
}
this.Title = Master.MyTitle;
}
</script>

<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1"


Runat="Server">
Content from Content page.
</asp:Content>

See Also
Concepts
ASP.NET Master Pages Overview
ASP.NET

Events in ASP.NET Master and Content Pages


Both master pages and content pages can contain event handlers for controls. For controls, events are handled locally—a
control in a content page raises an event in the content page, and a control in the master page raises an event in the master
page. Controls events are not sent from the content page to the master page. Similarly, you cannot handle an event from a
master page control in a content page.
In some cases, the same event is raised in both the content and the master page. For example, both pages raise Init and Load
events. The general rule for how events are raised is that the initialization events are raised from the innermost control to the
outermost one, and all other events are raised from the outermost control to the innermost one. It is helpful to remember that
the master page is merged into the content page and treated as a control in the content page.
The following is the sequence in which events occur when a master page is merged with a content page:
1. Master page controls Init event.
2. Content controls Init event.
3. Master page Init event.
4. Content page Init event.
5. Content page Load event.
6. Master page Load event.
7. Content controls Load event.
8. Content page PreRender event.
9. Master page PreRender event.
10. Master page controls PreRender event.
11. Content controls PreRender event.
The sequence of events in master and content pages rarely is important for you as page developer. However, if you are
creating event handlers that depend on the availability of certain controls, you will find it helpful to understand the event
sequence in master and content pages.
See Also
Tasks
How to: Reference ASP.NET Master Page Content
Concepts
ASP.NET Master Pages Overview
ASP.NET

How to: Reference ASP.NET Master Page Content


You can write code in content pages that references properties, methods, and controls in the master page, with some
restrictions. The rule for properties and methods is that you can reference them if they are declared as public members of the
master page. This includes public properties and public methods. You can reference controls on the master page independently
of referencing public members.
To reference a public member on the master page
1. Add a @ MasterType directive in the content page. In the directive, set the VirtualPath attribute to the location of the
master page, as in this example:

<%@ MasterType virtualpath="~/Masters/Master1.master" %>

This directive causes the content page's Master property to be strongly typed.
2. Write code that uses the master page's public member as a member of the Master property, as in this example, which
assigns the value of a public property named CompanyName from the master page to a text box on the content page:
VB
CompanyName.Text = Master.CompanyName

C#
CompanyName.Text = Master.CompanyName;

To reference a control on the master page


Use the FindControl method, using the value returned by the Master property as the naming container.
The following code example shows how to use the FindControl method to get a reference to two controls on the master
page, a TextBox control and a Label control. Because the TextBox control is inside a ContentPlaceHolder control, you
must first get a reference to the ContentPlaceHolder and then use its FindControl method to locate the TextBox
control.
VB
Sub Page_Load()
Dim mpContentPlaceHolder As ContentPlaceHolder
Dim mpTextBox As TextBox
mpContentPlaceHolder = _
CType(Master.FindControl("ContentPlaceHolder1"), _
ContentPlaceHolder)
If Not mpContentPlaceHolder Is Nothing Then
mpTextBox = CType(mpContentPlaceHolder. _
FindControl("TextBox1"), TextBox)
If Not mpTextBox Is Nothing Then
mpTextBox.Text = "TextBox found!"
End If
End If

' Gets a reference to a Label control not in a


' ContentPlaceHolder
Dim mpLabel As Label
mpLabel = CType(Master.FindControl("masterPageLabel"), Label)
If Not mpLabel Is Nothing Then
Label1.Text = "Master page label = " + mpLabel.Text
End If
End Sub

C#
void Page_Load()
{
// Gets a reference to a TextBox control inside
// a ContentPlaceHolder
ContentPlaceHolder mpContentPlaceHolder;
TextBox mpTextBox;
mpContentPlaceHolder =
(ContentPlaceHolder)Master.FindControl("ContentPlaceHolder1");
if(mpContentPlaceHolder != null)
{
mpTextBox =
(TextBox) mpContentPlaceHolder.FindControl("TextBox1");
if(mpTextBox != null)
{
mpTextBox.Text = "TextBox found!";
}
}

// Gets a reference to a Label control that not in


// a ContentPlaceHolder
Label mpLabel = (Label) Master.FindControl("masterPageLabel");
if(mpLabel != null)
{
Label1.Text = "Master page label = " + mpLabel.Text;
}
}

See Also
Concepts
ASP.NET Master Pages Overview
Working with ASP.NET Master Pages Programmatically
Other Resources
Accessing ASP.NET Controls Programmatically
Visual Web Developer

ASP.NET Themes in Visual Studio


An ASP.NET theme is a collection of properties that define the appearance of pages and controls in your Web site. A theme can
include skin files, which define property settings for ASP.NET Web server controls, and can also include cascading style sheet
files (.css files) and graphics. By applying a theme, you can give the pages in your Web site a consistent appearance.
The topics in this section describe what ASP.NET themes are, how they work, and how to create and apply them.
In This Section
ASP.NET Themes and Skins Overview
Walkthrough: Customizing a Web Site Using Themes in Visual Studio
How to: Define ASP.NET Page Themes (Visual Studio)
How to: Apply ASP.NET Themes
How to: Disable ASP.NET Themes
How to: Apply ASP.NET Themes Programmatically
Reference
PageTheme
Provides reference documentation on the Theme class.
See Also
Other Resources
ASP.NET Web Sites (Visual Studio)
ASP.NET Web Pages (Visual Studio)
ASP.NET Web Server Controls (Visual Studio)
ASP.NET

ASP.NET Themes and Skins Overview


A theme is a collection of property settings that allow you to define the look of pages and controls, and then apply the look
consistently across pages in a Web application, across an entire Web application, or across all Web applications on a server.
Themes and Control Skins
Themes are made up of a set of elements: skins, cascading style sheets (CSS), images, and other resources. At a minimum, a
theme will contain skins. Themes are defined in special directories in your Web site or on your Web server.
Skins
A skin file has the file name extension .skin and contains property settings for individual controls such as Button, Label, TextBox,
or Calendar controls. Control skin settings are like the control markup itself, but contain only the properties you want to set as
part of the theme. For example, the following is a control skin for a Button control:

<asp:button runat="server" BackColor="lightblue" ForeColor="black" />

You create .skin files in the Theme folder. A .skin file can contain one or more control skins for one or more control types. You
can define skins in a separate file for each control or define all the skins for a theme in a single file.
There are two types of control skins, default skins and named skins:
A default skin automatically applies to all controls of the same type when a theme is applied to a page. A control skin is a
default skin if it does not have a SkinID attribute. For example, if you create a default skin for a Calendar control, the
control skin applies to all Calendar controls on pages that use the theme. (Default skins are matched exactly by control
type, so that a Button control skin applies to all Button controls, but not to LinkButton controls or to controls that derive
from the Button object.)
A named skin is a control skin with a SkinID property set. Named skins do not automatically apply to controls by type.
Instead, you explicitly apply a named skin to a control by setting the control's SkinID property. Creating named skins
allows you to set different skins for different instances of the same control in an application.
Cascading Style Sheets
A theme can also include a cascading style sheet (.css file). When you put a .css file in the theme folder, the style sheet is
applied automatically as part of the theme. You define a style sheet using the file name extension .css in the theme folder.
Theme Graphics and Other Resources
Themes can also include graphics and other resources, such as script files or sound files. For example, part of your page theme
might include a skin for a TreeView control. As part of the theme, you can include the graphics used to represent the expand
button and the collapse button.
Typically, the resource files for the theme are in the same folder as the skin files for that theme, but they can be elsewhere in
the Web application, in a subfolder of the theme folder for example. To refer to a resource file in a subfolder of the theme
folder, use a path like the one shown in this Image control skin:

<asp:Image runat="server" ImageUrl="ThemeSubfolder/filename.ext" />

You can also store your resource files outside the theme folder. If you use the tilde (~) syntax to refer to the resource files, the
Web application will automatically find the images. For example, if you place the resources for a theme in a subfolder of your
application, you can use paths of the form ~/SubFolder/filename.ext to refer to resource files, as in the following example.

<asp:Image runat="server" ImageUrl="~/AppSubfolder/filename.ext" />

Scoping Themes
You can define themes for a single Web application, or as global themes that can be used by all applications on a Web server.
After a theme is defined, it can be placed on individual pages using the Theme or StyleSheetTheme attribute of the @ Page
directive, or it can be applied to all pages in an application by setting the pages Element (ASP.NET Settings Schema) element in
the application configuration file. If the pages Element (ASP.NET Settings Schema) element is defined in the Machine.config file,
the theme will apply to all pages in Web applications on the server.
Page Themes
A page theme is a theme folder with control skins, style sheets, graphics files and other resources created as a subfolder of the
\App_Themes folder in your Web site. Each theme is a different subfolder of the \App_Themes folder. The following example
shows a typical page theme, defining two themes named BlueTheme and PinkTheme.

MyWebSite
App_Themes
BlueTheme
Controls.skin
BlueTheme.css
PinkTheme
Controls.skin
PinkTheme.css

Global Themes
A global theme is a theme that you can apply to all the Web sites on a server. Global themes allow you to define an overall look
for your domain when you maintain multiple Web sites on the same server.
Global themes are like page themes in that they include property settings, style sheet settings, and graphics. However, global
themes are stored in a folder named Themes that is global to the Web server. Any Web site on the server, and any page in any
Web site, can reference a global theme. For more information about creating a global theme folder, see
How to: Define ASP.NET Themes.
Theme Settings Precedence
You can specify the precedence that theme settings take over local control settings by specifying how the theme is applied.
If you set a page's Theme property, control settings in the theme and the page are merged to form the final settings for the
control. If a control setting is defined in both the control and the theme, the control settings from the theme override any page
settings on the control. This strategy enables the theme to create a consistent look across pages, even if controls on the pages
already have individual property settings. For example, it allows you to apply a theme to a page you created in an earlier
version of ASP.NET.
Alternatively, you can apply a theme as a style sheet theme by setting the page's StyleSheetTheme property. In this case, local
page settings take precedence over those defined in the theme when the setting is defined in both places. This is the model
used by cascading style sheets. You might apply a theme as a style sheet theme if you want to be able to set the properties of
individual controls on the page while still applying a theme for an overall look.
Global theme elements cannot be partially replaced by elements of application-level themes. If you create an application-level
theme with the same name as a global theme, theme elements in the application-level theme will not override the global
theme elements.
Properties You Can Define Using Themes
As a rule, you can use themes to define properties that concern a page or control's appearance or static content. You can set
only those properties that have a ThemeableAttribute attribute set to true in the control class.
Properties that explicitly specify control behavior rather than appearance do not accept theme values. For example, you cannot
set a Button control's CommandName property by using a theme. Similarly, you cannot use a theme to set a GridView
control's AllowPaging property or DataSource property.
Note that you cannot use expression builders, which generate code expressions for assignment in a page at compile time, in
themes or skins.
Themes vs. Cascading Style Sheets
Themes are similar to cascading style sheets in that both themes and style sheets define a set of common attributes that can be
applied to any page. However, themes differ from style sheets in the following ways:
Themes can define many properties of a control or page, not just style properties. For example, using themes, you can
specify the graphics for a TreeView control, the template layout of a GridView control, and so on.
Themes can include graphics.
Themes do not cascade the way style sheets do. By default, any property values defined in a theme referenced by a
page's Theme property override the property values declaratively set on a control, unless you explicitly apply the theme
using the StyleSheetTheme property. For more information, see the Theme Settings Precedence section above.
Only one theme can be applied to each page. You cannot apply multiple themes to a page, unlike style sheets where
multiple style sheets can be applied.
Security Considerations
Themes can cause security issues when they are used on your Web site. Malicious themes can be used to:
Alter a control's behavior so that it does not behave as expected.
Inject client-side script, therefore posing a cross-site scripting risk.
Alter validation.
Expose sensitive information.
The mitigations for these common threats are:
Protect the global and application theme directories with proper access control settings. Only trusted users should be
allowed to write files to the theme directories.
Do not use themes from an untrusted source. Always examine any themes from outside your organization for malicious
code before using them on you Web site.
Do not expose the theme name in query data. Malicious users could use this information to use themes that are
unknown to the developer and thereby expose sensitive information.

See Also
Tasks
How to: Define ASP.NET Themes
How to: Apply ASP.NET Themes
Visual Web Developer

Walkthrough: Customizing a Web Site Using Themes in Visual


Studio
This walkthrough illustrates how to use themes to apply a consistent look to pages and controls in your Web site. A theme can
include skin files that define a common look for individual controls, one or more style sheets, and common graphics for use
with controls, such as the TreeView control. This walkthrough shows you how to work with ASP.NET themes in your Web sites.
Tasks illustrated in this walkthrough include:
Applying predefined ASP.NET themes to individual pages and to your site as a whole.
Creating your own theme that includes skins, which are used to define the look of individual controls.
Prerequisites
In order to complete this walkthrough, you will need:
Microsoft Visual Web Developer (Visual Studio).
The .NET Framework.
Creating the Web Site
If you have already created a Web site in Visual Web Developer (for example, by following the steps in
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and go to the next section.
Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, enter the name of the folder where you want to keep the pages of your Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click the programming language you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
To begin your work with themes in this walkthrough, you will set up a Button control, a Calendar control, and a Label control,
so you can see how these controls are affected by themes.
To place controls on the page
1. Switch to Design view.
2. From the Standard group of the Toolbox, drag a Calendar control, a Button control, and a Label control to the page.
The exact layout of the page is not important.
Note
Do not apply any formatting to any of the controls. For example, do not use the AutoFormat command to set the look
of the Calendar control.

3. Switch to Source view.


4. Be sure that the <head> element of the page has the runat="server" attribute so that it reads as follows:
<head runat="server"></head>

5. Save the page.


To test the page, you will want to see the page before a theme is applied, and then with different themes.
Creating and Applying a Theme to a Page
ASP.NET makes it easy to apply a predefined theme to a page, or to create a unique theme. (For details, see
How to: Define ASP.NET Themes.) In this part of the walkthrough, you will create a theme with some simple skins, which define
the appearance of controls.
To create a new theme
1. In Visual Web Developer, right-click the name of your Web site, click Add ASP.Net Folder, and then click Theme.
The folder named App_Themes and a subfolder named Theme1 are created.
2. Rename the Theme1 folder sampleTheme.
The name of this folder will be the name of the theme that you create (here, sampleTheme). The exact name is not
important, but you must remember it when you apply your custom theme.
3. Right click the sampleTheme folder, select Add New Item, add a new text file, and name it sampleTheme.skin.
4. In the sampleTheme.skin file, add skin definitions as shown in the following code example.

<asp:Label runat="server" ForeColor="red" Font-Size="14pt" Font-Names="Verdana" />


<asp:button runat="server" Borderstyle="Solid" Borderwidth="2px" Bordercolor="Blue" Ba
ckcolor="yellow"/>

Note
The exact characteristics that you define are not important. The values in the preceding selection are suggestions that w
ill be more obvious when you test the theme later.

The skin definitions are similar to the syntax for creating a control, except that the definitions include only settings that
affect the appearance of the control. For example, the skin definitions do not include a setting for the ID property.
5. Save the skin file, and then close it.
You can now test the page before any themes are applied.
Note
If you add a cascading style sheet (CSS) file to your sampleTheme folder, it will be applied to all pages that use the theme.

To test themes
1. Press CTRL+F5 to run the page.
The controls are displayed with their default appearance.
2. Close the browser, and then return to Visual Web Developer.
3. In Source view, add the following attribute to the @ Page directive:

<%@ Page Theme="sampleTheme" ... %>

Note
You must indicate the name of an actual theme in the attribute value (in this case, the sampleTheme.skin file you define
d previously).
4. Press CTRL+F5 to run the page again.
This time, the controls are rendered with the color scheme defined in your theme.
The Label and Button controls will appear with the settings you made in the sampleTheme.skin file. Because you did not
make an entry in the sampleTheme.skin file for the Calendar control, it is displayed with its default appearance.
5. In Visual Web Developer, set the theme to the name of another theme, if available.
6. Press CTRL+F5 run the page again.
The controls change appearance again.
Style Sheet Themes vs. Customization Themes
After you have created your theme, you can tailor how it is used in your application by associating it with your page as either a
customization theme (as done in the previous section), or as a style sheet theme. A style sheet theme uses the same theme files
as a customization theme, but its precedence within the page's controls and properties is lower, equivalent to a CSS file. Within
ASP.NET, the order of precedence is:
Theme settings, including themes set in your Web.config file.
Local page settings.
Style sheet theme settings.
In this regard, if you choose to use a style sheet theme, your theme's properties will be overridden by anything declared locally
within the page. Similarly, if you use a customization theme, your theme's properties will override anything within the local
page, and anything within any style sheet theme in use.
To use a style sheet theme and see order of precedence
1. Switch to Source view.
2. Change the page declaration:

<%@ Page theme="sampleTheme" %>

to a style sheet theme declaration:

<%@ Page StyleSheetTheme="sampleTheme" %>

3. Press CTRL+F5 to run the page.


Note that the ForeColor property of the Label1 control is red.
4. Switch to Design view.
5. Select Label1 and, in Properties, set ForeColor to blue.
6. Press CTRL+F5 to run the page.
The ForeColor property of Label1 is blue.
7. Switch to Source view.
8. Change the page declaration to declare a theme, rather than a style sheet theme, by changing:

<%@ Page StyleSheetTheme="sampleTheme" %>

back to:

<%@ Page Theme="sampleTheme" %>

9. Press CTRL+F5 to run the page.


The ForeColor property of Label1 is again red.
Basing a Custom Theme on Existing Controls
An easy way to create skin definitions is to use the designer to set appearance properties, and then copy the control definition
to a skin file.
To base a custom theme on existing controls
1. In Design view, set properties of the Calendar control so that the control has a distinctive look. The following settings are
suggestions:
BackColor Cyan
BorderColor Red
BorderWidth 4
CellSpacing 8
Font-Name Arial
Font-Size Large
SelectedDayStyle-BackColor Red
SelectedDayStyle-ForeColor Yellow
TodayDayStyle-BackColor Pink
Note
The exact characteristics that you define are not important. The values in the preceding list are suggestions that will be
more obvious when you test the theme later.

2. Switch to Source view and copy the <asp:calendar> element and its attributes.
3. Switch to or open the sampleTheme.skin file.
4. Paste the Calendar control definition into the sampleTheme.skin file.
5. Remove the ID property from the definition in the sampleTheme.skin file.
6. Save the sampleTheme.skin file.
7. Switch to the Default.aspx page, and drag a second Calendar control onto the page. Do not set any of its properties.
8. Run the Default.aspx page.
Both Calendar controls will appear the same. The first Calendar control reflects the explicit property settings that you
made. The second Calendar control inherited its appearance properties from the skin definition that you made in the
sampleTheme.skin file.
Applying Themes to a Web Site
You can apply a theme to an entire Web site, which means you do not need to reapply the theme to individual pages. (If you
want, you can override the themes settings on a page.)
To set a theme for a Web site
1. Create a Web.config file if one was not automatically added to your Web site by following these steps:
a. In Solution Explorer, right-click the name of your Web site, and then click Add New Item.
b. Under Templates, select Web Configuration File, and then click Add.
Note You do not need to type a name, because the file is always named Web.config.
2. Add the <pages> element if it does not already exist. The <pages> element should appear inside the <system.web>
element.
3. Add the following attribute to the <pages> element.

<pages theme="sampleTheme" />

Note
Web.config is case-sensitive and the values are camel-cased. (For example: theme and styleSheetTheme).

4. Save and close the Web.config file.


5. Switch to Default.aspx and switch to Source view.
6. Remove the theme="themeName" attribute from your page declaration.
7. Press CTRL+F5 to run Default.aspx.
The page is now displayed with the theme you specified in the Web.config file.
If you choose to specify a theme name in your page declaration, it will override any theme specified in your Web.config file.
Next Steps
ASP.NET support for themes gives you a variety of options for tailoring the look and feel of an entire application. This
walkthrough covered some of the basics, but you might be interested in learning more. For example, you might want to learn
more about:
Using themes in general. For more information, see ASP.NET Themes and Skins Overview
Creating your own themes and skins. For more information, see How to: Define ASP.NET Themes
Using themes with code. For more information, see How to: Apply ASP.NET Themes Programmatically
See Also
Concepts
ASP.NET Themes and Skins Overview
Visual Web Developer

How to: Define ASP.NET Page Themes (Visual Studio)


In Visual Web Developer you can define page themes which you can then apply to one or more pages in your application. You
can also create themes at the machine level that can be used in multiple applications on the server.
Themes consist of several supporting files, including style sheets for page appearance, control skins to define the appearance
of server controls, and any other supporting images or files that make up the theme. The content of a theme is the same
whether the theme is defined as a page theme or as a global theme.
Themes can be applied by using either the Theme or StyleSheetTheme attribute of the @ Page directive, or by setting the
pages Element (ASP.NET Settings Schema) element in the application configuration file. Visual Web Developer will only visually
represent themes applied by using the StyleSheetTheme attribute.
To create a page theme
1. In Solution Explorer, right-click the name of the Web site for which you want to create a page theme, and then click Add
ASP.NET Folder.
2. Click Theme.
If the App_Themes folder does not already exist, Visual Web Developer creates it. Visual Web Developer then creates a
new folder for the theme as a child folder of the App_Themes folder.
3. Type a name for the new folder.
The name of this folder is also the name of the page theme. For example, if you create a folder named
\App_Themes\FirstTheme, the name of your theme is FirstTheme.
4. Add files to your new folder for control skins, style sheets, and images that make up the theme.
To add a skin file and a skin to a page theme
1. In Solution Explorer, right-click the name of your theme and then click Add New Item.
2. In the Add New Item dialog box, click Skin File.
3. In the Name box, type a name for the .skin file, and then click Add.
The typical convention is to create one .skin file per control, such as Button.skin or Calendar.skin. However, you can create
as many or as few .skin files as you need.
4. In the .skin file, add a normal control definition by using declarative syntax, but include only the properties that you want
to set for the theme. The control definition must include the runat="server" attribute, and it must not include the ID=""
attribute.
The following code example shows a default control skin for a Button control, defining the color and font for all of the
Button controls in the theme.

<asp:Button runat="server"
BackColor="Red"
ForeColor="White"
Font-Name="Arial"
Font-Size="9px" />

This Button control skin does not contain a skinID attribute. It will be applied to all of the Button controls in the themed
application that do not specify the skinID attribute.
Note
An easy way to create a control skin is to add the control to a page and configure it so that it has the look you want. For
example, you might add a Calendar control to a page and set its day header, selected date, and other properties. Then, y
ou can copy the control definition from the page to a skin file, but you must remove the ID attribute.
5. Repeat steps 2 and 3 for each control skin file that you want to create.
Note
You can define only one default skin per control. Use the SkinID attribute in the skin's control declaration to create na
med skins for the same type of control.

To add a cascading style sheet file to your page theme


1. In Solution Explorer, right-click the name of your theme and then click Add New Item.
2. In the Add New Item dialog box, click Style Sheet.
3. In the Name box, type a name for the .css file, and then click Add.
When the theme is applied to a page, ASP.NET adds a reference to the style sheet to the head element of the page. For
more information, see How to: Apply ASP.NET Themes
Creating Global Themes
A global theme applies to all of the Web sites on a server. The location in which you create a folder for global themes depends
on whether you are running your Web site using Internet Information Services (IIS) or testing it using the ASP.NET
Development Server.
Note
If you are working with a file system Web site, by default Visual Web Developer runs your Web site for testing by launching t
he ASP.NET Development Server. For other types of Web sites, Visual Web Developer runs pages in IIS for testing.

To create a global theme


1. Create a Themes folder using the following path.

%windows%\Microsoft.NET\Framework\version\ASP.NETClientFiles\Themes

Note
The folder name for global themes is Themes, not App_Themes, as it is for page themes.

Create a subfolder of the Themes folder to hold your global theme files.
The name of the subfolder is the name of the theme. For example, if you create a folder named \Themes\FirstTheme, the
name of your theme is FirstTheme.
2. Add files to your new folder for control skins, style sheets, and images that make up the global theme.
Note
When you define a global theme, you cannot directly add skin and style sheet files to it using Visual Web Developer. Yo
u might find it easier to define and test the theme as a page theme and then copy it to the folder used for global theme
s on your Web server.

3. If your Web site is a file-system Web site that you are testing with the ASP.NET Development Server, your theme is ready
to test.
4. If you are testing your Web site using a local IIS Web site, open a command window and run aspnet_regiis -c to install
the theme on the server running IIS.
5. If you are testing your theme on a remote Web site or an FTP Web site, you must manually create a Themes folder using
the following path.
IISRootWeb\aspnet_client\system_web\version\Themes

See Also
Concepts
ASP.NET Themes and Skins Overview
ASP.NET

How to: Apply ASP.NET Themes


You can apply themes to a page, a Web site, or globally. Setting a theme at the Web site level applies styles and skins to all the
pages and controls in the site unless you override a theme for an individual page. Setting a theme at the page level applies
styles and skins to that page and all its controls.
By default, themes override local control settings. Alternatively, you can set a theme as a style sheet theme, so that the theme
applies only to control settings that are not explicitly set on the control.
To apply a theme to a Web site
1. In the application's Web.config file, set the <pages> element to the name of the theme, either a global theme or a page
theme, as shown in the following example:

<configuration>
<system.web>
<pages theme="ThemeName" />
</system.web>
</configuration>

Note
If an application theme has the same name as a global application theme, the page theme takes precedence.

2. To set a theme as a style sheet theme and be subordinated to local control settings), set the StyleSheetTheme attribute
instead:

<configuration>
<system.web>
<pages StyleSheetTheme="Themename" />
</system.web>
</configuration>

A theme setting in the Web.config file applies to all ASP.NET Web pages in that application. Theme settings in the Web.config
file follow normal configuration hierarchy conventions. For example, to apply a theme to only a subset of pages, you can put
the pages in a folder with their own Web.config file or create a <location> element in the root Web.config file to specify a
folder. For details, see Configuring Specific Files and Subdirectories.
To apply a theme to an individual page
Set the Theme or StyleSheetTheme attribute of the @ Page directive to the name of the theme to use, as shown in the
following example:

<%@ Page Theme="ThemeName" %>


<%@ Page StyleSheetTheme="ThemeName" %>

The theme and its corresponding styles and skins now applies only to the page declaring it.
Applying Skins to Controls
Skins defined in your theme apply to all control instances in the application or pages to which the theme is applied. In some
cases, you might want to apply a specific set of properties to an individual control. You can do that by creating a named skin
(an entry in a .skin file that has a SkinID property set) and then applying it by ID to individual controls. For details about
creating named skins, see How to: Define ASP.NET Themes.
To apply a named skin to a control
Set the control's SkinID property, as shown in the following example:
<asp:Calendar runat="server" ID="DatePicker" SkinID="SmallCalendar" />

If the page theme does not include a control skin that matches the SkinID property, the control uses the default skin for
that control type.

See Also
Tasks
How to: Disable ASP.NET Themes
How to: Define ASP.NET Themes
How to: Apply ASP.NET Themes Programmatically
Concepts
ASP.NET Themes and Skins Overview
ASP.NET

How to: Disable ASP.NET Themes


You can configure a page or control to ignore themes. Themes override local settings for page and control appearance by
default. Disabling this behavior is useful when a control or page already has a predefined look that you do not want the theme
to override.
Note
You can give precedence to control settings on the current page by applying a theme as a style sheet theme. In that case, the
theme is used to set properties that have no local settings, but explicit local settings take precedence. For details, see
How to: Apply ASP.NET Themes.

To disable themes for a page


Set the EnableTheming attribute of the @ Page directive to false, as in this example:

<%@ Page EnableTheming="false" %>

To disable themes for a control


Set the EnableTheming property of the control to false, as in this example:

<asp:Calendar id="Calendar1" runat="server" EnableTheming="false" />

See Also
Tasks
How to: Apply ASP.NET Themes
How to: Define ASP.NET Themes
How to: Apply ASP.NET Themes
Concepts
ASP.NET Themes and Skins Overview
ASP.NET

How to: Apply ASP.NET Themes Programmatically


In addition to specifying theme and skin preferences in page declarations and configuration files, you can apply themes
programmatically. You can set both page themes and style sheet themes programmatically; however, the procedure for
applying each type of theme is different.
Note
The themes referenced below are not included in ASP.NET. To create a custom theme, see How to: Define ASP.NET Themes.

To apply a page theme programmatically


In a handler for the page's PreInit method, set the page's Theme property.
The following code example shows how to set a page's theme conditionally based on a value passed in the query string.
VB
Protected Sub Page_PreInit(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles Me.PreInit
Select Case Request.QueryString("theme")
Case "Blue"
Page.Theme = "BlueTheme"
Case "Theme2"
Page.Theme = "PinkTheme"
End Select
End Sub

C#
Protected void Page_PreInit(object sender, EventArgs e)
{
switch (Request.QueryString["theme"])
{
case "Blue":
Page.Theme = "BlueTheme";
break;
case "Pink":
Page.Theme = "PinkTheme";
break;
}
}

To apply a style sheet theme programmatically


In the page's code, override the StyleSheetTheme property and in the get accessor, return the name of the style sheet
theme.
The following code example shows how to set a theme named BlueTheme as the style sheet theme for a page:
VB
Public Overrides Property StyleSheetTheme() As String
Get
Return "BlueTheme "
End Get
Set(ByVal value As String)
End Set
End Property

C#
public override String StyleSheetTheme
{
get { return "BlueTheme "; }
}

To apply control skins programmatically


In a handler for the page's PreInit method, set the control's SkinID property.
The following code example shows how to set the SkinID property of a Calendar control.
VB
Sub Page_PreInit(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles Me.PreInit
Calendar1.SkinID = "BlueTheme"
End Sub

C#
void Page_PreInit(object sender, EventArgs e)
{
Calendar1.SkinID = "MySkin";
}

See Also
Tasks
How to: Define ASP.NET Themes
Concepts
ASP.NET Themes and Skins Overview
Walkthrough: Creating User-Selectable Themes
This walkthrough illustrates how to create an ASP.NET page that lets the user select a theme for the page. Although this
example uses a single control skin and a basic cascading style sheet (CSS) file, the principles shown apply to more complex
themes that include graphics, different layout schemes in the CSS file, and more complex server control skins.
Tasks illustrated in this walkthrough include:
Creating a theme, including a CSS file and a server control skin, in Microsoft Visual Web Developer.
Creating an ASP.NET master page that uses a theme.
Creating an ASP.NET page with a master page applied that uses a theme.
Creating a drop-down list server control that applies a new theme to a page, including changing styles on the master
page elements.
Running a page to show different themes applied to the page.
Prerequisites
To complete this walkthrough, you will need:
Visual Web Developer (Visual Studio).
The .NET Framework.
Creating a Web Site
If you have already created a Web site in Visual Web Developer (for example, by following the steps in
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and skip to the next section,
"Creating a Master Page." Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, enter the name of the folder where you want to keep the pages of your Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click the programming language you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Creating a Theme
A theme is a collection of property settings that allow you to define the look of pages and controls. You can apply this look
consistently across pages in a Web application. Themes are made up of several elements: server control skins, CSS files, and
other resources. In this example, you use a skin and a style sheet to create a theme.
Themes are defined in special directories in your Web site project.
To create a theme
1. In Solution Explorer, right-click the Web site project name, click Add ASP.NET Folder, and then click Theme.
The App_Themes folder is created automatically and a new themes folder named Theme1 is added.
2. Right-click the new Theme1 folder, and click Rename. Type Blue and press ENTER.
3. Right-click the new Blue folder, and then click Add New Item.
4. In the Add New Item dialog box, select Skin File and name the file default.skin. Click Add.
5. In Solution Explorer, right-click the new Blue folder again, and then click Add New Item.
6. In the Add New Item dialog box, select Style Sheet. Name the style sheet default.css. Click Add.
The first theme is now created with an empty CSS file and server control skin file. You will edit these files in a moment,
but first you need to create a page that contains a control and some HTML that the theme can be applied to.
Creating a Master Page
To show that a theme can easily be applied to both a master page and a page that uses that master page, create a simple
master page to use with the Default.aspx page in your Web project.
To create the master page
1. In Solution Explorer, right-click the name of your Web site, and then click Add New Item.
2. Under Visual Studio installed templates, click Master Page.
3. In the Name box, type Master1.master.
4. In the Language list, click the programming language you prefer.
5. Clear the Place code in separate file check box, and then click Add.
The new master page opens in Source view. At the top of the page is an @ Master declaration instead of the @ Page
declaration normally found at the top of ASP.NET pages. The body of the page contains an <asp:contentplaceholder>
control, which defines the area of the master page where replaceable content will be merged from content pages at run
time. You will work more with the content placeholder later in this walkthrough.
Laying Out the Master Page
The master page defines the elements that make up the page. It can contain any combination of static text and controls. A
master page also contains one or more content placeholders that designate where dynamic content will appear when pages
are displayed.
In this walkthrough, you use a table containing a title, several horizontal rules, and a master page content placeholder as the
layout for your Home.aspx page.
To create a table for the master page
With the Master1.master file selected in Source view, select the text between the two <form> tags and paste the
following content into the selected area. Note that this code puts the content placeholder in a table, instead of between
the <div> tags as it is in the default master layout.
VB
<table width="100%" cellspacing="0" cellpadding="0" border="0" class="header">
<tr>
<td class="title">Switchable Themes Example</td>
</tr>
<tr>
<td><hr /></td>
</tr>
<tr>
<td>
<asp:contentplaceholder id="ContentPlaceHolder1" runat="server">
</asp:contentplaceholder>
</td>
</tr>
<tr>
<td><hr /></td>
</tr>
</table>
C#
<table width="100%" cellspacing="0" cellpadding="0" border="0" class="header">
<tr>
<td class="title">Switchable Themes Example</td>
</tr>
<tr>
<td><hr /></td>
</tr>
<tr>
<td>
<asp:contentplaceholder id="ContentPlaceHolder1" runat="server">
</asp:contentplaceholder>
</td>
</tr>
<tr>
<td><hr /></td>
</tr>
</table>

The master page now has a layout that can be applied to the content page (named Home.aspx) that you will create in the
next section.
Creating a Content Page
The master page provides the template for your content. You define content for the master page by creating an ASP.NET page
that is associated with the master page. The content page is a specialized ASP.NET page that contains only the content to be
merged with the master page. In the content page, you add the text and controls that you want to display when users request
that page.
The content page will use the master page you have created and the themes you have yet to finish. The page will use the
master page's content placeholder and have a title, a subtitle, and a drop-down list. Because the page will be using a master
page, it must contain a MasterPageFile attribute in the @ Page directive, as well as the content placeholder.
To create the content page
1. In Solution Explorer, right-click the name of your Web site, and click Add New Item.
2. Under Visual Studio installed templates, click Web Form.
3. In the Name box, type Home.
4. In the Language list, click the programming language you prefer.
5. Select the Select master page check box, and then click Add.
The Select a Master Page dialog box appears.
6. Click Master1.master, and then click OK.
A new file called Home.aspx is created. The page contains an @ Page directive that attaches the current page to the
selected master page with the MasterPageFile attribute, as shown in the following example.
VB
<%@ Page Language="VB" MasterPageFile="~/Master1.master" ... %>

C#
<%@ Page Language="C#" MasterPageFile="~/Master1.master" ... %>

The page also contains an <asp:Content> element that you will work with next.
Adding Content to the Content Page
A content page does not have the usual elements that make up an ASP.NET page, such as <html>, <body>, or <form>
elements. Instead, you add only the content that you want to display on the master page by replacing the placeholder regions
you created in the master page. For this example, you can add a heading 1 element, a heading 2 element, a paragraph element,
and a drop-down list. You will use the drop-down list to select a theme to apply to the page.
To add content to the home page
1. Paste the following code between the <asp:Content> beginning and ending tags. The following example creates three
HTML elements: a heading 1, a heading 2, and a paragraph. It also adds a drop-down list control. Note that you could
also add the control to the page in Design view if you prefer.

<h1 id="title1">Switchable Themes on a Page</h1><br />


<h2 id="title2">Note how the master page content and the page content are affected
</h2>
<p>Select a color from the drop-down list below to change the appearance of this p
age.</p>
<br /><br />
<asp:dropdownlist id="ddlThemes" runat="server" autopostback="true" >
<asp:listitem value="Blue">I'd like the page to be blue!</asp:listitem>
<asp:listitem value="Red">I'd like the page to be red!</asp:listitem>
<asp:listitem value="Green">I'd like the page to be green!</asp:listitem>
</asp:dropdownlist>

2. Add a script section that will run the code that loads the theme when it is selected from the drop-down list. The following
example and the <script> tags should be added to the content page on the line after the @ Page directive.
VB
<script runat="server">
Public Sub Page_PreInit()
' Sets the Theme for the page.
Me.Theme = "Blue"
If ((Not (Request.Form) Is Nothing) _
AndAlso (Request.Form.Count > 0)) Then
Me.Theme = Me.Request.Form(4).Trim
End If
End Sub
</script>

C#
<script runat="server">
public void Page_PreInit()
{
// Sets the Theme for the page.
this.Theme = "Blue";
if (Request.Form != null && Request.Form.Count > 0)
this.Theme = this.Request.Form[4].Trim();
}
</script>

The theme is loaded during the PreInit event of the page life cycle. The page request form contains an array of values,
and the value at index 4 is the value selected from the drop-down list. This value is assigned to the theme of the page,
and when the page is loaded, the new theme is applied.
The next step in the walkthrough is to create several themes you can use to show that a different theme is being applied.
Editing the Blue Theme
The Blue theme contains an empty style sheet and an empty skin. Because you know what elements make up the default page
and the master page it uses, you can now edit the theme files to add color to the page elements.
To edit the Blue theme
1. Open the Default.skin file from the Blue theme folder in Source view.
2. Add the following code to the drop-down list to designate the page colors when the Blue theme is selected.

<asp:dropdownlist runat="server" ForeColor="white" BackColor="Blue" />

3. Open the Default.css file from the Blue folder in Source view. First, add the following code to format the table title from
the master page.

td.title
{
font-size: 1em;
text-align: center;
font-family: verdana;
font-size: x-large;
font-weight: bolder;
color: Navy;
}

4. Next, add a background color to the table with the following code.

table.header
{
background-color: Blue;
}

5. Next, style the heading 1 and heading 2 elements in the content page.

h1
{
font-size: large;
color: Navy;
}

h2
{
font-family: Verdana;
font-size: medium;
margin-top: 30;
color: Navy;
}

6. Finally, style the horizontal rule and the paragraph element.

p
{
font-family: Verdana;
font-size: small;
color: Aqua;
text-align: left;
}

hr
{
border: 0;
border-top: 2px solid Aqua;
height: 2px;
}

Connecting the Themes to the Page


Before you can see the theme applied to the Home.aspx page, you need to add an attribute to the @ Page directive that
indicates that the page uses a theme.
To connect a page to a theme
1. Open Home.aspx in Source view.
2. Add the StylesheetTheme attribute to the @ Page directive and set it to equal the Blue theme. The page directive should
look like the following example.
VB
<%@ Page Language="VB" MasterPageFile="~/switchtheme.master" Title="Switchable Themes"
StylesheetTheme="Blue" %>

C#
<%@ Page Language="C#" MasterPageFile="~/switchtheme.master" Title="Switchable Themes"
StylesheetTheme="Blue" %>

Testing the Page


You can test the page by running it as you would any ASP.NET page.
To test the page
While viewing the Home.aspx page, press CTRL+F5 to run the page.
ASP.NET merges the content in the Home.aspx page and the layout in the Master1.master page into a single page, and
then applies the Blue theme and displays the resulting page in the browser. Note that the Blue theme has been applied to
the HTML elements and the drop-down list as well as the title and background defined in the master file.
Creating Additional Themes
The Blue theme is fine, but the purpose of this walkthrough is to give the page user several options for a theme. You can copy
the skin and style sheet files into new theme directories, and then edit the colors used in the theme to reflect the new theme
colors. The following procedure creates two new themes, called Red and Green.
To create additional themes
1. In Solution Explorer, right-click the App_Themes folder, click Add ASP.NET Folder, and then click Theme. With the
folder title Theme1 selected, type Red and press ENTER.
2. Open the Blue folder and select the Default.skin and Default.css files. Right-click the two selected files, and then click
Copy.
3. Right-click the Red folder, and then click Paste.
4. Repeat step 1, but name the new theme folder Green. Then, right-click the Green folder and click Paste, placing copies
of the Default.skin and Default.css files into the Green folder.
5. Edit the color attribute in the skin file to reflect the theme color. For example, the skin file in the Red theme should look
like the following example.

<asp:dropdownlist runat="server" ForeColor="white" BackColor="Red" />

6. Edit the style sheet for each theme to reflect the theme's name. Note that you will want to use several shades of green for
the various HTML elements and text to show up against the background. The style sheet for the Green theme might look
like the following example.

p
{
font-family: Verdana;
font-size: small;
color: Teal;
text-align: left;
}

hr
{
border: 0;
border-top: 2px solid Teal;
height: 2px;
}

h1
{
font-size: large;
color: Green;
}

h2
{
font-family: Verdana;
font-size: medium;
margin-top: 30;
color: Green;
}

table.header
{
background-color: Lime;
}

td.title
{
font-size: 1em;
text-align: center;
font-family: verdana;
font-size: x-large;
font-weight: bolder;
color: Teal;
}

Testing the Theme Selection


The drop-down list can now be used to select among the three themes for the page.
To select different themes
1. Switch to the Home.aspx page, and then press CTRL+F5.
2. Select either Green or Red from the drop-down list.
Note that the style sheet is applied to the HTML elements of the page and the skin is applied to the drop-down list
control.
Next Steps
For more information about using master pages, see
Walkthrough: Creating and Using ASP.NET Master Pages in Visual Web Developer.
See Also
Tasks
How to: Define ASP.NET Themes
How to: Apply ASP.NET Themes
Concepts
ASP.NET Master Pages Overview
Visual Web Developer

ASP.NET Web Parts in Visual Studio


ASP.NET Web parts is an integrated set of controls for creating Web sites that enable end users to modify the content,
appearance, and behavior of Web pages directly from a browser. The topics in this section provide information on what Web
parts are, how they work, and how to use them to create ASP.NET Web pages that users can customize.
In This Section
Getting Started - Customizing Web Pages with Web Parts
Learning More - Customizing Web Pages with Web Parts
Walkthrough Topics — Customizing Web Pages with Web Parts
How-to Topics — Customizing Web Pages with Web Parts
See Also
Other Resources
ASP.NET Web Pages (Visual Studio)
ASP.NET Web Sites (Visual Studio)
ASP.NET Web Server Controls (Visual Studio)
Web Page Designer
Visual Web Developer

Getting Started - Customizing Web Pages with Web Parts


The topics in this section provide essential information on ASP.NET Web Parts, an integrated set of controls for creating Web
sites. These controls enable end users to modify a site's content, appearance, and behavior directly from a browser.
In This Section
ASP.NET Web Parts Overview
Walkthrough: Creating a Web Parts Page in Visual Web Developer
Web Parts Control Set Overview
Web Parts Page Display Modes
Walkthrough: Changing Display Modes on a Web Parts Page
Web Parts Personalization
See Also
Other Resources
ASP.NET Web Parts in Visual Studio
ASP.NET Web Sites (Visual Studio)
ASP.NET Web Pages (Visual Studio)
ASP.NET

ASP.NET Web Parts Overview


ASP.NET Web Parts is an integrated set of controls for creating Web sites that enable end users to modify the content,
appearance, and behavior of Web pages directly from a browser. The modifications can be applied to all users on the site or to
individual users. When users modify pages and controls, the settings can be saved to retain a user's personal preferences
across future browser sessions, a feature called personalization. These Web Parts capabilities mean that developers can
empower end users to personalize a Web application dynamically, without developer or administrator intervention.
Using the Web Parts control set, you as a developer can enable end users to:
Personalize page content. Users can add new Web Parts controls to a page, remove them, hide them, or minimize them
like ordinary windows.
Personalize page layout. Users can drag a Web Parts control to a different zone on a page, or change its appearance,
properties, and behavior.
Export and import controls. Users can import or export Web Parts control settings for use in other pages or sites,
retaining the properties, appearance, and even the data in the controls. This reduces data entry and configuration
demands on end users.
Create connections. Users can establish connections between controls so that, for example, a chart control could display a
graph for the data in a stock ticker control. Users could personalize not only the connection itself, but the appearance and
details of how the chart control displays the data.
Manage and personalize site-level settings. Authorized users can configure site-level settings, determine who can access
a site or page, set role-based access to controls, and so on. For example, a user in an administrative role could set a Web
Parts control to be shared by all users, and prevent users who are not administrators from personalizing the shared
control.
Web Parts Essentials
The Web Parts control set consists of three main building blocks: personalization, user interface (UI) structural components,
and actual Web Parts UI controls. For more details, see Web Parts Control Set Overview. Much of your development effort will
focus on Web Parts controls, which are simply ASP.NET controls that can use the features of the Web Parts control set.
As an example of how Web Parts controls can be used to build personalizable Web pages, examine the following screen shot.
Typical Web Parts page

This page contains several basic elements of a Web Parts application:


Use of zones for page layout. There are two columns that can contain controls: one has the Weather and Stock Quotes
controls, the other has Hotmail and News controls. These columns in Web Parts terminology are called zones--regions
on a page that contain Web Parts controls. Zones exist to lay out Web Parts controls on a page, and to provide a common
UI for the controls. There can be one or many zones on a page, each zone can contain one or many Web Parts controls,
and each zone can have a vertical or horizontal orientation for page layout.
Web Parts controls within the zones. Each control has UI verbs (actions that a user can perform) that can appear as links,
buttons, or clickable images on the control. In the preceding screen shot, notice that each control has a button in its title
bar that exposes a drop-down menu. In the menus for each control are options to change details particular to that
control, and other options to carry out common actions such as moving or deleting a control, and getting help. Some
controls, such as the Weather control, allow users to personalize them so the controls display only information relevant
to the user.
Links to enable extensive personalization. These allow users to change the content, color, and layout of the page. For
instance, if users click the Add Column link, a Web Parts application could enable them to add another column to a
page. Or users could click the Add Content link, which displays a catalog of controls that that they can optionally add to
the page. One of those could be a stock charting control. A user could add that control to one of the zones on the page,
and could then connect it to the existing Stock Quotes control to chart the stock data it contains.
Developer Scenarios for Using Web Parts
You will typically work with Web Parts in one of three ways: creating pages that use Web Parts controls, creating individual
Web Parts controls, or creating complete, personalizable Web applications, such as a portal.
Page Development
Page developers can use visual design tools such as Microsoft Visual Studio 2005 to create pages that use Web Parts. One
advantage in using a tool such as Visual Studio is that the Web Parts control set provides features for drag-and-drop creation
and configuration of Web Parts controls in a visual designer. For example, you can use the designer to drag a Web Parts zone,
or a Web Parts editor control, onto the design surface, and then configure the control right in the designer using the UI
provided by the Web Parts control set. This can speed development of Web Parts applications and reduce the amount of code
you have to write.
Control Development
You can use any existing ASP.NET control as a Web Parts control, including standard Web server controls, custom server
controls, and user controls. For maximum programmatic control of your environment, you can also create custom Web Parts
controls that derive from the WebPart class. For individual Web Parts control development, you will typically either create a
user control and use it as a Web Parts control, or develop a custom Web Parts control.
As an example of developing a custom Web Parts control, you could create a control to provide any of the features provided by
other ASP.NET server controls that might be useful to package as a personalizable Web Parts control: calendars, lists, financial
information, news, calculators, rich text controls for updating content, editable grids that connect to databases, charts that
dynamically update their displays, or weather and travel information. If you provide a visual designer with your control, then
any page developer using Visual Studio can simply drag your control into a Web Parts zone and configure it at design time
without having to write additional code.
Web Application Development
Developing fully integrated and personalizable Web applications--such as a portal-- involves the most comprehensive use of
Web Parts. You can develop a Web site that allows extensive user personalization of the UI and content--with features similar
to MSN. Or you can even develop a packaged application that can be shipped and used by companies or fee-based ISPs that
provide portal hosting services.
In a Web application scenario, you could offer a complete solution for end users to manage and personalize the application.
This could include a set of Web Parts controls that provide the desired features for the site, a consistent set of themes and
styles that allow end users to personalize the UI in a consistent way, catalogs of Web Parts controls from which users can select
the ones they want to appear on a page, authentication services, and role-based management (for example, allowing
administrative users to personalize Web Parts controls and site settings for all users).
For each part of your application, you can extend the Web Parts control set as needed to provide greater control over the
environment. For example, besides authoring custom Web Parts controls for the primary UI of your pages, you might also
want to develop a custom Web Parts catalog that is consistent with the look and feel of your application, and gives users more
flexibility to choose how controls are added to a page. Or you could extend a zone control to provide additional UI options for
the Web Parts controls it contains. You could also write a custom personalization provider to give more flexibility and control
over how the personalization data is stored and managed.
See Also
Tasks
Walkthrough: Creating a Web Parts Page
Walkthrough: Creating a Web Parts Page in Visual Studio
Reference
Web Parts Control Set Overview
System.Web.UI.WebControls.WebParts
Concepts
Web Parts Personalization Overview
ASP.NET

ASP.NET Web Parts Life Cycle


When controls from the ASP.NET Web Parts integrated set of controls are included within a Web page, they obey that page's
rules; in particular, they operate within the page's life cycle.
A Web page goes through a life cycle in which it performs a series of processing steps. These steps include initialization,
control creation, restoring and maintaining state, running event handler code, and rendering. It is important for you to
understand the page life cycle and how it applies to Web Parts so you can implement your logic at the appropriate phase in the
cycle. In particular, you must familiarize yourself with the page life cycle to properly initialize the Web Parts controls, populate
properties with personalization data, and run any behavior logic.
Web Parts Life Cycle Phases
This section provides detailed information about the Web Parts life cycle phases, as shown in the following illustration.
Web Parts Life Cycle

Initialization
The following main tasks are performed during the initialization phase:
The WebPartZone objects register with the WebPartManager control.
The WebPartManager control loads the static WebPart objects.
The WebPartManager control subscribes to the control life cycle events.
The WebPartManager control calls the TrackViewState method for each static WebPart object already in the control
hierarchy at this point.
If you need to programmatically set the properties for a GenericWebPart control, you should do it during this phase so that
these properties are available at the proper time, for example when personalization is loaded.
Initialization Complete
The following main tasks are performed during this phase:
The WebPartManager control loads the dynamic WebPart objects and the WebPartConnection objects.
Note
When the WebPartManager control loads the dynamic WebPart objects, each of them must be brought to the same
state conditions in which the other parts are. This synchronization causes the TrackViewState method to be called on
each dynamic WebPart object.

The WebPartManager control calls the WebPartPersonalization control on the static and dynamic WebPart objects.
Load Complete
The following main task is performed during this phase:
Note
During the load complete phase, you can set the values of properties that are not marked as personalizable. At this stage, the
WebPartManager control performs some final initialization on the Web Parts controls it manages.

Save State Complete


The following main tasks are performed during this phase:
The WebPartManager control extracts the personalization information from the static and dynamic WebPart objects.
The WebPartManager control saves the static and dynamic WebPart objects' personalization information in
permanent storage.
See Also
Tasks
Walkthrough: Creating a Web Parts Page
Walkthrough: Creating a Web Parts Page in Visual Studio
Reference
Web Parts Control Set Overview
System.Web.UI.WebControls.WebParts
WebPartManager
WebPart
WebPartZone
WebPartConnection
Concepts
Web Parts Personalization Overview
ASP.NET Page Life Cycle Overview
ASP.NET Application Life Cycle Overview
Visual Web Developer

Walkthrough: Creating a Web Parts Page in Visual Web


Developer
This walkthrough is a hands-on demonstration of the essential components and tasks for creating Web pages that use Web
Parts controls in a visual page design tool such as Microsoft Visual Studio.
In many Web applications it is useful to be able to change the appearance of the content, as well as to allow users to select and
arrange the content they want to see. ASP.NET Web Parts enable you to create Web pages that present modular content and
that enable users to change the appearance and content to suit their preferences. For a general introduction to Web Parts, see
ASP.NET Web Parts Overview. For an overview of the Web Parts control set, see Web Parts Control Set Overview.
During this walkthrough, you create a page that uses Web Parts controls to create a Web page that user can modify, or
personalize. Tasks illustrated in this walkthrough include:
Adding Web Parts controls to a page.
Creating a custom user control and using it as a Web Parts control.
Allowing users to personalize the layout of the Web Parts controls on the page.
Allowing users to edit the appearance of a Web Parts control.
Allowing users to select from a catalog of available Web Parts controls.
Prerequisites
In order to complete this walkthrough, you will need:
A site that can identify individual users. If you have a site already configured with ASP.NET membership, you can use that
site for this walkthrough. Otherwise, the walkthrough provides instructions on how to configure your site to identify you
by your Windows user account name.
A visual design environment for creating Web pages. This walkthrough uses Visual Studio.
A configured personalization provider and database. Web Parts personalization is enabled by default, and it uses the SQL
personalization provider (SqlPersonalizationProvider) with Microsoft SQL Server Express Edition to store personalization
data. This walkthrough uses SQL Server Express and the default SQL provider. If you have SQL Server Express installed,
no configuration is needed. SQL Server Express is available with Microsoft Visual Studio 2005 as an optional part of the
installation, or as a free download from Microsoft.com. To use a full version of SQL Server, you must install and configure
an ASP.NET application services database, and configure the SQL personalization provider to connect to that database.
For details, see Creating and Configuring the Application Services Database for SQL Server.
Creating and Configuring the Web Site
This walkthrough requires that you have a user identity, so that your Web Parts settings can be keyed to you. If you already
have a Web site configured to use membership, it is recommended that you use that site. Otherwise, you can create a new site
and use your current Windows user name as your user identity.
To create a new Web site
In Visual Studio, create a new ASP.NET Web site. For details, see
Walkthrough: Creating a Web Site with Membership and User Login (Visual Studio).
Creating a Simple Page with Web Parts
In this part of the walkthrough, you create a page that uses Web Parts controls to show static content. The first step in working
with Web Parts is to create a page with two required elements. First, a Web parts page needs a WebPartManager control to
coordinate all Web Parts controls. Second, a Web Parts page needs one or more zones, which are composite controls that
contain WebPart or other server controls and occupy a specified region of a page.
Note
You do not need to do anything to enable Web Parts personalization; it is enabled by default for the Web Parts control set. W
hen you first run a Web Parts page on a site, ASP.NET sets up a default personalization provider to store user personalization
settings. For more information about personalization, see Web Parts Personalization Overview.

To create a page for containing Web Parts controls


1. Close the default page and add a new page named WebPartsDemo.aspx.
2. Switch to Design view.
3. From the View menu, make sure that the Non-Visual Controls and Details options are selected so you can see layout
tags and controls that do not have a UI.
4. Place the insertion point before the <div> tags on the design surface, and press ENTER to add a new line.
5. Position the insertion point before the new line character. From the Block Format list in the toolbar, select Heading 1
and in the heading, add the text Web Parts Demonstration Page.
6. From the WebParts tab of the Toolbox, drag a WebPartManager control onto the page, between the new line character
and the opening <div> tag.
The WebPartManager control does not render any output, so it appears as a gray box on the designer surface.
7. Position the insertion point within the <div> tags.
8. In the Layout menu, click Insert Table, and create a new table that has one row and three columns. Click the Cell
Properties button, select top from the Vertical align drop-down list, click OK, and click OK again to create the table.
9. Drag a WebPartZone control into the left table column. Right-click the WebPartZone control, choose Properties, and
set the following properties:
ID: SidebarZone

HeaderText: Sidebar

10. Drag a second WebPartZone control into the middle table column and set the following properties:
ID: MainZone

HeaderText: Main

11. Save the file.


Your page now has two distinct zones that you can control separately. However, neither zone has any content, so creating
content is the next step. For this walkthrough, you work with Web Parts controls that display only static content.
The layout of a Web Parts zone is specified by a <zonetemplate> element. Inside the zone template, you can add any
ASP.NET control, whether it is a custom Web Parts control, a user control, or an existing server control. Notice that here you are
using the Label control, and to that you are simply adding static text. When you place a regular server control in a
WebPartZone zone, ASP.NET treats the control as a Web Parts control at run time, which enables Web Parts features on the
control.
To create content for the main zone
1. In Design view, drag a Label control from the Standard tab of the Toolbox into the contents area of the zone whose ID
property is set to MainZone.
2. Switch to Source view.
Notice that a <zonetemplate> element was added to wrap the Label control in the MainZone.
3. Add an attribute named title to the <asp:label> element, and set its value to Content. Remove the Text="Label"
attribute from the <asp:label> element. Inside the <asp:label> element, add some text such as <h2>Welcome to my
Home Page</h2>. Your code should look as follows:

<asp:webpartzone id="MainZone" runat="server" headertext="Main">


<zonetemplate>
<asp:label id="Label1" runat="server" title="Content">
<h2>Welcome to My Home Page</h2>
</asp:label>
</zonetemplate>
</asp:webpartzone>

4. Save the file.


Next, create a user control that can also be added to the page as a Web Parts control.
To create a user control
1. Add a new Web user control to your site to serve as a search control named SearchUserControl.ascx, making sure that
the Place source code in a separate file is cleared.
Note
The user control for this walkthrough does not implement actual search functionality; it is used only to demonstrate W
eb Parts features.

2. Switch to Design view.


3. From the Standard tab of the Toolbox, drag a TextBox control onto the page.
4. Place the insertion point after the text box you just added, and press ENTER to add a new line.
5. Drag a Button control onto the page on the new line below the text box you just added.
6. Switch to Source view and then ensure that the source code for the user control looks like the following example:
VB
<%@ control language="VB" classname="SearchUserControl" %>
<asp:textbox runat="server" id="TextBox1"></asp:textbox>
<br />
<asp:button runat="server" id="Button1" text="Search" />

C#
<%@ control language="C#" classname="SearchUserControl" %>
<asp:textbox runat="server" id=" TextBox1"></asp:textbox>
<br />
<asp:button runat="server" id=" Button1" text="Search" />

7. Save and close the file.


Security Note
This control has a textbox that accepts user input, which is a potential security threat. User input in a Web page can pot
entially contain malicious client script. By default, ASP.NET Web pages validate user input to ensure that the input does
not contain HTML elements or script. As long as this validation is enabled, you do not need to explicitly check for script
or HTML elements in user input. For more information, see Script Exploits Overview.

Now you can add Web Parts controls to the Sidebar zone. You are adding two controls to the Sidebar zone, one containing a
list of links and another that is the user control you created earlier in the walkthrough. The links are added as a standard Label
server control, similar to the way you created the static text for the Main zone. However, although the individual server controls
contained in the user control could be contained directly in the zone (like the label control), in this case they are not. Instead,
they are part of the user control you created in the previous procedure. This demonstrates a common way to package controls
and extra functionality you want in a user control, and then reference that control in a zone as a Web Parts control.
At run time, the Web Parts control set wraps both controls with GenericWebPart controls. When a GenericWebPart control
wraps a Web server control, the generic part control is the parent control, and you can access the server control through the
parent control's ChildControl property. Using generic part controls enables standard Web server controls to have the same
basic behavior and attributes as Web Parts controls that derive from the WebPart class.
To add Web Parts controls to the sidebar zone
1. Open the WebPartsDemo.aspx page.
2. Switch to Design view.
3. Drag the user control page you created, SearchUserControl.ascx, from Solution Explorer into the zone whose ID
property is set to SidebarZone.
4. Save the WebPartsDemo.aspx page.
5. Switch to Source view.
6. Inside the <asp:webpartzone> element for the SidebarZone, add an <asp:label> element that contains links and in the
user control tag, add a Title attribute with a value of Search, as shown in the following example:

<asp:WebPartZone id="SidebarZone" runat="server"


headertext="Sidebar">
<zonetemplate>
<asp:label runat="server" id="linksPart" title="My Links">
<a href="http://www.asp.net">ASP.NET site</a>
<br />
<a href="http://www.gotdotnet.com">GotDotNet</a>
<br />
<a href="http://www.contoso.com">Contoso.com</a>
<br />
</asp:label>
<uc1:SearchUserControl id="searchPart" runat="server"
title="Search" />
</zonetemplate>
</asp:WebPartZone>

7. Save and close the file.


Now you can test your page.
To test the page
Load the page in a browser.
The page displays the two zones. The following screen shot shows the page.
Web Parts Demo page with two zones
In the title bar of each control is a downward arrow that provides access to a verbs menu of available actions you can
perform on a control. Click the verbs menu for one of the controls, then click the Minimize verb and note that the
control is minimized. From the verbs menu, click Restore, and the control returns to its normal size.
Enabling Users to Edit Pages and Change Layout
Web Parts provides the capability for users to change the layout of Web Parts controls by dragging them from one zone to
another. In addition to allowing users to move WebPart controls from one zone to another, you can allow users to edit various
characteristics of the controls, including their appearance, layout, and behavior. The Web Parts control set provides basic
editing functionality for WebPart controls. Although you will not do so in this walkthrough, you can also create custom editor
controls that allow users to edit the features of WebPart controls. As with changing the location of a WebPart control, editing
a control's properties relies on ASP.NET personalization to save the changes that users make.
In this part of the walkthrough, you add the ability for users to edit the basic characteristics of any WebPart control on the
page. To enable these features, you add another custom user control to the page, along with an <asp:editorzone> element
and two editing controls.
To create a user control that enables changing page layout
1. In Visual Studio, on the File menu, click New, and then click File.
2. In the Add New Item dialog, select Web User Control. Name the new file DisplayModeMenu.ascx. Clear the Place
source code in separate file box.
3. Click Add to create the new control.
4. Switch to Source view.
5. Remove all the existing code in the new file, and paste in the following code. This user control code uses features of the
Web Parts control set that enable a page to change its view or display mode, and also enables you to change the physical
appearance and layout of the page while you are in certain display modes.
VB
<%@ control language="vb" classname="DisplayModeMenuVB"%>
<script runat="server">
' Use a field to reference the current WebPartManager control.
Dim _manager As WebPartManager

Sub Page_Init(ByVal sender As Object, ByVal e As EventArgs)


AddHandler Page.InitComplete, AddressOf InitComplete
End Sub

Sub InitComplete(ByVal sender As Object, ByVal e As System.EventArgs)


_manager = WebPartManager.GetCurrentWebPartManager(Page)

Dim browseModeName As String = _


WebPartManager.BrowseDisplayMode.Name
' Fill the drop-down list with the names of supported display modes.
Dim mode As WebPartDisplayMode
For Each mode In _manager.SupportedDisplayModes
Dim modeName As String = mode.Name
' Make sure a mode is enabled before adding it.
If mode.IsEnabled(_manager) Then
Dim item As New ListItem(modeName, modeName)
DisplayModeDropdown.Items.Add(item)
End If
Next mode

' If Shared scope is allowed for this user, display the


' scope-switching UI and select the appropriate radio button
' for the current user scope.
If _manager.Personalization.CanEnterSharedScope Then
Panel2.Visible = True
If _manager.Personalization.Scope = _
PersonalizationScope.User Then
RadioButton1.Checked = True
Else
RadioButton2.Checked = True
End If
End If
End Sub

' Change the page to the selected display mode.


Sub DisplayModeDropdown_SelectedIndexChanged(ByVal sender As Object, _
ByVal e As EventArgs)

Dim selectedMode As String = DisplayModeDropdown.SelectedValue


Dim mode As WebPartDisplayMode = _
_manager.SupportedDisplayModes(selectedMode)
If Not (mode Is Nothing) Then
_manager.DisplayMode = mode
End If
End Sub

' Set the selected item equal to the current display mode.
Sub Page_PreRender(ByVal sender As Object, ByVal e As EventArgs)
Dim items As ListItemCollection = DisplayModeDropdown.Items
Dim selectedIndex As Integer = _
items.IndexOf(items.FindByText(_manager.DisplayMode.Name))
DisplayModeDropdown.SelectedIndex = selectedIndex
End Sub

' Reset all of a user's personalization data for the page.


Protected Sub LinkButton1_Click(ByVal sender As Object, _
ByVal e As EventArgs)

_manager.Personalization.ResetPersonalizationState()

End Sub

' If not in User personalization scope, toggle into it.


Protected Sub RadioButton1_CheckedChanged(ByVal sender As _
Object, ByVal e As EventArgs)
If _manager.Personalization.Scope = _
PersonalizationScope.Shared Then
_manager.Personalization.ToggleScope()
End If
End Sub

' If not in Shared scope, and if user has permission, toggle the
' scope.
Protected Sub RadioButton2_CheckedChanged(ByVal sender As _
Object, ByVal e As EventArgs)
If _manager.Personalization.CanEnterSharedScope AndAlso _
_manager.Personalization.Scope = _
PersonalizationScope.User Then
_manager.Personalization.ToggleScope()
End If
End Sub

</script>
<div>
<asp:Panel ID="Panel1" runat="server"
Borderwidth="1"
Width="230"
BackColor="lightgray"
Font-Names="Verdana, Arial, Sans Serif" >
<asp:Label ID="Label1" runat="server"
Text="&nbsp;Display Mode"
Font-Bold="true"
Font-Size="8"
Width="120" />
<asp:DropDownList ID="DisplayModeDropdown" runat="server"
AutoPostBack="true"
Width="120"
OnSelectedIndexChanged="DisplayModeDropdown_SelectedIndexChanged" />
<asp:LinkButton ID="LinkButton1" runat="server"
Text="Reset User State"
ToolTip="Reset the current user's personalization data for
the page."
Font-Size="8"
OnClick="LinkButton1_Click" />
<asp:Panel ID="Panel2" runat="server"
GroupingText="Personalization Scope"
Font-Bold="true"
Font-Size="8"
Visible="false" >
<asp:RadioButton ID="RadioButton1" runat="server"
Text="User"
AutoPostBack="true"
GroupName="Scope"
OnCheckedChanged="RadioButton1_CheckedChanged" />
<asp:RadioButton ID="RadioButton2" runat="server"
Text="Shared"
AutoPostBack="true"
GroupName="Scope"
OnCheckedChanged="RadioButton2_CheckedChanged" />
</asp:Panel>
</asp:Panel>
</div>

C#
<%@ control language="C#" classname="DisplayModeMenuCS"%>
<script runat="server">

// Use a field to reference the current WebPartManager control.


WebPartManager _manager;

void Page_Init(object sender, EventArgs e)


{
Page.InitComplete += new EventHandler(InitComplete);
}

void InitComplete(object sender, System.EventArgs e)


{
_manager = WebPartManager.GetCurrentWebPartManager(Page);

String browseModeName = WebPartManager.BrowseDisplayMode.Name;

// Fill the drop-down list with the names of supported display modes.
foreach (WebPartDisplayMode mode in
_manager.SupportedDisplayModes)
{
String modeName = mode.Name;
// Make sure a mode is enabled before adding it.
if (mode.IsEnabled(_manager))
{
ListItem item = new ListItem(modeName, modeName);
DisplayModeDropdown.Items.Add(item);
}
}

// If Shared scope is allowed for this user, display the


// scope-switching UI and select the appropriate radio
// button for the current user scope.
if (_manager.Personalization.CanEnterSharedScope)
{
Panel2.Visible = true;
if (_manager.Personalization.Scope ==
PersonalizationScope.User)
RadioButton1.Checked = true;
else
RadioButton2.Checked = true;
}
}

// Change the page to the selected display mode.


void DisplayModeDropdown_SelectedIndexChanged(object sender,
EventArgs e)
{
String selectedMode = DisplayModeDropdown.SelectedValue;

WebPartDisplayMode mode =
_manager.SupportedDisplayModes[selectedMode];
if (mode != null)
_manager.DisplayMode = mode;
}

// Set the selected item equal to the current display mode.


void Page_PreRender(object sender, EventArgs e)
{
ListItemCollection items = DisplayModeDropdown.Items;
int selectedIndex =
items.IndexOf(items.FindByText(_manager.DisplayMode.Name));
DisplayModeDropdown.SelectedIndex = selectedIndex;
}

// Reset all of a user's personalization data for the page.


protected void LinkButton1_Click(object sender, EventArgs e)
{
_manager.Personalization.ResetPersonalizationState();
}

// If not in User personalization scope, toggle into it.


protected void RadioButton1_CheckedChanged(object sender, EventArgs e)
{
if (_manager.Personalization.Scope ==
PersonalizationScope.Shared)
_manager.Personalization.ToggleScope();
}

// If not in Shared scope, and if user has permission, toggle


// the scope.
protected void RadioButton2_CheckedChanged(object sender,
EventArgs e)
{
if (_manager.Personalization.CanEnterSharedScope &&
_manager.Personalization.Scope ==
PersonalizationScope.User)
_manager.Personalization.ToggleScope();
}
</script>
<div>
<asp:Panel ID="Panel1" runat="server"
Borderwidth="1"
Width="230"
BackColor="lightgray"
Font-Names="Verdana, Arial, Sans Serif" >
<asp:Label ID="Label1" runat="server"
Text="&nbsp;Display Mode"
Font-Bold="true"
Font-Size="8"
Width="120" />
<asp:DropDownList ID="DisplayModeDropdown" runat="server"
AutoPostBack="true"
Width="120"
OnSelectedIndexChanged="DisplayModeDropdown_SelectedIndexChanged" />
<asp:LinkButton ID="LinkButton1" runat="server"
Text="Reset User State"
ToolTip="Reset the current user's personalization data for
the page."
Font-Size="8"
OnClick="LinkButton1_Click" />
<asp:Panel ID="Panel2" runat="server"
GroupingText="Personalization Scope"
Font-Bold="true"
Font-Size="8"
Visible="false" >
<asp:RadioButton ID="RadioButton1" runat="server"
Text="User"
AutoPostBack="true"
GroupName="Scope"
OnCheckedChanged="RadioButton1_CheckedChanged" />
<asp:RadioButton ID="RadioButton2" runat="server"
Text="Shared"
AutoPostBack="true"
GroupName="Scope"
OnCheckedChanged="RadioButton2_CheckedChanged" />
</asp:Panel>
</asp:Panel>
</div>

6. Save the file.


Note
Although this user control can enable users of the Web Parts page to toggle between shared and user-personalization
mode, this feature requires the user to have appropriate permissions, as specified in the Web.config file. This walkthrou
gh does not illustrate how to grant these rights, so the feature is not enabled. Therefore, the user and shared radio butt
ons on the user control are hidden when you run the page. For more information on personalization, see
Web Parts Personalization.

To enable users to change the layout


1. Open the WebPartsDemo.aspx page.
2. Switch to Design view.
3. Position the insertion point just after the WebPartManager control that you added earlier. Press ENTER to create a
blank line after the WebPartManager control.
4. Drag the user control you just created (DisplayModeMenu.ascx) into the WebPartsDemo.aspx page and drop it on the
blank line.
5. Drag an EditorZone control from the WebParts tab of the Toolbox to the remaining open table cell in the
WebPartsDemo.aspx page.

6. From the WebParts tab of the Toolbox, drag an AppearanceEditorPart control and a LayoutEditorPart control into the
EditorZone control.
7. Switch to Source view.
The resulting code in the table cell will look similar to the following code.

<td valign="top">
<asp:EditorZone ID="EditorZone1" runat="server">
<ZoneTemplate>
<asp:AppearanceEditorPart ID="AppearanceEditorPart1"
runat="server" />
<asp:LayoutEditorPart ID="LayoutEditorPart1" runat="server" />
</ZoneTemplate>
</asp:EditorZone>
</td>

Note
Although the AppearanceEditorPart and LayoutEditorPart controls are used in this walkthrough, the
BehaviorEditorPart and PropertyGridEditorPart controls are not, because they require setup beyond the scope of this w
alkthrough.

8. Save the WebPartsDemo.aspx file.


You have created a user control that allows you to change display modes and change page layout, and you have referenced the
control on the primary Web page.
You can now test the capability to edit pages and change layout.
To test layout changes
1. Load the page in a browser.
2. In the Display Mode menu, click Edit.
The zone titles are displayed.
3. Drag the My Links control by its title bar from the Sidebar zone to the bottom of the Main zone.
The page will look like the following:
Web Parts Demo page with My Links control moved

4. Click Display Mode, and then click Browse.


The page is refreshed, the zone names disappear, and the My Links control remains where you positioned it.
5. To demonstrate that personalization is working, close the browser, and then load the page again. The changes you made
are saved for future browser sessions.
6. In the Display Mode menu, click Edit.
Each control on the page is now displayed with a downward arrow in its title bar, which contains the verbs drop-down
menu.
7. Click the arrow to display the verbs menu on the My Links control and then click Edit.
The EditorZone control appears, displaying the EditorPart controls you added.
8. In the Appearance section of the edit control, change the Title to My Favorites. In the Chrome Type list, select Title
Only, and then click Apply.
The following screen shot shows the page in edit mode.
Web Parts Demo page in Edit mode
9. In the Display Mode menu, click Browse to return to browse mode.
The control now has an updated title and no border, as shown in the following screen shot.
Edited Web Parts Demo page

Adding Web Parts at Run Time


You can also enable users to add Web Parts controls to their page at run time. To do so, configure the page with a Web Parts
catalog, which contains a list of Web Parts controls that you want to make available to users.
Note
In this walkthrough, you create a template containing FileUpload and Calendar controls. This will allow you to test the basic f
unctionality of the catalog, but the resulting Web Parts controls do not have any real functionality. If you have a custom Web
or user control, you can substitute it for the static content.

To allow users to add Web Parts at run time


1. Open the WebPartsDemo.aspx page.
2. Switch to Design view.
3. From the WebParts tab of the Toolbox, drag a CatalogZone control into the right column of the table, beneath the
EditorZone control.
Both controls can be in the same table cell because they will not be displayed at the same time.
4. In the Properties pane, assign the string Add Web Parts to the HeaderText property of the CatalogZone control.
5. From the WebParts tab of the Toolbox, drag a DeclarativeCatalogPart control into the content area of the CatalogZone
control.
6. Click the arrow in the upper right corner of the DeclarativeCatalogPart control to expose its Tasks menu, and then
select Edit Templates.
7. From the Standard tab of the Toolbox, drag a FileUpload control and a Calendar control into the WebPartsTemplate
section of the DeclarativeCatalogPart control.
8. Switch to Source view and inspect the source code of the <asp:catalogzone> element.
Notice that the DeclarativeCatalogPart control contains a <webpartstemplate> element with the two enclosed
server controls that you will be able to add to your page from the catalog.
Note
If you have a custom control, this is the place to substitute it for one of the server controls in the example, although this
requires steps beyond the scope of this walkthrough. For further details, see the code example in the documentation fo
r the WebPart class.

9. Add a Title property to each of the controls you added to the catalog, using the string value shown for each title in the
code example below. Even though the title is not a property you can normally set on these two server controls at design
time, when a user adds these controls to a WebPartZone zone from the catalog at run time, they are each wrapped with
a GenericWebPart control. This enables them to act as Web Parts controls, so they will be able to display titles.
The code for the two controls contained in the DeclarativeCatalogPart control will look like the following.

<asp:DeclarativeCatalogPart ID="DeclarativeCatalogPart1"
runat="server">
<WebPartsTemplate>
<asp:Calendar ID="Calendar1"
runat="server"
title="My Calendar" />
<asp:FileUpload ID="FileUpload1"
runat="server"
title="Upload Files" />
</WebPartsTemplate>
</asp:DeclarativeCatalogPart>

10. Save the page.


You can now test the catalog.
To test the Web Parts catalog
1. Load the page in a browser.
2. In the Display Mode menu, click Catalog.
The catalog titled Add Web Parts is displayed.
3. Drag the My Favorites control from the Main zone back to the top of the Sidebar zone.
4. In the Add Web Parts catalog, select both check boxes, and then select Main from the list of available zones
5. Click Add in the catalog.
The controls are added to the Main zone. If you want, you can add multiple instances of controls from the catalog to your
page. The following screen shot shows the page with the file upload control and the calendar in the Main zone:
Controls added to Main zone from the catalog
6. In the Display Mode menu, click Browse.
The catalog disappears and the page is refreshed.
7. Close the browser and then Load the page again.
The changes you made persist.
Next Steps
This walkthrough has illustrated the basic principles of using simple Web Parts controls on an ASP.NET Web page. You might
want to experiment with additional, more sophisticated Web Parts features. Suggestions for further exploration include:
Create Web Parts controls that offer more sophisticated functionality than the static Web Parts from this walkthrough.
You can create Web Parts controls as user controls or custom controls. For details, see the documentation for the
WebPart class.
See Also
Tasks
Walkthrough: Creating a Web Parts Page
Reference
Web Parts Control Set Overview
WebPart
Concepts
ASP.NET Web Parts Overview
ASP.NET

Web Parts Control Set Overview


The ASP.NET Web Parts control set is a group of components that work together to enable you to create Web pages on which
end users can modify the appearance and behavior of the user interface (UI) directly from a browser. This overview covers the
fundamental aspects of the Web Parts control set, including a description of the most frequently used and
essential Web Parts components needed to create a Web Parts page.
Categories of Web Parts Components
The Web Parts control set consists of three fundamental building blocks: personalization capabilities, UI structural components
required for using Web Parts UI controls on a page, and the Web Parts UI controls themselves. The following diagram
illustrates the relationships among these building blocks in the Web Parts control set.
Web Parts controls hierarchy

Personalization is the foundation of the Web Parts feature. It enables users to modify--or personalize--the layout, appearance,
and behavior of Web Parts controls on a page. The personalized settings are long-lived: they are persisted not just during the
current browser session (as with view state), but also in long-term storage, so that a user's settings are saved for future
browser sessions as well. Personalization is enabled by default for Web Parts pages. For more details on personalization, see
Web Parts Personalization Overview.
The UI structural components rely on personalization and provide the core structure and services needed by all Web Parts
controls. One UI structural component required on every Web Parts page is the WebPartManager control. Although never
visible, this control has the critical task of coordinating all Web Parts controls on a page. For example, it tracks all the individual
Web Parts controls. It manages Web Parts zones (regions that contain Web Parts controls on a page), and which controls are in
which zones. It also tracks and controls the different display modes a page can be in, such as browse,connect, edit, or catalog
mode, and whether personalization changes apply to all users or to individual users. Finally, it initiates and tracks connections
and communication between Web Parts controls.
The second kind of UI structural component is the zone. Zones act as layout managers on a Web Parts page. They contain and
organize controls that derive from the Part class (part controls), and provide the ability to do modular page layout in either
horizontal or vertical orientation. Zones also offer common and consistent UI elements (such as header and footer style, title,
border style, action buttons, and so on) for each control they contain; these common elements are known as the chrome of a
control. Several specialized types of zones are used in the different display modes and with various controls. The different
types of zones are described in the Web Parts Essential Controls section below.
The Web Parts UI controls, all of which derive from the Part class, comprise the primary UI on a Web Parts page. The Web
Parts control set is flexible and inclusive in the options it gives you for creating part controls. In addition to creating your own
custom Web Parts controls, you can also use existing ASP.NET server controls, user controls, or custom server controls as Web
Parts controls. For more details on the variety of ways in which you can use server controls as Web Parts controls, see
ASP.NET Web Parts Overview. The essential controls that are most commonly used for creating Web Parts pages are described
in the next section.
Web Parts Essential Controls
The Web Parts control set is extensive, but some controls are essential either because they are required for Web Parts to work,
or because they are the controls most frequently used on Web Parts pages. As you begin using Web Parts and creating basic
Web Parts pages, it is helpful to be familiar with the essential Web Parts controls described in the following table.
Web Parts control Description
WebPartManager Manages all Web Parts controls on a page. One (and only one) WebPartManager control is requ
ired for every Web Parts page.
CatalogZone Contains CatalogPart controls. Use this zone to create a catalog of Web Parts controls from which
users can select controls to add to a page.

EditorZone Contains EditorPart controls. Use this zone to enable users to edit and personalize Web Parts cont
rols on a page.
WebPartZone Contains and provides overall layout for the WebPart controls that compose the main UI of a pag
e. Use this zone whenever you create pages with Web Parts controls. Pages can contain one or m
ore zones.

ConnectionsZone Contains WebPartConnection controls, and provides a UI for managing connections..

WebPart Renders the primary UI; most Web Parts UI controls fall into this category.
(GenericWebPart) For maximum programmatic control, you can create custom Web Parts controls that derive from t
he base WebPart control.
You can also use existing server controls, user controls, or custom controls as Web Parts controls.
Whenever any of these controls are placed in a zone, the WebPartManager control automaticall
y wraps them with GenericWebPart controls at run time so that you can use them with Web Part
s functionality.

CatalogPart Contains a list of available Web Parts controls that users can add to the page.

WebPartConnection Creates a connection between two Web Parts controls on a page. The connection defines one of t
he Web Parts controls as a provider (of data), and the other as a consumer.

EditorPart Serves as the base class for the specialized editor controls.

EditorPart controls Allow users to personalize various aspects of Web Parts UI controls on a page.
(AppearanceEditorPart,
LayoutEditorPart,
BehaviorEditorPart, and
PropertyGridEditorPart)
See Also
Tasks
Walkthrough: Creating a Web Parts Page in Visual Studio
Walkthrough: Creating a Web Parts Page
Concepts
ASP.NET Web Parts Overview
Web Parts Personalization Overview
ASP.NET

Web Parts Page Display Modes


An ASP.NET Web Parts page can enter several different display modes. A display mode is a special state that applies to an
entire page, where certain user interface (UI) elements are visible and enabled, while others are invisible and disabled. Display
modes enable end users to perform certain tasks to modify or personalize a page, such as editing Web Parts controls, changing
the layout of a page, or adding new controls from a catalog of available controls.
How Web Parts Display Modes Work
A page can be in only one display mode at a time. The WebPartManager control contains the implementation for the display
modes that are available in the Web Parts control set, and manages all display mode operations for a page.
Typically, you provide a UI that enables users to switch among display modes as needed. You can change a page's display
mode programmatically, using the DisplayMode property. For more information on how to change a page's display mode, see
Walkthrough: Changing Display Modes on a Web Parts Page.
There are five standard display modes in the Web Parts control set: browse (the normal mode in which an end user views a
Web page), design, edit, catalog, and connect. Each of these display modes is derived from the WebPartDisplayMode class. The
following table lists the display modes and summarizes their behavior.
Display mode Description
BrowseDisplayMode Displays Web Parts controls and UI elements in the normal mode in which end users view a page.

DesignDisplayMode Displays zone UI and enables users to drag Web Parts controls to change the layout of a page.

EditDisplayMode Displays editing UI elements and enables end users to edit the controls on a page. Allows dragging of co
ntrols.

CatalogDisplayMode Displays catalog UI elements and enables end users to add and remove page controls. Allows dragging
of controls.

ConnectDisplayMode Displays connections UI elements and enables end users to connect Web Parts controls.

See Also
Tasks
Walkthrough: Creating a Web Parts Page
Walkthrough: Changing Display Modes on a Web Parts Page
How to: Set the Display Mode of a Web Parts Page
Reference
Web Parts Control Set Overview
WebPartDisplayMode
ASP.NET

Walkthrough: Changing Display Modes on a Web Parts Page


This walkthrough illustrates two methods of changing display modes on an ASP.NET Web Parts page, and also demonstrates
how a user navigates between page display modes. During this walkthrough, you will learn how to:
Create a custom user control that enables you to change display modes on a Web page that contains Web Parts controls.
Switch between the various display modes on a Web Parts page.
For more information about display modes and when to use them, see Web Parts Page Display Modes.
Prerequisites
In order to complete this walkthrough, you will need:
Internet Information Services (IIS) installed and configured on the computer that will host the site. For details about
installing and configuring IIS, see the IIS Help documentation included with the installation, or see the online IIS
documentation on the Microsoft TechNet site (Internet Information Services 6.0 Technical Resources).
An ASP.NET Web site that can identify individual users. If you have such a site already configured, you can use that site as
a starting point for this walkthrough. Otherwise, for details on creating a virtual directory or site, see
How to: Create and Configure Virtual Directories in IIS.
A configured personalization provider and database. Web Parts personalization is enabled by default, and it uses the SQL
personalization provider (SqlPersonalizationProvider) with the SQL Server Express (SSE) edition to store personalization
data. This walkthrough uses SSE and the default SQL provider. If you have SSE installed, no configuration is needed. SSE
is available with Microsoft Visual Studio 2005 as an optional part of the installation, or as a free download. For details,
see the Microsoft SQL Server 2005 Express Edition Web page. To use one of the full versions of SQL Server, you must
install and configure an ASP.NET application services database and configure the SQL personalization provider to
connect to that database. For details, see Creating and Configuring the Application Services Database for SQL Server. You
can also create and configure a custom provider to use with other, non-SQL databases or storage solutions. For details
and a code example see Implementing a Membership Provider.
A custom Web Parts control derived from the WebPart class, so that you can add it to the catalog on the Web Parts page.
For an example of a custom WebPart control and how to reference it in a page, see the code example for the
TextDisplayWebPart control in the documentation for the WebPartDisplayMode class.

Creating a User Control to Change Display Modes


In this section you create a user control that can be added to any page containing Web Parts controls, so that users can easily
switch between the various page display modes.
To create a user control to change display modes
1. In a text editor, create a new file.
2. At the top of the file, add a control declaration, as shown in the following code example:
VB
<%@ control language="vb" classname="DisplayModeMenuVB"%>

C#
<%@ control language="C#" classname="DisplayModeMenuCS"%>

3. Beneath the control declaration, add the following markup to the page.
This markup creates the user interface (UI) for the control, which consists of three main parts:
A drop-down list control (an <asp:dropdownlist> element) that enables users to change display modes.
A hyperlink (an <asp:linkbutton> element) that enables a user to reset the user-specific personalization data on
the page, returning the page to its default appearance and layout prior to user modifications.
A pair of radio button controls (two <asp:radiobutton> elements) that enable users to switch between user and
shared personalization scope (user scope is the default). When the current user personalizes the page, the
personalization scope determines what range of users will be able to see the effects of the personalization.
Your code should look like the following block of code:
VB
<div>
<asp:Panel ID="Panel1" runat="server"
Borderwidth="1"
Width="230"
BackColor="lightgray"
Font-Names="Verdana, Arial, Sans Serif" >
<asp:Label ID="Label1" runat="server"
Text="&nbsp;Display Mode"
Font-Bold="true"
Font-Size="8"
Width="120"
AssociatedControlID="DisplayModeDropdown"/>
<asp:DropDownList ID="DisplayModeDropdown" runat="server"
AutoPostBack="true"
Width="120"
OnSelectedIndexChanged="DisplayModeDropdown_SelectedIndexChanged" />
<asp:LinkButton ID="LinkButton1" runat="server"
Text="Reset User State"
ToolTip="Reset the current user's personalization data for the page."
Font-Size="8"
OnClick="LinkButton1_Click" />
<asp:Panel ID="Panel2" runat="server"
GroupingText="Personalization Scope"
Font-Bold="true"
Font-Size="8"
Visible="false" >
<asp:RadioButton ID="RadioButton1" runat="server"
Text="User"
AutoPostBack="true"
GroupName="Scope" OnCheckedChanged="RadioButton1_CheckedChanged" />
<asp:RadioButton ID="RadioButton2" runat="server"
Text="Shared"
AutoPostBack="true"
GroupName="Scope"
OnCheckedChanged="RadioButton2_CheckedChanged" />
</asp:Panel>
</asp:Panel>
</div>

C#
<div>
<asp:Panel ID="Panel1" runat="server"
Borderwidth="1"
Width="230"
BackColor="lightgray"
Font-Names="Verdana, Arial, Sans Serif" >
<asp:Label ID="Label1" runat="server"
Text="&nbsp;Display Mode"
Font-Bold="true"
Font-Size="8"
Width="120"
AssociatedControlID="DisplayModeDropdown"/>
<asp:DropDownList ID="DisplayModeDropdown" runat="server"
AutoPostBack="true"
Width="120"
OnSelectedIndexChanged="DisplayModeDropdown_SelectedIndexChanged" />
<asp:LinkButton ID="LinkButton1" runat="server"
Text="Reset User State"
ToolTip="Reset the current user's personalization data for the page."
Font-Size="8"
OnClick="LinkButton1_Click" />
<asp:Panel ID="Panel2" runat="server"
GroupingText="Personalization Scope"
Font-Bold="true"
Font-Size="8"
Visible="false" >
<asp:RadioButton ID="RadioButton1" runat="server"
Text="User"
AutoPostBack="true"
GroupName="Scope" OnCheckedChanged="RadioButton1_CheckedChanged" />
<asp:RadioButton ID="RadioButton2" runat="server"
Text="Shared"
AutoPostBack="true"
GroupName="Scope"
OnCheckedChanged="RadioButton2_CheckedChanged" />
</asp:Panel>
</asp:Panel>
</div>

4. Name the file DisplaymodemenuCS.ascx or DisplaymodemenuVB.ascx (depending on which language you are using for
the sample) and save it in the folder for the virtual directory or Web site you are using for this walkthrough.

To add display mode capabilities to the user control


1. In the user control's source file, add a pair of <script> tags just above the opening <div> tag in the page, and add a
runat="server" attribute within the opening <script> tag.
2. Add the following code in the <script> section to enable users to change display modes on the page, to reset
personalization data on the page, and to switch between user and shared personalization scope:
VB
<script runat="server">
' Use a field to reference the current WebPartManager.
Dim _manager As WebPartManager

Sub Page_Init(ByVal sender As Object, ByVal e As EventArgs)


AddHandler Page.InitComplete, AddressOf InitComplete
End Sub

Sub InitComplete(ByVal sender As Object, ByVal e As System.EventArgs)


_manager = WebPartManager.GetCurrentWebPartManager(Page)

Dim browseModeName As String = WebPartManager.BrowseDisplayMode.Name

' Fill the dropdown with the names of supported display modes.
Dim mode As WebPartDisplayMode
For Each mode In _manager.SupportedDisplayModes
Dim modeName As String = mode.Name
' Make sure a mode is enabled before adding it.
If mode.IsEnabled(_manager) Then
Dim item As New ListItem(modeName, modeName)
DisplayModeDropdown.Items.Add(item)
End If
Next mode

' If shared scope is allowed for this user, display the scope-switching
' UI and select the appropriate radio button for the current user scope.
If _manager.Personalization.CanEnterSharedScope Then
Panel2.Visible = True
If _manager.Personalization.Scope = PersonalizationScope.User Then
RadioButton1.Checked = True
Else
RadioButton2.Checked = True
End If
End If

End Sub

' Change the page to the selected display mode.


Sub DisplayModeDropdown_SelectedIndexChanged(ByVal sender As Object, _
ByVal e As EventArgs)

Dim selectedMode As String = DisplayModeDropdown.SelectedValue


Dim mode As WebPartDisplayMode = _
_manager.SupportedDisplayModes(selectedMode)
If Not (mode Is Nothing) Then
_manager.DisplayMode = mode
End If

End Sub

' Set the selected item equal to the current display mode.
Sub Page_PreRender(ByVal sender As Object, ByVal e As EventArgs)
Dim items As ListItemCollection = DisplayModeDropdown.Items
Dim selectedIndex As Integer = _
items.IndexOf(items.FindByText(_manager.DisplayMode.Name))
DisplayModeDropdown.SelectedIndex = selectedIndex

End Sub

' Reset all of a user's personalization data for the page.


Protected Sub LinkButton1_Click(ByVal sender As Object, _
ByVal e As EventArgs)

_manager.Personalization.ResetPersonalizationState()

End Sub

' If not in User personalization scope, toggle into it.


Protected Sub RadioButton1_CheckedChanged(ByVal sender As Object, _
ByVal e As EventArgs)

If _manager.Personalization.Scope = PersonalizationScope.Shared Then


_manager.Personalization.ToggleScope()
End If
End Sub

' If not in Shared scope, and if user is allowed, toggle the scope.
Protected Sub RadioButton2_CheckedChanged(ByVal sender As Object, _
ByVal e As EventArgs)

If _manager.Personalization.CanEnterSharedScope AndAlso _
_manager.Personalization.Scope = PersonalizationScope.User Then
_manager.Personalization.ToggleScope()
End If

End Sub

</script>

C#
<script runat="server">

// Use a field to reference the current WebPartManager.


WebPartManager _manager;

void Page_Init(object sender, EventArgs e)


{
Page.InitComplete += new EventHandler(InitComplete);
}

void InitComplete(object sender, System.EventArgs e)


{
_manager = WebPartManager.GetCurrentWebPartManager(Page);

String browseModeName = WebPartManager.BrowseDisplayMode.Name;

// Fill the dropdown with the names of supported display modes.


foreach (WebPartDisplayMode mode in _manager.SupportedDisplayModes)
{
String modeName = mode.Name;
// Make sure a mode is enabled before adding it.
if (mode.IsEnabled(_manager))
{
ListItem item = new ListItem(modeName, modeName);
DisplayModeDropdown.Items.Add(item);
}
}

// If shared scope is allowed for this user, display the scope-switching


// UI and select the appropriate radio button for the current user scope.
if (_manager.Personalization.CanEnterSharedScope)
{
Panel2.Visible = true;
if (_manager.Personalization.Scope == PersonalizationScope.User)
RadioButton1.Checked = true;
else
RadioButton2.Checked = true;
}

}
// Change the page to the selected display mode.
void DisplayModeDropdown_SelectedIndexChanged(object sender, EventArgs e)
{
String selectedMode = DisplayModeDropdown.SelectedValue;

WebPartDisplayMode mode = _manager.SupportedDisplayModes[selectedMode];


if (mode != null)
_manager.DisplayMode = mode;
}

// Set the selected item equal to the current display mode.


void Page_PreRender(object sender, EventArgs e)
{
ListItemCollection items = DisplayModeDropdown.Items;
int selectedIndex =
items.IndexOf(items.FindByText(_manager.DisplayMode.Name));
DisplayModeDropdown.SelectedIndex = selectedIndex;
}

// Reset all of a user's personalization data for the page.


protected void LinkButton1_Click(object sender, EventArgs e)
{
_manager.Personalization.ResetPersonalizationState();
}

// If not in User personalization scope, toggle into it.


protected void RadioButton1_CheckedChanged(object sender, EventArgs e)
{
if (_manager.Personalization.Scope == PersonalizationScope.Shared)
_manager.Personalization.ToggleScope();
}

// If not in Shared scope, and if user is allowed, toggle the scope.


protected void RadioButton2_CheckedChanged(object sender, EventArgs e)
{
if (_manager.Personalization.CanEnterSharedScope &&
_manager.Personalization.Scope == PersonalizationScope.User)
_manager.Personalization.ToggleScope();
}
</script>

There are several things to notice in the code:


In the InitComplete method, the code determines which display modes are currently available on the page, and
populates the drop-down list control with display modes. The code also determines whether the current user can
enter into shared personalization scope on the page and selects the appropriate radio button control.
The DisplayModeDropdown_SelectedIndexChanged method actually changes the page's display mode, using the
WebPartManager control and the mode selected by the user.
The LinkButton1_Click method resets the personalization state on the page, which means that all user
personalization data for the page is eliminated from the personalization data store and the page is returned to its
default state.
The RadioButton1_CheckChanged and RadioButton2_CheckChanged methods switch the personalization scope to
either user or shared scope.
3. Save and close the file.
Creating a Web Page to Host the Display Modes Control
Now that you have created a user control to change display modes, you can create a Web page that hosts the user control, and
that also contains Web Parts zones and other server controls to provide Web Parts functionality.
To create a Web page that can change display modes
1. Place the compiled assembly for the custom control your Web site's Bin folder.
As the prerequisites for this walkthrough state, you need a compiled, custom WebPart control. This walkthrough uses
the custom control called TextDisplayWebPart, which is available in the class overview topic of the
WebPartDisplayMode class. The compiled assembly should be named TextDisplayWebPartCS.dll or
TextDisplayWebPartVB.dll, depending on which language you use.

Security Note
The control has a text box that accepts user input, which is a potential security threat. By default, ASP.NET Web pages va
lidate user input to ensure that the input does not contain HTML elements or script. For more information, see
Script Exploits Overview.

2. In a text editor, create a new file.


3. At the top of the file, add a page declaration and two register directives. One register directive is for the user control; the
other is for the compiled, custom WebPart control you are using for this walkthrough. The directive's Assembly
attribute must reference the name of the assembly file for the custom control, without the extension.
VB
<%@ page language="VB" %>
<%@ register TagPrefix="uc1"
TagName="DisplayModeMenuVB"
Src="DisplayModeMenuVB.ascx" %>
<%@ register tagprefix="aspSample"
Namespace="Samples.AspNet.VB.Controls"
Assembly="TextDisplayWebPartVB"%>

C#
<%@ page language="C#" %>
<%@ register TagPrefix="uc1"
TagName="DisplayModeMenuCS"
Src="DisplayModeMenuCS.ascx" %>
<%@ register tagprefix="aspSample"
Namespace="Samples.AspNet.CS.Controls"
Assembly="TextDisplayWebPartCS"%>

4. Beneath the register directives, add the following code block, which enables you to manually switch the page to catalog
mode:
VB
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
Sub Button1_Click(Byval sender As Object, _
ByVal e As EventArgs)
WebPartManager1.DisplayMode = WebPartManager.CatalogDisplayMode
End Sub
</script>
C#
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
void Button1_Click(object sender, EventArgs e)
{
WebPartManager1.DisplayMode = WebPartManager.CatalogDisplayMode;
}
</script>

5. After the code block, add the following markup to the file.
There are a number of features in this code example that are necessary to a Web Parts page, including an
<asp:webpartmanager> element, Web Parts zones corresponding to the possible display modes of the page, and
several controls. For more information on these, see Walkthrough: Creating a Web Parts Page.
The code for the rest of the page should look like the following code block.
VB
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title>Web Parts Display Modes</title>
</head>
<body>
<form id="Form2" runat="server">
<asp:webpartmanager id="WebPartManager1" runat="server" />
<uc1:DisplayModeMenuVB ID="DisplayModeMenu1" runat="server" />
<asp:webpartzone
id="WebPartZone1"
runat="server" BackImageUrl="~/MyImage.gif">
<zonetemplate>
<asp:Calendar
ID="Calendar1"
Runat="server"
Title="My Calendar" />
</zonetemplate>
</asp:webpartzone>
<asp:WebPartZone ID="WebPartZone2" Runat="server">
</asp:WebPartZone>
<asp:EditorZone ID="editzone1" Runat="server">
<ZoneTemplate>
<asp:AppearanceEditorPart
ID="appearanceeditor1"
Runat="server" />
<asp:LayoutEditorPart
ID="LayoutEditorPart1"
Runat="server" />
</ZoneTemplate>
</asp:EditorZone>
<asp:CatalogZone ID="catalogzone1" Runat="server">
<ZoneTemplate>
<asp:DeclarativeCatalogPart
ID="declarativepart1"
Runat="server">
<WebPartsTemplate>
<aspSample:TextDisplayWebPart
runat="server"
id="textwebpart"
title = "Text Content WebPart"/>
</WebPartsTemplate>
</asp:DeclarativeCatalogPart>
</ZoneTemplate>
</asp:CatalogZone>
<br />
<asp:button
id="button1"
runat="server"
text="Catalog Mode"
OnClick="Button1_Click"
/>
</form>
</body>
</html>

C#
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title>Web Parts Display Modes</title>
</head>
<body>
<form id="Form2" runat="server">
<asp:webpartmanager id="WebPartManager1" runat="server" />
<uc1:DisplayModeMenuCS ID="DisplayModeMenu1" runat="server" />
<asp:webpartzone
id="WebPartZone1"
runat="server" BackImageUrl="~/MyImage.gif">
<zonetemplate>
<asp:Calendar
ID="Calendar1"
Runat="server"
Title="My Calendar" />
</zonetemplate>
</asp:webpartzone>
<asp:WebPartZone ID="WebPartZone2" Runat="server">
</asp:WebPartZone>
<asp:EditorZone ID="editzone1" Runat="server">
<ZoneTemplate>
<asp:AppearanceEditorPart
ID="appearanceeditor1"
Runat="server" />
<asp:LayoutEditorPart
ID="LayoutEditorPart1"
Runat="server" />
</ZoneTemplate>
</asp:EditorZone>
<asp:CatalogZone ID="catalogzone1" Runat="server">
<ZoneTemplate>
<asp:DeclarativeCatalogPart
ID="declarativepart1"
Runat="server">
<WebPartsTemplate>
<aspSample:TextDisplayWebPart
runat="server"
id="textwebpart"
title = "Text Content WebPart" AllowClose="true"/>
</WebPartsTemplate>
</asp:DeclarativeCatalogPart>
</ZoneTemplate>
</asp:CatalogZone>
<br />
<asp:button
id="button1"
runat="server"
text="Catalog Mode"
OnClick="Button1_Click"
/>
</form>
</body>
</html>

6. Name the file Displaymodes.aspx and save it in the directory for your Web site.
Testing the Web Page to Change Display Modes
Now you have created everything necessary to run a Web page that contains Web Parts controls and that can switch between
various page display modes.
To test the page and change display modes
1. Load the page in a browser.
The page will look similar to the following screen shot:
Page with control for changing display modes

2. Click the Display Mode drop-down list control.


Notice the various display modes that are available on the page. Because the page contains a WebPartZone control, an
EditorZone control, and a CatalogZone control, corresponding display modes appear in the drop-down list for each of
these zone types, in addition to the default Browse display mode.
Note
The page could also contain a ConnectionsZone control, which would enable you to create connections between contro
ls and would add a connection display mode to the drop-down list. However, connections are beyond the scope of this
walkthrough.

3. Select Catalog mode from the drop-down list.


The catalog mode UI appears, and the TextDisplayWebPart control is visible in the catalog, available to be added to the
page.
4. Click the Close button to return the page to browse mode.
5. As an alternate way of switching to a display mode, without requiring the user control, click the Catalog Mode button
near the bottom of the page. The code for this switch appears in the Web page's Button1_Click method.
The page switches to catalog mode.
6. Select the check box next to the custom control in the catalog, and click Add to add it to the page.
7. Click Close to return the page to browse mode.
The added control now appears on the page.
8. In the Display Mode drop-down list control, select Edit.
The page switches to edit mode. The titles of the zones become visible, and a verbs menu button that looks like a small
triangle appears in the title bar of each server control residing in a WebPartZone. The verbs menu provides various
actions that a user can apply to a control.
9. Click the verbs menu on the TextDisplayWebPart control.
A drop-down menu appears.
10. In the verbs menu, click the Edit option.
The special editing UI, which is declared in the <asp:editorzone> element, appears. With these controls, you can change
the layout and appearance of the custom control.
11. Use the editing UI to change the title of the custom control. Then click Apply to apply the changes.
12. Position your mouse pointer in the title bar of the custom control. Click the title bar and drag the control from
WebPartZone1 into WebPartZone2.

13. Use the Display Mode drop-down list control to change the page back to browse mode.
The page will look similar to the following screen shot.
Page after making changes in various display modes

See Also
Tasks
Walkthrough: Creating a Web Parts Page
Reference
Web Parts Control Set Overview
WebPartDisplayMode
Concepts
Web Parts Page Display Modes
ASP.NET

Web Parts Personalization


In certain Web applications, you might want to allow users to modify, or personalize, the application's user interface and
behavior. ASP.NET Web Parts controls provide this capability in one of their core features, personalization. Personalization
allows the properties or state of Web Parts controls to be saved in long term storage and not be tied to a particular browser
session.
In This Section
Web Parts Personalization Overview
Requirements for Using Web Parts Personalization
How to: Create Personalizable Properties on a Web Parts Control
Walkthrough: Implementing Web Parts Personalization with a User Control
Walkthrough: Implementing Web Parts Personalization using IPersonalizable
How to: Enable Shared Personalization of Web Parts Pages
How to: Disable Web Parts Personalization
How to: Create Personalizable Properties on a Web Parts Control
How to: Remove User Entries from the Personalization Store
How to: Enable Users to Clear Personalization State
Related Sections
ASP.NET Web Parts Pages
Provides links to all topics about ASP.NET Web Parts.
ASP.NET

Web Parts Personalization Overview


In certain Web applications, you might want to allow users to modify, or personalize, the application's user interface and
behavior. The ASP.NET Web Parts control set provides this capability in one of its core features, personalization. Personalization
allows the properties or state of Web Parts controls to be saved in long term storage and not tied to a particular browser
session.
How Personalization Works
Personalization enables you to create properties for Web Parts controls that have several unique characteristics. Personalizable
properties are:
Tied to the identity of a specific user and Web page. Each user's settings for the personalizable controls on each
page can be saved in personalization data. This data enables users to modify the UI on a Web page and save their
individual preferences.
Long-lived. Personalized settings are not tied to a single browser session. Because they are stored in long-term storage,
the application can retrieve a user's settings each time the user visits a specific page.
Personalization uses an ASP.NET application services database to store personalization data. By default, ASP.NET creates
this database automatically in a subfolder named "app_data" when an ASP.NET application first uses personalization or
one of the other application services such as roles, membership or profiles. Also by default, ASP.NET creates the database
as a single SQL Server Express database file that contains the database schema for all of the application services. Using
the Web.config file, you can configure your application so that a separate database file is created for personalization.
Further, in the Web.config file, you can specify a SQL Server database to store the application services data instead of
using the default SQL Server Express database file.
Persisted through a provider layer. The mechanism for storing and retrieving personalization data consists of a
provider component and a data store. ASP.NET includes a default Microsoft SQL provider and database. You can also
create a custom provider and configure it to use any data store.
Declarative on any Web Parts control. When you are developing a custom control, you can add the Personalizable
attribute in code to enable a particular property on any Web Parts control for personalization. In addition to custom
controls derived from the WebPart class, this also applies to ASP.NET server controls, custom server controls, or user
controls, since they can be used as Web Parts controls.
Note
It is important to recognize that ordinary properties are handled differently in that they cannot be persisted like person
alizable properties. If you add a WebPart control or other server control to a WebPartZoneBase zone programmaticall
y, and you try to set its non-personalizable properties programmatically (for example, if you set the Text property on a
Label control), the properties are reset to their default values after the controls are added, because there is no way for t
hese property values to be persisted in long term personalization storage. To persist the properties in long-term storag
e, they must be marked with the Personalizable attribute in the source code. Alternatively, if you want to persist the pr
operties only across requests within the same browser session (but not in long-term storage), you can use view state.

Personalization and Other ASP.NET Features


Personalization contrasts in several ways with the other ASP.NET techniques for persisting a Web application's state data:
Personalization is a feature of Web Parts. You cannot use personalization by itself. To use personalization, you must
use controls within a WebPartZone so they will have Web Parts functionality.
Note
Any ASP.NET server control, custom control, or user control can be used as a Web Parts control to take advantage of pe
rsonalization.

Personalization is different from view state. View state and personalization both persist control state data, but view
state data only persists during the current browser session, while personalization data is long-lived.
Personalization is different from profiles. Personalization stores user-specific state data for controls on a particular
Web page only. Information that relates to the user as a person, and that is intended to be used across multiple pages in
a Web application (such as account information in a shopping cart application), should be kept in a profile. For more
information, see ASP.NET Profile Properties Overview.
Key Concepts in Personalization
When you use personalization with Web Parts controls, you should understand several concepts that affect how
personalization works.
The first concept is page personalization scope. Page personalization scope is the range of users to which personalization
changes on a page can apply. At any given time, a Web Parts page can be in one of two possible page personalization scopes,
Shared or User. In Shared scope, any personalization changes on the page apply to all users; in User scope, personalization
changes on the page apply only to the current user.
A second and related concept is control visibility. Control visibility determines whether a given control is visible to an individual
user or to all users. Each WebPart control on a page is either a shared control, visible to all users of that page, or a per-user
control, visible only to an individual user. Visibility is determined by how a control is added to a page. If a control is added by
declaring it in the markup of a Web page (a static control), it is always a shared control. If a control is added by application code
or by a user selecting it from a catalog of controls (a dynamic control), visibility is determined by the current personalization
scope of the page. If the page is in Shared scope, a dynamically added control is shared, and if the page is in User scope, the
control is a per-user control.
A third important concept is property scope. When you create a personalizable property on a control using the Personalizable
attribute in the source code, you can set the personalization scope for the property to either Shared or User (User is the
default scope). This provides detailed control over which properties on a control can be personalized by all users, and which
can be personalized only by authorized users when the page scope is Shared.
Taken together, these concepts of page personalization scope, control visibility, and property personalization scope create the
range of options for how Web Parts controls can be viewed and personalized by users. The following table summarizes how
Web Parts controls behave when users personalize them in the various scopes.
Control vi Page in Shared scope Page in User scope
sibility
shared con An authorized user can personalize Individual users can not personalize properties scoped as Shared. They can per
trol (Web both Shared and User scoped prop sonalize User-scoped properties, and their values for these properties take pre
Part contr erties on the control for all users. cedence over the property values assigned when the page was in Share scope.
ols are sha If the user-specific personalization data on a control is lost or reset, User-scope
red by def In the case of a dynamic control (a d properties revert to the values they had when the page was in Shared scope.
ault) control that is added to the page pr
ogrammatically, or from a catalog Individual users can close a shared control for themselves, which adds it to the
of controls), an authorized user can Page Catalog, but they cannot permanently delete it.
permanently delete it for all users.
In the case of a static control (a con
trol that is declared in the markup
of an .aspx page), it cannot be delet
ed, although an authorized user ca
n close the control for all users.

per-user c The control cannot be personalized Individual users can personalize both Shared and User scoped personalizable
ontrol with the page in Shared scope, bec properties on the control for themselves, because the control instance is compl
ause the control does not even app etely private.
ear on the page. The control only a
ppears when the page is in User sc Individual users can also permanently delete the control.
ope.

Essential Personalization Components


The following table shows the two components in the Web Parts control set that are essential to personalization, and that you
work with directly or indirectly whenever you use personalization.
Web Parts control Description
WebPartManager Manages all Web Parts on a page, enables or disables personalization, and manages the life cycle of p
ersonalization data. One (and only one) WebPartManager control is required for every Web Parts pa
ge.

WebPartPersonalization Implements the logic necessary to carry out personalization actions.

See Also
Reference
Web Parts Control Set Overview
Concepts
ASP.NET Web Parts Overview
Requirements for Using Web Parts Personalization
ASP.NET Profile Properties Overview
ASP.NET

Requirements for Using Web Parts Personalization


Personalization is a fundamental capability of the ASP.NET Web Parts control set, and is required when you want to create
pages with Web Parts controls that allow users to modify or personalize Web pages. This topic discusses the basic
requirements for working with Web Parts personalization. For additional material on personalization and what it does within
the Web Parts control set, see Web Parts Personalization Overview.
Configuring a Site for Membership
A prerequisite for using personalization is an ASP.NET Web site configured to identify individual users. Typically this site will
use Windows authentication if it is a local intranet site, or forms authentication if it is an Internet site. For details on configuring
a site, see Configuring ASP.NET Applications.
Selecting a Provider
To use personalization, you need a provider to manage the personalization data, and a database to store it. After you have
configured a site for membership, you can optionally use the default provider. ASP.NET includes a default Microsoft SQL
Server Express provider and database to store personalization data. If you want to use this provider, no additional setup is
required. You can also set up your own custom database provider.
Creating a Page with Web Parts Controls
Another requirement for working with personalization is to create a page that uses Web Parts controls. For details on how to
create a basic Web Parts page with personalization, see Walkthrough: Creating a Web Parts Page. For information on how to
work with user controls and personalization, see Walkthrough: Implementing Web Parts Personalization with a User Control.
Disabling Web Parts Personalization
While Web Parts personalization is enabled by default, you might want to disable it in certain cases. For example, you might
want to use some Web Parts controls on a page, but not allow users to personalize the page. For details on how to disable
personalization, see How to: Disable Web Parts Personalization.
See Also
Concepts
ASP.NET Web Parts Overview
Web Parts Personalization Overview
ASP.NET

Walkthrough: Implementing Web Parts Personalization with a


User Control
This walkthrough shows you how to create an ASP.NET user control that relies on Web Parts personalization to provide user-
specific default values on a Web page.
ASP.NET Web Parts enable you to build Web pages with modular layouts in which users can modify the appearance and
content to suit their preferences. A key Web Parts feature known as personalization lets you save user-specific settings for each
page and reuse those settings in future browser sessions.
Using Web Parts and personalization, you can build Web pages that include a feature useful for many Web applications: the
ability to supply user-specific default values in a form. This walkthrough demonstrates how to supply user-specific default
values by implementing a user control that can be treated as a personalizable Web Parts control. This development approach
could be useful if you were creating an application for customer service agents to fill out online forms, for example. The Web
Parts and personalization capabilities enable your page to recognize each agent. The user control allows each agent to save
default values for the fields on the form, and then the default values can be automatically filled in on subsequent visits to the
page.
Note
The user control you create in this walkthrough does not inherit from the WebPart class. But in this walkthrough you learn th
at a user control can function as a WebPart control. During the walkthrough you add the user control to a WebPartZoneBase
zone. Doing so enables ASP.NET to wrap the user control in a GenericWebPart control. The user control will then work like an
y other WebPart control, and will allow you to explore personalization.

During this walkthrough, you will learn how to:


Create a user control with personalizable properties, whose values can be saved in long-term storage.
Display user-specific default values on a form in a Web page.
Work with the user control in a zone as a true WebPart control.
Note
This type of application could be developed using ASP.NET profiles. However, in this case you are not storing informati
on about the user to be reused across an entire application, as in a shopping cart application. Instead, you are saving us
er-specific preferences or settings for each control, on a per-page basis. For more information about profiles, see
ASP.NET Profile Properties Overview.

Prerequisites
In order to complete this walkthrough, you will need:
Internet Information Services (IIS) installed and configured on the computer that will host the site. For details about
installing and configuring IIS, see the IIS Help documentation included with the installation, or see the online IIS
documentation on the Microsoft TechNet site (Internet Information Services 6.0 Technical Resources).
An ASP.NET Web site that can identify individual users. If you have such a site already configured, you can use that site as
a starting point for this walkthrough. Otherwise, for details on creating a virtual directory or site, see
How to: Create and Configure Virtual Directories in IIS.
A configured personalization provider and database. Web Parts personalization is enabled by default, and it uses the SQL
personalization provider (SqlPersonalizationProvider) with the Microsoft SQL Server Standard Edition to store
personalization data. This walkthrough uses SSE and the default SQL provider. If you have SSE installed, no configuration
is needed. SSE is available with Microsoft Visual Studio 2005 as an optional part of the installation, or as a free download.
For details, see the Microsoft SQL Server 2005 Express Edition Web page. To use one of the full versions of SQL Server,
you must install and configure an ASP.NET application services database, and configure the SQL personalization provider
to connect to that database. For details, see Creating and Configuring the Application Services Database for SQL Server.
You can also create and configure a custom provider to use with other, non-SQL databases or storage solutions. For
details and a code example see Implementing a Membership Provider.
Creating a Personalizable User Control
In this part of the walkthrough, you create a user control that provides the user interface (UI) for an agent information form.
The control also exposes personalizable properties for name and phone information.
Note
You do not need to enable Web Parts personalization; it is enabled by default. For more information about personalization, s
ee Web Parts Personalization Overview.

To create personalizable properties for the user control


1. In a text editor, create a new file and add the following control declaration to the beginning of the file, along with opening
and closing <script> tags:
VB
<%@ control language="VB" classname="AccountUserControl" %>
<script runat="server">
</script>

C#
<%@ control language="C#" classname="AccountUserControl" %>
<script runat="server">
</script>

2. Within the <script> tags, add code to create two personalizable properties: one named UserName, the other named
Phone, as shown in the following example.

Note
Each property has a Personalizable attribute. This enables Web Parts personalization to store the property values in a
database.

VB
<Personalizable()> _
Property UserName() As String

Get
If Textbox1.Text Is Nothing Or Textbox1.Text.Length < 0 Then
Return String.Empty
Else
Return Textbox1.Text
End If
End Get

Set(ByVal value As String)


Textbox1.Text = value
End Set

End Property

<Personalizable()> _
Property Phone() As String

Get
If Textbox2.Text Is Nothing Or Textbox2.Text.Length < 0 Then
Return String.Empty
Else
Return Textbox2.Text
End If
End Get

Set(ByVal value As String)


Textbox2.Text = value
End Set

End Property

C#

[Personalizable]
public string UserName
{
get
{
if(Textbox1.Text == null | Textbox1.Text.Length < 0)
return String.Empty;
else
return Textbox1.Text;
}

set
{
Textbox1.Text = value;
}
}

[Personalizable]
public string Phone
{
get
{
if(Textbox2.Text == null | Textbox2.Text.Length < 0)
return String.Empty;
else
return Textbox2.Text;
}

set
{
Textbox2.Text = value;
}
}

Security Note
This control has a textbox that accepts user input, which is a potential security threat. By default, ASP.NET Web pages va
lidate user input to ensure that the input does not contain HTML elements or script. For more information, see
Script Exploits Overview.

3. Name the file AccountUserControlCS.ascx or AccountUserControlVB.ascx (depending on which language you are using),
and save it in the root directory of your Web site.
Now that you have added personalizable properties to save the default values, you can add UI controls to the user control to
display a user's name and phone number.
To add UI controls to the user control
1. Beneath the <script> tags, add a Label control and a TextBox control wrapped by <div> tags to contain the user's name,
as shown in the following code example:

<div>
<asp:label id="Label1" runat="server">Name</asp:label>
<asp:textbox id="Textbox1" runat="server" />
</div>

2. Beneath the control you just added, add a Label control and a TextBox control wrapped by <div> tags to contain the
user's phone number, as in the following example:

<div>
<asp:label id="Label2" runat="server">Phone</asp:label>
<asp:textbox id="Textbox2" runat="server" />
</div>

3. Beneath the control you just added, add an <asp:button> element wrapped by <div> tags, to save the user's
information by performing a postback:

<div>
<asp:button id="Button1" runat="server"
text="Save Form Values" />
</div>

4. Save the file.


Referencing the User Control as a Web Parts Control
Now that you have created a user control with personalizable properties, you can create an ASP.NET Web page to host the user
control as a Web Parts control. It is necessary to host the control as a Web Parts control in order for personalization features to
work.
To reference the user control as a Web Parts control
1. In a text editor, create a new file and add the following page declaration to the beginning of the file:
VB
<%@ page language="VB" %>

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

2. Beneath the page declaration, add a declaration to reference the user control you created previously, as shown in the
following example:
VB
<%@ register tagprefix="uc1"
tagname="AccountUserControl"
src="AccountUserControlvb.ascx"%>

C#
<%@ register tagprefix="uc1"
tagname="AccountUserControl"
src="AccountUserControlcs.ascx"%>
3. Beneath the control reference, add the following basic page structure to host the user control as a Web Parts control.
Note
For the user control to work as a Web Parts control, the page must contain an <asp:webpartmanager> element, and
the user control must be contained within an <asp:webpartzone> element and a <zonetemplate> element in succe
ssion.

<html>
<head runat="server">
<title>Personalizable User Control</title>
</head>
<body>
<form id="form1" runat="server">
<asp:webpartmanager id="WebPartManager1" runat="server" />
<asp:webpartzone id="zone1" runat="server" headertext="Main">
<zonetemplate>
<uc1:AccountUserControl
runat="server"
id="accountwebpart"
title="Agent Information" />
</zonetemplate>
</asp:webpartzone>
</form>
</body>
</html>

4. Name the file Hostaccountcontrol.aspx and save it in the same directory as the user control.
You have now created a personalizable user control, and referenced it as a Web Parts control in a Web Forms page. The final
step is to test your user control.
To test the personalizable user control
1. Load the Hostaccountcontrol.aspx page in a browser.
2. Enter values in the Name and Phone fields, and click the Save Form Values button.
3. Close the browser.
4. Load the page again in a browser.
The values you entered previously appear in the form. These are the values that were saved in the personalizable
properties, and were restored from the database when you reloaded the page in the browser.
5. Enter new values in the form, but do not click the button to save them.
6. Close the browser.
7. Load the page again in a browser.
The original values you entered and saved in the personalized properties are the ones that reappear in the form, because
you did not save the new values.
Next Steps
This walkthrough has demonstrated the basic tasks involved in creating a user control with personalizable properties. You
created a control that allows you to save user-specific settings for the specific control and page, and display those saved
settings when the user revisits the page in a new browser session. Suggestions for further exploration include:
Investigate the other components involved in creating a Web Parts page. For an introduction, see
Walkthrough: Creating a Web Parts Page.
Learn more about working with user controls. For details, see ASP.NET User Controls Overview.
Learn to create your own custom Web Parts controls, which offer more programmatic control than a user control and
provide the full range of Web Parts features. For more information, see
How to: Treat a User Control as a Web Parts Control.
See Also
Concepts
ASP.NET Web Parts Overview
Web Parts Personalization Overview
Walkthrough: Implementing Web Parts Personalization using
IPersonalizable
This walkthrough demonstrates how to supply user-specific default values by implementing a user control as a personalizable
Web Parts control.
The most significant characteristic of this control is that its personalizable properties are stored in non-value type variables. In
this case, the values are stored in a BulletedList control. This implies that the system does not have any way to know when the
user changes the values in the list. This walkthrough demonstrates how to inform the system that the values are changed so
they can be preserved for future use. This can be useful if you are creating customizable online forms on a per-user basis. Web
Parts personalization allows the system to recognize the user so that his or her default form values can be automatically
restored on subsequent visits to the site.
Note
The user control you create in this walkthrough does not inherit from the WebPart class; however, a user control can function
as a WebPart control. During this walkthrough, you add a user control to a WebPartZoneBase zone. This allows ASP.NET to
wrap the user control in a GenericWebPart control. The user control will then work like any other WebPart control, and will a
llow you to explore personalization.

During this walkthrough, you will learn how to:


Create a user control with personalizable properties, whose values can be saved in long-term storage.
Display user-specific default values.
Work with the user control in a zone as a true WebPart control.
Note
This type of application could be developed using ASP.NET profiles. However, in this case you are not storing information ab
out the user to be reused across an entire application, as in a shopping cart application. Instead, you are saving user-specific
preferences or settings for each control, on a per-page basis. For more information about profiles, see
ASP.NET Profile Properties Overview.

Prerequisites
To complete this walkthrough, you will need:
Internet Information Services (IIS) installed and configured on the computer that will host the site. For more information
about installing and configuring IIS, see the IIS Help documentation included with the installation, or see the online IIS
documentation on the Microsoft TechNet site (Internet Information Services 6.0 Technical Resources).
An ASP.NET Web site that can identify individual users. If you have such a site already configured, you can use that site as
a starting point for this walkthrough. Otherwise, for more information about creating a virtual directory or site, see
How to: Create and Configure Virtual Directories in IIS.
A configured personalization provider and database. Web Parts personalization is enabled by default, and it uses the SQL
personalization provider (SqlPersonalizationProvider) with the Microsoft SQL Server Standard Edition (SSE) to store
personalization data. This walkthrough uses SSE and the default SQL provider. If you have SSE installed, no configuration
is needed. SSE is available with Microsoft Visual Studio 2005 as an optional part of the installation, or as a free download
from Microsoft.com. To use one of the full versions of SQL Server, you must install and configure an ASP.NET application
services database, and configure the SQL personalization provider to connect to that database. For more information, see
Creating and Configuring the Application Services Database for SQL Server. You can also create and configure a custom
provider to use with other, non-SQL databases or storage solutions. For more information and a code example, see
Implementing a Membership Provider.
Creating a Personalizable User Control that Contains Reference Type Variables
In this part of the walkthrough, you create a user control that allows you to enter a friendly name and URL for a Web site.
When you click the Save button, the friendly name is added to a BulletedList control. These values are stored by the Web
Parts personalization feature on a per-user basis. Every time the user accesses the control coming from another page or in a
new session, the system displays the saved BulletedList values.
Note
You do not need to enable Web Parts personalization; it is enabled by default. For more information about personalization, s
ee Web Parts Personalization Overview.

To create the personalizable user control


1. In a text editor, create a new file to contain a user control, name it UrlList.ascx, and save it in your Web directory. The
code that implements the control's behavior is contained in a separate file, as shown in step 4.
2. In the new file, add a control directive in the programming language you are using, as shown in the following example.
VB
<%@ Control Language="VB" AutoEventWireup="false"
CodeFile="UrlList.ascx.vb" Inherits="WebParts_UrlList" %>

C#
<%@ Control Language="C#" AutoEventWireup="true"
CodeFile="UrlList.ascx.cs" Inherits="WebParts_UrlList" %>

3. Below the directive, add the following elements to represent the control's user interface (UI).

<table>

<tr>
<td>
<asp:Label ID="NameLabelID" Text="Name: " runat="server" />
</td>
<td>
<asp:TextBox ID="NameTextBoxID" runat="server" />
</td>
</tr>

<tr>
<td>
<asp:Label ID="UrlLabelID1" Text="Url: " runat="server" />
</td>
<td>
<asp:TextBox ID="UrlTextBoxID" runat="server" />
</td>
</tr>

<tr>
<td>
<asp:Button ID="SaveID" runat="server"
OnClick="SaveButton_Click" Text="Save" />
</td>
<td>
<asp:Button ID="ResetID" runat="server"
OnClick="ResetButton_Click" Text="Reset" />
</td>
</tr>

</table>
<div>
// This is the complex variable whose status
// must be preserved.
<asp:BulletedList
ID="BulletedListID" runat="server"
DisplayMode="HyperLink" Target="_blank" />

</div>

4. Create another new file to act as the companion file, and add the following code to it. The following example represents
the companion file (UrlList.ascx.vb or UrlList.ascx.cs, depending on which language you are using) that implements the
behavior of the preceding UrlList.ascx control. This code is divided in two parts. One part contains the code that handles
the user input and the page load event; the other contains the code that implements the IPersonalizable interface. This
allows the preservation of the BulletedList values -- that is, the personalization of the user control. This example
implements the Load, Save, and IsDirty interface members.
VB
' UrlList.ascx.vb
Imports System
Imports System.Collections
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Web.UI.WebControls.WebParts

Partial Class WebParts_VB_UrlList


Inherits System.Web.UI.UserControl
Implements IPersonalizable

Private _userUrls As ArrayList


Private _listDirty As Boolean

' This code implements the IPersonalizable members.

Public Overridable ReadOnly Property IsDirty() As Boolean _


Implements System.Web.UI.WebControls.WebParts.IPersonalizable.IsDirty

Get
Return _listDirty
End Get
End Property

Public Overridable Shadows Sub Load(ByVal state As PersonalizationDictionary) _


Implements System.Web.UI.WebControls.WebParts.IPersonalizable.Load

If Not (state Is Nothing) Then

Dim userUrlsEntry As PersonalizationEntry = state("userUrls")


If Not (userUrlsEntry Is Nothing) Then
_userUrls = CType(userUrlsEntry.Value, ArrayList)
End If
End If

End Sub 'Load

Public Overridable Sub Save(ByVal state As PersonalizationDictionary) _


Implements System.Web.UI.WebControls.WebParts.IPersonalizable.Save
If Not (_userUrls Is Nothing) AndAlso _userUrls.Count <> 0 Then
state("userUrls") = New PersonalizationEntry(_userUrls, _
PersonalizationScope.User)
End If

End Sub

' This code handles the user's input.


Protected Sub SaveButton_Click(ByVal sender As Object, _
ByVal e As EventArgs)

Dim name As String = NameTextBoxID.Text.Trim()


Dim url As String = UrlTextBoxID.Text.Trim()

Dim p As New Pair(name, url)

If _userUrls Is Nothing Then


_userUrls = New ArrayList()
End If
_userUrls.Add(p)

BulletedListID.Items.Add(New ListItem(CStr(p.First), _
CStr(p.Second)))

_listDirty = True

End Sub 'SaveButton_Click

Protected Sub ResetButton_Click(ByVal sender As Object, _


ByVal e As EventArgs)

_userUrls = New ArrayList()

BulletedListID.Items.Clear()

_listDirty = True

End Sub 'ResetButton_Click

Protected Sub Page_Load(ByVal sender As Object, _


ByVal e As EventArgs)
If Not (_userUrls Is Nothing) Then
BulletedListID.Items.Clear()
Dim p As Pair
For Each p In _userUrls
BulletedListID.Items.Add(New _
ListItem(CStr(p.First), CStr(p.Second)))
Next p
End If

End Sub 'Page_Load

End Class

C#
// UrlList.ascx.cs
using System;
using System.Collections;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;

public partial class WebParts_UrlList : System.Web.UI.UserControl,


IPersonalizable
{
private ArrayList _userUrls;
private bool _listDirty;

// This code implements the IPersonalizable members.

public new void Load(PersonalizationDictionary state)


{
if (state != null)
{

PersonalizationEntry userUrlsEntry = state["userUrls"];


if (userUrlsEntry != null)
{
_userUrls = (ArrayList)userUrlsEntry.Value;
}

}
}

public void Save(PersonalizationDictionary state)


{

if ((_userUrls != null) && (_userUrls.Count != 0))


{
state["userUrls"] =
new PersonalizationEntry(_userUrls, PersonalizationScope.User);
}

public virtual bool IsDirty


{
get
{
return _listDirty;
}
}

// This code handles the user's input.

protected void Page_Load(object sender, EventArgs e)


{
if (_userUrls != null)
{
BulletedListID.Items.Clear();
foreach (Pair p in _userUrls)
{
BulletedListID.Items.Add(
new ListItem((string)p.First, (string)p.Second));
}
}

protected void SaveButton_Click(object sender, EventArgs e)


{
string name = NameTextBoxID.Text.Trim();
string url = UrlTextBoxID.Text.Trim();

Pair p = new Pair(name, url);

if (_userUrls == null)
{
_userUrls = new ArrayList();
}
_userUrls.Add(p);

BulletedListID.Items.Add(
new ListItem((string)p.First, (string)p.Second));

_listDirty = true;
}

protected void ResetButton_Click(object sender, EventArgs e)


{

_userUrls = new ArrayList();

BulletedListID.Items.Clear();

_listDirty = true;

5. Name the file UrlList.ascx.vb or UrlList.ascx.cs (depending on which language you are using), and save it in the root
directory of your Web site.
Security Note
This control has a text box that accepts user input, which is a potential security threat. User input in a Web page can pot
entially contain malicious client script. By default, ASP.NET Web pages validate user input to ensure that the input does
not contain HTML elements or script. As long as this validation is enabled, you do not need to explicitly check for script
or HTML elements in user input. For more information, see Script Exploits Overview.

Referencing the User Control as a Web Parts Control


Now that you have created a user control with personalizable properties, you can create a Web Forms page to host the user
control as a Web Parts control.
Note
You must host the control as a Web Parts control for personalization to work.
To reference the user control as a Web Parts control
1. In the text editor, create a new file. Add a page declaration to the beginning of the file, as shown in the following example.
VB
<%@ page language="VB" %>

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

2. Beneath the page declaration, add a declaration to reference the user control you created previously, as shown in the
following example.
VB
<%@ Register tagprefix="UserControl" tagname="UrlList"
src="UrlList.ascx" %>

C#
<%@ Register tagprefix="UserControl" tagname="UrlList"
src="UrlList.ascx" %>

3. Beneath the control reference, add the following basic page structure to host the user control as a Web Parts control.
Note
For the user control to work as a Web Parts control, the page must contain an <asp:webpartmanager> element, and
the user control must be contained within an <asp:webpartzone> element and a <zonetemplate> element in succe
ssion, as the following example shows.

<html>
<head runat="server">
<title>Personalizable User Control</title>
</head>
<body>
<form id="form1" runat="server">
<asp:WebPartManager ID="mgr" runat="server" />
<div>
<asp:WebPartZone ID="WebPartZone1" runat="server">
<ZoneTemplate>
< UserControl:UrlList ID="AccUserID" runat="server"
title="URL List WebPart" />
</ZoneTemplate>
</asp:WebPartZone>
</div>
</form>
</body>
</html>

4. Name the file UrlList.aspx and save it in the same directory as the user control.
You have now created a personalizable user control, and referenced it as a Web Parts control in a Web Forms page.
The final step is to test your user control.
To test the personalizable user control
1. Load the UrlList.aspx page in a browser.
2. Enter values in the Name and URL fields, and click the Save Form Values button.
3. Close the browser.
4. Load the page again in a browser.
The values you entered previously should appear in the form. These are the values that were saved in the BulletedList
control, and were restored from the database when you reloaded the page in the browser.
5. Enter new values in the form, but do not click the button to save them. Close the browser.
6. Load the page again in a browser. The original values you entered and saved in the personalized properties should be the
ones that reappear in the form.
Next Steps
This walkthrough has demonstrated the basic tasks involved in creating a user control with personalizable properties. You
created a control that allows you to save user-specific settings for the specific control and page, and display those saved
settings when the user revisits the page in a new browser session. Suggestions for further exploration include:
Investigate the other components involved in creating a Web Parts page. For an introduction, see
Walkthrough: Creating a Web Parts Page.
Learn more about working with user controls. For more information, see ASP.NET User Controls Overview.
Learn to create your own custom Web Parts controls, which offer more programmatic control than a user control and
provide the full range of Web Parts features. For more information, see
How to: Treat a User Control as a Web Parts Control.
See Also
Concepts
ASP.NET Web Parts Overview
Web Parts Personalization Overview
ASP.NET

How to: Enable Shared Personalization of Web Parts Pages


Web Parts personalization is enabled by default, and authenticated users of a Web Parts page are able to personalize pages for
themselves without any special configuration. However, individual or user-scoped personalization changes are visible only to
the user who made them. If you want to provide a selected user (such as a site manager) or users with the ability to make
personalization changes in shared scope so that the changes to a page are visible to all users, you must add a setting to the
Web site's configuration file. This topic demonstrates how to update a configuration file to enable a specific user to personalize
a Web Parts page in shared scope, so that the changes are visible to all users.
Important
Enabling shared personalization creates some potential for security issues. For more information, see
Securing Web Parts Pages.

To update the configuration file using a text editor


1. Navigate to the root directory for your Web site, and open the Web.config file in a text editor. If your site does not already
have a Web.config file, you must first create a new configuration file. For more information about configuration files, see
Configuring ASP.NET Applications.
2. Within the <system.web> section of the configuration file, add an <authorization> section, and within that, add an
<allow> element to specify which user or users have access to shared personalization scope. The markup you add
should look like the following example markup, except that you should assign a valid local or domain user account, or a
group account, to the users attribute. The user or users specified will have the ability to edit a page in shared
personalization scope, so that the changes they make will be visible to all users. For more information about the
authorization element, see authorization Element (ASP.NET Settings Schema).

<authorization>
<allow verbs="enterSharedScope" users="SomeUserAccount"
roles="admin" />
</authorization>

3. Save and close the Web.config file.


To update the configuration file in IIS Manager
1. Rather than editing the configuration file directly, if your site is running under Microsoft Internet Information Services
(IIS) and if you are an administrator on the computer hosting your site, you can use IIS Manager to update the
configuration file. First, you need to start IIS Manager. On the Start menu, click Run.
Important
You must be logged on as a member of the Administrators group on the local computer to perform the following proc
edure (or procedures), or you must have been delegated the appropriate authority.

2. In the Open box, type inetmgr and click OK.


3. In IIS Manager, expand the local computer node, expand the Web Sites node, and select your site.
4. Right-click and select Properties, and then click the ASP.NET Configuration tab.
5. Click the Edit Configuration button, and then click the Authorization tab.
6. Click the Add button to add a new local authorization rule.
7. Select Allow for the rule type.
8. Select Specific Verbs in the Verbs section, and type enterSharedScope in the text box.
9. In the Users and Roles section, select Users, and then type the name of a user account in the text box.
Important
This could be a local user account, a user group, or a domain account, which would require you to enter it in the form d
omain\user.

10. Select the Roles check box, and then type admin in the text box.
11. Click OK to close each of the three consecutive windows, and close IIS Manager.
12. Open the Web.config file in the root directory of your Web site. In the <system.web> section of the file, there should
now be an entry to enable the user you specified to enter shared personalization scope. When the user or users specified
in the users attribute access a page that enables editing of Web Parts controls, they will have the option to enter into
shared personalization scope and make changes that will be visible to all users. The entry in Web.config should look
similar to the following code.

<authorization>
<allow verbs="enterSharedScope" users="SomeUserAccount"
roles="admin" />
</authorization>

See Also
Concepts
Web Parts Personalization Overview
Securing Web Parts Pages
Other Resources
ASP.NET Configuration Settings
Configuring ASP.NET Applications
ASP.NET

How to: Disable Web Parts Personalization


Web Parts personalization is enabled by default on Web Parts pages. However, you might want to disable it in certain cases.
For example, you might have a website where many pages use Web Parts controls and personalization. There might be certain
pages where you want the benefits of Web Parts features such as modular layout and the ability to create connections between
static Web Parts controls, but you also want the pages to remain read-only, meaning that users cannot personalize or modify
them. In such cases, you can disable personalization using the WebPartManager control on a Web Parts page.
Disabling Web Parts Personalization
To disable Web Parts personalization for a page
1. Open the Web Parts .aspx page and locate the <asp:webpartmanager> element.
2. Add the personalization-enabled attribute to the <asp:webpartmanager> element, and set its value to false, as in
the following code example.

<asp:webpartmanager runat="server" id="wpmgr1"


personalization-enabled="false" />

Personalization is now disabled on the page.


See Also
Concepts
Web Parts Personalization Overview
Requirements for Using Web Parts Personalization
Visual Web Developer

Learning More - Customizing Web Pages with Web Parts


The topics in this section provide in-depth information on ASP.NET Web Parts, an integrated set of controls for creating Web
sites that enables end users to modify a site's content, appearance, and behavior directly from a browser.
In This Section
Web Parts Connections Overview
How to: Treat a User Control as a Web Parts Control
Securing Web Parts Pages
Using ASP.NET Server Controls in Web Parts Applications
Web Parts Control Description Files
Creating a Data-bound Web Parts Control
See Also
Other Resources
ASP.NET Web Parts in Visual Studio
ASP.NET Web Sites (Visual Studio)
ASP.NET Web Pages (Visual Studio)
ASP.NET

Web Parts Connections Overview


The Web Parts control set enables you to create connections between server controls, so that the total value and usefulness of
the connected controls exceeds that of the individual, unconnected controls. A complete, integrated set of connection
components is provided, so that with a minimal number of steps, a few lines of code, and no need to handle all the underlying
complexity and synchronization of data, you can equip existing WebPart (or server or user) controls to form connections. With
controls that are enabled for connections, you can create dynamic, programmatic connections between the controls at run
time, as well as static, predefined connections declared in the markup of a Web page. You can also provide users with a user
interface (UI) that enables them to connect or disconnect controls at run time, and to manage existing connections.
Connections offer advantages to users and developers. By using connections, users can find new and meaningful ways to view
their data. Suppose you build an application in which a server control contacts a Web service, returns historical records of
average daily temperatures for a state, and lists the data in tabular form. If a user wants the flexibility to view that data in
different ways, the server control could be connected to a charting control that can consume tabular data and display it in
various chart views. The user could even be given the option of whether to display the data in a table or connect the
temperature data to the charting control. With new views of the data, users might notice new trends and relationships in
temperatures that were harder to visualize with the data in tabular form.
By using connections, developers can discover new opportunities for code reuse and for combining the functionality of isolated
controls. Suppose a developer creates a control that saves address information for the user, including a postal code, and makes
this information always available to fill in the shipping address form when the user orders something. Then the developer adds
other controls that depend on a specific postal code, such as controls to display weather information and news headlines in the
user's area, as well as a control that looks up businesses by category within a given postal code. Rather than design each new
control with the same feature of saving a postal code, the developer could design each control to require the input of a postal
code. Then the developer could simply connect the control that already saves the postal code to the weather, news, and
business listing controls that take a postal code as an input. Each connection extends the usefulness of the original control and
eliminates redundancy in the code of the new controls.
Connections Concepts
A Web Parts connection is a link or association between two server controls that enables them to share data. A connection
always involves exactly two controls: one is the provider of data, and the other is the consumer of the data from the provider. A
control can be both a consumer and a provider, and any type of server control, whether a WebPart control, a custom control,
or a user control, can be designed to participate in connections. A provider control by default can establish connections with
multiple consumers at the same time (like the previous example of a postal code control that provides a postal code to a
weather information control, a news headline control, and a business listing control). A consumer control by default can
connect to only one provider at a time.
Connections always take place in the context of a Web Parts application, which means that at a minimum, besides the two
server controls participating in the connection, two additional controls are required on the Web page. One of them is the
WebPartManager control, which is present on every page that contains Web Parts controls. The second required control is a
zone that inherits from the WebPartZoneBase class, such as the WebPartZone control. Any two server controls, in order to
form a connection, must reside within a WebPartZoneBase type of zone.
In a connection relationship, the consumer and the provider each have at least one associated object called a connection point.
Based on the ConnectionPoint class, a connection point contains the details necessary for a server control to connect to
another control, such as the type of the control itself, the type of data the control recognizes, an ID for the connection point
object, and whether the control can form multiple connections. A server control can have multiple connection points. A
provider's connection points are defined by instances of the ProviderConnectionPoint class, and the consumer's are defined by
instances of the ConsumerConnectionPoint class.
To form a connection, the consumer and provider must both recognize the same type of data, which in Web Parts connections
is passed by means of an interface instance. The type of data that a control recognizes is specified in the control's associated
connection point, in the InterfaceType property. If the provider and consumer recognize the same type of data, they are
compatible. If a provider and consumer are incompatible, a developer must use a special transformer object to translate the
provider's data into a form the consumer can work with. This transformer object inherits from the base WebPartTransformer
class, and a developer can either inherit from the base class to develop a custom transformer, or use one of the provided
transformer objects (RowToFieldTransformer or RowToParametersTransformer).
After a connection has been created, it is contained in a WebPartConnection object. The connection object encapsulates all the
details about a connection, including references to its consumer and provider objects, the IDs of the consumer and provider,
references to any connection points and their IDs, references to any transformers associated with the connection, and details
about the state of the connection, such as whether it is active and whether it is static or dynamic.
You can provide users with a way to create and manage connections by using the ConnectionsZone control. You can declare an
<asp:connectionszone> element on a Web page, which provides users with a run-time UI that allows them to connect or
disconnect controls, and to configure certain connection details.
How Connections Work
Web Parts connections are based on a "pull" model of connectivity, where the consumer gets data from the provider. To create
a connection, a control acting as a data provider defines a communication contract indicating the data it can provide. Another
control, acting as the consumer and with knowledge of the communication contract, retrieves that data.
The mechanism for establishing a connection is a special callback method: one in the consumer and one in the provider.
However, the Web Parts control set handles all the callback and communication details, so the steps required of developers are
minimal. As a developer, if you want to use the simplest approach, all you have to do is select a method in the provider to use
as the callback method, and mark it in the source code with a ConnectionProvider attribute. Then within that method, return
the interface instance containing the data to pass to the consumer. The interface instance can be very simple (for example, a
single property that contains a string value such as a postal code). A provider can implement one of the provided interfaces
(IWebPartField, IWebPartRow, or IWebPartTable), but in most cases it is preferable to create a simple, custom interface with
one or more properties or methods containing the data you want to share with a consumer, and implement that interface in
the provider. The consumer's callback method retrieves the instance of the interface from the provider. Again, all that is
required of a developer is to identify which method in the consumer (using a ConnectionConsumer attribute) will retrieve
the interface instance, and assign it to some internal variable for processing and rendering. Note that the data from the
provider is passed during the prerendering phase of the page and control cycle, so you should plan to process the data and
update any logic in the consumer after prerendering is complete.
Note
As mentioned previously, the consumer and provider must be compatible with regard to the interface type, or else they must
use a WebPartTransformer object to establish the connection.

The pipelines through which data is exchanged are the connection points for the consumer and provider. You can create a
connection point for a control in several ways. As mentioned in the preceding paragraph, you can use the
ConnectionConsumerAttribute or ConnectionProviderAttribute classes, which each create a connection point for you. In this
approach, you can add a ConnectionConsumer attribute to the consumer's callback method in the source code, and similarly
add a ConnectionProvider attribute to the provider's callback method. This identifies the respective callback methods, and
allows you to specify some details about the connection point, such as an ID and a display name (which appears in the UI for
users to form connections). As another alternative, you can create a custom connection point by inheriting from
ConnectionPoint, or you can use or inherit from the ConsumerConnectionPoint or ProviderConnectionPoint classes. As
noted previously, a control acting as either a consumer or a provider can have multiple connection points.
A connection between controls can be either static or dynamic. Static connections are coded declaratively in the hosting page
and created during the prerendering phase of the page. This ensures that the connection is active when a user views the page.
For an example, see How to: Declare a Static Connection between Two Web Parts Controls. Dynamic connections can be
created either programmatically in the control's code or declaratively on the hosting page. If you declare two compatible server
controls within a WebPartZoneBase zone on a Web page, and declare an instance of the ConnectionsZone control on the
page, users can create and configure a dynamic connection between the controls at run time.
Web Part Connections and Other ASP.NET Features
Connections contrast in several ways with the other ASP.NET techniques for transferring information between controls in a
Web application:
Connections are a feature of Web Parts. You can only connect controls that are designed for Web Parts connections
and that reside within a WebPartZoneBase zone.
Note
As noted previously, any ASP.NET server control, custom control, or user control can be used as a Web Parts control to
take advantage of connections.

Connections are different from data binding. Connections between controls in a Web Parts zone use an interface to
create a contract between the controls. Data binding is a connection between a control and a storage device or back-end
database. Web Parts connections move data only between controls on a page.
Connections can be personalized. Connection settings that indicate which controls are connected can be safely stored
with other personalization data. For more information on personalization, see Web Parts Personalization Overview.

Essential Connections Classes


The following table shows three components in the Web Parts control set that are essential to connections, and that you work
with directly or indirectly whenever you use connections.
Web Parts Description
control
WebPart Manages all connections between controls in the Web Parts zone on a page. One (and only one) WebPartManag
Manager er control is required for every Web Parts page.

WebPartZ The WebPartZoneBase base class provides the required context in which server controls can connect and exchan
oneBase ge data. You can inherit from the base class to create a custom zone, or use the WebPartZone control as the actu
al zone to contain the server controls involved in a connection.
WebPartZ
one

WebPartC Represents a connection, with references to the provider and consumer, and all the other required components of
onnection a connection.

Connectio The ConnectionPoint base class defines an object that is associated with a consumer or provider and contains th
nPoint e details necessary to exchange data. The ProviderConnectionPoint is associated with the provider, and the Con
sumerConnectionPoint is associated with the consumer.
ProviderC
onnection
Point
Consumer
Connectio
nPoint

Connectio Provides a UI that enables users to create run-time, dynamic connections between server controls.
nsZone

See Also
Tasks
How to: Declare a Static Connection between Two Web Parts Controls
Reference
Web Parts Control Set Overview
WebPartConnection
ConnectionPoint
Concepts
ASP.NET Web Parts Overview
ASP.NET

How to: Declare a Static Connection between Two Web Parts


Controls
Developers can create a static Web Parts connection between two server controls by declaring the connection in page
persistence format. A static connection becomes a permanent object on a Web page, like a declared control. All users can see a
static connection (because it is a shared object), and they can never delete the connection object, although they can disconnect
it if provided with the user interface (UI) options for doing so. Static connections are a good option when you want a
connection that is always available to all users, and you do not want users to have the option of deleting it from the page. For
details about connections, see WebPartConnection and Web Parts Connections Overview. For details about static connections,
see IsStatic. This topic demonstrates how to create a static connection between two WebPart controls.
Note
This topic focuses on showing how to declare a static connection in the markup of a Web page. To declare a static Web Parts
connection between two server controls, the controls must be properly designed to handle connections, and they must resid
e in a WebPartZoneBase zone. For a full description of the requirements for controls that participate in connections, see Web
PartConnection. To obtain the example code for the two WebPart controls and the Web page used to host the static conne
ction that is demonstrated in this topic, see the Example section for the IsStatic property.

To declare server controls within a zone


1. Add a <webpartzone> element within the body section of the Web page that will contain your connection, and add a
child <zonetemplate> element to contain the server controls that you add to the zone. The code should look like the
following example.

<asp:WebPartZone ID="WebPartZone1" runat="server">


<ZoneTemplate>
</ZoneTemplate>
</asp:WebPartZone>

2. Between the tags of the <zonetemplate> element, declare the server controls that will act as the provider and the
consumer controls in a Web Parts connection. These controls must already be designed to participate in connections. You
can also add other server controls to the zone. As noted previously in this topic, the controls declared in this example are
obtained from the example code found in the IsStatic property. The code for the entire zone with the server controls
looks like the following.

<asp:WebPartZone ID="WebPartZone1" runat="server">


<ZoneTemplate>
<aspSample:ZipCodeWebPart ID="zip1" runat="server"
Title="ZIP Code Provider" />
<aspSample:WeatherWebPart ID="weather1" runat="server"
Title="ZIP Code Consumer" />
</ZoneTemplate>
</asp:WebPartZone>

To declare a static connection


1. Your Web page should already have an <asp:webpartmanager> element, which is required on pages that use Web
Parts controls. Add a <staticconnections> element as a child of the <asp:webpartmanager> element to contain one
or more declared static connections. The code should look like the following example.

<asp:WebPartManager ID="mgr" runat="server" >


<StaticConnections>
</StaticConnections>
</asp:WebPartManager>
2. Within the <staticconnections> element, declare an <asp:webpartconnection> element. For the connection, you
must specify the following required attributes in addition to the id and runat attributes:
ConsumerID - Indicates the ID of the consumer control in the connection.
ConsumerConnectionPointID - Indicates the ID of a special callback method in the consumer used to establish
the connection. This attribute is required only if the consumer has more than one connection point. For details on
connection points, see ConnectionPoint.
ProviderID - Indicates the ID of the provider control in the connection.
ProviderConnectionPointID - Indicates the ID of a special callback method in the provider used to establish the
connection. This attribute is required only if the provider has more than one connection point.
The completed code for the <asp:webpartmanager> element and the child static connection should look like the
following example.

<asp:WebPartManager ID="mgr" runat="server" >


<StaticConnections>
<asp:WebPartConnection ID="conn1"
ConsumerConnectionPointID="ZipCodeConsumer"
ConsumerID="weather1"
ProviderConnectionPointID="ZipCodeProvider"
ProviderID="zip1" />
</StaticConnections>
</asp:WebPartManager>

See Also
Reference
WebPartConnection
IsStatic
Concepts
Web Parts Connections Overview
ASP.NET Web Parts Overview
ASP.NET

How to: Treat a User Control as a Web Parts Control


The ASP.NET Web Parts control set enables you to use existing Web server controls as Web Parts controls in order to achieve
maximum code reuse and to gain the benefits of Web Parts personalization. User controls are one type of server control you
can use as Web Parts controls. This topic demonstrates how to treat an existing user control as a Web Parts control.
Note
For this procedure to work, you need an ASP.NET Web site that can identify individual users. If you have such a site already c
onfigured, you can use that. Otherwise, for details on creating a virtual directory, see
How to: Create and Configure Virtual Directories in IIS. You also need a user control that is enabled to work with Web Parts p
ersonalization. If you do not have such a user control, a sample one is provided in the Code section.

When you use a user control in a Web Parts application, it takes on the full capabilities of a WebPart control at run time. For
details, see Using ASP.NET Server Controls in Web Parts Applications. The user control also retains its normal capabilities as a
server control, with one exception: output caching is disabled on user controls that are being used in Web Parts applications.
The Web Parts control set requires all controls to be added to the control tree for every page request. This is necessary so that
the personalization feature can work, and personalization data can be round-tripped to the controls. However, when output
caching is enabled on a user control, it is not added to the control tree, which would interfere with Web Parts features. This is
why output caching is disabled by design on user controls in Web Parts applications.
To create a Web Parts page to host the user control
1. Create a new ASP.NET page. Add the following page declaration at the top of the page.
VB
<@page language="VB" %>

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

2. Beneath the page declaration you just added, add the following basic page structure with HTML tags.

<html>
<head>
<title>Web Parts Demo Page</title>
</head>
<body>
<h1>Web Parts User Control Demonstration</h1>
<form runat="server">
<table cellspacing="0" cellpadding="0" border="0">
<tr>
<td valign="top">
</td>
<td valign="top">
</td>
<td valign="top">
</td>
</tr>
</table>
</form>
</body>
</html>

3. Save the page to a directory under the site that is enabled for personalization.
To add Web Parts controls to the page
1. Just below the <form> element in your page, add a WebPartManager control.

<asp:webpartmanager id="WebPartManager1" runat="server" />

2. Just below the <asp:webpartmanager> element, and within the table's first set of <td> tags (the first table column)
add a WebPartZone control to contain the user control that you will add in a later step.

<asp:webpartzone id="SideBarZone" runat="server"


headertext="Sidebar Zone">
<zonetemplate>
</zonetemplate>
</asp:webpartzone>

3. Within the <zonetemplate> element of the zone you just added, add an existing server control and some static content
that will be treated as another Web Parts control (since it is within a Web Parts zone) at run time:

<asp:label runat="server" id="linksPart" title="My Links">


<a href="www.asp.net">ASP.NET site</a>
<br />
<a href="www.gotdotnet.com">GotDotNet</a>
<br />
<a href="www.contoso.com">Contoso.com</a>
<br />
</asp:label>

4. Within the table's second set of <td> tags (the second table column) add another WebPartZone control to contain the
user control that you will add in a later step.

<asp:webpartzone id="MainZone" runat="server"


headertext="Main Zone">
<zonetemplate>
</zonetemplate>
</asp:webpartzone>

5. Within the table's third <td> element(the third column) add an <asp:editorzone> element. Add a <zonetemplate>
element, then add an <asp:appearanceeditorpart> and an <asp:layouteditorpart> element. The code in the editor
zone should look like the following:

<asp:editorzone id="EditorZone1" runat="server">


<zonetemplate>
<asp:appearanceeditorpart runat="server"
id="AppearanceEditorPart1" />
<asp:layouteditorpart runat="server"
id="LayoutEditorPart1" />
</zonetemplate>
</asp:editorzone>

6. Save the page.


To create a user control
1. Create a new file in your text editor. This file will contain a user control that can also be added to the page as a Web Parts
control.
Note
The search control for this walkthrough does not implement actual search functionality; it is used only to demonstrate
Web Parts features.

2. At the top of the new file, add a control declaration as shown in the following example.
VB
<%@ control language="VB" classname="SearchUserControl" %>

C#
<%@ control language="C#" classname="SearchUserControl" %>

3. Beneath the control declaration, add a pair of <script> tags, and within them add code to create a personalizable
property. Note that the ResultsPerPage property has a Personalizable attribute. This property would enable users of
the control to personalize how many search results to return per page, if you provided an edit control with the user
interface (UI) to change the setting in Design view. The code for your control should look like the following code example.
VB
<%@ control language="VB" classname="SearchUserControl" %>
<script runat="server">
Private results As Integer

<Personalizable()> _
Property ResultsPerPage() As Integer

Get
Return results
End Get

Set(ByVal value As Integer)


results = value
End Set

End Property
</script>

C#
<%@ control language="C#" classname="SearchUserControl" %>
<script runat="server">
private int results;

[Personalizable]
public int ResultsPerPage
{
get
{return results;}

set
{results = value;}
}
</script>

4. Add a text box and a button below the <script> element to provide the basic UI for a search control, as shown in the
following code example.
<asp:textbox runat="server" id="inputBox"></asp:textbox>
<br />
<asp:button runat="server" id="searchButton" text="Search" />

5. Name the file SearchUserControlVB.ascx or SearchUserControlCS.ascx (depending on which language you are using),
and save it in the same directory as the WebPartsDemo.aspx page.
Security Note
This control has a textbox that accepts user input, which is a potential security threat. User input in a Web page can pot
entially contain malicious client script. By default, ASP.NET Web pages validate user input to ensure that the input does
not contain HTML elements or script. As long as this validation is enabled, you do not need to explicitly check for script
or HTML elements in user input. For more information, see Script Exploits Overview.

To reference the user control within the main Web Parts zone
1. At the top of the Web page, just after the page declaration, add the following declaration to reference the user control
you just created. If you are not using the user control sample provided in this topic, the src attribute needs to be set to
the path and file name of the user control you are using, and you may also optionally assign a different value to the
tagname attribute.
[VB]

<%@ register tagprefix="uc1" tagname="SearchUserControl"


src="searchusercontrolvb.ascx" %>

[C#]

<%@ register tagprefix="uc1" tagname="SearchUserControl"


src="searchusercontrolcs.ascx" %>

2. Inside the <zonetemplate> element for the Main zone, reference the user control you created previously.

<uc1:SearchUserControl id="searchPart" runat="server"


title="Search" />

3. Save and close the page.

Example
The following code example provides a complete code listing of the sample Web Parts page used to host the user control. It
also provides code for the sample user control that is referenced in the page as a Web Parts control. Note that in order for the
user control to be treated as a true Web Parts control capable of personalization, it must expose a public property using the
[Personalizable] code attribute.
VB
<!-- Web Parts page to host the user control -->
<%@ page language="VB" %>
<%@ register tagprefix="uc1" tagname="SearchUserControl"
src="searchusercontrol.ascx" %>
<html>
<head>
<title>Web Parts Demo Page</title>
</head>
<body>
<h1>Web Parts User Control Demonstration</h1>
<form runat="server" id="form1">
<asp:webpartmanager id="WebPartManager1" runat="server" />
<asp:webpartpagemenu
id="pagemenu1"
runat="server"
Mode="Menu"
MenuStyle-BorderWidth="1">
<browsemodeverb text="Browse" />
<designmodeverb text="Design" />
<editmodeverb text="Edit" />
</asp:webpartpagemenu>
<table cellspacing="0" cellpadding="0" border="0">
<tr>
<td valign="top">
<asp:webpartzone id="SideBarZone" runat="server"
headertext="Sidebar Zone">
<zonetemplate>
<asp:label runat="server" id="linksPart" title="My Links">
<a href="www.asp.net">ASP.NET site</a>
<br />
<a href="www.gotdotnet.com">GotDotNet</a>
<br />
<a href="www.contoso.com">Contoso.com</a>
<br />
</asp:label>
</zonetemplate>
</asp:webpartzone>
</td>
<td valign="top">
<asp:webpartzone id="MainZone" runat="server"
headertext="Main Zone">
<zonetemplate>
<uc1:SearchUserControl id="searchPart" runat="server"
title="Search" />
</zonetemplate>
</asp:webpartzone>
</td>
<td valign="top">
<asp:editorzone id="EditorZone1" runat="server">
<zonetemplate>
<asp:appearanceeditorpart runat="server"
id="AppearanceEditorPart1" />
<asp:layouteditorpart runat="server"
id="LayoutEditorPart1" />
</zonetemplate>
</asp:editorzone>
</td>
</tr>
</table>
</form>
</body>
</html>

<!-- Web Parts user control -->


<%@ control language="VB" classname="SearchUserControl" %>
<script runat="server">
Private results As Integer

<Personalizable()> _
Property ResultsPerPage() As Integer

Get
Return results
End Get

Set(ByVal value As Integer)


results = value
End Set
End Property
</script>
<asp:textbox runat="server" id="inputBox"></asp:textbox>
<br />
<asp:button runat="server" id="searchButton" text="Search" />

C#
<!-- Web Parts page to host the user control -->
<%@ page language="C#" %>
<%@ register tagprefix="uc1" tagname="SearchUserControl"
src="searchusercontrol.ascx" %>

<html>
<head>
<title>Web Parts Demo Page</title>
</head>
<body>
<h1>Web Parts User Control Demonstration</h1>
<form runat="server" id="form1">
<asp:webpartmanager id="WebPartManager1" runat="server" />
<asp:webpartpagemenu
id="pagemenu1"
runat="server"
Mode="Menu"
MenuStyle-BorderWidth="1">
<browsemodeverb text="Browse" />
<designmodeverb text="Design" />
<editmodeverb text="Edit" />
</asp:webpartpagemenu>
<table cellspacing="0" cellpadding="0" border="0">
<tr>
<td valign="top">
<asp:webpartzone id="SideBarZone" runat="server"
headertext="Sidebar Zone">
<zonetemplate>
<asp:label runat="server" id="linksPart" title="My Links">
<a href="www.asp.net">ASP.NET site</a>
<br />
<a href="www.gotdotnet.com">GotDotNet</a>
<br />
<a href="www.contoso.com">Contoso.com</a>
<br />
</asp:label>
</zonetemplate>
</asp:webpartzone>
</td>
<td valign="top">
<asp:webpartzone id="MainZone" runat="server"
headertext="Main Zone">
<zonetemplate>
<uc1:SearchUserControl id="searchPart" runat="server"
title="Search" />
</zonetemplate>
</asp:webpartzone>
</td>
<td valign="top">
<asp:editorzone id="EditorZone1" runat="server">
<zonetemplate>
<asp:appearanceeditorpart runat="server"
id="AppearanceEditorPart1" />
<asp:layouteditorpart runat="server"
id="LayoutEditorPart1" />
</zonetemplate>
</asp:editorzone>
</td>
</tr>
</table>
</form>
</body>
</html>

<!-- Web Parts user control -->


<%@ control language="C#" classname="SearchUserControl" %>
<script runat="server">
private int results;

[Personalizable]
public int ResultsPerPage
{
get
{return results;}

set
{results = value;}
}
</script>
<asp:textbox runat="server" id="inputBox"></asp:textbox>
<br />
<asp:button runat="server" id="searchButton" text="Search" />

If you run the sample code and click the Display Mode page menu, you can alternate among the different personalization
modes on the menu: Browse, Design, and Edit. In Design mode, you can arrange the layout of the page by clicking in the
header of the two Web Parts controls and dragging them into other zones. In Edit mode, you can click the edit image in the
header of either of the Web Parts controls, and then set various UI properties on that control.
See Also
Tasks
Walkthrough: Creating a Web Parts Page
Concepts
ASP.NET Web Parts Overview
Using ASP.NET Server Controls in Web Parts Applications
ASP.NET

Securing Web Parts Pages


Web Parts is the new feature of ASP.NET that gives end users the ability to modify or personalize Web pages. Having
personalized Web pages is very enabling and powerful for users of Web applications, but it also has security implications that
developers should know about.
Web Parts Security Issues
Because Web Parts is a feature of ASP.NET, and Web Parts controls are extended ASP.NET server controls, Web Parts pages are
susceptible to all the same risks as ASP.NET pages. A Web application with pages that use Web Parts controls is really just a
specialized type of ASP.NET application, and an application that uses Web Parts can run in any trust level that an ordinary
ASP.NET application can. For general information about ASP.NET Web site security, see ASP.NET Web Site Security. However,
Web Parts has some unique security issues that normal ASP.NET pages do not have. These issues are discussed in the
following sections.
Importing Control Data
The Web Parts feature with the greatest security risks is the import feature. This feature allows a user to import an XML
description file that contains state and property data for a server control (the control's assembly file must already be available
on the Web server). Importing data for controls is a way for users to share data and easily configure complex controls. But the
inherent risk is that there could be malicious data in the description file. For example, if someone has placed malicious script
code as the value of a string property in the description file, then that script could potentially be executed when a user imports
the description file and adds the referenced server control to a Web page. To minimize the risk of importing description files
with malicious data, server controls that have string-typed properties should always encode the property data. Another risk
involves importing types through description files (see Web Parts Control Description Files). A malicious user could submit
requests to load many assemblies into the AppDomain, resulting in an excessive amount of memory being consumed. If you
want to avoid the risks associated with import, you can disable the feature altogether simply by not using the server control
that implements it. Or you can limit what users have access to the control. For instance, you could use role management, and if
a user is in the administrator role, you could programmatically add the ImportCatalogPart to the page for that user. For more
information about the control, see the reference topic for the ImportCatalogPart class.
Exporting Control Data
The export feature has nearly as much potential for risk as import, because it can expose sensitive data. Export enables users to
save the property and state data for a particular control into an XML description file. (This is the same file that can be imported
using the import feature.) The primary risk here is that users might export sensitive data out of the application and into the
description file, which is a simple text file that anyone with the proper permissions could read. Export is disabled by default in
ASP.NET, so if you do not need the feature, you can safely ignore it. This is clearly the most secure option.
If you do want to enable export, you should be aware of the options for determining which properties can be exported. When
you create a WebPart or server control that will be used in a WebPartZone zone, for each public property that you want to
make exportable, you can add the Personalizable metadata attribute. This makes the property exportable if export is enabled,
and it also raises a message box to the user, warning that the data will be exported. One of the parameters of the
Personalizable attribute is called IsSensitive. This Boolean parameter is useful if you have a property that you want to be
exportable in some situations, but not in others. For details and an example, see the reference topic for the ExportMode
property.
Understanding Personalization Details
Web Parts personalization is the feature that enables users to modify Web pages to suit their preferences, and to save their
settings in long-term storage, so that the personalized pages retain the settings across browser sessions. Most Web Parts
features require personalization; therefore, it is enabled by default in ASP.NET Web sites, although it is used only on pages that
contain Web Parts controls. Because personalization is such a powerful feature, it also carries some degree of risk. Users are
able to modify the actual layout, appearance, and even the content and controls on a Web page. The personalization data is
stored in a database and is used to render pages, so users have a lot of potential for malicious activity relating to the content of
a site. Users that have access to shared personalization scope can even change the way pages will appear for all users.
If you have a particular page that uses Web Parts features but does not require personalization (for example, one of the
common pages in a portal site), it is a good practice to disable personalization, because this enhances performance and
reduces your site's exposure to security risks. For more information, see How to: Disable Web Parts Personalization.
Authenticating Users for Personalization
Personalization requires authenticated users. You cannot enable personalization for anonymous users. This means that to have
full personalization and Web Parts functionality, your Web site must use Windows or Forms-based authentication. For
information about authentication options, see Basic Security Practices for Web Applications (Visual Studio). To set up a site
using the new membership feature (which uses Forms authentication), see Managing Users by Using Membership.
Granting Minimal Access to Shared Personalization
Web Parts personalization changes always apply to a given range or scope of users. Changes made in user scope are visible
only to the user making the changes, whereas changes made in shared scope are visible to all users. Shared personalization
scope exists so that users in a manager or administrative role can make changes to a page that apply to all users of a site. By
default, all users are denied access to shared scope. Only selected users should be given access, which must be done explicitly
in a Web site's configuration file. For details, see How to: Enable Shared Personalization of Web Parts Pages.
Using Tested and Trusted Controls
Because Web Parts provides users with powerful capabilities, such as the ability to add new server controls to a page,
developers should be very cautious about which server controls they use within a Web Parts application. Server controls,
especially ones from third parties or vendors, should be carefully reviewed and tested to ensure that they can be trusted for
use in a Web Parts application. For example, suppose a particular server control is poorly designed and inefficient in its
memory usage. If you add that control to a Web Parts catalog, users can add it to a Web page. And because a control in a
catalog can be added to a page any number of times (multiple instances), a user could add the poorly performing control
multiple times, which could effectively generate a denial of service attack when the page tries to process many instances of the
control. For more information about Web Parts catalogs, see the reference topic for the CatalogPart class.
Using Authorization and Filtering on Controls
Web Parts has a feature that enables you to set and check the authorization level for the server controls you use to create the
user interface (UI) of your Web Parts pages. If a control is authorized based on the criteria you set, it will appear on the page,
and if it is authorized at some reduced level or not at all, you can change its appearance accordingly, or hide it altogether. For
example, suppose you have a user who is designated as an administrator. There might be a server control that you want to be
visible only to the administrator. Using the authorization and filtering features of Web Parts, you could make sure that this
control appears only to a designated administrator, and is hidden from other users. The primary mechanisms for using
authorization and filtering are the AuthorizationFilter property of the WebPart class, and the IsAuthorized and
OnAuthorizeWebPart methods of the WebPartManager class.
Encoding String-Typed Properties in Editing Controls
One unique feature of Web Parts is that end users can switch a page into an editing mode, and they can edit a server control by
changing its layout, appearance, behavior, and its personalizable property values. But this presents some risk, because a
malicious user could insert inappropriate data, or attempt a script injection attack, using the ability to edit string-typed
properties. As a security practice, if you create custom EditorPart controls to edit server controls, and if any of the
personalizable properties in a given server control are of a string type or use a string converter, your EditorPart control
should encode the string data before assigning it to the property. For an example, see the reference documentation on the
HtmlEncode method.
See Also
Reference
System.Web.UI.Design.WebControls.WebParts
Other Resources
ASP.NET Web Parts Pages
ASP.NET

Using ASP.NET Server Controls in Web Parts Applications


In a Web Parts application, the primary user interface (UI) consists of ASP.NET server controls that reside within zones--regions
on a Web page that have a common UI and are created by a type of composite control derived from the WebPartZoneBase
class. The capabilities of these server controls that form the primary UI of a Web Parts application are defined in the base
WebPart class, but you are not limited to using controls that derive from this class. You can also use any standard ASP.NET
server control, user control, or custom server control. This topic discusses some issues about using server controls in Web
Parts applications when the controls do not inherit from the WebPart class.
Creating Run-Time Web Parts Controls
For the various kinds of server controls that do not inherit from the WebPart class, the Web Parts control set provides a
mechanism that enables them to participate in Web Parts applications and to have the same capabilities as a control derived
from the WebPart class. This does not require any special action by developers; all that is necessary is to add a server control
to a WebPartZoneBase zone. When a Web page is compiled, any server control that resides in a zone and does not inherit
from the WebPart class is automatically wrapped with an instance of the GenericWebPart class, and becomes a child control
of that instance. Because the GenericWebPart class inherits from the WebPart class, the server control is now enabled with
the full functionality of a WebPart control. In essence, by adding server controls that do not inherit from the WebPart class to
a WebPartZoneBase zone, developers enable the controls to become run-time WebPart controls.
Note
Just as you can use server controls in Web Parts applications, you can also use WebPart controls outside of Web Parts applic
ations. If you add a control that inherits from the WebPart class to a page outside of a zone, it functions as a normal server c
ontrol and simply loses its Web Parts capabilities.

Adding ASP.NET Server Controls to Zones


When you add ASP.NET server controls, user controls, or custom controls to a WebPartZoneBase zone, no special techniques
or declarations on the page are required. You can add them to a zone in the same ways that you would normally add controls
to a Web page: declaratively (in the page persistence format), or programmatically. In addition, you can use the Web Parts
catalog feature, which enables you to add server controls to a catalog from which users can select and add controls to the page
at run time. For more information, see the DeclarativeCatalogPart and ImportCatalogPart controls.
If you add a server control to a zone programmatically, the recommended approach is to add it by using the AddWebPart
method of the WebPartManager control.
When you add server controls that are not WebPart controls declaratively to a zone, if you use a visual design tool such as
Microsoft Visual Studio 2005, you will not see WebPart properties and members in the properties pane or in IntelliSense. For
more information, see the following section that discusses when to use WebPart controls versus using other server controls.
Deciding When to Use Different Server Control Options
Because you can use any kind of server control in a Web Parts application, you might wonder if there is ever any reason to
create a control that derives from the WebPart class.
The key factors you must consider are the advantages of adapting preexisting server controls versus creating new ones by
deriving from the WebPart class. The following guidelines might help in your decision.
Using Server Controls
In many cases, the preferred option to create Web Parts controls is to use an ASP.NET server control, a user control, or a
custom control, particularly if the controls already exist. You do not lose any run-time Web Parts functionality when you use
these kinds of server controls, and you gain many advantages such as the ability to reuse existing code, and the ability to
leverage your knowledge of control development and apply it to Web Parts applications.
You can also make the various server controls behave identically to true WebPart controls by implementing several interfaces
that the WebPart class implements. These include:
The IWebActionable interface. If you implement this interface, you will be able to add custom verbs (common actions that
users can carry out on a control in the UI, such as minimize, close, or edit) to the verbs menu of your control.
The IWebEditable interface. If you implement this interface, you can associate custom EditorPart controls with your server
control, enabling users to edit specified custom properties and behavior on the control at run time.
The IWebPart interface. If you implement this interface, your control will have a number of the properties of a true
WebPart control that is inherited from the Part class, which give it the same look and feel as a WebPart control, even at
design time.
Deriving from WebPart
The main benefit of creating a control by deriving from the WebPart class is that you gain full control over its Web Parts-
specific behavior.
An example of this occurs when a control developer wants to change the run-time behavior of a control, and then redistribute
it to users. A developer could override one of the WebPart class's virtual properties--such as AllowClose--and make it a read-
only property that always returns false. This prevents the control from ever being closed, and users of the control are limited
to that behavior.
A second example where you can benefit by inheriting from the WebPart class relates to design-time behavior. On a WebPart
control, all the exposed WebPart members are visible to page developers at design time through IntelliSense (if they use a
visual design tool such as Microsoft Visual Studio 2005), so that they can work with the properties in declarative mode and in
the Properties pane. In contrast, if you declare server controls in a zone at design time, and they are not WebPart controls,
you cannot see any members that are specific to the WebPart class (although you can still declare them) in IntelliSense or in
the Properties pane. That is because at design time, an ordinary server control has not yet been wrapped with a
GenericWebPart object, so it does not have the WebPart features it will have at run time. Although you can enable server
controls to look and act like WebPart controls by implementing the interfaces listed above, often it is more straightforward to
simply create a WebPart control. Control developers and vendors who create packages of controls can benefit from deriving
from the WebPart class so that they can provide richer design-time features for their controls.
Conclusions
In conclusion, if you do not need to override the controls' standard properties, you might find it easier to use the pre-existing
server controls and make them parts of the WebPart control.
If you decide to create a custom WebPart control, the following are the properties that you can potentially override:
AllowClose
AllowConnect
AllowEdit
AllowHide
AllowMinimize
AllowZoneChange
AuthorizationFilter
ChromeState
ChromeType
Direction
ExportMode
HelpMode
HelpUrl
Hidden
ImportErrorMessage
User Controls as WebPart Controls
User controls are a powerful option for ASP.NET developers, because they enable developers to quickly build a complex UI for
a control using the same declarative syntax that is used in Web pages. They also provide a convenient way to partition and
reuse code across multiple pages. As ASP.NET server controls, user controls are also an excellent option to use in Web Parts
applications. User controls can be added directly to a WebPartZoneBase zone, and they will function as run-time WebPart
controls, as described above. They can also be used with the Web Parts catalog feature, either as controls that can be imported,
or to package a set of other server controls that users can select and add to a page (for more information, see the
WebPartsListUserControlPath property).
Important
You should be aware that ASP.NET output caching is disabled on user controls being used as run-time WebPart controls. Th
e Web Parts control set requires that a control be in the control tree for each request to a page. This is necessary for certain
Web Parts features such as personalization (for more information, see Web Parts Personalization Overview) to work. On req
uests where a user control is cached (for more information, see the @ OutputCache directive), it is not added to the control tr
ee. For this reason, output caching is incompatible with Web Parts features, and does not work with user controls that are fun
ctioning as WebPart controls in a Web Parts application.

See Also
Reference
WebPart
GenericWebPart
WebPartZoneBase
Other Resources
ASP.NET User Controls
ASP.NET

Web Parts Control Description Files


Web Parts control description files contain property values, state data, and assembly or source file details exported from a
WebPart control (or other ASP.NET server or user control used in a Web Parts application) to an XML file with a .WebPart
extension. A description file is used by the Web Parts import feature to import the control it describes into a Web Parts page,
and to configure the imported control with the saved data. This topic describes the basic structure and XML elements included
in a description file.

<webParts>
<webPart>
<metaData>
<type …/>
<importErrorMessage …/>
</metadata>
<data>
<properties>
<ipersonalizable>
<property …/>
</ipersonalizable>
<property …/>
</properties>
<genericWebPartProperties>
<ipersonalizable>
<property …/>
</ipersonalizable>
<property …/>
</genericWebPartProperties>
</data>
</webPart>
</webParts>

Remarks
The following table lists each element that can be included in a Web Parts description file (with the element's immediate child
elements indented beneath it), lists any attributes that exist on that element, and summarizes what the element is used for.
Note that, if a control implements the IPersonalizable interface, the appropriate <ipersonalizable> child element appears and
contains the implemented properties as <property> elements; otherwise, the <ipersonalizable> element does not appear in
the file.
Ele Attributes Summary
me
nt
we None. The parent element in the file; it can occur once per file. The logic of the XML is th
bPa at this element could contain multiple <webPart> elements per file, but as curre
rts ntly implemented there is one <webPart> in a description file.
we
bPa
rt

we xmlns="http://schemas.microsoft.c Represents the control whose state and property data are contained in the file. C
bPa om/WebPart/v3" urrently, there can only be one <webPart> element per file.
rt
Note
me This is a namespace attribute with a fix
taD ed value.
ata
dat
a
met None. Contains information about the type of the <webPart> element and a message
aDa to display to users if there are errors during the import process. One instance per
ta <webPart> element.
typ
e
im
port
Erro
rMe
ssag
e

typ The type element must have either a n Lists type information for an assembly that contains a <webPart> element, or th
e ame or a src attribute specified, and ca e path of a source file if <webPart> represents a user control. One instance per
n have both. If both are specified, name <webPart> element.
takes precedence.
The value of the name attribute consist
s of a string with type and (optional) ass
embly information about the <webPar
t> element.
The src attribute provides a path to the
source file of a user control.

imp None. Contains the text of a message displayed to users if an error occurs during the i
ortE mport process. One instance per <webPart> element.
rror
Mes
sag
e

dat None. Contains the state and property values data for the <webPart> element. One ins
a tance per <webPart> element.
pr
ope
rties
ge
neri
cWe
bPa
rtPr
ope
rties

pro None. Contains <property> elements, a single <ipersonalizable> element (which co


pert ntains child <property> elements), or both. The <properties> element is alway
ies s present, but will only have child <property> elements if <webPart> has pers
onalizable properties. One instance per <webPart> element.
ipe
rson
aliza
ble
pr
ope
rty
gen None. Contains <property> elements, a single <ipersonalizable> element (which co
eric ntains child <property> elements), or both. This element is only present if the c
We ontrol that corresponds to <webPart> does not inherit from the WebPart class.
bPa One instance per <webPart> element.
rtPr
ope
rtie
s
ipe
rson
aliza
ble
pr
ope
rty

iper None. A child of both the <properties> element and the <genericWebPartPropertie
son s> element. This element appears only if the control that corresponds to the <w
aliz ebPart> element implements the IPersonalizable interface. It contains one or
abl more <property> elements. One instance per <webPart> element.
e
pr
ope
rty
pro The property element has three attribut A child of the <properties>, <genericWebPartProperties>, and <ipersonaliz
pert es: name, type, and null. The name an able> elements. This element contains name/value pairs for each property value
y d type attributes are required; null is u or state data item within the <webPart> element. The actual data for a property
sed only if the property has a null value is contained between the <property> element tags, and the name and type of th
. e property item are specified by attributes. There can be zero to many <propert
y> elements within the three types of parent elements that contain them.
The name attribute is the name of a par
ticular property on the control that corr
esponds to the <webPart> element.
The null attribute can take a value of tr
ue or false; it is used only when a prop
erty actually has a null value, to disting
uish that value from an empty string (""
) value.
The type attribute identifies the Type of
the property referenced in the name att
ribute. The actual value of type can be a
string with a fully qualified type name,
or it can be a string that uses one of the
abbreviated type names listed below.
* string
* int
* bool
* double
* single
* datetime
* color
* unit
* fontsize
* object
* direction (represents
ContentDirection)
* helpmode (represents
WebPartHelpMode)
* chromestate (represents
PartChromeState)
* chrometype (represents
PartChromeType)
* exportmode (represents
WebPartExportMode)
Example
The following code examples demonstrate two .WebPart description files that were exported from instances of controls in a
Web Parts application. The first example shows a file for a control that inherits from the base WebPart class. Note that its
property data is all contained within the <properties> section. The second example shows a file for an ASP.NET server control
that does not inherit from the WebPart class. Note that its property data is all contained within the
<genericWebPartProperties> section.

<!-- File exported from a System.Web.UI.WebControls.WebParts.WebPart


control. -->
<?xml version="1.0" encoding="utf-8"?>
<webParts>
<webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
<metaData>
<type name="Samples.AspNet.CS.Controls.TextDisplayWebPart,
App_Code.zq0cecf5, Version=0.0.0.0, Culture=neutral,
PublicKeyToken=null" />
<importErrorMessage>
Cannot import this Web Parts control.
</importErrorMessage>
</metaData>
<data>
<properties>
<property name="AllowClose" type="bool">True</property>
<property name="Width" type="unit" />
<property name="AllowMinimize" type="bool">True</property>
<property name="ContentText" type="string" null="true" />
<property name="AllowConnect" type="bool">True</property>
<property name="ChromeType" type="chrometype">
Default
</property>
<property name="TitleIconImageUrl" type="string" />
<property name="Description" type="string" />
<property name="Hidden" type="bool">False</property>
<property name="TitleUrl" type="string" />
<property name="AllowEdit" type="bool">True</property>
<property name="Height" type="unit" />
<property name="HelpUrl" type="string" />
<property name="Title" type="string" />
<property name="CatalogIconImageUrl" type="string" />
<property name="Direction" type="direction">
NotSet
</property>
<property name="ChromeState" type="chromestate">
Normal
</property>
<property name="AllowZoneChange" type="bool">True</property>
<property name="AllowHide" type="bool">True</property>
<property name="HelpMode" type="helpmode">Navigate</property>
<property name="ExportMode" type="exportmode">All</property>
</properties>
</data>
</webPart>
</webParts>

<!-- File exported from a System.Web.UI.WebControls.BulletedList


control placed in a Web Parts zone. -->
<?xml version="1.0" encoding="utf-8"?>
<webParts>
<webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
<metaData>
<type name="System.Web.UI.WebControls.BulletedList,
System.Web, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a" />
<importErrorMessage>
Cannot import this Web Parts control.
</importErrorMessage>
</metaData>
<data>
<properties />
<genericWebPartProperties>
<property name="AllowClose" type="bool">True</property>
<property name="Width" type="unit" />
<property name="AllowMinimize" type="bool">True</property>
<property name="AllowConnect" type="bool">True</property>
<property name="ChromeType" type="chrometype">
Default
</property>
<property name="TitleIconImageUrl" type="string" />
<property name="Description" type="string" />
<property name="Hidden" type="bool">False</property>
<property name="TitleUrl" type="string" />
<property name="AllowEdit" type="bool">True</property>
<property name="Height" type="unit" />
<property name="HelpUrl" type="string" />
<property name="Title" type="string">
Favorite Links
</property>
<property name="CatalogIconImageUrl" type="string" />
<property name="Direction" type="direction">
NotSet
</property>
<property name="ChromeState" type="chromestate">
Normal
</property>
<property name="AllowZoneChange" type="bool">
True
</property>
<property name="AllowHide" type="bool">True</property>
<property name="HelpMode" type="helpmode">
Navigate
</property>
<property name="ExportMode" type="exportmode">
All
</property>
</genericWebPartProperties>
</data>
</webPart>
</webParts>

See Also
Reference
ExportWebPart
ImportWebPart
ExportMode
ImportCatalogPart
ASP.NET

Creating a Data-bound Web Parts Control


By inheriting from the WebPart base class, you can give Web Parts capabilities to an ordinary data-bound server control. In
Web Parts applications, end users are able to modify (personalize) the behavior and user interface (UI) of server controls, and
have their settings saved in long-term storage for future browser sessions. Users can drastically change the look and feel of a
page by adding or removing controls, editing the properties and appearance of controls, rearranging the page layout,
importing or exporting settings for the controls, and even forming connections that enable controls to share data. To learn
more about Web Parts applications, see the topics listed in ASP.NET Web Parts Pages. This topic describes the prerequisites for
using a custom, data-bound WebPart control (or any server control) in a Web Parts application, and summarizes some
members of the base WebPart class that are often useful to implement or override when creating a custom control. An
example of overriding and implementing some of these members is provided in the topic
Data-bound Web Parts Control Example.
Required Elements for using a Web Parts Control
No Web Parts control can run in isolation and still retain its Web Parts features. If you run a WebPart control in a Web
application without the other required elements for a Web Parts application, the control simply loses its Web Parts features
and functions as an ordinary server control. The following list explains the required elements that must be in place before you
can use a custom WebPart control with Web Parts features:
The WebPartManager control. This control must be present on every page that offers Web Parts functionality. For details,
see Web Parts Control Set Overview.
A WebPartZoneBase zone control. A Web page must have a zone that derives from this abstract class, such as the
WebPartZone control, to contain WebPart controls. For details, see Web Parts Control Set Overview.
An ASP.NET Web site that can recognize individual users, using Windows or Forms authentication. For details on creating
a virtual directory or site, see How to: Create and Configure Virtual Directories in IIS or
How to: Create and Configure Local ASP.NET Web Sites in IIS.
A configured personalization provider and database, to store user settings on controls. Web Parts personalization is
enabled by default, and it uses the SQL personalization provider (SqlPersonalizationProvider) with the Microsoft SQL
Server Express (SSE) edition to store personalization data. This walkthrough uses SSE and the default SQL provider. If you
have SSE installed, no configuration is needed. SSE is available with Microsoft Visual Studio 2005 as an optional part of
the installation, or as a free download from Microsoft.com. To use one of the full versions of Microsoft SQL Server, you
must install and configure an ASP.NET application services database, and configure the SQL personalization provider to
connect to that database. For details, see Creating and Configuring the Application Services Database for SQL Server. You
can also create and configure a custom provider to use with other, non-SQL databases or storage solutions. For details
and a code example, see Implementing a Membership Provider.
Commonly Overridden or Used WebPart Members
Although any type of server control can be used in Web Parts applications, there are some benefits to creating custom
WebPart controls (for details, see Using ASP.NET Server Controls in Web Parts Applications). When you inherit from the
WebPart base class, there are no required members to implement. There are, however, some commonly used members that
you might want to use or override, and these are summarized in the following table. For a complete example of a data-bound
server control implemented as a WebPart control, see Data-bound Web Parts Control Example. The following table
summarizes some of the commonly used members.
Member Description
WebPart A common usage for this constructor is to set default values on some of the properties that determine
the appearance and behavior of a WebPart control, like the properties inherited from the Part class, or
behavioral properties such as the AllowEdit and AllowLayoutChange properties.

Behavioral properties This includes a number of the "Allow" properties of the class, such as AllowClose, AllowConnect, Allow
Edit, AllowMinimize, AllowLayoutChange, and AllowZoneChange. Rather than simply assign default
values to these properties in the constructor, developers can completely control a property, for exampl
e by preventing users or developers who use the control from ever being able to close the control.
CreateChildControls When you inherit from the WebPart class, you need to provide a UI for your custom control. A very ef
fective way of doing this is to override the CreateChildControls method and, in this method, add oth
er server controls to make up the UI of your custom control. You might need to carry out additional tas
ks when you add these controls, such as creating custom event handlers for them, or binding them to
a data source.

Rendering methods You might need to override common rendering methods such as RenderControl or RenderContents. I
n these methods, you can either completely override the rendering, or call the base method first, and t
hen modify some aspect of the rendering.

Verbs If you create custom WebPartVerb objects that will appear on the verbs menu of your control with the
standard verbs (such as close and minimize), you must add them to the Verbs collection of your contr
ol.

CreateEditorParts If you create custom EditorPart controls, to enable users to edit the custom properties on your control,
you must associate them with your control by overriding the CreateEditorParts method. For an exam
ple, see the IWebEditable interface.

PersonalizableAttribute When you create custom properties in your WebPart control, you will often want users to be able to e
dit and personalize those properties, just like the standard WebPart control properties, so that their se
ttings can be saved. Add the Personalizable metadata attribute to any property that users should be a
ble to personalize.

Sample Data-bound WebPart Control


For a full code example that demonstrates how to create a GridView control that binds to the Northwind database, and
implements the control as a WebPart control, see Data-bound Web Parts Control Example.
See Also
Tasks
Walkthrough: Creating a Web Parts Page
Reference
WebPart
Concepts
ASP.NET Web Parts Overview
Other Resources
ASP.NET Web Parts Pages
ASP.NET

How to: Build and Run the Data-bound Web Parts Control
Example
This topic contains instructions for building and running the data-bound WebPart control, for which a complete code example
is provided in the topic Data-bound Web Parts Control Example. The code example demonstrates how to create a custom
server control that binds a GridView control to a data source, but also inherits from the WebPart class so that it can participate
in Web Parts applications. This topic gives the related information you will need to compile the code example and configure an
ASP.NET Web application to run the control as a Web Parts control.
Compiling the WebPart Control
For the code example to run, you must compile this source code. You can compile it explicitly and put the resulting assembly in
your Web site's Bin folder or the global assembly cache. Alternatively, you can put the source code in your site's App_Code
folder, where it will be dynamically compiled at run time. This code example uses dynamic compilation. For a walkthrough that
demonstrates how to compile, see Walkthrough: Developing and Using a Custom Server Control.
To dynamically compile the data-bound WebPart control
1. In the root folder of your Web application, create a folder named App_Code.
2. Obtain the source code for the custom data-bound WebPart control from the topic
Data-bound Web Parts Control Example. Place the source code file in the App_Code folder. The name of the file does not
matter because you are using dynamic compilation, but the file must have the appropriate extension for the language
you are using (such as .cs or .vb).

Using the Control in a Web Parts Application


Configuring an application to use Web Parts requires only that you have an ASP.NET Web site that can authenticate individual
users, and a database enabled to handle application services including personalization. For this example (because it uses a
data-bound control), you also need to create a connection string in the Web.config file that enables the data source to connect
to the Northwind sample database. After the application is configured, in every Web Parts application you need to add a
WebPartManager control and at least one WebPartZone control to each Web page that will host the WebPart and server
controls in your Web Parts application. The second procedure below demonstrates how to add these controls, and to carry out
the other steps needed to prepare the page to run the data-bound control.
To configure an ASP.NET application to run Web Parts controls
1. Ensure that you have an ASP.NET Web application that is configured to recognize individual users. If you need directions
on how to create such a site, see How to: Create and Configure Virtual Directories in IIS or
How to: Create and Configure Local ASP.NET Web Sites in IIS.
2. Ensure that you have a configured personalization provider and database. Web Parts personalization is enabled by
default, and it uses the SQL personalization provider (SqlPersonalizationProvider) with the Microsoft SQL Server Express
(SSE) edition to store personalization data. This topic uses SSE and the default SQL provider. If you have SSE installed, no
configuration is needed. SSE is available with Microsoft Visual Studio 2005 as an optional part of the installation, or as a
free download from Microsoft.com. To use one of the full versions of Microsoft SQL Server, you must install and
configure an ASP.NET application services database, and configure the SQL personalization provider to connect to that
database. For details, see Creating and Configuring the Application Services Database for SQL Server. You can also create
and configure a custom provider to use with other, non-SQL databases or storage solutions. For details and a code
example, see Implementing a Membership Provider.
3. Create a connection string so that the data-bound control can connect to the sample Northwind database. To run the
example, you will need access to the sample Northwind database provided with SQL Server. If you do not have the
Northwind sample database installed, you can download scripts to create and install the database from the
Microsoft Download Center.
A recommended approach for connection strings is to place them in the Web.config file for your application. For more
information about configuration files, see ASP.NET Configuration Files. The following code example shows a connection
string in the Web.config file, connecting to a local instance of Northwind running on SSE. Note that the single quotation
marks (') that would normally delimit the path to the database file are rendered as entities (&quot;). This is required
because Web.config is an XML file.
<connectionStrings>
<add name="nwind"
connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=
&quot;C:\SQL Server 2000 Sample Databases\NORTHWND.MDF&quot;;
Initial Catalog=Northwind;Integrated Security=True;"
providerName="System.Data.SqlClient" />
</connectionStrings>

Note
It is recommended that you encrypt any sensitive information such as a password contained in a connection string. For
details on encrypting configuration data, see
Walkthrough: Encrypting Configuration Information Using Protected Configuration.

4. In the <system.web> section of the Web.config file, add a <webparts> element. This is not required for every Web
Parts application, but certain features of Web Parts applications must be configured in this section if you want to use
them. The sample data-bound WebPart control is enabled for exporting a configuration file containing its state and
property data. Because the export feature is disabled by default in Web Parts applications, you must enable it in the
<webParts> section. Add an enabledExport attribute to the <webParts> element and set its value to true, as in the
following code example.

<webParts enableExport="true" />

5. Save and close the Web.config file.

To prepare a Web page to host Web Parts controls


1. Create a user control that will enable users to switch between the available Web Parts display modes on the Web page.
This control and the next step are not required to run the data-bound Web Parts control, but this is a feature that is useful
on many Web Parts pages. In an editor, paste the following code for the user control, and save the file in your Web
application's root folder with the name Displaymodemenucs.ascx or Displaymodemenuvb.ascx (depending on which
language you are using).
VB
<!-- This user control recognizes what display modes are possible
on a page, given the zones that are present, and enables users to
switch among the display modes. -->
<%@ control language="vb" classname="DisplayModeMenuVB"%>

<script runat="server">

' Use a field to reference the current WebPartManager.


Dim _manager As WebPartManager

Sub Page_Init(ByVal sender As Object, ByVal e As EventArgs)


AddHandler Page.InitComplete, AddressOf InitComplete

End Sub

Sub InitComplete(ByVal sender As Object, ByVal e As System.EventArgs)


_manager = WebPartManager.GetCurrentWebPartManager(Page)

Dim browseModeName As String = WebPartManager.BrowseDisplayMode.Name

' Fill the dropdown with the names of supported display modes.
Dim mode As WebPartDisplayMode
For Each mode In _manager.SupportedDisplayModes
Dim modeName As String = mode.Name
' Make sure a mode is enabled before adding it.
If mode.IsEnabled(_manager) Then
Dim item As New ListItem(modeName + " Mode", modeName)
DisplayModeDropdown.Items.Add(item)
End If
Next mode

End Sub

' Change the page to the selected display mode.


Sub DisplayModeDropdown_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventA
rgs)
Dim selectedMode As String = DisplayModeDropdown.SelectedValue

Dim mode As WebPartDisplayMode = _manager.SupportedDisplayModes(selectedMode)


If Not (mode Is Nothing) Then
_manager.DisplayMode = mode
End If

End Sub

Sub Page_PreRender(ByVal sender As Object, ByVal e As EventArgs)


DisplayModeDropdown.SelectedValue = _manager.DisplayMode.Name

End Sub

</script>
<div>
<asp:DropDownList ID="DisplayModeDropdown"
runat="server"
AutoPostBack="true"
OnSelectedIndexChanged="DisplayModeDropdown_SelectedIndexChanged" />
</div>

C#
<!-- This user control recognizes what display modes are possible
on a page, given the zones that are present, and enables users to
switch among the display modes. -->
<%@ control language="C#" classname="DisplayModeMenuCS"%>

<script runat="server">

// Use a field to reference the current WebPartManager.


WebPartManager _manager;

void Page_Init(object sender, EventArgs e)


{
Page.InitComplete += new EventHandler(InitComplete);
}

void InitComplete(object sender, System.EventArgs e)


{
_manager = WebPartManager.GetCurrentWebPartManager(Page);

String browseModeName = WebPartManager.BrowseDisplayMode.Name;

// Fill the dropdown with the names of supported display modes.


foreach (WebPartDisplayMode mode in _manager.SupportedDisplayModes)
{
String modeName = mode.Name;
// Make sure a mode is enabled before adding it.
if (mode.IsEnabled(_manager))
{
ListItem item = new ListItem(modeName + " Mode", modeName);
DisplayModeDropdown.Items.Add(item);
}
}

// Change the page to the selected display mode.


void DisplayModeDropdown_SelectedIndexChanged(object sender,
EventArgs e)
{
String selectedMode = DisplayModeDropdown.SelectedValue;

WebPartDisplayMode mode = _manager.SupportedDisplayModes[selectedMode];


if (mode != null)
_manager.DisplayMode = mode;

void Page_PreRender(object sender, EventArgs e)


{
DisplayModeDropdown.SelectedValue = _manager.DisplayMode.Name;
}

</script>
<div>
<asp:DropDownList ID="DisplayModeDropdown"
runat="server"
AutoPostBack="true"
OnSelectedIndexChanged="DisplayModeDropdown_SelectedIndexChanged" />
</div>

2. Create a new ASP.NET page to host the custom WebPart control and the other controls. Add a Register directive to the
page, just below the Page directive, to register the user control you just created. The directive contents depend on which
language you are using, and should look like the following example.
[Visual Basic]

<%@ register src="displaymodevb.ascx" tagname="displaymodevb"


tagprefix="uc1" %>

[C#]

<%@ register src="displaymodecs.ascx" tagname="displaymodecs"


tagprefix="uc1" %>
3. Now add a Register directive for the custom WebPart control. Because this topic uses dynamic compilation, you do not
need to add an Assembly attribute to the directive. Just below the previous directive in the file, add another Register
directive, assign an arbitrary string to its tagprefix attribute, and assign the namespace of the custom control to the
namespace attribute, again depending on the language you used, as in the following example.
[Visual Basic]

<%@ register tagprefix="aspSample"


namespace="Samples.AspNet.VB.Controls" %>

C#
<%@ register tagprefix="aspSample"
namespace="Samples.AspNet.CS.Controls" %>

4. Add an <asp:webpartmanager> element to the page, just inside the <form> element, as shown in the following code
example. A WebPartManager control is required on every page that uses Web Parts.

<asp:webpartmanager id="WebPartManager1" runat="server">


</asp:webpartmanager>

5. Declare the user control for switching display modes, just after the <asp:webpartmanager> element. How you declare
the control depends on which language you are using, as in the following code example.
[Visual Basic]

<uc1:displaymodevb id="Displaymodevb1" runat="server" />

C#
<uc1:displaymodecs id="Displaymodecs1" runat="server" />

6. After the user control, add a table with one row and two columns, to structure the layout of the controls on the page. The
table markup should look like the following code example.

<table style="width: 80%; position: relative">


<tr valign="top">
<td style="width: 40%">
</td>
<td style="width: 40%">
</td>
</tr>
</table>

7. Within each set of <td> tags, add an <asp:webpartzone> element. A zone that derives from the WebPartZoneBase
class is required to contain WebPart controls and enable them to have full Web Parts functionality. The markup for the
first zone should look like the following code example.

<asp:webpartzone id="WebPartZone1" runat="server"


style="position: relative" >
<parttitlestyle font-size="14" font-names="Verdana" />
<zonetemplate>
</zonetemplate>
</asp:webpartzone>

The markup for the second zone should look like this.
<asp:webpartzone id="WebPartZone2" runat="server"
style="position: relative" >
<zonetemplate>
</zonetemplate>
</asp:webpartzone>

8. Declare the custom data-bound WebPart control in the first zone, between the <zonetemplate> tags, as shown in the
following code example. Note that the markup uses the tag prefix defined in the Register directive for the control, as well
as the class name for the custom control. Also note that a custom property defined in the control--ConnectionString--
appears as an attribute with the connection string from the Web.config file assigned to it. This approach enables page
developers to determine what connection string to use for the control. The markup should look like this.

<aspSample:SmallGridWebPart id="grid1" runat="server"


title="Customer Phone List" width="300"
connectionstring="<%$ ConnectionStrings:nwind %>" />

9. For comparison purposes, declare an ordinary calendar server control in the second zone, between the
<zonetemplate> tags. Because you are placing the control in a WebPartZone control, it will behave like a WebPart
control at run time. For details on using server controls in Web Parts applications, see
Using ASP.NET Server Controls in Web Parts Applications. The markup should look like the following code example.

<asp:calendar id="Calendar1" runat="server"


style="position: relative"></asp:calendar>

10. Save and close the page. You are now ready to run the page and test the custom WebPart control. The completed code
for the page should look like the following code example.
VB
<%@ Page Language="VB" %>
<!-- Register the user control to change display modes. -->
<%@ register src="displaymodevb.ascx" tagname="displaymodevb"
tagprefix="uc1" %>
<!-- Register the namespace that contains the custom WebPart
control. Note there is no assembly attribute because this example
uses dynamic compilation, by placing the source file for the
control in an App_Code subfolder. -->
<%@ register tagprefix="aspSample"
namespace="Samples.AspNet.VB.Controls" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:webpartmanager id="WebPartManager1" runat="server">
</asp:webpartmanager>
<uc1:displaymodevb id="Displaymodevb1" runat="server" />
<br />
<table style="width: 80%; position: relative">
<tr valign="top">
<td style="width: 40%">
<asp:webpartzone id="WebPartZone1" runat="server"
style="position: relative" >
<parttitlestyle font-size="14" font-names="Verdana" />
<zonetemplate>
<aspSample:SmallGridWebPart id="grid1" runat="server"
title="Customer Phone List" width="300"
connectionstring="<%$ ConnectionStrings:nwind %>"
/>
</zonetemplate>
</asp:webpartzone>
</td>
<td style="width: 40%">
<asp:webpartzone id="WebPartZone2" runat="server"
style="position: relative">
<zonetemplate>
<asp:calendar id="Calendar1" runat="server"
style="position: relative"></asp:calendar>
</zonetemplate>
</asp:webpartzone>
</td>
</tr>
</table>
</div>
</form>
</body>
</html>

C#
<%@ Page Language="C#" %>
<!-- Register the user control to change display modes. -->
<%@ register src="displaymodecs.ascx" tagname="displaymodecs"
tagprefix="uc1" %>
<!-- Register the namespace that contains the custom WebPart
control. Note there is no assembly attribute because this example
uses dynamic compilation, by placing the source file for the
control in an App_Code subfolder. -->
<%@ register tagprefix="aspSample"
namespace="Samples.AspNet.CS.Controls" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:webpartmanager id="WebPartManager1" runat="server">
</asp:webpartmanager>
<uc1:displaymodecs id="Displaymodecs1" runat="server" />
<br />
<table style="width: 80%; position: relative">
<tr valign="top">
<td style="width: 40%">
<asp:webpartzone id="WebPartZone1" runat="server"
style="position: relative" >
<parttitlestyle font-size="14" font-names="Verdana, Arial" />
<zonetemplate>
<aspSample:SmallGridWebPart id="grid1" runat="server"
title="Customer Phone List" width="300"
connectionstring="<%$ ConnectionStrings:nwind %>"
/>
</zonetemplate>
</asp:webpartzone>
</td>
<td style="width: 40%">
<asp:webpartzone id="WebPartZone2" runat="server"
style="position: relative">
<zonetemplate>
<asp:calendar id="Calendar1" runat="server"
style="position: relative"></asp:calendar>
</zonetemplate>
</asp:webpartzone>
</td>
</tr>
</table>
</div>
</form>
</body>
</html>

See Also
Concepts
Creating a Data-bound Web Parts Control
Data-bound Web Parts Control Example
ASP.NET

Data-bound Web Parts Control Example


The following code example shows how to create a custom data-bound control that inherits from the WebPart class and can be
used in Web Parts applications. For details about how to build this control and use it in an ASP.NET application, see
How to: Build and Run the Data-bound Web Parts Control Example.
Example
VB
Imports System
Imports System.Collections
Imports System.ComponentModel
Imports System.Drawing
Imports System.Security.Permissions
Imports System.Web
Imports System.Web.Configuration
Imports System.Data.Sql
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Web.UI.WebControls.WebParts

Namespace Samples.AspNet.VB.Controls

<AspNetHostingPermission(SecurityAction.Demand, _
Level:=AspNetHostingPermissionLevel.Minimal)> _
<AspNetHostingPermission(SecurityAction.InheritanceDemand, _
Level:=AspNetHostingPermissionLevel.Minimal)> _
Public Class SmallGridWebPart
Inherits WebPart
Private connString As String

' Use predefined strings for commands in the data source.


Private Const selectStmt As String = "Select * from [Customers]"
Private Const deleteCmd As String = "DELETE FROM [Customers] " _
& "WHERE [CustomerID] = @CustomerID"
Private Const insertCmd As String = "INSERT INTO [Customers] " _
& "([CustomerID], [CompanyName], [ContactName], [Phone]) " _
& "VALUES (@CustomerID, @CompanyName, @ContactName, @Phone)"
Private Const updateCmd As String = "UPDATE [Customers] SET " _
& "[CompanyName] = @CompanyName, [ContactName] = @ContactName, " _
& "[Phone] = @Phone WHERE [CustomerID] = @CustomerID"

Public Sub New()


ExportMode = WebPartExportMode.All
End Sub 'New
' This override prevents users from closing the control.
Public Overrides Property AllowClose() As Boolean
Get
Return False
End Get
Set(ByVal value As Boolean)
' No implementation for the set accessor. We have to have
' it because the base property has it, but we want to
' prevent users from closing the control and developers
' from being able to update the property.
End Set
End Property
' Allow page developers to set the connection string.
Public Property ConnectionString() As String
Get
Return connString
End Get
Set(ByVal value As String)
connString = value
End Set
End Property

Protected Overrides Sub CreateChildControls()


Controls.Clear()

' Create the SqlDataSource control.


Dim ds As New SqlDataSource(Me.ConnectionString, selectStmt)
ds.ID = "dsCustomers"
ds.DataSourceMode = SqlDataSourceMode.DataSet
ds.InsertCommandType = SqlDataSourceCommandType.Text
ds.InsertCommand = insertCmd
ds.UpdateCommandType = SqlDataSourceCommandType.Text
ds.UpdateCommand = updateCmd
ds.DeleteCommandType = SqlDataSourceCommandType.Text
ds.DeleteCommand = deleteCmd
Dim deleteParams As New ParameterCollection()
deleteParams.Add(BuildParam("CustomerID", TypeCode.String))
Dim insertParams As New ParameterCollection()
insertParams.Add(BuildParam("CustomerID", TypeCode.String))
insertParams.Add(BuildParam("CompanyName", TypeCode.String))
insertParams.Add(BuildParam("ContactName", TypeCode.String))
insertParams.Add(BuildParam("Phone", TypeCode.String))
Dim updateParams As New ParameterCollection()
updateParams.Add(BuildParam("CustomerID", TypeCode.String))
updateParams.Add(BuildParam("CompanyName", TypeCode.String))
updateParams.Add(BuildParam("ContactName", TypeCode.String))
updateParams.Add(BuildParam("Phone", TypeCode.String))

Me.Controls.Add(ds)

' Create the GridView control and bind it to the SqlDataSource.


Dim grid As New GridView()
grid.ID = "customerGrid"
grid.Font.Size = 8
grid.AllowPaging = True
grid.AllowSorting = True
grid.AutoGenerateColumns = False
Dim fields As String() = {"CustomerID"}
grid.DataKeyNames = fields
grid.DataSourceID = "dsCustomers"
Dim controlButton As New CommandField()
controlButton.ShowEditButton = True
controlButton.ShowSelectButton = True
grid.Columns.Add(controlButton)
Dim customerID As BoundField = BuildBoundField("CustomerID")
customerID.ReadOnly = True
grid.Columns.Add(customerID)
grid.Columns.Add(BuildBoundField("CompanyName"))
grid.Columns.Add(BuildBoundField("ContactName"))
grid.Columns.Add(BuildBoundField("Phone"))

Me.Controls.Add(grid)

End Sub 'CreateChildControls

Private Function BuildParam(ByVal paramName As String, _


ByVal dataTypeCode As TypeCode) As Parameter

Dim theParm As New Parameter(paramName, dataTypeCode)


Return theParm

End Function 'BuildParam


Private Function BuildBoundField(ByVal fieldName _
As String) As BoundField

Dim theField As New BoundField()


theField.DataField = fieldName
theField.HeaderText = fieldName
theField.SortExpression = fieldName
Return theField
End Function 'BuildBoundField
End Class 'SmallGridWebPart

End Namespace

C#
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Security.Permissions;
using System.Web;
using System.Web.Configuration;
using System.Data.Sql;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;

namespace Samples.AspNet.CS.Controls
{
[AspNetHostingPermission(SecurityAction.Demand,
Level = AspNetHostingPermissionLevel.Minimal)]
[AspNetHostingPermission(SecurityAction.InheritanceDemand,
Level = AspNetHostingPermissionLevel.Minimal)]
public class SmallGridWebPart : WebPart
{
private String connString;
// Use predefined strings for commands in the data source.
private const string selectStmt = @"Select * from [Customers]";
private const string deleteCmd = @"DELETE FROM [Customers] " +
@"WHERE [CustomerID] = @CustomerID";
private const string insertCmd = @"INSERT INTO [Customers] " +
@"([CustomerID], [CompanyName], [ContactName], " +
@"[Phone]) VALUES (@CustomerID, @CompanyName, " +
@"@ContactName, @Phone)";
private const string updateCmd = @"UPDATE [Customers] SET " +
@"[CompanyName] = @CompanyName, [ContactName] = @ContactName, " +
@"[Phone] = @Phone WHERE [CustomerID] = @CustomerID";

public SmallGridWebPart()
{
ExportMode = WebPartExportMode.All;
}

// This override prevents users from closing the control.


public override bool AllowClose
{
get
{
return false;
}
// No implementation for the set accessor. We have to have
// it because the base property has it, but we want to
// prevent users from closing the control and developers
// from being able to update the property.
set { ; }
}

// Allow page developers to set the connection string.


public String ConnectionString
{
get { return connString; }
set { connString = value; }
}

protected override void CreateChildControls()


{
Controls.Clear();

// Create the SqlDataSource control.


SqlDataSource ds = new SqlDataSource(this.ConnectionString, selectStmt);
ds.ID = "dsCustomers";
ds.DataSourceMode = SqlDataSourceMode.DataSet;
ds.InsertCommandType = SqlDataSourceCommandType.Text;
ds.InsertCommand = insertCmd;
ds.UpdateCommandType = SqlDataSourceCommandType.Text;
ds.UpdateCommand = updateCmd;
ds.DeleteCommandType = SqlDataSourceCommandType.Text;
ds.DeleteCommand = deleteCmd;
ParameterCollection deleteParams = new ParameterCollection();
deleteParams.Add(BuildParam("CustomerID", TypeCode.String));
ParameterCollection insertParams = new ParameterCollection();
insertParams.Add(BuildParam("CustomerID", TypeCode.String));
insertParams.Add(BuildParam("CompanyName", TypeCode.String));
insertParams.Add(BuildParam("ContactName", TypeCode.String));
insertParams.Add(BuildParam("Phone", TypeCode.String));
ParameterCollection updateParams = new ParameterCollection();
updateParams.Add(BuildParam("CustomerID", TypeCode.String));
updateParams.Add(BuildParam("CompanyName", TypeCode.String));
updateParams.Add(BuildParam("ContactName", TypeCode.String));
updateParams.Add(BuildParam("Phone", TypeCode.String));

this.Controls.Add(ds);

// Create the GridView control and bind it to the SqlDataSource.


GridView grid = new GridView();
grid.ID = "customerGrid";
grid.Font.Size = 8;
grid.AllowPaging = true;
grid.AllowSorting = true;
grid.AutoGenerateColumns = false;
String[] fields = { "CustomerID" };
grid.DataKeyNames = fields;
grid.DataSourceID = "dsCustomers";
CommandField controlButton = new CommandField();
controlButton.ShowEditButton = true;
controlButton.ShowSelectButton = true;
grid.Columns.Add(controlButton);
BoundField customerID = BuildBoundField("CustomerID");
customerID.ReadOnly = true;
grid.Columns.Add(customerID);
grid.Columns.Add(BuildBoundField("CompanyName"));
grid.Columns.Add(BuildBoundField("ContactName"));
grid.Columns.Add(BuildBoundField("Phone"));
this.Controls.Add(grid);

private Parameter BuildParam(String paramName, TypeCode dataTypeCode)


{
Parameter theParm = new Parameter(paramName, dataTypeCode);
return theParm;
}

private BoundField BuildBoundField(String fieldName)


{
BoundField theField = new BoundField();
theField.DataField = fieldName;
theField.HeaderText = fieldName;
theField.SortExpression = fieldName;
return theField;
}

See Also
Tasks
How to: Build and Run the Data-bound Web Parts Control Example
Reference
WebPart
Concepts
Creating a Data-bound Web Parts Control
Other Resources
ASP.NET Web Parts Pages
How to: Provide Optional Web Parts Controls
One feature of the Web Parts control set is the ability to make a catalog of optional controls available for an end user to add to
a page.
Note
You must provide a way for end users to view the page in catalog mode so that they can see the catalog. You can do this by s
etting the DisplayMode property of the local WebPartManager instance to catalog mode, as described in
How to: Set the Display Mode of a Web Parts Page. Alternatively, you can create a user control that exposes all available page
display modes and provides other useful functionality. For more information, see
Walkthrough: Changing Display Modes on a Web Parts Page.

To create a catalog of optional Web Parts controls


1. Create an ASP.NET Web Parts page with personalization enabled. For details, see
Walkthrough: Creating a Web Parts Page.
2. Add to the page a WebPartZone zone that contains a ZoneTemplate template. This is where the user will put the controls
he or she selects.
3. Add to the page a CatalogZone zone that contains a ZoneTemplate template, which in turn contains a
DeclarativeCatalogPart control.
4. Inside the DeclarativeCatalogPart control, add a pair of <WebPartsTemplate> tags that contain the controls to include
in your catalog. The markup for the CatalogZone zone should now look something like the following example.
VB
<asp:CatalogZone ID="CZ1" runat="server">
<ZoneTemplate>
<asp:DeclarativeCatalogPart ID="DCP1" runat="server">
<WebPartsTemplate>
<asp:Label ID="Label1" runat="server" Text="Label" />
<asp:Button ID="Button1" runat="server" Text="Button" />
</WebPartsTemplate>
</asp:DeclarativeCatalogPart>
</ZoneTemplate>
</asp:CatalogZone>

C#
<asp:CatalogZone ID="CZ1" runat="server">
<ZoneTemplate>
<asp:DeclarativeCatalogPart ID="DCP1" runat="server">
<WebPartsTemplate>
<asp:Label ID="Label1" runat="server" Text="Label" />
<asp:Button ID="Button1" runat="server" Text="Button" />
</WebPartsTemplate>
</asp:DeclarativeCatalogPart>
</ZoneTemplate>
</asp:CatalogZone>

The controls inside the DeclarativeCatalogPart control will be available to the end user when the page is viewed in
catalog mode.
See Also
Tasks
Walkthrough: Changing Display Modes on a Web Parts Page
How to: Set the Display Mode of a Web Parts Page
Reference
DeclarativeCatalogPart
CatalogZone
WebPartZone
System.Web.UI.WebControls.WebParts.WebPartManager.DisplayMode
How to: Enable Users to Import Web Parts Control Settings
Part of the functionality of the Web Parts control set is the ability to import custom Web Parts controls through the use of the
ImportCatalogPart control. The ImportCatalogPart control loads a description file, which is an XML file with a .WebPart
extension that contains the location and personalizable property values of the control to be imported. When a user clicks the
Upload button on the ImportCatalogPart control, the actual control is loaded from the Web server. The user can then add
the imported control to the page.
Note
The actual control to be imported must reside on the Web server that hosts the page.

For more information about how to export a description file for importing, see How to: Export Web Parts Control Settings.
To enable importing on a page
1. Create an ASP.NET Web Parts page that includes a CatalogZone zone that in turn contains an ImportCatalogPart
control inside a ZoneTemplate template. The markup for the CatalogZone zone should look something like the
following example.

<asp:CatalogZone id="CZ1" runat="server">


<ZoneTemplate>
<asp:ImportCatalogPart id="ICP1" runat="server" />
</ZoneTemplate>
</asp:CatalogZone>

Note
The page must contain a WebPartManager control for Web Parts controls to function. For more information, see
Walkthrough: Creating a Web Parts Page.

2. Provide a means for the user to switch the page display mode to catalog mode.
For more information on setting and changing page display modes, see
How to: Set the Display Mode of a Web Parts Page and Walkthrough: Changing Display Modes on a Web Parts Page.
To import a Web Parts control
1. Open the page in a browser and set the display mode to catalog mode.
2. Click the Browse button on the ImportCatalogPart control.
3. Browse to the location of the description file you want to load, select the file, and click Open.
4. Click the Upload button.
The control appears inside the ImportCatalogPart control.
5. Drag the imported control onto the page and set the page display mode back to browse mode.
See Also
Tasks
How to: Export Web Parts Control Settings
How to: Set the Display Mode of a Web Parts Page
Walkthrough: Changing Display Modes on a Web Parts Page
Reference
System.Web.UI.WebControls.WebParts
ImportCatalogPart
WebPartManager
Other Resources
ASP.NET Web Parts Pages
How to: Export Web Parts Control Settings
Part of the functionality of the Web Parts control set is the ability to import custom Web Parts controls through the use of the
ImportCatalogPart control. However, before a control can be imported by an end user it must be made available for export by
the page developer.
After you have completed the export operation, you will need a way for users to import the control. For more information, see
How to: Enable Users to Import Web Parts Control Settings.
To enable a custom Web Parts control for export
1. Create an ASP.NET page that contains a custom Web Parts control.
This control can be derived from the WebPart class or be any inherited control or user control placed inside a
WebPartZone zone. For more information about how to create a Web Parts page, see
Walkthrough: Creating a Web Parts Page. For an example of a custom Web Parts control, see WebPart.
Note
Only properties with the Personalizable attribute are included in the .WebPart file used for export.

2. In your Web.config file, inside the <system.web> section, add a <webParts> element with enableExport set to true, as
shown in the following example.

<webParts enableExport="true"></webParts>

3. Set the ExportMode property of the control to all. If your control is derived from WebPart, you can do
this in markup as shown in the following example.

<aspSample:CustomWebPart id="Sample" runat="server" ExportMode="All" />

If you are not using an inherited WebPart control but are using another control inside a WebPartZone zone, you
must set the ExportMode property of the containing GenericWebPart control in code, as in the example shown in the
Example section.
4. Load the Web page in a browser and, on the verbs menu of the WebPart control, click the export verb and follow the
instructions to export a description file that contains the control's state and property data.
Example
To export a control that does not inherit from the WebPart class, you must first place the control inside a WebPartZone zone
on the page. This automatically wraps the control in a GenericWebPart control, which you can access through code to set the
ExportMode property during the Page_Load() event. In the following example, Control1 is the name of the control to export.
VB
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Loa
d
Dim gwp As GenericWebPart
gwp = Control1.Parent
gwp.ExportMode = WebPartExportMode.All
End Sub

C#
protected void Page_Load(object sender, EventArgs e)
{
GenericWebPart gwp = (GenericWebPart) Control1.Parent;
gwp.ExportMode = WebPartExportMode.All;
}
See Also
Tasks
How to: Treat a User Control as a Web Parts Control
How to: Enable Users to Import Web Parts Control Settings
How to: Enable Users to Import Web Parts Control Settings
Reference
System.Web.UI.WebControls.WebParts
WebPart
GenericWebPart
ExportMode
ImportCatalogPart
Other Resources
ASP.NET Web Parts Pages
Visual Web Developer

Walkthrough Topics — Customizing Web Pages with Web Parts


The following walkthrough topics demonstrate how to create and manage ASP.NET Web Parts pages and controls.
Walkthrough Topics
Walkthrough: Creating a Web Parts Page in Visual Web Developer
Walkthrough: Changing Display Modes on a Web Parts Page
Walkthrough: Implementing Web Parts Personalization with a User Control
See Also
Other Resources
ASP.NET Web Parts in Visual Studio
Visual Web Developer

How-to Topics — Customizing Web Pages with Web Parts


The following procedures describe how to create and manage ASP.NET Web Parts pages and controls.
How-to Topics
How to: Enable Shared Personalization of Web Parts Pages
How to: Disable Web Parts Personalization
How to: Declare a Static Connection between Two Web Parts Controls
How to: Treat a User Control as a Web Parts Control
How to: Build and Run the Data-bound Web Parts Control Example
See Also
Other Resources
ASP.NET Web Parts in Visual Studio
Visual Web Developer

Saving ASP.NET Page Values (Visual Studio)


The Web is inherently stateless; each request for a page is treated as a new request, and information from one request is not
available by default to the next request. To help overcome this inherent limitation of Web-based applications, ASP.NET includes
a number of features for managing state—that is, for storing information between requests. You can use state management to
track any piece of information or data that affects the behavior of the application: catalogs, shopping carts, user options, lists of
reviews, and hit counters are all examples.
The topics in this section provide information about ASP.NET statement management features and on choosing which type of
state management you should use in each different situation.
In This Section
ASP.NET State Management Overview
ASP.NET State Management Recommendations
ASP.NET Cookies
ASP.NET View State
ASP.NET Session State
ASP.NET Application State
See Also
Other Resources
ASP.NET Web Sites (Visual Studio)
ASP.NET Web Pages (Visual Studio)
ASP.NET

ASP.NET State Management Overview


A new instance of the Web page class is created each time the page is posted to the server. In traditional Web programming,
this would typically mean that all information associated with the page and the controls on the page would be lost with each
round trip. For example, if a user enters information into a text box, that information would be lost in the round trip from the
browser or client device to the server.
To overcome this inherent limitation of traditional Web programming, ASP.NET includes several options that help you preserve
data on both a per-page basis and an application-wide basis. These features are as follows:
View state
Control state
Hidden fields
Cookies
Query strings
Application state
Session state
Profile Properties
View state, control state, hidden fields, cookies, and query strings all involve storing data on the client in various ways.
However, application state, session state, and profile properties all store data in memory on the server. Each option has distinct
advantages and disadvantages, depending on the scenario.
Client-Based State Management Options
The following sections describe options for state management that involve storing information either in the page or on the
client computer. For these options, no information is maintained on the server between round trips.
View State
The ViewState property provides a dictionary object for retaining values between multiple requests for the same page. This is
the default method that the page uses to preserve page and control property values between round trips.
When the page is processed, the current state of the page and controls is hashed into a string and saved in the page as a
hidden field, or multiple hidden fields if the amount of data stored in the ViewState property exceeds the specified value in the
MaxPageStateFieldLength property. When the page is posted back to the server, the page parses the view-state string at page
initialization and restores property information in the page.
You can store values in view state as well. For details, see How to: Save Values in View State. For recommendations about when
you should use view state, see ASP.NET State Management Recommendations.
Control State
Sometimes you need to store control-state data in order for a control to work properly. For example, if you have written a
custom control that has different tabs that show different information, in order for that control to work as expected, the control
needs to know which tab is selected between round trips. The ViewState property can be used for this purpose, but view state
can be turned off at a page level by developers, effectively breaking your control. To solve this, the ASP.NET page framework
exposes a feature in ASP.NET called control state.
The ControlState property allows you to persist property information that is specific to a control and cannot be turned off like
the ViewState property.
Hidden Fields
ASP.NET allows you to store information in a HiddenField control, which renders as a standard HTML hidden field. A hidden
field does not render visibly in the browser, but you can set its properties just as you can with a standard control. When a page
is submitted to the server, the content of a hidden field is sent in the HTTP form collection along with the values of other
controls. A hidden field acts as a repository for any page-specific information that you want to store directly in the page.
Security Note
It is easy for a malicious user to see and modify the contents of a hidden field. Do not store any information in a hidden field
that is sensitive or that your application relies on to work properly. For more information, see
ASP.NET State Management Recommendations.

A HiddenField control stores a single variable in its Value property and must be explicitly added to the page. For more
information, see HiddenField Web Server Control Overview.
In order for hidden-field values to be available during page processing, you must submit the page using an HTTP POST
command. If you use hidden fields and a page is processed in response to a link or an HTTP GET command, the hidden fields
will not be available. For usage recommendations, see ASP.NET State Management Recommendations.
Cookies
A cookie is a small amount of data that is stored either in a text file on the client file system or in-memory in the client browser
session. It contains site-specific information that the server sends to the client along with page output. Cookies can be
temporary (with specific expiration times and dates) or persistent.
You can use cookies to store information about a particular client, session, or application. The cookies are saved on the client
device, and when the browser requests a page, the client sends the information in the cookie along with the request
information. The server can read the cookie and extract its value. A typical use is to store a token (perhaps encrypted) indicating
that the user has already been authenticated in your application.
Security Note
The browser can only send the data back to the server that originally created the cookie. However, malicious users have ways
to access cookies and read their contents. It is recommended that you do not store sensitive information, such as a user nam
e or password, in a cookie. Instead, store a token in the cookie that identifies the user, and then use the token to look up the s
ensitive information on the server.

For more information about using cookies, see Cookies and ASP.NET State Management Recommendations.
Query Strings
A query string is information that is appended to the end of a page URL. A typical query string might look like the following
example:

http://www.contoso.com/listwidgets.aspx?category=basic&price=100

In the URL path above, the query string starts with a question mark (?) and includes two attribute/value pairs, one called
"category" and the other called "price."
Query strings provide a simple but limited way to maintain state information. For example, they are an easy way to pass
information from one page to another, such as passing a product number from one page to another page where it will be
processed. However, some browsers and client devices impose a 2083-character limit on the length of the URL.
Security Note
Information that is passed in a query string can be tampered with by a malicious user. Do not rely on query strings to convey
important or sensitive data. Additionally, a user can bookmark the URL or send the URL to other users, thereby passing that i
nformation along with it. For more information, see ASP.NET State Management Recommendations and
How to: Protect Against Script Exploits in a Web Application by Applying HTML Encoding to Strings.

In order for query string values to be available during page processing, you must submit the page using an HTTP GET
command. That is, you cannot take advantage of a query string if a page is processed in response to an HTTP POST command.
For usage recommendations, see ASP.NET State Management Recommendations.
Server-Based State Management Options
ASP.NET offers you a variety of ways to maintain state information on the server, rather than persisting information on the
client. With server-based state management, you can decrease the amount of information sent to the client in order to
preserve state, however it can use costly resources on the server. The following sections describe three server-based state
management features: application state, session state, and profile properties.
Application State
ASP.NET allows you to save values using application state — which is an instance of the HttpApplicationState class — for each
active Web application. Application state is a global storage mechanism that is accessible from all pages in the Web application.
Thus, application state is useful for storing information that needs to be maintained between server round trips and between
requests for pages. For more information, see ASP.NET Application State Overview.
Application state is stored in a key/value dictionary that is created during each request to a specific URL. You can add your
application-specific information to this structure to store it between page requests.
Once you add your application-specific information to application state, the server manages it. For usage recommendations,
see ASP.NET State Management Recommendations.
Session State
ASP.NET allows you to save values by using session state — which is an instance of the HttpSessionState class — for each
active Web-application session. For an overview, see Session State Overview.
Session state is similar to application state, except that it is scoped to the current browser session. If different users are using
your application, each user session will have a different session state. In addition, if a user leaves your application and then
returns later, the second user session will have a different session state from the first.
Session state is structured as a key/value dictionary for storing session-specific information that needs to be maintained
between server round trips and between requests for pages. For more information, see Session State Overview.
You can use session state to accomplish the following tasks:
Uniquely identify browser or client-device requests and map them to an individual session instance on the server.
Store session-specific data on the server for use across multiple browser or client-device requests within the same
session.
Raise appropriate session management events. In addition, you can write application code leveraging these events.
Once you add your application-specific information to session state, the server manages this object. Depending on which
options you specify, session information can be stored in cookies, on an out-of-process server, or on a computer running
Microsoft SQL Server. For usage recommendations, see ASP.NET State Management Recommendations.
Profile Properties
ASP.NET provides a feature called profile properties, which allows you to store user-specific data. This feature is similar to
session state, except that the profile data is not lost when a user's session expires. The profile-properties feature uses an
ASP.NET profile, which is stored in a persistent format and associated with an individual user. The ASP.NET profile allows you
to easily manage user information without requiring you to create and maintain your own database. In addition, the profile
makes the user information available using a strongly typed API that you can access from anywhere in your application. You
can store objects of any type in the profile. The ASP.NET profile feature provides a generic storage system that allows you to
define and maintain almost any kind of data while still making the data available in a type-safe manner.
To use profile properties, you must configure a profile provider. ASP.NET includes a SqlProfileProvider class that allows you to
store profile data in a SQL database, but you can also create your own profile provider class that stores profile data in a custom
format and to a custom storage mechanism such as an XML file, or even to a web service.
Because data that is placed in profile properties is not stored in application memory, it is preserved through Internet
Information Services (IIS) restarts and worker-process restarts without losing data. Additionally, profile properties can be
persisted across multiple processes such as in a Web farm or a Web garden. For more information, see
ASP.NET Profile Properties Overview.
See Also
Concepts
What's New in ASP.NET State Management
ASP.NET State Management Recommendations
ASP.NET Cookies Overview
View State Overview
Session State Overview
ASP.NET Application State Overview
ASP.NET Profile Properties Overview
ASP.NET

What's New in ASP.NET State Management


ASP.NET version 2.0 retains much of the functionality of ASP.NET version 1.1, including automatic page-state persistence using
view state, and database support for session and application state. Additionally, ASP.NET 2.0 adds two new features: view-state
chunking and control state.
Control State
Sometimes you need to store control-state data in order for a control to work properly. For example, if you have written a
custom control that has different tabs that show different information, in order for that control to work as expected, somehow
the control needs to know which tab is selected between round trips. The ViewState property can be used for this purpose, but
view state can be turned off at a page level by developers, effectively breaking your control. To solve this, the ASP.NET page
framework exposes a new feature in ASP.NET version 2.0, called control state.
The ControlState property allows you to persist property information that is specific to a control and cannot be turned off like
the ViewState property. To use control state, your control must call the RegisterRequiresControlState method during
initialization and then override the SaveControlState and LoadControlState methods.
Profile Properties
Many times, you need to store user-specific data in order to customize the experience of a user when they use your application.
There are two major ways to accomplish this in ASP.NET 1.1. Session state provides an easy way to store user-specific
information. However, session state is removed from memory when the user session expires. You can also use cookies to store
a unique user identifier, and then persist and retrieve information from a database. However, this requires custom code. To
solve this, ASP.NET 2.0 provides a new feature called profile properties, which allows you to store user-specific data.
The profile properties feature is similar to session state, except that the profile data is not lost when a user session expires.
Instead, the profile properties feature uses an ASP.NET profile that is stored in a persistent format and associated with an
individual user. The ASP.NET profile allows you to manage user information without requiring that you create and maintain
your own database. In addition, the profile makes the user information available using a strongly typed API that you can access
from anywhere in your application. You can store objects of any type in the profile. The ASP.NET profile feature provides a
generic storage system that allows you to define and maintain almost any kind of data while still making the data available in a
type-safe manner.
For more information, see ASP.NET Profile Properties Overview.
View-State Chunking
View state provides an easy way to automatically persist field and control data on the page without having to manually request
it and then re-populate during round trips to the server. It also allows you to store custom data on the page in the ViewState
property.
However, view-state data can, in some cases, become very large. Because view-state data is stored in hidden fields, some
proxies and firewalls will prevent access to the page that contains them. For this reason, the ASP.NET 2.0 page framework
introduces a feature called view-state chunking. If the amount of view-state data becomes too large, view-state chunking will
automatically split the data into chunks and put the data into multiple hidden-form fields.
To enable view-state chunking, set the MaxPageStateFieldLength property to the maximum size (in bytes) that you want to
allow in a single view-state field. When the page is posted back to the server, the page parses the view-state string at page
initialization and restores property information in the page. The default setting is -1, which means that there is no maximum
size and the view state will not be broken up into chunks.
For more information, see View State Overview.
Custom Session-State Management
By default, session-state values and information are stored in memory within the ASP.NET process. ASP.NET also provides
session-state providers that allow you to use a session-state server that keeps session data in a separate process, or you can
persist session state data to a SQL database. However, with ASP.NET 2.0, you can create custom session-state providers that
allow you to customize how session-state data is stored in your ASP.NET applications. For example, you might consider
creating a custom provider for the following reasons:
You need to store session-state information in a data source other than SQL Server, such as a Visual FoxPro database or
an Oracle database.
You need to manage session-state information using a database schema that is different from the database schema used
by the providers that ship with the .NET Framework. An example of this would be shopping cart data that is stored with a
predefined schema in an existing a SQL Server database for a company or Web site.
For more information, see Implementing a Session-State Store Provider.
The HiddenField Control
View state gives you the programmatic ability to store data on a Web page and it automatically retrieves, persists, and
maintains that data in hidden form fields on the page. However, ASP.NET 2.0 adds a new Web control, the HiddenField control
that renders as an input type="hidden"/ element but gives you an API that is consistent with other Web controls.
See Also
Concepts
ASP.NET State Management Overview
ASP.NET State Management Recommendations
ASP.NET Cookies Overview
View State Overview
Session State Overview
ASP.NET Application State Overview
ASP.NET

ASP.NET State Management Recommendations


State management is the process by which you maintain state and page information over multiple requests for the same or
different pages. As is true for any HTTP-based technology, Web Forms pages are stateless, which means that they do not
automatically indicate whether the requests in a sequence are all from the same client or even whether a single browser
instance is still actively viewing a page or site. Furthermore, pages are destroyed and re-created with each round trip to the
server; therefore, page information will not exist beyond the life cycle of a single page. For more information about server
round trips and the life cycle of Web Forms pages, see ASP.NET Page Life Cycle Overview.
ASP.NET provides multiple ways to maintain state between server round trips. Which of these options you choose depends
heavily upon your application, and it should be based on the following criteria:
How much information do you need to store?
Does the client accept persistent or in-memory cookies?
Do you want to store the information on the client or on the server?
Is the information sensitive?
What performance and bandwidth criteria do you have for your application?
What are the capabilities of the browsers and devices that you are targeting?
Do you need to store information per user?
How long do you need to store the information?
Do you have a Web farm (multiple servers), a Web garden (multiple processes on one machine), or a single process that
serves the application?
Client-Side State Management Options
Storing page information using client-side options doesn't use server resources. These options typically have minimal security
but fast server performance because the demand on server resources is modest. However, because you must send information
to the client for it to be stored, there is a practical limit on how much information you can store this way.
The following are the client-side state management options that ASP.NET supports:
View state
Control state
Hidden fields
Cookies
Query strings
View State
Web Forms pages provide the ViewState property as a built-in structure for automatically retaining values between multiple
requests for the same page. View state is maintained as a hidden field in the page. For more information, see
ASP.NET State Management Overview.
You can use view state to store your own page-specific values across round trips when the page posts back to itself. For
example, if your application is maintaining user-specific information — that is, information that is used in the page but is not
necessarily part of any control — you can store it in view state.
Advantages of using view state are:
No server resources are required The view state is contained in a structure within the page code.
Simple implementation View state does not require any custom programming to use. It is on by default to maintain
state data on controls.
Enhanced security features The values in view state are hashed, compressed, and encoded for Unicode
implementations, which provides more security than using hidden fields.
Disadvantages of using view state are:
Performance considerations Because the view state is stored in the page itself, storing large values can cause the
page to slow down when users display it and when they post it. This is especially relevant for mobile devices, where
bandwidth is often a limitation.
Device limitations Mobile devices might not have the memory capacity to store a large amount of view-state data.
Potential security risks The view state is stored in one or more hidden fields on the page. Although view state stores
data in a hashed format, it can still be tampered with. The information in the hidden field can be seen if the page output
source is viewed directly, creating a potential security issue. For more information, see ASP.NET Web Application Security
and Basic Security Practices for Web Applications.
For more information about using view state, see View State Overview.
Control State
The ASP.NET page framework provides the ControlState property as way to store custom control data between server trips. For
example, if you have written a custom control that has different tabs showing different information, in order for that control to
work as expected, the control needs to know which tab is selected between round trips. View state can be used for this
purpose, but developers can turn view state off at the page level, effectively breaking your control. Unlike view state, control
state cannot be turned off, so it provides a more reliable way to store control-state data.
Advantages of using control state are:
No server resources are required By default, control state is stored in hidden fields on the page.
Reliability Because control state cannot be turned off like view state, control state is a more reliable method for
managing the state of controls.
Versatility Custom adapters can be written to control how and where control-state data is stored.
Disadvantage of using control state are:
Some programming is required While the ASP.NET page framework provides a foundation for control state, control
state is a custom state-persistence mechanism. To fully utilize control state, you must write code to save and load control
state.
Hidden Fields
You can store page-specific information in a hidden field on your page as a way of maintaining the state of your page. For
more information about hidden fields, see ASP.NET State Management Recommendations.
If you use hidden fields, it is best to store only small amounts of frequently changed data on the client.
Note
If you use hidden fields, you must submit your pages to the server using the HTTP POST method rather than requesting the p
age via the page URL (the HTTP GET method).

Advantages of using hidden fields are:


No server resources are required The hidden field is stored and read from the page.
Widespread support Almost all browsers and client devices support forms with hidden fields.
Simple implementation Hidden fields are standard HTML controls that require no complex programming logic.
Disadvantages of using hidden fields are:
Potential security risks The hidden field can be tampered with. The information in the hidden field can be seen if the
page output source is viewed directly, creating a potential security issue. You can manually encrypt and decrypt the
contents of a hidden field, but doing so requires extra coding and overhead. If security is a concern, consider using a
server-based state mechanism so that no sensitive information is sent to the client. For more information, see
ASP.NET Web Application Security and Basic Security Practices for Web Applications.
Simple storage architecture The hidden field does not support rich data types. Hidden fields offer a single string
value field in which to place information. To store multiple values, you must implement delimited strings and the code to
parse those strings. You can manually serialize and de-serialize rich data types to and from hidden fields, respectively.
However, it requires extra code to do so. If you need to store rich data types on the client, consider using view state
instead. View state has serialization built-in, and it stores data in hidden fields.
Performance considerations Because hidden fields are stored in the page itself, storing large values can cause the
page to slow down when users display it and when they post it.
Storage limitations If the amount of data in a hidden field becomes very large, some proxies and firewalls will prevent
access to the page that contains them. Because the maximum amount can vary with different firewall and proxy
implementations, large hidden fields can be sporadically problematic. If you need to store many items of data, consider
doing one of the following:
Put each item in a separate hidden field.
Use view state with view-state chunking turned on, which automatically separates data into multiple hidden
fields.
Instead of storing data on the client, persist the data on the server. The more data you send to the client, the
slower the apparent response time of your application will be because the browser will need to download or send
more data.
Cookies
Cookies are useful for storing small amounts of frequently changed information on the client. The information is sent with the
request to the server. For details about creating and reading cookies, see ASP.NET Cookies Overview.
Advantages of using cookies are:
Configurable expiration rules The cookie can expire when the browser session ends, or it can exist indefinitely on the
client computer, subject to the expiration rules on the client.
No server resources are required The cookie is stored on the client and read by the server after a post.
Simplicity The cookie is a lightweight, text-based structure with simple key-value pairs.
Data persistence Although the durability of the cookie on a client computer is subject to cookie expiration processes
on the client and user intervention, cookies are generally the most durable form of data persistence on the client.
Disadvantages of using cookies are:
Size limitations Most browsers place a 4096-byte limit on the size of a cookie, although support for 8192-byte cookies
is becoming more common in newer browser and client-device versions.
User-configured refusal Some users disable their browser or client device's ability to receive cookies, thereby limiting
this functionality.
Potential security risks Cookies are subject to tampering. Users can manipulate cookies on their computer, which can
potentially cause a security risk or cause the application that is dependent on the cookie to fail. Also, although cookies are
only accessible by the domain that sent them to the client, hackers have historically found ways to access cookies from
other domains on a user's computer. You can manually encrypt and decrypt cookies, but it requires extra coding and can
affect application performance because of the time that is required for encryption and decryption. For more information,
see ASP.NET Web Application Security and Basic Security Practices for Web Applications.
Note
Cookies are often used for personalization, where content is customized for a known user. In most of these cases, identi
fication is the issue rather than authentication. Thus, you can typically secure a cookie that is used for identification by s
toring the user name, account name, or a unique user ID (such as a GUID) in the cookie and then using the cookie to ac
cess the user personalization infrastructure of a site.

Query Strings
A query string is information that is appended to the end of a page URL. For more information, see
ASP.NET State Management Overview.
You can use a query string to submit data back to your page or to another page through the URL. Query strings provide a
simple but limited way of maintaining some state information. For example, query strings are an easy way to pass information
from one page to another, such as passing a product number to another page where it will be processed.
Advantages of using query strings are:
No server resources are required The query string is contained in the HTTP request for a specific URL.
Widespread support Almost all browsers and client devices support using query strings to pass values.
Simple implementation ASP.NET provides full support for the query-string method, including methods of reading
query strings using the Params property of the HttpRequest object.
Disadvantages of using query strings are:
Potential security risks The information in the query string is directly visible to the user via the browser's user
interface. A user can bookmark the URL or send the URL to other users, thereby passing the information in the query
string along with it. If you are concerned about any sensitive data in the query string, consider using hidden fields in a
form that uses POST instead of using query strings. For more information, see ASP.NET Web Application Security and
Basic Security Practices for Web Applications.
Limited capacity Some browsers and client devices impose a 2083-character limit on the length of URLs.
Client-Side Method State Management Summary
The following table lists the client-side state management options that are available with ASP.NET, and provides
recommendations about when you should use each option.
State managem Recommended usage
ent option
View state Use when you need to store small amounts of information for a page that will post back to itself. Using the
ViewState property provides functionality with basic security.

Control state Use when you need to store small amounts of state information for a control between round trips to the ser
ver.

Hidden fields Use when you need to store small amounts of information for a page that will post back to itself or to anoth
er page, and when security is not an issue.
Note
You can use a hidden field only on pages that are submitted to the server.

Cookies Use when you need to store small amounts of information on the client and security is not an issue.

Query string Use when you are transferring small amounts of information from one page to another and security is not
an issue.
Note
You can use query strings only if you are requesting the same page, or another page via a link.

Server-Side State Management Options


Server-side options for storing page information typically have higher security than client-side options, but they can use more
Web server resources, which can lead to scalability issues when the size of the information store is large. ASP.NET provides
several options to implement server-side state management. For more information, see ASP.NET State Management Overview.
The following are the server-side state management options that ASP.NET supports:
Application state
Session state
Profile properties
Database support
Application State
ASP.NET provides application state via the HttpApplicationState class as a method of storing global application-specific
information that is visible to the entire application. Application-state variables are, in effect, global variables for an ASP.NET
application. For more information, see ASP.NET Application State Overview
You can store your application-specific values in application state, which is then managed by the server. For more information,
see ASP.NET State Management Overview.
Data that is shared by multiple sessions and does not change often is the ideal type of data to insert into application-state
variables.
Advantages of using application state are:
Simple implementation Application state is easy to use, familiar to ASP developers, and consistent with other .NET
Framework classes.
Application scope Because application state is accessible to all pages in an application, storing information in
application state can mean keeping only a single copy of the information (for instance, as opposed to keeping copies of
information in session state or in individual pages).
Disadvantages of using application state are:
Application scope The scope of application state can also be a disadvantage. Variables stored in application state are
global only to the particular process the application is running in, and each application process can have different values.
Therefore, you cannot rely on application state to store unique values or update global counters in Web-garden and
Web-farm server configurations.
Limited durability of data Because global data that is stored in application state is volatile, it will be lost if the Web
server process containing it is destroyed, such as from a server crash, upgrade, or shutdown.
Resource requirements Application state requires server memory, which can affect the performance of the server as
well as the scalability of the application.
Careful design and implementation of application state can increase Web application performance. For example, placing a
commonly used, relatively static dataset in application state can increase site performance by reducing the overall number of
data requests to a database. However, there is a performance trade-off. Application state variables containing large blocks of
information reduce Web server performance as server load increases. The memory occupied by a variable stored in application
state is not released until the value is either removed or replaced. Therefore, it is best to use application-state variables only
with small, infrequently changed datasets. For more information, see Developing High-Performance ASP.NET Applications.
Session State
ASP.NET provides a session state, which is available as the HttpSessionState class, as a method of storing session-specific
information that is visible only within the session. ASP.NET session state identifies requests from the same browser during a
limited time window as a session, and provides the ability to persist variable values for the duration of that session. For more
information, see ASP.NET State Management Overview and Session State Overview.
You can store your session-specific values and objects in session state, which is then managed by the server and available to
the browser or client device. The ideal data to store in session-state variables is short-lived, sensitive data that is specific to an
individual session.
Advantages of using session state are:
Simple implementation The session-state facility is easy to use, familiar to ASP developers, and consistent with other
.NET Framework classes.
Session-specific events Session management events can be raised and used by your application.
Data persistence Data placed in session-state variables can be preserved through Internet Information Services (IIS)
restarts and worker-process restarts without losing session data because the data is stored in another process space.
Additionally, session-state data can be persisted across multiple processes, such as in a Web farm or a Web garden.
Platform scalability Session state can be used in both multi-computer and multi-process configurations, therefore
optimizing scalability scenarios.
Cookieless support Session state works with browsers that do not support HTTP cookies, although session state is
most commonly used with cookies to provide user identification facilities to a Web application. Using session state
without cookies, however, requires that the session identifier be placed in the query string, which is subject to the
security issues stated in the query string section of this topic. For more information about using session state without
cookies, see Configuring ASP.NET Applications.
Extensibility You can customize and extend session state by writing your own session-state provider. Session state
data can then be stored in a custom data format in a variety of data storage mechanisms, such as a database, an XML file,
or even to a Web service. For more information, see Implementing a Session-State Store Provider.
Disadvantage of using session state are:
Performance considerations Session-state variables stay in memory until they are either removed or replaced, and
therefore can degrade server performance. Session-state variables that contain blocks of information, such as large
datasets, can adversely affect Web-server performance as server load increases.
Profile Properties
ASP.NET provides a feature called profile properties, which allows you to store user-specific data. It is similar to session state,
except that unlike session state, the profile data is not lost when a user's session expires. The profile properties feature uses an
ASP.NET profile, which is stored in a persistent format and associated with an individual user. The ASP.NET profile allows you
to easily manage user information without requiring you to create and maintain your own database. In addition, the profile
makes the user information available using a strongly typed API that you can access from anywhere in your application. You
can store objects of any type in the profile. The ASP.NET profile feature provides a generic storage system that allows you to
define and maintain almost any kind of data while still making the data available in a type-safe manner. For more information,
see ASP.NET Profile Properties Overview.
Advantages of using profile properties are:
Data persistence Data placed in profile properties is preserved through IIS restarts and worker-process restarts
without losing data because the data is stored in an external mechanism. Additionally, profile properties can be persisted
across multiple processes, such as in a Web farm or a Web garden.
Platform scalability Profile properties can be used in both multi-computer and multi-process configurations,
therefore optimizing scalability scenarios.
Extensibility In order to use profile properties, you must configure a profile provider. ASP.NET includes a
SqlProfileProvider class that allows you to store profile data in a SQL database, but you can also create your own profile
provider class that stores profile data in a custom format and to a custom storage mechanism, such as an XML file, or
even to a Web service. For more information, see ASP.NET Profile Providers and Implementing a Profile Provider.
Disadvantages of using profile properties are:
Performance considerations Profile properties are generally slower than using session state because instead of
storing data in memory, the data is persisted to a data store.
Additional configuration requirements Unlike session state, the profile properties feature requires a considerable
amount of configuration to use. To use profile properties, you must not only configure a profile provider, but you must
pre-configure all of the profile properties that you want to store. For more information, see
ASP.NET Profile Properties Overview and Defining ASP.NET Profile Properties.
Data maintenance Profile properties require a certain amount of maintenance. Because profile data is persisted to
non-volatile storage, you must make sure that your application calls the appropriate cleanup mechanisms, which are
provided by the profile provider, when data becomes stale.
Database Support
In some cases, you might want to use database support to maintain state on your Web site. Typically, database support is used
in conjunction with cookies or session state. For example, it is common for an e-commerce Web site to maintain state
information by using a relational database for the following reasons:
Security
Personalization
Consistency
Data mining
The following are typical features of a cookie-supported database Web site:
Security The visitor types an account name and password into a site logon page. The site infrastructure queries the
database with the logon values to determine whether the user has rights to utilize your site. If the database validates the
user information, the Web site will distribute a valid cookie containing a unique ID for that user on that client computer.
The site grants access to the user.
Personalization With security information in place, your site can distinguish each user by reading the cookie on the
client computer. Typically, sites have information in the database that describes the preferences of a user (identified by a
unique ID). This relationship is known as personalization. The site can research the user's preferences using the unique ID
contained in the cookie, and then place content and information in front of the user that pertains to the user's specific
wishes, reacting to the user's preferences over time.
Consistency If you have created a commerce Web site, you might want to keep transactional records of purchases
made for goods and services on your site. This information can be reliably saved in your database and referenced by the
user's unique ID. It can be used to determine whether a purchase transaction has been completed, and to determine the
course of action if a purchase transaction fails. The information can also be used to inform the user of the status of an
order placed using your site.
Data mining Information about your site usage, your visitors, or your product transactions can be reliably stored in a
database. For example, your business development department might want to use the data collected from your site to
determine next year's product line or distribution policy. Your marketing department might want to examine
demographic information about users on your site. Your engineering and support departments might want to look at
transactions and note areas where your purchasing process could be improved. Most enterprise-level relational
databases, such as Microsoft SQL Server, contain an expansive toolset for most data mining projects.
By designing the Web site to repeatedly query the database by using the unique ID during each general stage in the above
scenario, the site maintains state. In this way, the user perceives that the site is remembering and reacting to him or her
personally.
Advantages of using a database to maintain state are:
Security Access to databases requires rigorous authentication and authorization.
Storage capacity You can store as much information as you like in a database.
Data persistence Database information can be stored as long as you like, and it is not subject to the availability of the
Web server.
Robustness and data integrity Databases include various facilities for maintaining good data, including triggers and
referential integrity, transactions, and so on. By keeping information about transactions in a database (rather than in
session state, for example), you can recover from errors more readily.
Accessibility The data stored in your database is accessible to a wide variety of information-processing tools.
Widespread support There is a large range of database tools available, and many custom configurations are available.
Disadvantages of using a database to maintain state are:
Complexity Using a database to support state management requires that the hardware and software configurations be
more complex.
Performance considerations Poor construction of the relational data model can lead to scalability issues. Also,
leveraging too many queries to the database can adversely affect server performance.
Server-Side Method State Management Summary
The following table lists the server-side state management options that are available with ASP.NET, and provides
recommendations about when you should use each option.
State Recommended usage
manag
ement
option
Applicat Use when you are storing infrequently changed, global information that is used by many users, and security is not an
ion stat issue. Do not store large quantities of information in application state.
e
Session Use when you are storing short-lived information that is specific to an individual session and security is an issue. Do n
state ot store large quantities of information in session state. Be aware that a session-state object will be created and maint
ained for the lifetime of every session in your application. In applications hosting many users, this can occupy signific
ant server resources and affect scalability.

Profile Use when you are storing user-specific information that needs to be persisted after the user session is expired and ne
properti eds to be retrieved again on subsequent visits to your application.
es

Databas Use when you are storing large amounts of information, managing transactions, or the information must survive appl
e suppo ication and session restarts. Data mining is a concern, and security is an issue.
rt

See Also
Concepts
ASP.NET State Management Overview
What's New in ASP.NET State Management
ASP.NET Cookies Overview
View State Overview
ASP.NET Profile Properties Overview
Session State Overview
ASP.NET Application State Overview
ASP.NET

ASP.NET Cookies
The topics in this section describe how to create cookies in ASP.NET Web applications. Cookies are small text files that the
server and browser exchange on each page request, and that you can use to store information that can help you customize
your application for each user.
In This Section
ASP.NET Cookies Overview
How to: Write a Cookie
How to: Read a Cookie
How to: Delete a Cookie
Related Sections
ASP.NET State Management
Provides links to additional topics that describe how to maintain information across page requests.
ASP.NET

ASP.NET Cookies Overview


Cookies provide a means in Web applications to store user-specific information. For example, when a user visits your site, you
can use cookies to store user preferences or other information. When the user visits your Web site another time, the
application can retrieve the information it stored earlier.
What Are Cookies?
A cookie is a small bit of text that accompanies requests and pages as they go between the Web server and browser. The
cookie contains information the Web application can read whenever the user visits the site.
For example, if a user requests a page from your site and your application sends not just a page, but also a cookie containing
the date and time, when the user's browser gets the page, the browser also gets the cookie, which it stores in a folder on the
user's hard disk.
Later, if user requests a page from your site again, when the user enters the URL the browser looks on the local hard disk for a
cookie associated with the URL. If the cookie exists, the browser sends the cookie to your site along with the page request. Your
application can then determine the date and time that the user last visited the site. You might use the information to display a
message to the user or check an expiration date.
Cookies are associated with a Web site, not with a specific page, so the browser and server will exchange cookie information
no matter what page the user requests from your site. As the user visits different sites, each site might send a cookie to the
user's browser as well; the browser stores all the cookies separately.
Cookies help Web sites store information about visitors. More generally, cookies are one way of maintaining continuity in a
Web application—that is, of performing state management. Except for the brief time when they are actually exchanging
information, the browser and Web server are disconnected. Each request a user makes to a Web server is treated
independently of any other request. Many times, however, it's useful for the Web server to recognize users when they request
a page. For example, the Web server on a shopping site keeps track of individual shoppers so the site can manage shopping
carts and other user-specific information. A cookie therefore acts as a kind of calling card, presenting pertinent identification
that helps an application know how to proceed.
Cookies are used for many purposes, all relating to helping the Web site remember users. For example, a site conducting a poll
might use a cookie simply as a Boolean value to indicate whether a user's browser has already participated in voting so that
the user cannot vote twice. A site that asks a user to log on might use a cookie to record that the user already logged on so that
the user does not have to keep entering credentials.
Cookie Limitations
Most browsers support cookies of up to 4096 bytes. Because of this small limit, cookies are best used to store small amounts
of data, or better yet, an identifier such as a user ID. The user ID can then be used to identify the user and read user information
from a database or other data store. (See the section "Cookies and Security" below for information about security implications
of storing user information.)
Browsers also impose limitations on how many cookies your site can store on the user's computer. Most browsers allow only
20 cookies per site; if you try to store more, the oldest cookies are discarded. Some browsers also put an absolute limit, usually
300, on the number of cookies they will accept from all sites combined.
A cookie limitation that you might encounter is that users can set their browser to refuse cookies. If you define a P3P privacy
policy and place it in the root of your Web site, more browsers will accept cookies from your site. However, you might have to
avoid cookies altogether and use a different mechanism to store user-specific information. A common method for storing user
information is session state, but session state depends on cookies, as explained later in the section "Cookies and Session State."
Note
For more information on state management and options for saving information in a Web application, see
ASP.NET State Management Overview and ASP.NET State Management Recommendations.

Although cookies can be very useful in your application, the application should not depend on being able to store cookies. Do
not use cookies to support critical features. If your application must rely on cookies, you can test to see whether the browser
will accept cookies. See the "Checking Whether a Browser Accepts Cookies" section later in this topic.
Writing Cookies
The browser is responsible for managing cookies on a user system. Cookies are sent to the browser via the HttpResponse
object that exposes a collection called Cookies. You can access the HttpResponse object as the Response property of your
Page class. Any cookies that you want to send to the browser must be added to this collection. When creating a cookie, you
specify a Name and Value. Each cookie must have a unique name so that it can be identified later when reading it from the
browser. Because cookies are stored by name, naming two cookies the same will cause one to be overwritten.
You can also set a cookie's date and time expiration. Expired cookies are deleted by the browser when a user visits the site that
wrote the cookies. The expiration of a cookie should be set for as long as your application considers the cookie value to be
valid. For a cookie to effectively never expire, you can set the expiration date to be 50 years from now.
Note
Users can clear the cookies on their computer at any time. Even if you store cookies with long expiration times, a user might
decide to delete all cookies, wiping out any settings you might have stored in cookies.

If you do not set the cookie's expiration, the cookie is created but it is not stored on the user's hard disk. Instead, the cookie is
maintained as part of the user's session information. When the user closes the browser, the cookie is discarded. A non-
persistent cookie like this is useful for information that needs to be stored for only a short time or that for security reasons
should not be written to disk on the client computer. For example, non-persistent cookies are useful if the user is working on a
public computer, where you do not want to write the cookie to disk.
You can add cookies to the Cookies collection in a number of ways. The following example shows two methods to write
cookies:
VB
Response.Cookies("userName").Value = "patrick"
Response.Cookies("userName").Expires = DateTime.Now.AddDays(1)

Dim aCookie As New HttpCookie("lastVisit")


aCookie.Value = DateTime.Now.ToString()
aCookie.Expires = DateTime.Now.AddDays(1)
Response.Cookies.Add(aCookie)

C#
Response.Cookies["userName"].Value = "patrick";
Response.Cookies["userName"].Expires = DateTime.Now.AddDays(1);

HttpCookie aCookie = new HttpCookie("lastVisit");


aCookie.Value = DateTime.Now.ToString();
aCookie.Expires = DateTime.Now.AddDays(1);
Response.Cookies.Add(aCookie);

The example adds two cookies to the Cookies collection, one named userName and the other named lastVisit. For the first
cookie, the values of the Cookies collection are set directly. You can add values to the collection this way because Cookies
derives from a specialized collection of type NameObjectCollectionBase.
For the second cookie, the code creates an instance of an object of type HttpCookie, sets its properties, and then adds it to the
Cookies collection via the Add method. When you instantiate an HttpCookie object, you must pass the cookie name as part of
the constructor.
Both examples accomplish the same task, writing a cookie to the browser. In both methods, the expiration value must be of
type DateTime. However, the lastVisited value is also a date-time value. Because all cookie values are stored as strings, the
date-time value has to be converted to a String .
Cookies with More Than One Value
You can store one value in a cookie, such as user name and last visit. You can also store multiple name-value pairs in a single
cookie. The name-value pairs are referred to as subkeys. (Subkeys are laid out much like a query string in a URL.) For example,
instead of creating two separate cookies named userName and lastVisit, you can create a single cookie named userInfo that
has the subkeys userName and lastVisit.
You might use subkeys for several reasons. First, it is convenient to put related or similar information into a single cookie. In
addition, because all the information is in a single cookie, cookie attributes such as expiration apply to all the information.
(Conversely, if you want to assign different expiration dates to different types of information, you should store the information
in separate cookies.)
A cookie with subkeys also helps you limit the size of cookie files. As noted earlier in the "Cookie Limitations" section, cookies
are usually limited to 4096 bytes and you can't store more than 20 cookies per site. By using a single cookie with subkeys, you
use fewer of those 20 cookies that your site is allotted. In addition, a single cookie takes up about 50 characters for overhead
(expiration information, and so on), plus the length of the value that you store in it, all of which counts toward the 4096-byte
limit. If you store five subkeys instead of five separate cookies, you save the overhead of the separate cookies and can save
around 200 bytes.
To create a cookie with subkeys, you can use a variation of the syntax for writing a single cookie. The following example shows
two ways to write the same cookie, each with two subkeys:
VB
Response.Cookies("userInfo")("userName") = "patrick"
Response.Cookies("userInfo")("lastVisit") = DateTime.Now.ToString()
Response.Cookies("userInfo").Expires = DateTime.Now.AddDays(1)

Dim aCookie As New HttpCookie("userInfo")


aCookie.Values("userName") = "patrick"
aCookie.Values("lastVisit") = DateTime.Now.ToString()
aCookie.Expires = DateTime.Now.AddDays(1)
Response.Cookies.Add(aCookie)

C#
Response.Cookies["userInfo"]["userName"] = "patrick";
Response.Cookies["userInfo"]["lastVisit"] = DateTime.Now.ToString();
Response.Cookies["userInfo"].Expires = DateTime.Now.AddDays(1);

HttpCookie aCookie = new HttpCookie("userInfo");


aCookie.Values["userName"] = "patrick";
aCookie.Values["lastVisit"] = DateTime.Now.ToString();
aCookie.Expires = DateTime.Now.AddDays(1);
Response.Cookies.Add(aCookie);

Controlling Cookie Scope


By default, all cookies for a site are stored together on the client, and all cookies are sent to the server with any request to that
site. In other words, every page in a site gets all of the cookies for that site. However, you can set the scope of cookies in two
ways:
Limit the scope of cookies to a folder on the server, which allows you to limit cookies to an application on the site.
Set scope to a domain, which allows you to specify which subdomains in a domain can access a cookie.
Limiting Cookies to a Folder or Application
To limit cookies to a folder on the server, set the cookie's Path property, as in the following example:
VB
Dim appCookie As New HttpCookie("AppCookie")
appCookie.Value = "written " & DateTime.Now.ToString()
appCookie.Expires = DateTime.Now.AddDays(1)
appCookie.Path = "/Application1"
Response.Cookies.Add(appCookie)

C#
HttpCookie appCookie = new HttpCookie("AppCookie");
appCookie.Value = "written " + DateTime.Now.ToString();
appCookie.Expires = DateTime.Now.AddDays(1);
appCookie.Path = "/Application1";
Response.Cookies.Add(appCookie);

Note
You can also write cookies by adding them to the Cookies collection directly as shown in earlier examples.

The path can either be a physical path under the site root or a virtual root. The effect will be that the cookie is available only to
pages in the Application1 folder or virtual root. For example, if your site is called www.contoso.com, the cookie created in the
previous example will be available to pages with the path http://www.contoso.com/Application1/ and to any pages beneath
that folder. However, the cookie will not be available to pages in other applications such as
http://www.contoso.com/Application2/ or just http://www.contoso.com/.
Note
In some browsers, the path is case sensitive. You cannot control how users type URLs into their browsers, but if your applicat
ion depends on cookies tied to a specific path, be sure that the URLs in any hyperlinks you create match the case of the Path
property value.

Limiting Cookie Domain Scope


By default, cookies are associated with a specific domain. For example, if your site is www.contoso.com, the cookies you write
are sent to the server when users request any page from that site. (This might not include cookies with a specific path value.) If
your site has subdomains—for example, contoso.com, sales.contoso.com, and support.contoso.com—then you can associate
cookies with a specific subdomain. To do so, set the cookie's Domain property, as in this example:
VB
Response.Cookies("domain").Value = DateTime.Now.ToString()
Response.Cookies("domain").Expires = DateTime.Now.AddDays(1)
Response.Cookies("domain").Domain = "support.contoso.com"

C#
Response.Cookies["domain"].Value = DateTime.Now.ToString();
Response.Cookies["domain"].Expires = DateTime.Now.AddDays(1);
Response.Cookies["domain"].Domain = "support.contoso.com";

When the domain is set in this way, the cookie will be available only to pages in the specified subdomain. You can also use the
Domain property to create a cookie that can be shared among multiple subdomains, as shown in the following example:
VB
Response.Cookies("domain").Value = DateTime.Now.ToString()
Response.Cookies("domain").Expires = DateTime.Now.AddDays(1)
Response.Cookies("domain").Domain = "contoso.com"

C#
Response.Cookies["domain"].Value = DateTime.Now.ToString();
Response.Cookies["domain"].Expires = DateTime.Now.AddDays(1);
Response.Cookies["domain"].Domain = "contoso.com";

The cookie will then be available to the primary domain as well as to sales.contoso.com and support.contoso.com domains.
Reading Cookies
When a browser makes a request to the server, it sends the cookies for that server along with the request. In your ASP.NET
applications, you can read the cookies using the HttpRequest object, which is available as the Request property of your Page
class. The structure of the HttpRequest object is essentially the same as that of the HttpResponse object, so you can read
cookies out of the HttpRequest object much the same way you wrote cookies into the HttpResponse object. The following
code example shows two ways to get the value of a cookie named username and display its value in a Label control:
VB
If Not Request.Cookies("userName") Is Nothing Then
Label1.Text = Server.HtmlEncode(Request.Cookies("userName").Value)
End If
If Not Request.Cookies("userName") Is Nothing Then
Dim aCookie As HttpCookie = Request.Cookies("userName")
Label1.Text = Server.HtmlEncode(aCookie.Value)
End If

C#
if(Request.Cookies["userName"] != null)
Label1.Text = Server.HtmlEncode(Request.Cookies["userName"].Value);

if(Request.Cookies["userName"] != null)
{
HttpCookie aCookie = Request.Cookies["userName"];
Label1.Text = Server.HtmlEncode(aCookie.Value);
}

Before trying to get the value of a cookie, you should make sure that the cookie exists; if the cookie does not exist, you will get
a NullReferenceException exception. Notice also that the HtmlEncode method was called to encode the contents of a cookie
before displaying it in the page. This makes certain that a malicious user has not added executable script into the cookie. For
more about cookie security, see the "Cookies and Security" section.
Note
Because different browsers store cookies differently, different browsers on the same computer won't necessarily be able to r
ead each other's cookies. For example, if you use Internet Explorer to test a page one time, but then later use a different brow
ser to test again, the second browser won't find the cookies saved by Internet Explorer.

Reading the value of a subkey in a cookie is likewise similar to setting it. The following code example shows one way to get the
value of a subkey:
VB
If Not Request.Cookies("userInfo") Is Nothing Then
Label1.Text = _
Server.HtmlEncode(Request.Cookies("userInfo")("userName"))
Label2.Text = _
Server.HtmlEncode(Request.Cookies("userInfo")("lastVisit"))
End If

C#
if(Request.Cookies["userInfo"] != null)
{
Label1.Text =
Server.HtmlEncode(Request.Cookies["userInfo"]["userName"]);

Label2.Text =
Server.HtmlEncode(Request.Cookies["userInfo"]["lastVisit"]);
}

In the preceding example, the code reads the value of the subkey lastVisit, which was set earlier to the string representation
of a DateTime value. Cookies store values as strings, so if you want to use the lastVisit value as a date, you have to convert
it to the appropriate type, as in this example:
VB
Dim dt As DateTime
dt = DateTime.Parse(Request.Cookies("userInfo")("lastVisit"))

C#
DateTime dt;
dt = DateTime.Parse(Request.Cookies["userInfo"]["lastVisit"]);
The subkeys in a cookie are typed as a collection of type NameValueCollection. Therefore, another way to get an individual
subkey is to get the subkeys collection and then extract the subkey value by name, as shown in the following example:
VB
If Not Request.Cookies("userInfo") Is Nothing Then
Dim UserInfoCookieCollection As _
System.Collections.Specialized.NameValueCollection
UserInfoCookieCollection = Request.Cookies("userInfo").Values
Label1.Text = _
Server.HtmlEncode(UserInfoCookieCollection("userName"))
Label2.Text = _
Server.HtmlEncode(UserInfoCookieCollection("lastVisit"))
End If

C#
if(Request.Cookies["userInfo"] != null)
{
System.Collections.Specialized.NameValueCollection
UserInfoCookieCollection;

UserInfoCookieCollection = Request.Cookies["userInfo"].Values;
Label1.Text =
Server.HtmlEncode(UserInfoCookieCollection["userName"]);
Label2.Text =
Server.HtmlEncode(UserInfoCookieCollection["lastVisit"]);
}

Changing a Cookie's Expiration Date


The browser is responsible for managing cookies, and the cookie's expiration time and date help the browser manage its store
of cookies. Therefore, although you can read the name and value of a cookie, you cannot read the cookie's expiration date and
time. When the browser sends cookie information to the server, the browser does not include the expiration information. (The
cookie's Expires property always returns a date-time value of zero.) If you are concerned about the expiration date of a cookie,
you must reset it, which is covered in the "Modifying and Deleting Cookies" section.
Note
You can read the Expires property of a cookie that you have set in the HttpResponse object, before the cookie has been sen
t to the browser. However, you cannot get the expiration back in the HttpRequest object.

Reading Cookie Collections


You might occasionally need to read through all the cookies available to the page. To read the names and values of all the
cookies available to the page, you can loop through the Cookies collection using code such as the following.
VB
Dim i As Integer
Dim output As System.Text.StringBuilder = New System.Text.StringBuilder
Dim aCookie As HttpCookie
For i = 0 to Request.Cookies.Count - 1
aCookie = Request.Cookies(i)
output.Append("Cookie name = " & Server.HtmlEncode(aCookie.Name) _
& "<br />")
output.Append("Cookie value = " & _
Server.HtmlEncode(aCookie.Value) & "<br /><br />")
Next
Label1.Text = output.ToString()

C#
System.Text.StringBuilder output = new System.Text.StringBuilder();
HttpCookie aCookie;
for(int i=0; i<Request.Cookies.Count; i++)
{
aCookie = Request.Cookies[i];
output.Append("Cookie name = " + Server.HtmlEncode(aCookie.Name)
+ "<br />");
output.Append("Cookie value = " + Server.HtmlEncode(aCookie.Value)
+ "<br /><br />");
}
Label1.Text = output.ToString();

Note
When you run this code, you might see a cookie named ASP.NET_SessionId. That is a cookie that ASP.NET uses to store a uni
que identifier for your session. The session cookie is not persisted on your hard disk. For more about session cookies, see the
"Cookies and Session State" later in this topic.

A limitation of the preceding example is that if the cookie has subkeys, the display shows the subkeys as a single name/value
string. You can read a cookie's HasKeys property to determine whether the cookie has subkeys. If so, you can read the subkey
collection to get individual subkey names and values. You can read subkey values from the Values collection directly by index
value. The corresponding subkey names are available in the AllKeys member of the Values collection, which returns an array of
strings. You can also use the Keys member of the Values collection. However, the AllKeys property is cached the first time it is
accessed. In contrast, the Keys property builds an array each time it is accessed. For this reason, the AllKeys property is much
faster on subsequent accesses within the context of the same page request.
The following example shows a modification of the preceding example. It uses the HasKeys property to test for subkeys, and if
subkeys are detected, the example gets subkeys from the Values collection:
VB
Dim i As Integer
Dim j As Integer
Dim output As System.Text.StringBuilder = New StringBuilder()
Dim aCookie As HttpCookie
Dim subkeyName As String
Dim subkeyValue As String
For i = 0 To Request.Cookies.Count - 1
aCookie = Request.Cookies(i)
output.Append("Name = " & aCookie.Name & "<br />")
If aCookie.HasKeys Then
For j = 0 To aCookie.Values.Count - 1
subkeyName = Server.HtmlEncode(aCookie.Values.AllKeys(j))
subkeyValue = Server.HtmlEncode(aCookie.Values(j))
output.Append("Subkey name = " & subkeyName & "<br />")
output.Append("Subkey value = " & subkeyValue & _
"<br /><br />")
Next
Else
output.Append("Value = " & Server.HtmlEncode(aCookie.Value) & _
"<br /><br />")
End If
Next
Label1.Text = output.ToString()

C#
for(int i=0; i<Request.Cookies.Count; i++)
{
aCookie = Request.Cookies[i];
output.Append("Name = " + aCookie.Name + "<br />");
if(aCookie.HasKeys)
{
for(int j=0; j<aCookie.Values.Count; j++)
{
subkeyName = Server.HtmlEncode(aCookie.Values.AllKeys[j]);
subkeyValue = Server.HtmlEncode(aCookie.Values[j]);
output.Append("Subkey name = " + subkeyName + "<br />");
output.Append("Subkey value = " + subkeyValue +
"<br /><br />");
}
}
else
{
output.Append("Value = " + Server.HtmlEncode(aCookie.Value) +
"<br /><br />");
}
}
Label1.Text = output.ToString();

Alternatively, you can extract the subkeys as a NameValueCollection object as shown in the following example:
VB
Dim i As Integer
Dim j As Integer
Dim output As System.Text.StringBuilder = New StringBuilder()
Dim aCookie As HttpCookie
Dim subkeyName As String
Dim subkeyValue As String
For i = 0 To Request.Cookies.Count - 1
aCookie = Request.Cookies(i)
output.Append("Name = " & aCookie.Name & "<br />")
If aCookie.HasKeys Then
Dim CookieValues As _
System.Collections.Specialized.NameValueCollection = _
aCookie.Values
Dim CookieValueNames() As String = CookieValues.AllKeys
For j = 0 To CookieValues.Count - 1
subkeyName = Server.HtmlEncode(CookieValueNames(j))
subkeyValue = Server.HtmlEncode(CookieValues(j))
output.Append("Subkey name = " & subkeyName & "<br />")
output.Append("Subkey value = " & subkeyValue & _
"<br /><br />")
Next
Else
output.Append("Value = " & Server.HtmlEncode(aCookie.Value) & _
"<br /><br />")
End If
Next
Label1.Text = output.ToString

C#
System.Text.StringBuilder output = new System.Text.StringBuilder();
HttpCookie aCookie;
string subkeyName;
string subkeyValue;

for (int i = 0; i < Request.Cookies.Count; i++)


{
aCookie = Request.Cookies[i];
output.Append("Name = " + aCookie.Name + "<br />");
if (aCookie.HasKeys)
{
System.Collections.Specialized.NameValueCollection CookieValues =
aCookie.Values;
string[] CookieValueNames = CookieValues.AllKeys;
for (int j = 0; j < CookieValues.Count; j++)
{
subkeyName = Server.HtmlEncode(CookieValueNames[j]);
subkeyValue = Server.HtmlEncode(CookieValues[j]);
output.Append("Subkey name = " + subkeyName + "<br />");
output.Append("Subkey value = " + subkeyValue +
"<br /><br />");
}
}
else
{
output.Append("Value = " + Server.HtmlEncode(aCookie.Value) +
"<br /><br />");
}
}
Label1.Text = output.ToString();

Modifying and Deleting Cookies


You cannot directly modify a cookie. Instead, changing a cookie consists of creating a new cookie with new values and then
sending the cookie to the browser to overwrite the old version on the client. The following code example shows how you can
change the value of a cookie that stores a count of the user's visits to the site:
VB
Dim counter As Integer
If Request.Cookies("counter") Is Nothing Then
counter = 0
Else
counter = Int32.Parse(Request.Cookies("counter").Value)
End If
counter += 1
Response.Cookies("counter").Value = counter.ToString
Response.Cookies("counter").Expires = DateTime.Now.AddDays(1)

C#
int counter;
if (Request.Cookies["counter"] == null)
counter = 0;
else
{
counter = int.Parse(Request.Cookies["counter"].Value);
}
counter++;

Response.Cookies["counter"].Value = counter.ToString();
Response.Cookies["counter"].Expires = DateTime.Now.AddDays(1);

Deleting Cookies
Deleting a cookie—physically removing it from the user's hard disk—is a variation on modifying it. You cannot directly remove
a cookie because the cookie is on the user's computer. However, you can have the browser delete the cookie for you. The
technique is to create a new cookie with the same name as the cookie to be deleted, but to set the cookie's expiration to a date
earlier than today. When the browser checks the cookie's expiration, the browser will discard the now-outdated cookie. The
following code example shows one way to delete all the cookies available to the application:
VB
Dim aCookie As HttpCookie
Dim i As Integer
Dim cookieName As String
Dim limit As Integer = Request.Cookies.Count - 1
For i = 0 To limit
cookieName = Request.Cookies(i).Name
aCookie = New HttpCookie(cookieName)
aCookie.Expires = DateTime.Now.AddDays(-1)
Response.Cookies.Add(aCookie)
Next

C#
HttpCookie aCookie;
string cookieName;
int limit = Request.Cookies.Count;
for (int i=0; i<limit; i++)
{
cookieName = Request.Cookies[i].Name;
aCookie = new HttpCookie(cookieName);
aCookie.Expires = DateTime.Now.AddDays(-1);
Response.Cookies.Add(aCookie);
}

Modifying or Deleting Subkeys


Modifying an individual subkey is the same as creating it, as shown in the following example:
VB
Response.Cookies("userInfo")("lastVisit") = DateTime.Now.ToString()
Response.Cookies("userInfo").Expires = DateTime.Now.AddDays(1)

C#
Response.Cookies["userInfo"]["lastVisit"] = DateTime.Now.ToString();
Response.Cookies["userInfo"].Expires = DateTime.Now.AddDays(1);

To delete an individual subkey, you manipulate the cookie's Values collection, which holds the subkeys. You first recreate the
cookie by getting it from the Cookies object. You can then call the Remove method of the Values collection, passing to the
Remove method the name of the subkey to delete. You then add the cookie to the Cookies collection so it will be sent in its
modified form back to the browser. The following code example shows how to delete a subkey. In the sample, the name of the
subkey to remove is specified in a variable.
VB
Dim subkeyName As String
subkeyName = "userName"
Dim aCookie As HttpCookie = Request.Cookies("userInfo")
aCookie.Values.Remove(subkeyName)
aCookie.Expires = DateTime.Now.AddDays(1)
Response.Cookies.Add(aCookie)

C#
string subkeyName;
subkeyName = "userName";
HttpCookie aCookie = Request.Cookies["userInfo"];
aCookie.Values.Remove(subkeyName);
aCookie.Expires = DateTime.Now.AddDays(1);
Response.Cookies.Add(aCookie);

Cookies and Security


The security issues with cookies are similar to those of getting data from the client. In your application, cookies are another
form of user input and are therefore subject to examining and spoofing. A user can as a minimum see the data that you store
in a cookie, since the cookie is available on the user's own computer. The user can also change the cookie before the browser
sends it to you.
You should never store sensitive data in a cookie, such as user names, passwords, credit card numbers, and so on. Do not put
anything in a cookie that should not be in the hands of a user or of someone who might somehow steal the cookie.
Similarly, be suspicious of information you get out of a cookie. Do not assume that the data is the same as when you wrote it
out; use the same safeguards in working with cookie values that you would with data that a user has typed into a Web page.
The examples earlier in this topic showed HTML-encoding the contents of a cookie before displaying the value in a page, as
you would before displaying any information you get from users.
Cookies are sent between browser and server as plain text, and anyone who can intercept your Web traffic can read the cookie.
You can set a cookie property that causes the cookie to be transmitted only if the connection uses the Secure Sockets Layer
(SSL). SSL does not protect the cookie from being read or manipulated while it is on the user's computer, but it does prevent
the cookie from being read while in transit because the cookie is encrypted. For more information, see
Basic Security Practices for Web Applications.
Determining Whether a Browser Accepts Cookies
Users can set their browser to refuse cookies. No error is raised if a cookie cannot be written. The browser likewise does not
send any information to the server about its current cookie settings.
Note
The Cookies property does not indicate whether cookies are enabled. It indicates only whether the current browser inherentl
y supports cookies.

One way to determine whether cookies are accepted is by trying to write a cookie and then trying to read it back again. If you
cannot read the cookie you wrote, you assume that cookies are turned off in the browser.
The following code example shows how you might test whether cookies are accepted. The sample consists of two pages. The
first page writes out a cookie, and then redirects the browser to the second page. The second page tries to read the cookie. It in
turn redirects the browser back to the first page, adding to the URL a query string variable with the results of the test.
The code for the first page looks like this:
VB
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
If Request.QueryString("AcceptsCookies") Is Nothing Then
Response.Cookies("TestCookie").Value = "ok"
Response.Cookies("TestCookie").Expires = _
DateTime.Now.AddMinutes(1)
Response.Redirect("TestForCookies.aspx?redirect=" & _
Server.UrlEncode(Request.Url.ToString))
Else
Label1.Text = "Accept cookies = " & _
Server.UrlEncode(Request.QueryString("AcceptsCookies"))
End If
End If
End Sub

C#
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
if (Request.QueryString["AcceptsCookies"] == null)
{
Response.Cookies["TestCookie"].Value = "ok";
Response.Cookies["TestCookie"].Expires =
DateTime.Now.AddMinutes(1);
Response.Redirect("TestForCookies.aspx?redirect=" +
Server.UrlEncode(Request.Url.ToString()));
}
else
{
Label1.Text = "Accept cookies = " +
Server.UrlEncode(
Request.QueryString["AcceptsCookies"]);
}
}
}

The page first tests to see if this is a postback, and if not, the page looks for the query string variable name AcceptsCookies
that contains the test results. If there is no query string variable, the test has not been completed, so the code writes out a
cookie named TestCookie. After writing out the cookie, the sample calls Redirect to transfer to the test page
TestForCookies.aspx. Appended to the URL of the test page is a query string variable named redirect containing the URL of
the current page; this will allow you to redirect back to this page after performing the test.
The test page can consist entirely of code; it does not need to contain controls. The following code example illustrates the test
page.
VB
Sub Page_Load()
Dim redirect As String = Request.QueryString("redirect")
Dim acceptsCookies As String
If Request.Cookies("TestCookie") Is Nothing Then
acceptsCookies = "no"
Else
acceptsCookies = "yes"
' Delete test cookie.
Response.Cookies("TestCookie").Expires = _
DateTime.Now.AddDays(-1)
End If
Response.Redirect(redirect & "?AcceptsCookies=" & acceptsCookies, _
True)
End Sub

C#
protected void Page_Load(object sender, EventArgs e)
{
string redirect = Request.QueryString["redirect"];
string acceptsCookies;
if(Request.Cookies["TestCookie"] ==null)
acceptsCookies = "no";
else
{
acceptsCookies = "yes";
// Delete test cookie.
Response.Cookies["TestCookie"].Expires =
DateTime.Now.AddDays(-1);
}
Response.Redirect(redirect + "?AcceptsCookies=" + acceptsCookies,
true);
}

After reading the redirect query string variable, the code tries to read the cookie. For housekeeping purposes, if the cookie
exists, it is immediately deleted. When the test is finished, the code constructs a new URL from the URL passed to it in the
redirect query string variable. The new URL also includes a query string variable containing test results. The final step is to
use the new URL to redirect the browser to the original page.
An improvement in the example would be to keep the cookie test results in a persistent store such as a database so that the
test does not have to be repeated each time the user views the original page. (Storing the test results in session state by default
requires cookies.)
Cookies and Session State
When a user navigates to your site, the server establishes a unique session for that user that lasts for the duration of the user's
visit. For each session, ASP.NET maintains session state information where applications can store user-specific information. For
more information, see Session State Overview topic.
ASP.NET must track a session ID for each user so that it can map the user to session state information on the server. By default,
ASP.NET uses a non-persistent cookie to store the session state. However, if a user has disabled cookies on the browser,
session state information cannot be stored in a cookie.
ASP.NET offers an alternative in the form of cookieless sessions. You can configure your application to store session IDs not in
a cookie, but in the URLs of pages in your site. If your application relies on session state, you might consider configuring it to
use cookieless sessions. However, under some limited circumstances, if the user shares the URL with someone else—perhaps
to send the URL to a colleague while the user's session is still active—then both users can end up sharing the same session,
with unpredictable results. For more information on configuring your application to use cookieless sessions, see the
ASP.NET State Management Overview topic.
See Also
Concepts
Basic Security Practices for Web Applications
Other Resources
ASP.NET State Management
ASP.NET

How to: Write a Cookie


Cookies provide a means in Web applications to store user-specific information, such as history or user preferences. A cookie
is a small bit of text that accompanies requests and responses as they go between the Web server and client. The cookie
contains information that the Web application can read whenever the user visits the site.
The browser manages the cookies on client computers. Cookies are sent to the client using the HttpResponse object, which
exposes a property called Cookies. Any cookies that you want your Web application to send to the browser must be added to
this collection. When you write a new cookie, you must specify the Name and Value. Each cookie must have a unique name so
that your Web application can identify it when the browser sends it with future requests.
There are two ways to write a cookie to a user's computer. You can either directly set cookie properties on the Cookies
collection or you can create an instance of the HttpCookie object and add it to the Cookies collection. You must create cookies
before the ASP.NET page is rendered to the client. For example, you can write a cookie in a Page_Load event handler but not
in a Page_Unload event handler. For more information on the page life cycle see ASP.NET Page Life Cycle Overview.
For more information, see ASP.NET Cookies Overview.
To write a cookie by setting cookie properties on the Cookies collection
In the ASP.NET page you want to write a cookie, assign properties to a cookie in the Cookies collection.
The following code example shows a cookie named UserSettings with the values of the subkeys Font and Color set. It
also sets the expiration time to be tomorrow.
VB
Response.Cookies("UserSettings")("Font") = "Arial"
Response.Cookies("UserSettings")("Color") = "Blue"
Response.Cookies("UserSettings").Expires = DateTime.Now.AddDays(1)

C#
Response.Cookies["UserSettings"]["Font"] = "Arial";
Response.Cookies["UserSettings"]["Color"] = "Blue";
Response.Cookies["UserSettings"].Expires = DateTime.Now.AddDays(1d);

To write a cookie by creating an instance of the HttpCookie object


1. Create an object of type HttpCookie and assign it a name.
2. Assign values to cookie's subkeys and set any cookie properties.
3. Add the cookie to the Cookies collection.
The following code example shows an instance of the HttpCookie object named myCookie, which represents a cookie
named UserSettings.
VB
Dim myCookie As HttpCookie = New HttpCookie("UserSettings")
myCookie("Font") = "Arial"
myCookie("Color") = "Blue"
myCookie.Expires = Now.AddDays(1)
Response.Cookies.Add(myCookie)

C#
HttpCookie myCookie = new HttpCookie("UserSettings");
myCookie["Font"] = "Arial";
myCookie["Color"] = "Blue";
myCookie.Expires = DateTime.Now.AddDays(1d);
Response.Cookies.Add(myCookie);

Robust Programming
By default, cookies are shared by all pages that are in the same domain, but you can limit cookies to specific subfolders in a
Web site by setting their Path property. To allow a cookie to be retrieved by all pages in all folders of your application, set it
from a page that is in the root folder of your application and do not set the Path property.
If you do not specify an expiration limit for the cookie, the cookie is not persisted to the client computer and it expires when the
user session expires.
Cookies can store values only of type String. You must convert any non-string values to strings before you can store them in a
cookie. For many data types, calling the ToString method is sufficient. For more information, see the ToString method for the
data type you wish to persist.
Security
Do not store sensitive information, such as a user name or a password, in a cookie. For more cookie security information see
ASP.NET Cookies Overview.
See Also
Tasks
How to: Read a Cookie
How to: Delete a Cookie
Concepts
ASP.NET Cookies Overview
Basic Security Practices for Web Applications
ASP.NET State Management Overview
ASP.NET

How to: Read a Cookie


Cookies provide a means in Web applications to store user-specific information, such as history or user preferences. A cookie
is a small bit of text that accompanies requests and responses as they go between the Web server and client. The cookie
contains information that the Web application can read whenever the user visits the site.
The browser is responsible for managing cookies on a user system. Cookies are sent to the server with a page request and are
accessible as part of the HttpRequest object, which exposes a Cookies collection. You can read only cookies that have been
created by pages in the current domain or path.
Procedure
To read a cookie
Read a string from the Cookies collection using the cookie's name as the key.
The following example reads a cookie named UserSettings and then reads the value of the subkey named Font.
VB
If (Request.Cookies("UserSettings") IsNot Nothing) Then
Dim userSettings As String
If (Request.Cookies("UserSettings")("Font") IsNot Nothing) Then
userSettings = Request.Cookies("UserSettings")("Font")
End If
End If

C#
if (Request.Cookies["UserSettings"] != null)
{
string userSettings;
if (Request.Cookies["UserSettings"]["Font"] != null)
{ userSettings = Request.Cookies["UserSettings"]["Font"]; }
}

Compiling the Code


This example requires:
An ASP.NET Web page.
A cookie written previously named UserSettings, as illustrated in the topic How to: Write a Cookie.

Robust Programming
For security reasons, you can read only cookies that are set by pages that are part of the same domain. If the cookie's Path
property has been set, that cookie is available only to pages and subfolders within that path of the domain.
When reading specific cookie values, test that the cookie exists and that it has a value, otherwise an exception will occur.
All values in a cookie are stored as type String, so to work with cookie values as different data types, you must convert the
value appropriately.
Security
The browser can send the data back only to the server that originally created the cookie. However, malicious users can access
cookies and read their contents. Do not store sensitive information in a cookie, such as a user name or password. Instead, store
a token that you can use to look up the sensitive information on the server. Additionally, cookies can be tampered with, so any
data in cookie should be treated with the same measures you use to prevent cross site scripting attacks. See
Script Exploits Overview for more information.
See Also
Tasks
How to: Write a Cookie
How to: Delete a Cookie
Concepts
ASP.NET Cookies Overview
Basic Security Practices for Web Applications
ASP.NET State Management Overview
ASP.NET

How to: Delete a Cookie


You cannot directly delete a cookie on a user's computer. However, you can direct the user's browser to delete the cookie by
setting the cookie's expiration date to a past date. The next time a user makes a request to a page within the domain or path
that set the cookie, the browser will determine that the cookie has expired and remove it.
Note
Calling the Remove method of the Cookies collection removes the cookie from the collection on the server side, so the cooki
e will not be sent to the client. However, the method does not remove the cookie from the client if it already exists there.

To assign a past expiration date on a cookie


1. Determine whether the cookie exists, and if so, create a new cookie with the same name.
2. Set the cookie's expiration date to a time in the past.
3. Add the cookie to the Cookies collection object.
The following code example shows how to set a past expiration date on a cookie.
VB
If (Not Request.Cookies("UserPreferences1") Is Nothing) Then
Dim myCookie As HttpCookie
myCookie = New HttpCookie("UserPreferences1")
myCookie.Expires = DateTime.Now.AddDays(-1D)
Response.Cookies.Add(myCookie)
End If

C#
if (Request.Cookies["UserSettings"] != null)
{
HttpCookie myCookie = new HttpCookie("UserSettings");
myCookie.Expires = DateTime.Now.AddDays(-1d);
Response.Cookies.Add(myCookie);
}

Compiling the Code


This example requires:
An ASP.NET Web page.
A cookie written previously named UserSettings, as illustrated in the topic How to: Write a Cookie.

Robust Programming
For security reasons, you can read only cookies that are set by pages that are part of the same domain. If the cookie's Path
property has been set, that cookie is also available only to pages and subfolders within that path of the domain.
When reading specific cookie values, test that the cookie exists and that it has a value, otherwise an exception will occur.
Security
The browser can send the data back only to the server that originally created the cookie. However, malicious users can access
cookies and read their contents. Do not store sensitive information in a cookie, such as a user name or password. Instead, store
a token that you can use to look up the sensitive information on the server. Additionally, cookies can be tampered with, so any
data in cookie should be treated with the same measures you use to prevent cross site scripting attacks. See
How to: Protect Against Script Exploits in a Web Application by Applying HTML Encoding to Strings for more information.
See Also
Tasks
How to: Write a Cookie
How to: Read a Cookie
Concepts
ASP.NET Cookies Overview
Basic Security Practices for Web Applications
ASP.NET State Management Overview
ASP.NET

ASP.NET View State


ASP.NET Web pages provide view state, which is a way for you to store information directly in the page that you want to
persist between postbacks. The topics in this section provide information on what view state is and how it works, and how you
can use view state in your application.
In This Section
View State Overview
Securing View State
How to: Save Values in View State
How to: Read Values from View State
Related Sections
ASP.NET State Management
Provides information on all the ways in ASP.NET that you can store information between page requests.
ASP.NET

View State Overview


A Web application is stateless. A new instance of the Web page class is created each time the page is requested from the
server. This would ordinarily mean that all information associated with the page and its controls would be lost with each round
trip. For example, if a user enters information into a text box on an HTML Web page, that information is sent to the server, but
is not returned to the client. To overcome this inherent limitation of Web programming, the ASP.NET page framework includes
several state-management features, one of which is view state, to preserve page and control values between round trips to the
Web server. For more information on state management, see ASP.NET State Management Overview.
View state is the method that the ASP.NET page framework uses by default to preserve page and control values between round
trips. When the HTML for the page is rendered, the current state of the page and values that need to be retained during
postback are serialized into base64-encoded strings and output in the view state hidden field or fields. You can change the
default behavior and store view state in another location such as a SQL Server database by implementing a custom
PageStatePersister class to store page data. For an example of storing page state on a stream rather than in a hidden page
field, see the example for the PageStatePersister class.
You can access view state in your own code using the page's ViewState property to preserve data during round trips to the
Web server. The ViewState property is a dictionary containing key/value pairs containing the view state data.
Security Note
It is easy for a malicious user to see and modify the contents of a hidden field. For more information on securing view state d
ata, see Securing View State.

For recommendations about when you should store information in view state, see
ASP.NET State Management Recommendations.
Data Types You Can Store in View State
You can store objects of the following types in view state:
Strings
Integers
Boolean values
Array objects
ArrayList objects
Hash tables
Custom type converters (see the TypeConverter class for more information)
You can store other types of data as well, but the class must be compiled with the Serializable attribute so that view state can
serialize them into XML.
Considerations for Using View State
View state provides state information for a specific ASP.NET page. If you need to use information on more than one page, or if
you need the information to persist across visits to the Web site, you should use another method for maintaining state, such as
application state, session state or personalization.
View state information is serialized into XML and then encoded using base64 encoding, which can generate large amounts of
data. When the page is posted back to the server, the contents of view state are sent as part of the page post-back information.
If view state contains a large amount of information, it can affect performance of the page. Therefore, it is recommended that
you test the performance of your pages using typical data for your application to determine if the size of view state is causing
performance problems for your application. For alternatives to using view state, see
ASP.NET State Management Recommendations.
In some circumstances, such as data-driven pages that are refreshed from the data store on each postback, you should turn
view state off to remove the large hidden fields generated by data controls such as the GridView control.
Note
Even when you explicitly turn view state off, a hidden field is still sent to the browser to indicate that postback is occurring for
the page.

Another important consideration is that if the amount of data in a hidden field becomes large, some proxies and firewalls will
prevent access to the page that contains them. Because the maximum amount can vary with different firewall and proxy
implementations, large hidden fields can cause sporadic problems. To help avoid this problem, if the amount of data stored in
the ViewState property exceeds the value specified in the page's MaxPageStateFieldLength property, the page splits view state
into multiple hidden fields to reduce the size of each individual field below the size that firewalls reject.
Some mobile devices do not allow hidden fields at all. Therefore, view state will not work for those devices. For more
information and alternatives, see ASP.NET Mobile Web Development Overview.
Control State
In addition to view state, ASP.NET supports a page-state feature called control state. The page uses control state to persist
control information that must be retained between postbacks, even if view state is disabled for the page or for a control. Like
view state, control state is stored view state in one or more hidden fields. For more information, see
ASP.NET State Management Overview.
See Also
Tasks
How to: Save Values in View State
How to: Read Values from View State
Concepts
ASP.NET State Management Overview
ASP.NET State Management Recommendations
ASP.NET

Securing View State


The ViewState property provides a dictionary object for retaining values between multiple requests for the same page. This is
the default method that Web pages use to preserve page and control property values between round trips.
When the page is processed, the current state of the page and controls is encoded and the resulting string is saved in the page
as a hidden field. If the amount of data that is stored in the ViewState property exceeds the value specified in the
MaxPageStateFieldLength property, the string is saved in the page as multiple hidden fields. When the page is posted back to
the server, the page parses the view state string at page initialization and restores property information.
The information in this topic describes best practices that will help you improve the security of application data that is stored in
view state.
While following coding and configuration best practices can improve the security of your application, it is also important that
you continually keep your Web server computer up to date with the latest security updates for Microsoft Windows and Internet
Information Services (IIS), as well as any security updates for Microsoft SQL Server or other membership data sources.
More detailed information about best practices for writing secure code and securing applications can be found in the book
"Writing Secure Code" by Michael Howard and David LeBlanc, or through the guidance provided by
Microsoft Patterns and Practices.
Securing View State Data on the Page
By default, view state data is stored on the page in a hidden field and is encoded using base64 encoding. In addition, a hash is
created from the data using a machine authentication code (MAC) key. The hash value is added to the encoded view state data
and the resulting string is stored on the page. When the page is posted back to the server, the ASP.NET page framework re-
hashes the view state data and compares the hash with the hash stored previously in the page. If the hash does not match, an
exception is raised indicating that view state data might be invalid.
By creating a hash value, the ASP.NET page framework can test whether the view state data has been tampered with. But view
state data can still be viewed, and can potentially be intercepted and read by malicious users.
MAC Encoding
When the ASP.NET page framework creates a hash for view state data, it uses a MAC key that is either auto-generated or
specified in the Machine.config file. If the key is auto-generated, it is created based on the MAC address of the computer. The
MAC address is the unique GUID value of the network adapter in the computer.
It can be difficult for malicious users to reverse-engineer the MAC key based on the value in the page and the view state. Thus,
MAC encoding is typically a reliable way to determine whether anyone has tampered with the view-state data.
In general, the larger the MAC key that is used to generate the hash, the less likely it is that the hash value for different strings
will be the same. When the key is auto-generated, ASP.NET uses SHA1 encoding to create a large key. However, in a Web-farm
environment, the key must be the same across all of the servers. If the key is not the same, and the page is posted back to a
different server than the one that created the page, the ASP.NET page framework will raise an exception. Therefore, in a Web
farm environment, you should specify a key in the Machine.config file instead of allowing ASP.NET to auto-generate one. The
longer the key, the more secure it is; but the longer the key is the more time it takes to create a hash, so it is important to weigh
security needs versus performance needs.
Encryption
While MAC encoding helps prevent tampering with view state data, it does not prevent users from viewing the data. View state
data is stored in one or more hidden fields on the page and is encoded using base64 encoding. You can prevent people from
viewing this data in two ways: transmitting the page over SSL and by encrypting the view state data. Requiring the page to be
sent over SSL can help prevent data-packet sniffing and unauthorized data access by people who are not the intended
recipients of the page.
However, the user who requested the page can still view the view state data because SSL decrypts the page to display it in the
browser. This is fine if you are protecting the data primarily from people who should not be allowed to see the page and are
not concerned about authorized users having access to view state data. However, in some cases controls might use view state
to store information that no users should have access to. For example, the page might contain a data-bound control that stores
item identifiers (data keys) in view state. If those identifiers contain sensitive data, such as social security numbers of customer
IDs, you should encrypt the view-state data in addition or instead of sending over SSL.
To encrypt the data, set the page's ViewStateEncryptionMode property to true. If you store information in view state, you can
use normal read and write techniques; the page handles all encryption and decryption for you. Encrypting view state data can
affect the performance of your application, so do not use encryption unless you need it.
Control State Encryption
Web controls can maintain small amounts of data, called control state, that are required for the correct operation of the control.
When a control uses control state, a view state field containing the control state is sent to the client on each request even when
view state is turned off for the application or page.
Controls that use control state can require that view state be encrypted by calling the RegisterRequiresViewStateEncryption
method. If any control on the page requires that view state be encrypted, then all view state on the page will be encrypted.
Per-user View State Encoding
If your Web site authenticates users, you can set the ViewStateUserKey property in the Page_Init event handler to associate
the page's view state with a specific user. This helps prevent one-click attacks, in which a malicious user creates a valid, pre-
filled Web page with view state from a previously created page. The attacker then lures a victim into clicking a link that sends
the page to the server using the victim's identity.
When the ViewStateUserKey property is set, the attacker's identity is used to create the hash of the view state of the original
page. When the victim is lured into resending the page, the hash values will be different because the user keys are different.
The page will fail verification and an exception will be thrown.
You must the ViewStateUserKey property to a unique value for each user, such as the user name or identifier.
Securing Configuration in Shared Hosting Environment
In a shared hosting environment, malicious users can potentially modify state-management properties that might affect other
applications on the computer. This can be done through direct modification to the Machine.config file, modification via the
configuration APIs, and other administration and configuration tools. You can help prevent modification to your application
configuration by encrypting sections of configuration files. For more information, see
Encrypting Configuration Information Using Protected Configuration
See Also
Concepts
ASP.NET State Management Recommendations
View State Overview
ASP.NET

How to: Save Values in View State


View state is a repository in an ASP.NET page that can store values that need to be retained during postback. View state is
typically used for page variables that must be retained rather than user or session data. For example, you can store information
in view state that will be accessed during the page load event the next time the page is sent to the server. For usage
recommendations, see ASP.NET State Management Recommendations.
View state data is stored in one or more hidden fields as base64-encoded strings. You can access view state information using
the page's ViewState property, which exposes a dictionary object. Because the data in view state is stored as a string, only
objects that can be serialized can be stored.
Since view state is sent as a hidden field, changes to view state can be made until the PreRenderComplete event. Once the page
is rendered to the browser, changes to view state will not be saved.
The information in the hidden view state field can be seen if the page output source is viewed, creating a potential security
issue. To mitigate this issue, you can encrypt view state by setting the viewStateEncryptionMode attribute in the @ Page
directive to "Always". For more information on security issues with saving information in view state, see Securing View State.
Note
To use the ViewState property, the ASP.NET Web page must have a server form element (<form runat="server">). For usa
ge recommendations, see ASP.NET State Management Recommendations.

This example saves a string and an integer value to view state.


To save a value to view state
In page code, set the value of the variable in the ViewState property.
The following code example shows how to save an ArrayList to view state.
VB
<%@ Page Language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1


/DTD/xhtml1-transitional.dtd">

<script runat="server">
' Sample ArrayList for the page.
Dim PageArrayList As ArrayList

Function CreateArray() As ArrayList


' Create a sample ArrayList.
Dim result As ArrayList
result = New ArrayList(4)
result.Add("item 1")
result.Add("item 2")
result.Add("item 3")
result.Add("item 4")

Return result
End Function
Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
If (Me.ViewState("arrayListInViewState") IsNot Nothing) Then
PageArrayList = CType(Me.ViewState("arrayListInViewState"), ArrayList)
Else
' ArrayList isn't in view state, so we need to load it from scratch.
PageArrayList = CreateArray()
End If
' Code that uses PageArrayList.
End Sub
Sub Page_PreRender(ByVal sender As Object, ByVal e As EventArgs)
' Save PageArrayList before the page is rendered.
Me.ViewState.Add("arrayListInViewState", PageArrayList)
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>View state sample</title>
</head>
<body>
<form id="form1" runat="server">
<div>
</div>
</form>
</body>
</html>

C#
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">

<script runat="server">
// Sample ArrayList for the page.
ArrayList PageArrayList;

ArrayList CreateArray()
{
// Create a sample ArrayList.
ArrayList result = new ArrayList(4);

result.Add("item 1");
result.Add("item 2");
result.Add("item 3");
result.Add("item 4");
return result;
}

void Page_Load(object sender, EventArgs e)


{
if (ViewState["arrayListInViewState"] != null)
{
PageArrayList = (ArrayList)ViewState["arrayListInViewState"];
}
else
{
// ArrayList isn't in view state, so we need to load it from scratch.
PageArrayList = CreateArray();
}
// Code that uses PageArrayList.
}

void Page_PreRender(object sender, EventArgs e)


{
// Save PageArrayList before the page is rendered.
ViewState.Add("arrayListInViewState", PageArrayList);
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>View state sample</title>
</head>
<body>
<form id="form1" runat="server">
<div>

</div>
</form>
</body>
</html>

To encrypt view state


In the @ Page directive, set the ViewStateEncryptionMode attribute to "Always", as in the following example:

<% @Page ViewStateEncryptionMode="Always" ... %>

Robust Programming
Only types marked with Serializable can be stored in view state. For more information, see View State Overview.
View state information is stored using base64 encoding and is included in the page during rendering, increasing the size of the
page. When the page is posted back, the contents of view state are sent as part of the page postback information. Because view
state can significantly increase network traffic and slow down connections, it is recommended that you do not store large
quantities of information in view state.
Another important consideration is that if the amount of data in a hidden field becomes large, some proxies and firewalls will
prevent access to the page that contains them. Because the maximum amount of data allowed in hidden fields can vary with
different firewall and proxy implementations, large hidden fields can cause unpredictable behavior. For more information, see
ASP.NET State Management Recommendations.
Some mobile devices do not allow hidden fields at all. Therefore, view state will not work for those devices. For more
information, see Understanding State Management.
Security
Information in view state is stored in base-64 format, but it can be tampered with by malicious users. You should treat
information stored in view state as user-supplied data and always validate the information before using it. For more
information about mitigating view state security risks, see Securing View State. For general information about securing your
ASP.NET application, see ASP.NET Web Application Security and Basic Security Practices for Web Applications.
See Also
Tasks
How to: Read Values from View State
Concepts
View State Overview
Securing View State
ASP.NET State Management Overview
ASP.NET State Management Recommendations
ASP.NET

How to: Read Values from View State


View state is a repository in an ASP.NET page that can store values that need to be retained during postback. For example, you
can store information in view state that will be accessed during the page load event the next time the page is sent to the server.
For usage recommendations, see ASP.NET State Management Recommendations.
View state data is stored in one or more hidden fields as base64-encoded strings. You can access view state information using
the page's ViewState property, which exposes a dictionary object. Because the data in view state is stored as a string, only
objects that can be serialized can be stored.
Note
To use the ViewState property, the ASP.NET Web page must contain a form element with the attribute runat="server". For
usage recommendations, see ASP.NET State Management Recommendations.

To read a value from view state


In page code, set the value of the variable in the ViewState property.
The following code example shows how you can get an ArrayList object named arrayListInViewState from view state
and then bind a GridView control to the object as a data source.
[Visual Basic]

Dim arrayList As ArrayList


arrayList = CType(ViewState("arrayListInViewState"), ArrayList)

Me.GridView1.DataSource = arrayList
Me.GridView1.DataBind()

C#
arrayList = new ArrayList();
arrayList = (ArrayList)ViewState["arrayListInViewState"];

this.GridView1.DataSource = arrayList;
this.GridView1.DataBind();

Robust Programming
Values in view state are typed as String. In Visual Basic, if you set Option Strict On, you must cast view state values to the
appropriate type before using them, as shown in the example. In C#, you should always cast to the appropriate type when
reading view state values.
No exception is thrown if you attempt to get a value out of view state that does not exist. To be sure that the value you want is
in view state, check first for the existence of the object with a test such as the following:
VB
If ViewState("color") Is Nothing Then
' No such value in view state, take appropriate action.
End If

C#
if (ViewState["color"] == null)
// No such value in view state, take appropriate action.

If you attempt to use a nonexistent view state entry in some other way (for example, to examine its type), a
NullReferenceException exception is thrown.
View state information is stored using base64 encoding and is included in the page during rendering, increasing the size of the
page. When the page is posted back, the contents of view state are sent as part of the page postback information. Because this
can significantly increase network traffic and slow down connections, it is recommended that you do not store large quantities
of information in view state.
Another important consideration is that if the amount of data in a hidden field becomes large, some proxies and firewalls will
prevent access to the page that contains them. Because the maximum amount can vary with different firewall and proxy
implementations, large hidden fields can be sporadically problematic. For more information see
ASP.NET State Management Recommendations.
Some mobile devices do not allow hidden fields at all. Therefore, view state will not work for those devices. For more
information, see ASP.NET Mobile Web Development Overview.
Security
Information in view state is stored in base-64 format, but it can be tampered with by malicious users. You should treat
information stored in view state as user-supplied data and always validate the information before using it. For more
information about mitigating view state security risks, see Securing View State. For general information about securing your
ASP.NET application, see ASP.NET Web Application Security and Basic Security Practices for Web Applications.
See Also
Tasks
How to: Save Values in View State
Concepts
View State Overview
Securing View State
ASP.NET State Management Overview
ASP.NET State Management Recommendations
ASP.NET

ASP.NET Session State


ASP.NET session state enables you to store and retrieve values for a user as the user navigates the different ASP.NET pages
that make up a Web application. HTTP is a stateless protocol, meaning that your Web server treats each HTTP request for a
page as an independent request; by default, the server retains no knowledge of variable values used during previous requests.
As a result, building Web applications that need to maintain some cross-request state information (applications that implement
shopping carts, data scrolling, and so on) can be a challenge. ASP.NET session state identifies requests received from the same
browser during a limited period of time as a session, and provides the ability to persist variable values for the duration of that
session.
ASP.NET session state is enabled by default for all ASP.NET applications. ASP.NET session-state variables are easily set and
retrieved using the Session property, which stores session variable values as a collection indexed by name. For example, the
following code example creates the session variables FirstName and LastName to represent the first name and last name of a
user, and sets them to values retrieved from TextBox controls.
VB
Session("FirstName") = FirstNameTextBox.Text
Session("LastName") = LastNameTextBox.Text

C#
Session["FirstName"] = FirstNameTextBox.Text;
Session["LastName"] = LastNameTextBox.Text;

ASP.NET stores session information in the memory space of the ASP.NET application by default. You can, optionally, store
session information using a stand-alone service so that session information is preserved if the ASP.NET application is restarted,
in a SQL Server so that session information is available to multiple Web servers in a Web farm (and also persists if the ASP.NET
application is restarted), or in a custom data store. For more information, see Session-State Modes.
ASP.NET also provides several other options for persisting data within an application besides session state. For a comparison
of each, see ASP.NET State Management Recommendations.
In This Section
Session State Overview
Describes the different capabilities of the session-state feature.
Session Identifiers
Describes how a browser is identified with a particular session.
Session-State Events
Describes session-state events that can be added to the global.asax file.
Session-State Modes
Discusses the different session-state storage modes.
Securing Session State
Describes security issues to consider when using session state.
How to: Save Values in Session State
Provides a sample of storing values in session-state variables.
How to: Read Values from Session State
Provides a sample of reading values from session-state variables.
Implementing a Session-State Store Provider
Describes how to create a custom session-state store provider and includes a sample.
Reference
System.Web.SessionState
Provides classes and interfaces that enable storage of application data in session state.
Session
Provides access to the session for the current HTTP request.
Related Sections
ASP.NET State Management Recommendations
Describes differences between ASP.NET state-management options.
ASP.NET State Management
Provides an overview of the methods available to store application state in ASP.NET applications.
ASP.NET

Session State Overview


ASP.NET session state enables you to store and retrieve values for a user as the user navigates the different ASP.NET pages
that make up a Web application. HTTP is a stateless protocol, meaning that your Web server treats each HTTP request for a
page as an independent request; the server retains no knowledge of variable values used during previous requests. ASP.NET
session state identifies requests from the same browser during a limited time window as a session, and provides the ability to
persist variable values for the duration of that session.
ASP.NET session state is enabled by default for all ASP.NET applications.
Alternatives to session state include application state (see the Application property), which stores variables that can be
accessed by all users of an ASP.NET application; the System.Web.Profile namespace, which persists user values in a data store
without expiring them using a time-out; the System.Web.Caching namespace, which stores frequently used values in memory
that is available to all ASP.NET applications; ASP.NET System.Web.UI.WebControls, which persist control values in the
ViewState; Cookies; the QueryString; and fields on an HTML form that are available from an HTTP POST using the Form
collection. See ASP.NET State Management Recommendations for a comparison of different state-management options.
Session Variables
Session variables are stored in a SessionStateItemCollection that is exposed through the System.Web.HttpContext.Session
property. The collection of session variables is indexed by the name of the variable or by an integer index. Session variables are
created by simply referring to the session variable by name. You do not need to declare a session variable or explicitly add it to
the collection. For example, the following code example creates session variables for the first and last name of a user and sets
them to values retrieved from TextBox controls.
VB
Session("FirstName") = FirstNameTextBox.Text
Session("LastName") = LastNameTextBox.Text

C#
Session["FirstName"] = FirstNameTextBox.Text;
Session["LastName"] = LastNameTextBox.Text;

By default, session variables can be any valid .NET type. For example, the following code example stores an ArrayList of values
in a session variable named "StockPicks." Note that the value returned by the "StockPicks" session variable must be cast as the
appropriate type upon retrieval from the SessionStateItemCollection.
Note
When you use a session-state mode other than InProc, the session-variable type must be either a primitive .NET type or seria
lizable, because the session-variable value is stored in an external data store. For more information, see Session-State Modes.

VB
' When retrieving an object from session state, cast it as
' the appropriate type.
Dim stockPicks As ArrayList = CType(Session("StockPicks"), ArrayList)
' Write the modified stock picks list back to session state.
Session("StockPicks") = stockPicks

C#
// When retrieving an object from session state, cast it as
// the appropriate type.
ArrayList stockPicks = (ArrayList)Session["StockPicks"];
// Write the modified stock picks list back to session state.
Session["StockPicks"] = stockPicks;

Session Identifiers
Sessions are identified by a unique session identifier that can be read using the SessionID property. When session state is
enabled for an ASP.NET application, each request for a page in the application is examined for a SessionID value sent from the
browser. If no SessionID value is supplied, ASP.NET starts a new session and the SessionID for that session is sent to the
browser with the response.
SessionID values are stored in a cookie, by default, but you can also configure your application to store SessionID values in
the URL for a "cookieless" session. For more information, see Session Identifiers.
A session is considered active as long as requests continue to be made with the same SessionID value. If the time between
requests for a particular session exceeds the specified time-out value in minutes, then the session is considered expired.
Requests made with an expired SessionID value result in a new session being started.
Session Events
ASP.NET provides two events that help you manage user sessions: the Session_OnStart event, which is raised when a new
session begins, and the Session_OnEnd event, which is raised when a session is abandoned or expires. Session events are
specified in the Global.asax file for an ASP.NET application. Note that the Session_OnEnd event is not supported if the session
Mode is set to a value other than InProc, which is the default mode.
Note
If the Global.asax file or Web.config file for an ASP.NET application is modified, the application will be restarted and any value
s stored in application state or session state will be lost. Be aware that some anti-virus software can update the last-modified
date and time of the Global.asax or Web.config file for an application.

For more information, see Session-State Events.


Session Modes
ASP.NET session state supports several different storage options for session variables. Each option is identified as a session-
state Mode. The default behavior is to store session variables in the memory space of the ASP.NET worker process. However,
you can also specify that session state be stored in a separate process, in a SQL Server database, or in a custom data source. If
you do not want session state enabled for your application, you can set the session mode to Off.
For more information, see Session-State Modes.
Configuring Session State
Session state is configured using the sessionState element of the system.web configuration section. You can also configure
session state using the EnableSessionState page directive.
The sessionState element allows you to specify the mode in which the session will store data, the way in which session
identifier values are sent between the client and the server, the session Timeout value, and supporting values based on the
session Mode. For example, the following sessionState element configures an application for SQLServer session mode, with a
Timeout of 30 minutes, and specifies that session identifiers are stored in the URL.

<sessionState mode="SQLServer"
cookieless="true "
regenerateExpiredSessionId="true "
timeout="30"
sqlConnectionString="Data Source=MySqlServer;Integrated Security=SSPI;"
stateNetworkTimeout="30"/>

You can disable session state for an application by setting the session-state mode to Off. If you want to disable session state
for only a particular page of an application, you can set the EnableSessionState page directive to false. Note that the
EnableSessionState page directive can also be set to ReadOnly to provide read-only access to session variables.
Concurrent Requests and Session State
Access to ASP.NET session state is exclusive per session, which means that if two different users make concurrent requests,
access to each separate session is granted concurrently. However, if two concurrent requests are made for the same session
(that is, using the same SessionID value), then the first request received gains exclusive access to the session information and
the second request will execute once the first request completes, or until the exclusive lock on the information is freed due to
the first request exceeding the lock timeout. If the EnableSessionState page directive is set to ReadOnly, then a request for
the read-only session information does not result in an exclusive lock on the session data. Read-only requests for session data
may still have to wait for a lock gained by a read-write request for session data to clear.
See Also
Other Resources
ASP.NET Session State
ASP.NET State Management
ASP.NET

Session Identifiers
Browser sessions are identified using a unique identifier stored in the SessionID property. The session ID enables an ASP.NET
application to associate a specific browser with related session data and information on the Web server. Session ID values are
transmitted between the browser and the Web server in a cookie, or in the URL if cookieless sessions are specified.
Caution
P:System.Web.SessionState.HttpSessionState.SessionID values are sent in clear text whether as a cookie or as part of the URL.
An unwanted source could gain access to the session of another user by obtaining the SessionID value and including it in re
quests to the server. If you are storing private or sensitive information in session state, it is recommended that you use SSL t
o encrypt any communication between the browser and server that includes the SessionID.

Cookieless SessionIDs
The SessionID is stored in a non-expiring session cookie in the browser by default. You can specify that session identifiers not
be stored in a cookie by setting the cookieless attribute to true in the sessionState section of the Web.config file.
Note
To improve the security of your application, you should allow users to log out of your application, at which point the applicati
on should call the Abandon method. This reduces the potential for an unwanted source to obtain the unique identifier in the
URL and use it to retrieve private user data stored in the session.

ASP.NET maintains cookieless session state by automatically inserting a unique session ID into the page's URL. For example,
the following URL has been modified by ASP.NET to include the unique session ID lit3py55t21z5v55vlm25s55:

http://www.example.com/s(lit3py55t21z5v55vlm25s55)/orderform.aspx

ASP.NET modifies the links contained in all requested pages that use a path relative to the application (explicit paths are not
modified) by embedding a session ID value in the links just before sending each page to the browser. Session state is
maintained as long as the user follows the path of links that the ASP.NET application provides. However, if the client rewrites a
URL supplied by the application, ASP.NET may not be able to resolve the session ID and associate the request with an existing
session, resulting in a new session being started for the request.
The session ID is embedded in the URL after the slash that follows the application name and before any remaining file or
virtual directory identifier. This allows ASP.NET to resolve the application name before involving the SessionStateModule in the
request.
The following example shows a Web.config file that configures an ASP.NET application to use cookieless session identifiers.

<configuration>
<system.web>
<sessionState cookieless="true"
regenerateExpiredSessionId="true" />
</system.web>
</configuration>

Regenerating Expired Session Identifiers


The session ID values used in cookieless sessions are recycled by default. That is, if a request is made with a session ID that has
expired, a new session is started using the SessionID supplied with the request. This behavior can result in the unwanted
sharing of session data when a link that contains a cookieless SessionID is shared with multiple browsers, perhaps through a
search engine or other program. You can reduce the possibility of session data being shared by multiple clients by disabling
the recycling of session identifiers. To do this, set the regenerateExpiredSessionId attribute of the sessionState configuration
element to true. This will result in a new session ID being generated when a cookieless session request is made with an expired
session ID.
Note
If the request made with the expired session ID is made using the HTTP POST method, then any posted data will be lost whe
n regenerateExpiredSessionId is true, as ASP.NET performs a redirect to ensure that the browser has the new session iden
tifier in the URL.

Custom Session Identifiers


You can implement a custom class to supply and validate SessionID values by creating a class that inherits the
SessionIDManager class and overriding the CreateSessionID and Validate methods with your own custom implementations.
For an example of overriding the SessionIDManager class and implementing these methods, see the example provided for
the CreateSessionID method.
You can replace the entire SessionIDManager by creating a class that implements the ISessionIDManager interface. For
example, you may have a Web application that associates a unique identifier with non-ASP.NET pages such as HTML pages or
images using an ISAPI filter. You can implement a custom SessionIDManager class to use this unique identifier with ASP.NET
session state. If your custom class supports cookieless session identifiers, you will need to implement a solution for sending
and retrieving session identifiers in the URL
See Also
Other Resources
ASP.NET Session State
ASP.NET State Management
ASP.NET

Session-State Events
ASP.NET provides two events that help you manage user sessions: the Session_OnStart event, which is raised when a new
session begins, and the Session_OnEnd event, which is raised when a session is abandoned or expires.
Note
If the Global.asax file or Web.config file for an ASP.NET application is modified, the application will be restarted. If the current
session-state mode is InProc, any values stored in application state or session state will be lost. Be aware that some anti-virus
software can update the last-modified date and time of the Global.asax or Web.config file for an application. For information
on setting the session state mode, see Session-State Modes.

The Session_OnStart Event


You can handle the Session_OnStart event by adding a subroutine named Session_OnStart to the Global.asax file. The
Session_OnStart subroutine is run at the beginning of a request if the request begins a new session. A new session will be
started if a request is made that does not contain a SessionID value or if the SessionID property contained in the request
references a session that has expired.
You can use the Session_OnStart event to initialize session variables as well as to track session-related information.
The Session_OnEnd Event
You can handle the Session_OnEnd event by adding a subroutine named Session_OnEnd to the Global.asax file. The
Session_OnEnd subroutine is run when the Abandon method has been called or when the session has expired. A session
expires when the number of minutes specified by the Timeout property passes without a request being made for the session.
The Session_OnEnd event is supported only when the session state Mode property is set to InProc, which is the default. If the
session state Mode is StateServer or SQLServer, then the Session_OnEnd event in the Global.asax file is ignored. If the
session state Mode is set to Custom, then support for the Session_OnEnd event is determined by the custom session-state
store provider.
You can use the Session_OnEnd event to clean up session-related information such as information for a user that is tracked in
a data source by the SessionID value.
Session Events Example
The following code example shows a sample of the Session_OnStart and Session_OnEnd subroutines you can add to the
Global.asax file. The subroutines defined in this example create a counter that keeps track of the number of application users
actively using the application. Note that this example will function properly only when the session state Mode property is set
to InProc, as the Session_OnEnd event is only supported for in-process session-state storage.
VB
<script language="VB" runat="server">
Public Sub Application_OnStart()
Application("UsersOnline") = 0
End Sub

Public Sub Session_OnStart()


Application.Lock()
Application("UsersOnline") = CInt(Application("UsersOnline")) + 1
Application.UnLock()
End Sub
Public Sub Session_OnEnd()
Application.Lock()
Application("UsersOnline") = CInt(Application("UsersOnline")) - 1
Application.UnLock()
End Sub
</script>

C#
<script language="C#" runat="server">
public void Application_OnStart()
{
Application["UsersOnline"] = 0;
}
public void Session_OnStart()
{
Application.Lock();
Application["UsersOnline"] = (int)Application["UsersOnline"] + 1;
Application.UnLock();
}

public void Session_OnEnd()


{
Application.Lock();
Application["UsersOnline"] = (int)Application["UsersOnline"] - 1;
Application.UnLock();
}
</script>

See Also
Other Resources
ASP.NET Session State
ASP.NET State Management
ASP.NET

Session-State Modes
ASP.NET session state supports several different storage options for session data. Each option is identified by a value in the
SessionStateMode enumeration. The following list describes the available session state modes:
InProc mode, which stores session state in memory on the Web server. This is the default.
StateServer mode, which stores session state in a separate process called the ASP.NET state service. This ensures that
session state is preserved if the Web application is restarted and also makes session state available to multiple Web
servers in a Web farm.
SQLServer mode stores session state in a SQL Server database. This ensures that session state is preserved if the Web
application is restarted and also makes session state available to multiple Web servers in a Web farm.
Custom mode, which enables you to specify a custom storage provider.
Off mode, which disables session state.
You can specify which mode you want ASP.NET session state to use by assigning a SessionStateMode enumeration values to
the mode attribute of the sessionState element in your application's Web.config file. Modes other than InProc and Off require
additional parameters, such as connection-string values as discussed later in this topic. You can view the currently selected
session state by accessing the value of the System.Web.SessionState.HttpSessionState.Mode property.
In-Process Mode
In-process mode is the default session state mode and is specified using the InProc SessionStateMode enumeration value.
In-process mode stores session state values and variables in memory on the local Web server. It is the only mode that supports
the Session_OnEnd event. For more information about the Session_OnEnd event, see Session-State Events.
Caution
If you enable Web-garden mode by setting the webGarden attribute to true in the processModel element of the application'
s Web.config file, do not use InProc session state mode. If you do, data loss can occur if different requests for the same sessi
on are served by different worker processes.

State Server Mode


StateServer mode stores session state in a process, referred to as the ASP.NET state service, that is separate from the ASP.NET
worker process or IIS application pool. Using this mode ensures that session state is preserved if the Web application is
restarted and also makes session state available to multiple Web servers in a Web farm.
To use StateServer mode, you must first be sure the ASP.NET state service is running on the server used for the session store.
The ASP.NET state service is installed as a service when ASP.NET and the .NET Framework are installed. The ASP.Net state
service is installed at the following location:
systemroot\Microsoft.NET\Framework\versionNumber\aspnet_state.exe
To configure an ASP.NET application to use StateServer mode, in the application's Web.config file do the following:
Set the mode attribute of the sessionState element to StateServer.
Set the stateConnectionString attribute to tcpip=serverName:42424.
Note
To improve the security of your application when using StateServer mode, it is recommended that you protect your st
ateConnectionString value by encrypting the sessionState section of your configuration file. For details, see
Encrypting Configuration Information Using Protected Configuration.

The following example shows a configuration setting for StateServer mode where session state is stored on a remote
computer named SampleStateServer:

<configuration>
<system.web>
<sessionState mode="StateServer"
stateConnectionString="tcpip=SampleStateServer:42424"
cookieless="false"
timeout="20"/>
</system.web>
</configuration>

Note
Objects stored in session state must be serializable if the mode is set to StateServer. For information on serializable objects,
see the SerializableAttribute class.

To use StateServer mode in a Web farm, you must have the same encryption keys specified in the machineKey element of
your Web configuration for all applications that are part of the Web farm. For information on how to create machine keys, see
article 313091, "How to create keys by using Visual Basic .NET for use in Forms authentication," in the Microsoft Knowledge
Base at http://support.microsoft.com.
SQL Server Mode
SQLServer mode stores session state in a SQL Server database. Using this mode ensures that session state is preserved if the
Web application is restarted and also makes session state available to multiple Web servers in a Web farm.
Note
Objects stored in session state must be serializable if the mode is SQL Server. For information on serializable objects, see the
SerializableAttribute class.

To use SQLServer mode, you must first be sure the ASP.NET session state database is installed on SQL Server. You can install
the ASP.NET session state database using the Aspnet_regsql.exe tool, as described later in this topic.
To configure an ASP.NET application to use SQLServer mode, do the following in the application's Web.config file:
Set the mode attribute of the sessionState element to SQLServer.
Set the sqlConnectionString attribute to a connection string for your SQL Server database.
Note
to improve the security of your application when using SQLServer mode, it is recommended that you protect your sql
ConnectionString value by encrypting the sessionState section of your configuration file. For details, see
Encrypting Configuration Information Using Protected Configuration.

The following example shows a configuration setting for SQLServer mode where session state is stored on a SQL Server
named "SampleSqlServer":

<configuration>
<system.web>
<sessionState mode="SQLServer"
sqlConnectionString="Integrated Security=SSPI;data
source=SampleSqlServer;" />
</system.web>
</configuration>

Note
If you specify a trusted connection to your SQL Server in the configuration file using the sessionState element's sqlConnecti
onString attribute, the SessionStateModule will connect to SQL Server using SQL Server integrated security. The connection
will be made using the ASP.NET process identity or the user credentials supplied for the identity configuration element, if the
y exist. You can specify that the IIS impersonated identity be used instead by specifying <identity impersonate="true" />
and setting the useHostingIdentity attribute of the sessionState configuration element to false. For more information on th
e ASP.NET process identity, see Configuring ASP.NET Process Identity and ASP.NET Impersonation.
To configure SQLServer mode for a Web farm, in the configuration file for each Web server, set the sessionState element's
sqlConnectionString attribute to point to the same SQL Server database. The path for the ASP.NET application in the IIS
metabase must be identical on all Web servers that share session state in the SQL Server database. For information on steps to
resolve the issue when application paths differ between servers, see article 325056, "PRB: Session State Is Lost in Web Farm If
You Use SqlServer or StateServer Session Mode," in the Microsoft Knowledge Base at http://support.microsoft.com.
Installing the Session State Database Using the Aspnet_regsql.exe Tool
To install the session state database on SQL Server, run the Aspnet_regsql.exe tool located in the
systemroot\Microsoft.NET\Framework\versionNumber folder on your Web server. Supply the following information with the
command:
The name of the SQL Server instance, using the -S option.
The logon credentials for an account that has permission to create a database on SQL Server. Use the -E option to use the
currently logged-on user, or use the -U option to specify a user ID along with the -P option to specify a password.
The -ssadd command-line option to add the session state database.
By default, you cannot use the Aspnet_regsql.exe tool to install the session state database on SQL Server Express Edition.
In order to run the Aspnet_regsql.exe tool to install a SQL Server Express Edition database, you must first enable the
Agent XPs SQL Server option using T-SQL commands like the following:

EXECUTE sp_configure 'show advanced options', 1


RECONFIGURE WITH OVERRIDE
GO

EXECUTE sp_configure 'Agent XPs', 1


RECONFIGURE WITH OVERRIDE
GO

EXECUTE sp_configure 'show advanced options', 0


RECONFIGURE WITH OVERRIDE
GO

You must run these T-SQL commands for any instance of SQL Server Express Edition where the Agent XPs option is
disabled.
By default, the Aspnet_regsql.exe tool will create a database named ASPState containing stored procedures that support
SQLServer mode. Session data itself is stored in the tempdb database by default. You can optionally use the -sstype option to
change the storage location of session data. The following table specifies the possible values for the -sstype option:
Opti Description
on
t Stores session data in the SQL Server tempdb database. This is the default. If you store session data in the tempdb datab
ase, the session data is lost if SQL Server is restarted.

p Stores session data in the ASPState database instead of in the tempdb database.

c Stores session data in a custom database. If you specify the c option, you must also include the name of the custom data
base using the -d option.

For example, the following command creates a database named ASPState on a SQL Server instance named "SampleSqlServer"
and specifies that session data is also stored in the ASPState database:
aspnet_regsql.exe -S SampleSqlServer -E -ssadd -sstype p
Note
If you are running ASP.NET 1.0 or ASP.NET 1.1, you cannot use the Aspnet_regsql.exe tool to configure ASP.NET to store sessi
on state in a persistent SQL Server database. However, you can obtain scripts to store session state in a persistent database. F
or details, see article 311209, "HOW TO: Configure ASP.NET for Persistent SQL Server Session State Management" in the Mic
rosoft Knowledge Base at http://support.microsoft.com. As an alternative, Web servers running ASP.NET 1.0 or ASP.NET 1.1 c
an direct persistent session state to a SQL Server that has the ASP.NET 2.0 session state schema installed.

In SQLServer mode, you can configure several computers running SQL Server to work as a failover cluster, which is two or
more identical computers running SQL Server that store data for a single database. If one computer running SQL Server fails,
another server in the cluster can take over and serve requests without session-data loss. To configure SQL Server mode for a
failover cluster, you must specify -sstype p when you execute the Aspnet_regsql.exe tool so that session state data is stored in
the ASPState database instead of the tempdb database. Storing session state in the tempdb database is not supported for a
SQL Server cluster. For more information about setting up SQL Server mode for a failover cluster, see article 323262, "How to
use ASP.NET session state SQL Server Mode in a failover cluster" in the Microsoft Knowledge Base at
http://support.microsoft.com.
Custom Mode
Custom mode specifies that you want to store session state data using a custom session state store provider. When you
configure your ASP.NET application with a Mode of Custom, you must specify the type of the session state store provider
using the providers sub-element of the sessionState configuration element. You specify the provider type using an add sub-
element and include both a type attribute that specifies the provider's type name and a name attribute that specifies the
provider instance name. The name of the provider instance is then supplied to the customProvider attribute of the
sessionState element to configure ASP.NET session state to use that provider instance for storing and retrieving session data.
The following example shows elements from a Web.config file that specify that ASP.NET session state use a custom session
state store provider:

<configuration>
<connectionStrings>
<add name="OdbcSessionServices"
connectionString="DSN=SessionState;" />
</connectionStrings>
<system.web>
<sessionState
mode="Custom"
customProvider="OdbcSessionProvider">
<providers>
<add name="OdbcSessionProvider"
type="Samples.AspNet.Session.OdbcSessionStateStore"
connectionStringName="OdbcSessionServices"
writeExceptionsToEventLog="false" />
</providers>
</sessionState>
</system.web>
</configuration>

For more information on custom session state store providers, see Implementing a Session-State Store Provider.
Note
A custom session state store provider will access any secured resource, such as SQL Server, using the ASP.NET process identi
ty or the user credentials supplied to the identity configuration element, if they exist. You can specify that the IIS impersonate
d identity be used instead by specifying <identity impersonate="true" /> and setting the useHostingIdentity attribute o
f the sessionState configuration element to false. For more information on the ASP.NET process identity, see
Configuring ASP.NET Process Identity and ASP.NET Impersonation.

See Also
Reference
providers Element for sessionState (ASP.NET Settings Schema)
Other Resources
ASP.NET Session State
ASP.NET State Management
ASP.NET

Securing Session State


ASP.NET session state enables you to store and retrieve values for a user as the user navigates the different ASP.NET pages
that make up a Web application. ASP.NET session state identifies requests from the same browser during a limited time
window as a session and can persist variable values for the duration of that session. Browser sessions are identified in a
session cookie or in the URL when session state is configured as "cookieless."
ASP.NET session state is enabled by default for all ASP.NET applications and is configured to use session cookies to identify
browser sessions.
ASP.NET session state stores session-variable values in memory by default, but you can also configure session state to store
session-variable values in a state server, a SQL Server, or a custom session-state store.
While following coding and configuration best practices can improve the security of your application, it is also important that
you continually keep your application server up to date with the latest security patches for Microsoft Windows and Internet
Information Services (IIS), as well as with any patches for Microsoft SQL Server, Active Directory, and other data sources for
your application.
For more detailed information about best practices for writing secure code and securing applications, see the book Writing
Secure Code by Michael Howard and David LeBlanc and the guidance provided by Microsoft Patterns and Practices
(http://www.microsoft.com/resources/practices/default.mspx).
Secure Session-State Configuration
The session-state feature is enabled by default. While the default configuration settings are set to the most secure values, you
should disable session state if it is not required for your application. For information about session-state configuration settings
and their default values, see sessionState Element (ASP.NET Settings Schema).
Securing Configuration Values
When storing sensitive information in a configuration file for an application, you should encrypt the sensitive values using
Protected Configuration. Information that is especially sensitive includes the encryption keys stored in the machineKey
configuration element and data source connection strings stored in the connectionStrings configuration element. For more
information, see Encrypting Configuration Information Using Protected Configuration.
Securing Connections to a Session State Data Source
Connection Strings
As mentioned earlier, it is important to protect the sensitive information stored in a connection string to a computer running
SQL Server, the session state service, or another data source. To keep the connection to your data server secure, it is
recommended that you encrypt connection-string information in the configuration by using Protected Configuration. For more
information, see Encrypting Configuration Information Using Protected Configuration.
Connecting to SQL Server using Integrated Security
You should connect to computers running SQL Server using Integrated Security to avoid the possibility of your connection
string being compromised and your user ID and password being exposed. When you specify a connection that uses Integrated
Security to connect to a computer running SQL Server, the session-state feature reverts to the identity of the process. You
should ensure that the identity of the process that is running ASP.NET (for example, the application pool) is the default process
account or a restricted user account. For more information, see ASP.NET Impersonation and Session-State Modes.
Securing the Session ID
When protecting your application and data, it is important that you safeguard the session identifier from being exposed to an
unwanted source over the network and being used in a replay attack against your application. The following recommendations
can improve the security of your session identifier.
Protect your application with Secure Sockets Layer (SSL).
Specify a smaller value for the session Timeout. Also consider forcing a redirect on the client that is the same length as
the session time-out by using a client script, or adding a refresh header by using the AddHeader method as shown in the
following example.
VB
Response.AddHeader("Refresh", Session.Timeout & ";URL=Logoff.htm"
Response.AddHeader("Refresh", Session.Timeout + ";URL=Logoff.htm";

Avoid using cookieless sessions. If you specify cookieless sessions, warn users not to e-mail, bookmark, or save links that
contain a Session ID.
Avoid specifying cookie modes of AutoDetect and UseDeviceProfile.
Allow users to log out, at which point you should call theSystem.Web.SessionState.HttpSessionState.Abandon method.
Warn the user to close his or her browser after logging out.
When using cookieless sessions, configure regenerateExpiredSessionID as true to always start a new session when an
expired session identifier is supplied.
Secure Web Pages that Use Session State
Application pages that work with sensitive data should be secured using standard Web-security mechanisms, such as using
Secure Sockets Layer (SSL) and requiring that users be logged in to carry out sensitive operations like updating personal
information or deleting accounts.
Additionally, pages should not expose sensitive feature data such as passwords, and in some cases user names, in clear text.
Ensure that pages that display such information make use of SSL and are available only to authenticated users.
Error Messages and Events
Exceptions
To prevent sensitive information from being exposed to unwanted sources, configure your application either to not display
detailed error messages or to display detailed error messages only when the client is the Web server itself. For more
information, see customErrors Element (ASP.NET Settings Schema).
Event Log
If your server is running Windows Server 2003, you can improve the security of your application by securing the event log, and
by setting parameters regarding the size, retention, and so on of the event log to prevent an indirect denial of service attack
against it.
Custom Session-State Store Providers
When creating a custom session-state store provider, ensure that you follow security best practices to avoid attacks such as
SQL injection attacks when working with a database. When making use of a custom session-state store provider, ensure that
the provider has been reviewed for security best practices.
See Also
Other Resources
ASP.NET Session State
ASP.NET Web Site Security (Visual Studio)
ASP.NET

How to: Save Values in Session State


This example uses the HttpSessionState object to persist values within an individual session.
Example
VB
Dim firstName As String = "John"
Dim lastName As String = "Smith"
Dim city As String = "Seattle"
Session("FirstName") = firstName
Session("LastName") = lastName
Session("City") = city

C#
string firstName = "Jeff";
string lastName = "Smith";
string city = "Seattle";
Session["FirstName"] = firstName;
Session["LastName"] = lastName;
Session["City"] = city;

Compiling the Code


This example requires:
A Web Forms page or class that has access to the current request context using the Current property in an ASP.NET
application that has session state enabled.
Robust Programming
Session state can expire (by default, after 20 minutes of inactivity), and the information that you store there can be lost. You
can control session-state lifetime using the timeout attribute of the sessionState configuration section.
Depending on your application requirements, you may want to consider an alternative to session state for storing information
for each user. ASP.NET provides several other options for persisting data within an application. For a comparison of each, see
ASP.NET State Management Recommendations.
See Also
Tasks
How to: Save Values in View State
Reference
HttpSessionState Class
Concepts
ASP.NET State Management Overview
ASP.NET State Management Recommendations
Other Resources
ASP.NET State Management
ASP.NET

How to: Read Values from Session State


This example accesses the Item property to retrieve the values in session state.
Example
VB
Dim firstName as String = CType(Session.Item("FirstName"), String)
Dim lastName as String = CType(Session.Item("LastName"), String)
Dim city as String = CType(Session.Item("City"), String)

C#
string firstName = (string)(Session["First"]);
string lastName = (string)(Session["Last"]);
string city = (string)(Session["City"]);

Compiling the Code


This example requires:
A Web Forms page or class that has access to the current request context using the Current property in an ASP.NET
application that has session state enabled.
Robust Programming
No exception is thrown if you attempt to get a value out of session state that does not exist. To be sure that the value you want
is in session state, check first for the existence of the object with a test such as the following:
VB
If Session.Item("FirstName") Is Nothing Then
' No such value in session state, take appropriate action.
End If

C#
if (Session["City"] == null)
// No such value in session state; take appropriate action.

If you attempt to use a nonexistent session state entry in some other way (for example, to examine its type), a
NullReferenceException exception is thrown.
Session values are of type Object. In Visual Basic, if you set Option Strict On, you must cast from type Object to the
appropriate type when getting values out of session state, as shown in the example. In C#, you should always cast to the
appropriate type when reading session values.
See Also
Tasks
How to: Read Values from View State
How to: Save Values in View State
Concepts
ASP.NET State Management Overview
ASP.NET State Management Recommendations
Other Resources
ASP.NET State Management
ASP.NET

Implementing a Session-State Store Provider


Describes a custom session-state store provider implementation and demonstrates implementing a sample provider.
ASP.NET session state is designed to enable you to store user session data in different sources. By default, session state values and information are stored in memory within the ASP.NET process. One
alternative is to store session data in a state server, which keeps session data in a separate process and retains it if the ASP.NET application is shut down and restarted. Another alternative is to store session
data in a SQL Server database, where it can be shared by multiple Web servers.
You can use the session-state stores that are included with ASP.NET, or you can implement your own session-state store provider. You might create a custom session-state store provider for the following
reasons:
You need to store session-state information in a data source other than SQL Server, such as a FoxPro database or an Oracle database.
You need to manage session-state information using a database schema that is different from the database schema used by the providers that ship with the .NET Framework. An example of this would
be shopping cart data that is stored with a predefined schema in your existing SQL Server database.
You can implement a custom session-state store provider by creating a class that inherits the SessionStateStoreProviderBase class. For more information, see the "Required Classes" section later in this
topic.
The Session State Module
Session state is managed by the SessionStateModule class, which calls the session-state store provider to read and write session data to the data store at different times during a request. At the beginning
of a request, the SessionStateModule instance retrieves data from the data source by calling the GetItemExclusive method, or if the EnableSessionState page attribute has been set to ReadOnly, by calling
the GetItem method. At the end of a request, if the session-state values have been modified, the SessionStateModule instance calls the
System.Web.SessionState.SessionStateStoreProviderBase.SetAndReleaseItemExclusive(System.Web.HttpContext,System.String,System.Web.SessionState.SessionStateStoreData,System.Object,System.Boolean)
method to write the updated values to the session-state store. SessionStateModule calls additional members of the SessionStateStoreProviderBase implementation to initialize a new session as well as
to delete session data from the data store when the System.Web.SessionState.HttpSessionState.Abandon method is called. Each member of the SessionStateStoreProviderBase class is discussed in more
detail in the "Required Classes" section later in this topic.
The SessionStateModule class determines the SessionID value itself, rather than relying on the session-state store provider to do so. If needed, you can implement a custom SessionIDManager by creating
a class that inherits the ISessionIDManager interface. For more information, see the "Remarks" section in ISessionIDManager.
SessionStateModule will revert to the ASP.NET process identity to access any secured resource, such as a database server. You can specify that the SessionStateModule instance impersonate the identity
supplied by IIS by setting the useHostingIdentity attribute of the <sessionState> configuration element to false. For example, if you have configured your IIS application to use Windows Integrated
security and you want ASP.NET to impersonate the identity provided by IIS for session management, specify <identity impersonate="true" /> in the <system.web> configuration section of the
Web.config file for the application, and set the useHostingIdentity attribute of the <sessionState> configuration element to false. If the useHostingIdentity attribute is true, ASP.NET will impersonate
the process identity, or the user credentials supplied to the <identity> configuration element (if they exist) when connecting to the data source. For more information on the ASP.NET process identity, see
Configuring ASP.NET Process Identity and ASP.NET Impersonation.
Locking Session-Store Data
ASP.NET applications are multithreaded so they can respond to multiple concurrent requests. Multiple concurrent requests might attempt to access the same session information. Consider a scenario where
multiple frames in a frameset all reference ASP.NET Web pages in the same application. The separate requests for each frame in the frameset might be executed on the Web server concurrently on different
threads. If the ASP.NET pages for each frame access session-state variables, you could have multiple threads accessing the session store concurrently. To avoid data collisions at the session store and
unexpected session-state behavior, the SessionStateModule and SessionStateStoreProviderBase classes include functionality that exclusively locks the session-store item for a particular session during
the execution of an ASP.NET page. Note that no lock is set on a session-store item if the EnableSessionState attribute is marked as ReadOnly. However, other ASP.NET pages in the same application
might be able to write to the session store, so a request for read-only session data from the store might still have to wait for locked data to be freed.
A lock is set on session-store data at the beginning of the request in the call to the GetItemExclusive method. When the request completes, the lock is released during the call to the
SetAndReleaseItemExclusive method.
If the SessionStateModule instance encounters locked session data during the call to either the GetItemExclusive or GetItem method, it will re-request the session data at half-second intervals until
either the lock is released or the amount of time specified in the ExecutionTimeout property has elapsed. If the request times out, SessionStateModule calls the ReleaseItemExclusive method to free the
session-store data and request the session-store data at that time.
Locked session-store data might have been freed by a call to the ReleaseItemExclusive method on a separate thread, before the call to the SetAndReleaseItemExclusive method for the current
response. This could cause the SessionStateModule instance to set and release session-state store data that has already been released and modified by another session. To avoid this situation,
SessionStateModule includes a lock identifier with each request to modify locked session-store data. Session-store data is only modified if the lock identifier in the data store matches the lock identifier
supplied by SessionStateModule.
Deleting Expired Session-Store Data
When the Abandon method is called for a session, the data for that session is deleted from the data store using the RemoveItem method. Otherwise, the data remains in the session data store to serve
future requests for the session.
The mechanism for deleting expired session data depends on the capabilities of your data source. If your data source can be configured to delete expired session data according to the session Timeout
property, you can use the SetItemExpireCallback method to reference the delegate for the Session_OnEnd event and raise it when deleting expired session data.
ApplicationName
To maintain session scope, session-state providers store session information uniquely for each application. This allows multiple ASP.NET applications to use the same data source without running into a
conflict if duplicate session identifiers are encountered.
Because session-state store providers store session information uniquely for each application, you must ensure that your data schema, queries, and updates include the application name. For example, the
following command might be used to retrieve session data from a database.

SELECT * FROM Sessions


WHERE SessionID = 'ABC123' AND ApplicationName = 'MyApplication'

Alternatively, you can store a combination of the session identifier and the application name as the unique identifier for an item in the session-state data store.
Required Classes
To implement a session-state store provider, create a class that inherits the SessionStateStoreProviderBase abstract class. The SessionStateStoreProviderBase class in turn inherits the ProviderBase
abstract class, so you must implement the required members of the ProviderBase class as well. The following tables list the properties and methods that you must implement from the ProviderBase and
SessionStateStoreProviderBase abstract classes and provides a description of each. To view an implementation of each member, see Sample Session-State Store Provider.
Required ProviderBase Members
Member Description
Initialize m Takes as input the name of the provider and a NameValueCollection instance of configuration settings. This method is used to set property values for the provider instance, including implement
ethod ation-specific values and options specified in the configuration file (Machine.config or Web.config).
Required SessionStateStoreProvider Members
Member Description
InitializeRequest Takes as input the HttpContext instance for the current request and performs any initialization required by your session-state store provider.
method

EndRequest met Takes as input the HttpContext instance for the current request and performs any cleanup required by your session-state store provider.
hod

Dispose method Frees any resources no longer in use by the session-state store provider.
GetItemExclus Takes as input the HttpContext instance for the current request and the SessionID value for the current request. Retrieves session values and information from the session data store and
ive method locks the session-item data at the data store for the duration of the request. The GetItemExclusive method sets several output-parameter values that inform the calling SessionStateMod
ule about the state of the current session-state item in the data store.
If no session item data is found at the data store, the GetItemExclusive method sets the locked output parameter to false and returns null. This causes SessionStateModule to call the
CreateNewStoreData method to create a new SessionStateStoreData object for the request.
If session-item data is found at the data store but the data is locked, the GetItemExclusive method sets the locked output parameter to true, sets the lockAge output parameter to the curr
ent date and time minus the date and time when the item was locked, sets the lockId output parameter to the lock identifier retrieved from the data store, and returns null. This causes Sess
ionStateModule to call the GetItemExclusive method again after a half-second interval, to attempt to retrieve the session-item information and obtain a lock on the data. If the value tha
t the lockAge output parameter is set to exceeds the ExecutionTimeout value, SessionStateModule calls the ReleaseItemExclusive method to clear the lock on the session-item data a
nd then call the GetItemExclusive method again.
The actionFlags parameter is used with sessions whose Cookieless property is true, when the regenerateExpiredSessionId attribute is set to true. An actionFlags value set to
InitializeItem (1) indicates that the entry in the session data store is a new session that requires initialization. Uninitialized entries in the session data store are created by a call to the
CreateUninitializedItem method. If the item from the session data store is already initialized, the actionFlags parameter is set to zero.
If your provider supports cookieless sessions, set the actionFlags output parameter to the value returned from the session data store for the current item. If the actionFlags parameter value
for the requested session-store item equals the InitializeItem enumeration value (1), the GetItemExclusive method should set the value in the data store to zero after setting the actionFl
ags out parameter.

GetItem metho This method performs the same work as the GetItemExclusive method, except that it does not attempt to lock the session item in the data store. The GetItem method is called when the E
d nableSessionState attribute is set to ReadOnly.

SetAndRelease Takes as input the HttpContext instance for the current request, the SessionID value for the current request, a SessionStateStoreData object that contains the current session values to
ItemExclusive be stored, the lock identifier for the current request, and a value that indicates whether the data to be stored is for a new session or an existing session.
method
If the newItem parameter is true, the SetAndReleaseItemExclusive method inserts a new item into the data store with the supplied values. Otherwise, the existing item in the data store i
s updated with the supplied values, and any lock on the data is released. Note that only session data for the current application that matches the supplied SessionID value and lock identifie
r values is updated.
After the SetAndReleaseItemExclusive method is called, the ResetItemTimeout method is called by SessionStateModule to update the expiration date and time of the session-item data
.

ReleaseItemEx Takes as input the HttpContext instance for the current request, the SessionID value for the current request, and the lock identifier for the current request, and releases the lock on an ite
clusive method m in the session data store. This method is called when the GetItem or GetItemExclusive method is called and the data store specifies that the requested item is locked, but the lock age h
as exceeded the ExecutionTimeout value. The lock is cleared by this method, freeing the item for use by other requests.

RemoveItem Takes as input the HttpContext instance for the current request, the SessionID value for the current request, and the lock identifier for the current request, and deletes the session informa
method tion from the data store where the data store item matches the supplied SessionID value, the current application, and the supplied lock identifier. This method is called when the Abandon
method is called.

CreateUninitia Takes as input the HttpContext instance for the current request, the SessionID value for the current request, and the lock identifier for the current request, and adds an uninitialized item t
lizedItem meth o the session data store with an actionFlags value of InitializeItem.
od
The CreateUninitializedItem method is used with cookieless sessions when the regenerateExpiredSessionId attribute is set to true, which causes SessionStateModule to generate a
new SessionID value when an expired session ID is encountered.
The process of generating a new SessionID value requires the browser to be redirected to a URL that contains the newly generated session ID. The CreateUninitializedItem method is cal
led during an initial request that contains an expired session ID. After SessionStateModule acquires a new SessionID value to replace the expired session ID, it calls the CreateUninitiali
zedItem method to add an uninitialized entry to the session-state data store. The browser is then redirected to the URL containing the newly generated SessionID value. The existence of t
he uninitialized entry in the session data store ensures that the redirected request with the newly generated SessionID value is not mistaken for a request for an expired session, and instea
d is treated as a new session.
The uninitialized entry in the session data store is associated with the newly generated SessionID value and contains only default values, including an expiration date and time, and a value
that corresponds to the actionFlags parameter of the GetItem and GetItemExclusive methods. The uninitialized entry in the session state store should include an actionFlags value equ
al to the InitializeItem enumeration value (1). This value is passed to SessionStateModule by the GetItem and GetItemExclusive methods and specifies for SessionStateModule that
the current session is a new session. SessionStateModule will then initialize the new session and raise the Session_OnStart event.

CreateNewSto Takes as input the HttpContext instance for the current request and the Timeout value for the current session, and returns a new SessionStateStoreData object with an empty
reData method ISessionStateItemCollection object, an HttpStaticObjectsCollection collection, and the specified Timeout value. The HttpStaticObjectsCollection instance for the ASP.NET application can
be retrieved using the GetSessionStaticObjects method.

SetItemExpire Takes as input a delegate that references the Session_OnEnd event defined in the Global.asax file. If the session-state store provider supports the Session_OnEnd event, a local reference t
Callback meth o the SessionStateItemExpireCallback parameter is set and the method returns true; otherwise, the method returns false.
od

Sample Provider
To view an example implementation of a custom session-state store provider that manages session information in an Access database, see Sample Session-State Store Provider.
See Also
Concepts
Sample Session-State Store Provider
Other Resources
ASP.NET Session State
ASP.NET State Management
ASP.NET

Sample Session-State Store Provider


Describes a custom session-state store-provider implementation that uses the ODBC .NET Framework data provider to
manage session information in an Access database.
The following topics include the code for a sample session-state store-provider implementation. The sample provider uses the
System.Data.Odbc classes to store and retrieve session information by using an Access database.
This topic describes implementation details about the sample session-state store provider and describes how to build the
sample and configure an ASP.NET application to use the sample provider.
The code for the sample provider can be found in the How to: Sample Session-State Store Provider topic.
Database Schema
The sample session-state provider uses a single table named Sessions to manage session information. To create the Access
table used by the sample provider, issue the following data-definition query in a new or existing Access database.

CREATE TABLE Sessions


(
SessionId Text(80) NOT NULL,
ApplicationName Text(255) NOT NULL,
Created DateTime NOT NULL,
Expires DateTime NOT NULL,
LockDate DateTime NOT NULL,
LockId Integer NOT NULL,
Timeout Integer NOT NULL,
Locked YesNo NOT NULL,
SessionItems Memo,
Flags Integer NOT NULL,
CONSTRAINT PKSessions PRIMARY KEY (SessionId, ApplicationName)
)

Event Log Access


If the sample provider encounters an exception when working with the data source, it writes the details of the exception to the
Application Event Log instead of returning the exception to the ASP.NET application. This is done as a security measure to avoid
private information about the data source from being exposed in the ASP.NET application.
The sample provider specifies an event Source property value of "OdbcSessionStateStore." Before your ASP.NET application
will be able to write to the Application Event Log successfully, you will need to create the following registry key:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application\OdbcSessionStateS
tore

If you do not want the sample provider to write exceptions to the event log, then you can set the custom
writeExceptionsToEventLog attribute to false in the Web.config file.
Support for the Session_OnEnd Event
The sample session-state store provider does not support the Session_OnEnd event defined in the Global.asax file, as there is
no way for the Access database to notify the session-state store provider that the expiration date and time for a session has
passed. The session-state store provider must query for this information. You cannot predict when the session-state store
provider will be used, and it is therefore unlikely that the Session_OnEnd event will be raised at the exact time that the session
times out. As a result, the SetItemExpireCallback method implementation in the sample session-state store provider returns
false, to inform the SessionStateModule that the Session_OnEnd event is not supported.
Cleaning Up Expired Session Data
Because the sample session-state store provider does not provide support for the Session_OnEnd event, it does not
automatically clean up expired session-item data. It is recommended that you periodically delete expired session information
from the data store with the following code.
VB
Dim commandString As String = "DELETE FROM Sessions WHERE Expires < ?"
Dim conn As OdbcConnection = new OdbcConnection(connectionString)
Dim cmd As OdbcCommand = New OdbcCommand(commandString, conn)
cmd.Parameters.Add("@Expires", OdbcType.DateTime).Value = DateTime.Now
conn.Open()
cmd.ExecuteNonQuery()
conn.Close()

C#
string commandString = "DELETE FROM Sessions WHERE Expires < ?";
OdbcConnection conn = new OdbcConnection(connectionString);
OdbcCommand cmd = new OdbcCommand(commandString, conn);
cmd.Parameters.Add("@Expires", OdbcType.DateTime).Value = DateTime.Now;
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();

Building the Sample Provider


In order to use the sample provider, you can place your source code in the App_Code directory of your application. Note that if
you already have source code in the App_Code directory of your application, you must add the version of the sample provider
that is written in the same language as the existing code in the directory. The provider will be compiled by ASP.NET when your
application is requested.
You can also compile the sample provider as a library and place it in the Bin directory of your Web application, or strongly
name it and place it in the GAC. The following command shows how to compile the sample provider using the command-line
compiler after the sample code has been copied to a file named OdbcSessionStateStore.vb for Visual Basic and
OdbcSessionStateStore.cs for C#.
VB
vbc /out:OdbcSessionStateStore.dll /t:library OdbcSessionStateStore.vb /r:System.Web.dll /r
:System.Configuration.dll

C#
csc /out:OdbcSessionStateStore.dll /t:library OdbcSessionStateStore.cs /r:System.Web.dll /r
:System.Configuration.dll

Using the Sample Provider in an ASP.NET Application


The following example shows the Web.config file for an ASP.NET application configured to use the sample provider. The
example uses an ODBC DSN named "SessionState" to obtain connection information for the Access database. To use the
sample provider, you will need to either create the "SessionState" System DSN or supply a valid ODBC connection string to
your database.
The example configuration assumes that your Web site is set up to use forms authentication and includes an ASP.NET page
called login.aspx that allows users to log in.

<configuration>
<connectionStrings>
<add name="OdbcSessionServices" connectionString="DSN=SessionState;" />
</connectionStrings>
<system.web>
<sessionState
cookieless="true"
regenerateExpiredSessionId="true"
mode="Custom"
customProvider="OdbcSessionProvider">
<providers>
<add name="OdbcSessionProvider"
type="Samples.AspNet.Session.OdbcSessionStateStore"
connectionStringName="OdbcSessionServices"
writeExceptionsToEventLog="false" />
</providers>
</sessionState>
</system.web>
</configuration>

See Also
Concepts
Implementing a Session-State Store Provider
Other Resources
ASP.NET Session State
ASP.NET State Management
ASP.NET

How to: Sample Session-State Store Provider


Demonstrates a session-state store provider implementation.
The following code example program shows how to implement a session-state store provider. For details about how to build
this provider and use it in an ASP.NET application, see Sample Session-State Store Provider.
Example
VB
Imports System
Imports System.Web
Imports System.Web.Configuration
Imports System.Configuration
Imports System.Collections.Specialized
Imports System.Web.SessionState
Imports System.Data
Imports System.Data.Odbc
Imports System.Diagnostics
Imports System.IO

' This session state store provider supports the following schema:
'
' CREATE TABLE Sessions
' (
' SessionId Text(80) NOT NULL,
' ApplicationName Text(255) NOT NULL,
' Created DateTime NOT NULL,
' Expires DateTime NOT NULL,
' LockDate DateTime NOT NULL,
' LockId Integer NOT NULL,
' Timeout Integer NOT NULL,
' Locked YesNo NOT NULL,
' SessionItems Memo,
' Flags Integer NOT NULL,
' CONSTRAINT PKSessions PRIMARY KEY (SessionId, ApplicationName)
' )
'
' This session state store provider does not automatically clean up
' expired session item data. It is recommended
' that you periodically delete expired session information from the
' data store with the following code (where 'conn' is the OdbcConnection
' for the session state store provider):
'
' Dim commandString As String = "DELETE FROM Sessions WHERE Expires < ?"
' Dim conn As OdbcConnection = New OdbcConnection(connectionString)
' Dim cmd As OdbcCommand = New OdbcCommand(commandString, conn)
' cmd.Parameters.Add("@Expires", OdbcType.DateTime).Value = DateTime.Now
' conn.Open()
' cmd.ExecuteNonQuery()
' conn.Close()

Namespace Samples.AspNet.Session

Public NotInheritable Class OdbcSessionStateStore


Inherits SessionStateStoreProviderBase
Private pConfig As SessionStateSection = Nothing
Private connectionString As String
Private pConnectionStringSettings As ConnectionStringSettings
Private eventSource As String = "OdbcSessionStateStore"
Private eventLog As String = "Application"
Private exceptionMessage As String = _
"An exception occurred. Please contact your administrator."
Private pApplicationName As String

'
' If False, exceptions are thrown to the caller. If True,
' exceptions are written to the event log.
'

Private pWriteExceptionsToEventLog As Boolean = False


Public Property WriteExceptionsToEventLog As Boolean
Get
Return pWriteExceptionsToEventLog
End Get
Set
pWriteExceptionsToEventLog = value
End Set
End Property

'
' The ApplicationName property is used to differentiate sessions
' in the data source by application.
'

Public ReadOnly Property ApplicationName As String


Get
Return pApplicationName
End Get
End Property

'
' ProviderBase members
'

Public Overrides Sub Initialize(name As String, config As NameValueCollection)

'
' Initialize values from web.config.
'

If config Is Nothing Then _


Throw New ArgumentNullException("config")

If name Is Nothing OrElse name.Length = 0 Then _


name = "OdbcSessionStateStore"

If String.IsNullOrEmpty(config("description")) Then
config.Remove("description")
config.Add("description", "Sample ODBC Session State Store provider")
End If

' Initialize the abstract base class.


MyBase.Initialize(name, config)

'
' Initialize the ApplicationName property.
'

pApplicationName = _
System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath

'
' Get <sessionState> configuration element.
'
Dim cfg As System.Configuration.Configuration = _
WebConfigurationManager.OpenWebConfiguration(ApplicationName)
pConfig = _
CType(cfg.GetSection("system.web/sessionState"), SessionStateSection)

'
' Initialize OdbcConnection.
'

pConnectionStringSettings = _
ConfigurationManager.ConnectionStrings(config("connectionStringName"))

If pConnectionStringSettings Is Nothing OrElse _


pConnectionStringSettings.ConnectionString.Trim() = "" Then
Throw New HttpException("Connection string cannot be blank.")
End If

connectionString = pConnectionStringSettings.ConnectionString

'
' Initialize WriteExceptionsToEventLog
'

pWriteExceptionsToEventLog = False

If Not config("writeExceptionsToEventLog") Is Nothing Then


If config("writeExceptionsToEventLog").ToUpper() = "TRUE" Then _
pWriteExceptionsToEventLog = True
End If
End Sub

'
' SessionStateStoreProviderBase members
'

Public Overrides Sub Dispose()


End Sub

'
' SessionStateProviderBase.SetItemExpireCallback
'

Public Overrides Function SetItemExpireCallback( _


expireCallback As SessionStateItemExpireCallback) As Boolean

Return False
End Function

'
' SessionStateProviderBase.SetAndReleaseItemExclusive
'

Public Overrides Sub SetAndReleaseItemExclusive(context As HttpContext, _


id As String, _
item As SessionStateStoreData, _
lockId As Object, _
newItem As Boolean)

' Serialize the SessionStateItemCollection as a string.


Dim sessItems As String = Serialize(CType(item.Items, SessionStateItemCollection))

Dim conn As OdbcConnection = New OdbcConnection(connectionString)


Dim cmd As OdbcCommand
Dim deleteCmd As OdbcCommand = Nothing

If newItem Then
' OdbcCommand to clear an existing expired session if it exists.
deleteCmd = New OdbcCommand("DELETE FROM Sessions " & _
"WHERE SessionId = ? AND ApplicationName = ? AND Expires < ?", conn)
deleteCmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id
deleteCmd.Parameters.Add( _
"@ApplicationName", OdbcType.VarChar, 255).Value = ApplicationName
deleteCmd.Parameters.Add( _
"@Expires", OdbcType.DateTime).Value = DateTime.Now

' OdbcCommand to insert the New session item.


cmd = New OdbcCommand("INSERT INTO Sessions " & _
" (SessionId, ApplicationName, Created, Expires, " & _
" LockDate, LockId, Timeout, Locked, SessionItems, Flags) " & _
" Values(?, ?, ?, ?, ?, ? , ?, ?, ?, ?)", conn)
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id
cmd.Parameters.Add( _
"@ApplicationName", OdbcType.VarChar, 255).Value = ApplicationName
cmd.Parameters.Add( _
"@Created", OdbcType.DateTime).Value = DateTime.Now
cmd.Parameters.Add( _
"@Expires", OdbcType.DateTime).Value = DateTime.Now.AddMinutes(CDbl(item.Timeout)
)
cmd.Parameters.Add( _
"@LockDate", OdbcType.DateTime).Value = DateTime.Now
cmd.Parameters.Add("@LockId", OdbcType.Int).Value = 0
cmd.Parameters.Add( _
"@Timeout", OdbcType.Int).Value = item.Timeout
cmd.Parameters.Add("@Locked", OdbcType.Bit).Value = False
cmd.Parameters.Add( _
"@SessionItems", OdbcType.VarChar, sessItems.Length).Value = sessItems
cmd.Parameters.Add("@Flags", OdbcType.Int).Value = 0
Else

' OdbcCommand to update the existing session item.


cmd = New OdbcCommand( _
"UPDATE Sessions SET Expires = ?, SessionItems = ?, Locked = ? " & _
" WHERE SessionId = ? AND ApplicationName = ? AND LockId = ?", conn)
cmd.Parameters.Add("@Expires", OdbcType.DateTime).Value = _
DateTime.Now.AddMinutes(CDbl(item.Timeout))
cmd.Parameters.Add("@SessionItems", _
OdbcType.VarChar, sessItems.Length).Value = sessItems
cmd.Parameters.Add("@Locked", OdbcType.Bit).Value = False
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id
cmd.Parameters.Add( _
"@ApplicationName", OdbcType.VarChar, 255).Value = ApplicationName
cmd.Parameters.Add("@LockId", OdbcType.Int).Value = lockId
End If

Try
conn.Open()

If Not deleteCmd Is Nothing Then _


deleteCmd.ExecuteNonQuery()
cmd.ExecuteNonQuery()
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "SetAndReleaseItemExclusive")
Throw New Exception(exceptionMessage)
Else
Throw e
End If
Finally
conn.Close()
End Try
End Sub

'
' SessionStateProviderBase.GetItem
'

Public Overrides Function GetItem(context As HttpContext, _


id As String, _
ByRef locked As Boolean, _
ByRef lockAge As TimeSpan, _
ByRef lockId As Object, _
ByRef actionFlags As SessionStateActions) _
As SessionStateStoreData

Return GetSessionStoreItem(False, context, id, locked, lockAge, lockId, actionFlags)


End Function

'
' SessionStateProviderBase.GetItemExclusive
'

Public Overrides Function GetItemExclusive(context As HttpContext, _


id As String, _
ByRef locked As Boolean, _
ByRef lockAge As TimeSpan, _
ByRef lockId As Object, _
ByRef actionFlags As SessionStateActions) _
As SessionStateStoreData

Return GetSessionStoreItem(True, context, id, locked, lockAge, lockId, actionFlags)


End Function

'
' GetSessionStoreItem is called by both the GetItem and
' GetItemExclusive methods. GetSessionStoreItem retrieves the
' session data from the data source. If the lockRecord parameter
' is True (in the case of GetItemExclusive), then GetSessionStoreItem
' locks the record and sets a New LockId and LockDate.
'

Private Function GetSessionStoreItem(lockRecord As Boolean, _


context As HttpContext, _
id As String, _
ByRef locked As Boolean, _
ByRef lockAge As TimeSpan, _
ByRef lockId As Object, _
ByRef actionFlags As SessionStateActions) _
As SessionStateStoreData

' Initial values for Return value and out parameters.


Dim item As SessionStateStoreData = Nothing
lockAge = TimeSpan.Zero
lockId = Nothing
locked = False
actionFlags = 0

' Connection to ODBC database.


Dim conn As OdbcConnection = New OdbcConnection(connectionString)
' OdbcCommand for database commands.
Dim cmd As OdbcCommand = Nothing
' DataReader to read database record.
Dim reader As OdbcDataReader = Nothing
' DateTime to check if current session item is expired.
Dim expires As DateTime
' String to hold serialized SessionStateItemCollection.
Dim serializedItems As String = ""
' True if a record is found in the database.
Dim foundRecord As Boolean = False
' True if the returned session item is expired and needs to be deleted.
Dim deleteData As Boolean = False
' Timeout value from the data store.
Dim timeout As Integer = 0

Try
conn.Open()

' lockRecord is True when called from GetItemExclusive and


' False when called from GetItem.
' Obtain a lock if possible. Ignore the record if it is expired.
If lockRecord Then
cmd = New OdbcCommand( _
"UPDATE Sessions SET" & _
" Locked = ?, LockDate = ? " & _
" WHERE SessionId = ? AND ApplicationName = ? AND Locked = ? AND Expires > ?",
conn)
cmd.Parameters.Add("@Locked", OdbcType.Bit).Value = True
cmd.Parameters.Add("@LockDate", OdbcType.DateTime).Value = _
DateTime.Now
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, _
255).Value = ApplicationName
cmd.Parameters.Add("@Locked", OdbcType.Int).Value = False
cmd.Parameters.Add( _
"@Expires", OdbcType.DateTime).Value = DateTime.Now

If cmd.ExecuteNonQuery() = 0 Then
' No record was updated because the record was locked or not found.
locked = True
Else
' The record was updated.
locked = False
End If
End If

' Retrieve the current session item information.


cmd = New OdbcCommand( _
"SELECT Expires, SessionItems, LockId, LockDate, Flags, Timeout " & _
" FROM Sessions " & _
" WHERE SessionId = ? AND ApplicationName = ?", conn)
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, _
255).Value = ApplicationName

' Retrieve session item data from the data source.


reader = cmd.ExecuteReader(CommandBehavior.SingleRow)

Do While reader.Read()
expires = reader.GetDateTime(0)

If expires < DateTime.Now Then


' The record was expired. Mark it as not locked.
locked = False
' The session was expired. Mark the data for deletion.
deleteData = True
Else
foundRecord = True
End If

serializedItems = reader.GetString(1)
lockId = reader.GetInt32(2)
lockAge = DateTime.Now.Subtract(reader.GetDateTime(3))
actionFlags = CType(reader.GetInt32(4), SessionStateActions)
timeout = reader.GetInt32(5)
Loop

reader.Close()

' If the returned session item is expired,


' delete the record from the data source.
If deleteData Then
cmd = New OdbcCommand("DELETE FROM Sessions " & _
"WHERE SessionId = ? AND ApplicationName = ?", conn)
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, _
255).Value = ApplicationName

cmd.ExecuteNonQuery()
End If
' The record was not found. Ensure that locked is False.
If Not foundRecord Then _
locked = False

' If the record was found and you obtained a lock, then set
' the lockId, clear the actionFlags,
' and create the SessionStateStoreItem to return.
If foundRecord AndAlso Not locked Then
lockId = CInt(lockId) + 1

cmd = New OdbcCommand("UPDATE Sessions SET" & _


" LockId = ?, Flags = 0 " & _
" WHERE SessionId = ? AND ApplicationName = ?", conn)
cmd.Parameters.Add("@LockId", OdbcType.Int).Value = lockId
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = Application
Name

cmd.ExecuteNonQuery()

' If the actionFlags parameter is not InitializeItem,


' deserialize the stored SessionStateItemCollection.
If actionFlags = SessionStateActions.InitializeItem Then
item = CreateNewStoreData(context, pConfig.Timeout.Minutes)
Else
item = Deserialize(context, serializedItems, timeout)
End If
End If
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "GetSessionStoreItem")
Throw New Exception(exceptionMessage)
Else
Throw e
End If
Finally
If Not reader Is Nothing Then reader.Close()
conn.Close()
End Try

Return item
End Function

'
' Serialize is called by the SetAndReleaseItemExclusive method to
' convert the SessionStateItemCollection into a Base64 string to
' be stored in an Access Memo field.
'

Private Function Serialize(items As SessionStateItemCollection) As String


Dim ms As MemoryStream = New MemoryStream()
Dim writer As BinaryWriter = New BinaryWriter(ms)

If Not items Is Nothing Then _


items.Serialize(writer)

writer.Close()

Return Convert.ToBase64String(ms.ToArray())
End Function

'
' Deserialize is called by the GetSessionStoreItem method to
' convert the Base64 string stored in the Access Memo field to a
' SessionStateItemCollection.
'

Private Function Deserialize(context As HttpContext, _


serializedItems As String, timeout As Integer) As SessionStateStoreData

Dim ms As MemoryStream = _
New MemoryStream(Convert.FromBase64String(serializedItems))

Dim sessionItems As SessionStateItemCollection = _


New SessionStateItemCollection()

If ms.Length > 0 Then


Dim reader As BinaryReader = New BinaryReader(ms)
sessionItems = SessionStateItemCollection.Deserialize(reader)
End If

Return New SessionStateStoreData(sessionItems, _


SessionStateUtility.GetSessionStaticObjects(context), _
timeout)
End Function

'
' SessionStateProviderBase.ReleaseItemExclusive
'

Public Overrides Sub ReleaseItemExclusive(context As HttpContext, _


id As String, _
lockId As Object)

Dim conn As OdbcConnection = New OdbcConnection(connectionString)


Dim cmd As OdbcCommand = _
New OdbcCommand("UPDATE Sessions SET Locked = 0, Expires = ? " & _
"WHERE SessionId = ? AND ApplicationName = ? AND LockId = ?", conn)
cmd.Parameters.Add("@Expires", OdbcType.DateTime).Value = _
DateTime.Now.AddMinutes(pConfig.Timeout.Minutes)
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, _
255).Value = ApplicationName
cmd.Parameters.Add("@LockId", OdbcType.Int).Value = lockId

Try
conn.Open()

cmd.ExecuteNonQuery()
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "ReleaseItemExclusive")
Throw New Exception(exceptionMessage)
Else
Throw e
End If
Finally
conn.Close()
End Try
End Sub

'
' SessionStateProviderBase.RemoveItem
'

Public Overrides Sub RemoveItem(context As HttpContext, _


id As String, _
lockId As Object, _
item As SessionStateStoreData)

Dim conn As OdbcConnection = New OdbcConnection(connectionString)


Dim cmd As OdbcCommand = New OdbcCommand("DELETE * FROM Sessions " & _
"WHERE SessionId = ? AND ApplicationName = ? AND LockId = ?", conn)
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, _
255).Value = ApplicationName
cmd.Parameters.Add("@LockId", OdbcType.Int).Value = lockId

Try
conn.Open()

cmd.ExecuteNonQuery()
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "RemoveItem")
Throw New Exception(exceptionMessage)
Else
Throw e
End If
Finally
conn.Close()
End Try
End Sub

'
' SessionStateProviderBase.CreateUninitializedItem
'

Public Overrides Sub CreateUninitializedItem(context As HttpContext, _


id As String, _
timeout As Integer)

Dim conn As OdbcConnection = New OdbcConnection(connectionString)


Dim cmd As OdbcCommand = New OdbcCommand("INSERT INTO Sessions " & _
" (SessionId, ApplicationName, Created, Expires, " & _
" LockDate, LockId, Timeout, Locked, SessionItems, Flags) " & _
" Values(?, ?, ?, ?, ?, ? , ?, ?, ?, ?)", conn)
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, _
255).Value = ApplicationName
cmd.Parameters.Add("@Created", OdbcType.DateTime).Value = _
DateTime.Now
cmd.Parameters.Add("@Expires", OdbcType.DateTime).Value = _
DateTime.Now.AddMinutes(CDbl(timeout))
cmd.Parameters.Add("@LockDate", OdbcType.DateTime).Value = _
DateTime.Now
cmd.Parameters.Add("@LockId", OdbcType.Int).Value = 0
cmd.Parameters.Add("@Timeout", OdbcType.Int).Value = timeout
cmd.Parameters.Add("@Locked", OdbcType.Bit).Value = False
cmd.Parameters.Add("@SessionItems", OdbcType.VarChar, 0).Value = ""
cmd.Parameters.Add("@Flags", OdbcType.Int).Value = 1

Try
conn.Open()

cmd.ExecuteNonQuery()
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "CreateUninitializedItem")
Throw New Exception(exceptionMessage)
Else
Throw e
End If
Finally
conn.Close()
End Try
End Sub

'
' SessionStateProviderBase.CreateNewStoreData
'

Public Overrides Function CreateNewStoreData( _


context As HttpContext, _
timeout As Integer) As SessionStateStoreData

Return New SessionStateStoreData(New SessionStateItemCollection(), _


SessionStateUtility.GetSessionStaticObjects(context), _
timeout)
End Function

'
' SessionStateProviderBase.ResetItemTimeout
'

Public Overrides Sub ResetItemTimeout(context As HttpContext, _


id As String)
Dim conn As OdbcConnection = New OdbcConnection(connectionString)
Dim cmd As OdbcCommand = _
New OdbcCommand("UPDATE Sessions SET Expires = ? " & _
"WHERE SessionId = ? AND ApplicationName = ?", conn)
cmd.Parameters.Add("@Expires", OdbcType.DateTime).Value = _
DateTime.Now.AddMinutes(pConfig.Timeout.Minutes)
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, _
255).Value = ApplicationName

Try
conn.Open()

cmd.ExecuteNonQuery()
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "ResetItemTimeout")
Throw New Exception(exceptionMessage)
Else
Throw e
End If
Finally
conn.Close()
End Try
End Sub
'
' SessionStateProviderBase.InitializeRequest
'

Public Overrides Sub InitializeRequest(context As HttpContext)

End Sub

'
' SessionStateProviderBase.EndRequest
'

Public Overrides Sub EndRequest(context As HttpContext)

End Sub

'
' WriteToEventLog
' This is a helper function that writes exception detail to the
' event log. Exceptions are written to the event log as a security
' measure to ensure Private database details are not returned to
' browser. If a method does not Return a status or Boolean
' indicating the action succeeded or failed, the caller also
' throws a generic exception.
'

Private Sub WriteToEventLog(e As Exception, action As String)


Dim log As EventLog = New EventLog()
log.Source = eventSource
log.Log = eventLog

Dim message As String = _


"An exception occurred communicating with the data source." & vbCrLf & vbCrLf
message &= "Action: " & action & vbCrLf & vbCrLf
message &= "Exception: " & e.ToString()

log.WriteEntry(message)
End Sub
End Class
End Namespace

C#
using System;
using System.Web;
using System.Web.Configuration;
using System.Configuration;
using System.Configuration.Provider;
using System.Collections.Specialized;
using System.Web.SessionState;
using System.Data;
using System.Data.Odbc;
using System.Diagnostics;
using System.IO;

/*
This session state store provider supports the following schema:

CREATE TABLE Sessions


(
SessionId Text(80) NOT NULL,
ApplicationName Text(255) NOT NULL,
Created DateTime NOT NULL,
Expires DateTime NOT NULL,
LockDate DateTime NOT NULL,
LockId Integer NOT NULL,
Timeout Integer NOT NULL,
Locked YesNo NOT NULL,
SessionItems Memo,
Flags Integer NOT NULL,
CONSTRAINT PKSessions PRIMARY KEY (SessionId, ApplicationName)
)

This session state store provider does not automatically clean up


expired session item data. It is recommended
that you periodically delete expired session information from the
data store with the following code (where 'conn' is the OdbcConnection
for the session state store provider):
string commandString = "DELETE FROM Sessions WHERE Expires < ?";
OdbcConnection conn = new OdbcConnection(connectionString);
OdbcCommand cmd = new OdbcCommand(commandString, conn);
cmd.Parameters.Add("@Expires", OdbcType.DateTime).Value = DateTime.Now;
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();

*/

namespace Samples.AspNet.Session
{

public sealed class OdbcSessionStateStore : SessionStateStoreProviderBase


{
private SessionStateSection pConfig = null;
private string connectionString;
private ConnectionStringSettings pConnectionStringSettings;
private string eventSource = "OdbcSessionStateStore";
private string eventLog = "Application";
private string exceptionMessage =
"An exception occurred. Please contact your administrator.";
private string pApplicationName;

//
// If false, exceptions are thrown to the caller. If true,
// exceptions are written to the event log.
//

private bool pWriteExceptionsToEventLog = false;

public bool WriteExceptionsToEventLog


{
get { return pWriteExceptionsToEventLog; }
set { pWriteExceptionsToEventLog = value; }
}

//
// The ApplicationName property is used to differentiate sessions
// in the data source by application.
//

public string ApplicationName


{
get { return pApplicationName; }
}

public override void Initialize(string name, NameValueCollection config)


{
//
// Initialize values from web.config.
//

if (config == null)
throw new ArgumentNullException("config");

if (name == null || name.Length == 0)


name = "OdbcSessionStateStore";

if (String.IsNullOrEmpty(config["description"]))
{
config.Remove("description");
config.Add("description", "Sample ODBC Session State Store provider");
}

// Initialize the abstract base class.


base.Initialize(name, config);

//
// Initialize the ApplicationName property.
//

pApplicationName =
System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath;

//
// Get <sessionState> configuration element.
//

Configuration cfg =
WebConfigurationManager.OpenWebConfiguration(ApplicationName);
pConfig =
(SessionStateSection)cfg.GetSection("system.web/sessionState");

//
// Initialize connection string.
//

pConnectionStringSettings =
ConfigurationManager.ConnectionStrings[config["connectionStringName"]];

if (pConnectionStringSettings == null ||
pConnectionStringSettings.ConnectionString.Trim() == "")
{
throw new ProviderException("Connection string cannot be blank.");
}

connectionString = pConnectionStringSettings.ConnectionString;

//
// Initialize WriteExceptionsToEventLog
//

pWriteExceptionsToEventLog = false;

if (config["writeExceptionsToEventLog"] != null)
{
if (config["writeExceptionsToEventLog"].ToUpper() == "TRUE")
pWriteExceptionsToEventLog = true;
}
}
//
// SessionStateStoreProviderBase members
//

public override void Dispose()


{
}

//
// SessionStateProviderBase.SetItemExpireCallback
//

public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallbac


k)
{
return false;
}

//
// SessionStateProviderBase.SetAndReleaseItemExclusive
//

public override void SetAndReleaseItemExclusive(HttpContext context,


string id,
SessionStateStoreData item,
object lockId,
bool newItem)
{
// Serialize the SessionStateItemCollection as a string.
string sessItems = Serialize((SessionStateItemCollection)item.Items);

OdbcConnection conn = new OdbcConnection(connectionString);


OdbcCommand cmd;
OdbcCommand deleteCmd = null;

if (newItem)
{
// OdbcCommand to clear an existing expired session if it exists.
deleteCmd = new OdbcCommand("DELETE FROM Sessions " +
"WHERE SessionId = ? AND ApplicationName = ? AND Expires < ?", conn);
deleteCmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id;
deleteCmd.Parameters.Add
("@ApplicationName", OdbcType.VarChar, 255).Value = ApplicationName;
deleteCmd.Parameters.Add
("@Expires", OdbcType.DateTime).Value = DateTime.Now;

// OdbcCommand to insert the new session item.


cmd = new OdbcCommand("INSERT INTO Sessions " +
" (SessionId, ApplicationName, Created, Expires, " +
" LockDate, LockId, Timeout, Locked, SessionItems, Flags) " +
" Values(?, ?, ?, ?, ?, ? , ?, ?, ?, ?)", conn);
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id;
cmd.Parameters.Add
("@ApplicationName", OdbcType.VarChar, 255).Value = ApplicationName;
cmd.Parameters.Add
("@Created", OdbcType.DateTime).Value = DateTime.Now;
cmd.Parameters.Add
("@Expires", OdbcType.DateTime).Value = DateTime.Now.AddMinutes((Double)item.Time
out);
cmd.Parameters.Add
("@LockDate", OdbcType.DateTime).Value = DateTime.Now;
cmd.Parameters.Add("@LockId", OdbcType.Int).Value = 0;
cmd.Parameters.Add
("@Timeout", OdbcType.Int).Value = item.Timeout;
cmd.Parameters.Add("@Locked", OdbcType.Bit).Value = false;
cmd.Parameters.Add
("@SessionItems", OdbcType.VarChar, sessItems.Length).Value = sessItems;
cmd.Parameters.Add("@Flags", OdbcType.Int).Value = 0;
}
else
{
// OdbcCommand to update the existing session item.
cmd = new OdbcCommand(
"UPDATE Sessions SET Expires = ?, SessionItems = ?, Locked = ? " +
" WHERE SessionId = ? AND ApplicationName = ? AND LockId = ?", conn);
cmd.Parameters.Add("@Expires", OdbcType.DateTime).Value =
DateTime.Now.AddMinutes((Double)item.Timeout);
cmd.Parameters.Add("@SessionItems",
OdbcType.VarChar, sessItems.Length).Value = sessItems;
cmd.Parameters.Add("@Locked", OdbcType.Bit).Value = false;
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar,
255).Value = ApplicationName;
cmd.Parameters.Add("@LockId", OdbcType.Int).Value = lockId;
}

try
{
conn.Open();

if (deleteCmd != null)
deleteCmd.ExecuteNonQuery();

cmd.ExecuteNonQuery();
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "SetAndReleaseItemExclusive");
throw new ProviderException(exceptionMessage);
}
else
throw e;
}
finally
{
conn.Close();
}
}

//
// SessionStateProviderBase.GetItem
//
public override SessionStateStoreData GetItem(HttpContext context,
string id,
out bool locked,
out TimeSpan lockAge,
out object lockId,
out SessionStateActions actionFlags)
{
return GetSessionStoreItem(false, context, id, out locked,
out lockAge, out lockId, out actionFlags);
}

//
// SessionStateProviderBase.GetItemExclusive
//

public override SessionStateStoreData GetItemExclusive(HttpContext context,


string id,
out bool locked,
out TimeSpan lockAge,
out object lockId,
out SessionStateActions actionFlags)
{
return GetSessionStoreItem(true, context, id, out locked,
out lockAge, out lockId, out actionFlags);
}

//
// GetSessionStoreItem is called by both the GetItem and
// GetItemExclusive methods. GetSessionStoreItem retrieves the
// session data from the data source. If the lockRecord parameter
// is true (in the case of GetItemExclusive), then GetSessionStoreItem
// locks the record and sets a new LockId and LockDate.
//

private SessionStateStoreData GetSessionStoreItem(bool lockRecord,


HttpContext context,
string id,
out bool locked,
out TimeSpan lockAge,
out object lockId,
out SessionStateActions actionFlags)
{
// Initial values for return value and out parameters.
SessionStateStoreData item = null;
lockAge = TimeSpan.Zero;
lockId = null;
locked = false;
actionFlags = 0;

// ODBC database connection.


OdbcConnection conn = new OdbcConnection(connectionString);
// OdbcCommand for database commands.
OdbcCommand cmd = null;
// DataReader to read database record.
OdbcDataReader reader = null;
// DateTime to check if current session item is expired.
DateTime expires;
// String to hold serialized SessionStateItemCollection.
string serializedItems = "";
// True if a record is found in the database.
bool foundRecord = false;
// True if the returned session item is expired and needs to be deleted.
bool deleteData = false;
// Timeout value from the data store.
int timeout = 0;

try
{
conn.Open();

// lockRecord is true when called from GetItemExclusive and


// false when called from GetItem.
// Obtain a lock if possible. Ignore the record if it is expired.
if (lockRecord)
{
cmd = new OdbcCommand(
"UPDATE Sessions SET" +
" Locked = ?, LockDate = ? " +
" WHERE SessionId = ? AND ApplicationName = ? AND Locked = ? AND Expires > ?",
conn);
cmd.Parameters.Add("@Locked", OdbcType.Bit).Value = true;
cmd.Parameters.Add("@LockDate", OdbcType.DateTime).Value
= DateTime.Now;
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar,
255).Value = ApplicationName;
cmd.Parameters.Add("@Locked", OdbcType.Int).Value = false;
cmd.Parameters.Add
("@Expires", OdbcType.DateTime).Value = DateTime.Now;

if (cmd.ExecuteNonQuery() == 0)
// No record was updated because the record was locked or not found.
locked = true;
else
// The record was updated.

locked = false;
}

// Retrieve the current session item information.


cmd = new OdbcCommand(
"SELECT Expires, SessionItems, LockId, LockDate, Flags, Timeout " +
" FROM Sessions " +
" WHERE SessionId = ? AND ApplicationName = ?", conn);
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar,
255).Value = ApplicationName;

// Retrieve session item data from the data source.


reader = cmd.ExecuteReader(CommandBehavior.SingleRow);
while (reader.Read())
{
expires = reader.GetDateTime(0);
if (expires < DateTime.Now)
{
// The record was expired. Mark it as not locked.
locked = false;
// The session was expired. Mark the data for deletion.
deleteData = true;
}
else
foundRecord = true;

serializedItems = reader.GetString(1);
lockId = reader.GetInt32(2);
lockAge = DateTime.Now.Subtract(reader.GetDateTime(3));
actionFlags = (SessionStateActions)reader.GetInt32(4);
timeout = reader.GetInt32(5);
}
reader.Close();

// If the returned session item is expired,


// delete the record from the data source.
if (deleteData)
{
cmd = new OdbcCommand("DELETE FROM Sessions " +
"WHERE SessionId = ? AND ApplicationName = ?", conn);
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar,
255).Value = ApplicationName;

cmd.ExecuteNonQuery();
}

// The record was not found. Ensure that locked is false.


if (!foundRecord)
locked = false;

// If the record was found and you obtained a lock, then set
// the lockId, clear the actionFlags,
// and create the SessionStateStoreItem to return.
if (foundRecord && !locked)
{
lockId = (int)lockId + 1;

cmd = new OdbcCommand("UPDATE Sessions SET" +


" LockId = ?, Flags = 0 " +
" WHERE SessionId = ? AND ApplicationName = ?", conn);
cmd.Parameters.Add("@LockId", OdbcType.Int).Value = lockId;
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = Application
Name;

cmd.ExecuteNonQuery();

// If the actionFlags parameter is not InitializeItem,


// deserialize the stored SessionStateItemCollection.
if (actionFlags == SessionStateActions.InitializeItem)
item = CreateNewStoreData(context, pConfig.Timeout.Minutes);
else
item = Deserialize(context, serializedItems, timeout);
}
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "GetSessionStoreItem");
throw new ProviderException(exceptionMessage);
}
else
throw e;
}
finally
{
if (reader != null) { reader.Close(); }
conn.Close();
}

return item;
}

//
// Serialize is called by the SetAndReleaseItemExclusive method to
// convert the SessionStateItemCollection into a Base64 string to
// be stored in an Access Memo field.
//
private string Serialize(SessionStateItemCollection items)
{
MemoryStream ms = new MemoryStream();
BinaryWriter writer = new BinaryWriter(ms);

if (items != null)
items.Serialize(writer);

writer.Close();

return Convert.ToBase64String(ms.ToArray());
}

//
// DeSerialize is called by the GetSessionStoreItem method to
// convert the Base64 string stored in the Access Memo field to a
// SessionStateItemCollection.
//

private SessionStateStoreData Deserialize(HttpContext context,


string serializedItems, int timeout)
{
MemoryStream ms =
new MemoryStream(Convert.FromBase64String(serializedItems));
SessionStateItemCollection sessionItems =
new SessionStateItemCollection();

if (ms.Length > 0)
{
BinaryReader reader = new BinaryReader(ms);
sessionItems = SessionStateItemCollection.Deserialize(reader);
}

return new SessionStateStoreData(sessionItems,


SessionStateUtility.GetSessionStaticObjects(context),
timeout);
}

//
// SessionStateProviderBase.ReleaseItemExclusive
//

public override void ReleaseItemExclusive(HttpContext context,


string id,
object lockId)
{
OdbcConnection conn = new OdbcConnection(connectionString);
OdbcCommand cmd =
new OdbcCommand("UPDATE Sessions SET Locked = 0, Expires = ? " +
"WHERE SessionId = ? AND ApplicationName = ? AND LockId = ?", conn);
cmd.Parameters.Add("@Expires", OdbcType.DateTime).Value =
DateTime.Now.AddMinutes(pConfig.Timeout.Minutes);
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar,
255).Value = ApplicationName;
cmd.Parameters.Add("@LockId", OdbcType.Int).Value = lockId;
try
{
conn.Open();

cmd.ExecuteNonQuery();
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "ReleaseItemExclusive");
throw new ProviderException(exceptionMessage);
}
else
throw e;
}
finally
{
conn.Close();
}
}

//
// SessionStateProviderBase.RemoveItem
//
public override void RemoveItem(HttpContext context,
string id,
object lockId,
SessionStateStoreData item)
{
OdbcConnection conn = new OdbcConnection(connectionString);
OdbcCommand cmd = new OdbcCommand("DELETE * FROM Sessions " +
"WHERE SessionId = ? AND ApplicationName = ? AND LockId = ?", conn);
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar,
255).Value = ApplicationName;
cmd.Parameters.Add("@LockId", OdbcType.Int).Value = lockId;

try
{
conn.Open();

cmd.ExecuteNonQuery();
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "RemoveItem");
throw new ProviderException(exceptionMessage);
}
else
throw e;
}
finally
{
conn.Close();
}
}

//
// SessionStateProviderBase.CreateUninitializedItem
//

public override void CreateUninitializedItem(HttpContext context,


string id,
int timeout)
{
OdbcConnection conn = new OdbcConnection(connectionString);
OdbcCommand cmd = new OdbcCommand("INSERT INTO Sessions " +
" (SessionId, ApplicationName, Created, Expires, " +
" LockDate, LockId, Timeout, Locked, SessionItems, Flags) " +
" Values(?, ?, ?, ?, ?, ? , ?, ?, ?, ?)", conn);
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar,
255).Value = ApplicationName;
cmd.Parameters.Add("@Created", OdbcType.DateTime).Value
= DateTime.Now;
cmd.Parameters.Add("@Expires", OdbcType.DateTime).Value
= DateTime.Now.AddMinutes((Double)timeout);
cmd.Parameters.Add("@LockDate", OdbcType.DateTime).Value
= DateTime.Now;
cmd.Parameters.Add("@LockId", OdbcType.Int).Value = 0;
cmd.Parameters.Add("@Timeout", OdbcType.Int).Value = timeout;
cmd.Parameters.Add("@Locked", OdbcType.Bit).Value = false;
cmd.Parameters.Add("@SessionItems", OdbcType.VarChar, 0).Value = "";
cmd.Parameters.Add("@Flags", OdbcType.Int).Value = 1;

try
{
conn.Open();

cmd.ExecuteNonQuery();
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "CreateUninitializedItem");
throw new ProviderException(exceptionMessage);
}
else
throw e;
}
finally
{
conn.Close();
}
}

//
// SessionStateProviderBase.CreateNewStoreData
//

public override SessionStateStoreData CreateNewStoreData(


HttpContext context,
int timeout)
{
return new SessionStateStoreData(new SessionStateItemCollection(),
SessionStateUtility.GetSessionStaticObjects(context),
timeout);
}

//
// SessionStateProviderBase.ResetItemTimeout
//

public override void ResetItemTimeout(HttpContext context,


string id)
{
OdbcConnection conn = new OdbcConnection(connectionString);
OdbcCommand cmd =
new OdbcCommand("UPDATE Sessions SET Expires = ? " +
"WHERE SessionId = ? AND ApplicationName = ?", conn);
cmd.Parameters.Add("@Expires", OdbcType.DateTime).Value
= DateTime.Now.AddMinutes(pConfig.Timeout.Minutes);
cmd.Parameters.Add("@SessionId", OdbcType.VarChar, 80).Value = id;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar,
255).Value = ApplicationName;

try
{
conn.Open();

cmd.ExecuteNonQuery();
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "ResetItemTimeout");
throw new ProviderException(exceptionMessage);
}
else
throw e;
}
finally
{
conn.Close();
}
}

//
// SessionStateProviderBase.InitializeRequest
//

public override void InitializeRequest(HttpContext context)


{
}

//
// SessionStateProviderBase.EndRequest
//
public override void EndRequest(HttpContext context)
{
}

//
// WriteToEventLog
// This is a helper function that writes exception detail to the
// event log. Exceptions are written to the event log as a security
// measure to ensure private database details are not returned to
// browser. If a method does not return a status or Boolean
// indicating the action succeeded or failed, the caller also
// throws a generic exception.
//

private void WriteToEventLog(Exception e, string action)


{
EventLog log = new EventLog();
log.Source = eventSource;
log.Log = eventLog;
string message =
"An exception occurred communicating with the data source.\n\n";
message += "Action: " + action + "\n\n";
message += "Exception: " + e.ToString();

log.WriteEntry(message);
}
}
}

See Also
Concepts
Sample Session-State Store Provider
Implementing a Session-State Store Provider
Other Resources
ASP.NET Session State
ASP.NET State Management
ASP.NET

ASP.NET Application State


Application state is a data repository available to all classes in an ASP.NET application. Application state is stored in memory on
the server and is faster than storing and retrieving information in a database. Unlike session state, which is specific to a single
user session, application state applies to all users and all sessions. Therefore, application state is a useful place to store small
amounts of often-used data that does not change from one user to another. The topics in this section provide information on
how application state works and how to use it.
In This Section
ASP.NET Application State Overview
How to: Save Values in Application State
How to: Read Values from Application State
Related Sections
ASP.NET State Management
Describes ways to store state information between page requests.
ASP.NET

ASP.NET Application State Overview


Application state is a data repository available to all classes in an ASP.NET application. Application state is stored in memory on
the server and is faster than storing and retrieving information in a database. Unlike session state, which is specific to a single
user session, application state applies to all users and sessions. Therefore, application state is a useful place to store small
amounts of often-used data that does not change from one user to another. For information on saving data on a per-user basis
see Session State Overview and ASP.NET Profile Properties Overview.
Using Application State
Application state is stored in an instance of the HttpApplicationState class. This class exposes a key-value dictionary of objects.
The HttpApplicationState instance is created the first time a user accesses any URL resource in an application. The
HttpApplicationState class is most often accessed through the Application property of the HttpContext class.
You can use application state in two ways. You can add, access, or remove values from the Contents collection directly through
code. The HttpApplicationState class can be accessed at any time during the life of an application. However, it is often useful
to load application state data when the application starts. To do so, you can put code to load application state into the
Application_Start method in the Global.asax file. For more information see ASP.NET Application Life Cycle Overview.
Alternatively, you can add objects to the StaticObjects collection via an <object runat="server"> declaration in your Web
application's Global.asax file. Application state defined in this way can then be accessed from code anywhere in your
application. The following example shows an object declaration for an application state value:

<object runat="server" scope="application" ID="MyInfo"


PROGID="MSWC.MYINFO">
</object>

You can add objects to the StaticObjects collection only in the Global.asax file. The collection throws a NotSupportedException
if you attempt to add objects directly through code.
You can access members of objects stored in application state without having to reference the Application collection. The
following code example shows how to reference a member of an object defined in the StaticObjects collection of application
state:
VB
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
Label1.Text = MyInfo.Title
End Sub

C#
protected void Page_Load(Object sender, EventArgs e)
Label1.Text = MyInfo.Title;
End Sub

Application State Considerations


When using application state, you must be aware of the following important considerations:
Resources Because it is stored in memory, application state is very fast compared to saving data to disk or a database.
However, storing large blocks of data in application state can fill up server memory, causing the server to page memory
to disk. As an alternative to using application state, you can use the ASP.NET cache mechanism for storing large amounts
of application data. The ASP.NET cache also stores data in memory and is therefore very fast; however, ASP.NET actively
manages the cache and will remove items when memory becomes scarce. For more information see
ASP.NET Caching Overview.
Volatility Because application state is stored in server memory, it is lost whenever the application is stopped or
restarted. For example, if the Web.config file is changed, the application is restarted and all application state is lost unless
application state values have been written to a non-volatile storage medium such as a database.
Scalability Application state is not shared among multiple servers serving the same application, as in a Web farm, or
among multiple worker processes serving the same application on the same server, as in a Web garden. Your application
therefore cannot rely on application state containing the same data for application state across different servers or
processes. If your application will run in multi-processor or multi-server environments, consider using a more scalable
option, such as a database, for data that must preserve fidelity across the application.
Concurrency Application state is free-threaded, which means that application state data can be accessed
simultaneously by many threads. Therefore, it is important to ensure that when you update application state data, you do
so in a thread-safe manner by including built-in synchronization support. You can use the Lock and UnLock methods to
ensure data integrity by locking the data for writing by only one source at a time. You can also reduce the likelihood of
concurrency problems by initializing application state values in the Application_Start method in the Global.asax file. For
more information see ASP.NET Application Life Cycle Overview.
See Also
Tasks
How to: Save Values in Application State
How to: Read Values from Application State
Concepts
ASP.NET State Management Overview
What's New in ASP.NET State Management
ASP.NET

How to: Save Values in Application State


Application state is a data repository that is available to all classes in an ASP.NET application. Application state is stored in
memory on the server and is faster than storing and retrieving information in a database. Unlike session state, which is specific
to a single user session, application state applies to all users and sessions. Therefore, application state is a useful place to store
small amounts of often-used data that does not change from one user to another.
Application state is stored in the HttpApplicationState class, a new instance of which is created the first time a user accesses
any URL resource in an application. The HttpApplicationState class is exposed through the Application property.
Application state stores data as Object data types. Therefore, you must convert the data back to the appropriate type when
retrieving it.
Application state is stored in memory on the server, so a large amount of data in application state can fill up server memory
quickly. If the application is restarted, application state data is lost. Application state is not shared between multiple servers
within a Web farm or between worker processes in a Web garden. Finally, application state is free-threaded, so any data that is
stored in application state must have built-in synchronization support. For more information about these considerations, see
ASP.NET Application State and ASP.NET State Management Recommendations.
To write a value to application state
In your application, set the value of the variable in the HttpApplicationState class.
The following code example shows how you can set the application variable Message to a string.
VB
Application("Message") = "Welcome to the Contoso site."

C#
Application["Message"] = "Welcome to the Contoso site.";

To write a value to application state when the application starts


In Application_Start handler of your application's Global.asax file, set the value of the application state variable. Just as
in a regular .aspx page, the HttpApplicationState class is exposed through the Application object.
The following code example shows how you can set the application variable Message to a string and initialize the variable
PageRequestCount to 0.

VB
Application("Message") = "Welcome to the Contoso site."
Application("PageRequestCount") = 0

C#
Application["Message"] = "Welcome to the Contoso site.";
Application["PageRequestCount"] = 0;

Writing a Value to Application State with Locking


Application state variables can be accessed by multiple threads at the same time. Therefore, to prevent invalid data, you must
lock application state for writing by only one thread before setting values.
Note
You should always modify application state data within a lock statement unless you have set some other type of lock. For mo
re information, see Synchronizing Data for Multithreading.
To write a value to application state with locking
In the code where you set the application variable, call the System.Web.HttpApplicationState.Lock method, set the
application state value, and then call the System.Web.HttpApplicationState.UnLock method to unlock the application
state, freeing it for other write requests.
The following code example shows how you can lock and unlock application state. The code increases the
PageRequestCount variable by 1 and then unlocks application state.

VB
Application.Lock()
Application("PageRequestCount") = _
CInt(Application("PageRequestCount")) + 1
Application.UnLock()

C#
Application.Lock();
Application["PageRequestCount"] =
((int)Application["PageRequestCount"])+1;
Application.UnLock();

See Also
Tasks
How to: Read Values from Application State
Concepts
ASP.NET State Management Overview
ASP.NET State Management Recommendations
Other Resources
ASP.NET Application State
ASP.NET

How to: Read Values from Application State


Application state is a data repository that is available to all classes within an ASP.NET application. Application state is stored in
memory on the server and is faster than storing and retrieving data in a database. Unlike session state, which is specific to a
single user session, application state applies to all users and sessions. Therefore, application state is a useful place to store
small amounts of often-used data that does not change from one user to another.
Application state is stored in the HttpApplicationState class, a new instance of which is created the first time a user accesses a
URL resource within an application. For more information, see ASP.NET Application State Overview.
Application state stores data typed as Object. Therefore, even though you do not have to serialize the data when storing it in
application state, you must cast the data to the appropriate type when retrieving it. Although you can cast a null (Nothing in
Visual Basic) object, if you attempt to use a non-existent application-state entry in some other way (for example, to examine its
type), a NullReferenceException exception is thrown.
Procedure
To read a value from application state
Determine whether the application variable exists, and then convert the variable to the appropriate type when you access
it.
The following code example retrieves the application state AppStartTime value and converts it to a variable named
appStateTime of type DateTime.

VB
If (Not Application("AppStartTime") Is Nothing) Then
Dim myAppStartTime As DateTime = _
CDate(Application("AppStartTime"))
End If

C#
if (Application["AppStartTime"] != null)
{
DateTime myAppStartTime = (DateTime)Application["AppStartTime"];
}

See Also
Tasks
How to: Save Values in Application State
Concepts
ASP.NET State Management Overview
ASP.NET State Management Recommendations
Other Resources
ASP.NET Application State
Visual Web Developer

ASP.NET Caching (Visual Studio)


ASP.NET caching allows you to store pages, parts of pages, or your own data in server memory for faster response time. The
topics in this section provide information on how to configure your pages and Web site to use caching and how to work with
caching programmatically.
In This Section
Getting Started - Enhancing Web Site Performance with Caching
Learning More - Caching
Walkthrough Topics — ASP.NET Caching (Visual Studio)
How-to Topics — ASP.NET Caching (Visual Studio)
See Also
Other Resources
ASP.NET Web Sites (Visual Studio)
ASP.NET Web Pages (Visual Studio)
Visual Web Developer

Getting Started - Enhancing Web Site Performance with


Caching
The topics in this section provide essential information on using ASP.NET caching.
In This Section
ASP.NET Caching Overview
What's New in ASP.NET Caching
Walkthrough: Using Output Caching to Enhance Web Site Performance
Walkthrough: Using ASP.NET Output Caching with SQL Server
Caching ASP.NET Pages
Caching Application Data
Cache Configuration in ASP.NET
See Also
Other Resources
ASP.NET Caching (Visual Studio)
ASP.NET Web Sites (Visual Studio)
ASP.NET Web Pages (Visual Studio)
ASP.NET

ASP.NET Caching Overview


Often an application can increase performance by storing in memory data that is accessed frequently and that requires
significant processing time to create. For example, if your application processes large amounts of data using complex logic and
then returns the data as a report accessed frequently by users, it is efficient to avoid recreating the report every time a user
requests it. Similarly, if your application includes a page that processes complex data but that is updated only infrequently, it is
inefficient for the server to recreate that page on every request.
To help you increase application performance in these situations, ASP.NET provides caching using two basic caching
mechanisms. The first is application caching, which allows you to cache data you generate, such as a DataSet or a custom
report business object. The second is page output caching, which saves the output of page processing and reuses the output
instead of re-processing the page when a user requests the page again.
Application Cache
The application cache provides a programmatic way for you to store arbitrary data in memory using key/value pairs. Using the
application cache is similar to using application state. However, unlike application state, the data in the application cache is
volatile, meaning it is not stored in memory for the life of the application. The advantage of using the application cache is that
ASP.NET manages the cache and removes items when they expire or become invalidated, or when memory runs low. You can
also configure application caching to notify your application when an item is removed. For more information see
Caching Application Data.
The pattern when using the application cache is to determine whether an item exists in the cache any time you access an item,
and if it does, to use it. If the item does not exist, you can recreate the item and then place it back in the cache. This pattern
ensures that you always have the latest data in the cache.
For more information see How to: Retrieve Values of Cached Items.
Page Output Cache
The page output cache stores the contents of a processed ASP.NET page in memory. This allows ASP.NET to send a page
response to a client without going through the page processing lifecycle again. Page output caching is especially useful for
pages that do not change often but require significant processing to create. For example, if you are creating a high-traffic Web
page to display data that is not frequently updated, page output caching can dramatically increase the performance of that
page. Page caching can be configured individually for each page, or you can create cache profiles in the Web.config file, which
allow you to define caching settings once and then use those settings with multiple pages.
Page output caching provides two models for page caching: full page caching and partial page caching. Full page caching
allows the entire contents of a page to be persisted to memory and used to fulfill client requests. Partial page caching allows
parts of a page to be cached and other parts to be dynamic. For more information see Caching ASP.NET Pages.
Partial page caching can work in two ways: control caching and post-cache substitution. Control caching, also sometimes
referred to as fragment caching, allows you to cache parts of the page output by including the information in a user control
and then marking the user control as cacheable. This allows specific content within a page to be cached, while the overall page
is not cached and therefore recreated each time. For example, if you create a page that displays largely dynamic content, such
as stock information, but has sections that are static, such as weekly summaries, you can place the static sections in user
controls and allow them to be cached.
Post-cache substitution is the opposite. The page as a whole is cached, but fragments within the page are dynamic. For
example, if you create a page that is static for set periods of time, you can set the entire page to be cached. If you added a Label
control to the page that displayed the user's name, the Label would stay the same for each page refresh and each user,
showing the name of the user who requested that page before it was cached. However, with post-cache substitution, you can
configure the page to be cached, but mark individual sections of the page as not cacheable. In this case, you could add your
Label controls to a non-cacheable section and they would be dynamically created for each user and page request. For more
information, see Caching Portions of an ASP.NET Page.
Caching Pages Based on Request Parameters
In addition to caching a single version of a page, ASP.NET page output caching provides features to create multiple versions of
the page that vary by different request parameters. For more information, see Caching Multiple Versions of a Page.
Automatic Data Removal
ASP.NET can remove data from the cache for one of these reasons:
Because memory on the server is low, a process known as scavenging.
Because the item in the cache has expired.
Because the item's dependency changes.
To help you manage cached items, ASP.NET can notify your application when items are removed from the cache.
Scavenging
Scavenging is the process of deleting items from the cache when memory is scarce. Items are removed when they have not
been accessed in some time or when items are marked as low priority when added to the cache. ASP.NET uses the
CacheItemPriority object to determine which items to scavenge first. For more information see How to: Add Items to the Cache.
Expiration
In addition to scavenging, ASP.NET automatically removes items from the cache when they expire. When adding an item to the
cache, you can set it to expire as described in the following table.
Expiration T Description
ype
Sliding expira Specifies how long after an item was last accessed that it expires. For example, you can set an item to expire 20
tion minutes after it was last accessed in the cache.

Absolute expi Specifies that an item expires at a set time, regardless of how often it is accessed. For example, you can set an ite
ration m to expire at 6:00 PM or after four hours.
Dependencies
You can configure an item's lifetime in the cache be dependent on other application elements such as files or databases. When
the element that a cache item depends on changes, ASP.NET removes the item from the cache. For example, if your Web site
displays a report that the application creates from an XML file, you can place the report in the cache and configure it to have a
dependency on the XML file. When the XML file changes, ASP.NET removes the report from the cache. When your code
requests the report, the code first determines whether the report is in the cache, and if not, your code can recreate it. Therefore,
an up-to-date version of the report is always available.
ASP.NET caching supports the dependencies described in the following table.
Dep Description
end
ency
Key Items in the application cache are stored in key/value pairs. Key dependency allows an item to be dependent on the key
depe of another item in the application cache. When the original item is removed, the item that has the key dependency is also
nden removed. For example, you could add a cache item named ReportsValid, and then cache several reports that are depend
cy ent on the ReportsValid key. When the ReportsValid item is removed, all the dependent cached reports are likewise re
moved from the cache.

File An item in the cache is dependent on an external file. If the file is modified or deleted, the cached item is removed.
depe
nden
cy

SQL An item in the cache is dependent on changes in a table in a Microsoft SQL Server 2005, SQL Server 2000, or SQL Server
depe 7.0 database. For SQL Server 2005, an item can be dependent on a row in a table. For more information, see
nden Caching in ASP.NET with the SqlCacheDependency Class.
cy

Aggr An item in the cache is dependent on multiple elements through the use of the AggregateCacheDependency class. If any
egat of the dependencies change, the item is removed from the cache.
e de
pend
ency
Cust An item in the cache is configured with a dependency that you create in your own code. For example, you can create a cu
om d stom Web service cache dependency that removes data from the cache when a call to a Web service results in a particula
epen r value.
denc
y

Application Cache Item Removal Notification


You can be notified when an item is removed from the application cache. For example, if you have an item that takes
considerable amount of processing time to create, you can be notified when it is removed from the cache so that you can
replace it immediately. As a result, the next time the item is requested, the user does not have to wait for it to be processed. For
more information, see How to: Notify an Application When an Item Is Removed from the Cache.
See Also
Tasks
How to: Cache Page Output with File Dependencies
Concepts
What's New in ASP.NET Caching
Caching ASP.NET Pages
Caching Application Data
Caching in ASP.NET with the SqlCacheDependency Class
ASP.NET

What's New in ASP.NET Caching


ASP.NET version 2.0 retains all of the caching functionality of ASP.NET version 1.1, but adds new features and enhances
existing features. New features include cache profiles, custom cache dependencies, a SQL cache dependency, and creating
dynamic content in cached pages (post-cache substitution). Feature enhancements include a more powerful partial-page
(control) caching model, enhanced cache configuration, and improvements to the output cache directive.
New Cache Features
Cache Profiles
Cache profiles allow you to create cache settings in an application's Web.config file and then reference those settings on
individual pages. This allows you to apply cache settings to many pages at once. For example, you can define a cache profile
named DailyUpdate that sets a page's cache duration to one day. You can then configure individual pages to use the
DailyUpdate cache profile, and the cache duration of those pages will be one day. If you change the DailyUpdate cache profile
to not use caching, the pages will stop being cached. For more information see Cache Configuration in ASP.NET.
Custom Cache Dependencies
In ASP.NET 2.0 you can create your own custom cache dependency based on application-specific conditions. To create a
custom cache dependency, you create a class that inherits from CacheDependency and in your custom class implement your
own dependency methods. For example, you can create a dependency that polls a Web service for data; when the data
changes, you can invalidate your cache data. To learn about adding items to the cache by specifying a dependency, see
How to: Add Items to the Cache.
SqlCacheDependency
ASP.NET 2.0 introduces the SqlCacheDependency class, which allows you to configure an item in the cache to have a
dependency on a table or row in a Microsoft SQL Server database. When a change occurs in the table or in a specific row, the
cached item that has a dependency is invalidated and therefore removed from the cache. ASP.NET 2.0 allows you to set a
dependency on a table in SQL Server 7.0, SQL Server 2000, and SQL Server 2005. When using SQL Server 2005, you can also
set a dependency on a specific record. For more information, see Caching in ASP.NET with the SqlCacheDependency Class.
Post-Cache Substitution
ASP.NET 2.0 now supports post-cache substitution, which allows you to configure a section in a page as non-cacheable.
Therefore, although the page is cached, parts of it will be re-processed when the page is requested again. For example, you can
create a cached page with mostly static content but that displays the user's name in a Label control. Without post-cache
substitution, the user name would remain the same for all requests. With post-cache substitution, you can mark the page as
cacheable and put the Label control inside another control marked as not cacheable. The user name will then refresh each time
the page is requested. For more information see Caching Portions of an ASP.NET Page.
Caching Enhancements
Control Caching
In ASP.NET 1.1, you configure user control caching declaratively by setting parameters in the @ Control directive. In ASP.NET
2.0, you can configure user control cache settings at run time with the CachePolicy object. The CachePolicy object allows you
to work with user control caching the same way that you can work programmatically with page output caching. For more
information, see Caching Portions of an ASP.NET Page.
Cache Configuration Enhancements
In addition to cache profiles, ASP.NET 2.0 introduces new cache configuration settings that you can specify in an application's
Web.config file. These settings allow more control over the cache, such as how much memory is used and cache scavenging
behavior. For more information see Cache Configuration in ASP.NET.
Output Cache Directive Improvements
ASP.NET 2.0 includes new @ OutputCache directive options and includes enhancements to existing ones. The new features and
enhancements enable declarative control over output cache features that were previously available only programmatically
using the HttpCachePolicy class. For example, you can now declaratively set the Duration attribute and the NoStore attribute in
the page @ OutputCache directive. For more information, see Setting the Cacheability of a Page.
See Also
Tasks
How to: Add Items to the Cache
Concepts
ASP.NET Caching Overview
Caching ASP.NET Pages
Caching Application Data
Caching in ASP.NET with the SqlCacheDependency Class
Visual Web Developer

Walkthrough: Using Output Caching to Enhance Web Site


Performance
Performance is a critical aspect of any Web application. Decreasing the amount of processing a Web server must do to comply
with individual requests results in quicker response times, the server's ability to handle more concurrent requests, and a
reduced load on intermediate and back-end data systems.
One way to achieve better performance with ASP.NET is by using output caching to reduce server workload. Output caching is
an optimization that reduces Web server response time.
Normally, when a browser requests an ASP.NET page, ASP.NET creates an instance of the page, runs any code in the page, runs
database queries (if any), dynamically assembles the page, and then sends the resulting output to the browser. Output caching
allows ASP.NET to send a pre-processed copy of a page rather than go through this process for each request. This difference
cuts down the amount of processing the Web server does, which increases performance and enables greater scalability.
Tasks illustrated in this walkthrough include:
Caching pages, using either a page directive to have the entire page output cached, regardless of browser type, individual
parameters, or data.
Using application-level cache profiles, a feature that enables you to define output caching settings for an entire
application. Individual pages can associate themselves with profiles contained in your Web.config file. This enables you to
control caching centrally instead of editing each page.
Caching based on individual parameters sent with the page.
Prerequisites
In order to complete this walkthrough, you will need:
Visual Web Developer (Visual Studio).
Microsoft .NET Framework version 2.0.
Creating the Web Site
If you have already created a Web site in Visual Web Developer (see
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and go to the next topic in this
walkthrough. Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site. (In Visual Web Developer Express Edition, on the File menu, click New, and then
click Web Site.)
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, select ASP.NET Web Site.
4. In the Location box, type the name of the folder where you want to keep the pages of your Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, select the programming language that you prefer to work in.
6. Click OK.
7. Visual Web Developer creates the folder and a new page named Default.aspx.
Configuring Page-Level Caching
This procedure introduces you to basic page caching. In this procedure, you will add a Label control to your page that displays
the time when the page was created, and then configure the page to be cached. By displaying the page's creation time you can
see that the page request is fulfilled from the cache.
To configure page-level caching
1. Open or switch to the Default.aspx page. (Alternatively, you can use any other page in your Web site.)
2. Switch to Design view.
3. From the Standard group in the toolbox, drag a Label control to your page, leaving the default name of Label1.
4. Double-click a blank are of the page.
The designer switches to the code editor and creates a Page_Load method.
5. Add the following highlighted code to the method:
VB
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs)
Label1.Text = System.DateTime.Now.ToString()
End Sub

C#
protected void Page_Load(Object sender, System.EventArgs e)
{
Label1.Text = System.DateTime.Now.ToString();
}

6. Press CTRL+F5 to run the page.


When the page appears in the browser, you will see the current date and time. Press your browser's refresh button and
notice that the timestamp changes each time.
7. Close the browser.
8. Add the following @ OutputCache directive to the top of the page:

<%@ OutputCache Duration="15" VaryByParam="none" %>

This directive configures the page to be cached. The Duration attribute specifies that the page will remain in the cache
for 15 seconds.
9. Press CTRL+F5 to run the page again.
10. Refresh the page several times.
Notice that the time display is updated only every 15 seconds, regardless of how many times you refresh the browser.
This is because the request is fulfilled from the cache until the duration time has elapsed, at which point the page code is
executed again.
Setting Application-Level Caching
In the preceding procedure, you configured caching for an individual page. In some circumstances you might want to configure
caching for all pages in your Web site. You might also want to establish different caching rules (profiles) and apply the cache
profiles to sets of individual pages. Setting application-level caching enables you to change cache behavior from a single
configuration file rather than editing the @ OutputCache directive of individual pages. In the following procedure, you will set
up a simple cache profile and use it for the page that you were just working with.
To configure application-level caching
1. If you already have a Web.config file, go to step 4.
2. In Solution Explorer, right-click the name of your Web site, and then click Add New Item.
3. In the Add Item dialog box, click Web Configuration File, and then click Add.
Be sure that you use the name Web.config.
4. Add the following XML as a child of the system.web element:

<!-- caching section group -->


<caching>
<outputCacheSettings>
<outputCacheProfiles>
<add name="AppCache1" enabled="true" duration="60"/>
</outputCacheProfiles>
</outputCacheSettings>
</caching>

5. Save the file and then close it.


6. Open or switch to the Web page you were working with, and then switch to Source view.
7. Change the @ OutputCache directive to read as follows:

<%@ OutputCache CacheProfile="AppCache1" VaryByParam="none" %>

8. Press CTRL+F5 to run the page.


9. Refresh the page a number of times.
This time the date will remain the same for the duration specified in the cache profile, which is 60 seconds.
Caching Using Parameters
The @ OutputCache directive requires you to set the VaryByParam attribute, which until you now you have set to "none".
The VaryByParam attribute enables you to configure caching so that ASP.NET stores different versions of a page depending
on parameters such as query strings, form post values, request headers, and so on.
For example, you can use cache parameters in a page that displays weather conditions for select cities, where the weather data
is refreshed only every three hours. In this scenario, you want to cache a separate version of the page for each city. You can do
so by setting the cache parameter to vary by a query string parameter.
In the following procedure, you will change the Label control you added to your page so that it displays the time with a
colored background. You can change the color by using a TextBox control for entering a color name.
When you submit the page, the color you type is submitted as post data, and the color behind the Label control changes.
When a new color is requested (when the page includes new post data), the page is regenerated and the timestamp is updated.
However, subsequent requests for the same color will result in the cached page being returned (until the duration interval has
been exceeded).
To cache based on parameters
1. Open or switch to the page you have been working on.
2. Switch to Design view.
3. From the Standard group of the toolbox, drag a TextBox control onto the page and set its ID to Color.
4. Drag a Button control onto the page, leaving the default name of Button1.
5. Set the Button control's Text property to "Change Color".
Double-click the Button control to create a Click event handler.
6. Within the method, add the following highlighted code:
VB
Protected Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Label1.BackColor = _
System.Drawing.Color.FromName(Server.HtmlEncode(Color.Text))
End Sub
C#
protected void Button1_Click(Object sender, System.EventArgs e)
{
Label1.BackColor =
System.Drawing.Color.FromName(Server.HtmlEncode(Color.Text));
}

7. Set the defaultbutton attribute of the form element to "Button1".


This causes the Click event handler for the button to be invoked when the ENTER key is pressed.
8. Replace the @ OutputCache directive with the following version:

<%@ OutputCache Location="Server" Duration="60" VaryByParam="Color" %>

9. Press CTRL+F5 to run the page.


10. Type a color name such as "red" or "blue" in the text box, and then click Change Color.
ASP.NET caches a version of the page that uses the color you specify.
11. Refresh the page a number of times.
If you do not type in a new color name, the date and time will not change for at least one minute, as specified by the
Duration attribute in your @ OutputCache directive.
12. Enter a new color, such as "green" or "orchid" and then submit the page.
This time you will see the time update along with the new color.
Next Steps
This walkthrough has illustrated basic concepts of caching ASP.NET pages. You might also want to explore these additional
caching techniques:
Instead of using page declarations, specify caching programmatically. For example, in your Page_Load method you could
access the HttpCachePolicy class (through Page.Response.Cache), and set values and behavior accordingly.
Cache data-bound pages so that they are regenerated only when the data they are dependent on has changed. For
details, see Walkthrough: Using ASP.NET Output Caching with SQL Server.
See Also
Tasks
Walkthrough: Using ASP.NET Output Caching with SQL Server
Reference
@ OutputCache
HttpCachePolicy
VaryByParams
Concepts
ASP.NET Caching Overview
Visual Web Developer

Walkthrough: Using ASP.NET Output Caching with SQL Server


This walkthrough shows how to cache ASP.NET pages that depend on data in a SQL Server database.
An advanced feature of ASP.NET output caching is SQL cache dependency. SQL cache dependency enables you to cache pages
that are dependent on data from SQL Server tables. You can configure SQL Server and ASP.NET to cache page requests,
reducing server workload, until the data on which the page depends has been updated in SQL Server. SQL cache dependency
is useful for data such as product catalogs or customer registration information that remains comparatively static.
Tasks illustrated in this walkthrough include:
Creating and configuring a page to display data from the Northwind database.
Enabling a database for SQL cache notification.
Specifying the SQL cache dependency on your page and in your Web.config file.
Making changes to the Northwind database and viewing the caching behavior.
Prerequisites
In order to complete this walkthrough, you will need:
Access to SQL Server 2000 or SQL Server 2005 with the Northwind database.
Access to the SQL Server Northwind database. For information about downloading and installing the SQL Server sample
Northwind database, see Installing Sample Databases on the Microsoft SQL Server Web site.
Note
If you need information about how to log on to the computer running SQL Server, contact the server administrator.

Microsoft Data Access Components (MDAC) version 2.7 or later.


If you are using Windows XP or Windows Server 2003, you already have MDAC 2.7. However, if you are using Windows
2000, you might to need to upgrade the MDAC already installed on your computer. For more information, see the MSDN
article MDAC Installation.
The .NET Framework version 2.0.
Creating the Web Site
If you have already created a Web site in Visual Web Developer (see
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and go to "Enabling Cache
Notification for SQL Server" later in this walkthrough. Otherwise, create a new Web site and page using the following
procedure.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site. (In Visual Web Developer Express Edition, on the File menu click New, and then
click Web Site.)
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, enter the name of the folder where you want to keep the pages of your Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click the programming language you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Enabling Cache Notification for SQL Server
You must configure SQL Server to provide proper notification to ASP.NET regarding changes in dependent data. You will need
administrative privileges to configure the server.
To enable cache notification for SQL Server
1. On the Windows Start menu, point to All Programs, point to Accessories, and then click Command Prompt to open a
command prompt window.
2. Locate the Aspnet_regsql.exe executable file on your disk drive. This file is installed with the .NET Framework version 2.0
in the following location:

%windir%\Microsoft.NET\Framework\FrameworkVersion

Be sure that %windir% represents your Windows directory and that the .NET Framework version is 2.0 or later. The path
might look like the following:

C:\WINDOWS\Microsoft.NET\Framework\v2.0.40217

3. Use the following command to enable cache notification for the Employees table in the Northwind database:

aspnet_regsql.exe -S <Server> -U <Username> -P <Password> -ed -d Northwind -et -t Empl


oyees

Note
You will need administrative privileges or the administrative account and password. If you do not have this information
, contact your database administrator.

A message will appear indicating success or failure in enabling the database. The following message indicates success:

Enabling the table for SQL cache dependency.


..
Finished.

Adding a Data Connection to the Project


To work with the SQL Server database in Visual Web Developer, you need to add a connection to the Northwind database.
To add a data source to the project
1. In Server Explorer (Database Explorer in Visual Web Developer Express Edition), right-click Data Connections, and
then click Add Connection.
Note
Server Explorer (Database Explorer in Visual Web Developer Express Edition) is typically docked behind Solution Ex
plorer.

If Server Explorer (Database Explorer in Visual Web Developer Express Edition) is not visible, in the View menu, click
Server Explorer (Database Explorer in Visual Web Developer Express Edition).
2. If the Choose Data Source dialog box is displayed, do the following:
a. In the Data source list, click Microsoft SQL Server.
b. In the Data provider list, click .NET Framework Data Provider for SQL Server.
c. Click Continue.
3. In the Add Connection dialog box, provide the details (server name, login credentials, and so on) for your database, and
then select the Northwind database.
4. Click OK.
Adding a Time Stamp and Data to the Web Page
You can now create a Web page to demonstrate caching. In this section you will add a time stamp to track page creation times
and a GridView control to view the Employees table of the Northwind database.
To add a time stamp and data to the Web page
1. Switch to or open the Default.aspx page.
2. Switch to Design view.
3. From the Standard group in the Toolbox, drag a Label control onto the page, leaving the default name of Label1.
4. In Server Explorer (Database Explorer in Visual Web Developer Express Edition), expand Data Connections.
5. Expand the node for the data connection you created earlier.
6. Expand the Tables node.
7. Drag the Employees table to your page.
Visual Web Designer creates a GridView control that is configured to use the connection and table you selected.
8. In the GridView Tasks menu, click Configure Data Source.
The default data connection string name NorthwindConnectionString1 appears in the first step of the Configure Data
Source wizard.
9. Click Next.
10. In the Configure Select Statement pane, select Specify columns from a table or view.
11. In the Name list, click Employees.
12. In the Columns list, select the EmployeeID, LastName, and FirstName columns.
13. Click Next.
14. Click Finish.
Visual Web Designer configures the GridView control to display the data you have selected.
Note
If you see a message asking whether you want to refresh the fields and keys for the GridView control, click Yes.

15. Double-click a blank part of the page.


The designer generates a Page_Load method and switches views.
16. Add the following highlighted code to display a time stamp indicating page creation:
VB
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles Me.Load
Label1.Text = System.DateTime.Now
End Sub

C#
protected void Page_Load(Object sender, System.EventArgs e)
{
Label1.Text = System.DateTime.Now.ToString();
}

17. Save the file.


Testing the Page without Caching
Now you can run the page and observe the behavior without caching. The page is loaded and the current server time is
displayed, and then the data is retrieved and placed on the page.
To test the page without caching
1. Press CTRL+F5 to run the page.
2. Refresh the page in the browser
Note that the time stamp changes with each page refresh. The data remains the same.
Configuring the Web Page for Caching
In this part of the walkthrough, you will configure the page for SQL cache dependency based on the Employees table of the
Northwind database.
To configure the Web page for caching
1. Switch to Source view.
2. At the top of the page, add the following directive to indicate the dependency:

<%@ OutputCache Duration="3600" SqlDependency="Northwind:Employees" VaryByParam="none"


%>

The VaryByParam attribute indicates whether ASP.NET should take into consideration page parameters (such as query string
or posted values) when caching. When VaryByParam is set to none, no parameters will be considered; all users are sent the
same page no matter what additional parameters are supplied. Setting VaryByParam to * (an asterisk) means that for each
unique combination of request parameters a unique page will be cached. However, setting VaryByParam to * can cause many
different versions of the page to be cached, so if you know the parameters to vary caching by, it is recommended that you
explicitly specify them in the VaryByParam attribute. For details, see Caching Multiple Versions of a Page.
Setting Caching Configuration in the Web.config File
In addition to the OutputCache declaration on your Web page in the preceding section, you need to specify caching details in
the Web.config file.
To create and update the Web.config file
1. If your Web site already has a Web.config file, go to step 4.
2. In Solution Explorer, right-click the name of your Web site and then click Add New Item.
3. In the Add Item dialog box, click Web Configuration File, and then click Add.
Be sure to use the name Web.config.
4. Add the following XML to the Web.config file as a child of the system.web element:

<!-- caching section group -->


<caching>
<sqlCacheDependency enabled = "true" pollTime = "1000" >
<databases>
<add name="Northwind"
connectionStringName="NorthwindConnectionString1"
pollTime = "1000"
/>
</databases>
</sqlCacheDependency>
</caching>

Note
The connection string name NorthwindConnectionString1 was established earlier when you created the data conne
ction. If your connection string has a different name, substitute that name instead.

Note
The account credentials specified in the connection string must have sufficient privileges to poll the database.

5. Save the file and then close it.


Testing the Page with Caching
With caching enabled, refreshing the page will no longer result in an updated time stamp or a database query, because
ASP.NET will fulfill the page request from the cache.
To test the page with caching
Press CTRL+F5 to run the page.
Note that the time stamp remains the same with each page refresh. The page is being retrieved from the cache.
Changing the Data
Now you can change the data in the database and see that the cache is invalidated and a new page is created.
To change the data
1. In Server Explorer (Data Explorer in Visual Web Developer Express Edition), expand the Data Connections node.
2. Expand the connection you created earlier.
3. Expand the Tables node.
4. Right-click Employees, and then click Show Table Data.
5. Update the database by editing any field in the data table, ensuring it is a field your Web page is displaying.
Alternatively, you can use the SQL pane (if the SQL pane is not visible, in the Query Designer menu, click Pane, and
then click SQL). Enter a SQL command directly and then click the Execute SQL button in the Query Designer toolbar. For
example, run the following command:

UPDATE dbo.Employees SET LastName = 'Doe' WHERE (EmployeeID = 5)

This changes the name of employee 5 to Doe.


6. Close the view of the data.
Testing the SQL Cache Dependency
You can now test the page to see whether the data and timestamp have changed.
To test SQL cache dependency
1. Press CTRL+F5 to run the page.
Note that the time stamp has changed and that the new data is displayed.
2. Press CTRL+F5 to run the page again.
This time the time stamp remains the same, because the data has not changed, and the page is now being retrieved once
again from the cache.
Next Steps
You can cache pages using other parameters as well. For information, see
Walkthrough: Using Output Caching to Enhance Web Site Performance. If you are not familiar with data access, see
Walkthrough: Basic Data Access in Web Pages.
See Also
Reference
DefaultHttpCachePolicy
OutputCacheSettingsSection
Concepts
Caching in ASP.NET with the SqlCacheDependency Class
ASP.NET

Caching ASP.NET Pages


ASP.NET allows you to cache some or all of the response generated by an ASP.NET page, referred to in ASP.NET as output
caching. You can cache the page at the browser making the request, at the Web server responding to the request, and at any
other cache-capable devices, such as proxy servers, that are in the request or response stream. Caching provides a powerful
way for you to increase the performance of your Web applications. Caching allows subsequent requests for a page to be
satisfied from the cache so the code that initially creates the page does not have to be run again. Caching your site's most
frequently accessed pages can substantially increase your Web server's throughput, commonly measured in requests per
second.
You can specify cache settings declaratively in a page or configuration file, or programmatically using a cache API. For more
information, see Setting the Cacheability of a Page.
You can cache pages based on the values of query string parameters or form variables (control values). Caching based on
these types of values must be explicitly enabled by using the @ OutputCache directive's VaryByParam attribute. For more
information, see Caching Multiple Versions of a Page.
When a cached page is requested by a user, ASP.NET determines whether the cached output is still valid based on the cache
policy you have defined for the page. If the output is valid, the cached output is sent to the client and the page is not re-
processed. ASP.NET allows you to run code during this validation check so that you can write custom logic to check whether
the page is valid. For more information see How to: Check the Validity of a Cached Page.
Sometimes it is impractical to cache an entire page because portions of the page might need to change on each request. In
those cases, you can cache a portion of a page. ASP.NET provides functionality to cache only portions of an ASP.NET page. For
more information see Caching Portions of an ASP.NET Page.
See Also
Tasks
How to: Set the Cacheability of an ASP.NET Page Declaratively
How to: Set a Page's Cacheability Programmatically
How to: Set Expiration Values for ASP.NET Page Caching
How to: Check the Validity of a Cached Page
How to: Cache Page Output with File Dependencies
How to: Cache Page Output with Cache Key Dependencies
Concepts
ASP.NET Caching Overview
Setting the Cacheability of a Page
Caching Multiple Versions of a Page
ASP.NET

Setting the Cacheability of a Page


The cacheability of a page or user control refers to whether a page can be cached on a device during the page's response life
cycle. Devices that can cache a page include the browser making the request, the Web server responding to the request, and
any other cache-capable devices, such as proxy servers, that are in the request or response stream.
When a Web server sends a response to the requesting browser, the server includes in the response a Cache-Control field in
the HTTP header that defines the devices on which the page can be cached. Depending on the needs of your application, you
can define which devices should or should not cache individual ASP.NET pages. For example, you might want the cacheability
settings for a user logon page to be different from those for a page that displays a selection of products from a catalog. In the
case of the logon page, for security reasons you might want to cache the page only on the server, while the catalog page can
be cached on any device.
For ASP.NET pages, you can set cacheability by using values in the HttpCacheability enumeration. The enumeration has the
following values. The first three map directly to Cache-Control HTTP header settings, and the last three are special values.
NoCache Specifies that the device making the request should get the response from the Web server each time.
Public Allows the response to be cached by clients and shared (proxy) caches.
Private Specifies that the response is cacheable only on the client and not by shared (proxy server) caches.
Server Specifies that the response is cached only at the origin server.
ServerAndNoCache Applies the settings of both Server and NoCache to indicate that the content is cached at the
server but all others are explicitly denied the ability to cache the response.
ServerAndPrivate Specifies that a response should be cached only on the origin server and on the requesting client;
proxy servers are not allowed to cache the response.
You can set a page's cacheability declaratively by including a Location attribute in the @ OutputCache directive and specifying
one of the OutputCacheLocation enumeration values. You can also set a page's cacheability programmatically using the
SetCacheability method to specify an HttpCacheability value for the page. The method is accessible through the Cache
property of the Response class.
Note
If you use the @ OutputCache directive to set your page's cacheability, you must declare the Duration attribute and either t
he VaryByControl attribute or the VaryByParam attribute along with the Location attribute. The Duration attribute must be
set to a value larger than zero. You can set the VaryByParam attribute to "None" if you do not want to use the functionality
of the VaryByParam or VaryByControl parameters. For more information, see
How to: Set Expiration Values for ASP.NET Page Caching and Caching Multiple Versions of a Page.

As an alternative to setting a page's cacheability using the @ OutputCache directive, you can create a cache profile in your
application's Web.config file and then reference the profile in your page. For more information, see
Cache Configuration in ASP.NET.
See Also
Tasks
How to: Set the Cacheability of an ASP.NET Page Declaratively
How to: Set a Page's Cacheability Programmatically
Reference
Duration
Concepts
Caching ASP.NET Pages
ASP.NET

How to: Set the Cacheability of an ASP.NET Page Declaratively


The cacheability of a page or user control refers to whether or not a page can be cached on a device during its response life
cycle. These devices include the client (browser) making the request, the Web server responding to the request, and any cache-
capable devices, such as proxy servers, that are in the request or response stream.
If you know at design time what cacheability setting you need for a page, you can set cacheability declaratively. The page will
then use the same cacheability settings for all requests. For more information, see Setting the Cacheability of a Page.
To set a page's cacheability declaratively
1. Include an @ OutputCache directive in the page and define Duration and VaryByParam attributes.
2. Include a Location attribute in the @ OutputCache directive and define its value as one of the following values in the
OutputCacheLocation enumeration: Any, Client, Downstream, Server, ServerAndClient, or None.
The following code shows how to set the page's cacheability to 60 seconds:

<%@ OutputCache Duration="60" VaryByParam="None"%>

Note
The default setting is Any. If you do not define a Location attribute, the page output can be cached on all cache-capabl
e network devices that are involved in the response. These include the requesting client, the origin server, and any prox
y servers through which the response passes.

To set a page's cacheability declaratively using a cache profile


1. Define a cache profile in your application's Web.config file and in the profile, include duration and varyByParam
settings.
The following <caching> configuration element defines a cache profile named Cache30Seconds, which will cache the
page on the server for 30 seconds.

<caching>
<outputCacheSettings>
<outputCacheProfiles>
<add name="Cache30Seconds" duration="30"
varyByParam="none" />
</outputCacheProfiles>
</outputCacheSettings>
</caching>

2. Include an @ OutputCachedirective in each ASP.NET page that uses the profile, and set the CacheProfile attribute to the
name of the cache profile defined in your Web.config file.
The following code specifies that the page should use the cache profile named Cache30Seconds:

<%@ OutputCache CacheProfile="Cache30Seconds" %>

See Also
Tasks
How to: Set a Page's Cacheability Programmatically
Concepts
Caching ASP.NET Pages
Caching ASP.NET Pages
Setting the Cacheability of a Page
ASP.NET

How to: Set a Page's Cacheability Programmatically


The cacheability of a page or user control refers to whether a page can be cached on a device during the page's response life
cycle. Devices that can cache a page include the browser making the request, the Web server responding to the request, and
any cache-capable devices, such as proxy servers, that are in the request or response stream.
You can set cacheability programmatically if your application will determine cacheability based on run-time conditions, such as
reading the request header. For more information, see Setting the Cacheability of a Page.
To set a page's cacheability programmatically
In the page's code, call the SetCacheability method on the Cache property of the Response object.
The following code sets the Cache-Control HTTP header to Public.
C#
Response.Cache.SetCacheability(HttpCacheability.Public);

Response.Cache.SetCacheability(HttpCacheability.Public)

If you pass either NoCache or ServerAndNoCache to the SetCacheability method to prevent a requesting browser from
caching a page in its History folder, any time a user clicks a back or forward button, a new version of the response will be
requested. You can override this behavior conditionally by calling the SetAllowResponseInBrowserHistory method on the
Cache property and passing true for the allow parameter.
If you set cacheability to any value other than NoCache or ServerAndNoCache, ASP.NET ignores the value set by the
SetAllowResponseInBrowserHistory method.
See Also
Tasks
How to: Set the Cacheability of an ASP.NET Page Declaratively
Concepts
Caching ASP.NET Pages
Setting the Cacheability of a Page
ASP.NET

How to: Set Expiration Values for ASP.NET Page Caching


To cause a page to be added to the output cache, you establish an expiration policy for that page. You can do this declaratively
or programmatically.
To set output-cache expirations for a page declaratively
Include an @ OutputCache directive in the ASP.NET page (.aspx file) whose response you want to cache. Set the Duration
attribute to a positive numeric value, and set the VaryByParam attribute to a value.
Note
The @ OutputCache directive sets the Cache-Control header to Any by default.

For example, the following @ OutputCache directive sets the page's expiration to 60 seconds:

<%@ OutputCache Duration="60" VaryByParam="None" %>

Note
You must include a VaryByParam attribute when using the @ OutputCache directive or a parser error will occur. If y
ou do not want to use the functionality offered by the VaryByParam attribute, set its value to "None". For more inform
ation, see Caching Multiple Versions of a Page.

To set output-cache expirations for a page programmatically


In the page's code, set the expiration policy for the page on the Cache property of the Response object.
Note
If you set expirations for a page programmatically, you must set the Cache-Control header for the cached page as well
. To do so, call the SetCacheability method and pass it the HttpCacheability enumeration value Public.

The following code example sets the same cache policy as the @ OutputCache directive does in the preceding
procedure.
C#
Response.Cache.SetExpires(DateTime.Now.AddSeconds(60));
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.SetValidUntilExpires(true);

VB
Response.Cache.SetExpires(DateTime.Now.AddSeconds(60))
Response.Cache.SetCacheability(HttpCacheability.Public)
Response.Cache.SetValidUntilExpires(True)

When the cached page expires, the subsequent request for the page causes a dynamically generated response. This
response page is cached for the specified duration.
See Also
Tasks
How to: Set the Cacheability of an ASP.NET Page Declaratively
How to: Set a Page's Cacheability Programmatically
Concepts
Caching ASP.NET Pages
Setting the Cacheability of a Page
ASP.NET

How to: Check the Validity of a Cached Page


When a cached page is requested by a user, ASP.NET determines whether the cached output is still valid based on the cache
policy you have defined in the page. If the output is valid, the cached output is sent to the client and the page is not re-
processed. However, ASP.NET provides you with the ability to run code during this validation check using a validation callback,
so that you can write custom logic to check whether the page is valid. The validation callback allows you to invalidate cached
pages outside of the normal process of using cache dependencies.
To programmatically check the validity of a cached page
1. Define an event handler of type HttpCacheValidateHandler and include code that checks the validity of the cached page
response.
The validation handler must return one of the following HttpValidationStatus values:
Invalid Indicates that the cached page is invalid, the page is evicted from the cache, and the request is handled as a
cache miss.
IgnoreThisRequest Causes the request to be treated as a cache miss. The page is therefore processed again, but
the cached page is not invalidated.
Valid Indicates that the cached page is valid.
The following code example illustrates a validation handler named ValidateCacheOutput that determines whether the
query string variable status contains the values "invalid" or "ignore". If the status value is "invalid", the method returns
Invalid and the page is invalidated in the cache. If the status value is "ignore", the method returns IgnoreThisRequest
and the page is left in the cache but a new response is generated for this request.
C#
public static void ValidateCacheOutput(HttpContext context, Object data,
ref HttpValidationStatus status)
{
if (context.Request.QueryString["Status"] != null)
{
string pageStatus = context.Request.QueryString["Status"];

if (pageStatus == "invalid")
status = HttpValidationStatus.Invalid;
else if (pageStatus == "ignore")
status = HttpValidationStatus.IgnoreThisRequest;
else
status = HttpValidationStatus.Valid;
}
else
status = HttpValidationStatus.Valid;
}

VB
Public Shared Sub ValidatePage(ByVal context As HttpContext, _
ByVal data As [Object], ByRef status As HttpValidationStatus)
If Not (context.Request.QueryString("Status") Is Nothing) Then
Dim pageStatus As String = context.Request.QueryString("Status")

If pageStatus = "invalid" Then


status = HttpValidationStatus.Invalid
ElseIf pageStatus = "ignore" Then
status = HttpValidationStatus.IgnoreThisRequest
Else
status = HttpValidationStatus.Valid
End If
Else
status = HttpValidationStatus.Valid
End If
End Sub

2. From one of the page life-cycle events (such as the page's Load event), call the AddValidationCallback method, passing as
the first argument the event handler you defined in step 1.
The following code example sets the ValidateCacheOutput method to be the validation handler.
C#
protected void Page_Load(object sender, EventArgs e)
{
Response.Cache.AddValidationCallback(
new HttpCacheValidateHandler(ValidateCacheOutput),
null);
}

VB
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load

Response.Cache.AddValidationCallback( _
New HttpCacheValidateHandler(AddressOf ValidatePage), Nothing)
End Sub

See Also
Concepts
Caching ASP.NET Pages
ASP.NET

How to: Cache Page Output with File Dependencies


At times you might want to remove a page from the output cache when a file changes. For example, you might have a page
that gets its contents from a process-intensive report that produces an XML file as output. The page needs to be reprocessed
only if the XML file changes. To limit reprocessing to just those times when it is necessary, you can use the make the page's
cache policy dependent on a single file. If required, you can make the cached page dependent on more than one file.
Note
You can explicitly remove any page from the output cache by calling the RemoveOutputCacheItem method. You can do this f
rom the Global.asax file, from a custom ASP.NET server control, or from a page, depending on the needs of your application.

To make cached page output dependent upon a file


1. Specify the settings for caching page output either declaratively or programmatically. For more information, see
How to: Set Expiration Values for ASP.NET Page Caching, Setting the Cacheability of a Page, and
Caching Multiple Versions of a Page.
2. In the page code, call the AddFileDependency method. As the method's filename parameter, pass the path of the file on
which you are creating a dependency.
The following code example sets a file dependency on the TextFile1.txt file. When the file changes, the page output will be
removed from the cache.
C#
protected void Page_Load(object sender, EventArgs e)
{
string fileDependencyPath = Server.MapPath("TextFile1.txt");
Response.AddFileDependency(fileDependencyPath);

// Set additional properties to enable caching.


Response.Cache.SetExpires(DateTime.Now.AddSeconds(60));
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.SetValidUntilExpires(true);
}

VB
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As EventArgs) Handles Me.Load
Dim fileDependencyPath As String = _
Server.MapPath("TextFile1.txt")
Response.AddFileDependency(fileDependencyPath)

' Set additional properties to enable caching.


Response.Cache.SetExpires(DateTime.Now.AddSeconds(60))
Response.Cache.SetCacheability(HttpCacheability.Public)
Response.Cache.SetValidUntilExpires(True)
End Sub

Note
You cannot use these methods from an ASP.NET user control. However, in any user control that specifies the
@ OutputCache directive you can create a file dependency and assign it to the Dependency property.

To make cached page output dependent on a group of files


1. Specify the settings for caching page output either declaratively or programmatically. For more information, see
How to: Set Expiration Values for ASP.NET Page Caching, Setting the Cacheability of a Page, and
Caching Multiple Versions of a Page.
2. In the page code, create a String array or an ArrayList that contains the paths of the files to make the page dependent on.
3. Call the AddFileDependencies method and as the filenames parameter, pass the array.
The following code example creates a string array of the file paths for the TextFile1.txt and XMLFile1.xml files and makes
the page output dependent on the two files. If either one of the files is modified, the page output will be removed from
the cache.
C#
protected void Page_Load(object sender, EventArgs e)
{
string[] fileDependencies;
string fileDependency1 = Server.MapPath("TextFile1.txt");
string fileDependency2 = Server.MapPath("XMLFile1.xml");
fileDependencies = new String[] { fileDependency1,
fileDependency2 };
Response.AddFileDependencies(fileDependencies);
}

VB
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles M
e.Load
Dim fileDependencies() As String
Dim fileDependency1 As String = Server.MapPath("TextFile1.txt")
Dim fileDependency2 As String = Server.MapPath("XMLFile1.xml")
fileDependencies = New String() {fileDependency1, _
fileDependency2}
Response.AddFileDependencies(fileDependencies)
End Sub

See Also
Tasks
How to: Set a Page's Cacheability Programmatically
Concepts
Caching ASP.NET Pages
Setting the Cacheability of a Page
ASP.NET

How to: Cache Page Output with Cache Key Dependencies


At times, you might want to remove a page from the output cache when another item in the cache is removed. For example,
you might have a page that displays a process-intensive report that is placed in the application cache and used by multiple
pages. When the report is changed or is removed from cache, you want the page output to be removed from the cache also
because the report is no longer valid. To do this you can make cached page output dependent on other cached items.
Note
You can explicitly remove any page from the output cache by calling the RemoveOutputCacheItem method. You can do this f
rom the Global.asax file, from a custom ASP.NET server control, or from a page, depending on the needs of your application.

To make cached page output dependent upon another cache item


1. In a page, specify cache settings either declaratively or programmatically. For more information, see
How to: Set Expiration Values for ASP.NET Page Caching, Setting the Cacheability of a Page, and
Caching Multiple Versions of a Page.
2. In page code, call the AddCacheItemDependency method. As the cacheKey parameter, pass the name of the cache item
on which to create a dependency.
The following code example shows how to set a dependency on the item named ProcessIntensiveReport. When this
item is modified or removed, the page output will be removed from the cache.
C#
protected void Page_Load(object sender, EventArgs e)
{
Response.AddCacheItemDependency("ProcessIntensiveReport");

// Set additional properties to enable caching.


Response.Cache.SetExpires(DateTime.Now.AddSeconds(60));
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.SetValidUntilExpires(true);
}

VB
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles M
e.Load
Response.AddCacheItemDependency("ProcessIntensiveReport")

' Set additional properties to enable caching.


Response.Cache.SetExpires(DateTime.Now.AddSeconds(60))
Response.Cache.SetCacheability(HttpCacheability.Public)
Response.Cache.SetValidUntilExpires(True)
End Sub

Note
You cannot call the AddCacheItemDependency method in an ASP.NET user control. However, in any user control tha
t specifies the @ OutputCache directive, you can create a CacheDependency object that describes the cache key depend
ency and assign it to the Dependency property of the UserControl object.

See Also
Tasks
How to: Set a Page's Cacheability Programmatically
Concepts
Caching ASP.NET Pages
Setting the Cacheability of a Page
ASP.NET

Caching Application Data


ASP.NET has a powerful, easy-to-use caching mechanism that allows you to store objects in memory that require extensive
server resources to create. Caching these types of resources can significantly improve the performance of your application.
Caching is implemented by the Cache class, with cache instances private to each application. The cache lifetime is tied to that of
the application; when the application is restarted, the Cache object is recreated.
The Cache class has been designed for ease of use. You can place items in the Cache and later retrieve them using simple
key/value pairs. For examples of how to do this, see How to: Add Items to the Cache and
How to: Retrieve Values of Cached Items.
The Cache class offers powerful features that allow you to customize how items are cached and how long they are cached. For
example, when system memory becomes scarce, the cache automatically removes seldom-used or low-priority items to free
memory. This technique is referred to as scavenging, and is one of the ways that the cache ensures that out-of-date data does
not consume valuable server resources.
You can instruct the Cache object to give certain items priority over other items when it performs scavenging. To indicate an
item's importance, you can specify one of the CacheItemPriority enumeration values when you add an item using the Add or
Insert methods.
You can also establish an expiration policy for an item when you add it to the cache using the Add or Insert methods. You can
define the lifetime for an item by specifying an exact time the item will expire (an absolute expiration) using a DateTime value.
Alternatively, you can specify a sliding expiration using a TimeSpan value, which allows you to specify the elapsed time before
the item expires based on the time it was last accessed. Once an item expires, it is removed from the cache. Attempts to retrieve
its value will return null (Nothing in Visual Basic) unless the item is added to the cache again.
For volatile items that are stored in the cache, such as those that have regular data refreshes or those that are valid for only a
set amount of time, you typically set an expiration policy that keeps those items in the cache as long as their data remains
current. For example, if you are writing an application that tracks sports scores by obtaining the data from another Web site,
you can cache the scores for a game as long as those scores do not change on the source Web site. In this case, you can set an
expiration policy that is based on how often the other Web site updates the scores. You can write code that determines if an
up-to-date score is in the cache. If the score is not up to date, the code can read the score from the source Web site and cache
the new value.
Finally, ASP.NET allows you to define the validity of a cached item based on an external file or directory (a file dependency) or
on another cached item (a key dependency). If the item with the associated dependency changes, the cached item is invalidated
and removed from the cache. You can use this technique to remove items from the cache when their data source changes. For
example, if you write an application that processes financial data from an XML file, you can insert the data from the file in the
cache and maintain a dependency on that XML file. When the file is updated, the item is removed from the cache, your
application rereads the XML file and puts the refreshed data into the cache.
Note
The Cache object has no information about the content of the items it contains. It merely holds a reference to those objects. I
t also provides methods to track their dependencies and set expiration policies.

For more information on how to use these features, see How to: Add Items to the Cache.
See Also
Tasks
How to: Add Items to the Cache
How to: Retrieve Values of Cached Items
How to: Delete Items from the Cache in ASP.NET
How to: Notify an Application When an Item Is Removed from the Cache
Concepts
ASP.NET Caching Overview
What's New in ASP.NET Caching
ASP.NET

How to: Add Items to the Cache


You can access items in the application cache using the Cache object. You can add an item to the application cache using the
Cache object's Insert method. The method adds an item to the cache and has several overloads that enable you to add the
item with different options for setting dependencies, expiration, and removal notification. If you use the Insert method to add
an item to the cache and an item with the same name already exists, the existing item in the cache is replaced.
You can also add items to the cache using the Add method. This method enables you to set all the same options as the Insert
method; however, Add method returns the object you added to the cache. Additionally, if you use the Add method and an item
with the same name already exists in the cache, the method will not replace the item and will not raise an exception.
The procedures in this topic illustrate the following ways to add items to the application cache:
Adding an item to the cache by directly setting the item via key and value.
Adding items to the cache using the Insert method.
Adding an item to the cache and adding a dependency so that the item is removed from the cache when the dependency
changes. You can set dependencies based on other cache items, on files, and on multiple objects.
Adding an item to the cache with expiration policies. In addition to being able to set an item's dependency, you can set
the item to expire after a period of time (a sliding expiration) or at a specific time (an absolute expiration). You can define
either an absolute expiration or a sliding expiration, but not both.
Adding an item to the cache and defining the relative priority of the cached item. Relative priorities help the .NET
Framework determine what cache items to remove; lower priority items are removed from the cache before higher
priority items.
Adding an item by calling the Add method.
In addition to the dependencies shown here, you can create a dependency on a SQL Server table or based on a custom
dependency. For more information, see ASP.NET Caching Overview and
Caching in ASP.NET with the SqlCacheDependency Class.
You can also have the application cache notify your application when the item is removed from the cache, using the
CacheItemRemovedCallback delegate. For a full example, see
How to: Notify an Application When an Item Is Removed from the Cache.
To add an item to the cache by directly setting the item via key and value
Add items to the cache as you would add items to a dictionary by specifying the item's key and value.
The following code example adds an item named CacheItem1 to the Cache object:
C#
Cache["CacheItem1"] = "Cached Item 1";

VB
Cache("CacheItem1") = "Cached Item 1"

To add items to the cache by using the Insert method


Call the Insert method, passing the key and value of the item to add.
The following code example adds a string under the name CacheItem2:
C#
Cache.Insert("CacheItem2", "Cached Item 2");

VB
Cache.Insert("CacheItem2", "Cached Item 2")

To add an item to the cache by specifying a dependency


Call the Insert method, passing it an instance of the CacheDependency object
The following code example adds an item named CacheItem3 that is dependent on another item in the cache named
CacheItem2:

C#
string[] dependencies = { "CacheItem2" };
Cache.Insert("CacheItem3", "Cached Item 3",
new System.Web.Caching.CacheDependency(null, dependencies));

VB
Dim dependencies As String() = {"CacheItem2"}
Cache.Insert("CacheItem3", "Cached Item 3", _
New System.Web.Caching.CacheDependency( _
Nothing, dependencies))

The following code example shows an item named CacheItem4 added to the cache and having a file dependency set on
the file named XMLFile.xml:
C#
Cache.Insert("CacheItem4", "Cached Item 4",
new System.Web.Caching.CacheDependency(
Server.MapPath("XMLFile.xml")));

VB
Cache.Insert("CacheItem4", "Cached Item 4", _
New System.Web.Caching.CacheDependency( _
Server.MapPath("XMLFile.xml")))

The following code example shows how to create multiple dependencies. It adds a key dependency on another item in
the cache named CacheItem1 and a file dependency on the file named XMLFile.xml.
C#
System.Web.Caching.CacheDependency dep1 =
new System.Web.Caching.CacheDependency(Server.MapPath("XMLFile.xml"));
string[] keyDependencies2 = { "CacheItem1" };
System.Web.Caching.CacheDependency dep2 =
new System.Web.Caching.CacheDependency(null, keyDependencies2);
System.Web.Caching.AggregateCacheDependency aggDep =
new System.Web.Caching.AggregateCacheDependency();
aggDep.Add(dep1);
aggDep.Add(dep2);
Cache.Insert("CacheItem5", "Cached Item 5", aggDep);

VB
Dim dep1 As CacheDependency = _
New CacheDependency(Server.MapPath("XMLFile.xml"))
Dim keyDependencies2 As String() = {"CacheItem1"}
Dim dep2 As CacheDependency = _
New System.Web.Caching.CacheDependency(Nothing, _
keyDependencies2)
Dim aggDep As AggregateCacheDependency = _
New System.Web.Caching.AggregateCacheDependency()
aggDep.Add(dep1)
aggDep.Add(dep2)
Cache.Insert("CacheItem5", "Cached Item 5", aggDep)

The add an item to the cache with expiration policies


Call the Insert method, passing it an absolute or sliding expiration time.
The following code example adds an item to the cache with an absolute expiration of one minute:
C#
Cache.Insert("CacheItem6", "Cached Item 6",
null, DateTime.Now.AddMinutes(1d),
System.Web.Caching.Cache.NoSlidingExpiration);

VB
Cache.Insert("CacheItem6", "Cached Item 6", _
Nothing, DateTime.Now.AddMinutes(1.0), _
TimeSpan.Zero)

The following code example adds an item to the cache with a sliding expiration time of 10 minutes:
C#
Cache.Insert("CacheItem7", "Cached Item 7",
null, System.Web.Caching.Cache.NoAbsoluteExpiration,
new TimeSpan(0, 10, 0));

VB
Cache.Insert("CacheItem7", "Cached Item 7", _
Nothing, System.Web.Caching.Cache.NoAbsoluteExpiration, _
New TimeSpan(0, 10, 0))

To add an item to the Cache with priority settings


Call the Insert method, specifying a value from the CacheItemPriority enumeration.
The following code example adds an item to the cache with a priority value of High:
C#
Cache.Insert("CacheItem8", "Cached Item 8",
null, System.Web.Caching.Cache.NoAbsoluteExpiration,
System.Web.Caching.Cache.NoSlidingExpiration,
System.Web.Caching.CacheItemPriority.High, null);

VB
Cache.Insert("CacheItem8", "Cached Item 8", _
Nothing, System.Web.Caching.Cache.NoAbsoluteExpiration, _
System.Web.Caching.Cache.NoSlidingExpiration, _
System.Web.Caching.CacheItemPriority.High, _
Nothing)
To add an item to the cache using the Add method
Call the Add method, which returns an object representing the item.
The following code example adds an item to the cache named CacheItem9 and sets the value of the variable CachedItem9
to be the item that was added.
C#
string CachedItem9 = (string)Cache.Add("CacheItem9",
"Cached Item 9", null,
System.Web.Caching.Cache.NoAbsoluteExpiration,
System.Web.Caching.Cache.NoSlidingExpiration,
System.Web.Caching.CacheItemPriority.Default,
null);

VB
Dim CachedItem9 As String = CStr(Cache.Add("CacheItem9", _
"Cached Item 9", Nothing, _
System.Web.Caching.Cache.NoAbsoluteExpiration, _
System.Web.Caching.Cache.NoSlidingExpiration, _
System.Web.Caching.CacheItemPriority.Default, _
Nothing))

See Also
Tasks
How to: Delete Items from the Cache in ASP.NET
How to: Notify an Application When an Item Is Removed from the Cache
How to: Retrieve Values of Cached Items
Concepts
ASP.NET Caching Overview
Caching Application Data
Caching in ASP.NET with the SqlCacheDependency Class
ASP.NET

How to: Retrieve Values of Cached Items


To retrieve data from the cache, you specify the key that the cached item was stored under. However, because information
stored in the cache is volatile—that is, it might be removed by ASP.NET—the recommended development pattern is to
determine first whether the item is in the cache. If it is not, you add it back to the cache and then retrieve the item.
To retrieve the value of a cached item
Check to see if the item is not null (Nothing in Visual Basic), in the Cache object. If it exists, assign it to your variable.
Otherwise, recreate the item, add it to the cache, and then access it.
The following code example shows how to retrieve the item named CacheItem from the cache. The code assigns the
contents of the item to the variable named cachedString. If the item is not in the cache, the code adds the item to the
cache and then assigns the item to cachedString.
C#
string cachedString;
cachedString = (string)Cache["CacheItem"];
if (cachedString == null)
{
cachedString = "Hello, World.";
Cache.Insert("CacheItem", cachedString);
}

VB
Dim cachedString As String
cachedString = CStr(Cache("CacheItem"))
If cachedString Is Nothing Then
cachedString = "Hello, World."
Cache.Insert("CacheItem", cachedString)
End If

See Also
Tasks
How to: Add Items to the Cache
How to: Delete Items from the Cache in ASP.NET
How to: Notify an Application When an Item Is Removed from the Cache
Concepts
ASP.NET Caching Overview
Caching Application Data
ASP.NET

How to: Delete Items from the Cache in ASP.NET


Data in the ASP.NET cache is volatile — that is, it is not permanently stored. It might be automatically removed from the cache
for one of these reasons:
Because the cache is full.
Because the item has expired.
Because an item it is dependent on changes.
For more information see ASP.NET Caching Overview.
The specific method for removing items from the cache is determined in the code used to add the item to the cache. For more
information, see How to: Add Items to the Cache. You can be notified when an item is removed from the cache. For more
information see How to: Notify an Application When an Item Is Removed from the Cache.
In addition to allowing items to be removed from the cache automatically, you can explicitly remove them.
Note
If you call the Insert method and add an item to the cache with the same name as an existing item, the old item will be delete
d from the cache.

To delete an item from the cache explicitly


Call the Remove method, passing the key of the item you want to remove.
The following example shows how to remove an item with the key MyData1.
VB
Cache.Remove("MyData1")

C#
Cache.Remove("MyData1");

See Also
Tasks
How to: Add Items to the Cache
How to: Notify an Application When an Item Is Removed from the Cache
How to: Retrieve Values of Cached Items
Concepts
Caching Application Data
ASP.NET

How to: Notify an Application When an Item Is Removed from


the Cache
In most cache scenarios, when an item is removed from the cache, you do not need to put it back into the cache until it is
needed again. The typical development pattern is to always check the cache for the item before using it. If the item is in the
cache, you use it. If it is not in the cache, you retrieve the item again and add it back to the cache.
However, in some cases it is useful for your application to be notified when an item is removed from the cache. For example,
you might have a cached report that takes considerable processing time to create. When it is removed from the cache, you
want it to be regenerated and put into the cache immediately so that the next time it is requested, the user does not have to
wait for it to be processed.
To enable notification of items being removed from the cache, ASP.NET provides the CacheItemRemovedCallback delegate.
The delegate defines the signature to use when you write an event handler that is called in response to an item being removed
from the cache. ASP.NET also provides the CacheItemRemovedReason enumeration, which is used to specify the reason for
cache item removal.
Typically, you implement the callback by creating a handler in a business object that manages the particular cache data that
you are trying to retrieve. For example, you might have a ReportManager object that has two methods, GetReport and
CacheReport. The GetReport report method checks the cache to see if the report is already cached and if it is not, the method
regenerates the report and caches it. The CacheReport method has the same function signature of the
CacheItemRemovedCallback delegate; when the report is removed from cache, ASP.NET calls the CacheReport method,
which then re-adds it to the cache.
To notify an application when an item is removed from the cache
1. Create a class that is responsible for retrieving the item from the cache and handling the callback method to add the item
back into the cache.
2. In the class, create a method that adds an item to the cache.
3. In the class, create a method that gets an item from the cache.
4. Create a method that handles the cache item removal callback. The method must have the same function signature as the
CacheItemRemovedCallback delegate. In the method, perform the logic you want to run when the item is removed
from the cache, such as regenerating the item and adding it back into the cache.

To test the cache item callback


1. Create an ASP.NET Web page that calls the method in your class that adds the item to the cache.
The following code example shows how to call the GetReport method of the ReportManager class (defined in the example
that follows the procedure). It then displays the report in a Label control named Label1 during the page's Page_Load
method.
C#
protected void Page_Load(object sender, EventArgs e)
{
this.Label1.Text = ReportManager.GetReport();
}

VB
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
Me.Label1.Text = ReportManager.GetReport()
End Sub

2. Request the ASP.NET page in a browser and view the report.


The report is created the first time the page is requested, and subsequent requests will access the report from the cache
until the report is removed.
Example
The following code example shows a complete class named ReportManager that handles notification when an item is deleted
from the cache. The class manages a report in the form of a string that represents a long-running process.
Although the example uses a class declared as static (Shared in Visual Basic), it is not required that you use a static class.
However, the method that will handle the callback must exist when the cache item is deleted. For example, you should not
implement the callback handler in an ASP.NET page, because the page might have been disposed of by the time the item is
deleted from the cache and therefore the method to handle the callback will not be available. Using a static class for the
method that handles the callback ensures that the method will still exist when the item is removed from cache. However, the
drawback to a static class is that all static methods need to be thread safe.
Caution
Do not set the CacheItemRemovedCallback to a method in a page. In addition to a page method not being available for a
callback after the page is disposed of, pointing the callback to a page method can prevent the memory used by the page fro
m being reclaimed by garbage collection. This happens because the callback contains a reference to the page and the garbag
e collector will not remove an item from memory if the item has any references. During periods of application load, this coul
d cause memory to be used up very quickly.

The example class includes these features:


A private member for tracking whether the report has been removed from the cache.
A method named CacheReport that adds an item to the cache under the name MyReport and sets the item to expire one
minute after being added to the cache. The method also passes the ReportRemovedCallback method to the
onRemoveCallback parameter, which registers the ReportRemoveCallback method so it is called when the item is deleted
from cache.
A method named GetReport that gets an item from the cache. The method determines whether the item named
MyReport exists in the cache. If the item does not exist, the method calls CacheReport, which adds the item to the cache.

A method named ReportRemovedCallback that handles the cache item removal callback. ReportRemovedCallback has the
same function signature as the CacheItemRemovedCallback delegate. The method sets the variable
_reportRemovedFromCache to true and then adds the item back to the cache via the CacheReport method.
C#
using System;
using System.Web;
using System.Web.Caching;
public static class ReportManager
{
private static bool _reportRemovedFromCache = false;
static ReportManager()
{ }

public static String GetReport()


{
lock (typeof(ReportManager))
{
if (HttpContext.Current.Cache["MyReport"] != null)
return (string)HttpRuntime.Cache["MyReport"];
else
{
CacheReport();
return (string)HttpRuntime.Cache["MyReport"];
}
}
}
public static void CacheReport()
{
lock (typeof(ReportManager))
{
HttpContext.Current.Cache.Add("MyReport",
CreateReport(), null, DateTime.MaxValue,
new TimeSpan(0, 1, 0),
System.Web.Caching.CacheItemPriority.Default,
ReportRemovedCallback);
}
}

private static string CreateReport()


{
System.Text.StringBuilder myReport =
new System.Text.StringBuilder();
myReport.Append("Sales Report<br />");
myReport.Append("2005 Q2 Figures<br />");
myReport.Append("Sales NE Region - $2 million<br />");
myReport.Append("Sales NW Region - $4.5 million<br />");
myReport.Append("Report Generated: " + DateTime.Now.ToString()
+ "<br />");
myReport.Append("Report Removed From Cache: " +
_reportRemovedFromCache.ToString());
return myReport.ToString();
}

public static void ReportRemovedCallback(String key, object value,


CacheItemRemovedReason removedReason)
{
_reportRemovedFromCache = true;
CacheReport();
}
}

VB
Imports System
Imports System.Web
Imports System.Web.Caching
Public Class ReportManager
Private Shared _reportRemovedFromCache As Boolean = False
Shared Sub New()
End Sub

Private Sub New()


End Sub

Public Shared Function GetReport() As String


SyncLock (GetType(ReportManager))
If HttpContext.Current.Cache("MyReport") IsNot Nothing Then
Return CStr(HttpRuntime.Cache("MyReport"))
Else
CacheReport()
Return CStr(HttpRuntime.Cache("MyReport"))
End If
End SyncLock
End Function

Public Shared Sub CacheReport()


SyncLock (GetType(ReportManager))
HttpContext.Current.Cache.Add("MyReport", CreateReport(), _
Nothing, DateTime.MaxValue, New TimeSpan(0, 1, 0), _
System.Web.Caching.CacheItemPriority.Default, _
AddressOf ReportRemovedCallback)
End SyncLock
End Sub

Private Shared Function CreateReport() As String


Dim myReport As New System.Text.StringBuilder()
myReport.Append("Sales Report<br />")
myReport.Append("2005 Q2 Figures<br />")
myReport.Append("Sales NE Region - $2 million<br />")
myReport.Append("Sales NW Region - $4.5 million<br />")
myReport.Append("Report Generated: " & _
DateTime.Now.ToString() & "<br />")
myReport.Append("Report Removed From Cache: " _
& _reportRemovedFromCache.ToString())
Return myReport.ToString()
End Function

Public Shared Sub ReportRemovedCallback(ByVal key As String, _


ByVal value As Object, ByVal removedReason _
As CacheItemRemovedReason)
_reportRemovedFromCache = True
CacheReport()
End Sub
End Class

See Also
Tasks
How to: Add Items to the Cache
How to: Retrieve Values of Cached Items
How to: Delete Items from the Cache in ASP.NET
Concepts
ASP.NET Caching Overview
What's New in ASP.NET Caching
Cache Configuration in ASP.NET
Caching Application Data
ASP.NET

Cache Configuration in ASP.NET


ASP.NET provides many options for configuring page output caching and the cache API. You use the page output cache to
cache page responses after they have been processed. You use the cache API to programmatically cache application data. For
more information, see ASP.NET Caching Overview.
Page Output Cache Configuration
You can configure page output caching in these places:
Configuration files You can configure page output cache settings in any configuration file in the application
configuration hierarchy, including the Machine.config file (to make settings for all Web applications on the computer)
and your application-specific Web.config file (to make settings for a single application).
Individual pages You can set caching options in individual pages either declaratively or programmatically. You can
also apply cache profiles created in the configuration file to individual pages.
User controls You can set caching in individual user controls either declaratively or programmatically. This is an easy
way to cache content within a page that is otherwise not cached.
Web.config Cache Configuration Settings
There are two top-level configuration sections for the page output cache in the Web.config file: the OutputCacheSection and
the OutputCacheSettingsSection.
The OutputCacheSection section is used to configure application-scope settings, such as whether page output caching is
enabled or disabled. For example, you can disable page output caching for the entire application by adding
enableOutputCache="false" to the OutputCacheSection in your Web.config file. Settings in the configuration file take
precedence over cache settings in individual pages, so the example setting means that output cache will not be used.
The OutputCacheSettingsSection is used to configure profiles and dependencies that can be used by individual pages. For
example, the following code creates an OutputCacheProfile named CacheProfile1 that will cache the implementing page for
60 seconds:

<outputCacheSettings>
<outputCacheProfiles>
<add name="CacheProfile1" duration="60" />
</outputCacheProfiles>
</outputCacheSettings>

Machine.config Cache Configuration Settings


The configuration sections for the Machine.config file are the same as for the Web.config file, except that you can lock
configuration settings in the Machine.config file so that they cannot be overridden by individual applications at any level. This
might be necessary in a shared hosting scenario in which the hoster does not want individual applications modifying the cache
configuration. For more information see How to: Lock ASP.NET Configuration Settings.
Page Cache Configuration Settings
You can configure caching in individual pages by applying cache profiles that have been defined in a configuration file.
Alternatively, you can configure individual cache properties in the @ OutputCache directive or by setting attributes in the
page's class definition. For more information see @ OutputCache and Setting the Cacheability of a Page.
User Control Cache Configuration Settings
You can configure user control caching by setting the @ OutputCache directive in the user control file or by setting the
PartialCachingAttribute attribute in the control's class definition. For more information, see
Caching Portions of an ASP.NET Page.
Cache API Configuration Settings
You can configure the application's cache API in your Web.config file. As with the page output cache, application hosters can
set configuration properties in the Machine.config file and lock cache configuration settings for all applications. The application
cache API is configured in the CacheSection. For example, you can disable item expiration with the following configuration
element:
<cache disableExpiration="true" />

You can also specify other application cache API configuration settings by assigning values to attributes such as
DisableExpiration and DisableMemoryCollection within the configuration file's CacheSection.
See Also
Concepts
ASP.NET Caching Overview
What's New in ASP.NET Caching
Caching ASP.NET Pages
Caching Application Data
ASP.NET Configuration Overview
Other Resources
ASP.NET Configuration Files
Visual Web Developer

Learning More - Caching


The topics in this section provide in-depth information on using ASP.NET caching.
In This Section
Caching Multiple Versions of a Page
Caching Portions of an ASP.NET Page
Dynamically Updating Portions of a Cached Page
Caching in ASP.NET with the SqlCacheDependency Class
See Also
Other Resources
ASP.NET Caching (Visual Studio)
ASP.NET Web Sites (Visual Studio)
ASP.NET Web Pages (Visual Studio)
ASP.NET

Caching Multiple Versions of a Page


At times you might have a page that you want to cache, but for which different versions are created based on the request. For
example, the page might have different output depending on the values passed in the query string.
ASP.NET allows you to cache multiple versions of the same page in the output cache. You can vary the output cache by the
following:
The query string in an initial request (HTTP GET).
Control values passed on postback (HTTP POST values).
The HTTP headers passed with a request.
The major version number of the browser making the request.
A custom string in the page. In that case, you create custom code in the Global.asax file to specify the page's caching
behavior.
You can cache multiple versions of a page output declaratively using attributes of the @ OutputCache directive, and
programmatically using the properties and methods of the HttpCachePolicy class.
The @ OutputCache directive includes four attributes that enable you to cache multiple versions of page output:
The VaryByParam attribute allows you to vary the cached output depending on the query string.
The VaryByControl attribute allows you to vary the cached output depending on a control value.
The VaryByHeader attribute allows you to vary the cached output depending on the request's HTTP header.
The VaryByCustom attribute allows you to vary the cached output by browser type or by a custom string that you define.
Note
You must include either the VaryByParam attribute or the VaryByControl attribute in any @ OutputCache directive.
However, if you do not need to vary your cached output by control or parameters, you can define VaryByParam with i
ts value to None.

The HttpCachePolicy class provides two properties and a method that allow you to programmatically specify the same cache
configuration that you can set declaratively. The VaryByParams and VaryByHeaders properties allow you to specify the query
string parameter and header names, respectively, that you want to vary the cache policy by. The SetVaryByCustom method
allows you to define custom strings by which to vary the output cache.
See Also
Tasks
How to: Set the Cacheability of an ASP.NET Page Declaratively
How to: Set a Page's Cacheability Programmatically
How to: Cache Versions of a Page Using Requesting Browser
How to: Cache Versions of a Page Using Parameters
How to: Cache Versions of a Page Using HTTP Headers
How to: Cache Versions of a Page Using Custom Strings
Concepts
Caching ASP.NET Pages
Setting the Cacheability of a Page
ASP.NET

How to: Cache Versions of a Page Using Requesting Browser


If your Web application contains a page that creates different output based on the type of the requesting browser, you can
cache versions of page's output by the major version of the browser that requests the page. For example, when an Internet
Explorer 6 browser requests a page, one version of the page is cached. When a Netscape Navigator browser, another version
of Internet Explorer, or any other browser requests the page, another version of the page is added to the output cache.
Note
Major version and browser type information is passed through the MajorVersion property of the HttpBrowserCapabilities ob
ject in the current request. For more information, see How to: Detect Browser Types in ASP.NET Web Pages.

To cache multiple versions of a page declaratively based on browser type


1. In the ASP.NET page, include an @ OutputCache directive with the required Duration and VaryByParam or VaryByControl
attributes. The Duration attribute must be set to an integer greater than zero. If you want to cache only by browser type,
set the VaryByParam attribute to "None".
2. In the @ OutputCache directive, include the VaryByCustom attribute and set it to "browser".
The following example will cause the page to be cached for 10 seconds. The output will vary by the browser type.

<%@ OutputCache Duration="10" VaryByParam="None" VaryByCustom="browser" %>

To cache multiple versions of a page programmatically based on browser type.


1. In the page code, call the SetExpires and SetCacheability methods on the Cache property of the page's Response
property.
2. Call the SetVaryByCustom method, passing the value "browser" in the custom parameter.
The following code example shows how to cache multiple versions of a page for one minute. The output will vary by the
type of browser that made the request.
C#
protected void Page_Load(object sender, EventArgs e)
{
Response.Cache.SetExpires(DateTime.Now.AddMinutes(1d));
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.SetValidUntilExpires(true);
Response.Cache.SetVaryByCustom("browser");
}

VB
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles M
e.Load
Response.Cache.SetExpires(DateTime.Now.AddMinutes(1.0))
Response.Cache.SetCacheability(HttpCacheability.Public)
Response.Cache.SetValidUntilExpires(True)
Response.Cache.SetVaryByCustom("browser")
End Sub

See Also
Tasks
How to: Set the Cacheability of an ASP.NET Page Declaratively
How to: Set a Page's Cacheability Programmatically
How to: Cache Versions of a Page Using Parameters
How to: Cache Versions of a Page Using HTTP Headers
How to: Cache Versions of a Page Using Custom Strings
Concepts
Caching ASP.NET Pages
Setting the Cacheability of a Page
Caching Multiple Versions of a Page
ASP.NET

How to: Cache Versions of a Page Using Parameters


There are times when you want to cache a page, but the page might generate different output based on the value of a query
string parameter or values sent with the page on postback. For example, if you have a page that shows locations of stores
based on a user's state, the page might accept a "state" query string value that generates a different version of the page for
each state.
You can cache multiple versions of page responses based on the parameters sent as query string values or form post values.
Note
ASP.NET treats query string values or form post values with identical key/value pairs as identical for caching purposes, regar
dless of the order in which the parameters are passed. However, for caching purposes, parameter names are case-sensitive a
nd ASP.NET will cache different versions of a page for uppercase and lowercase parameter names and values.

To cache multiple versions of page output declaratively using parameters


1. In the ASP.NET page, include an @ OutputCache directive with a Duration attribute. The Duration attribute is required
and must be set to an integer greater than zero.
2. In the @ OutputCache directive, include a VaryByParam attribute and set its value to the name of the query string or
form post parameter that you want to vary the page by.
The following code example caches the page for 60 seconds and specifies that different versions of the page output will
be cached based on the City query string value or form post parameter.

<%@ OutputCache Duration="60" VaryByParam="City" %>

Note
If you want to vary the output cache by multiple parameters, include a list of parameter names separated by semicolon
s (;). If you want to vary the cache by all parameter values, set the VaryByParam attribute to an asterisk (*). The followi
ng code example shows how to vary the page output by City and ZipCode parameters.

To cache multiple versions of page output programmatically using parameters


1. In the page's Page_Load event, call the SetCacheability and SetExpires methods on the Cache property of the Response
object.
2. Specify the parameter name as the argument for the Response object's VaryByParams property, and set the property to
true.
The following code example shows how to cache multiple versions of a page when requests arrive at the server with
different values for the Zip parameter.
C#
Response.Cache.SetExpires(DateTime.Now.AddMinutes(1.0));
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.SetValidUntilExpires(true);
Response.Cache.VaryByParams["Zip"] = true;

VB
Response.Cache.SetExpires(DateTime.Now.AddMinutes(1.0))
Response.Cache.SetCacheability(HttpCacheability.Public)
Response.Cache.SetValidUntilExpires(True)
Response.Cache.VaryByParams("Zip") = True
Note
If you want to vary the cached content by multiple parameters, set the VaryByParams property multiple times. If you
want to vary the cached content by all header values, set the VaryByHeader attribute to an asterisk (*). The following co
de example shows how to vary the page output by City and Zip parameters.

See Also
Tasks
How to: Set the Cacheability of an ASP.NET Page Declaratively
How to: Set a Page's Cacheability Programmatically
How to: Cache Versions of a Page Using Requesting Browser
How to: Cache Versions of a Page Using HTTP Headers
How to: Cache Versions of a Page Using Custom Strings
Concepts
Caching ASP.NET Pages
Setting the Cacheability of a Page
Caching Multiple Versions of a Page
ASP.NET

How to: Cache Versions of a Page Using HTTP Headers


ASP.NET allows you to cache multiple versions of a page depending on the value of an HTTP header that you specify. You can
specify caching by a single header, multiple headers, or all headers passed to your application when the page is requested.
To cache versions of a page declaratively based on HTTP header values
1. In the ASP.NET page, include an @ OutputCache directive with the required Duration and VaryByParam or VaryByControl
attributes. The Duration attribute must be set to an integer greater than zero. If you want to cache only by HTTP header
values, you must set the VaryByParam attribute to "None".
2. In the @ OutputCache directive, include the VaryByHeader attribute and set its value to the name of the HTTP header that
you want to vary the cache content by.
The following example caches the page for 60 seconds and sets versions of a page to be cached based on the value
passed with the Accept-Language HTTP header:

<%@ OutputCache Duration="60" VaryByParam="None" VaryByHeader="Accept-Language" %>

Note
If you want to vary the cached content by multiple headers, include a list of header names separated by semicolons (;). I
f you want to vary the cached content by all header values, set the VaryByHeader attribute to an asterisk (*).

To cache versions of a page programmatically based on an HTTP header value


1. In the page's Page_Load method, call the SetCacheability and SetExpires methods on the Cache property of the page's
Response object.
2. Set the value for the HTTP header in the VaryByHeaders property to true.
The following code example shows how to cache multiple versions of a page for one minute for requests with different
values for the Accept-Language HTTP header.
C#
protected void Page_Load(object sender, EventArgs e)
{
Response.Cache.SetExpires(DateTime.Now.AddMinutes(1d));
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.SetValidUntilExpires(true);
Response.Cache.VaryByHeaders["Accept-Language"] = true;
}

VB
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles M
e.Load
Response.Cache.SetExpires(DateTime.Now.AddMinutes(1.0))
Response.Cache.SetCacheability(HttpCacheability.Public)
Response.Cache.SetValidUntilExpires(True)
Response.Cache.VaryByHeaders("Accept-Language") = true
End Sub

Note
If you want to vary the cached content by multiple headers, you need to set multiple values in the VaryByHeaders pro
perty. If you want to vary by all headers, set VaryByHeaders["VaryByUnspecifiedParameters"] to true.
See Also
Tasks
How to: Set the Cacheability of an ASP.NET Page Declaratively
How to: Set a Page's Cacheability Programmatically
How to: Cache Versions of a Page Using Requesting Browser
How to: Cache Versions of a Page Using Parameters
How to: Cache Versions of a Page Using Custom Strings
Concepts
Caching ASP.NET Pages
Setting the Cacheability of a Page
Caching Multiple Versions of a Page
ASP.NET

How to: Cache Versions of a Page Using Custom Strings


In addition to varying the output cache by browser type and parameters, you can cache multiple versions of page output based
on different strings returned by a method that you define.
When you cache pages based on custom strings, you first specify an identifier for the custom string to use. You then create a
method in the application's Global.asax file that accepts the identifier and returns a value to vary the output cache by.
To cache multiple versions of page output based on custom strings
1. In the ASP.NET page, include an @ OutputCache directive with the required Duration and VaryByParam attributes. The
Duration attribute must be set to an integer greater than zero. If you do not want to use the functionality provided by
the VaryByParam attribute, you must set its value to "None".
2. To set the custom string declaratively, in the @ OutputCache directive, include the VaryByCustom attribute that is set to
the string that you want to vary the output cache by.
The following directive varies the page output by the custom string "minorversion".

<%@ OutputCache Duration="10" VaryByParam="None" VaryByCustom="minorversion" %>

3. To set the custom string programmatically, call the SetVaryByCustom method and pass it the custom string to use.
The following code example shows how to set the custom string to "minorversion".
C#
Response.Cache.SetVaryByCustom("minorversion");

VB
Response.Cache.SetVaryByCustom("minorversion")

Note
If you attempt to set the custom string both programmatically and declaratively, you will get an
InvalidOperationException. You need to choose one approach or the other.

4. In the application's Global.asax file, override the GetVaryByCustomString method to specify the behavior of the output
cache for the custom string.
As its arg parameter, the overridden method accepts the string that you set in the VaryByCustom attribute or in the
SetVaryByCustom method. For example, you might have pages that are cached by the minor version of the requesting
browser. For these pages you can set the VaryByCustom attribute to "minorversion". Then, in the overridden
GetVaryByCustomString method, you can check the arg parameter and return different strings depending on whether
the value of the arg parameter is "minorversion".
The following code example shows a Global.asax file with an override of the GetVaryByCustomString method.
C#
<%@ Application language="C#" %>
<script runat="server">
public override string GetVaryByCustomString(HttpContext context,
string arg)
{
if(arg == "minorversion")
{
return "Version=" +
context.Request.Browser.MinorVersion.ToString();
}
return base.GetVaryByCustomString(context, arg);
}
</script>

VB
<script runat="server">
Public Overrides Function GetVaryByCustomString(context _
As HttpContext, arg As String) As String
If (arg = "minorversion") Then
Return "Version=" & _
context.Request.Browser.MinorVersion.ToString()
return base.GetVaryByCustomString(context, arg);
End Function
</script>

See Also
Tasks
How to: Set the Cacheability of an ASP.NET Page Declaratively
Concepts
Caching ASP.NET Pages
Setting the Cacheability of a Page
Caching Multiple Versions of a Page
ASP.NET

Caching Portions of an ASP.NET Page


Sometimes it is impractical to cache an entire page because portions of the page might need to change on each request. In
those cases, you can cache just a portion of a page. There are two options to do this: control caching and post-cache
substitution.
In control caching, also known as fragment caching, you can cache parts of the page output by creating user controls to contain
the cached content and then marking the user controls as cacheable. This allows specific content within a page to be cached,
while the overall page is recreated each time. For example, if you create a page that displays largely dynamic content, such as
stock information, but also has sections that are static, such as weekly summaries, you can create the static sections in user
controls and configure the user controls to be cached.
Post-cache substitution is the opposite. The page is cached, but fragments within the page are dynamic and should therefore
not be cached. For example, if you create a page that is entirely static for set periods of time such as a page of news stories, you
can set the entire page to be cached. If you added rotating ad banners to the cached page, they would not change between
page requests. However, with post-cache substitution, the page can be cached, but you can mark specific parts as non-
cacheable. In the example, you would mark your ad banners as non-cacheable. They would then be dynamically created for
each page request and added to the cached page output. For more information on post-cache substitution, see
Dynamically Updating Portions of a Cached Page.
Control Caching
Creating user controls to cache content allows you to separate portions of a page that take valuable processor time to create,
such as database queries, from other parts of the page. The parts of the page that require fewer server resources can be
generated dynamically for each request.
Once you identify the portions of the page that you want to cache and create the user controls that contain each of those
portions, you must determine the caching policies for the user controls. You can set these policies declaratively using the
@ OutputCache directive, or by using the PartialCachingAttribute class in the code for the user control.
For example, if you include the following directive at the top of a user control file (.ascx file), a version of the control is stored in
the output cache for 120 seconds.

<%@ OutputCache Duration="120" VaryByParam="None" %>

If you want to set caching parameters in code, you can use an attribute in the user control's class declaration. For example, if
you include the following attribute in the metadata of your class declaration, a version of the content in the output cache is
stored for 120 seconds:
C#
[PartialCaching(120)]
public partial class CachedControl : System.Web.UI.UserControl
{
// Class Code
}

VB
<PartialCaching(120)> _
Partial Class CachedControl
Inherits System.Web.UI.UserControl
' Class Code
End Class

For more information on the attributes that you can set on page output, see the @ OutputCache topic. For more information
on how to develop user controls, see ASP.NET Web Server Controls Overview.
Note
Because you can nest user controls on a page, you can also nest user controls that have been placed in the output cache. You
can specify different cache settings for the page and for nested user controls.
Referencing Cached User Controls Programmatically
When creating a cacheable user control declaratively, you can include an ID attribute in order to programmatically reference
that instance of the user control. However, before referencing the user control in code, you must verify the existence of the user
control in the output cache. A user control that is cached is dynamically generated only for the first request; any subsequent
requests are satisfied from the output cache until the specified time expires. After you determine that the user control has been
instantiated, you can programmatically manipulate the user control from the containing page. For example, if you declaratively
assign a user control an ID of SampleUserControl, you can check for its existence with the following code:
C#
protected void Page_Load(object sender, EventArgs e)
{
if (SampleUserControl != null)
// Place code manipulating SampleUserControl here.
}

VB
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
If SampleUserControl <> Nothing Then
' Place code manipulating SampleUserControl here.
End If
End Sub

Caching the Page and User Controls for Different Durations


You can set different output cache duration values for a page and for user controls on the page. If the page output cache
duration is longer than the user control output cache duration, the page output cache duration takes precedence. For example,
if page output caching is set to 100 seconds and the user control output caching is set to 50 seconds, the entire page, including
the user control, is stored in the output cache for 100 seconds, regardless of the shorter setting for the user control.
The following code example shows the effect of a longer cache duration in the page than in a user control. The page is
configured to be cached for 100 seconds.
C#
<%@ Page language="C#" %>
<%@ Register tagprefix="SampleControl" tagname="Time" src="uc01.ascx" %>
<%@ OutputCache duration="100" varybyparam="none" %>

<SampleControl:Time runat="server" /><br /> <br /> <br />

This page was most recently generated at:<p>


<% DateTime t = DateTime.Now.ToString();
Response.Write(t); %>

VB
<%@ Page language="VB" %>
<%@ Register tagprefix="SampleControl" tagname="Time" src="uc01.ascx" %>
<%@ OutputCache duration="100" varybyparam="none" %>

<SampleControl:Time runat="server" /><br /> <br /> <br />

This page was most recently generated at:<p>


<% Dim t As DateTime = DateTime.Now.ToString()
Response.Write(t) %>

The following code example shows the user control included in the page. The cache duration for the control is set to 50
seconds.
C#
<% @Control language="C#" %>
<% @OutputCache duration="50" varybyparam="none" %>
This user control was most recently generated at:<p>
<% DateTime t = DateTime.Now.ToString();
Response.Write(t); %>

VB
<% @Control language="VB" %>
<% @OutputCache duration="50" varybyparam="none" %>

This user control was most recently generated at:<p>


<% Dim t As DateTime = DateTime.Now.ToString()
Response.Write(t) %>

If the page output cache duration is less than that of a user control, the user control will be cached until its duration has
expired, even after the remainder of the page is regenerated for a request. For example, if page output caching is set to 50
seconds and the user control's output caching is set to 100 seconds, the user control expires once for every two times the rest
of the page expires.
The following code shows the markup for a page that contains the user control with a longer cache duration than that of the
page. The page is configured to be cached for 50 seconds.
C#
<%@ Page language="C#" %>
<%@ Register tagprefix="SampleControl" tagname="Time" src="uc2.ascx" %>
<%@ OutputCache duration="50" varybyparam="none" %>

<SampleControl:Time runat="server" /><br /> <br /> <br />

This page was most recently generated at:<p>


<% DateTime t = DateTime.Now.ToString();
Response.Write(t); %>

VB
<%@ Page language="VB" %>
<%@ Register tagprefix="SampleControl" tagname="Time" src="Uc2.ascx" %>
<%@ OutputCache duration="50" varybyparam="none" %>

<SampleControl:Time runat="server" /><br /> <br /> <br />


This page was most recently generated at:<p>
<% Dim t As DateTime = DateTime.Now.ToString()
Response.Write(t) %>

The following code shows the user control included in the page. The cache duration for the control is set to 100 seconds.
C#
<% @Control language="C#" %>
<% @OutputCache duration="100" varybyparam="none" %>

This user control was most recently generated at:<p>

<% DateTime t = DateTime.Now.ToString();


Response.Write(t); %>

VB
<% @Control language="VB" %>
<% @OutputCache duration="100" varybyparam="none" %>

This user control was most recently generated at:<p>


<% Dim t As DateTime = DateTime.Now.ToString()
Response.Write(t) %>

See Also
Concepts
ASP.NET Caching Overview
Dynamically Updating Portions of a Cached Page
Caching Multiple Versions of a Page
Caching Application Data
What's New in ASP.NET Caching
Cache Configuration in ASP.NET
ASP.NET

Caching Multiple Versions of User Control Output


Just as you can vary the versions of a page that are output-cached, you can output cache regions of a page with user controls.
You can do this by varying the user control output by the control's name and the GET query string or form POST parameter
values, or by varying the output by parameter values alone. You can also cache multiple versions of a user control on a page by
declaring it more than once in its containing .aspx file. You can use any of these techniques, whether you specify output
caching for the user control with the @ OutputCache directive in the .ascx file or with the PartialCachingAttribute attribute
when you develop the user control in a code-behind class.
The @ OutputCache directive for user controls supports four attributes, VaryByParam, VaryByCustom, VaryByControl, and
Shared. The PartialCachingAttribute class includes four properties, VaryByParams, VaryByControls, VaryByCustom, and
Shared, that allow you to use the same techniques by adding an attribute to a user control in a code-behind class.
When an ASP.NET page that contains a user control with output cache settings is first requested, an instance of the control's
output is saved to memory. By default, each page that contains the same user control will add another instance of the control's
output to memory when it is requested.
For example, if you created a user control named Sample.ascx with output-cache settings and added Sample.ascx to twenty-
five ASP.NET pages in your application, there would be at least that many versions of Sample.ascx stored in the output cache.
In addition, if you use the VaryByControl, VaryByCustom, or VaryByParam attribute to modify the caching behavior of the
user control, there could be many more versions of user control output in the cache. For example, assume that you include a
TextBox Web server control in your user control and set its ID property to MyTextBox. If you set the VaryByControl attribute to
MyTextBox, there will be a version of user control output stored in the cache for every value that the MyTextBox control receives.

If the same user control is used in multiple pages within the same application, you can save memory by setting the Shared
attribute of the user control's @ OutputCache directive to true, or by setting the Shared property on the control's
PartialCachingAttribute attribute to true. This means that each page will access the same instance of user control output.
Using the Shared property in commonly used and frequently cached user controls can save a significant amount of memory.
There is a major difference between adding user-control output to the output cache and doing the same for page output. While
the output cache for both supports using GET query string and form POST parameters to create and cache multiple versions of
output, user controls do not support caching based on HTTP headers.
There are four techniques you can use to vary output-cached user controls:
You can use the VaryByParam attribute or the VaryByParams property of the PartialCachingAttribute class, which
provide the same functionality as that provided for page output caching. You can set either to any string, but you need to
make it equal to the GET query string or form POST parameters that are associated with the user control you create.
You can use the VaryByControl attribute or the VaryByControls property of the PartialCachingAttribute class to vary
the output-cached user control according to the ID property of an ASP.NET server control contained by the user control.
You can use the VaryByCustom attribute or the VaryByCustom property of the PartialCachingAttribute class to
define code for a custom string that you want to vary the cached user control output by. This works in the same manner
as the VaryByControl attribute technique for varying page output caching. For more information, see
How to: Cache Versions of a Page Using Custom Strings.
You can include multiple instances of a user control in an ASP.NET page. Unless you set the Shared attribute of the
@ OutputCache directive to true, output for each instance of the control will be cached.
For more information on each of these topics, see How to: Cache Multiple Versions of a User Control Based on Parameters and
How to: Cache Multiple Versions of a User Control by Using Declarative Attributes.
See Also
Tasks
How to: Cache Multiple Versions of a User Control Based on Parameters
How to: Cache Multiple Versions of a User Control by Using Declarative Attributes
Concepts
ASP.NET Caching Overview
What's New in ASP.NET Caching
Caching ASP.NET Pages
Caching Multiple Versions of a Page
ASP.NET

How to: Cache Multiple Versions of a User Control Based on


Parameters
You can vary caching of user-control output in two ways:
Specify the user control name along with either a query string or a form POST parameter. You can do this declaratively
using the VaryByParam attribute of the @ OutputCache directive. Alternatively, you can do it programmatically by setting
VaryByParams property in the PartialCachingAttribute in the user control's code.
Specify the ID property of an ASP.NET server control contained in the user control. You can do this declaratively using the
VaryByControl attribute. Alternatively, you can do it programmatically by setting the VaryByControls property in the
PartialCachingAttribute.
Note
Varying user control output to the cache based on query string or form POST parameters will work only if the user con
trol posts back and processes the postback itself. If the user control posts back to the containing page, this type of user
control output caching will not function properly.

To cache multiple versions of a user control declaratively using the VaryByControl attribute
1. Create a user control that posts back.
2. In the user control, include an @ OutputCache directive with Duration and VaryByControl attributes.
Note
If you use the VaryByControl attribute in the directive, you do not need to also include the VaryByParam attribute, alt
hough you can include it and set it to "None".

3. Set the VaryByControl attribute to the ID of a control that you want to vary the user control output by.
For example, the following @ OutputCache directive sets the user control's expiration to 60 seconds and varies the
control's output by an ASP.NET server control with ID of State:

<%@ OutputCache Duration="60" VaryByControl="State" %>

To cache multiple versions of a user control programmatically using the VaryByControls property
1. In code, create a user control code that posts back to itself.
2. Include a PartialCachingAttribute at the beginning of the user control code.
3. Include a value for the Duration parameter and set the VaryByControls parameter to the ID of the ASP.NET server
control in the user control that you want to vary the user control output by.
The following code example sets Duration to 60 seconds and VaryByControls to State. This code should be included
before the code that extends the UserControl class.
C#
[PartialCaching(60, null, State, null)]

VB
<PartialCaching(60, null, State, null)>

To cache multiple versions of a user control declaratively using the VaryByParam attribute
1. Create a user control that posts back to itself.
2. In the user control, include an @ OutputCache directive with Duration and VaryByParam attributes.
Note
If you include the VaryByControl attribute in the @ OutputCache directive for a user control, you do not need to also i
nclude the VaryByParam attribute.

3. Set the VaryByParam attribute to the GET query string or form POST parameter that you want to vary the user control
by.
For example, the following @ OutputCache directive sets expirations for the user control to 60 seconds and varies the
control's output by a the value of a form POST or query string parameter named State.

<%@ OutputCache Duration="60" VaryByParam="State" %>

To cache multiple versions of a user control programmatically using the VaryByParams property
1. In code, create a user control code that posts back to itself.
2. Include a PartialCachingAttribute at the beginning of the user control code.
3. Include a value for the Duration parameter and set the VaryByParams parameter to the GET query string or form POST
parameter that you want to vary the user control output by.
The following code example sets Duration to 60 seconds and VaryByParams to a form POST or query string parameter
named State. This code should be included before the code that extends the UserControl class.
C#
[PartialCaching(60, State, null, null)]

VB
<PartialCaching(60, State, null, null)>

See Also
Tasks
How to: Cache Multiple Versions of a User Control by Using Declarative Attributes
Concepts
ASP.NET Caching Overview
What's New in ASP.NET Caching
Caching ASP.NET Pages
Caching Multiple Versions of a Page
Caching Multiple Versions of User Control Output
ASP.NET

How to: Cache Multiple Versions of a User Control by Using


Declarative Attributes
You can cache multiple versions of a user control by simply declaring it in an .aspx file more than once. As with user controls
that are not cached, you can include a cached user control in an ASP.NET page as many times as needed for your application.
Unless you set the Shared property to true for the user control, multiple versions of the control output will be stored in the
cache.
To cache multiple versions of a user control by using declarative attributes
1. Using either the @ OutputCache directive in an .ascx file or the PartialCachingAttribute in the code-behind class, specify
the output cache settings for the user control.
The following @ OutputCache declaration will cache the control for 120 seconds:

<%@ OutputCache Duration="120" VaryByParam="None" %>

2. Include multiple versions of the user control in a page, including the property you defined in the class as an attribute in
the element. Make sure the property values are unique on the page.
Simply including the @ OutputCache directive with a valid duration value in the .ascx file or setting the
PartialCachingAttribute in the code-behind class allows varied cache output of a user control.
See Also
Tasks
How to: Cache Multiple Versions of a User Control Based on Parameters
Concepts
ASP.NET Caching Overview
What's New in ASP.NET Caching
Caching ASP.NET Pages
Caching Multiple Versions of a Page
Caching Multiple Versions of User Control Output
ASP.NET

Dynamically Updating Portions of a Cached Page


Caching a page can dramatically increase the performance of a Web application. However, in some cases you need most of the
page to be cached and some fragments within the page to be dynamic. For example, if you create a page of news stories that is
entirely static for set periods of time, you can set the entire page to be cached. If you wanted to include a rotating ad banner
that changed on every page request, then the part of the page containing the advertisement needs to be dynamic.
To allow you to cache a page but substitute some content dynamically, you can use ASP.NET post-cache substitution. With
post-cache substitution, the entire page is output cached with specific parts marked as exempt from caching. In the example of
the ad banners, the AdRotator control allows you to take advantage of post-cache substitution so that ads dynamically created
for each user and for each page refresh.
There are three ways to implement post-cache substitution:
Declaratively, using the Substitution control.
Programmatically, using the Substitution control API.
Implicitly, using the AdRotator control.
Substitution Control
The ASP.NET Substitution control specifies a section of a cached page that is created dynamically rather than cached. You
place a Substitution control at the location on the page where you want the dynamic content to appear.
At run time, the Substitution control calls a method that you specify with the MethodName property. The method must return
a string, which then replaces the content of the Substitution control. The method must be a static method on the containing
Page or UserControl control.
Using the substitution control causes client-side cacheability to be changed to server cacheability, so that the page will not be
cached on the client. This ensures that future requests to the page call the method again to generate dynamic content.
Substitution API
To create dynamic content for a cached page programmatically, you can call the WriteSubstitution method in your page code,
passing it the name of a method as a parameter. The method that handles the creation of the dynamic content takes a single
HttpContext parameter and returns a string. The return string is the content that will be substituted at the given location. An
advantage of calling the WriteSubstitution method instead of using the Substitution control declaratively is that you can call
a method of any arbitrary object, rather than calling a static method of the Page or the UserControl object.
Calling the WriteSubstitution method causes client-side cacheability to be changed to server cacheability, so that the page
will not be cached on the client. This ensures that future requests to the page call the method again to generate dynamic
content.
AdRotator Control
The AdRotator server control implements support for post-cache substitution internally. If you place an AdRotator control on
your page, it will render unique advertisements on each request, regardless of whether the parent page is cached. As a result, a
page that includes an AdRotator control is only cached server-side.
See Also
Concepts
ASP.NET Caching Overview
Caching ASP.NET Pages
Caching Multiple Versions of a Page
Caching Portions of an ASP.NET Page
Caching Application Data
Caching in ASP.NET with the SqlCacheDependency Class
ASP.NET

Caching in ASP.NET with the SqlCacheDependency Class


ASP.NET allows you to use the SqlCacheDependency class to create a cache item dependency on a table or row in a database.
When a change occurs in the table or in a specific row, the item that has a dependency is invalidated and removed from the
cache. You can set a dependency on a table in Microsoft SQL Server 7.0, SQL Server 2000, and SQL Server 2005. If you are
using SQL Server 2005 you can also set a dependency on a specific record.
Using caching with a SQL dependency can dramatically increase application performance in certain scenarios. For example,
imagine you are building an e-commerce application that displays product information from a database. Without caching, your
application must request the data from the database each time a user wants to view a product. You could cache the product
information for a day at a time, ensuring fast response times because the product information is already in memory. However,
if product information changes, the cached product information might then be out of sync with the data for up to a day.
Using SQL cache dependency, you could cache your product information and create a dependency on a database table or row
change. When the data changes—and only then—the cache items based on that data are invalidated and removed from the
cache. The next time you request that item from the cache, if it is not in the cache, you can re-add the updated version to the
cache and be assured that you have the latest data.
SQL cache dependency is also available for the page output cache. For example, you could create a page named
ViewProduct.aspx that shows information about a particular product. You could set that page's cache policy to be a SQL
dependency as you would for an item you added manually to the cache. The page would then be stored in the cache until the
table or row that it was dependent on changed. When the data changed, the page would be recreated and stored in the output
cache again.
For more information see ASP.NET Caching Overview.
Features
ASP.NET SQL cache dependency offers the following features:
You can use SQL cache dependency for both the application cache and the page output cache.
You can use SQL cache dependency with SQL Server 7.0 and later versions.
You can use SQL cache dependency in a Web garden (multiple processors on one server) or a Web farm (multiple
servers running the same application).
The database operations associated with SQL cache dependency are simple and therefore do not incur a heavy
processing cost on the server.
You do not need extensive SQL knowledge to configure SQL cache dependency in your application and in SQL Server.
ASP.NET includes tools that automate the configuration. Additionally, you can use the SqlCacheDependencyAdmin class
to programmatically configure SQL cache dependency.
SQL Server 7.0 and SQL Server 2000 Implementation
ASP.NET implements a poll model for SQL Server 7.0 and SQL Server 2000 cache dependency. A thread within the ASP.NET
process polls the SQL Server database at a specified time interval to determine whether the data has changed. If so, dependent
cache items are invalidated and removed from the cache. You can specify the poll interval in your application declaratively in
the Web.config file or programmatically using the SqlCacheDependency class.
SQL cache dependency is limited to data changes at the table level for SQL Server 7.0 and SQL Server 2000. You can configure
ASP.NET to poll the database for changes in a table, but not in a specific row.
Enabling SQL Caching
In order to use SQL cache dependency in SQL Server 7.0 and SQL Server 2000, you must configure SQL Server to support it.
ASP.NET provides utilities to configure SQL caching on SQL Server, including a tool named Aspnet_regsql.exe and the
SqlCacheDependencyAdmin class. For more information on enabling SQL cache dependency with SQL Server see
How to: Cache Page Output with Cache Key Dependencies.
SQL Server 2005 Implementation
SQL Server 2005 implements a different model for cache dependency than SQL Server 7.0 and SQL Server 2000. You do not
need to go through any special configuration steps to enable SQL cache dependency on SQL Server 2005. Additionally, SQL
Server 2005 implements a change notification model where notifications are sent to subscribing application servers, rather
than relying on the polling model required in earlier versions of SQL Server.
SQL Server 2005 cache dependency is more flexible in the types of changes that receive notification. SQL Server 2005
monitors changes to the result set of a particular SQL command. If a change occurs in the database that would modify the
results set of that command, the dependency causes the cached item to be invalidated. This allows SQL Server 2005 to provide
row-level notification.
There are some requirements for the query used to test for changes. You must provide fully qualified table names, including
the owner name (for example, dbo.authors). In general, SQL 2005 notification supports Select queries as well as stored
procedures, and supports multiple and nested queries, but does not support aggregate operations such as COUNT(*). For more
information about what queries are supported and the rules for notification in SQL Server 2005, see the SQL Books Online
topic named "Creating a Query for Notification."
Configuring SQL Caching in ASP.NET Application
Once you have configured SQL Server 7.0 or SQL Server 2000 for cache dependencies, or have created the appropriate
command dependency in SQL Server 2005, you can configure your application to use SQL cache dependency just as you
would configure any other cache dependency. For example, you can create a cache profile in the Web.config file and then
reference that cache profile on each page that should use the SQL cache dependency. You could also use SQL cache
dependency by enabling it programmatically using the SqlCacheDependency class. For more information, see
How to: Cache Page Output with Cache Key Dependencies.
See Also
Tasks
How to: Cache Page Output with File Dependencies
Concepts
ASP.NET Caching Overview
What's New in ASP.NET Caching
Cache Configuration in ASP.NET
Visual Web Developer

Walkthrough Topics — ASP.NET Caching (Visual Studio)


The following walkthrough topics demonstrate how to implement caching with your Web pages.
Walkthrough Topics
Walkthrough: Using Output Caching to Enhance Web Site Performance
Walkthrough: Using ASP.NET Output Caching with SQL Server
See Also
Other Resources
ASP.NET Caching (Visual Studio)
Visual Web Developer

How-to Topics — ASP.NET Caching (Visual Studio)


The following step-by-step procedures describe how to implement caching with your Web pages.
How-to Topics
How to: Set the Cacheability of an ASP.NET Page Declaratively
How to: Set a Page's Cacheability Programmatically
How to: Set Expiration Values for ASP.NET Page Caching
How to: Check the Validity of a Cached Page
How to: Cache Page Output with File Dependencies
How to: Cache Page Output with Cache Key Dependencies
How to: Add Items to the Cache
How to: Retrieve Values of Cached Items
How to: Delete Items from the Cache in ASP.NET
How to: Notify an Application When an Item Is Removed from the Cache
How to: Cache Versions of a Page Using Requesting Browser
How to: Cache Versions of a Page Using Parameters
How to: Cache Versions of a Page Using HTTP Headers
How to: Cache Versions of a Page Using Custom Strings
How to: Cache Multiple Versions of a User Control Based on Parameters
How to: Cache Multiple Versions of a User Control by Using Declarative Attributes
See Also
Other Resources
ASP.NET Caching (Visual Studio)
Visual Web Developer

ASP.NET Web Server Controls (Visual Studio)


ASP.NET Web server controls are objects on ASP.NET Web pages that run when the page is requested and render markup to a
browser. Many Web server controls are similar to familiar HTML elements, such as buttons and text boxes. Other controls,
however, encompass complex behavior, such as a calendar controls or controls that manage data connections.
The topics in this section describe what ASP.NET Web server controls are and how to work with them. The section also contains
information about all built-in ASP.NET Web server controls and how you can create your own controls.
In This Section
Working with Web Server Controls
Provides information on how to add ASP.NET server controls to pages; how to configure their properties, behavior, and
appearance; and how to work with them programmatically.
Individual Web and HTML Controls
Provides details about built-in ASP.NET server controls.
Custom Web Server Controls
Provides information about creating your own ASP.NET server controls.
Related Sections
Guided Tour of Creating Web Sites in Visual Web Developer
Provides links to tutorials on all aspects of creating ASP.NET Web sites and ASP.NET Web pages.
Visual Web Developer

Working with Web Server Controls


The topics in this section provide general information on ASP.NET Web server controls, including what they are, how they
work, and how to program them to create dynamic Web pages.
In This Section
Getting Started — Working with Web Server Controls
Learning More — Working with Web Server Controls
Walkthrough Topics — Working with Web Server Controls
How-to Topics — Working with Web Server Controls
See Also
Other Resources
ASP.NET Web Server Controls (Visual Studio)
ASP.NET Web Pages (Visual Studio)
Visual Web Developer

Getting Started — Working with Web Server Controls


The topics in this section provide essential information on ASP.NET Web server controls, including what they are and how they
work, and how to add them to ASP.NET Web pages.
In This Section
ASP.NET Web Server Controls Overview
Tab Order, Focus, and Access Keys in ASP.NET Web Server Controls
See Also
Other Resources
Working with Web Server Controls
ASP.NET Web Server Controls (Visual Studio)
ASP.NET Web Pages (Visual Studio)
ASP.NET

ASP.NET Web Server Controls Overview


When you create ASP.NET Web pages, you can use these types of controls:
HTML server controls HTML elements exposed to the server so you can program them. HTML server controls expose
an object model that maps very closely to the HTML elements that they render.
Web server controls Controls with more built-in features than HTML server controls. Web server controls include not
only form controls such as buttons and text boxes, but also special-purpose controls such as a calendar, menus, and a
tree view control. Web server controls are more abstract than HTML server controls in that their object model does not
necessarily reflect HTML syntax.
Validation controls Controls that incorporate logic to enable you to what users enter for input controls such as the
TextBox control. Validation controls enable you to check for a required field, to test against a specific value or pattern of
characters, to verify that a value lies within a range, and so on. For more information, see Validation ASP.NET Controls.
User controls Controls that you create as ASP.NET Web pages. You can embed ASP.NET user controls in other ASP.NET
Web pages, which is an easy way to create toolbars and other reusable elements. For more information, see
ASP.NET User Controls.
Note
You can also create output for mobile devices. To do so, you use the same ASP.NET page framework, but you create Mo
bile ASP.NET Web pages instead of ASP.NET Web pages and use controls specifically designed for mobile devices. For
details, see Creating ASP.NET Mobile Web Pages.

You can use all types of controls on the same page. The following sections provide more detail about ASP.NET server controls.
Note
In some situations, server controls require client script in order to function properly. If a user has disabled scripting in the bro
wser, the controls might not function as you intend. For details, see ASP.NET Web Server Controls and Browser Capabilities.

HTML Server Controls


HTML server controls are HTML elements (or elements in other supported markup, such as XHTML) containing attributes that
make them programmable in server code. By default, HTML elements on an ASP.NET Web page are not available to the server.
Instead, they are treated as opaque text and passed through to the browser. However, by converting HTML elements to HTML
server controls, you expose them as elements you can program on the server.
The object model for HTML server controls maps closely to that of the corresponding elements. For example, HTML attributes
are exposed in HTML server controls as properties.
Any HTML element on a page can be converted to an HTML server control by adding the attribute runat="server". During
parsing, the ASP.NET page framework creates instances of all elements containing the runat="server" attribute. If you want to
reference the control as a member within your code, you should also assign an id attribute to the control.
The page framework provides predefined HTML server controls for the HTML elements most commonly used dynamically on a
page: the form element, the input elements (text box, check box, Submit button), the select element, and so on. These
predefined HTML server controls share the basic properties of the generic control, and in addition, each control typically
provides its own set of properties and its own event.
HTML server controls offer the following features:
An object model that you can program against on the server using familiar object-oriented techniques. Each server
control exposes properties that enable you to manipulate the control's markup attributes programmatically in server
code.
A set of events for which you can write event handlers in much the same way you would in a client-based form, except
that the event is handled in server code.
The ability to handle events in client script.
Automatic maintenance of the control's state. When the page makes a round trip to the server, the values that the user
entered into HTML server controls are automatically maintained and sent back to the browser.
Interaction with ASP.NET validation controls so you can verify that a user has entered appropriate information into a
control.
Data binding to one or more properties of the control.
Support for styles if the ASP.NET Web page is displayed in a browser that supports cascading style sheets.
Pass-through of custom attributes. You can add any attributes you need to an HTML server control and the page
framework will render them without any change in functionality. This enables you to add browser-specific attributes to
your controls.
For details about how to convert an HTML element to an HTML server control, see
How to: Add HTML Server Controls to a Web Page Using ASP.NET Syntax.
Web Server Controls
Web server controls are a second set of controls designed with a different emphasis. They do not necessarily map one-to-one
to HTML server controls. Instead, they are defined as abstract controls in which the actual markup rendered by the control can
be quite different from the model that you program against. For example, a RadioButtonList Web server control might be
rendered in a table or as inline text with other markup.
Web server controls include traditional form controls such as buttons and text boxes as well as complex controls such as tables.
They also include controls that provide commonly used form functionality such as displaying data in a grid, choosing dates,
displaying menus, and so on.
Web server controls offer all of the features described above for HTML server controls (except one-to-one mapping to
elements) and these additional features:
A rich object model that provides type-safe programming capabilities.
Automatic browser detection. The controls can detect browser capabilities and render appropriate markup.
For some controls, the ability to define your own layout for the control using Templates.
For some controls, the ability to specify whether a control's event causes immediate posting to the server or is instead
cached and raised when the page is submitted.
Support for themes, which enable you to define a consistent look for controls throughout your site. For details, see
ASP.NET Themes and Skins.
Ability to pass events from a nested control (such as a button in a table) to the container control.
The controls use syntax such as the following:

<asp:button attributes runat="server" id="Button1" />

The attributes in this case are not those of HTML elements. Instead, they are properties of the Web control.
When the ASP.NET Web page runs, the Web server control is rendered on the page using appropriate markup, which often
depends not only on the browser type but also on settings that you have made for the control. For example, a TextBox control
might render as an input tag or a textarea tag, depending on its properties.
Detailed how-to and reference documentation is available for each control separately. For more information, see
Individual ASP.NET Web Server Controls.
See Also
Other Resources
ASP.NET Web Server Controls
ASP.NET

What's New in Web Server Controls


ASP.NET 2.0 includes changes to Web server controls from previous versions as well as introducing numerous new controls
and features. This topic discusses both the
general changes to controls as well as new controls and changes to existing controls.
General Control Changes
Themes
You can now use themes to define a consistent look and feel for pages and controls. A theme is a set of elements, including
skins, cascading style sheets (CSS), and images, that can be applied to an individual control, a page, or a Web site. For more
information, see ASP.NET Themes and Skins Overview.
Validation
Validation controls expose a ValidationGroup property that enables you to specify discrete sets of validation controls that are
validated (or not validated) together. You can get references to all of the validation controls for a validation group by calling
the GetValidators method.
The Page class now includes an overload to the Validate method that takes a parameter that identifies a validation group. You
can call the overload that takes the validationGroup parameter to force validation for only that validation group, or the
overload that takes no parameters to force validation for all validation controls on the page.
Additionally, the Page class's IsValid property now considers validation controls only in the current validation group. The
current validation group is determined by the control that caused validation to occur. For example, if a button control is clicked
and causes validation for the LoginForm validation group, then the IsValid property will return true if all validation controls
whose ValidationGroup property is set to LoginForm are valid.
Validation controls also now have a SetFocusOnError property. If the property is true, when a validation error occurs, focus is
set to the control identified by the ControlToValidate property.
The CustomValidator class now has a ValidateEmptyText property. If the ValidateEmptyText property is true, the
CustomValidator object calls the client-side validation method identified by the ClientValidationFunction property and raises
the ServerValidate event even when the value that is being validated is an empty string.
For more information, see Validation ASP.NET Controls.
Data Binding
ASP.NET has a new data binding model that is built on data source controls. Data source controls connect to and retrieve data
from a variety of data sources including databases, business objects, and XML, and make the data available for other controls
to bind to, without requiring code. They can also support modifying data. Data-bound controls now include a DataSourceID
property that identifies the data source control to bind to. For more information, see Data Source Controls Overview.
Additionally, list controls such as the ListBox and DropDownList controls now expose an AppendDataBoundItems property;
when this property is set to true, the control combines statically defined list items with items dynamically added by data
binding.
Client Callbacks
Several controls, including the TreeView control, support client callbacks, which enable the control to communicate with the
server without requiring a full postback.
For more information, see Implementing Client Callbacks Without Postbacks in ASP.NET Web Pages.
Standards Support
ASP.NET controls have been updated to support the XHTML standard as well as standards for accessible applications. For more
information, see ASP.NET and XHTML and Accessibility Support in ASP.NET.
New Controls
ASP.NET includes a number of new controls as listed in the following tables.
Standard Controls
BulletedList
Displays items as a bulleted list. Similar to other list controls such as the CheckBoxList or RadioButtonList controls, but
renders differently. Bullet style can be set to text, hyperlinks, button controls, and images. Like all list controls, the
BulletedList control can be populated using data binding.
For more information, see BulletedList Web Server Control Overview.
FileUpload
Manages file uploads using the HTML <input type="file"> element. Similar to the HtmlInputFile control, but supports
additional options for handling uploaded data, including saving it as a file or handling it as stream.
For more information, see FileUpload Web Server Control Overview.
HiddenField
Manages hidden form fields using the HTML <input type="hidden"> element. Similar to the HtmlInputHidden control, but
derives from the WebControl base class for added functionality.
For more information, see HiddenField Web Server Control Overview.
ImageField
Displays an image for each record displayed in data-bound controls, such as the GridView and DetailsView controls.
ImageMap, CircleHotSpot, PolygonHotSpot, RectangleHotSpot
Renders an HTML image map. When using the ImageMap control, you define an Image control, then define hotspots
(CircleHotSpot, PolygonHotSpot, or RectangleHotSpot objects) as child controls with appropriate sets of coordinates.
For each hotspot, you can specify a mode, such as Navigate or PostBack, and related properties, such as the NavigateUrl
property when in Navigate mode, or the PostBackValue property when in PostBack mode.
For more information, see ImageMap Web Server Control Overview.
Menu
Used to display a menu in an ASP.NET Web page. Often used in combination with a SiteMapDataSource control for creating
Web site navigation.
For information on site navigation, see ASP.NET Site Navigation Overview.
MultiView, View
Generates multi-panel displays where you can conditionally render different views. The MultiView control is the parent
control for which you define two or more View controls as children. The View controls contain markup and controls that
make up each panel of the display.
Note
For multi-panel displays that walk a user through a specific task, you might want to use the Wizard control instead.

For more information on the MultiView and View controls, see MultiView and View Web Server Controls Overview.
SiteMapPath
Creates a view of a portion of a site's navigation (a "bread crumb") based on information in a site map.
For information on site navigation, see ASP.NET Site Navigation Overview.
Substitution
Specifies a region on a page that can be dynamically filled even when the page has been cached. When using the
Substitution control, you define a callback method that returns the data to display.
For more information, see Substitution Web Server Control Overview.
TreeView
Displays hierarchical data, such as a table of contents or file directory, in a tree structure. The TreeView control can be bound
to a data source control such as an XmlDataSource or SiteMapDataSource control.
For more information, see TreeView Web Server Control Overview.
Wizard
Enables you to collect user input one step at a time and allows for either linear or nonlinear navigation through the steps.
For more information, see Wizard Web Server Control Overview.
Data Source Controls
ASP.NET now includes data source controls to support code-free data-binding scenarios. The following table describes the
built-in data source controls. For more details, see Data Source Web Server Controls.
AccessDataSource
Enables you to work with a Microsoft Access database. Supports sorting, filtering, and paging.
ObjectDataSource
Enables you to work with a business object or other class and create Web applications that rely on middle-tier objects to
manage data. Supports advanced sorting and paging scenarios unavailable with the other data source controls.
SiteMapDataSource
Enables navigation controls, such as a Menu control, to read ASP.NET site map information. For more information, see
ASP.NET Site Navigation Overview.
SqlDataSource
Enables you to work with Microsoft SQL Server, OLE DB, ODBC, or Oracle databases. When used with SQL Server, supports
advanced caching capabilities. Supports sorting, filtering, and paging.
XmlDataSource
Enables you to work with an XML file, especially for hierarchical ASP.NET server controls such as the TreeView or Menu
control. Supports filtering capabilities using XPath expressions and enables you to apply an XSLT transformation to the data.
The XmlDataSource allows you to update data by saving the entire XML document with changes.
Data-bound Controls
Data-bound controls can be bound to a data source control to make it easy to display and modify data in your Web application.
A data-bound control can bind to a tabular set of results such as a dataset or collection or to a single item in a table of results.
Note
Some controls, such as the TreeView, Menu, and SiteMapPath controls can bind to hierarchical data such as an XML file.

Data-bound controls that have shipped with previous releases of ASP.NET include the DataList, Repeater, and DataGrid
controls. The DataList and Repeater controls have been updated to bind to the new data source controls included with
ASP.NET. Although the DataGrid control is still available, is has been superseded by the GridView control.
The following table lists the new data-bound controls included with ASP.NET. For more information, see
ASP.NET Data-Bound Web Server Controls Overview.
GridView
Displays data as a table and provides the capability to sort columns, page through data, and edit or delete a single record.
The GridView control supersedes the DataGrid control from previous versions of ASP.NET. For more information, see
GridView Web Server Control.
DetailsView
Renders a single record at a time and provides the capability to page through data as well as to insert, update, and delete
records. The DetailsView control is often used in master-detail scenarios where the selected record in a master control such
as a GridView control determines the record displayed by the DetailsView control.
For more information, see DetailsView Web Server Control.
FormView
Renders a single record at a time from a data source, similar to the DetailsView control. However, the difference between
the FormView and the DetailsView controls is that the DetailsView control uses a tabular layout where each field of the
record is displayed as a row of its own. In contrast, the FormView control does not specify a pre-defined layout for
displaying a record. Instead, you create templates containing controls to display individual fields from the record. The
template contains the formatting, controls, and binding expressions used to create the form.
For more information, see FormView Web Server Control.
Login Controls
ASP.NET now includes login controls for use ASP.NET forms authentication and ASP.NET membership. The login controls
encapsulate much of the functionality required for an authenticated site, including allowing users to log in, displaying the
logged-in user name and related user information, creating a new user, and recovering or resetting a password, without
requiring code. Several of the login controls can be customized through the use of templates. The following table lists the login
controls with a brief description of each. For more information, see Login ASP.NET Controls.
Login
Displays a user interface for user authentication. By default, the Login control displays text boxes for the user name and
password and a check box that allows users to indicate whether the application should remember the user between visits.
LoginName
Displays a user's login name if the user has logged in using ASP.NET membership. Alternatively, if your site uses Integrated
Windows authentication, the control displays the user's Windows account name.
LoginStatus
Detects whether a user is logged in. If the user has not yet logged in, displays a login button that takes the user to a login
page. If the user is logged in, displays a logout button.
LoginView
Allows you to display a different user interface and templates based on user authentication and authorization (roles).
CreateUserWizard
Collects information for a new user and adds the user to the ASP.NET membership system.
ChangePassword
Allows users to change their password. (The control works only with ASP.NET membership, and does not allow user to
change their Windows password.)
PasswordRecovery
Allows user passwords to be retrieved based on the e-mail address that was used when the account was created. The
PasswordRecovery control sends an e-mail message containing a password to the user.
Changes to Existing Controls
Controls that were available in previous versions of ASP.NET have been updated with new functionality for data binding,
accessibility, and so on. The following table lists the controls and changes made to them for ASP.NET 2.0.
AdRotator
Supports the new data-binding model and can use data source controls for data retrieval (although this requires a specific
database schema). The AdRotator control implicitly supports post-cache substitution, meaning it will render unique
advertisements on each request, regardless of whether the page is cached.
For more information, see AdRotator Web Server Control Overview.
Button, ImageButton, LinkButton
Supports several new properties inherited from the Button base class.
The OnClientClick property identifies the name of a client-side method to invoke when the button is clicked but before a
postback occurs. In client script you can cancel the postback.
The PostBackUrl property allows you to post one ASP.NET page to another page by identifying the URL of the target page.
The UseSubmitBehavior property (available only for the Button control) enables you to specify whether to use the browser's
submit mechanism when submitting a page or to post the page using client-side script generated by ASP.NET.
Calendar
Exposes Caption and CaptionAlign properties that write a caption element into the rendered HTML table.
The Calendar control also now has a UseAccessibleHeader property. When this property is set to true, the Calendar control
renders day names in HTML table header (th) elements.
The DayRenderEventArgs object used with the DayRender event now includes a SelectUrl property. This returns the client
script that is normally used by the LinkButton control for rendering calendar days. You can use the SelectUrl property to
customize the format of day links.
For more information, see Calendar Web Server Control Overview.
CheckBox
Supports LabelAttributes and InputAttributes properties that enable you to specify custom attributes for the label and input
HTML elements that are rendered by the control, respectively.
For more information, see CheckBox and CheckBoxList Web Server Controls Overview.
CheckBoxList
Supports the new data-binding model and can make use of data source controls for data retrieval.
For more information, see CheckBox and CheckBoxList Web Server Controls Overview.
DataGrid
Supports the new data-binding model and uses data source controls. However, it is recommended that you use the
GridView control instead for tabular display of data. The GridView control provides improved support for data-binding
scenarios.
For more information on the GridView control, see GridView Web Server Control Overview and
Comparing the GridView and DataGrid Web Server Controls.
DropDownList
Supports the new data-binding model and can make use of data source controls for data retrieval.
For more information, see DropDownList Web Server Control Overview.
Image
Exposes a GenerateEmptyAlternateText property that ensures an empty alt attribute is included for the HTML image element
rendered by the control. This improves the accessibility of your application for users who use a screen reader.
For more information, see Image Web Server Control Overview.
Label
Exposes an AssociatedControlID property that enables you to link a Label control with another control on the page and act
as that control's caption. When users click the rendered HTML label element or use its access key, focus passes to the
associated control.
For more information, see Label Web Server Control Overview.
ListBox
Supports the new data-binding model and can make use of data source controls for data retrieval.
For more information, see ListBox Web Server Control Overview.
Literal
Exposes a Mode property that enables you to specify how the control treats HTML markup in its Text property. You can
encode the text, let the text pass through unchanged, or transform the text to remove unsupported markup elements for
non-HTML or XHTML browsers.
For more information, see Literal Web Server Control Overview.
Panel
Exposes a ScrollBars property that enables you to specify scrollbars for the panel.
Exposes a GroupingText property that you can set to a value that will be used as a title for a box rendered around the panel.
Exposes a DefaultButton property that allows you to specify a default button for the panel. When users press ENTER inside a
text box, the default button is invoked.
For more information, see Panel Web Server Control Overview.
RadioButtonList
Supports the new data-binding model and can make use of data source controls for data retrieval.
For more information, see RadioButton and RadioButtonList Web Server Controls Overview.
Table
Exposes Caption and CaptionAlign properties that render a caption element in the rendered HTML table. These properties
are available in any Web server control that inherently renders as a table, such as the Calendar and GridView controls.
TextBox
Supports the new AutoCompleteType property, which allows you to specify how the text box will retrieve values in a browser
that supports AutoComplete. By default, browsers that support AutoComplete index possible values for a text box based on
the ID of the control (the ID is used as the name of the HTML input element). The AutoCompleteType property allows you
to use the ID of the control (the default), specify a category of values for the control to use, or disable AutoComplete for the
control.
For more information on the AutoComplete feature in Internet Explorer, search for the
"Using AutoComplete in HTML Forms" topic on the MSDN Library Web site.
For more information on the TextBox control, see TextBox Web Server Control Overview.
See Also
Concepts
ASP.NET Web Server Controls Overview
Visual Web Developer

How to: Add Web Server Controls to a Web Forms Page Using
the Web Forms Designer
You add controls to an ASP.NET Web page much the same way you add any HTML element. You can either use a visual
designer and add a control from the toolbox, or you can type the element representing the control into the page's markup. This
topic covers using the designer. For information about creating controls using by typing markup, see
How to: Add Server Controls to an ASP.NET Web Page Using ASP.NET Syntax.
Note
You can also add controls programmatically at run time. For details, see
How to: Add Controls to an ASP.NET Web Page Programmatically.

To add a Web server control using the designer


1. Switch to Design view.
2. From the Standard tab of the Toolbox, drag the control onto the page.
A glyph ( ) appears on the control in Design view to indicate that it is a server-based control.
See Also
Tasks
How to: Add Controls to an ASP.NET Web Page Programmatically
Other Resources
ASP.NET Web Server Controls (Visual Studio)
ASP.NET

How to: Add Server Controls to an ASP.NET Web Page Using


ASP.NET Syntax
You can add a Web server control to a page by declaring it directly in the .aspx file.
Note
For background information about controls for ASP.NET Web pages, see ASP.NET Web Server Controls Overview

To add a control declaratively


1. If you are in a visual designer, switch to source-editing view.
2. Type the element representing the control into the .aspx file. The exact syntax you use depends on the control you are
adding, but in general the following applies:
Controls must include the attribute runat="server".
Set the control's ID attribute unless the control is part of a complex control and will be repeated (as in GridView,
FormView, DetailsView, Repeater, or DataList controls).
Web server controls are declared with an XML tag that references the asp namespace.
Control declarations must be properly closed. You can specify an explicit closing tag, or, if the control has no child
elements, you can specify a self-closing tag. The only exceptions are HTML input controls that cannot have child
elements, such as the input controls (for example, HtmlInputText Server Control Declarative Syntax,
HtmlImage Control, and HtmlButton Control).
Control properties are declared as attributes.
The following examples show typical declarations for Web server controls:
VB
<!-- Textbox Web server control -->
<asp:textbox id="TextBox1" runat="Server" Text=""></asp:textbox>

<!-- Same, but with self-closing element -->


<asp:textbox id="Textbox2" runat="Server" Text="" />

<!-- Web DropDownList control, which contains subelements -->


<asp:DropDownList id="DropDown1" runat="server">
<asp:ListItem Value="0">0</asp:ListItem>
<asp:ListItem Value="1">1</asp:ListItem>
<asp:ListItem Value="2">2</asp:ListItem>
<asp:ListItem Value="3">3</asp:ListItem>
</asp:DropDownList>

<asp:Repeater id="Repeater2" runat="server">


<HeaderTemplate>
Company data:
</HeaderTemplate>
<ItemTemplate>
<asp:Label ID="Label1" runat="server"
Font-Names="verdana" Font-Size="10pt"
Text='<%# Eval("Name") %>' />
( <asp:Label ID="Label2" runat="server"
Font-Names="verdana" Font-Size="10pt"
Text='<%# Eval("Ticker") %>'/>
)
</ItemTemplate>
<SeparatorTemplate>
,
</SeparatorTemplate>
</asp:Repeater>

C#
<!-- Textbox Web server control -->
<asp:textbox id="TextBox1" runat="Server" Text=""></asp:textbox>

<!-- Same, but with self-closing element -->


<asp:textbox id="Textbox2" runat="Server" Text="" />

<!-- Web DropDownList control, which contains subelements -->


<asp:DropDownList id="DropDown1" runat="server">
<asp:ListItem Value="0">0</asp:ListItem>
<asp:ListItem Value="1">1</asp:ListItem>
<asp:ListItem Value="2">2</asp:ListItem>
<asp:ListItem Value="3">3</asp:ListItem>
</asp:DropDownList>

<asp:Repeater id="Repeater2" runat="server">


<HeaderTemplate>
Company data:
</HeaderTemplate>
<ItemTemplate>
<asp:Label ID="Label1" runat="server"
Font-Names="verdana" Font-Size="10pt"
Text='<%# Eval("Name") %>' />
( <asp:Label ID="Label2" runat="server"
Font-Names="verdana" Font-Size="10pt"
Text='<%# Eval("Ticker") %>'/>
)
</ItemTemplate>
<SeparatorTemplate>
,
</SeparatorTemplate>
</asp:Repeater>

For information about the declarative syntax for a specific Web server control, see Web Server Control Syntax.
Note
If the page designer cannot render a Web server control correctly, it displays a gray box with the text "Error Creati
ng Control." This often means that the ASP.NET syntax of the control is incorrect — for example, if the runat="se
rver" attribute is missing in a Web server control element, you will see this error.

See Also
Tasks
How to: Set ASP.NET Server Control Style Properties Programmatically
How to: Set ASP.NET Server Control Style Properties Using ASP.NET Syntax
How to: Set HTML Server Control Properties Programmatically
Concepts
ASP.NET Web Server Controls Overview
Visual Web Developer

How to: Add HTML Server Controls to an ASP.NET Web Page


Using the Designer
Adding HTML server controls is like adding any HTML element, except that you convert the element to a server control so that
you can work with it in server code.
Note
For information about controls for Web Forms pages, see ASP.NET Web Server Controls Overview.

To add an HTML server control to an ASP.NET Web page using the designer
1. From the HTML tab of the Toolbox, drag an HTML element onto the page.
2. Convert the element to a control by right-clicking it and choosing Run As Server Control.
Visual Web Developer adds the attribute runat="server" to the element, which causes ASP.NET to treat the element as
a control. A glyph ( ) appears on the control in Design view to indicate that it is a server control.
For information about adding controls directly in the .aspx file, see
How to: Add HTML Server Controls to a Web Forms Page using ASP.NET Syntax.
See Also
Tasks
How to: Add Web Server Controls to a Web Forms Page Using the Web Forms Designer
How to: Add Controls to an ASP.NET Web Page Programmatically
How to: Convert HTML Server Controls to HTML Elements (Visual Studio)
How to: Set HTML Server Control Properties Programmatically
Other Resources
ASP.NET Web Server Controls (Visual Studio)
ASP.NET

How to: Add HTML Server Controls to a Web Page Using


ASP.NET Syntax
Adding HTML server controls is like adding any HTML element, except that you convert the element to a control so that you
can work with it in server code.
Note
For information about controls for ASP.NET Web pages, see Introduction to ASP.NET Server Controls.

You can add an HTML server control to a page by declaring it directly in the .aspx file.
To add an HTML server control
Type the HTML syntax of the element you want to use as a control. Include the normal HTML syntax for the element, and
in addition, do the following:
Set the control's ID attribute (property) to a unique value for that page, unless the control is part of a complex
control and will be repeated (as in Repeater, DataList, and GridView controls).
Set the runat="server" attribute to convert the element to a control.
The following example shows how to declare an HtmlInputText control, HtmlInputText control, an HtmlInputButton
control, and an HtmlAnchor control:
VB
<input id="Name" type="text" size="40" runat="server" />
<input type="submit" id="Enter" value="Enter" runat="server" />
Click <a id="Anchor1" runat="server" href="more.html">More </a> to see the next page.

C#
<input id="Name" type="text" size="40" runat="server" />
<input type="submit" id="Enter" value="Enter" runat="server" />
Click <a id="Anchor1" runat="server" href="more.html">More </a> to see the next page.

For information about the declarative syntax for a specific HTML server control, see HTML Server Controls.
See Also
Tasks
How to: Convert HTML Server Controls to HTML Elements (Visual Studio)
How to: Set HTML Server Control Properties Programmatically
Visual Web Developer

How to: Convert HTML Server Controls to HTML Elements


(Visual Studio)
If you no longer need to program an HTML server control in server code, you should convert it back to a plain HTML element.
Each HTML server control in a page uses resources, so it is a good practice to minimize the number of controls that the
ASP.NET page has to work with.
To convert an HTML server control to an HTML element
In Design view, right-click the control and clear the check mark next to Run As Server Control.
-or-
In Source view, remove the runat="server" attribute from the control's tag.
You do not have to remove the ID attribute. Be especially careful not to remove the ID attribute if there is client script that
references the element.
See Also
Tasks
How to: Add Controls to an ASP.NET Web Page Programmatically
How to: Add HTML Server Controls to an ASP.NET Web Page Using the Designer
How to: Set HTML Server Control Properties Programmatically
Visual Web Developer

How to: Set ASP.NET Server Control Properties (Visual Studio)


Setting a control's properties defines its appearance and behavior. This topic addresses how to set control properties at design
time using Visual Web Developer.
To set server controls properties in the designer
In Design view, select the control, and then set properties in the Properties window.
-or-
In Source view, place the insertion point in the element tag of the control, and then set properties in the Properties
window.
To set server controls properties using ASP.NET syntax
1. Switch to Source view.
2. In the control's markup element, set the attribute of the control declaration corresponding to the property you want.
Note
In Web server controls, the property names do not necessarily have the same names as HTML attributes; be sure you ar
e using the correct property name.

The following example sets the MaxLength property of an HtmlInputText control:

<input id="SampleTextBox" type=text runat=server maxlength="20" >

The following example sets the TextMode property of a TextBox control:

<asp:textbox text="" runat=Server TextMode="Multiline" />

See Also
Tasks
How to: Set HTML Server Control Properties Programmatically
Other Resources
Setting Web Server Control Properties Programmatically (Visual Studio)
Visual Web Developer

Setting Web Server Control Properties Programmatically


(Visual Studio)
You can set Web server control properties programmatically to change the control's appearance and behavior at run time.
Properties for Web server controls are strongly typed, so the exact technique you use to set properties depends on what type
of property you are setting. For example, setting a unit property such as width is different from setting a color property. The
sections below provide details about setting different types of properties. For information about the properties for a specific
control, search for the name of the control class in the Help index, such as "Button class (System.Web.UI.WebControls)".
Note
You set HTML server control properties slightly differently. For details, see
How to: Set HTML Server Control Properties Programmatically.

In This Section
How to: Set Web Server Control Properties Based on Simple Values or Enumerations
How to: Set Web Server Control Unit Properties
How to: Set Web Server Control Color Properties
How to: Set Web Server Control Properties in Collections
How to: Set HTML Attributes for Controls in ASP.NET Web Pages
How to: Read HTML Attributes for Controls in Web Forms Pages
How to: Set HTML Server Control Properties Programmatically
ASP.NET Expressions Overview
See Also
Other Resources
Working with Web Server Controls
ASP.NET Web Server Controls (Visual Studio)
ASP.NET Web Pages (Visual Studio)
ASP.NET

How to: Set Web Server Control Properties Based on Simple


Values or Enumerations
If a Web server control property's data type is a primitive type, such as a String, Boolean, or numeric type, you can set the
property value by simply assigning it to the property. Similarly, if the property's values are defined in an enumeration class,
you can simply assign the enumeration to the property.
To set a property value based on simple values
Assign the value as a literal or variable, as in the following example:
VB
Label1.Text = "Hello"
Datagrid1.PageSize = 5

C#
Label1.Text = "Hello";
DataGrid1.PageSize = 5;

To set a property value based on an enumeration


Assign the value using one of the enumeration values. ASP.NET can resolve the enumeration based on the property's
type. The following code example illustrates setting a property using an enumeration:
VB
'Uses TextBoxMode enumeration
TextBox1.TextMode = TextBoxMode.SingleLine
'Uses ImageAlign enumeration
Image1.ImageAlign = ImageAlign.Middle

C#
// Uses TextBoxMode enumeration
TextBox1.TextMode = TextBoxMode.SingleLine;
// Uses ImageAlign enumeration
Image1.ImageAlign = ImageAlign.Middle;

See Also
Tasks
How to: Set HTML Server Control Properties Programmatically
Other Resources
Setting Web Server Control Properties Programmatically (Visual Studio)
ASP.NET

How to: Set Web Server Control Unit Properties


Width, height, and similar properties for Web server controls are set in units. Units are implemented as objects (the Unit
structure), which allows you to specify a value and the measurement unit in various ways.
To set unit-based properties
Assign a reference to the Unit structure to your control.
The following code examples show variations on how to do this.
VB
' Default is pixels.
TextBox1.Width = New Unit(100)
TextBox1.Width = New Unit(100, UnitType.Pixel)
TextBox1.Width = New Unit("100px")
' Centimeters.
TextBox1.Width = New Unit("2cm")
TextBox1.Width = New Unit(10, UnitType.Percentage)
TextBox1.Width = New Unit("10%")

C#
// Default is pixels.
TextBox1.Width = new Unit(100);
TextBox1.Width = new Unit(100, UnitType.Pixel);
TextBox1.Width = new Unit("100px");
// Centimeters
TextBox1.Width = new Unit("2cm");
TextBox1.Width = new Unit(10, UnitType.Percentage);
TextBox1.Width = new Unit("10%");

See Also
Tasks
How to: Set ASP.NET Server Control Properties (Visual Studio)
Other Resources
Setting Web Server Control Properties Programmatically (Visual Studio)
ASP.NET

How to: Set Web Server Control Color Properties


To set a Web server control property such as the BackColor property to a color, you assign a reference to the Color object.
To set Web server control properties to a color
Call the Color object's FromArgb method, passing it a numeric value (RGB) or the FromName passing it the name of a
color as string. Alternatively, you can assign the color using a static method that references a predefined color name, as
in the following example:
VB
Button1.BackColor = System.Drawing.Color.FromName("Red")
' White in RGB.
Button1.BackColor = System.Drawing.Color.FromArgb(255, 255, 255)
Button1.BackColor = System.Drawing.Color.Red
' HTML 4.0 Color
Button1.BackColor = System.Drawing.Color.MediumSeaGreen

C#
Button1.BackColor = System.Drawing.Color.FromName("Red");
// White in RGB.
Button1.BackColor = System.Drawing.Color.FromArgb(255, 255, 255);
Button1.BackColor = System.Drawing.Color.Red;
// HTML 4.0 color.
Button1.BackColor = System.Drawing.Color.MediumSeaGreen;

See Also
Tasks
How to: Set ASP.NET Server Control Style Properties Programmatically
Other Resources
ASP.NET Themes and Skins
ASP.NET

How to: Set Web Server Control Properties in Collections


The properties of some Web server controls are not simple values or objects, but collections. For example, the individual values
of a ListBox Web server control are implemented as a collection of ListItem objects.
To set a collection-based control property
Instantiate the item you want to use, and then add it to the control's collection.
The following code example shows how to add a ListItem object to a ListBox control by adding it to the control's Items
collection. In the first example, the item is explicitly created before being added. In the second example, items are created
and added at the same time.
VB
Dim li As ListItem = New ListItem("Item 1")
ListBox1.Items.Add(li)

' Create and add the items at the same time


ListBox1.Items.Add(New ListItem("Apples"))
ListBox1.Items.Add(New ListItem("Oranges"))
ListBox1.Items.Add(New ListItem("Lemons"))

C#
// Create the items and then add them to the list.
ListItem li = new ListItem("Item 1");
ListBox1.Items.Add(li);

// Create and add the items at the same time.


ListBox1.Items.Add(new ListItem("Apples"));
ListBox1.Items.Add(new ListItem("Oranges"));
ListBox1.Items.Add(new ListItem("Lemons"));

See Also
Tasks
How to: Set ASP.NET Server Control Properties (Visual Studio)
Other Resources
Setting Web Server Control Properties Programmatically (Visual Studio)
ASP.NET

How to: Set HTML Attributes for Controls in ASP.NET Web


Pages
These example show how to add HTML attributes to elements in the page. The first example shows how to add attributes to a
control declaratively. Any attribute you add to a control that does not map to a property of that control is passed through to
the browser.
The second example shows how to add an attribute and a style programmatically to a Button control. The third example shows
how to add an attribute programmatically to the page's body tag, which requires that you first add runat="server" and an ID
attribute to the tag.
Example
VB
<body id="body" runat="server">
<form id="form1" runat="server">
<!-- Example1 -->
<input runat="server" id="Button1" type="button" onmouseover="rollover()" onmouseout=
"exitrollover()" />
</form>
</body>

<script runat="server">

Private Sub Page_Load(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles MyBase.Load

' Example 2
Button1.Attributes.Add("onclick", "alert('hello, world')")
Button1.Style.Add("background-color", "red")

' Example 3
body.Attributes("bgcolor") = "lightblue"

End Sub

</script>

C#
<body id="body" runat="server">
<form id="form1" runat="server">

<!-- Example1 -->


<input runat="server" id="Button1" type="button" onmouseover="rollover()" onmouseout=
"exitrollover()" />
</form>
</body>
<script runat="server">
private void Page_Load()
{
//Example 2
Button1.Attributes.Add("onclick", "alert('hello, world')");
Button1.Style.Add("background-color", "red");
//Example 3
Button1.Attributes["bgcolor"] = "lightblue";

}
</script>
Compiling the Code
This example requires:
An ASP.NET Web page.
An ASP.NET Button control named Button1.
The attributes runat="server" and id="body" in the page's body tag.

Robust Programming
No validation is done of the attributes you add to the control; the key/value pairs are rendered to the browser as-is.
When you set an attribute, it overrides any existing attribute of the same name. (It does not amend values onto an existing
attribute.) Therefore, if you want to amend an attribute, you must first read it, amend it, and then add it back to the control.
If an attribute is represented in the control by a property, the property takes precedence over attribute settings that you make.
For example, the Text property of a TextBox control takes precedence if you try to set the text using the value attribute.
See Also
Tasks
How to: Read HTML Attributes for Controls in Web Forms Pages
ASP.NET

How to: Read HTML Attributes for Controls in Web Forms


Pages
This example reads the attributes rendered for a TextBox Web server control and an HtmlInputButton control. The code reads
the Keys collection of the AttributeCollection object of each individual control. For each key item, the code extracts the
corresponding value by getting the value of the corresponding Item element.
Example
VB
Response.Write(Button1.Attributes.Item("Style") & "<br />")
Dim key As String
For Each key In Button1.Attributes.Keys
Response.Write(key & "=" & Button1.Attributes.Item(key) & "<br />")
Next
For Each key In Submit1.Attributes.Keys
Response.Write(key & "=" & Submit1.Attributes.Item(key) & "<br />")
Next

C#
Response.Write(Button1.Attributes[("Style")] + "<br />");

//String key;

foreach ( String key in Button1.Attributes.Keys)


{
Response.Write(key + "=" + Button1.Attributes[key] + "<br />");
}

foreach ( String key in Submit1.Attributes.Keys)


{
Response.Write(key + "=" + Submit1.Attributes[key] + "<br />");
}

Compiling the Code


This example requires:
An ASP.NET Web page.
A Button Web control named Button1.
An HtmlInputButton control whose ID attribute is set to Submit1.

Robust Programming
If you specify an invalid attribute name for the Item element, the return value is an empty string.
Web server controls return only the attributes that do not have corresponding strongly typed properties.
See Also
Tasks
How to: Set HTML Attributes for Controls in ASP.NET Web Pages
ASP.NET

How to: Set HTML Server Control Properties Programmatically


HTML server controls are of two slightly different types. The HTML elements most commonly used in forms are available as
individual HTML server controls, such as HtmlInputText, HtmlInputButton, HtmlTable, and so on. These HTML server controls
expose their own, control-specific properties that map directly to HTML attributes. However, any HTML element can be
converted to a control. In that case, the element becomes an HtmlGenericControl with base class properties such as TagName,
Visible, and InnerHTML.
To set properties of HTML server controls
Get or set the property name as you would with any object. All properties are either strings or integers.
The following example illustrates setting property names:
VB
Dim TotalCost As Integer
myAnchor.HRef = "http://www.microsoft.com"
Text1.MaxLength = 20
Text1.Text = String.Format("{0:$###}", TotalCost)
Span1.InnerHtml = "You must enter a value for Email Address."

C#
myAnchor.HRef = "http://www.microsoft.com";
Text1.MaxLength = 20;
Text1.Text = string.Format("{0:$####}", TotalCost);
Span1.InnerHtml = "You must enter a value for Email Address.";

Setting Attributes
All HTML server controls also support an Attributes collection, which gives you direct access to all the control's attributes. This
is particularly useful for working with attributes that are not exposed as individual properties.
To work with control attributes directly
Use the properties and methods of a control's Attributes collection, such as Add, Remove, Clear, and Count. The Keys
property returns a collection containing the names of all the attributes in the control. The following examples show
various ways to use the Attributes collection:
VB
' Adds new attribute.
Text1.Attributes.Add("bgcolor", "red")
' Removes one attribute.
Text1.Attributes.Remove("maxlength")
' Removes all attributes, clearing all properties.
'Text1.Attributes.Clear()
' Creates comma-delimited list of defined attributes
Dim strTemp As String = ""
Dim key As String
For Each key In Text1.Attributes.Keys
strTemp &= Text1.Attributes(key) & ", "
Next
End Sub

C#
// Adds a new attribute.
Text1.Attributes.Add("bgcolor", "red");
// Removes one attribute.
Text1.Attributes.Remove("maxlength");
// Removes all attributes, clearing all properties.
Text1.Attributes.Clear();
// Creates comma-delimited list of defined attributes
string strTemp = "";
foreach (string key in Text1.Attributes.Keys)
{
strTemp += Text1.Attributes[key] + ", ";
}

See Also
Tasks
How to: Set ASP.NET Server Control Properties (Visual Studio)
Other Resources
Setting Web Server Control Properties Programmatically (Visual Studio)
ASP.NET

ASP.NET Expressions Overview


ASP.NET expressions are a declarative way set control properties based on information that is evaluated at run time. For
example, you can use expressions to set a property to values that are based on connection strings, application settings, and
other values contained within an application's configuration and resource files. Expressions are evaluated at run time when the
declarative elements of the page are parsed, and the value represented by the expression is substituted for the expression
syntax. (Because expressions are evaluated at parse time, you cannot dynamically create expressions in code.)
A common use of expressions is in data source controls to reference a connection string. Rather than including the connection
string directly in the data source control as a property value, you can use an expression that specifies where the connection
string is in the configuration file. At run time, the expression is resolved by reading the connection string from the
configuration file. You can use expressions for any property setting that you want to resolve at run time rather than set as a
static value.
Using expressions helps you maintain your application in these ways:
You can reduce the code in your application by referencing dynamic information declaratively. This avoids having to
write code to set property values at run time.
You can reuse the same settings in multiple controls. For example, if you store a connection string in the Web.config file
and then use expressions to reference the connection string in pages, you change the connection string in one central
location rather than changing it in each control that uses the connection string.
You can store sensitive data such as connection string credentials (or other application data) in the Web.config file and
then encrypt the data.
If you are working with a visual designer such as Visual Studio, you can take advantage of tools in the designer that can
help you build expressions.
Expressions are also extensible, so that you can define your own expression syntax. You can then create expressions that call
your custom expression handler to return a value using your custom logic.
Basic Syntax
The basic syntax of an ASP.NET expression is the following:

<%$ expressionPrefix: expressionValue %>

The dollar sign ($) indicates to ASP.NET that an expression follows. The expression prefix defines the type of expression, such as
AppSettings, ConnectionStrings, or Resources. Following the colon (:) is the actual expression value that ASP.NET will
resolve.
Expression syntax is not bound to any specific .NET language. You can use the same expression syntax whether you use Visual
Basic, C#, or any other programming language in your ASP.NET pages.
Connection Strings
A common use of expressions is to set the connection string property of a control, such as the SqlDataSource control, based on
the value of a connection string stored in the Web.config file. For example, you might have the following SqlDataSource
control with a connection string attribute:

<asp:SqlDataSource ID="SqlDataSource1" Runat="server"


SelectCommand="SELECT * FROM [Employees]"
ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString1 %>">
</asp:SqlDataSource>

The highlighted code shows an expression, which is contained within the quotation marks and denotes the attribute's value.
The expression references a connection string named "NorthwindConnectionString1" that is defined in the connectionStrings
element of the Web.config file. The connectionStrings element might look like the following:

<configuration>
<connectionStrings>
<add name="NorthwindConnectionString1"
connectionString="Data Source=localhost;Integrated Security=SSPI;Initial Catalog=Nort
hwind;"
providerName="System.Data.SqlClient" />
</connectionStrings>
<!-- additional settings -->
</configuration>

Note
It is recommended for added security that you encrypt the section of the configuration file that contains connection strings. F
or details, see Encrypting Configuration Information Using Protected Configuration. In the preceding example, the configura
tion section of the configuration file is shown unencrypted for clarity.

Each connection string is given a name, which you can use in an expression to reference it within your ASP.NET pages.
Application Settings
In addition to using expressions for connection strings, you can use expressions to reference application settings defined in a
configuration file accessible to the Web site. For example, you might have frequently used strings, such as your site's copyright
message, stored in the appSettings section of your Web.config file, which might look like the following:

<appSettings>
<add key="copyright" value="(c)Copyright 2004 Northwind Traders"/>
</appSettings>

Within your ASP.NET pages, you could reference the value by using an expression similar to the following:

<%$ AppSettings: copyright %>

This would enable you to maintain frequently cited elements within the configuration file rather than having to change the
same text on every page.
Displaying Static Content Using Expressions
If you want to use an expression as a static value on your page or control, you use an expression as part of an ASP.NET server
control. A typical strategy is to add a Literal control and set its Text property to an expression. For example, to place a copyright
notice at the bottom of every page you could use the following:
<p align="center">
<asp:Literal runat="server" text="<%$ AppSettings: copyright %>"/>
</p>

Resource Files
In addition to displaying values contained in a configuration file, you can display values that are stored in resource (.resx or
.resource) files. You typically use resource files to store information for a specific language or language and culture
combination. By using resource files and expressions, you can create a Web page that displays text in different languages
depending on values determined at run time, such as the language and culture setting reported by the browser, or an explicit
language choice by the user.
For example, when localizing content automatically, you can set the Text property of a server control using expression syntax,
as in this example:

<asp:Label id="label1" runat="server" text="<%$ Resources: Messages, ThankYouLabel %>" />

In the App_GlobalResources folder, you could have resource files named Messages.resx, Messages.es.resx, Message.de.resx,
and so on—a Messages resource file for each language you want to support. The Messages.resx file represents the neutral
(fallback) resource that is used if no explicit culture is set. In the Messages.resx file, you might have an entry like this:

<data name="ThankYouLabel"><value>Thank you very much!</value></data>


You would have similar entries in other resource files, with the strings translated appropriately for the language represented
by that resource file. For more information on using expressions for resources and localization, see
ASP.NET Web Page Resources Overview.
See Also
Concepts
ASP.NET Web Page Syntax Overview
Other Resources
ASP.NET Configuration File Syntax
ASP.NET

How to: Specify Whether ASP.NET Web Server Controls Post to


the Server
By default, information and selections that the user specifies in an ASP.NET Web page are not posted immediately to the
server. Instead, the values are posted only when the entire page is posted, usually in response to clicking a button. However,
you might find it useful at times to send user changes to the server immediately.
To post control values to the server immediately
Set the control's AutoPostBack property to true.
You can also respond to user actions by creating client scripts. For example, you can create a client script to respond to
the Click event of a button or check box. For more information, see Client Script in ASP.NET Web Pages
See Also
Other Resources
Working with ASP.NET Web Server Controls
ASP.NET

Tab Order, Focus, and Access Keys in ASP.NET Web Server


Controls
To enhance the user experience of using controls in ASP.NET Web pages, you can specify the order in which users can tab
through ASP.NET Web server controls, and you can specify which control on the page has the focus when the page is initially
opened.
Tab Order
When pages are displayed in the browser, users can use a TAB key (TAB and SHIFT+TAB on Windows) to move the
focus/selection from control to control on the page. In most browsers, by default, the tab order for controls is the order in
which they appear in the page, beginning at the top left of the page and continuing to the bottom right of the page.
You can control the tab order for controls by setting their TabIndex property. When the controls are rendered, the TabIndex
value is rendered into the attribute for the browser required to support tabbing. In Internet Explorer, for example, the
TabIndex value is rendered as the tabindex attribute of an element on the page.
Tab order goes up sequentially, so that when a user moves from a control with a TabIndex property set to 3, the focus then
goes to the control with the TabIndex value of 4 (or higher). In many browsers, including Internet Explorer, tab order includes
controls that are located on the browser toolbar.
With some controls, pressing the TAB key can cause the control to perform a postback. For example, if you set a TextBox
control's AutoPostBack property to true, moving from the text box that contains changed text causes the page to post.
Focus
When a page is rendered to the browser, the browser determines which control should have the focus. In most cases, the
browser initially puts focus on the browser window itself or the first control on the page. This is true even after a postback,
because the page is being re-created on the server and the browser considers it a new page. (An exception is after a postback
caused by a TAB key, as explained earlier in the "Tab Order" section of this topic.)
If it is important to have the focus on a specific control in your application, you can set the focus on a control from server code.
For details, see How to: Set Focus on ASP.NET Web Server Controls.
Not all controls can receive focus. You can set the focus on any of the following:
Button
CheckBox
DropDownList
HyperLink
ImageButton
LinkButton
ListBox
RadioButton
TextBox
If a control is hidden, it cannot receive the focus. If you set focus on a control that cannot receive focus directly but that has
child controls that can receive the focus, the first child control will receive focus. For example, if you set the focus on the Login
control, the first text box that is located inside the Login control will receive the focus.
Access Keys
In addition to supporting tab order in your ASP.NET Web pages, you can add support for access keys (also known as hot keys).
An access key allows users to press the ALT key plus another key (for example, ALT+S) to jump to a specific control on the
page without using the mouse.
For details, see How to: Set Access Keys for ASP.NET Web Server Controls.
See Also
Other Resources
Programming ASP.NET Web Pages with Client Script
ASP.NET

How to: Set Focus on ASP.NET Web Server Controls


If it is important in your application, you can put the focus on a specific ASP.NET Web server control by using server code. You
can put the focus on a specific control dynamically, or you can specify a control that should get the focus by default. You can
set the default focus for the form as a whole, or you can set the default focus on a control that is a child of a Panel control.
You can put the focus on the following types of controls:
Button, LinkButton, and ImageButton controls
CheckBox control
DropDownList control
FileUpload control
HyperLink control
ListBox control
RadioButton control
TextBox control
You can also set the focus on controls that contain one or more of the controls listed above. For example, you can set the focus
on a Login control. In that case, the focus will be put on the first eligible control within the Login control.
In general, if you set focus on a control that cannot receive focus or is hidden or disabled, the call is ignored. If you attempt to
set focus on a non-visual control, such as a data source control, an exception is thrown.
Note
Setting focus requires that client scripting be enabled in the browser.

To set focus on an ASP.NET Web server control


Call the control's Focus method.
-or-
Call the page's SetFocus method, passing it the ID of the control on which you want to set focus.
The following code example shows how to set the focus on the control with the ID TextBox1:
Security Note
This example has a text box that accepts user input, which is a potential security threat. By default, ASP.NET Web pages
validate that user input does not include script or HTML elements. For more information, see Script Exploits Overview.

[Visual Basic]
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs)
TextBox1.Focus()
End Sub

C#
protected void Page_Load(object sender, EventArgs e)
{
TextBox1.Focus();
}
To set default focus in a form or panel
Set the DefaultFocus attribute of the form element in the page or of a Panel control.
The following code example shows a page with the default focus set to the control TextBox1:
VB
<%@ Page Language="VB" %>
<html>
<head runat="server">
<title>Test Page</title>
</head>
<body>
<form id="form1" runat="server" defaultfocus="TextBox1" >
<div>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<br />
<asp:Button ID="Button1" runat="server" Text="Button" />
<br />
</div>
</form>
</body>
</html>

C#
<%@ Page Language="C#" %>
<html>
<head runat="server">
<title>Test Page</title>
</head>
<body>
<form id="form1" runat="server" defaultfocus="TextBox1" >
<div>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<br />
<asp:Button ID="Button1" runat="server" Text="Button" />
<br />
</div>
</form>
</body>
</html>

See Also
Concepts
Tab Order, Focus, and Access Keys in ASP.NET Web Server Controls
ASP.NET

How to: Set Access Keys for ASP.NET Web Server Controls
An access key (also known as a hot key) allows users to press the ALT key plus another key to jump to a specific control on the
page without using the mouse.
You can set an access key on a specific control, such as a TextBox or ListBox control. Alternatively, you can set an access key for
a Label control, and then specify that the Label control is associated with another control. This approach enables you to use the
Label control as a caption, allowing you to indicate the access key with an underlined letter in the label text.
Note
Access keys and other keyboard shortcuts are not supported on all browsers.

To set an access key for a specific ASP.NET Web server control


Set the control's AccessKey property to the letter or number that you want to use with ALT key as a keyboard shortcut.
For example, to set a control's access key to ALT+S, set the control's AccessKey property to S.
Note
Some ALT-key sequences might be reserved in the browser. For example, in Internet Explorer, ALT+F opens the File me
nu. The browser determines whether to give precedence to your ALT-key sequence or to the brower's reserved keys.

To set an access key by using a Label control


1. Add a Label control to the page to act as a caption for the control that you want to put focus on with an access key.
2. In a Label control, set the following properties:
AccessKey Set this property to the letter or number to use with the ALT key, such as S to support ALT+S.
AssociatedControlID Set this property to the ID of the control to set the focus on when the ALT-key sequence is
pressed.
Text Optionally, use HTML to add an underline or other indicator to the Text property.
The following code example shows the markup for a Label control and a TextBox control. The Label control displays a
caption for the TextBox control, with the letter L underlined to indicate that the access key for the text box is ALT+L.
Security Note
This example has a text box that accepts user input, which is a potential security threat. By default, ASP.NET Web pages
validate that user input does not include script or HTML elements. For more information, see Script Exploits Overview.

<asp:Label ID="Label1" runat="server"


AccessKey="L"
AssociatedControlID="TextBox1"
Text="<u>L</u>ast name: ">
</asp:Label>&nbsp;
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>

Note
Setting focus by using an access key from a Label control requires that client scripting is enabled in the browser.

See Also
Concepts
Tab Order, Focus, and Access Keys in ASP.NET Web Server Controls
Visual Web Developer

Learning More — Working with Web Server Controls


The topics in this section provide in-depth information on ASP.NET Web server controls, including how to work with them
programmatically.
In This Section
ASP.NET Web Server Controls and CSS Styles
Adding ASP.NET Controls Programmatically
Accessing ASP.NET Controls Programmatically
ASP.NET Web Server Controls and Browser Capabilities
ASP.NET Web Server Controls Templates
See Also
Other Resources
Working with Web Server Controls
ASP.NET Web Server Controls (Visual Studio)
ASP.NET Web Pages (Visual Studio)
ASP.NET

ASP.NET Web Server Controls and CSS Styles


You can control the look of ASP.NET server controls by setting various appearance properties such as ForeColor, BackColor,
Height, and Width. In addition, some controls support style objects that expose additional style-related settings.
Note
ASP.NET Web pages function as HTML pages at run time. You can therefore use cascading style sheets (CSS) to set the appea
rance of any elements on the page other than Web server controls. In addition, you can define ASP.NET themes that include c
ascading style sheet settings, and then apply themes to pages or to your site. For details, see ASP.NET Themes and Skins.

The sections below provide information about setting styles directly, including how to work with styles both at design time and
programmatically.
Rendering Appearance Properties to the Browser
When the page runs, appearance properties are rendered according to the capabilities of the user's browser. If the user's
browser supports cascading style sheets (CSS), the appearance properties are rendered as style attributes of the HTML
elements that make up the control. For example, if you define a Hyperlink Web server control and set its ForeColor property to
Red, its Bold property to true, and its Size property to xx-small, the control is rendered as the following if the user's browser
supports style sheets:
VB
<a id="hyperlink1" style="color: red; font-size: xx-small; font-weight: bold;">HyperLink</a
>

C#
<a id="hyperlink1" style="color: red; font-size: xx-small; font-weight: bold;">HyperLink</a
>

On the other hand, if the user's browser does not support styles, the control is rendered using other means, such as a <font>
element. The following shows the rendering for the example from above, but for a browser that does not support styles:
VB
<a id="a1"><b><font color="red" size="1">HyperLink</font></b></a>

C#
<a id="a1"><b><font color="red" size="1">HyperLink</font></b></a>

Other examples of properties that are rendered differently depending on the browser are BorderWidth and BorderColor.
Some appearance properties, such as BorderStyle, cannot be rendered without using styles. These properties are therefore
ignored in browsers that do not support styles. For more information, see
ASP.NET Web Server Controls and Browser Capabilities.
Control Style Objects
In addition to appearance properties such as ForeColor and BackColor, controls expose one or more style objects that
encapsulate additional appearance properties. One example is the Font style property, which exposes an object of type FontInfo
containing individual properties pertaining to the font, such as Size, Name, and Bold.
Some controls expose style objects you can use to set the appearance of specific portions of the control. For example, the
Calendar Web server control contains style objects such as DayStyle (individual days), SelectedDayStyle (a day, week, or month
selected by the user), and WeekendDayStyle. Using the SelectedDayStyle style object, for example, you can set the
BackColor and ForeColor properties of the day selected by the user.
Most style objects are of type Style or TableItemStyle, because they are setting the attributes of table cells. The Font property is
of type FontInfo.
Precedence and Inheritance of Style Objects
In complex controls, style objects often inherit characteristics from other style objects. For example, in the Calendar control,
the SelectedDayStyle object is based on the DayStyle object. If you do not explicitly set any properties for
SelectedDayStyle, it inherits its characteristics from the DayStyle object.
This inheritance means that style-object properties you set have an order of precedence. For example, the following list shows
the order of style-object properties for the Calendar control, with the highest precedence given to the settings on the object
last on the list.
1. Appearance properties of the base Calendar control.
2. DayStyle style object.
3. WeekendDayStyle style object.
4. OtherMonthDayStyle style object.
5. TodayDayStyle style object.
6. SelectedDayStyle style object.
There can be difficulties with styles when they are split between a container element and a text element. For example, suppose
you have a style sheet for a control and you want the text style properties to be applied to a link and the rest of the style to be
applied to a container. This is feasible if you set the styles using the style properties of the control, such as MenuItemStyle for a
menu control or TodayDaySyle for a calendar control. But it is more difficult using styles defined by a CssClass property,
because ASP.NET has no way to know the contents of the class on the server. ASP.NET applies the styles defined in the
CssClass property to both the text and the container elements and adds an inline style to suppress the effects of this double
application (double borders, proportional font multiplication, and so on).
The best way to style a control is to use the style properties defined by the control and to use a style sheet or inline styles to
make minor adjustments to individual elements if necessary. To override a style defined by a control's style properties, use the
!important CSS rule in a style sheet or inline styles.
The following code example uses the CssClass property on the hovernodestyle element. This class is defined twice as
myclass and as a.myclass:visited so that it overrides the a:visited definition.

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


<html>
<head runat="server">
<asp:sitemapdatasource id="SiteMapSource" runat="server" />
<style type="text/css">
a:visited
{
color: #000066
}
myclass, a.myclass:visited {
color: #FF0000
}
</style>
</head>
<body>
<form runat="server">
<a href="http://www.Contoso.com">Contoso</a>
<asp:treeview id="treeview1" runat="server"
initialexpanddepth="1"
datasourceid="SiteMapSource"
forecolor="#444444"
font-names="Verdana"
font-size="0.8em">
<nodestyle font-bold="true" />
<hovernodestyle cssclass=myclass />
</asp:treeview>
</form>
</body>
</html>

If you use cascading style sheets (CSS) to customize the appearance of a control, use either inline styles or a separate CSS file,
but not both. Using both inline styles and a separate CSS file can cause unexpected results.
Controlling CSS Styles and Classes Directly
In addition to the appearance properties and style objects, controls expose two properties that allow you to manipulate CSS
styles more directly: CssClass and Style. The CssClass property enables you to assign a style sheet class to the control. The
Style property enables you to set a string of style attributes to be written as-is to the control. Using the Style property allows
you to set style attributes that are not exposed via other properties. The Style property exposes a collection whose methods,
such as Add and Remove, you can call to set styles directly.
Settings you make in the Style property are not reflected in the corresponding individual appearance property. For example, if
you set a string background-color:red in the Style property, the BackColor property is not also set to red, even though the
control will render with a red background. If you set both appearance properties and the Style property, the individual
appearance properties take precedence over the Style property.
See Also
Concepts
ASP.NET Web Server Controls and Browser Capabilities
Other Resources
Working with ASP.NET Web Server Controls
Visual Web Developer

How to: Set ASP.NET Server Control Style Properties in the


Designer
The designer provides tools that make it easier to set style properties.
To set style properties in the designer
1. In Design view, select the control that you want to set styles for.
2. In Properties, do the following:
Expand Styles, and then set properties for that object.
For example, to set properties for the ItemStyle property, in Properties, expand ItemStyle.
–or–
If the control supports property builders, such as the DataList control, in Properties, click the properties icon to
open the Properties dialog box. Click Format, under Objects, click a style object, and then set its properties.
See Also
Tasks
How to: Set ASP.NET Server Control Style Properties Programmatically
How to: Set ASP.NET Server Control Style Properties Using ASP.NET Syntax
Concepts
ASP.NET Web Server Controls and CSS Styles
ASP.NET

How to: Set ASP.NET Server Control Style Properties Using


ASP.NET Syntax
You can set style properties directly in the .aspx file in two ways.
To set style properties in the .aspx file
Declare the style property using a convention of hyphenating the style object name and property, as shown in the
following example:
VB
<asp:Calendar Id="MyCalendar"
SelectionMode="DayWeek" runat="server"
TitleStyle-Backcolor="#3366ff"
TitleStyle-ForeColor="White" />

C#
<asp:Calendar Id="MyCalendar"
SelectionMode="DayWeek" runat="server"
TitleStyle-Backcolor="#3366ff"
TitleStyle-ForeColor="White" />

-or-
Declare explicit elements in which you declare property elements of the appropriate data type, as shown in the following
example:
VB
<asp:Calendar id="Calendar1"
SelectionMode="DayWeek" runat="server">
<TitleStyle BackColor="#3366ff" ForeColor="white" />
</asp:Calendar>

C#
<asp:Calendar id="Calendar1"
SelectionMode="DayWeek" runat="server">
<TitleStyle BackColor="#3366ff" ForeColor="white" />
</asp:Calendar>

See Also
Tasks
How to: Set ASP.NET Server Control Style Properties Programmatically
Concepts
ASP.NET Web Server Controls and CSS Styles
Other Resources
Learning More — Programming ASP.NET Web Pages
ASP.NET

How to: Set ASP.NET Server Control Style Properties


Programmatically
You can set style properties of an ASP.NET server control programmatically, which allows you to change the appearance of a
control conditionally.
To set style properties programmatically
Use the following hierarchical convention for specifying the style object and property you want to set:
VB
Control.StyleObject.Property = value

C#
Control.StyleObject.Property = value;

The following code example shows how to set the BackColor property for the DayStyle object of a Calendar control:
VB
Calendar1.DayStyle.BackColor = System.Drawing.Color.Green

C#
Calendar1.DayStyle.BackColor = System.Drawing.Color.Green;

You can also create a separate Style object and copy or merge the values of its properties to one of the styles on a
control. This is a powerful way to apply the same styles to several different list objects in your project. In effect, you can
create a virtual style sheet as a Style object and then apply it to a series of controls.
To create a style object and apply it to controls
1. Create an instance of the Style object and set its properties, as shown in the following example:
VB
Dim s As Style = New Style()
s.BackColor = System.Drawing.Color.Red

C#
Style s = new Style();
s.BackColor = System.Drawing.Color.Red;

2. Assign the Style object to a control using one of the following methods:
The CopyFrom method applies all settings from a Style object, including null ones.
The MergeWith method copies only the properties already set on the Style object, skipping Style properties that
have not been set. Also, the MergeWith method will not overwrite any existing style elements.
The following code example shows how you might create a Style object, set one of its properties, and then apply it to
two different control style objects, using each of the methods described:
VB
' Apply all values in s, including nulls.
Calendar1.SelectedDayStyle.CopyFrom(s)
' Apply only values in s that are null in HeaderStyle.
DataGrid1.HeaderStyle.MergeWith(s)

C#
// Apply all values in s, including nulls.
Calendar1.SelectedDayStyle.CopyFrom(s);
// Apply only values in s that are null in HeaderStyle.
DataGrid1.HeaderStyle.MergeWith(s);

See Also
Tasks
How to: Set ASP.NET Server Control Style Properties Using ASP.NET Syntax
Concepts
ASP.NET Web Server Controls and CSS Styles
ASP.NET

Adding ASP.NET Controls Programmatically


This section contains topics that describe how to create ASP.NET Web server controls in code and add them to a page.
In This Section
How to: Add Controls to an ASP.NET Web Page Programmatically
Dynamic Web Server Controls and View State
Related Sections
ASP.NET Web Server Controls
Provides links to additional topics that describe how to work with ASP.NET server controls.
ASP.NET

Dynamic Web Server Controls and View State


When a Web server control is created dynamically at run time, some information about the control is stored in the view state
that is rendered with the page. When the page is posted back to the server, however, non-dynamic controls (those defined on
the page) are instantiated in the page's Init event and view state information is loaded before the dynamic controls can be
recreated (generally in the Page_Load handler). Effectively, before the dynamic controls are recreated, view state is
temporarily out of sync with the page's controls. After the Page_Load event has run, but before control event-handling
methods are called, the remaining view state information is loaded into the dynamically created controls.
In most scenarios, this view state processing model works fine. Typically, you add dynamic controls to the end of a container's
collection of controls. The view state information stored for the dynamic controls is therefore extra information at the end of
the view state structure for the appropriate container, and the page can ignore it until after the controls are created.
However, view state information about dynamically created controls can be a problem in two scenarios:
If you insert dynamic controls between existing controls.
If you insert controls dynamically and then reinsert them during a round trip, but with different values.
If you insert dynamic controls between existing controls, the dynamic control's view state information is inserted into the
corresponding location of the view state structure. When the page is posted and the view state is loaded, the dynamic control
does not yet exist; therefore, the extra information in view state does not correspond to the right control. The result is usually
an error indicating an invalid cast.
If you reinsert controls with each round trip, each generation of dynamically created controls will pick up property values from
the view state of the preceding set of controls. In many cases, you can avoid this problem by setting the EnableViewState
property of the container control to false. In that case, no information about the dynamic controls is saved, and there is no
conflict with successive versions of the controls.
For details about view state, see
ASP.NET Page Life Cycle Overview
ASP.NET State Management Overview, and ViewState.
See Also
Other Resources
Adding ASP.NET Controls Programmatically
Setting Web Server Control Properties Programmatically (Visual Studio)
ASP.NET

How to: Add Controls to an ASP.NET Web Page


Programmatically
At times it is more practical to create a control at run time than at design time. For example, imagine a search results page in
which you want to display results in a table. Because you do not know how many items will be returned, you want to
dynamically generate one table row for each returned item.
Note
Existing controls can often provide the functionality you get from creating controls dynamically. For example, controls such a
s the Repeater, DataList, and RadioButtonList controls can dynamically create rows or other control elements when the page
runs.

In order to programmatically add a control to a page, there must be a container for the new control. For example, if you are
creating table rows, the container is the table. If there is no obvious control to act as container, you can use a PlaceHolder or
Panel Web server control.
In some instances, you might want to create both static text and controls. To create static text, you can use either a Literal or a
Label Web server control. You can then add these controls to the container as you would any other control. For information
about view state in controls created at run time, see Dynamic Web Server Controls and View State.
Important

To add a control to an ASP.NET Web page programmatically


1. Create an instance of the control and set its properties, as shown in the following example:
VB
Dim myLabel As New Label()
myLabel.Text = "Sample Label"

C#
Label myLabel = new Label();
myLabel.Text = "Sample Label";

Note
Controls are typically added to the page during the page's initialization stage. For details about page stages, see
ASP.NET Page Life Cycle Overview.

2. Add the new control to the Controls collection of a container already on the page, as shown in the following example:
VB
Dim Panel1 As New Panel()
Panel1.Controls.Add(myLabel)

C#
Panel Panel1= new Panel();
Panel1.Controls.Add(myLabel);
Note
Because the Controls property is a collection, you can use the AddAt method to place the new control at a specific locat
ion — for example, in front of other controls. However, this can introduce errors into the page. For details, see
Dynamic Web Server Controls and View State.

The following code example shows the event handler for the SelectedIndexChanged event of a control named
DropDownList1. The handler creates as many label controls as the user has selected from the drop-down list. The
container for the controls is a PlaceHolder Web server control named Placeholder1.
Security Note
User input in a Web page can include potentially malicious client script. By default, ASP.NET Web pages validate that us
er input does not include script or HTML elements. For more information, Script Exploits Overview.

VB
Private Sub DropDownList1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e
As System.EventArgs) Handles DropDownList1.SelectedIndexChanged
Dim DropDownList1 As New DropDownList()
Dim PlaceHolder1 As New PlaceHolder()
Dim i As Integer
Dim numlabels As Integer

' Get the number of labels to create.


numlabels = CInt(DropDownList1.SelectedItem.Text)
For i = 1 To numlabels
Dim myLabel As Label = New Label()
' Set the label's Text and ID properties.
myLabel.Text = "Label " & i
myLabel.ID = "Label" & i
PlaceHolder1.Controls.Add(myLabel)
' Add a spacer in the form of an HTML <br /> element
Dim spacer As LiteralControl = New LiteralControl("<br />")
PlaceHolder1.Controls.Add(spacer)
Next
End Sub

C#
private void DropDownList1_SelectedIndexChanged(object sender, System.EventArgs e)
{
DropDownList DropDownList1 = new DropDownList();
PlaceHolder PlaceHolder1 = new PlaceHolder();

// Get the number of labels to create.


int numlabels = System.Convert.ToInt32(DropDownList1.SelectedItem.Text);
for (int i=1; i<=numlabels; i++)
{
Label myLabel = new Label();

// Set the label's Text and ID properties.


myLabel.Text = "Label" + i.ToString();
myLabel.ID = "Label" + i.ToString();
PlaceHolder1.Controls.Add(myLabel);
// Add a spacer in the form of an HTML <br /> element.
PlaceHolder1.Controls.Add(new LiteralControl("<br />"));
}
}

See Also
Tasks
How to: Set HTML Server Control Properties Programmatically
How to: Set ASP.NET Server Control Style Properties Programmatically
Concepts
ASP.NET Web Server Control Event Model
Other Resources
Setting Web Server Control Properties Programmatically (Visual Studio)
ASP.NET

Accessing ASP.NET Controls Programmatically


This section contains topics that describe how to programmatically reference individual controls on an ASP.NET Web page.
In This Section
Web Forms Control Identification
Web Forms Control ID Resolution
How to: Locate Child Controls by ID in an ASP.NET Web Page
Using the Controls Collection in an ASP.NET Web Page
How to: Locate the Web Forms Controls on a Page by Walking the Controls Collection
Using the NamingContainer Property to Determine a Control's Naming Container
How to: Access Members of a Web Server Control's Naming Container
Related Sections
Working with ASP.NET Web Server Controls
Provides general information about creating and programming ASP.NET Web server controls.
ASP.NET

Web Forms Control Identification


Every control on an ASP.NET Web page must be uniquely identifiable. Generally, you assign a value to a control's ID property
to uniquely identify it. This value becomes the instance name of the control — that is, the name by which you can refer to the
control in code. For example, if you set the ID property of a TextBox control to Text1, you can reference the control in code as
Text1.

A number of data-bound controls, including the DataList, Repeater, GridView, FormView, and DetailsView controls, act as
containers for other (child) controls. When these controls run, they generate multiple instances of the child control. For
example, if you create a DataList template with a Label control in it, when the page runs, there are as many instances of that
Label control in the page as there are records in the DataList control's data source.
Note
Controls that use templates, such as the DataList and Repeater controls, host template objects. For example, when the Data
List control runs, it creates multiple instances of the DataListItem class. These template objects in turn contain individual cont
rols such as labels, text boxes, buttons, and so on.

Because controls can be instantiated multiple times on the same page, and because you can reuse control names on different
pages, the ASP.NET page framework provides mechanisms to ensure that controls on the page and in your application have
unique identifiers. It also provides you with ways to find these individual controls so that you can manipulate them in your own
code.
The Naming Container
Controls that can act as containers for other controls generate a naming container, or an ID namespace, for their child controls.
By providing this naming container, controls can guarantee that ID attributes of their child controls are unique within the entire
application. (Controls generate a naming container by implementing the INamingContainer interface.) When child controls are
created at run time, the naming container is combined with the child control's ID property to create the value of the UniqueID
property of each child control. The UniqueID property therefore becomes a fully qualified identifier for a control, referencing
its naming container as well the controls' individual ID value.
In the example from above, the multiple instances of the Label control are created within the naming container — the
namespace — of the parent DataList control. The UniqueID property of each Label control will reflect this namespace, which
will have a format something like DataList1:_ctl:MyLabel, DataList1:_ct2:MyLabel, and so on.
Note
Do not write code that references controls using the value of the generated UniqueID property. You can treat the UniqueID
property as a handle (for example, by passing it to a process), but you should not rely on it having a specific structure.

In addition to each container control providing a naming container for its child controls, the page itself also provides a naming
container for all of its child controls. This creates a unique namespace within the application for all the controls on that page.
Using the NamingContainer Property
Child controls can reference their naming container via the NamingContainer property. This property returns an object of type
Control that you can cast to the appropriate DataList control, DataListItem object, and so on.
Referencing the naming container is useful when you need access from a child control to a property of the container control.
For example, in a handler for a child control's DataBinding event, you can access the DataItem object by getting it from the
naming container.
Note
The NamingContainer property does not necessarily reference the same control as the Parent property. For example, in a R
epeater control, you might have an item template containing a table that in turn contains a Label control. The parent control
of the label is a table cell (for example, a HtmlTableCell object), but its naming container is the DataListItem object, because i
t is the DataListItem that defines the namespace for the Label control, not the table.

Referencing Controls
If your page contains controls that are generated at run time, such as those in a template for the DataList, Repeater, or
GridView controls, you cannot directly reference them by their ID, because the ID is not unique. However, there are various
ways to find individual controls in the page. For details, see Accessing ASP.NET Controls Programmatically.
See Also
Concepts
Web Forms Control ID Resolution
ASP.NET

Web Forms Control ID Resolution


When you declare an ID attribute on a Web server control to provide programmatic access to that control, the ASP.NET page
framework automatically ensures that the ID you declare will be unique across your entire ASP.NET Web application.
The Naming Container
The ASP.NET page framework provides your applications with automatic control ID resolution through the INamingContainer
interface, which generates a naming container for each class that implements it. A naming container defines a new ID
namespace within an ASP.NET Web page control hierarchy. A naming container then allows the page framework to generate a
value for the UniqueID property of each Control object generated within that namespace. The UniqueID property is different
from the ID property that you declare in that it is the fully qualified identifier for a control.
The classes that implement INamingContainer include: Page, DataList, GridView, DataListItem, DataGridItem, and Repeater. In
general, controls that can create child controls dynamically implement INamingContainer.
The Page class serves as the top-level naming container for that page's control hierarchy.
Name Resolution in Data-Binding Scenarios
The automatic naming resolution provided by the page framework becomes important in data-binding scenarios. Consider the
following example, which shows controls declared on a page.
VB
<asp:Repeater id="MyDataList" runat="server">
<ItemTemplate>
<asp:Label id="MyLabel" Text="<%# Container.ToString() %>" runat="server"/><br />
</ItemTemplate>
</asp:Repeater>
<hr />
<asp:Label id="ResultsLabel" runat="server" AssociatedControlID="MyDataList"/>

C#
<asp:Repeater id="MyDataList" runat="server">
<ItemTemplate>
<asp:Label id="MyLabel" Text="<%# Container.ToString() %>" runat="server"/><br />
</ItemTemplate>
</asp:Repeater>
<hr />
<asp:Label id="ResultsLabel" runat="server" AssociatedControlID="MyDataList"/>

When the Label control is bound to a data source and the Repeater control iterates through the items from that data source,
the page must be able distinguish programmatically the different instances of the Label control, even though you have
assigned only the ID MyLabel to each instance. The page framework does this by using the fully qualified UniqueID property
for each control. For example, the following code generates three versions of the Label control and writes their UniqueID
property values to the page.
VB
<script language="vb" runat="server">

Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)


Dim sb As New StringBuilder()
sb.Append("Container: " + _
MyDataList.NamingContainer.ToString() + "<p>")

Dim a As New ArrayList()


a.Add("A")
a.Add("B")
a.Add("C")
MyDataList.DataSource = a
MyDataList.DataBind()

Dim i As Integer
Dim l As Label
For i = 0 To MyDataList.Controls.Count - 1
l = CType(CType(MyDataList.Controls(i), RepeaterItem).FindControl("MyLabel"),
Label)
sb.Append("Container: " & _
CType(MyDataList.Controls(i), RepeaterItem).NamingContainer.ToString() & _
"<p>")
sb.Append("<b>" & l.UniqueID.ToString() & "</b><p>")
Next
ResultsLabel.Text = sb.ToString()
End Sub
</script>

C#
<script language="c#" runat="server">

void Page_Load(Object sender, EventArgs e)


{
StringBuilder sb = new StringBuilder();
sb.Append("Container: " +
MyDataList.NamingContainer.ToString() + "<p>");

ArrayList a = new ArrayList();


a.Add("A");
a.Add("B");
a.Add("C");
MyDataList.DataSource = a;
MyDataList.DataBind();

for (int i = 0; i < MyDataList.Controls.Count; i++)


{
Label l =
(Label)((RepeaterItem)MyDataList.Controls[i]).FindControl("MyLabel");
sb.Append("Container: " +
((RepeaterItem)MyDataList.Controls[i]).NamingContainer.ToString() +
"<p>");
sb.Append("<b>" + l.UniqueID + "</b><p>");
}
ResultsLabel.Text = sb.ToString();
}
</script>

When this page is requested, it writes the following to the page:


The naming container of the Repeater control named MyDataList. This naming container depends upon the name given
to the .aspx file.
Note
If the .aspx file for this example were MySample1.aspx, the class of the naming container would be ASP.mysample1_asp
x, but the naming container would be Page.

The instance of the next control that serves as a naming container, namely the Repeater control. This container name is
displayed with its entire namespace qualifier.
The UniqueID property of each Label control inside the Repeater control.
Note
Do not write code that references controls using the value of the generated UniqueID property. You can treat the Uni
queID property as a handle (for example, by passing it to a process), but you should not rely on it having a specific stru
cture.

See Also
Tasks
How to: Locate Child Controls by ID in an ASP.NET Web Page
How to: Access Members of a Web Server Control's Naming Container
Concepts
Using the NamingContainer Property to Determine a Control's Naming Container
Other Resources
ASP.NET Web Server Controls
ASP.NET

How to: Locate Child Controls by ID in an ASP.NET Web Page


You can get a reference to a specific control using a method that searches its naming container for the control's ID.
To locate a control by ID
Call the FindControl method of the naming container, passing it a string containing the ID of the control you want to use.
The method returns an object of type Control that you can cast to the appropriate type.
The following code example shows how you can locate a specific control. The sample is a handler for the Click event of a
button in a GridView control. When the button is clicked, the code searches for a control named Label1 in the current
GridView item, which is the Label control's naming container. If the control is found, its text is displayed in a second
Label control named LabelText elsewhere on the page.
VB
Protected Sub GridView1_ItemCommand(ByVal source As Object, _
ByVal e As GridViewCommandEventArgs) _
Handles GridView1.ItemCommand
Dim l As Label
l = CType(e.Item.FindControl("Label1"), Label)
If (Not l Is Nothing) Then
LabelText.Text = l.Text
End If
End Sub

C#
protected void GridView1_ItemCommand(object source,
GridViewCommandEventArgs e)
{
Label l;
l = (Label) e.Item.FindControl("Label1");

if(!(l == null) ){
LabelText.Text = l.Text;
}
}

See Also
Concepts
Web Forms Control Identification
ASP.NET

Using the Controls Collection in an ASP.NET Web Page


The Control class and its derived classes (including the Page class) expose a Controls property that returns a ControlCollection
instance. This hierarchy allows you to walk the control tree programmatically to search for specific controls on a page, as well
as to check the type of controls within the collection in order to access their properties. The following code example shows how
to walk through the page's control hierarchy to find instances of the <asp:TextBox> control (of which there is only one).
Security Note
This example has a text box that accepts user input, which is a potential security threat. By default, ASP.NET Web pages valida
te that user input does not include script or HTML elements. For more information, see Script Exploits Overview.

VB
<%@ Page Language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >

<head id="head1" runat="server">

<title>Using the Controls Collection in a Web Form</title>

<script language="vb" runat="server">

Private Sub ChangeBtn_Click(ByVal sender As Object, ByVal e As EventArgs)

Dim c As Control
Dim c2 As Control

For Each c In Page.Controls


If c.Controls.Count > 0 Then
For Each c2 In c.Controls
If c2.GetType.ToString = "System.Web.UI.WebControls.TextBox" Then
MySpan.InnerHtml = CType(c2, TextBox).Text
CType(c2, TextBox).Text = ""
End If
Next
End If
Next
End Sub
</script>

</head>
<body>
<form id="form1" runat="server">
<table width="80%"
border="1"
cellpadding="1"
cellspacing="1">
<tr>
<td align="center" style="width:50%;">
<asp:TextBox id="MyTextBox"
text="Type something here"
runat="server"/>
</td>
<td align="center" style="width:50%;">
<span id="myspan" runat="server">&nbsp;</span>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input id="changebtn"
type="submit"
onserverclick="changebtn_click"
value="move your text"
runat="server" />
</td>
</tr>
</table>
</form>
</body>
</html>

C#
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<head id="head1" runat="server">
<title>Using the Controls Collection in a Web Form</title>

<script language="c#" runat="server">

private void ChangeBtn_Click(object sender, EventArgs e)


{
foreach(Control c in Page.Controls)
{
if (c.Controls.Count > 0)
{
foreach(Control c2 in c.Controls)
{
if (c2.GetType().ToString() == "System.Web.UI.WebControls.TextBox")
{
myspan.InnerHtml = ((TextBox)c2).Text;
((TextBox)c2).Text = "";
}
}
}
}
}

</script>
</head>
<body>
<form id="form1" runat="server">
<table width="80%"
border="1"
cellpadding="1"
cellspacing="1">
<tr>
<td align="center" style="width:50%;">
<asp:TextBox id="MyTextBox"
text="Type something here"
runat="server"/>
</td>
<td align="center" style="width:50%;">
<span id="myspan" runat="server">&nbsp;</span>
</td>
</tr>

<tr>
<td colspan="2" align="center">
<input id="changebtn"
type="submit"
onserverclick="ChangeBtn_Click"
value="move your text"
runat="server" />
</td>
</tr>
</table>
</form>
</body>
</html>

See Also
Other Resources
Accessing ASP.NET Controls Programmatically
ASP.NET

How to: Locate the Web Forms Controls on a Page by Walking


the Controls Collection
Every container control on the page, and the page itself, has a Controls collection that you can use to get to individual controls.
To locate controls in the Controls collection
Loop through the Controls collection of the container control. The collection is of type ControlCollection, and returns
objects of type Control.
The following example illustrates how to walk the Controls collection. The example assumes an ASP.NET Web page with
at least one TextBox control on it, a Label control, and a Button control. The code gets all the child controls of the Page
object. Because this would produce only a few high-level child controls, including the HtmlForm object, the code also
walks the Controls collection of each individual child control. The code looks for text boxes by comparing the type of
each control. When it finds a text box, it gets the text box's value and concatenates it into a string that is displayed at the
end in a Label control.
This example finds only the controls contained in the Page object and the controls that are direct children of the page. It
does not find text boxes that are children of a control that is in turn a child of the page. For example, if you added a Panel
control to page, the Panel control would be a child of the HtmlForm control contained by the Page, and it would be
found in this example. However, if you then added a TextBox control into the Panel control, the TextBox control text
would not be displayed by the example, because it is not a child of the page or of a control that is a child of the page. A
more practical application of walking the controls this way would be to create a recursive method that can be called to
walk the Controls collection of each control as it is encountered. However, for clarity, the example below is not created as
a recursive function.
VB
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim allTextBoxValues As String = ""
Dim c As Control
Dim childc As Control
For Each c In Page.Controls
For Each childc In c.Controls
If TypeOf childc Is TextBox Then
allTextBoxValues &= CType(childc, TextBox).Text & ","
End If
Next
Next
If allTextBoxValues <> "" Then
Label1.Text = allTextBoxValues
End If
End Sub

C#
private void Button1_Click(object sender, System.EventArgs e)
{
string allTextBoxValues = "";
foreach (Control c in Page.Controls)
{
foreach (Control childc in c.Controls)
{
if (childc is TextBox)
{
allTextBoxValues += ((TextBox)childc).Text + ",";
}
}
}
if (allTextBoxValues != "")
{
Label1.Text = allTextBoxValues;
}
}

See Also
Concepts
Web Forms Control Identification
ASP.NET

Using the NamingContainer Property to Determine a Control's


Naming Container
You can walk up the control tree on a page by means of the NamingContainer property. In contrast to the Container keyword,
which is available only in inline code (that is, in a declarative <%# %> expression), the NamingContainer property is
available in code to any instance of that class or of a derived class.
The following code example illustrates how to walk the control tree of an ASP.NET Web page. The button's ChangeBtn_Click
method handler searches for a control named Message in the first item of a Repeater control using the FindControl method,
and then determines the NamingContainer object for that control. It then determines the naming container for the control
returned by the first call to the NamingContainer property, and so on up the control tree until it finds a control that has no
naming container. (Note that the WalkContainers method will also add the type of the control at the lowest level, which is not
itself a naming container.)
VB
<html xmlns="http://www.w3.org/1999/xhtml" >

<head id="head1" runat="server">


<title>NamingContainer Example</title>
</head>

<script language="vb" runat="server">

Dim list As ArrayList

Private Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)

list = New ArrayList

list.Add("One")
list.Add("Two")
list.Add("Three")
MyRepeater.DataSource = list
MyRepeater.DataBind()
End Sub

Private Sub ChangeBtn_Click(ByVal sender As Object, ByVal e As EventArgs)

Dim x As Control = MyRepeater.Items(0).FindControl("Message")

If Not x Is Nothing Then


list = WalkContainers(x)
End If
MyRepeater.DataSource = list
MyRepeater.DataBind()
End Sub

Private Function WalkContainers(ByVal ctl As Control) As ArrayList


Dim ret As New ArrayList
Dim parent As Control = ctl.NamingContainer

If Not parent Is Nothing Then


Dim sublist As ArrayList = WalkContainers(parent)
Dim j As Integer
For j = 0 To sublist.Count - 1
ret.Add(sublist(j))
Next
End If
ret.Add(ctl.GetType.Name)
Return ret
End Function
</script>
<body>
<form id="repeaterform" runat="server">
<h3>Using the NamingContainer Property to Determine a
Control's Naming Container
</h3>
<table id="mytable" width="80%">
<asp:repeater id="MyRepeater" runat="server">
<ItemTemplate>
<tr>
<td align="center" style="width:100%;">
<span id="message" runat="server">
<%#Container.DataItem%>
</span>
</td>
</tr>
</ItemTemplate>
</asp:repeater>
<tr>
<td align="center" style="width:100%;">
<input id="changebtn"
type="submit"
onserverclick="changebtn_click "
runat="server" />
</td>
</tr>
</table>
</form>
</body>
</html>

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

<head id="head1" runat="server">


<title>NamingContainer Example</title>
</head>

<script language="c#" runat="server">


ArrayList list;

private void Page_Load(object sender, EventArgs e)


{
list = new ArrayList();
list.Add("One");
list.Add("Two");
list.Add("Three");
MyRepeater.DataSource = list;
MyRepeater.DataBind();
}

private void ChangeBtn_Click(object sender, EventArgs e)


{
Control x = MyRepeater.Items[0].FindControl("Message");
if (x != null) list = WalkContainers(x);
MyRepeater.DataSource = list;
MyRepeater.DataBind();
}

private ArrayList WalkContainers(Control ctl)


{
ArrayList ret = new ArrayList();
Control parent = ctl.NamingContainer;
if (parent != null)
{
ArrayList sublist = WalkContainers(parent);
for (int j = 0; j < sublist.Count; j++) ret.Add(sublist[j]);
}
ret.Add(ctl.GetType().Name);
return ret;
}
</script>

<body>
<form id="repeaterform" runat="server">
<h3>Using the NamingContainer Property to Determine a
Control's Naming Container
</h3>
<table id="mytable" width="80%">
<asp:repeater id="MyRepeater" runat="server">
<ItemTemplate>
<tr>
<td align="center" style="width:100%;">
<span id="message" runat="server">
<%#Container.DataItem%>
</span>
</td>
</tr>
</ItemTemplate>
</asp:repeater>
<tr>
<td align="center" style="width:100%;">
<input id="changebtn"
type="submit"
onserverclick="ChangeBtn_Click"
runat="server" />
</td>
</tr>
</table>
</form>
</body>
</html>

See Also
Concepts
Web Forms Control ID Resolution
ASP.NET

How to: Access Members of a Web Server Control's Naming


Container
At times, you need to access properties or methods of a control's naming container. For example, during data binding, the
naming container makes available a DataItem property containing the data to which controls are bound. You can access the
containing control in different ways, depending on context.
To access the naming container from a data-binding expression
In the data-binding expression, use the Container keyword, which returns a reference to the container. You can then
access the container's properties or methods.
This keyword is used most commonly in the Eval method to get values from the naming container's DataItem object, but
can be used outside of that method as well. The following example shows a Label control that might be in a template for
a DataList, Repeater, or GridView control. It displays the current item number followed by the current Title data item of
the naming container.
VB
<asp:Label ID="Label1" runat="server">
<%# Container.DataItemIndex + 1 %>. <%# Eval("Title") %>
</asp:Label>

C#
<asp:Label ID="Label1" runat="server">
<%# Container.DataItemIndex + 1 %>. <%# Eval("Title") %>
</asp:Label>

The following example is similar, but gets a value (the Author item) from the naming container's DataItem object:
VB
<asp:Label ID="Label2" runat="server" >
<%# DataBinder.Eval(Container.DataItem, "Author") %>
</asp:Label>

C#
<asp:Label ID="Label2" runat="server" >
<%# DataBinder.Eval(Container.DataItem, "Author") %>
</asp:Label>

Note
The NamingContainer property does not necessarily reference the same control as the Parent property. For example,
in a Repeater control, you might have an item template containing a table that in turn contains a Label control. The pa
rent control of the label is a table cell (for example, a HtmlTableCell object), but its naming container is the DataListItem
object, because it is the DataListItem that defines the namespace for the Label control, not the table.

A complete example using the syntax shown above to get property values is shown below.
VB
<%@ Page Language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/x


html1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>Naming Container Example</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:XmlDataSource ID="XmlDataSource1"
runat="server"
XPath="Books/LanguageBooks/Book">
<Data>
<Books>
<LanguageBooks>
<Book Title="Pure JavaScript"
Author="Wyke, Gilliam, and Ting"/>
<Book Title="Effective C++ Second Edition"
Author="Scott Meyers"/>
<Book Title="Assembly Language Step-By-Step"
Author="Jeff Duntemann"/>
<Book Title="Oracle PL/SQL"
Author="Steven Feuerstein"/>
</LanguageBooks>
<SecurityBooks>
<Book Title="Counter Hack"
Author="Ed Skoudis"/>
</SecurityBooks>
</Books>
</Data>
</asp:XmlDataSource>
<asp:GridView ID="GridView1"
runat="server"
DataSourceID="XmlDataSource1"
AutoGenerateColumns="False">
<Columns>
<asp:TemplateField HeaderText="Title" >
<ItemTemplate>
<asp:Label ID="Label1" runat="server">
<%# Container.DataItemIndex + 1 %>. <%# Eval("Title") %>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Author">
<ItemTemplate>
<asp:Label ID="Label2" runat="server" >
<%# DataBinder.Eval(Container.DataItem, "Author") %>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
</form>
</body>
</html>

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

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/x


html1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>Naming Container Example</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:XmlDataSource ID="XmlDataSource1"
runat="server"
XPath="Books/LanguageBooks/Book">
<Data>
<Books>
<LanguageBooks>
<Book Title="Pure JavaScript"
Author="Wyke, Gilliam, and Ting"/>
<Book Title="Effective C++ Second Edition"
Author="Scott Meyers"/>
<Book Title="Assembly Language Step-By-Step"
Author="Jeff Duntemann"/>
<Book Title="Oracle PL/SQL"
Author="Steven Feuerstein"/>
</LanguageBooks>
<SecurityBooks>
<Book Title="Counter Hack"
Author="Ed Skoudis"/>
</SecurityBooks>
</Books>
</Data>
</asp:XmlDataSource>
<asp:GridView ID="GridView1"
runat="server"
DataSourceID="XmlDataSource1"
AutoGenerateColumns="False">
<Columns>
<asp:TemplateField HeaderText="Title" >
<ItemTemplate>
<asp:Label ID="Label1" runat="server">
<%# Container.DataItemIndex + 1 %>. <%# Eval("Title") %>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Author">
<ItemTemplate>
<asp:Label ID="Label2" runat="server" >
<%# DataBinder.Eval(Container.DataItem, "Author") %>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
</form>
</body>
</html>

To access the naming container from code


Get the control's NamingContainer property and cast it to the container's class type, such as GridViewRow.
For an example, see Using the NamingContainer Property to Determine a Control's Naming Container.

See Also
Reference
Data Binding Expression Syntax
Concepts
Web Forms Control Identification
Other Resources
Accessing ASP.NET Controls Programmatically
ASP.NET

ASP.NET Web Server Controls and Browser Capabilities


Different browsers, and different versions of the same browser, support different features. ASP.NET server controls will
automatically determine the browser that has requested the page and render the appropriate markup for that browser.
However, some control features cannot be rendered on older browsers, so it is a good idea to look at the output of your pages
on as many browser types as you can to make sure that the pages are presented to all browsers the way you want them to be.
Autodetection of Browser Types
By default, the ASP.NET page framework determines browser capabilities by reading the user-agent information passed from
the browser to the server during a request. (This information is available as the UserAgent property of the HttpRequest object.)
The page matches the user-agent information against agent entries in configuration files and browser definition files.
Note
The browserCaps Element (ASP.NET Settings Schema) section of configuration files (.config) has been deprecated in the .NET
Framework version 2.0. For backward compatibility, the configuration settings in this section are still effective if they are set a
t the application level, but are merged with the information contained in browser definition files (.browser) located in the ma
chine-level %SystemRoot%\Microsoft.NET\Framework\versionNumber\CONFIG\Browsers folder and any existing applicatio
n-level App_Browser folders. For more information, see Browser Definition File Schema (browsers Element).

When the page finds a match between the current user-agent information and user agents listed in the file, it can read the
corresponding browser capabilities, such as whether the browser supports scripting, styles, frames, and so on. Based on these
capabilities, the controls on the page render Web controls using appropriate markup, such as XHTML, HTML 3.2, and so on. If
ASP.NET is rendering HTML, it can determine whether to render recent (cascading style sheet-compliant) or earlier (non-CSS-
compliant) versions of HTML elements. For older browsers, ASP.NET renders formatting information using tags (for example, a
<font> tag) rather than using CSS styles.
Overriding Browser Type Detection
If you want to explicitly control how the page is rendered instead of relying on automatic browser detection, you can set the
page's ClientTarget property. You can set the property declaratively as an attribute of the @ Page directive for that page, or you
can set it programmatically.
The value of the ClientTarget property is an alias for the type of browser you want to render the page for. For example, to
force the page to render for Microsoft Internet Explorer 6.0, you can use the alias uplevel. The alias must be defined in the
clientTarget Element (ASP.NET Settings Schema) section of the configuration file. The predefined defaults are ie5, ie4, uplevel,
and downlevel.
By specifying the alias downlevel, you can force the page to render HTML 3.2-compatible elements no matter what browser
has requested the page. Similarly, by specifying uplevel, you can force the page to render CSS style attributes even for older
browser versions.
You can create additional aliases by defining them in the Machine.config or Web.config file, which enables you to create
custom browser definitions. For more information, see ASP.NET Configuration Settings.
Client Script
Some functionality of ASP.NET server controls depends on being able to run client script. The client script is automatically
generated and sent as part of the page, if the browser is capable of executing script. Even so, some users might have turned off
script execution in their browsers, and will therefore not be able to fully use the control's capabilities. For more information,
see Client Script in ASP.NET Web Pages.
"Uplevel" and "Downlevel" Browser Capabilities
Browsers for desktop computers are split into two distinctive groups: "uplevel" (newer versions) and "downlevel" (earlier
versions). These groups define the type of native support a browser or client device offers, and they generally determine the
presentation and behavior of a loading page from a Web server.
Browsers and client devices that are considered "uplevel" usually support at least the following:
ECMAScript (JScript, JavaScript) version 1.2.
HTML version 4.0.
The Microsoft Document Object Model (MSDOM).
Cascading style sheets (CSS).
"Downlevel" browsers and client devices support the following only:
HTML version 3.2
The server control properties listed in the following table render differently in uplevel and downlevel browsers.
Server co Rendering behavior in uplevel and downlevel browsers
ntrol pro
perty
AccessKe This property does not work on any downlevel browsers for any controls. It is not HTML 4.0 and works only in Inter
y net Explorer 4.0 or later.

BackCol This property works on downlevel browsers for only certain controls: Table, Panel, GridView, Calendar, and
or ValidationSummary. It also works for CheckBoxList, RadioButtonList, and DataList if the layout is in a Table control.
In general, only controls that render as a <table> tag can output a background color in HTML 3.2, whereas almost
anything can in HTML 4.0. For controls that render in <span> tags, including Label controls, validator controls, and
list controls in Flow mode, BackColor works in Internet Explorer 5 or later but not in Internet Explorer 4.0.

BorderC This property works on downlevel browsers only for the same table-based controls as BackColor. However, it is ou
olor tput as the bordercolor attribute, which is not part of the HTML 3.2 standard. Some browsers support this attribute,
including Internet Explorer 3.0 and later, but not all browsers do.

BorderSt This property does not work on any downlevel browsers. There is no equivalent to it in HTML 3.2.
yle

BorderW This property works only in controls that render as an HTML <table> element (Table, Panel, GridView, and Calen
idth dar) or as an <img> element (Image, AdRotator). BorderWidth only works on downlevel browsers if specified in p
ixels; otherwise, it is always rendered as either border=1 or border=0. Also, BorderWidth only works with table-b
ased controls if GridLines is set to a value other than None. This is because there is no way to specify a border with
out gridlines in HTML 3.2. For controls that render as <span> tags, including Label controls, validator controls, and
list controls in Flow mode, BorderWidth works in Internet Explorer 5 or later, but not in Internet Explorer 4.0.

CssClass This property is always rendered as the class attribute, regardless of the browser. Most uplevel browsers recognize
the class attribute.

Enabled This property is used to specify whether a control raises its events and functions. In Internet Explorer 4.0 or later, set
ting Enabled to false has the effect of making the control appear unavailable and locked from input, using the disa
bled=true attribute.

Font-Bol These properties are rendered as style attributes for uplevel browsers (for example, Font-Weight for bold and Fon
d, Font-It t-Style for italic) and as independent elements (for example, <b> and <i>) for downlevel browsers.
alic, Font
-Strikeou
t and simi
lar proper
ties

Font-Siz This property works on downlevel browsers for all controls only if named font sizes are used (Small, Smaller, and so
e on). In uplevel browsers, this property is rendered as a style attribute; in downlevel browsers, it is rendered as a <f
ont> element.

Font-Ove This property does not work on any downlevel browser.


rline
ForeColo This property works on downlevel browsers for all controls except Image, AdRotator, HyperLink, and LinkButton. F
r or downlevel browsers, ForeColor is rendered in <font> tags.

Height This property does not work on downlevel browsers for Label controls, validator controls, HyperLink controls, or L
inkButton controls. Height also does not work for CheckBoxList, RadioButtonList, and DataList controls if the l
ayout for those controls is set to Flow. Only pixel and percentage measurements work.
For table-based controls, height on inner tables is not rendered for downlevel browsers because the Height attribut
e has been deprecated in HTML 4.01. This results in a slightly different appearance between the uplevel and downle
vel rendering. The most obvious difference will be if BackColor is set on the SideBarStyle property: in uplevel the B
ackColor appears to be the entire length of that column and in downlevel browsers it will only be as long as requir
ed to accommodate the text buttons.

TabInde This property does not work on any downlevel browsers for any controls. It is not HTML 4.0 and only works in Inter
x net Explorer 4.0 or later.

ToolTip This property does not work on any downlevel browsers.

Width This property does not work on downlevel browsers for Label, HyperLink, LinkButton, or validator controls. Widt
h also does not work for CheckBoxList, RadioButtonList, and DataList controls if the layout is set to Flow. Only p
ixel and percentage measurements work.

See Also
Tasks
How to: Detect Browser Types in ASP.NET Web Pages
Walkthrough: Developing and Using a Custom Server Control
Reference
clientTarget Element (ASP.NET Settings Schema)
ClientTarget
HttpBrowserCapabilities
Browser
UserAgent
WebControl
Other Resources
Programming ASP.NET Web Pages
Developing Custom ASP.NET Server Controls
ASP.NET

Securing Browser Definition Files


Browser definition files (.browser files) contain information about the capabilities of classes of browsers (such as Internet
Explorer) and specific browsers (such as Internet Explorer 6.0). At run time, ASP.NET uses the information in .browser files to
determine what browser has made the request, what capabilities the browser has, and how to render markup to that browser.
For more information, see Browser Definition File Schema (browsers Element).
For detailed information about best practices for writing secure code and securing applications, see the book "Writing Secure
Code" by Michael Howard and David LeBlanc, and see the guidance provided by Microsoft Patterns and Practices.
Note
Browser definition files are new in the .NET Framework version 2.0. In earlier versions of the .NET Framework, the browserC
aps element was used to define browser definitions in configuration files.

Browser Definition File Security


All browser capability features, including the .NET Framework classes and the browser definition files, require partial trust at
the application level, and require full trust at the global level. The global browser definition assembly is signed with a unique
machine key before placement in the global assembly cache and cannot be tampered with. The browser definition files in the
%SystemRoot%\Microsoft.NET\Framework\version\CONFIG\Browsers directory are protected by access control lists (ACLs)
and require administrative privileges to modify.
Browser Definition File Directories
The global Browser directory and the application-level App_Browsers subdirectory should contain only files with the file name
extension .browser. Only .browser files are compiled by the ASP.NET browser capabilities feature. Additionally, ASP.NET
protects the files in these directories from being served by the Web server and from being accessed by code in other
applications.
Browser Definition Files ACLs
The following table lists the ACLs that are set by default on the .browser files located in the
%SystemRoot%\Microsoft.NET\Framework\version\CONFIG\Browsers directory. These ACLs are also set on the directory itself,
but they include Modify permissions for the CREATOR OWNER group. The directory is read only.
Windows account Permissions
Administrators Full control

ASP.NET Machine Account (<server>\ASPNET) Read and Execute

CREATOR OWNER Full control

IIS_WPG (<server>\IIS_WPG) Read and Execute

LOCAL SERVICE Read and Execute

NETWORK SERVICE Read and Execute

Power Users (<server>\Power Users) Modify

SYSTEM Full control

Users (<server>\Users) Read and Execute

The following table lists the ACLs that should be set on application-level .browser files in the App_Browsers subdirectory.
Windows account Permissions
Administrators Full control

IIS_WPG (<server>\IIS_WPG) Read and Execute

INTERACTIVE Read

Internet Guest Account (<server>\IUSR_<server>) Read

NETWORK Read

NETWORK SERVICE Read

SYSTEM Full control

Users (<server>\Users) Read and Execute

ASP.NET Web Site Administration Tool account Special


Adding Browser Definition Files
Do not download or install browser definition files unless you trust their source. For example, examine a new browser
definition file to see if any unfamiliar namespaces are referenced in any of the following attributes:
The markupTextWriterType attribute of the controlAdapters element.
The value attribute of the capability element.
The controlType and adapterType attributes of the adapter element.
For information about valid elements and attributes, see Browser Definition File Schema (browsers Element).
Changing Browser Definition Files
If you add new browser definition files to the global directory or if you make changes to global browser definition files, those
changes have no effect until you manually recompile the browser capabilities collection using the Aspnet_regbrowsers.exe tool,
available in the %SystemRoot%\Microsoft.NET\Framework\version folder, or programmatically cause recompilation by using
the BrowserCapabilitiesCodeGenerator class.
However, you do not need to recompile changes to application-level browser definitions. Changes to those definitions are
recompiled and reapplied dynamically.
Securing Browser Definition Files in a Shared Hosting Environment
In a shared hosting environment, malicious users can potentially modify browser definition file settings through direct
modification of the browser definition files, modification via the configuration APIs, and other administration and configuration
tools. To mitigate this threat, maintain strong ACLs on browser definition files. The contents of browser definition file
directories are compiled, therefore they should be protected in the same way as any other code directory in the application. If a
user is prevented by the host administrator from adding code to an application, the user should also be prevented from adding
browser definition files.
Holding a File-Lock on a Browser Definition File
Only multiple attempts to save to a browser definition file or open a file handle can lock a browser definition file. A malicious
user might attempt to lock the browser definition files in the
%SystemRoot%\Microsoft.NET\Framework\version\CONFIG\Browsers directory. However, locking a browser definition file
requires Full trust, which is disabled in ASP.NET by default.
Using the Configuration API to Read Arbitrary Files
The classes of the browser definition configuration API cannot read any directories that are not part of the application domain,
or any files that do not have a .browser file name extension.
Caching Browser Capabilities
At run time, browser definition file information is merged into a collection of known browsers in a BrowserCapabilitiesFactory
object. When a request is made, ASP.NET identifies the requesting browser by the request header and compiles an
HttpCapabilitiesBase object that corresponds to the requesting browser. The object is cached and might be used again for a
different request made by the same browser.
A malicious client might try to flood your Web server with requests where each new request uses a different request header,
causing ASP.NET to generate and cache browser capability objects for each request, which in turn can result in a denial-of-
service attack. To mitigate this threat, configure the userAgentCacheKeyLength attribute of the
browserCaps Element (ASP.NET Settings Schema) element in the Machine.config file or a Web.config file. This element defines
the character length to use as the key to identify cached capabilities objects in the internal cache. The default is 64. You can
reduce this value to make it more likely that a matching browser will be found in the cache, reducing the load on the cache.
Exceptions
To help prevent sensitive information from being exposed to unwanted sources, configure your application either not to
display detailed error messages or to display detailed error messages only when the client is the Web server itself. For more
information, see customErrors Element (ASP.NET Settings Schema).
Event Log
If your server is running Windows Server 2003, you can improve the security of your application by securing the event log and
by setting parameters regarding the size, retention, and other features of the event log to help prevent an indirect denial of
service attack. For more information about configuring event logs, search for "Event Viewer" in Windows Help and Support.
See Also
Tasks
How to: Detect Browser Types in ASP.NET Web Pages
Reference
Browser Definition File Schema (browsers Element)
Concepts
ASP.NET Web Server Controls and Browser Capabilities
Securing Browser Definition Files
Configuration Inheritance
ASP.NET Device Filtering Overview
Architectural Overview of Adaptive Control Behavior
ASP.NET Mobile Web Development Overview
Securing ASP.NET Configuration
Other Resources
ASP.NET Web Site Security
ASP.NET

ASP.NET Web Server Controls Templates


Most Web server controls have a default look and layout, which you can manipulate by setting properties or by using styles.
Some Web server controls also allow you to customize their look by using templates.
A template is a set of HTML elements and controls that make up the layout for a particular portion of a control. For example, in
the DataList Web server control you can use a combination of HTML elements and controls to create the layout for each row of
the list. Similarly, the GridView Web server control has a default look for rows in the grid. However, you can customize the
grid's look by defining different templates for individual columns.
Note
Templates differ from styles. A template defines the content of a section of a control—for example, the contents of a row in t
he DataList control. Styles specify the appearance of elements such as color, font, and so on. Styles can apply to the control a
s a whole (for example, to set the font for the GridView control) as well as to template items.

Templates consist of HTML and embedded server controls. When the control runs in the ASP.NET Web page, the control
infrastructure renders the contents of the template in place of the default HTML for the control.
Which Controls Support Templates?
Not all Web server controls support templates. For the most part, templates are supported by complex controls. This includes
the GridView, DataList, Repeater, FormView, DetailsView, Login, and other controls.
Each control supports a slightly different set of templates that specify layouts for different portions of the control, such as the
header, footer, item, and selected item. You can specify a template for any or all of these, depending on which ones you want to
customize. In the GridView control, you can specify templates for columns (rather than rows).
The following table summarizes the Web server controls that support templates.
Control Templates
ChangePassword ChangePasswordTemplate
SuccessTemplate

CompleteWizardStep ContentTemplate
CustomNavigationTemplate

CreateUserWizard HeaderTemplate
SideBarTemplate
StartNavigationTemplate
StepNavigation
FinishNavigation

CreateUserWizardStep ContentTemplate
CustomNavigationTemplate
DataList HeaderTemplate
FooterTemplate
ItemTemplate
AlternatingItemTemplate
SeparatorTemplate
SelectedItemTemplate
EditItemTemplate

DetailsView HeaderTemplate
FooterTemplate
PagerTemplate
EmptyDataTemplate

FormView ItemTemplate
EditItemTemplate
InsertItemTemplate
HeaderTemplate
FooterTemplate
PagerTemplate
EmptyDataTemplate

GridView PagerTemplate
EmptyDataTemplate

Login LayoutTemplate

LoginView AnonymousTemplate
LoggedInTemplate

Menu DynamicTemplate
StaticTemplate

PasswordRecovery QuestionTemplate
SuccessTemplate
UserNameTemplate
Repeater HeaderTemplate
FooterTemplate
ItemTemplate
AlternatingItemTemplate
SeparatorTemplate

SiteMapPath CurrentNodeTemplate
RootNodeTemplate
NodeTemplate
PathSeparatorTemplate

Wizard FinishNavigationTemplate
HeaderTemplate
StartNavigationTemplate
StepNavigationTemplate
SideBarTemplate

Creating Templates
You can create templates directly in the .aspx file. Templates are created as XML declarations. The following example shows
how you can display a list of employee names, phone numbers, and e-mail addresses using templates in the DataList control.
The layout of the employee information is specified in the ItemTemplate using data-bound controls.
Note
If you are using a visual designer, such as Visual Studio 2005, you can typically use a visual tool to create and edit templates.
For more information, see How to: Create Web Server Control Templates Using the Designer.

VB
<asp:datalist id="DataList1" runat="server">
<HeaderTemplate>
Employee List
</HeaderTemplate>
<ItemTemplate>
<asp:label id="Label1" runat="server"
Text='<%# DataBinder.Eval(Container, "DataItem.EmployeeName")%>'></asp:label>
<asp:label id="Label2" runat="server"
Text='<%# DataBinder.Eval(Container, "DataItem.PhoneNumber")%>'></asp:label>
<asp:Hyperlink id="Hyperlink1" runat="server"
Text='<%# DataBinder.Eval(Container, "DataItem.Email") %>'
NavigateURL='<%# DataBinder.Eval(Container, "DataItem.Link") %>'>
</asp:Hyperlink>
</ItemTemplate>
</asp:datalist>

C#
<asp:datalist id="DataList1" runat="server">
<HeaderTemplate>
Employee List
</HeaderTemplate>
<ItemTemplate>
<asp:label id="Label1" runat="server"
Text='<%# DataBinder.Eval(Container, "DataItem.EmployeeName")%>'></asp:label>
<asp:label id="Label2" runat="server"
Text='<%# DataBinder.Eval(Container, "DataItem.PhoneNumber")%>'></asp:label>
<asp:Hyperlink id="Hyperlink1" runat="server"
Text='<%# DataBinder.Eval(Container, "DataItem.Email") %>'
NavigateURL='<%# DataBinder.Eval(Container, "DataItem.Link") %>'>
</asp:Hyperlink>
</ItemTemplate>
</asp:datalist>

Working with Templates


A templated control creates an instance of its template contents only on demand. This means that instances of the controls in
the template might not be created when the page load event occurs. This behavior can affect how a control inside a template
can be used; you cannot assume that a control instance inside a template has been created when the page is loaded.
Nested templates as well as nested master files are not rendered in the Design view of Visual Web Developer or Visual Studio
2005. The nesting is correctly rendered on a Web browser, however.
See Also
Concepts
ASP.NET Web Server Controls and CSS Styles
Other Resources
ASP.NET Web Server Controls
Accessing Data with ASP.NET
Visual Web Developer

How to: Create Web Server Control Templates Using the


Designer
The GridView, DetailsView, FormView, DataList, and Repeater Web server controls enable you to specify templates, and to
define the markup and server controls that define a portion of the control. For example, in the GridView control, you can
define templates for items, selected items, alternating items, and so on, so that each of these elements can have a custom look.
This topic describes how you can use the designer to create templates. You can create templates directly in Visual Web
Developer. For information about template creation using ASP.NET syntax, see
How to: Create ASP.NET Web Control Templates Declaratively. For background information about templates, see
ASP.NET Web Server Controls Templates.
Note
Data-binding syntax that is placed in a <textarea> HTML element in a template will be HTML encoded if you edit the templa
te using the designer. For example, if you edited the template using the designer, <textarea id="TextArea1"><%# Eval("De
scription") %><textarea> would automatically be changed to <textarea id="TextArea1">&lt;%# Eval("Description")
%&gt;<textarea>. As an alternative, you can render a <textarea> HTML element by binding a TextBox control to your data fi
eld and then specifying that the TextMode property of the TextBox control is MultiLine.

To create a template in Visual Web Developer


1. In Design view, drag a GridView control to the design surface.
The GridView control task list is displayed next to the new GridView control.
2. In the task list, click Edit Template, and then select the template that you want to edit.
Visual Web Developer displays the control in template-editing mode.
3. In the template, add the HTML text and server controls that you want.
4. In the template, use one of the following three methods to edit the controls you have added, just as you would edit other
Web server controls:
Select the control, and then use the Properties window to set its properties.
Bind data to the property by using the DataBinding dialog box. For details, see
Using Data Binding with ASP.NET Mobile Controls.
Double-click an embedded control to create an ItemCommand event handler for the container control. Events
raised by embedded controls are sent to the container. For details, see ASP.NET Web Server Control Event Model.
5. Repeat steps 1 through 3 to edit other templates.
6. To finish, click End Template Editing in the task list.
7. Set the appearance of individual templates by setting their style properties. For details, see
ASP.NET Web Server Controls and CSS Styles.
See Also
Concepts
ASP.NET Web Server Controls Templates
ASP.NET Web Server Controls and CSS Styles
Other Resources
ASP.NET Web Server Controls (Visual Studio)
ASP.NET

How to: Create ASP.NET Web Control Templates Declaratively


Web server controls such as the Repeater, DataList, and GridView controls allow you to specify templates, which are HTML
elements that define the layout for a particular portion of the control. For example, in the GridView control, you can define
templates for items, selected items, alternating items, and so on, so that each of these elements can have a custom look.
Note
For background information about templates, see ASP.NET Web Server Controls Templates

To create a Web server control template using ASP.NET syntax


1. In the ASP.NET page, insert an element inside the control to identify what template you are creating, as shown in the
following example:
VB
<asp:DataList id="DataList1" runat="server">
<ItemTemplate>

</ItemTemplate>
</asp:DataList>

C#
<asp:DataList id="DataList1" runat="server">
<ItemTemplate>

</ItemTemplate>
</asp:DataList>

2. Inside the template element, add HTML text and other controls as the template's content. Include property and data-
binding values for the embedded controls using normal syntax, as shown in the following example:
VB
<asp:DataList id="DataList3" runat="server">
<ItemTemplate>
Name: <asp:Label ID="Label2" runat="server"
Text='<%# DataBinder.Eval(Container, "DataItem.EmployeeName")%>'/>
</ItemTemplate>
</asp:DataList>

C#
<asp:DataList id="DataList3" runat="server">
<ItemTemplate>
Name: <asp:Label ID="Label2" runat="server"
Text='<%# DataBinder.Eval(Container, "DataItem.EmployeeName")%>'/>
</ItemTemplate>
</asp:DataList>

3. Repeat Steps 1 and 2 for each template you want to create.


The following example shows a complete declaration for a DataList Web server control with simple templates declared
for the Header, Item, and Separator templates.
VB
<asp:datalist id="DataList2" runat="server" >
<HeaderTemplate>
Items matching your query:
</HeaderTemplate>
<ItemTemplate>
Name: <asp:Label id="Label1" runat="server"
Text='<%# DataBinder.Eval(Container, "DataItem.EmployeeName")%>'></asp:Label>
</ItemTemplate>
<SeparatorTemplate>
<br /><hr />
</SeparatorTemplate>
</asp:datalist>

C#
<asp:datalist id="DataList2" runat="server" >
<HeaderTemplate>
Items matching your query:
</HeaderTemplate>
<ItemTemplate>
Name: <asp:Label id="Label1" runat="server"
Text='<%# DataBinder.Eval(Container, "DataItem.EmployeeName")%>'></asp:Label>
</ItemTemplate>
<SeparatorTemplate>
<br /><hr />
</SeparatorTemplate>
</asp:datalist>

See Also
Concepts
ASP.NET Web Server Controls Templates
Other Resources
ASP.NET Web Server Controls (Visual Studio)
ASP.NET

How to: Respond to Button Events in Data-Bound Controls


If you are using a data-bound control with templates (such as a DataList or FormView control), and the templates include
Button, LinkButton, or ImageButton Web server controls, the buttons can forward their Click events to the containing control.
This allows you to include buttons for custom functionality not already defined for the data bound control (such as edit, delete,
update, and cancel).
To respond to button events in data-bound controls
1. Add a Button, LinkButton, or ImageButton in a control template.
2. Set the button's CommandName property to a string that identifies its function, such as "sort" or "copy".
3. Create a method for the ItemCommand event of the control. In the method, do the following:
a. Check the CommandName property of the event-argument object to see what string was passed.
b. Perform the appropriate logic for the button that the user clicked.
The following example shows how you can respond to a button click in a DataList control. In the example, the
ItemTemplate contains an ImageButton control that displays a shopping cart. The button sends the command
AddToCart. The event handler determines which button was clicked, and if it was the shopping cart button, performs
appropriate logic.
VB
Private Sub DataList1_ItemCommand(ByVal source As Object, _
ByVal e As DataListCommandEventArgs) _
Handles DataList1.ItemCommand
If (e.CommandName = "AddToCart") Then
' Add code here to add the item to the shopping cart.
' Use the value of e.Item.ItemIndex to find the data row
' in the data source.
End If
End Sub

C#
private void DataList1_ItemCommand(object source,
DataListCommandEventArgs e)
{
if (e.CommandName == "AddToCart")
{
// Add code here to add the item to the shopping cart.
// Use the value of e.Item.ItemIndex to find the data row
// in the data source.
}
}

See Also
Tasks
How to: Create Event Handlers in ASP.NET Web Pages
How to: Create Event Handlers in ASP.NET Web Pages (Visual Studio)
Concepts
ASP.NET Data-Bound Web Server Controls Overview
ASP.NET

How To: Create ASP.NET Web Server Control Templates


Dynamically
When working with templated controls, you might not know until run time what templates you need or what text or controls
the template should contain. In that case, you can create the templates dynamically in code.
Note
You can also create templates as user controls and bind them dynamically to controls on your page. For details, see
How to: Create Templated ASP.NET User Controls.

You can create templates in code for all controls that use templates: the DataList, Repeater, GridView, FormView, DetailsView,
and others. For the GridView control, you use templates to define columns instead of the row layout templates as for the other
controls.
Note
There are a few differences when creating template columns for the GridView control as compared to other templated contr
ols. For details, see Creating a Custom Column in a GridView Web Server Control.

Creating the Template Class


To create dynamic templates, you create a template class, which you then instantiate when needed.
To create a template class
1. Create a new class that implements the System.Web.UI.ITemplate interface.
2. Optionally, pass into the class's constructor a value that the class can use to determine what type of template to create
(ItemTemplate, AlternatingItemTemplate, and so on).
Note
A type-safe way to pass the template type to the constructor is to add a parameter to the constructor with the type
ListItemType. The ListItemType enumeration defines the possible template types for the Repeater, DataList, and othe
r list controls.

3. In the class, implement the InstantiateIn method, which is the member of the ITemplate interface.
This method provides a way to insert an instance of text and controls into the specified container.
4. In the InstantiateIn method, create the controls for the template item, set their properties, and then add them to the
parent's Controls collection.
You can access the parent control via the reference passed to the InstantiateIn method.
Note
You cannot directly add static text to the Controls collection, but you can create controls like the Literal control or the
LiteralControl control, set their Text properties, and then add those controls to the parent collection.

5. For controls that require data binding, create and bind a method to handle the control's DataBinding event. This event is
raised after the template item has been created with all its controls, and it provides you with an opportunity to fetch data
and use it in a control.
Note
You cannot embed a data-binding expression as a string when creating controls in the template, as you do when defini
ng templates at design time, because data-binding expressions are converted into code before your template is created
.
In the handler for the DataBinding event, you have an opportunity to manipulate the contents of the control. Typically
(but not necessarily), you fetch data from somewhere and assign it to the control's Text property (or other property).
Note
For information on data binding in ASP.NET Web pages, see Accessing Data with ASP.NET.

To add data binding to a dynamic template, you must do the following:


Add a data-binding event handler to the controls you create in the template.
Create the handler that you are binding to. In the handler, get the data that you want to bind to and assign it to the
appropriate property of the control being bound.
Note
If you have multiple types of controls in your templates, you need to create a different data-binding event handler
for each control type.

The following code example illustrates a template class named MyTemplate that implements the ITemplate interface. The
MyTemplate class defines a constructor that accepts a ListItemType enumeration value to indicate what type of template
is being created. Depending on the template type, the code creates different types of controls and adds them to a
PlaceHolder control which is then added to the Controls collection of the parent control. For the ListItemType of Item
and AlternatingItem, an event handler named Item_DataBinding is created.
The rendered Web page results in an HTML table with a different background color for the alternating item template.
VB
Public Class MyTemplate
Implements System.Web.UI.ITemplate

Dim templateType As ListItemType

Sub New(ByVal type As ListItemType)


templateType = type
End Sub

Public Sub InstantiateIn(ByVal container As System.Web.UI.Control) _


Implements System.Web.UI.ITemplate.InstantiateIn

Dim ph As New PlaceHolder()


Dim item1 As New Label()
Dim item2 As New Label()
item1.ID = "item1"
item2.ID = "item2"

Select Case (templateType)


Case ListItemType.Header
ph.Controls.Add(New LiteralControl("<table border=""1"">" & _
"<tr><td><b>Category ID</b></td>" & _
"<td><b>Category Name</b></td></tr>"))
Case ListItemType.Item
ph.Controls.Add(New LiteralControl("<tr><td>"))
ph.Controls.Add(item1)
ph.Controls.Add(New LiteralControl("</td><td>"))
ph.Controls.Add(item2)
ph.Controls.Add(New LiteralControl("</td></tr>"))
AddHandler ph.DataBinding, New EventHandler(AddressOf Item_DataBinding
)
Case ListItemType.AlternatingItem
ph.Controls.Add(New LiteralControl("<tr bgcolor=""lightblue""><td>"))
ph.Controls.Add(item1)
ph.Controls.Add(New LiteralControl("</td><td>"))
ph.Controls.Add(item2)
ph.Controls.Add(New LiteralControl("</td></tr>"))
AddHandler ph.DataBinding, New EventHandler(AddressOf Item_DataBinding
)
Case ListItemType.Footer
ph.Controls.Add(New LiteralControl("</table>"))
End Select
container.Controls.Add(ph)
End Sub
End Class

C#
public class MyTemplate : System.Web.UI.ITemplate
{
System.Web.UI.WebControls.ListItemType templateType;
public MyTemplate(System.Web.UI.WebControls.ListItemType type)
{
templateType = type;
}

public void InstantiateIn(System.Web.UI.Control container)


{
PlaceHolder ph = new PlaceHolder();
Label item1 = new Label();
Label item2 = new Label();
item1.ID = "item1";
item2.ID = "item2";

switch (templateType)
{
case ListItemType.Header:
ph.Controls.Add(new LiteralControl("<table border=\"1\">" +
"<tr><td><b>Category ID</b></td>" +
"<td><b>Category Name</b></td></tr>"));
break;
case ListItemType.Item:
ph.Controls.Add(new LiteralControl("<tr><td>"));
ph.Controls.Add(item1);
ph.Controls.Add(new LiteralControl("</td><td>"));
ph.Controls.Add(item2);
ph.Controls.Add(new LiteralControl("</td></tr>"));
ph.DataBinding += new EventHandler(Item_DataBinding);
break;
case ListItemType.AlternatingItem:
ph.Controls.Add(new LiteralControl("<tr bgcolor=\"lightblue\"><td>"));
ph.Controls.Add(item1);
ph.Controls.Add(new LiteralControl("</td><td>"));
ph.Controls.Add(item2);
ph.Controls.Add(new LiteralControl("</td></tr>"));
ph.DataBinding += new EventHandler(Item_DataBinding);
break;
case ListItemType.Footer:
ph.Controls.Add(new LiteralControl("</table>"));
break;
}
container.Controls.Add(ph);
}
}

To create the handler for the DataBinding event


1. Create a method that is either part of your template class and is a peer of the class's other methods (such as
InstantiateIn) or a static (Shared in Visual Basic) method of the page. The handler's name must match the name you
used when binding the event earlier.
2. Get a reference to the DataItem object that contains the data by doing the following:
a. Get a reference to the template item, which you can get from your control's NamingContainer property.
b. Use that reference to get the naming container's (the template item's) DataItem property.
c. Extract the individual data element from the DataItem object and use it to set a property of the control you are
binding.
The following code example illustrates one way to perform data binding within a dynamic template. It shows a complete
data-binding event handler for the PlaceHolder control and for the Literal and Label controls created in the previous
procedure. The event handler is implemented as a static method of the page.
VB
Shared Sub Item_DataBinding(ByVal sender As Object, ByVal e As System.EventArgs)
Dim ph As PlaceHolder = CType(sender, PlaceHolder)
Dim ri As RepeaterItem = CType(ph.NamingContainer, RepeaterItem)
Dim item1Value As Integer = _
Convert.ToInt32(DataBinder.Eval(ri.DataItem, "CategoryID"))
Dim item2Value As String = _
Convert.ToString(DataBinder.Eval(ri.DataItem, "CategoryName"))
CType(ph.FindControl("item1"), Label).Text = item1Value.ToString()
CType(ph.FindControl("item2"), Label).Text = item2Value
End Sub

C#
static void Item_DataBinding(object sender, System.EventArgs e)
{
PlaceHolder ph = (PlaceHolder)sender;
RepeaterItem ri = (RepeaterItem)ph.NamingContainer;
Int32 item1Value = (Int32)DataBinder.Eval(ri.DataItem, "CategoryID");
String item2Value = (String)DataBinder.Eval(ri.DataItem, "CategoryName");
((Label)ph.FindControl("item1")).Text = item1Value.ToString();
((Label)ph.FindControl("item2")).Text = item2Value;
}

Using the Dynamic Template


When you have a dynamic template available, you can instantiate it in code.
To use a dynamic template
1. Create an instance of your dynamic template, passing it an item type value if appropriate.
2. Assign the instance to one of the template properties of the templated control, such as the ItemTemplate,
AlternatingItemTemplate, or HeaderTemplate properties.
The following code example shows how to use the dynamic template with a Repeater control. In this example, the
templates are instantiated while the page is being loaded and before the control is bound to its data source.
The example below assumes that you can connect to the Northwind sample database on Microsoft SQL Server 7.0 or
later. It returns a list of records from the Categories table.
VB
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles MyBase.Load

Dim conn As New System.Data.SqlClient.SqlConnection( _


ConfigurationManager.ConnectionStrings("Northwind").ConnectionString)

Dim sqlDataAdapter1 As System.Data.SqlClient.SqlDataAdapter


Dim dsCategories1 As System.Data.DataSet

sqlDataAdapter1 = New System.Data.SqlClient.SqlDataAdapter( _


"SELECT [CategoryID], [CategoryName] FROM [Categories]", conn)
dsCategories1 = New System.Data.DataSet()

Repeater1.HeaderTemplate = New MyTemplate(ListItemType.Header)


Repeater1.ItemTemplate = New MyTemplate(ListItemType.Item)
Repeater1.AlternatingItemTemplate = New MyTemplate(ListItemType.AlternatingItem)
Repeater1.FooterTemplate = New MyTemplate(ListItemType.Footer)
sqlDataAdapter1.Fill(dsCategories1, "Categories")
Repeater1.DataSource = dsCategories1.Tables("Categories")
Repeater1.DataBind()

End Sub

C#
protected void Page_Load(object sender, EventArgs e)
{
System.Data.SqlClient.SqlConnection conn =
new System.Data.SqlClient.SqlConnection(
ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString);

System.Data.SqlClient.SqlDataAdapter sqlDataAdapter1;
System.Data.DataSet dsCategories1;

sqlDataAdapter1 = new System.Data.SqlClient.SqlDataAdapter(


"SELECT [CategoryID], [CategoryName] FROM [Categories]", conn);
dsCategories1 = new System.Data.DataSet();

Repeater1.HeaderTemplate = new MyTemplate(ListItemType.Header);


Repeater1.ItemTemplate = new MyTemplate(ListItemType.Item);
Repeater1.AlternatingItemTemplate =
new MyTemplate(ListItemType.AlternatingItem);
Repeater1.FooterTemplate = new MyTemplate(ListItemType.Footer);
sqlDataAdapter1.Fill(dsCategories1, "Categories");
Repeater1.DataSource = dsCategories1.Tables["Categories"];
Repeater1.DataBind();
}

Running the Complete Example


After creating all the components listed previously, add a Repeater control named Repeater1 to the page markup and run the
page. The complete code and markup for the Web page (using the single-file code model) is shown below.
VB
<%@ Page Language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1


/DTD/xhtml1-transitional.dtd">

<script runat="server">

Public Class MyTemplate


Implements System.Web.UI.ITemplate
Dim templateType As ListItemType

Sub New(ByVal type As ListItemType)


templateType = type
End Sub

Public Sub InstantiateIn(ByVal container As System.Web.UI.Control) _


Implements System.Web.UI.ITemplate.InstantiateIn

Dim ph As New PlaceHolder()


Dim item1 As New Label()
Dim item2 As New Label()
item1.ID = "item1"
item2.ID = "item2"

Select Case (templateType)


Case ListItemType.Header
ph.Controls.Add(New LiteralControl("<table border=""1"">" & _
"<tr><td><b>Category ID</b></td>" & _
"<td><b>Category Name</b></td></tr>"))
Case ListItemType.Item
ph.Controls.Add(New LiteralControl("<tr><td>"))
ph.Controls.Add(item1)
ph.Controls.Add(New LiteralControl("</td><td>"))
ph.Controls.Add(item2)
ph.Controls.Add(New LiteralControl("</td></tr>"))
AddHandler ph.DataBinding, New EventHandler(AddressOf Item_DataBinding)
Case ListItemType.AlternatingItem
ph.Controls.Add(New LiteralControl("<tr bgcolor=""lightblue""><td>"))
ph.Controls.Add(item1)
ph.Controls.Add(New LiteralControl("</td><td>"))
ph.Controls.Add(item2)
ph.Controls.Add(New LiteralControl("</td></tr>"))
AddHandler ph.DataBinding, New EventHandler(AddressOf Item_DataBinding)
Case ListItemType.Footer
ph.Controls.Add(New LiteralControl("</table>"))
End Select
container.Controls.Add(ph)
End Sub
End Class
Shared Sub Item_DataBinding(ByVal sender As Object, ByVal e As System.EventArgs)
Dim ph As PlaceHolder = CType(sender, PlaceHolder)
Dim ri As RepeaterItem = CType(ph.NamingContainer, RepeaterItem)
Dim item1Value As Integer = _
Convert.ToInt32(DataBinder.Eval(ri.DataItem, "CategoryID"))
Dim item2Value As String = _
Convert.ToString(DataBinder.Eval(ri.DataItem, "CategoryName"))
CType(ph.FindControl("item1"), Label).Text = item1Value.ToString()
CType(ph.FindControl("item2"), Label).Text = item2Value
End Sub

Protected Sub Page_Load(ByVal sender As Object, _


ByVal e As System.EventArgs) Handles MyBase.Load
Dim conn As New System.Data.SqlClient.SqlConnection( _
ConfigurationManager.ConnectionStrings("Northwind").ConnectionString)

Dim sqlDataAdapter1 As System.Data.SqlClient.SqlDataAdapter


Dim dsCategories1 As System.Data.DataSet

sqlDataAdapter1 = New System.Data.SqlClient.SqlDataAdapter( _


"SELECT [CategoryID], [CategoryName] FROM [Categories]", conn)
dsCategories1 = New System.Data.DataSet()

Repeater1.HeaderTemplate = New MyTemplate(ListItemType.Header)


Repeater1.ItemTemplate = New MyTemplate(ListItemType.Item)
Repeater1.AlternatingItemTemplate = New MyTemplate(ListItemType.AlternatingItem)
Repeater1.FooterTemplate = New MyTemplate(ListItemType.Footer)
sqlDataAdapter1.Fill(dsCategories1, "Categories")
Repeater1.DataSource = dsCategories1.Tables("Categories")
Repeater1.DataBind()

End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Dynamically Creating Templates</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Repeater id="Repeater1" runat="server"></asp:Repeater>
</div>
</form>
</body>
</html>

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

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1


/DTD/xhtml1-transitional.dtd">

<script runat="server">

public class MyTemplate : System.Web.UI.ITemplate


{
System.Web.UI.WebControls.ListItemType templateType;
public MyTemplate(System.Web.UI.WebControls.ListItemType type)
{
templateType = type;
}

public void InstantiateIn(System.Web.UI.Control container)


{
PlaceHolder ph = new PlaceHolder();
Label item1 = new Label();
Label item2 = new Label();
item1.ID = "item1";
item2.ID = "item2";

switch (templateType)
{
case ListItemType.Header:
ph.Controls.Add(new LiteralControl("<table border=\"1\">" +
"<tr><td><b>Category ID</b></td>" +
"<td><b>Category Name</b></td></tr>"));
break;
case ListItemType.Item:
ph.Controls.Add(new LiteralControl("<tr><td>"));
ph.Controls.Add(item1);
ph.Controls.Add(new LiteralControl("</td><td>"));
ph.Controls.Add(item2);
ph.Controls.Add(new LiteralControl("</td></tr>"));
ph.DataBinding += new EventHandler(Item_DataBinding);
break;
case ListItemType.AlternatingItem:
ph.Controls.Add(new LiteralControl("<tr bgcolor=\"lightblue\"><td>"));
ph.Controls.Add(item1);
ph.Controls.Add(new LiteralControl("</td><td>"));
ph.Controls.Add(item2);
ph.Controls.Add(new LiteralControl("</td></tr>"));
ph.DataBinding += new EventHandler(Item_DataBinding);
break;
case ListItemType.Footer:
ph.Controls.Add(new LiteralControl("</table>"));
break;
}
container.Controls.Add(ph);
}
}

static void Item_DataBinding(object sender, System.EventArgs e)


{
PlaceHolder ph = (PlaceHolder)sender;
RepeaterItem ri = (RepeaterItem)ph.NamingContainer;
Int32 item1Value = (Int32)DataBinder.Eval(ri.DataItem, "CategoryID");
String item2Value = (String)DataBinder.Eval(ri.DataItem, "CategoryName");
((Label)ph.FindControl("item1")).Text = item1Value.ToString();
((Label)ph.FindControl("item2")).Text = item2Value;
}

protected void Page_Load(object sender, EventArgs e)


{
System.Data.SqlClient.SqlConnection conn =
new System.Data.SqlClient.SqlConnection(
ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString);

System.Data.SqlClient.SqlDataAdapter sqlDataAdapter1;
System.Data.DataSet dsCategories1;

sqlDataAdapter1 = new System.Data.SqlClient.SqlDataAdapter(


"SELECT [CategoryID], [CategoryName] FROM [Categories]", conn);
dsCategories1 = new System.Data.DataSet();

Repeater1.HeaderTemplate = new MyTemplate(ListItemType.Header);


Repeater1.ItemTemplate = new MyTemplate(ListItemType.Item);
Repeater1.AlternatingItemTemplate =
new MyTemplate(ListItemType.AlternatingItem);
Repeater1.FooterTemplate = new MyTemplate(ListItemType.Footer);
sqlDataAdapter1.Fill(dsCategories1, "Categories");
Repeater1.DataSource = dsCategories1.Tables["Categories"];
Repeater1.DataBind();
}

</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Dynamically Creating Templates</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Repeater id="Repeater1" runat="server"></asp:Repeater>
</div>
</form>
</body>
</html>

See Also
Other Resources
Working with ASP.NET Web Server Controls
Visual Web Developer

Walkthrough Topics — Working with Web Server Controls


The following walkthrough topic demonstrates how to add ASP.NET Web server controls to a page and how to set the
properties of these controls.
Walkthrough Topics
How To: Create ASP.NET Web Server Control Templates Dynamically
See Also
Other Resources
Working with Web Server Controls
Visual Web Developer

How-to Topics — Working with Web Server Controls


The following procedures describe how to add ASP.NET Web server controls to a page and how to set their properties.
How-to Topics
How to: Add Web Server Controls to a Web Forms Page Using the Web Forms Designer
How to: Add Server Controls to an ASP.NET Web Page Using ASP.NET Syntax
How to: Add HTML Server Controls to an ASP.NET Web Page Using the Designer
How to: Add HTML Server Controls to a Web Page Using ASP.NET Syntax
How to: Convert HTML Server Controls to HTML Elements (Visual Studio)
How to: Set ASP.NET Server Control Properties (Visual Studio)
How to: Set Web Server Control Properties Based on Simple Values or Enumerations
How to: Set Web Server Control Unit Properties
How to: Set Web Server Control Color Properties
How to: Set Web Server Control Properties in Collections
How to: Set HTML Attributes for Controls in ASP.NET Web Pages
How to: Read HTML Attributes for Controls in Web Forms Pages
How to: Set HTML Server Control Properties Programmatically
How to: Specify Whether ASP.NET Web Server Controls Post to the Server
How to: Set Focus on ASP.NET Web Server Controls
How to: Set Access Keys for ASP.NET Web Server Controls
How to: Set ASP.NET Server Control Style Properties in the Designer
How to: Set ASP.NET Server Control Style Properties Using ASP.NET Syntax
How to: Set ASP.NET Server Control Style Properties Programmatically
How to: Add Controls to an ASP.NET Web Page Programmatically
How to: Locate Child Controls by ID in an ASP.NET Web Page
How to: Locate the Web Forms Controls on a Page by Walking the Controls Collection
How to: Access Members of a Web Server Control's Naming Container
How to: Create Web Server Control Templates Using the Designer
How to: Create ASP.NET Web Control Templates Declaratively
How to: Respond to Button Events in Data-Bound Controls
See Also
Other Resources
Working with Web Server Controls
Visual Web Developer

Individual Web and HTML Controls


The topics in this section provide in-depth information about each built-in ASP.NET Web server control. The information is
arranged to match how the controls are presented on the Visual Web Developer Toolbox.
In This Section
Standard Toolbox Controls
Data Toolbox Controls
Validation Toolbox Controls
Navigation Toolbox Controls
Login Toolbox Controls
HTML Controls for ASP.NET Web Pages
ASP.NET Web User Controls (Visual Studio)
See Also
Other Resources
ASP.NET Web Server Controls (Visual Studio)
ASP.NET Web Pages (Visual Studio)
Visual Web Developer

Standard Toolbox Controls


The topics in this section describe how to work with ASP.NET Web server controls that appear on the Standard tab of the
Visual Web Developer Toolbox. These include controls that enable you to display buttons, lists, images, boxes, hyperlinks,
labels, tables, as well as more complicated controls that work with static and dynamic data or controls that act as containers for
other controls.
For complete syntax information for Web server controls, see Web Server Control Syntax.
In This Section
AdRotator Web Server Control (Visual Studio)
BulletedList Web Server Control (Visual Studio)
Button Web Server Controls (Visual Studio)
Calendar Web Server Control (Visual Studio)
CheckBox and CheckBoxList Web Server Controls (Visual Studio)
DropDownList Web Server Control (Visual Studio)
FileUpload Web Server Control (Visual Studio)
HiddenField Web Server Control (Visual Studio)
HyperLink Web Server Control (Visual Studio)
Image Web Server Control (Visual Studio)
ImageMap Web Server Control (Visual Studio)
Label Web Server Control (Visual Studio)
ListBox Web Server Control (Visual Studio)
Literal Web Server Control (Visual Studio)
Localize Web Server Control (Visual Studio)
MultiView and View Web Server Controls (Visual Studio)
Panel Web Server Control (Visual Studio)
PlaceHolder Web Server Control (Visual Studio)
RadioButton and RadioButtonList Web Server Controls (Visual Studio)
Substitution Web Server Control (Visual Studio)
Table, TableRow, and TableCell Web Server Controls (Visual Studio)
TextBox Web Server Control (Visual Studio)
Wizard Web Server Control (Visual Studio)
XML Web Server Control (Visual Studio)
Securing Standard Controls
See Also
Other Resources
Individual Web and HTML Controls
ASP.NET Web Server Controls (Visual Studio)
ASP.NET Web Pages (Visual Studio)
Web Server Control Syntax
Visual Web Developer

AdRotator Web Server Control (Visual Studio)


The topics in this section provide information about the ASP.NET AdRotator Web server control, which cycles through a series
of clickable banner ads that you define.
In This Section
AdRotator Web Server Control Overview
How to: Display Ads From an XML File Using the AdRotator Web Server Control
How to: Display Ads From a Database Using the AdRotator Web Server Control
How to: Select Ads in an AdRotator Web Server Control Programmatically
Walkthrough: Displaying and Tracking Advertisements with the AdRotator Control
See Also
Other Resources
Individual Web and HTML Controls
ASP.NET

AdRotator Web Server Control Overview


The AdRotator Web server control provides a convenient way to display advertisements (ads) on your ASP.NET Web pages.
The control displays a graphic image that you provide — a .gif file or similar image. When users click the ad, they are
redirected to a target URL that you have specified. The control automatically reads advertisement information, such as the
graphic file name and the target URL, from a list of ads that you provide using a data source, which is usually an XML file or
database table.
The AdRotator control selects ads randomly, changing the displayed ad each time the page is refreshed. Ads can be weighted
to control the priority level of banners, making it possible to have certain ads display more often than others. You can also
write custom logic that cycles through the ads.
Ad information can come from a variety of sources, such as the following:
An XML file You can store ad information in an XML file that contains references to ad banners and their associated
properties.
Any data source control, such as the SqlDataSource or ObjectDataSource controls For example, you can store ad
information in a database, and can use a SqlDataSource control to retrieve ad information, and then bind the
AdRotator control to the data source control.
Custom logic You can create a handler for the AdCreated event and select an ad in the event.
XML File Format for Ad Files
One method of storing ad-banner image locations, URLs for redirection, and associated properties is to put the information in
an XML file. By using the XML file format, you can create and maintain a list of advertisements without having to change the
code in your application whenever a change is made to an advertisement. For details, see
How to: Display Ads From an XML File Using the AdRotator Web Server Control.
Database Schema for Ad Files
Instead of creating an XML file for ad information, you can store ad information in a database table. The table requires a
specific schema that the AdRotator control can read. For details, see
How to: Display Ads From a Database Using the AdRotator Web Server Control.
Filtering Ads by Keyword
In the advertisement file, you can assign categories to ads by using the Keyword attribute and then configuring the
AdRotator control to show ads according to the filter criteria that you specify. For example, if a specific ad file contains
categories for both banks and hardware stores, you might only want the page to display ads that are related to banks. By
setting the AdRotator control's KeywordFilter property to "banks," the hardware store ads will be filtered out.
If a filter is specified, then one of the following two situations can result:
If the AdRotator control can find ads with the matching keyword, an ad with the keyword is displayed.
If no match for the keyword exists, then the AdRotator control will display a blank image in the browser.
Tracking Ad Response
The AdRotator control does not inherently provide a way to gather statistics about which ads users have clicked, how many
times an ad has been clicked, and so on. However, because you have control over the URL to which the ad points, you can add
tracking logic for the ads to your application. A typical way to do this is to point all ads to a tracking page that first gathers the
statistics you want, and then jumps to the ad's destination page.
Caching Ads
If the page that contains the AdRotator control is cached, the AdRotator control automatically performs cache substitution to
replace the cached ad with a new one whenever the page is retrieved from the cache. For more information, see
Dynamically Updating Portions of a Cached Page.
See Also
Tasks
How to: Display Ads From an XML File Using the AdRotator Web Server Control
How to: Select Ads in an AdRotator Web Server Control Programmatically
ASP.NET

How to: Display Ads From an XML File Using the AdRotator
Web Server Control
The AdRotator Web server control reads advertisement (ad) information from a data source, which one or more ad records.
You can store ad information in an XML file and then bind the AdRotator control to the file.
All attributes of the AdRotator control are optional. The following attributes can be included in the XML files:
ImageUrl The URL of the image to display.
NavigateUrl The URL of the page to go to when the AdRotator control is clicked.
AlternateText The text to display if the image is unavailable.
Keyword The category of the ad, which can be used to filter for specific ads.
Impressions A numeric value (a weighting number) that indicates the likelihood of how often the ad is displayed. The
total of all impressions values in the XML file cannot exceed 2,048,000,000 - 1.
Height The height of the ad in pixels. This value overrides the default height setting for the AdRotator control.
Width The width of the ad in pixels. This value overrides the default width setting for the AdRotator control.
To create an ad list as an XML file
1. Create a new XML file in your Web site's App_Data folder. For extra security, give the file a file name extension other than
.xml, such as .ads.
Note
It is recommended that you put the ad file in the App_Data folder because ASP.NET prevents files from that folder from
being served to browsers.

2. Add the following XML elements to the file:

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


<Advertisements xmlns="http://schemas.microsoft.com/AspNet/AdRotator-Schedule-File">
</Advertisements>

3. Create an Ad element inside the Advertisements element for each ad that you want to include in the ad list, and then
save the file.
A sample file might look like the following:

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


<Advertisements xmlns="http://schemas.microsoft.com/AspNet/AdRotator-Schedule-File">
<Ad>
<ImageUrl>~/images/Contoso_ad.gif</ImageUrl>
<NavigateUrl>http://www.contoso-ltd.com</NavigateUrl>
<AlternateText>Ad for Contoso, Ltd. Web site</AlternateText>
<Impressions>100</Impressions>
</Ad>
<Ad>
<ImageUrl>~/images/Aspnet_ad.gif</ImageUrl>
<NavigateUrl>http://www.asp.net</NavigateUrl>
<AlternateText>Ad for ASP.NET Web site</AlternateText>
<Impressions>50</Impressions>
</Ad>
</Advertisements>
To display ads from the database
1. Place an AdRotator control on the ASP.NET Web page at the location where you want the ads to display.
2. Set the AdRotator control's AdvertisementFile property to the path of the XML file that you created in the previous
procedure.
Note
It is recommended that you use a relative URL to make the application more portable. Use syntax such as ~\App_Data\f
ilename.ad. For information about file paths, see ASP.NET Web Site Paths.

When the page runs, the AdRotator control reads the XML file for the ads and selects one to display.
See Also
Tasks
How to: Display Ads From a Database Using the AdRotator Web Server Control
How to: Select Ads in an AdRotator Web Server Control Programmatically
Reference
AdRotator Web Server Control Overview
ASP.NET

How to: Display Ads From a Database Using the AdRotator


Web Server Control
The AdRotator control reads advertisement information from a data source, which contains one or more ad records. You can
store ad information in a database table with a specific schema, and then use a data source control to read the ad records at
run time. If you have an existing table with ad information, you can map the schema of your table to the fields that are required
by the AdRotator control.
You can store ad information in any type of database, as long as you have the corresponding data source control for that
database.
To create the database table for ads
1. If you do not already have a database table that contains the ad information, create a table with the following schema. All
columns except ID are optional.
Note
Data types are provided as SQL Server types. If you are using a different database, substitute the appropriate correspon
ding type.

Colu Data t Description


mn na ype
me
ID int Primary key. This column can have any name.

Image nvarch The relative or absolute URL of the image to display for the ad.
Url ar(leng
th)

Naviga nvarch The target URL for the ad. If you do not provide a value, the ad is not a hyperlink.
teUrl ar(leng
th)

Altern nvarch The text displayed if the image cannot be found. In some browsers, the text is displayed as a ToolTip. Alte
ateText ar(leng rnate text is also used for accessibility so that users who cannot see the graphic can hear its description r
th) ead out loud.

Keywo nvarch A category for the ad on which the page can filter.
rd ar(leng
th)

Impres int(4) A number that indicates the likelihood of how often the ad is displayed. The larger the number, the more
sions often the ad will be displayed. The total of all impressions values in the XML file may not exceed 2,048,00
0,000 - 1.

Width int(4) The width of the image in pixels.

Height int(4) The height of the image in pixels.

2. If you have an existing database table with ad information in it, set the following properties of the AdRotator control to
map your database table schema to the fields required by the control:
AlternateTextField
ImageUrlField
NavigateUrlField
3. Insert new records into the table with ad information.
To display ads from the database
1. Place a data source control, such as a SqlDataSource or AccessDataSource control, onto the page.
2. Configure the data source control with a connection string and query to select all of the records from the database table
you created earlier.
Note
For information about using data source controls, see Data Source Web Server Controls.

3. Place an AdRotator control on the ASP.NET Web page where you want the ads to appear.
4. Set the AdRotator control's DataSourceID property to the ID of the data source control that you created earlier in step 1.
When the page runs, the AdRotator control will query the database for the ads and select one to display.
See Also
Tasks
How to: Display Ads From an XML File Using the AdRotator Web Server Control
How to: Select Ads in an AdRotator Web Server Control Programmatically
Reference
AdRotator Web Server Control Overview
ASP.NET

How to: Select Ads in an AdRotator Web Server Control


Programmatically
Using the AdRotator Web server control, you can dynamically select ads by creating custom logic within an AdCreated event
handler.
To select ads using the AdCreated event
1. Create an AdCreated event handler for the AdRotator control.
The second parameter passed in the handler contains a reference to the ad that is being created.
2. Set the properties of the ad object to specify the image and navigation URLs of the ad to display.
The following example shows how you can set the ImageUrl, NavigateUrl, and AlternateText properties of the
AdCreatedEventArgs control:
VB
Public Sub AdRotator1_AdCreated(ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.AdCreatedEventArgs) _
Handles AdRotator1.AdCreated
e.ImageUrl = "images/contoso_ad.gif"
e.NavigateUrl = "http://www.contoso-ltd.com/"
e.AlternateText = "Ad for Contoso, Ltd. Web site"
End Sub

C#
protected void AdRotator1_AdCreated (object sender,
System.Web.UI.WebControls.AdCreatedEventArgs e)
{
e.ImageUrl = "images/contoso_ad.gif";
e.NavigateUrl = "http://www.contoso-ltd.com/";
e.AlternateText = "Ad for Contoso, Ltd Web site";
}

See Also
Reference
AdRotator Web Server Control Overview
Visual Web Developer

Walkthrough: Displaying and Tracking Advertisements with


the AdRotator Control
Web sites frequently display advertisements or similar dynamic content that invites users to visit another site. ASP.NET
provides the AdRotator control, which simplifies this task. The AdRotator control displays a graphic representing an ad,
randomly selecting the ad from a list that you create. You can then track how frequently an ad is viewed and how frequently
users click it.
This walkthrough illustrates how to use the AdRotator control to display ads and provides a simple way to track ad responses.
Tasks illustrated in this walkthrough include the following:
Creating a list of ads to display.
Displaying ads on a page.
Creating a way to track the number of times an ad is clicked.
Displaying statistics about ad clicks.
Prerequisites
In order to complete this walkthrough, you will need the following:
Microsoft Visual Web Developer Web development tool.
The .NET Framework.
A general understanding of working in Visual Web Developer. For an introduction, see
Walkthrough: Creating a Basic Web Page in Visual Web Developer.
Creating the Web Site
If you have already created a Web site in Visual Web Developer by completing
Walkthrough: Creating a Basic Web Page in Visual Web Developer, you can use that Web site and go to the next section.
Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, click File System, and then type the name of the folder where you want to keep the pages of the
Web site.
For example, type the folder name C:\WebSite.
5. In the Languages list, click the programming language that you prefer to work in.
The programming language that you choose will be the default for your Web site, but you can set the programming
language for each page individually.
6. Click OK.
Visual Studio creates the folder and a new page named Default.aspx.
Creating Advertisements
Ads are graphics that are displayed on the page with a target URL; when users click the graphic, they are redirected to the
target site. Therefore, you need graphics files to serve as advertisements.
Note
Later sections of this walkthrough assume that are you using graphics that are named according to the following procedure.
If you use existing graphics, make sure that you substitute the appropriate file names later in the walkthrough.

Start by creating a folder in the Web site to store graphics.


To create an Images folder
1. In Solution Explorer, right-click the name of the Web site, click New Folder, and then name the folder Images.
2. If you have existing graphics to use as ads, copy them to the new folder. Otherwise, follow the next procedure to create
some images.
If you already have some graphics that you can use to represent ads, you can use those. Otherwise, the following procedure
suggests one way that you can create graphics that are suited for this walkthrough.
To create graphics to serve as ads
1. In Microsoft Windows, open Paint.
2. On the Image menu, click Attributes.
3. In the Attributes dialog box, set Width to 250 and Height to 50, and then click OK.
4. From the Toolbox, drag the text tool onto the graphic, and then type some text that will help you identify the ad
5. In the <Websitename>\Images folder, save the graphic as <Websitename>\Images\Contoso_ad.gif.
6. Create a second graphic, and then save it as <Websitename>\Images\ASPNET_ad.gif.
7. Close Paint.
Creating a List of Ads
As soon as you have graphics for the ads, you must create a list of ads that the AdRotator control can read. The list is in the
form of an XML file.
To create an XML file of ads
1. In Solution Explorer, right-click App_Data, and then click Add New Item.
Note
When you put the XML file into the App_Data folder, the file automatically has the correct permissions to allow ASP.NE
T to read the file at run time. Putting the XML file in the App_Data folder helps to protect the file from being viewed in a
browser, because the App_Data folder is marked as nonbrowsable.

2. Under Visual Studio installed templates, click XML File.


3. In the Name box, type Sample.ads.
Note
Use the .ads extension.

4. Click Add.
A new XML file is created that contains only the XML directive.
5. Copy the following XML into the file, overwriting the XML directive.

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


<Advertisements>
<Ad>
<ImageUrl>~/images/Contoso_ad.gif</ImageUrl>
<NavigateUrl>http://www.contoso.com</NavigateUrl>
<AlternateText>Ad for Contoso.com</AlternateText>
</Ad>
<Ad>
<ImageUrl>~/images/ASPNET_ad.gif</ImageUrl>
<NavigateUrl>http://www.asp.net</NavigateUrl>
<AlternateText>Ad for ASP.NET Web site</AlternateText>
</Ad>
</Advertisements>

Note
If your graphics files have different file names, change the names in the <ImageUrl> elements accordingly.

This XML file contains <Ad> elements for two advertisements corresponding to the two graphics files that you have
created. In a real application, the URLs in the <NavigateUrl> elements would refer to the advertisers' Web sites.
Note
Additional elements are available for defining ads. For detailed information, see AdvertisementFile.

6. Save the file, and then close it.


Displaying Ads on the Page
You will now configure a Web page to display the ads that you have created. In the following procedure, you will bind an
AdRotator control to an XmlDataSource control. However, when using a static XML file, a data source control is not required,
because the XML file can be set directly with the AdvertisementFile property of the AdRotator control.
To display ads on the page
1. If you created a new Web site for this walkthrough, open the Default.aspx page.
2. If you are using a Web site that existed before you started this walkthrough, add a new page by following these steps:
a. In Solution Explorer, right-click the name of the Web site (for example, C:\WebSites), and then click Add New Item.
b. Under Visual Studio installed templates, click Web Form.
c. In the Name box, type TestAds.aspx.
d. Click Add.
3. Open TestAds.aspx and switch to Design view.
4. From the Standard group in the Toolbox, drag an AdRotator control onto the page.
The AdRotator Tasks shortcut menu appears.
5. In the Choose Data Source list, click New data source.
The Data Source Configuration wizard appears.
6. Under Where will the application get data from, click XML File.
7. In the Specify an ID for the data source box, leave the default, (XmlDataSource1).
8. Click OK.
The Configure Data Source dialog box appears.
9. In the Data file box, enter ~/App_Data/Sample.ads, and then click OK.
Alternatively, you can use Browse to locate the file:
a. In the Select XML File dialog box, in the Files of type list, click All Files (*.*).
b. Under Project Folders, click App_Data.
c. Under Contents of Folder, click Sample.ads, click OK, and then click OK.
10. From the Standard group in the Toolbox, drag a Button control onto the page.
Note
The exact layout of the page is not important.

The Button control is on the page only so that you have a convenient way to post back the page to the server.
Now you will test the ads.
To test the ads
1. Press CTRL+F5 to run the page.
One of the two ads appears on the page.
2. Click Button several times to cause the page to post back.
The ad that appears randomly varies.
Note
Because there are only two ads, you might have to click Button several times before you see a different ad.

3. Click an ad.
You are redirected to the target page for that ad.
4. Close the browser.
Tracking Ad Responses
At this point, your page just displays ads that users can click to jump to another page. In this part of the walkthrough, you will
add functionality to keep track of how many times users click the ads. You will change the URL of the ads in the Sample.ads file
to send the ad response to a redirection page, with information in the query string that identifies the ad and the ultimate
destination.
You will then create a second XML file to store ad counter information. In a production Web site, you should not use an XML
file to track ad clicks, because the XML file would not support much traffic. However, for purposes of this walkthrough, you will
use an XML file for convenience, so that you do not have to configure database access. Additionally, in a production application,
you would probably want more sophisticated click tracking, such as making sure that you are tracking unique visitors, tracking
time and date information about clicks, and so on. Nevertheless, the overall strategy of using a redirection page to process
clicks is the same regardless of how you choose to track the data.
Finally, you will create the redirection page, where you will accumulate counters for different ads, and then redirect again to the
target page that the ad is intended to display.
To redirect ads to a tracking page
1. Open the Sample.ads file.
2. Set NavigateUrl to include the following:
The name of your redirection page (AdRedirector.aspx).
An identifier for each ad.
The page to which the ad ultimately points.
The following code listing shows the Sample.ads XML file updated with URLs that specify the AdRedirector.aspx page.
The ad identifier and target page are specified as a query string.
Note
Because the ampersand (&) is a reserved character in XML, the query string includes the entity reference &amp; instea
d.

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


<Advertisements>
<Ad>
<ImageUrl>~/images/Contoso_ad.gif</ImageUrl>
<NavigateUrl>AdRedirector.aspx?ad=Widgets&amp;target=http://www.contoso.com/widget
s/</NavigateUrl>
<AlternateText>Ad for Contoso.com</AlternateText>
</Ad>
<Ad>
<ImageUrl>~/images/ASPNET_ad.gif</ImageUrl>
<NavigateUrl>AdRedirector.aspx?ad=ASPNET&amp;target=http://www.asp.net</NavigateUr
l>
<AlternateText>Ad for ASP.NET Web site</AlternateText>
</Ad>
</Advertisements>

3. Save the Sample.ads file, and then close it.


The next step is to create the XML file where you store counter information for the ad clicks. In a production Web site, you
would not need this step, because you would write information to a database instead. Using an XML file in this walkthrough
simplifies the steps that are required to track ad responses.
To create the XML file for tracking ad response
1. In Solution Explorer, right-click the App_Data folder, and then click Add New Item.
2. Under Templates, click XML File.
3. In the Name box, type AdResponses.xml, and then click Add.
A new XML file is created that contains only the XML directive.
4. Copy the following XML into the file, overwriting the XML directive.

<?xml version="1.0" standalone="yes"?>


<adResponses>
<ad adname="Widgets" hitCount="0" />
<ad adname="ASPNET" hitCount="0" />
</adResponses>

The file contains elements that have two pieces of information, the ID of an ad and a counter.
Note
If you assigned different IDs to the ads in the Sample.ads file in the previous procedure when you created the query stri
ngs, make sure that the IDs in the AdResponses.xml file match those.

5. Save the file, and then close it.


Note
Whether ASP.NET has Write permission for the XML file depends on which Web server you use. In this walkthrough, yo
u will use the ASP.NET Development Server, which is included with Visual Web Developer and has write access to the X
ML file. If you were using Microsoft Internet Information Services (IIS), the IIS Web server worker process may not have
write access to the XML file and you would have to explicitly set the Write permission. For more information on Web se
rvers in Visual Web Developer, see Web Servers in Visual Web Developer.
Now you will create the redirection page, which captures information about the ad that was clicked, updates the counter for the
ad, and then sends the request on to the page that is associated with the ad.
To create a Page_Load handler
1. In Solution Explorer, right-click the name of the Web site (for example, C:\WebSites), and then click Add New Item.
2. Under Visual Studio installed templates, click Web Form.
3. In the Name box, type AdRedirector.aspx, and then click Add.
This creates the page to which all ads will be directed when users click them. The page will not be displayed to users.
Therefore, you will not put any controls on it.
4. In Design view, double-click the page to create a Page_Load handler.
5. Copy the following code into the handler (do not overwrite the skeleton handler declaration).
VB
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles M
e.Load

Dim adName As String = Request.QueryString("ad")


Dim redirect As String = Request.QueryString("target")
If (adName Is Nothing Or redirect Is Nothing) Then
redirect = "TestAds.aspx"
End If

Dim doc As System.Xml.XmlDocument


Dim docPath As String = "~/App_Data/AdResponses.xml"

doc = New System.Xml.XmlDocument()


doc.Load(Server.MapPath(docPath))
Dim root As System.Xml.XmlNode = doc.DocumentElement
Dim xpathExpr As String
xpathExpr = "descendant::ad[@adname='" & adName & "']"
Dim adNode As System.Xml.XmlNode = _
root.SelectSingleNode(xpathExpr)
If adNode IsNot Nothing Then
Dim ctr As Integer = _
CInt(adNode.Attributes("hitCount").Value)
ctr += 1
Dim newAdNode As System.Xml.XmlNode = _
adNode.CloneNode(False)
newAdNode.Attributes("hitCount").Value = ctr.ToString()
root.ReplaceChild(newAdNode, adNode)
doc.Save(Server.MapPath(docPath))
End If
Response.Redirect(redirect)

End Sub

C#
protected void Page_Load(object sender, EventArgs e)
{
String adName = Request.QueryString["ad"];
String redirect = Request.QueryString["target"];
if (adName == null | redirect == null)
redirect = "TestAds.aspx";
System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
String docPath = @"~/App_Data/AdResponses.xml";
doc.Load(Server.MapPath(docPath));
System.Xml.XmlNode root = doc.DocumentElement;
System.Xml.XmlNode adNode =
root.SelectSingleNode(
@"descendant::ad[@adname='" + adName + "']");
if (adNode != null)
{
int ctr =
int.Parse(adNode.Attributes["hitCount"].Value);
ctr += 1;
System.Xml.XmlNode newAdNode = adNode.CloneNode(false);
newAdNode.Attributes["hitCount"].Value = ctr.ToString();
root.ReplaceChild(newAdNode, adNode);
doc.Save(Server.MapPath(docPath));
}
Response.Redirect(redirect);
}

The code reads the ad ID and URL from the query string. It then uses XML methods to read the AdResponse.xml file into
an XmlDocument object. The code locates the appropriate XML element using an XPath expression, extracts the
hitCounter value, and then updates the hitCounter value. Next, the code creates a copy of the XML element by cloning,
replaces the old element with the new one, and then writes the updated XML document back to disk. Finally, the code
redirects to the URL for the ad.
You will now test to confirm that the ad counters for the ads are working.
To test ad response tracking
1. Open the page that contains the AdRotator control, and then press CTRL+F5.
2. Click the ad.
You are redirected to the target page for that ad.
3. In the browser, click Back to return to the ad page.
4. Either click the ad again or click Button to display a different ad, and then click the ad.
5. Continue until you have clicked each ad at least one time, and one or more ads more than one time.
6. Close the browser.
7. In Visual Web Developer, open the AdResponse.xml file and verify that the counters for the ads reflect the number of
clicks from your test.
8. Close the AdResponse.xml file.
Displaying Ad Counter Data
For the final part of the walkthrough, you will create a page that displays the ad counter information, which is more convenient
than manually examining the XML file.
To create a page to display the ad response data
1. In Solution Explorer, right-click the name of the Web site, and then click Add New Item.
2. Under Visual Studio installed templates, click Web Form.
3. In the Name box, type ViewAdData.aspx.
4. Click Add.
5. Switch to Design view.
6. From the Data group in the Toolbox,, drag an XmlDataSource control onto the page.
7. On the XmlDataSource Tasks shortcut menu, click Configure Data Source.
The Configure Data Source <Datasourcename> dialog box appears.
8. In the Data file box, type ~/App_Data/AdResponses.xml.
Alternatively, you can use Browse to locate the file.
9. Click OK.
10. From the Data group in the Toolbox, drag a GridView control onto the page.
11. On the GridView Tasks shortcut menu, in the Choose Data Source list, click XmlDataSource1.
12. Press CTRL+F5 to run the page.
The page displays the ad response data in a grid.
13. Close the browser.
Next Steps
There are more features available in the AdRotator control than have been illustrated in this walkthrough. You might want to
explore these features in the following ways:
Use additional attributes when you create ads in the XML file.
For example, you can use the Impressions element to control how often an advertisement is selected relative to the
other advertisements in the advertisement file. The higher the value, the more likely the ad will be selected. For detailed
information, see AdvertisementFile.
Use a database to track ad responses.
Note
In a production application, do not use an XML file to track ad responses, because it will not scale to support many user
s. This walkthrough uses an XML file for ad responses only to simplify the walkthrough and to make is to that you do n
ot have to configure a database.

Track additional information about ad clicks.


You might want to make sure that you are tracking unique visitors, perhaps by writing a cookie to the browser, if the user
has clicked the ad within the last day, or by tracking the IP address of the browser when you store click information. You
might also aggregate click information by date and time, and perhaps track ad information according to other dynamic
content on the source page, which can help you analyze traffic patterns.
Bind the AdRotator control to its data using a different data source control.
For example, you can store advertisement data in a database. If you do, you can add a data source control to the page
and configure it to use a query to obtain advertisement data. You can then bind the AdRotator control to the data source
control. For detailed information, see How to: Display Ads From a Database Using the AdRotator Web Server Control.
See Also
Reference
AdRotator Web Server Control Overview
Visual Web Developer

BulletedList Web Server Control (Visual Studio)


The BulletedList Web server control allows you to create unordered or ordered (numbered) lists of items, which render as
HTML ul or ol elements, respectively. To specify the individual items in the list, place a ListItem control for each list entry
between the opening and closing tags of the BulletedList control.
In This Section
BulletedList Web Server Control Overview
An overview of the control.
How to: Add BulletedList Web Server Controls to a Web Forms Page (Visual Studio)
Explains how to add the control to a page.
How to: Respond to User Clicks in BulletedList Web Server Controls (Visual Studio)
Explains how to respond to the user's click events.
See Also
Tasks
How to: Add Items in List Web Server Controls (Visual Studio)
How to: Populate List Web Server Controls from a Data Source (Visual Studio)
How to: Set the Selection in List Web Server Controls (Visual Studio)
Other Resources
Individual Web and HTML Controls
ASP.NET

BulletedList Web Server Control Overview


The BulletedList control creates an unordered or ordered (numbered) list of items, which renders as an HTML ul or ol element,
respectively. You can specify the appearance of the items and of the bullets or numbers, define the list items statically or by
binding the control to data, and you can respond to users' clicks on items.
Defining List Items
The BulletedList derives from the same ListControl class as the ListBox, DropDownList, and other ASP.NET list controls, so
using it is similar to working with those controls. You can define list items for the BulletedList control either by creating static
items or by binding the control to a data source. If you know at design time what items you want to display, you can set the
control's Items collection to a set of individual items in markup. If the items to be displayed are dynamic, you can create the
item collection in code at run time. For details, see How to: Add Items in List Web Server Controls.
Alternatively, you can bind the control to a data source that contains the information you want to display. For details, see
How to: Populate List Web Server Controls from a Data Source.
You can combine static and data-bound list items by setting the control's AppendDataBoundItems property to true.
When you define items for the BulletedList control, you define two properties: the Text property and the Value property. The
Text property defines what the control displays on the page. The Value property defines a second value that is not displayed
but that you might want to return when a user selects an item. For example, you might display an employee name as the text
of an item, but use the employee ID as the value; when users click the item, you can read the value directly.
Security Note
Do not use sensitive data, such as customer numbers, for the value property of a BulletedList control. Even though it is not v
isible, the Value property settings of individual items are rendered to the page, where users can easily read them in the page
's source.

Customizing List Item Appearance


The BulletedList control can render either bullets or numbers, according to the setting of the BulletStyle property. If the
control is set to render bullets, you can select from predefined bullet style fields that match HTML standard bullet styles, such
as those represented by the Disc, Circle, and Square fields.
Note
Individual browsers vary in how they render bullets, and some browsers do not support certain bullet styles, such as the Disc
field.

You can also specify a custom image that will be displayed instead of the bullet.
If the control is set to render numbers, you can likewise select from HTML standard numbering options, such as the
LowerAlpha, UpperAlpha, LowerRoman, and UpperAlpha fields. By setting the FirstBulletNumber property, you can also
specify a starting number for the sequence.
Specifying Item Display Mode
The BulletedList control can display list items as any of the following:
Static text The text displayed by the control is not interactive.
T:System.Web.UI.WebControls.HyperLink controls Users can click links to navigate to another page. You must
provide a target URL as the Value property of individual items.
LinkButton controls Users can click individual items and the control performs a postback.
Responding to User Selection
If the BulletedList control is configured to display individual items as LinkButton controls, the control performs a postback
when a user clicks an item. The postback raises the BulletedList control's Click event, where you can provide logic to perform
application-specific tasks. The event passes to you the index number of the item that was clicked. For details, see
How to: Respond to User Clicks in BulletedList Web Server Controls.
See Also
Reference
BulletedList
Visual Web Developer

How to: Add BulletedList Web Server Controls to a Web Forms


Page (Visual Studio)
The BulletedList control can display static text in a list that is either unordered (bulleted) or ordered (numbered).
To add a BulletedList Web server control to a Web Forms page
1. From the Standard tab of the Toolbox, drag a BulletedList control onto the page.
2. In the Properties window, set the DisplayMode property to one of the following values to specify how the control
displays list items:
Text Items are displayed as plain text.
HyperLink Items are displayed as hyperlinks.
LinkButton Items are displayed as links that perform a postback.
3. Add list items to the control in one of the following ways:
Add individual items. For details, see How to: Add Items in List Web Server Controls (Visual Studio).
Bind data to the control. For details, see
How to: Populate List Web Server Controls from a Data Source (Visual Studio).
Note
If you have set the DisplayMode property to HyperLink, specify the target URLs of the hyperlinks in each item's
Value property.

4. In the Properties window, set the BulletStyle property to specify whether the control displays items as bullets or as
numbers. To create a numbered, or ordered, list, set the property to one of the following enumeration values:
Numbered
LowerAlpha
UpperAlpha
LowerRoman
LowerRoman
To create a bulleted, or unordered, list, set the property to one of the following values:
Disc
Circle
Square
To display bullets as custom images, set the BulletStyle property to the URL of a graphic. The same graphic is displayed
for each item.
See Also
Concepts
BulletedList Web Server Control Overview
Visual Web Developer

How to: Respond to User Clicks in BulletedList Web Server


Controls (Visual Studio)
You can configure a BulletedList control to display LinkButton controls as the bulleted list items. When users click a button, the
control posts the page back to the server and gives you an opportunity to run code in response to the click.
To respond to a user click in a BulletedList Web server control
1. In Design view, double-click the BulletedList control and then add a handler for the BulletedList control's Click event.
2. In the event handler, get the Index property of the BulletedListEventArgs value passed to the handler.
3. Using the index, get the appropriate item from the control and then get the item's Text and Value properties.
Example
The following code example shows a Click event handler for a BulletedList control. The handler displays which list item the
user clicked.
VB
Protected Sub BulletedList1_Click(ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.BulletedListEventArgs) _
Handles BulletedList1.Click
Dim position As Integer = e.Index
Dim li As ListItem = BulletedList3.Items(position)
Label1.Text = "You selected = " & li.Text & _
", with value = " & li.Value
End Sub

C#
protected void BulletedList1_Click(object sender,
BulletedListEventArgs e)
{
ListItem li = BulletedList1.Items[e.Index];
Label1.Text = "You selected = " + li.Text + ", with value = "
+ li.Value;
}

See Also
Concepts
BulletedList Web Server Control Overview
Visual Web Developer

Button Web Server Controls (Visual Studio)


Buttons in an ASP.NET Web page allow users to send commands. Buttons submit the page to the server and cause it to be
processed along with any pending events. Web server controls include three types of buttons: a standard command button
(Button control), a hyperlink-style button (LinkButton control), and a graphical button (ImageButton control). All three provide
similar features, but each offers a different look.
The topics in this section describe ASP.NET button controls and how to program them.
In This Section
Button Web Server Controls Overview
How to: Add Button Web Server Controls to a Web Forms Page (Visual Studio)
How to: Add ImageButton Web Server Controls to a Web Forms Page (Visual Studio)
How to: Determine Coordinates in an ImageButton Web Server Control
How to: Respond to Button Web Server Control Events
How to: Respond to Button Web Server Control Events in Client Script
Related Sections
How to: Add Web Server Controls to a Web Forms Page Using the Web Forms Designer
Explains how to include Web server controls on a form.
How to: Set ASP.NET Server Control Properties (Visual Studio)
Explains how to set Web server control properties at design time.
Setting Web Server Control Properties Programmatically (Visual Studio)
Explains how to set Web server control properties in code.
Server Event Handling in ASP.NET Web Pages (Visual Studio)
Explains how to handle Web server control events.
See Also
Other Resources
Individual Web and HTML Controls
ASP.NET

Button Web Server Controls Overview


Using ASP.NET button Web server controls on ASP.NET Web pages allows users to indicate that they have completed the form
or that they want to perform a specific command. Web server controls include three kinds of buttons, each of which appears
differently on Web pages.
Types of Buttons
The following table lists the types of buttons that you can create by using Web server controls.
Control Description
Button Web se Presents a standard command button, which is rendered as an HTML input element.
rver control

LinkButton We Renders as a hyperlink in the page. However, it contains client-side script that causes the form to be posted ba
b server contro ck to the server. (You can create a true hyperlink by using the HyperLink Web server control.)
l

ImageButton Allows you to specify a graphic as a button. This is useful for presenting a rich button appearance. The ImageB
Web server co utton controls also pinpoint where in the graphic a user has clicked, which allows you to use the button as an i
ntrol mage map.
Note
You can also use the HtmlButton and HtmlInputButton controls to create buttons on the page that are programmable in serv
er code. For details about the differences between HTML and Web server controls, see
ASP.NET Web Server Controls Overview.

Button Events
When a user clicks any of the three types of buttons, a form is submitted to the server. This causes the Web page to be
processed and any pending events to be raised in server-based code. The buttons can also raise their own Click events, for
which you can write event handlers.
Button Controls and Validation
If a page contains ASP.NET validator controls, by default, clicking a button control causes the validator control to perform its
check. If client-side validation is enabled for a validator control, the page is not submitted if a validation check has failed.
The following table describes the properties supported by button controls that enable you to control the validation process
more precisely.
Property Description
CausesValidation Specifies whether clicking the button also performs a validation check. Set this property to false to prevent a
property validation check.

ValidationGroup Allows you to specify which validators on the page are called when the button is clicked. If no validation grou
property ps are established, a button click calls all of the validators that are on the page.

For more information, see Validating User Input in ASP.NET Web Pages.
Button Postback Behavior
When users click a button control, the page is posted back to the server. By default, the page is posted back to itself, where the
same page is regenerated and the event handlers for controls on the page are processed.
You can configure buttons to post the current page to another page. This can be useful for creating multi-page forms. For
details, see Cross-Page Posting in ASP.NET Web Pages.
By default, the Button control submits the page by using an HTML POST operation. The LinkButton and ImageButton
controls cannot directly support an HTML POST operation. Therefore, when you use those buttons, they add client script to the
page that allows the controls to submit the page programmatically. (The LinkButton and ImageButton controls therefore
require that client script is enabled on the browser.)
Under some circumstances, you might want the Button control to also use client script to perform the postback. This can be
useful if you want to programmatically manipulate the postback, such as attaching it to other elements on the page. You can
set the Button control's UseSubmitBehavior property to true to cause the Button control to use client-script based postback.
Handling Client-Side Events for Button Controls
Button controls can raise both server events and client events. Server events occur after postback, and they are handled in the
server-side code that you write for the page. Client events are handled in client script, typically ECMAScript (JavaScript), and
are raised before the page is submitted. By adding client-side events to ASP.NET button controls, you can perform tasks, such
as displaying confirmation dialog boxes before submitting the page, and potentially canceling the submission. For details, see
Client Script in ASP.NET Web Pages and How to: Respond to Button Web Server Control Events in Client Script.
Buttons in Data Controls
Button Web server controls are often used in data controls, such as in the DataList, GridView, and Repeater list controls. When
this is the case, you should typically respond to the button controls' events differently than when the button controls are
exclusively used on a form. When a user clicks a button that is in a data control, the event message is sent to the data control,
where it raises an event that is specific to the data control. For example, in the DataList control, a button might raise the
DataList control's ItemCommand event instead of raising the Button control's Click event.
Because the list Web server controls can contain many different buttons, you can set the button's CommandArgument
property to specify a value to pass as part of the event. You can then test for this argument to see which button was clicked.
Binding Data to the Controls
You can bind the button Web server controls to a data source in order to control their property settings dynamically. For
example, you can set the buttons' Text property via data binding.
See Also
Tasks
How to: Add Client Script Events to ASP.NET Web Server Controls
Concepts
Client Script in ASP.NET Web Pages
Cross-Page Posting in ASP.NET Web Pages
Visual Web Developer

How to: Add Button Web Server Controls to a Web Forms Page
(Visual Studio)
Web server controls make it easy for you to add different types of buttons to your Web Forms page. There are three types of
button Web-server controls: Button, LinkButton, and ImageButton. For more information, see
Button Web Server Controls Overview.
Adding an ImageButton control to a page is a little more involved than working with other button types. For details, see
How to: Add ImageButton Web Server Controls to a Web Forms Page (Visual Studio).
To add a button Web server control to a Web Forms page
1. From the Standard tab of the Toolbox, drag a Button or LinkButton control onto the page.
2. In the Appearance category of the Properties window, specify the button label by setting the control's Text property.
Defining an Access Key
To make it easier for users to click a button, you can define an access key for the button. Users can then simultaneously press
the ALT key and the access key to click the button.
Note
Access keys are not supported in all browsers.

To define the access key for a button


In the Accessibility category of the Properties window, set the button control's AccessKey property to a single letter or
number. For example, to make the access-key combination ALT+B, specify B as the value of the AccessKey property.
Note
In Windows applications, access keys are typically indicated on a button by an underlined character. This marking is not
available for button Web server controls due to restrictions in HTML. If you want to be able to display the access key for
a button, you can use the HtmlButton control.

See Also
Tasks
How to: Respond to Button Web Server Control Events
Other Resources
Setting Web Server Control Properties Programmatically (Visual Studio)
Visual Web Developer

How to: Add ImageButton Web Server Controls to a Web


Forms Page (Visual Studio)
You can add an ImageButton Web server control to your Web Forms page when you want to display a picture, or image, as a
hyperlink.
Note
To create an image with multiple clickable regions, you can use the ImageMap control. For details, see
ImageMap Web Server Control Overview.

To add an ImageButton Web server control to a Web Forms page


1. From the Standard tab of the Toolbox, drag an ImageButton Web server control onto the page.
2. In the Appearance category of the Properties window, set the button's ImageUrl property to point to an image file (.gif,
.jpg, and so on).
Note
Click the ellipsis (...) button in the ImageUrl property box to select an image using the Select Image dialog box.

You can point to an image file anywhere by using a URL or UNC path.
Security Note
The URL associated with an ImageButton control can be tampered with by a malicious user. For more information,
How to: Protect Against Script Exploits in a Web Application by Applying HTML Encoding to Strings.

See Also
Tasks
How to: Determine Coordinates in an ImageButton Web Server Control
ASP.NET

How to: Determine Coordinates in an ImageButton Web Server


Control
When users click an ImageButton control, a parameter passed to the event handler for the control's Click event includes the
coordinates indicating where the user clicked. This allows you to perform different tasks based on where the user clicked.
Note
If you want to define specific areas of an image as regions that users can click, you can also use the ImageMap control.

Coordinate information is sent as part of the event-argument object for the ImageButton control's Click event.
To determine the coordinates where a user clicks
1. Create an event handler for the ImageButton control's Click event. The event-argument object for the method must be
of type ImageClickEventArgs.
2. In the Click event handler, get the X and Y properties of the ImageClickEventArgs argument object.
The x and y coordinates are expressed in pixels, where the upper left corner of the image is (0,0).
The following example shows how you can determine where the user clicked in a graphic that is 100 by 100 pixels. The
code gets the x and y coordinates where the user clicked. It then compares them against predetermined values to see if
the user clicked in a particular quadrant. The results are displayed in a Label control.
VB
Protected Sub ImageButton1_Click(ByVal sender As System.Object, _
ByVal e As System.Web.UI.ImageClickEventArgs) _
Handles ImageButton1.Click
Dim msg as String = ""
Dim x As Integer = e.X
Dim y As Integer = e.Y

' The button graphic is assumed to be 100x100 pixels.


' This checks coordinates against predetermined values that
' make up quadrants of the picture.
If x >= 50 And y >= 50 Then
msg = "Southeast"
ElseIf x >= 50 And y < 50 Then
msg = "Northeast"
ElseIf x < 50 And y >= 50 Then
msg = "Southwest"
ElseIf x < 50 And y < 50 Then
msg = "Northwest"
End If
Label1.Text = msg
End Sub

C#
protected void ImageButton1_Click(object sender,
System.Web.UI.ImageClickEventArgs e)
{
string msg = "";
int x = e.X;
int y = e.Y;

// The button graphic is assumed to be 100x100 pixels.


// This checks coordinates against predetermined values that
// make up quadrants of the picture.
if(x >= 50 && y >= 50)
{
msg = "Southeast";
}
else if(x >=50 && y < 50)
{
msg = "Northeast";
}
else if(x < 50 && y >= 50)
{
msg = "Southwest";
}
else if(x < 50 && y < 50)
{
msg = "Northwest";
}
Label1.Text = msg;
}

See Also
Reference
Button Web Server Controls Overview
ASP.NET

How to: Respond to Button Web Server Control Events


When a Button, LinkButton, or ImageButton Web server control is clicked, the current page is submitted to the server, where it
is processed.
To respond to a button event
Create an event handler for one of the following events:
The page's Page_Load event. Because the button always posts the page to the server, this method will always
run. Use the Page_Load event when it is not important which button was clicked, only that the form was
submitted.
The button's Click event. Write an event handler for this event when it is important to know which button was
clicked.
Note
If you are working with an ImageButton control and want to know the x and y coordinates of the user's click, y
ou must create an event handler for this event. For details, see
How to: Determine Coordinates in an ImageButton Web Server Control.

The following example shows how you can respond when a user clicks a Button Web server control. The method
displays a message in a Label Web server control.
VB
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles Button1.Click
Label1.Text="You clicked a button"
End Sub

C#
public void Button1_Click (object sender, System.EventArgs e)
{
Label1.Text="You clicked a button.";
}

The following example shows how you can respond to a button click in a Page_Load event handler. The method tests
the page's IsPostBack property to determine whether this is the first time the page has been processed or whether it was
submitted by a button click.
VB
Private Sub Page_Load(ByVal Sender As System.Object, ByVal e _
As System.EventArgs) Handles MyBase.Load
If Not IsPostback Then
' This is called the first time the page has loaded.
' The user will not have been able to click any buttons yet.
Else
' This is called if the form has been posted back, possibly
' by a button click.
Me.Label1.Text = "You clicked a button."
End If
End Sub

C#
private void Page_Load(object sender, System.EventArgs e)
{
if (!IsPostBack)
{
// Evals true first time browser hits the page.
}
else
{
// This is called if the form has been posted back, possibly
// by a button click.
this.Label1.Text = "You clicked a button.";
}
}

The following example shows a simple four-function integer calculator. By binding all of the buttons (Add, Subtract,
Multiply, and Divide) to the same method, you can handle all the calculations in one place and avoid repetitive code.
Binding the buttons to the Calculate method is accomplished by using the AddHandler method in Visual Basic, and by
using the += operator in C#. To ensure that the input values are integers, you could add error-handling code to the
Calculate method or use the validation controls that are available for Web Forms.
VB
' Set the CommandName property of the buttons to "Add",
' "Subtract", "Multiply", and "Divide".
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Hand
les MyBase.Load
AddHandler Me.btnAdd.Click, AddressOf Calculate
AddHandler Me.btnSubtract.Click, AddressOf Calculate
AddHandler Me.btnMultiply.Click, AddressOf Calculate
AddHandler Me.btnDivide.Click, AddressOf Calculate
End Sub

Public Sub Calculate(ByVal sender As Object, ByVal e As System.EventArgs)


Dim op1 As Integer = CType(Me.TextBox1.Text, Integer)
Dim op2 As Integer = CType(Me.TextBox2.Text, Integer)
Dim result As Integer
Select Case CType(sender, Button).CommandName
Case "Add"
result = op1 + op2
Case "Subtract"
result = op1 - op2
Case "Multiply"
result = op1 * op2
Case "Divide"
' Divide two numbers and return an integer result.
If op2 > 0 Then
result = op1 \ op2
Else
result = 0
End If
Case Else
' Error handling code here.
End Select
Label1.Text = result.ToString()
End Sub

C#
// Set the CommandName property of the buttons to "Add", _
// "Subtract", "Multiply", and "Divide".
protected void Page_Load(object sender, EventArgs e)
{
btnAdd.Click += new System.EventHandler(this.Calculate);
btnSubtract.Click += new System.EventHandler(this.Calculate);
btnMultiply.Click += new System.EventHandler(this.Calculate);
btnDivide.Click += new System.EventHandler(this.Calculate);
}

protected void Calculate (object sender, System.EventArgs e)


{
int op1 = Convert.ToInt16(TextBox1.Text);
int op2 = Convert.ToInt16(TextBox2.Text);
int result = 0;
switch(((Button)sender).CommandName)
{
case "Add" :
result = op1 + op2;
break;
case "Subtract" :
result = op1 - op2;
break;
case "Multiply" :
result = op1 * op2;
break;
case "Divide" :
// Integer division.
if (op2 > 0)
result = op1 / op2;
else
result = 0;
break;
default:
// Error handling code here.
break;
}
Label1.Text = result.ToString();
}

See Also
Reference
Button Web Server Controls Overview
ASP.NET

How to: Respond to Button Web Server Control Events in Client


Script
Button controls can raise both server events and client events. Server events occur after postbacks, and they are handled in the
server-side code that you write for the page. Client events are handled in client script, typically JavaScript (ECMAScript), and
they are raised before the page is submitted. By adding client-side events to ASP.NET button controls, you can perform tasks
such as displaying confirmation dialog boxes before submitting the page, and canceling the page submission altogether.
To add client script, which handles the OnClientClick event, to a button Web server control
In the ASP.NET button Web server control to which you want to add client script (a Button, LinkButton, or ImageButton
control), set the OnClientClick property to the client script that you want to run.
Note
If you want to be able to cancel the submission, set the OnClientClick property to the string "Return" and the function
name. The client script can then cancel the submission by returning false.

The following code example shows how to add a client-script click event to a Button control.
VB
<%@ Page Language="VB" %>
<script runat="server">
Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs)
Label1.Text = "Server click handler called."
End Sub
</script>

<body>
<form id="form1" runat="server">
<asp:Button ID="Button1" Runat="server"
OnClick="Button1_Click"
OnClientClick="return confirm('Ready to submit.')"
Text="Test Client Click" />
<br />
<asp:Label ID="Label1" Runat="server" text="" />
</form>
</body>
</html>

C#
<%@ Page Language="C#" %>
<script runat="server">
void Button1_Click(Object sender, EventArgs e)
Label1.Text = "Server click handler called.";
End Sub
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >


<body>
<form id="form1" runat="server">
<asp:Button ID="Button1" Runat="server"
OnClick="Button1_Click"
OnClientClick="return confirm('Ready to submit.')"
Text="Test Client Click" />
<br />
<asp:Label ID="Label1" Runat="server" text="" />
</form>
</body>
</html>

See Also
Reference
Button Web Server Controls Overview
Visual Web Developer

Calendar Web Server Control (Visual Studio)


The Calendar Web server control displays a traditional one-month calendar on an ASP.NET page. Users can view and select
dates on the calendar.
The topics in this section provide information about the Calendar Web server control and how to use it.
In This Section
Calendar Web Server Control Overview
How to: Control Month Navigation in a Calendar Web Server Control
How to: Control User Date Selection in a Calendar Web Server Control
How to: Customize Calendar Web Server Control Appearance
How to: Customize Individual Days in a Calendar Web Server Control
How to: Format Calendar Web Server Control Elements Using Styles
How to: Respond to Date Selection in a Calendar Web Server Control
How to: Read Selected Dates in the Calendar Web Server Control
How to: Select Dates Programmatically in a Calendar Web Server Control
How to: Set Today's Date Programmatically in a Calendar Web Server Control
How to: Display Selected Dates from a Database in the Calendar Control
See Also
Other Resources
Individual Web and HTML Controls
ASP.NET

Calendar Web Server Control Overview


You can use the Calendar Web server control to do the following:
Display and select dates The control displays a calendar through which users can navigate to any day in any year.
Setting the SelectedDate property causes a specific date to be highlighted in the control. Optionally, users can move to
arbitrary dates by clicking a day or moving from month to month. The calendar can be configured to allow users to select
multiple dates, either an entire week or an entire month.
A representation of the Calendar control displaying the month of October

Display appointment or other information in a calendar grid The Calendar control can display specific details for
individual days, such as a to-do list, a schedule of events, or similar information. This feature allows you to display day
information from a database.
The Calendar control is based on the .NET Framework DateTime object, and therefore supports the full range of dates that is
allowed by that object. Effectively, you can display any date between the years 0 and 9999 A.D.
When the Web Forms page runs, the Calendar control is rendered as an HTML table. Therefore, a number of the control's
properties pertain to various aspects of table formatting. A few of these properties are not fully supported in some older
browsers, so not all of the formatting features will be available in those browsers.
Displaying and Selecting Dates
The Calendar control displays the dates for one month at a time, with a total of six weeks appearing at once. The control
supports several types of dates, which are described in the following table.
Type of date Description
TodaysDate By default, this is set to match the current date on the server. However, you can adjust it so that the date appear
s correctly for a different locale.

VisibleDate This date determines which month appears in the calendar. The user can move from month to month on the cal
endar, thereby changing the visible date without affecting today's date. You can navigate between months by se
tting the visible date programmatically.

SelectedDat This is the date or date range that the user chooses. In the control, the user can choose a single day, week, or mo
e, nth, but can only select contiguous dates. You can also programmatically set the selected dates; in that case, you
SelectedDates can set non-contiguous selected dates.

Enabling Date Selection


By default, the calendar allows users to click an individual date to select it. If you are using the control as a read-only calendar,
you can disable the date-selection functionality.
If date selection is enabled, each day of the calendar contains a LinkButton control that raises an event when clicked. If you
enable week or month selection, a column of links is added to the left side of the calendar to enable the user to specify which
week to select.
Customizing the Calendar's Appearance
You can set calendar properties to change the colors, size, text, and other visual features of the calendar. There are a number of
ways to do this, as shown in the following table.
Customizati Description
on method
Setting prope You can set properties to display grid lines, change which day is displayed as the first day of the week, and chan
rties ge the appearance of the month and day names.

Setting exten You can use properties derived from the Style object to set the appearance of particular elements in the calend
ded style pro ar, such as the current date or the title bar containing the month and navigation links. These style properties are
perties supported in browsers that can use cascading style sheets; a reduced set of appearance styles is supported for e
arlier browsers.

Customizing t As the control renders individual days, it raises an event that you can handle to modify the stream being render
he rendering ed to the browser. This is useful not just for changing the appearance of days, but for including custom content
of individual on each day as well. For details, see How to: Customize Individual Days in a Calendar Web Server Control.
days

Capturing User Interaction with the Calendar Web Server Control


The Calendar control raises the SelectionChanged event when the user selects an individual date or range of dates and the
VisibleMonthChanged event when the user navigates to a new month. By creating methods for these events, you can
determine what day or dates the user has selected and respond appropriately. One response may be to customize the display
of that date.
Displaying Information from a Database in the Calendar Control
A common scenario is to display information from a database in the calendar. For example, an events calendar is often based
out of information that is stored in a database.
The Calendar control does not directly support data binding — that is, you do not bind the calendar as a whole to a data
source. Instead, you create a method for the control's DayRender event, which is raised as each day in the current calendar
month is being rendered. In the method for this event, you can extract information from a data source and add it to the stream
being sent to the browser. For details, see How to: Display Selected Dates from a Database in the Calendar Control.
Accessibility
To make the Calendar control more accessible to users of assistive devices, the control supports a property named
UseAccessibleHeader. When this property is set to true (which is the default setting), the column headings containing the
names of days are rendered using HTML th elements.
See Also
Tasks
How to: Customize Individual Days in a Calendar Web Server Control
How to: Select Dates Programmatically in a Calendar Web Server Control
How to: Display Selected Dates from a Database in the Calendar Control
ASP.NET

How to: Control Month Navigation in a Calendar Web Server


Control
By default, the calendar displays the month containing today's date. Users can move from month to month in the Calendar
control by clicking month navigation links (which are LinkButton Web server controls) in the title bar of the calendar. You can
control whether these links are available for the user to click.
You can also navigate programmatically, which is useful if you want to provide an alternate way for users to display a specific
month. Finally, you can respond to an event raised when the user navigates.
To enable or disable user month navigation
Set the Calendar control's ShowNextPrevMonth property to true or false. If the property is false, the control does not
display the LinkButton controls in the title that allow a user to move between months.
Tip
You can change the appearance of the month-navigation hyperlinks by setting the NextMonthText, PrevMonthText,
NextPrevFormat, and NextPrevStyle properties.

To navigate months programmatically


Set the control's VisibleDate property to a date in the month you want to display. The date can be any day within that
month but is typically set to the first day of the month. If the VisibleDate property is empty (if it is set to
DateTime.Empty), the currently visible month is derived from the value of the TodaysDate property.
The following example navigates to February, 2000:
VB
Calendar1.VisibleDate = New Date(2000, 2, 1)

C#
Calendar1.VisibleDate = new DateTime(2000, 2, 1);

Changing the VisibleDate property has no effect on the values of the TodaysDate, SelectedDayStyle, or SelectedDates
properties.
If month navigation is enabled, the control raises an event when the user moves to another month. You can handle this event
in order to replace or amend the default month navigation. For example, if you are using two Calendar controls in a trip-
planning page, you can prevent the user from setting the start-date month later than the end-date month.
To respond to a month navigation event
Create a method for the control's VisibleMonthChanged event. When this event is raised, the control has already
changed the VisibleMonth property by 1.
The VisibleMonthChanged event takes a single argument of type MonthChangedEventArgs. You can use the
following properties of this argument to determine or override what the user is doing:
Property Description
PreviousDate The value of the month that was displayed before the user clicked a month-navigation button. You can co
mpare the value of this property to that of the control's VisibleMonth property to determine the direction
in which the user is navigating. To cancel the effect of the user's click, set the control's VisibleDate propert
y to this value.
NewDate The value of the month that the user has navigated to. The VisibleDate property is updated to this value b
efore the VisibleMonthChanged event is raised.

VB
Public Sub Calendar1_VisibleMonthChanged(ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.MonthChangedEventArgs) _
Handles Calendar1.VisibleMonthChanged

' Select the 10th and 25th of each month.


Calendar1.SelectedDates.Clear()
Calendar1.SelectedDates.Add(New DateTime(e.NewDate.Year, e.NewDate.Month, 10))
Calendar1.SelectedDates.Add(New DateTime(e.NewDate.Year, e.NewDate.Month, 25))
End Sub

C#
private void Calendar1_VisibleMonthChanged (object sender,
System.Web.UI.WebControls.MonthChangedEventArgs e)
{
// Select the 10th and 25th of each month.
Calendar1.SelectedDates.Clear();
Calendar1.SelectedDates.Add(new DateTime(e.NewDate.Year, e.NewDate.Month, 10));
Calendar1.SelectedDates.Add(new DateTime(e.NewDate.Year, e.NewDate.Month, 25));
}

See Also
Concepts
Calendar Web Server Control Overview
ASP.NET

How to: Control User Date Selection in a Calendar Web Server


Control
You can specify that users can select individual days, individual weeks, or an entire month in the Calendar control.
Alternatively, you can disable day selection altogether.
To control user date selection
Set the Calendar control's SelectionMode property to one of the values defined in the SelectionMode enumeration:
Day, DayWeek, or DayWeekMonth. To disable all date selection, set the property to None.
Note
Users can only select a single day, a single week, or the whole month. However, in code you can select any arbitrary set
of dates. For details, see How to: Select Dates Programmatically in a Calendar Web Server Control.

When selection is enabled, the form is submitted whenever the user selects a day, week, or month, and an event is raised for
which you can create a method. For details, see How to: Respond to Date Selection in a Calendar Web Server Control.
To allow the user to select a date, the calendar is displayed with links. Individual days contain a link with the date number. If
you set the calendar to allow users to select a week or the whole month, an extra column with selection links is added to the
left of the calendar.
Note
You can also control date selection for individual days. For example, you might specify that users can click specific days of the
month, such as holidays. For details about customizing days in this way, see
How to: Customize Individual Days in a Calendar Web Server Control.

You can specify the text for the week and month selection links.
To specify week and month selection link text
Set the SelectWeekText and SelectMonthText properties to the text you want to use for the navigation links.
You can also set the font, color, and border style of the column containing the week and month selection links and set
styles for days. For details, see Formatting Web Calendar Elements Using Styles.
See Also
Concepts
Calendar Web Server Control Overview
ASP.NET

How to: Customize Calendar Web Server Control Appearance


Because the Calendar control is a complex control made up of many individual elements, it offers you a wide variety of options
for customizing its appearance.
Changing General Calendar Appearance
The Calendar control establishes a default look for the calendar on the page, but you can change the calendar's overall
appearance. If you set appearance properties for individual calendar elements, such as today's date, the selected date, and so
on, the individual settings are based on the default settings you make for the calendar as a whole. You can also select from
predefined formats.
Note
By default, there is no special formatting to indicate today's date on the Calendar control. For details about how to set this fo
rmat, see Formatting Web Calendar Elements Using Styles.

To change the general appearance of the Calendar control


Set properties as listed in the following table.
To specify Set this property
Font, text and background color Font, ForeColor, BackColor.

Overall control size Height, Width

Margins and spacing around individual days CellPadding, CellSpacing

Color, size, and style (for example, dotted) of bor BorderColor


der and grid lines
BorderStyle (set to a BorderStyle enumeration value: Dotted,
Dashed, Solid, and so on).
ShowGridLines (true or false)

Changing Day-of-Week Display


By default, the names of the days of the week are displayed in a row at the top of the calendar. You can control the format of
this row.
To change the day of week display
Set properties as listed in the following table.
To Set this property
Enable or disable the row that deploys days of th ShowDayHeader (true or false)
e week

Specify the format of day names (for example, fu DayNameFormat (use a value in the DayNameFormat enumeration: F
ll day name or abbreviation) ull, Short, FirstLetter, FirstTwoLetters).

Specify which day starts the week (default is Sun FirstDayOfWeek (use a day defined in the FirstDayOfWeek enumerati
day) on.

Set color, font, border style and width, and so on DayHeaderStyle, which incorporates style information.

Changing the Month Display and Navigation Links


The title bar by default displays the name of the current month and a set of navigation links (LinkButton controls) that allow
The title bar by default displays the name of the current month and a set of navigation links (LinkButton controls) that allow
users to move to the next and previous months.
To change month display and navigation links
Set properties as listed in the following table.
To Set this property
Remove the title bar altogether (which disables month navi ShowTitle (true or false)
gation).

Specify the format of the name of the month (for example, f TitleFormat (set to a value in the TitleFormat enumeration:
ull name or abbreviation) and optionally add a year. Month or MonthYear).

Specify the format and text of month navigation links NextPrevFormat (use a value in the NextPrevForm
at enumeration: Month or CustomText).
NextMonthText and PrevMonthText (set to strings)

Set color, font, border style and width, and so on TitleStyle, which incorporates style information. For details, s
ee Formatting Web Calendar Elements Using Styles.
Note
You can format the navigation links separately using the
NextPrevStyle property.

Note
You can use HTML tags within the property string.

See Also
Concepts
Calendar Web Server Control Overview
ASP.NET

How to: Customize Individual Days in a Calendar Web Server


Control
By default, days in the Calendar control are displayed as numbers. If day selection is enabled, the numbers appear as links. For
details, see How to: Control User Date Selection in a Calendar Web Server Control.
You can customize the appearance and content of individual days, which allows you to:
Programmatically highlight certain days, for example, showing holidays in a different color.
Programmatically specify whether an individual day can be selected.
Add information into the day display, such as appointment or event information.
Customize the link text that users can click to select a day.
When the Calendar control is creating the output to send to the browser, it raises a DayRender event. The control raises the
event for each day as it is preparing the day for display, so you can then programmatically examine which date is being
rendered and customize it appropriately.
The DayRender event method takes two arguments: a reference to the control raising the event (the Calendar control) and an
object of type DayRenderEventArgs. The DayRenderEventArgs object provides access to two additional objects:
Cell, a TableCell object that you can use to set the appearance of an individual day.
Day, which you can use to query information about the day being rendered, control whether the day can be selected, and
add content to a day. The Day object supports various properties you can use to learn about the day (for example,
IsSelected, IsToday, and so on). It also supports a Controls collection that you can manipulate to add content to the day.
To customize the appearance of an individual day
1. Create a method to handle the Calendar control's DayRender event.
2. In the method, set properties of the Cell object, which you can access with the DayRenderEventArgs argument.
The following example shows how to change the appearance of individual days. The method causes vacation days in the
calendar to be rendered in yellow, while weekend days are rendered in green. In the example, vacation days are
November 23 through November 30, 2005.
VB
Protected Sub Calendar1_DayRender(ByVal sender As Object, _
ByVal e As DayRenderEventArgs) Handles Calendar1.DayRender
' Display vacation dates in yellow boxes with purple borders.
Dim vacationStyle As New Style()
With vacationStyle
.BackColor = System.Drawing.Color.Yellow
.BorderColor = System.Drawing.Color.Purple
.BorderWidth = New Unit(3)
End With

' Display weekend dates in green boxes.


Dim weekendStyle As New Style()
weekendStyle.BackColor = System.Drawing.Color.Green

' Vacation is from Nov 23, 2005 to Nov 30, 2005.


If ((e.Day.Date >= New Date(2005, 11, 23)) _
And (e.Day.Date <= New Date(2005, 11, 30))) Then
e.Cell.ApplyStyle(vacationStyle)
ElseIf (e.Day.IsWeekend) Then
e.Cell.ApplyStyle(weekendStyle)
End If
End Sub

protected void Calendar1_DayRender(object sender,


DayRenderEventArgs e)
{
// Display vacation dates in yellow boxes with purple borders.
Style vacationStyle = new Style();
vacationStyle.BackColor = System.Drawing.Color.Yellow;
vacationStyle.BorderColor = System.Drawing.Color.Purple;
vacationStyle.BorderWidth = 3;

// Display weekend dates in green boxes.


Style weekendStyle = new Style();
weekendStyle.BackColor = System.Drawing.Color.Green;

if ((e.Day.Date >= new DateTime(2000,11,23)) &&


(e.Day.Date <= new DateTime(2000,11,30)))
{
// Apply the vacation style to the vacation dates.
e.Cell.ApplyStyle(vacationStyle);
}
else if (e.Day.IsWeekend)
{
// Apply the weekend style to the weekend dates.
e.Cell.ApplyStyle(weekendStyle);
}

To specify that an individual day can be selected


1. In a method for the Calendar control's DayRender event, determine what day is being rendered by getting information
from the Date property of the Day object.
2. Set that day's IsSelectable property to true.
The following example shows how to set the date October 1, 2005, as selectable; all other dates are made not selectable.
VB
Protected Sub Calendar1_DayRender(ByVal sender As Object, _
ByVal e As DayRenderEventArgs) Handles Calendar1.DayRender
Dim myAppointment As Date = New Date(2005, 10, 1)
If (e.Day.Date = myAppointment) Then
e.Day.IsSelectable = True
Else
e.Day.IsSelectable = False
End If
End Sub

C#
protected void Calendar1_DayRender(object sender,
DayRenderEventArgs e)
{
DateTime myAppointment = new DateTime(2005, 10, 1);
if (e.Day.Date == myAppointment)
{
e.Day.IsSelectable = true;
}
else
{
e.Day.IsSelectable = false;
}
}

To add content to an individual day


In a handler for the Calendar control's DayRender event, add any HTML or ASP.NET Web control to the Controls
collection of the Day object from the DayRenderEventArgs argument.
The following example displays holidays. The list of holidays is created as a two-dimensional array during page load.
Holiday descriptions are loaded into the elements corresponding to their date. In the DayRender event method, each
day is compared against the holiday array. If the corresponding element of the holiday array contains a value, a Label
control is created with the holiday text and added into the Controls collection for that day.
VB
Dim holidays(13, 32) As String

Protected Sub Page_Load(ByVal sender As Object, _


ByVal e As System.EventArgs) Handles Me.Load
holidays(1, 1) = "Birthday"
holidays(2, 14) = "Anniversary"
End Sub

Protected Sub Calendar1_DayRender(ByVal sender As Object, _


ByVal e As DayRenderEventArgs) Handles Calendar1.DayRender
If e.Day.IsOtherMonth Then
e.Cell.Controls.Clear()
Else
Dim aDate As Date = e.Day.Date
Dim aHoliday As String = holidays(aDate.Month, aDate.Day)
If (Not aHoliday Is Nothing) Then
Dim aLabel As Label = New Label()
aLabel.Text = "<br>" & aHoliday
e.Cell.Controls.Add(aLabel)
End If
End If
End Sub

C#
string[,] holidays = new String[13, 32];

protected void Calendar1_DayRender(object sender, DayRenderEventArgs e)


{
string aHoliday;
DateTime theDate = e.Day.Date;
aHoliday = holidays[theDate.Month, theDate.Day];
if (aHoliday != null)
{
Label aLabel = new Label();
aLabel.Text = " <br>" + aHoliday;
e.Cell.Controls.Add(aLabel);
}

protected void Page_Load(object sender, EventArgs e)


{
holidays[1, 1] = "Birthday";
holidays[2, 14] = "Anniversary";
}

To customize the link text for individual days


1. In a method for the Calendar control's DayRender event, get the SelectUrl property of the DayRenderEventArgs
argument. The SelectUrl property returns the JavaScript that is normally rendered for that day to cause a postback
indicating date selection.
2. Using concatenation, create an HTML hyperlink that uses the value of the SelectUrl property as the href attribute.
3. Add the hyperlink as the Text property of the Cell object.
The following example displays holidays. The list of holidays is created as a two-dimensional array during page load.
Holiday descriptions are loaded into the elements corresponding to their date. In the DayRender event method, each
day is compared against the holiday array. If the corresponding element of the holiday array contains a value, the code
creates link text that displays the holiday name instead of the day number.
VB
Dim holidays(13, 32) As String

Protected Sub Page_Load(ByVal sender As Object, _


ByVal e As System.EventArgs) Handles Me.Load
holidays(1, 1) = "Birthday"
holidays(2, 14) = "Anniversary"
End Sub

Protected Sub Calendar1_DayRender(ByVal sender As Object, _


ByVal e As DayRenderEventArgs) Handles Calendar1.DayRender
If e.Day.IsOtherMonth Then
e.Cell.Controls.Clear()
Else
Dim aDate As Date = e.Day.Date
Dim aHoliday As String = holidays(aDate.Month, aDate.Day)
If (Not aHoliday Is Nothing) Then
e.Cell.Text = _
"<a href=" & e.SelectUrl & ">" & aHoliday & "</a>"
End If
End If
End Sub

C#
string[,] holidays = new String[13, 32];

protected void Calendar1_DayRender(object sender, DayRenderEventArgs e)


{
string aHoliday;
DateTime theDate = e.Day.Date;
aHoliday = holidays[theDate.Month, theDate.Day];
if (aHoliday != null)
{
e.Cell.Text = "<a href=" + e.SelectUrl + ">" +
aHoliday + "</a>";
}
}

protected void Page_Load(object sender, EventArgs e)


{
holidays[1, 1] = "Birthday";
holidays[2, 14] = "Anniversary";
}

See Also
Tasks
How to: Display Selected Dates from a Database in the Calendar Control
Concepts
Calendar Web Server Control Overview
ASP.NET

How to: Format Calendar Web Server Control Elements Using


Styles
The Calendar control, like most Web server controls, allows you to use styles to specify the appearance of the control,
including aspects such as font, color, and borders. For general information about using styles with Web server controls, see
ASP.NET Web Server Controls and CSS Styles.
Note
Styles are not fully supported in all browsers.

To allow you flexibility in customizing the appearance of the calendar output, the Calendar control supports styles for a
number of discrete elements that make up the calendar grid. The following diagram displays a calendar with all optional
elements displayed.

The following table describes each of the elements that you can control using styles.
Calendar Element Description
DayStyle Days of the current month. Weekends, today, and the selected day can have different styles (see below).

DayHeaderStyle Row above the calendar where the names of the days appear.

NextPrevStyle Sections at the left and right ends of the title bar where the month-navigation LinkButtons are.

OtherMonthDayStyle Days from the previous and next month that appear on the current month view.

SelectedDayStyle The day selected by the user.

SelectorStyle The column to the left containing links for selecting a week or the whole month.

TitleStyle Title bar at the top of the calendar containing the month name and month navigation links. If NextPrevS
tyle is set, it overrides the extreme ends of the title bar.

TodayDayStyle Today's date.

WeekendDayStyle Weekend days.

To set calendar element styles


1. Type a style element, such as an <DayStyle> or <TitleStyle> element, into the page as a child of the Calendar control.
For syntax, see Calendar Web Server Control.
2. Set properties (attributes) of the style element, such as BackColor or BorderWidth.
The following shows a Calendar control declaration with a DayStyle element:

<asp:Calendar id="Calendar1" runat="server">


<DayStyle BackColor="#FF8080"
BorderWidth="2"
BorderStyle="Groove">
</DayStyle>
</asp:Calendar>

You can also set style elements at run time in code.


To set calendar element styles programmatically
Set properties of individual style elements using the following syntax:

Calendar1.StyleName.Property = setting

The following examples illustrate some typical style settings for the Calendar control:
VB
Calendar1.DayStyle.Font.Size = New FontUnit(10)
Calendar1.TitleStyle.ForeColor = System.Drawing.Color.Red

C#
Calendar1.DayStyle.Font.Size = new FontUnit(10);
Calendar1.TitleStyle.ForeColor = System.Drawing.Color.Red;

Note
For details about setting properties, see Setting ASP.NET Server Control Properties.

See Also
Concepts
Calendar Web Server Control Overview
ASP.NET

How to: Respond to Date Selection in a Calendar Web Server


Control
If the Calendar control's SelectionMode property is set to anything other than None, the user can select a day or a range of
dates. You can detect and respond to the user's choice.
To respond to a date selection
Create a method for the Calendar control's SelectionChanged event with the following signature:
VB
Private Sub Calendar1_SelectionChanged(ByVal sender _
As System.Object, ByVal e As System.EventArgs) _
Handles Calendar1.SelectionChanged

C#
private void Calendar1_SelectionChanged (object sender,
System.EventArgs e)

Note
The event is raised only if the date selection is changed by user action in the control. For instance, if the user clicks the s
ame date twice, the second click does not raise an event. The event is also not raised if you set a date range programma
tically.

Information about date selection is available in these properties:


Property Description
SelectedDate A single date. If the user has selected a single date, this property contains that date. If the user has selected multi
ple dates, this property contains the first date in the range.

SelectedDates A collection containing all the dates selected. The dates in this collection are ordered and unique. Because the Ca
lendar control does not allow the user to select multiple individual dates, the dates in the collection are also seq
uential.

To determine how many dates are selected


Get the value of the Count property of the SelectedDates collection, as shown in the following example.
VB
Public Sub Calendar1_SelectionChanged(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles Calendar1.SelectionChanged

Text1.Text = "You selected " _


& Calendar1.SelectedDates.Count.ToString() _
& " date(s)."
End Sub

C#
private void Calendar1_SelectionChanged (object sender, System.EventArgs e)
{
Text1.Text = String.Format("You selected {0} date(s).",
Calendar1.SelectedDates.Count);
}

If you've determined that the user has selected multiple dates, you can get the range.
To get the date range of a multi-date selection
1. Get the count of selected dates using the Count property of the SelectedDates property.
2. Get the first date in the collection, and then get the last date by extracting the date at the index of the count minus one.
The following example displays the first and last dates in text box controls on the page.
VB
Public Sub Calendar1_SelectionChanged(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles Calendar1.SelectionChanged

With Calendar1.SelectedDates
If .Count > 1 Then
Dim firstDate As Date = .Item(0).Date
Dim lastDate As Date = .Item(.Count - 1).Date
TextBox1.Text = firstDate.ToString()
TextBox2.Text = lastDate.ToString()
End If
End With
End Sub

C#
private void Calendar1_SelectionChanged (object sender,
System.EventArgs e)
{
SelectedDatesCollection theDates = Calendar1.SelectedDates;
if (theDates.Count > 1)
{
DateTime firstDate = theDates[0];
DateTime lastDate = theDates[theDates.Count-1];
TextBox1.Text = firstDate.ToString();
TextBox2.Text = lastDate.ToString();
}
}

To get the time span of a multi-date selection


Create a TimeSpan object and set it to the difference between the last and first dates in the SelectedDates collection,
and then get the TimeSpan object's Days property.
VB
Public Sub Calendar1_SelectionChanged(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Calendar1.SelectionChanged
With Calendar1.SelectedDates
Dim days As Integer
Dim firstDate As Date = .Item(0).Date
Dim lastDate As Date = .Item(.Count - 1).Date
' The Subtract method returns a TimeSpan object.
days = lastDate.Subtract(firstDate).Days + 1
TextBox1.Text = "You have selected " & days.ToString() & " day(s)."
End With
End Sub
C#
private void Calendar1_SelectionChanged (object sender,
System.EventArgs e)
{
SelectedDatesCollection theDates = Calendar1.SelectedDates;
TimeSpan timeSpan = theDates[theDates.Count-1] - theDates[0];
TextBox1.Text =
String.Format("You have selected {0} day(s).", timeSpan.Days + 1);
}

See Also
Tasks
How to: Select Dates Programmatically in a Calendar Web Server Control
Concepts
Calendar Web Server Control Overview
ASP.NET

How to: Read Selected Dates in the Calendar Web Server


Control
The first example displays the currently selected day. The second example displays all selected dates, which might be a single
day, a week, or a month.
Example
VB
' Example 1
Label1.Text = Calendar1.SelectedDate.ToShortDateString()

' Example 2
Dim s As String = ""
Dim d As DateTime
For Each d In Calendar1.SelectedDates
s &= "<br />" & d.ToShortDateString()
Next
Label1.Text = s

C#
// Example 1
Label1.Text = Calendar1.SelectedDate.ToShortDateString();

// Example 2
String s = "";
foreach(DateTime d in Calendar1.SelectedDates)
{
s += "<br />" + d.ToShortDateString();
}
Label1.Text = s;

Compiling the Code


This example requires:
A Web Forms page.
A Calendar control named Calendar1.
A Label control named Label1.

Robust Programming
If only one day is selected, the SelectedDates property will get just one date. If a week or a month is selected, the SelectedDate
property will get the first date from that collection.
See Also
Tasks
How to: Respond to Date Selection in a Calendar Web Server Control
Concepts
Calendar Web Server Control Overview
ASP.NET

How to: Select Dates Programmatically in a Calendar Web


Server Control
You can set date selections in your own code, either a single date or a range of dates. In contrast to user selection in the control
on a page, you can select multiple non-sequential dates in code.
Note
Setting a date programmatically does not raise the SelectionChanged event.

To select a single date


Set the control's SelectedDate property to an expression of type DateTime.
VB
Calendar1.SelectedDate = Date.Today

C#
Calendar1.SelectedDate = DateTime.Today;

Note
If you set the SelectedDate, all the dates in SelectedDates are effectively cleared.

To select a range of dates


Call the Add method of the control's SelectedDates collection. You can add dates in any order, because the collection
will order them for you. The collection also enforces uniqueness and will therefore ignore a date you add if the date is
already in the collection.
The following example sets the selection to every Wednesday in the month of February, 2000.
VB
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click

With Calendar1.SelectedDates
.Clear()
.Add(New Date(2000, 2, 2))
.Add(New Date(2000, 2, 9))
.Add(New Date(2000, 2, 16))
.Add(New Date(2000, 2, 23))
End With
End Sub

C#
public void Button1_Click (object sender, System.EventArgs e)
{
SelectedDatesCollection theDates = Calendar1.SelectedDates;
theDates.Clear();
theDates.Add(new DateTime(2000,2,2));
theDates.Add(new DateTime(2000,2,9));
theDates.Add(new DateTime(2000,2,16));
theDates.Add(new DateTime(2000,2,23));
}

The following example selects a sequence of seven dates.


VB
Dim today As Date = Date.Today
Dim i As Integer

With Calendar1.SelectedDates
.Clear()
For i = 0 To 6
.Add(today.AddDays(i))
Next
End With

C#
DateTime aDate = DateTime.Today;
SelectedDatesCollection theDates = Calendar1.SelectedDates;
theDates.Clear();
for (int i = 0;i <= 6;i++)
{
theDates.Add(aDate.AddDays(i));
}

To clear a date selection


Call the Clear method of the control's SelectedDates collection, as in the following example:
VB
Calendar1.SelectedDates.Clear()

C#
Calendar1.SelectedDates.Clear();

See Also
Concepts
Calendar Web Server Control Overview
ASP.NET

How to: Set Today's Date Programmatically in a Calendar Web


Server Control
By default, the value of "today" in the Calendar control is set to match the date of the server on which the Web Forms page
runs. However, you might need to adjust the date to accommodate users who are viewing the page from a different time zone.
To set today's date programmatically
Set the Calendar control's TodaysDate property to a DateTime value.
The following example sets TodaysDate to tomorrow and then sets the SelectedDate to TodaysDate. In the browser,
the date for tomorrow will be highlighted.
VB
Dim tomorrow As Date = Date.Today.AddDays(1)
Calendar1.TodaysDate = tomorrow
Calendar1.SelectedDate = Calendar1.TodaysDate

C#
DateTime tomorrow = DateTime.Today.AddDays(1);
Calendar1.TodaysDate = tomorrow;
Calendar1.SelectedDate = Calendar1.TodaysDate;

The following example shows how you can fill a DropDownList control with a selection of dates and then set the value of
today's date in the Calendar control according to the user's selection from the list.
VB
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
Dim today As DateTime = System.DateTime.Today
Dim yesterday As DateTime = today.AddDays(-1)
Dim tomorrow As DateTime = today.AddDays(1)
DropDownList1.items.Add(String.Format("{0:dd MMM yyyy}", _
today))
DropDownList1.items.Add(String.Format("{0:dd MMM yyyy}", _
yesterday))
DropDownList1.items.Add(String.Format("{0:dd MMM yyyy}", _
tomorrow))
End If
End Sub

Protected Sub DropDownList1_SelectedIndexChanged(ByVal sender _


As Object, ByVal e As System.EventArgs) _
Handles DropDownList1.SelectedIndexChanged
Calendar1.TodaysDate = _
Date.Parse(DropDownList1.SelectedItem.Text)
End Sub

C#
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
DateTime today = System.DateTime.Today;
DateTime yesterday = today.AddDays(-1);
DateTime tomorrow = today.AddDays(1);
DropDownList1.Items.Add(String.Format("{0:dd MMM yyyy}",
today));
DropDownList1.Items.Add(String.Format("{0:dd MMM yyyy}",
yesterday));
DropDownList1.Items.Add(String.Format("{0:dd MMM yyyy}",
tomorrow));
}
}
protected void DropDownList1_SelectedIndexChanged(object sender,
EventArgs e)
{
Calendar1.TodaysDate =
DateTime.Parse(DropDownList1.SelectedItem.Text);
}

See Also
Concepts
Calendar Web Server Control Overview
ASP.NET

How to: Display Selected Dates from a Database in the


Calendar Control
The Calendar control does not directly support data binding — that is, you do not bind the calendar as a whole to a data
source. Instead, you write code to get the data you need, and then in the DayRender event, you can compare the currently
rendered date against the data you have read from a data source.
To display database data in the Calendar control
1. Use ADO.NET types to connect to a database and query for the dates to display.
2. In the Calendar control's DayRender event, compare the date currently being rendered against the data you have
retrieved from the database. If there is a match, customize the day display.
Example
The following example reads holiday information from a database into an ADO.NET dataset. The selection gets dates for the
current month, defined as the range based on the Calendar control's VisibleDate property, which returns the first date of the
current month. Each time the user navigates to a new month, the code reads the holidays for that month. In the DayRender
event, code compares the date currently being rendered against the dates returned from the database. If a date matches, the
day is marked with a special color.
VB
Protected dsHolidays As DataSet

Protected Sub Page_Load(ByVal sender As Object, _


ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
Calendar1.VisibleDate = DateTime.Today
FillHolidayDataset()
End If
End Sub

Protected Sub FillHolidayDataset()


Dim firstDate As New DateTime(Calendar1.VisibleDate.Year, _
Calendar1.VisibleDate.Month, 1)
Dim lastDate As DateTime = GetFirstDayOfNextMonth()
dsHolidays = GetCurrentMonthData(firstDate, lastDate)
End Sub
Protected Function GetFirstDayOfNextMonth() As DateTime
Dim monthNumber, yearNumber As Integer
If Calendar1.VisibleDate.Month = 12 Then
monthNumber = 1
yearNumber = Calendar1.VisibleDate.Year + 1
Else
monthNumber = Calendar1.VisibleDate.Month + 1
yearNumber = Calendar1.VisibleDate.Year
End If
Dim lastDate As New DateTime(yearNumber, monthNumber, 1)
Return lastDate
End Function
Protected Sub Calendar1_VisibleMonthChanged(ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.MonthChangedEventArgs) _
Handles Calendar1.VisibleMonthChanged
FillHolidayDataset()
End Sub

Function GetCurrentMonthData(ByVal firstDate As DateTime, _ ByVal lastDate As DateTi


me) As DataSet
Dim dsMonth As New DataSet
Dim cs As ConnectionStringSettings
cs = ConfigurationManager.ConnectionStrings("ConnectionString1")
Dim connString As String = cs.ConnectionString
Dim dbConnection As New SqlConnection(connString)
Dim query As String
query = "SELECT HolidayDate FROM Holidays " & _
" WHERE HolidayDate >= @firstDate AND HolidayDate < @lastDate"
Dim dbCommand As New SqlCommand(query, dbConnection)
dbCommand.Parameters.Add(New SqlParameter("@firstDate", firstDate))
dbCommand.Parameters.Add(New SqlParameter("@lastDate", lastDate))
Dim sqlDataAdapter As New SqlDataAdapter(dbCommand)
Try
sqlDataAdapter.Fill(dsMonth)
Catch
End Try
Return dsMonth
End Function

Protected Sub Calendar1_DayRender(ByVal sender As Object, _


ByVal e As System.Web.UI.WebControls.DayRenderEventArgs) _
Handles Calendar1.DayRender
Dim nextDate As DateTime
If Not dsHolidays Is Nothing Then
For Each dr As DataRow In dsHolidays.Tables(0).Rows
nextDate = CType(dr("HolidayDate"), DateTime)
If nextDate = e.Day.Date Then
e.Cell.BackColor = System.Drawing.Color.Pink
End If
Next
End If
End Sub

C#
protected DataSet dsHolidays;

protected void Page_Load(object sender, EventArgs e)


{
if(!IsPostBack)
{
Calendar1.VisibleDate = DateTime.Today;
FillHolidayDataset();
}
}

protected void FillHolidayDataset()


{
DateTime firstDate = new DateTime(Calendar1.VisibleDate.Year,
Calendar1.VisibleDate.Month, 1);
DateTime lastDate = GetFirstDayOfNextMonth();
dsHolidays = GetCurrentMonthData(firstDate, lastDate);
}

protected DateTime GetFirstDayOfNextMonth()


{
int monthNumber, yearNumber;
if(Calendar1.VisibleDate.Month == 12)
{
monthNumber = 1;
yearNumber = Calendar1.VisibleDate.Year + 1;
}
else
{
monthNumber = Calendar1.VisibleDate.Month + 1;
yearNumber = Calendar1.VisibleDate.Year;
}
DateTime lastDate = new DateTime(yearNumber, monthNumber, 1);
return lastDate;
}
protected DataSet GetCurrentMonthData(DateTime firstDate,
DateTime lastDate)
{
DataSet dsMonth = new DataSet();
ConnectionStringSettings cs;
cs = ConfigurationManager.ConnectionStrings["ConnectionString1"];
String connString = cs.ConnectionString;
SqlConnection dbConnection = new SqlConnection(connString);
String query;
query = "SELECT HolidayDate FROM Holidays " + _
" WHERE HolidayDate >= @firstDate AND HolidayDate < @lastDate";
SqlCommand dbCommand = new SqlCommand(query, dbConnection);
dbCommand.Parameters.Add(new SqlParameter("@firstDate",
firstDate));
dbCommand.Parameters.Add(new SqlParameter("@lastDate", lastDate));
SqlDataAdapter sqlDataAdapter = new SqlDataAdapter(dbCommand);
try
{
sqlDataAdapter.Fill(dsMonth);
}
catch {}
return dsMonth;
}
protected void Calendar1_DayRender(object sender, DayRenderEventArgs e)
{
DateTime nextDate;
if(dsHolidays != null)
{
foreach(DataRow dr in dsHolidays.Tables[0].Rows)
{
nextDate = (DateTime) dr["HolidayDate"];
if(nextDate == e.Day.Date)
{
e.Cell.BackColor = System.Drawing.Color.Pink;
}
}
}
}
protected void Calendar1_VisibleMonthChanged(object sender,
MonthChangedEventArgs e)
{
FillHolidayDataset();
}

This example builds a query based on the dates in the currently displayed month. The VisibleDate property returns the first
date of the current month. (The VisibleDate property is not set until the user has navigated in the calendar, so the first time
the page is displayed, the code sets the VisibleDate property manually.) A helper function in the code calculates the first day
of the next month based on the VisibleDate property, and can therefore be used to build a date range within the current
month.
Compiling the Code
The code assumes that you are using a SQL Server database containing the table Holidays. The table has the column
HolidayDate. The connection string required to connect to the database is stored in the Web.config file under the name
ConnectionString1.
The code assumes that you have imported the namespaces System.Data and System.Data.SqlClient so that references to
DataSet, SqlConnection, and other objects can be used without being fully qualified.
Robust Programming
When querying the database, you should always enclose the execution of the query (in this example, when calling the data
adapter's Fill method) in a try-catch block.
See Also
Concepts
Calendar Web Server Control Overview
Visual Web Developer

CheckBox and CheckBoxList Web Server Controls (Visual


Studio)
The CheckBox and CheckBoxList Web server controls provide a way for users to switch between either/or (such as true/false,
yes/no, or on/off) options.
Because there are two different controls, and because they function somewhat differently, it is important to understand their
different purposes. The topics in this section provide information on what the CheckBox and CheckBoxList are, how they are
different, and how to work with each type of control.
In This Section
CheckBox and CheckBoxList Web Server Controls Overview
How to: Add CheckBox Web Server Controls to a Web Forms Page (Visual Studio)
How to: Add CheckBoxList Web Server Controls to a Web Forms Page (Visual Studio)
How to: Set Layout in a CheckBoxList Web Server Control
How to: Get and Set a CheckBox Web Server Control Value Programmatically
How to: Respond to User Selection in a CheckBox Web Server Control
See Also
Tasks
How to: Add Items in List Web Server Controls (Visual Studio)
How to: Populate List Web Server Controls from a Data Source (Visual Studio)
How to: Set the Selection in List Web Server Controls (Visual Studio)
Other Resources
Individual Web and HTML Controls
ASP.NET

CheckBox and CheckBoxList Web Server Controls Overview


You can use two types of Web server controls to add check boxes to a Web Forms page: individual CheckBox controls or a
CheckBoxList control. Both controls provide a way for users to input Boolean data: true or false, yes or no.
Note
You can also use the HtmlInputCheckBox control to add check boxes to a Web Forms page. For more information, see
HtmlInputCheckBox Server Control Declarative Syntax.

CheckBox Control versus CheckBoxList Control


You add individual CheckBox controls to a page and work with them singly. Alternatively, the CheckBoxList control is a
single control that acts as a parent control for a collection of check-box list items. It derives from a base ListControl class, and
therefore works much like the ListBox, DropDownList, RadioButtonList, and BulletedList Web server controls. For that reason,
many of the procedures for working with the CheckBoxList control are the same as the procedures for the other list Web
server controls.
Each type of control has advantages. By using individual CheckBox controls, you get more control over the layout of the check
boxes on the page than by using the CheckBoxList control. For example, you can include text (that is, non-check-box text)
between each check box. You can also control the font and color of individual check boxes.
The CheckBoxList control is a better choice if you want to create a series of check boxes from data in a database. (You can still
bind an individual CheckBox control to data.)
CheckBox Events
Events work differently between individual CheckBox controls and the CheckBoxList control.
Individual CheckBox Controls
Individual CheckBox controls raise the CheckedChanged event when users click the control. By default, this event does not
cause the page to be posted to the server, but you can have the control force an immediate post by setting the AutoPostBack
property to true. For details about responding to this event directly, see
How to: Respond to User Selection in a CheckBox Web Server Control.
Note
The ability of a CheckBox control to post to the server when it is checked requires that the browser support ECMAScript (Jav
aScript) and that scripting be enabled on the user's browser.

Whether a CheckBox control posts to the server or not, you might not need to create an event handler for the
CheckedChanged event. You can test which check box is selected in the handler. Typically, you create an event handler for the
CheckedChanged event only if you need to know that the check box was changed, not just to read the value of a check box.
CheckBox Control HTML Attributes
When the CheckBox control renders to the browser, it does so in two parts: an input element representing the check box, and
a separate label element representing the caption for the check box. The combination of the two elements is in turn wrapped
in a span element.
When you apply style or attribute settings to a CheckBox control, the settings are applied to the outer span element. For
example, if you set the control's BackColor property, the setting is applied to the span element, and therefore it affects both the
inner input and label attributes.
At times, you might want to be able to apply separate settings to the check box and to the label. The CheckBox control
supports two properties that you can set at run time: the InputAttributes property and the LabelAttributes property. Each
property allows you to add HTML attributes to the input and label elements, respectively. The attributes that you set are
passed through as-is to the browser. For example, the following code example shows how to set attributes for the input
element so that only the check box, not the label, changes color when users pass the mouse pointer over it.
[Visual Basic]

CheckBox1.InputAttributes.Add("onmouseover", _
"this.style.backgroundColor = 'red'")
CheckBox1.InputAttributes.Add("onmouseout", _
"this.style.backgroundColor = 'white'")
CheckBox1.InputAttributes.Add("onmouseover",
"this.style.backgroundColor = 'red'");
CheckBox1.InputAttributes.Add("onmouseout",
"this.style.backgroundColor = 'white'");

CheckBoxList Control
In contrast, the CheckBoxList control raises a SelectedIndexChanged event when users select any check box in the list. By
default, the event does not cause the form to be posted to the server, although you can specify this option by setting the
AutoPostBack property to true.
As with individual CheckBox controls, it is more common to test the state of the CheckBoxList control after the form has
been posted some other way.
Binding Data to the Control
As with any Web server control, you can bind an individual CheckBox control to a data source, and you can bind any property
of the CheckBox control to any field of the data source. For example, it is typical to set the control's Checked property from
information in a database.
You can also bind a CheckBoxList control to a data source. In that case, the check boxes each represent a different record in
the data source.
See Also
Tasks
How to: Add CheckBox Web Server Controls to a Web Forms Page
How to: Add CheckBoxList Web Server Controls to a Web Forms Page
How to: Add Items in List Web Server Controls
How to: Determine the Selection in List Web Server Controls
How to: Populate List Web Server Controls from a Data Source
How to: Respond to Changes in List Web Server Controls
How to: Set the Selection in List Web Server Controls
Visual Web Developer

How to: Add CheckBox Web Server Controls to a Web Forms


Page (Visual Studio)
You can add a check box to a Web Forms page in two ways:
By adding an individual CheckBox Web server control.
By adding a CheckBoxList control and then adding individual list items to the control.
Note
This topic addresses how to add individual CheckBox controls to the page. For information about adding items to a Ch
eckBoxList control, see How to: Add CheckBoxList Web Server Controls to a Web Forms Page (Visual Studio).

To add a CheckBox Web server control to a Web Forms page


1. From the Standard tab of the Toolbox, drag a CheckBox control onto the page.
2. In the Properties window, specify a caption by setting the Text property.
3. Optionally, change the orientation of the caption by setting the TextAlign property.
See Also
Tasks
How to: Add CheckBoxList Web Server Controls to a Web Forms Page (Visual Studio)
Reference
CheckBox and CheckBoxList Web Server Controls Overview
Visual Web Developer

How to: Add CheckBoxList Web Server Controls to a Web


Forms Page (Visual Studio)
When you use a CheckBoxList control, you add a single control to the page. Adding items to the control is a separate process
that depends on whether you will display a static list in the control or display a list that is generated dynamically at run time.
For details, see How to: Add Items in List Web Server Controls (Visual Studio).
To add a CheckBoxList Web server control to a Web Forms page
1. From the Standard tab of the Toolbox, drag a CheckBoxList control onto the page.
2. Optionally, in the Appearance category of the Properties window, change the orientation of the check box label by
setting the TextAlign property.
3. Optionally, change the layout of the control to display multiple columns. For details, see
How to: Set Layout in a CheckBoxList Web Server Control.
4. Create items for the control in one of the following ways:
By creating each item individually. For details, see How to: Add Items in List Web Server Controls (Visual Studio).
By binding data to the control. For details, see
How to: Populate List Web Server Controls from a Data Source (Visual Studio).
See Also
Reference
CheckBox and CheckBoxList Web Server Controls Overview
ASP.NET

How to: Set Layout in a CheckBoxList Web Server Control


By default, the CheckBoxList control displays a single column of check boxes. However, you can specify any number of
columns, and within the columns, you can specify how the items are ordered: vertically (the default) or horizontally. Vertical
layout in three columns results in a layout such as the following:

A D G
B E H
C F

Horizontal layout for the same items results in the following layout:

A B C
D E F
G H

To specify column count and ordering


1. Set the CheckBoxList control's RepeatColumns property to the number of columns you want.
2. Set the RepeatDirection to Vertical or Horizontal. If you are setting the property in code, use the RepeatDirection
enumeration, as shown in the following example:
VB
CheckBoxList1.RepeatDirection = RepeatDirection.Horizontal

C#
CheckBoxList1.RepeatDirection = RepeatDirection.Horizontal;

See Also
Reference
CheckBox and CheckBoxList Web Server Controls Overview
ASP.NET

How to: Get and Set a CheckBox Web Server Control Value
Programmatically
You can programmatically read or set the value of a CheckBox Web server control.
Note
If you are working with a CheckBoxList control, the procedure for getting and setting the value of a check box is different. For
details, see How to: Determine the Selection in List Web Server Controls.

To get or set CheckBox Web server control selection


Get or set the CheckBox control's Checked property. A value of true means the check box is selected.
Note
Testing the value of a check box does not tell you if the user changed the value of the control, only if it is selected.

In the following example, if the check box chkCanWeSendEmail is not selected, the check box chkSendInHTMLFormat is
automatically cleared as well.
VB
If chkCanWeSendEmail.Checked = False Then
chkSendInHTMLFormat.Checked = False
End If

C#
if(chkCanWeSendEmail.Checked == false){
chkSendInHTMLFormat.Checked = false;
}

See Also
Tasks
How to: Respond to User Selection in a CheckBox Web Server Control
Reference
CheckBox and CheckBoxList Web Server Controls Overview
ASP.NET

How to: Respond to User Selection in a CheckBox Web Server


Control
When the user selects a CheckBox control, the control raises an event that you can respond to.
Note
The CheckBoxList control raises events differently than individual CheckBox controls do. For details, see
How to: Determine the Selection in List Web Server Controls.

You might not need to respond directly to the check event of a CheckBox control at all. You respond to the event only if it is
important to know when the user has changed the check box selection. If you are interested only in the state of the check box
when selected, and not whether it has changed, you can simply test the check box after the form has been posted to the server.
For details, see How to: Get and Set a CheckBox Web Server Control Value Programmatically.
To respond to a selection in a CheckBox control
Create an event handler for the control's CheckedChanged event.
By default, the CheckedChanged event does not immediately cause the page to be posted to the server. Instead, the
event is raised in server code the next time the form is posted. To have the CheckedChanged event cause an immediate
posting, set the CheckBox control's AutoPostBack property to true.
Note
The ability of a CheckBox control to post to the server when it is checked requires that the browser support ECMAScri
pt (JavaScript) and that scripting be enabled on the user's browser.

The following example displays "True" or "False" in a Label Web server control to reflect the latest change in a
CheckBox control.
VB
Protected Sub CheckBox1_CheckedChanged(ByVal sender As _
System.Object, ByVal e As System.EventArgs) Handles _
CheckBox1.CheckedChanged
Label1.Text = "CheckBox1 selection is: " & _
CheckBox1.Checked.ToString()
End Sub

C#
protected void CheckBox1_CheckedChanged(object sender, EventArgs e)
{
Label1.Text = "CheckBox1 selection is: " + CheckBox1.Checked.ToString();
}

See Also
Reference
CheckBox and CheckBoxList Web Server Controls Overview
Visual Web Developer

DropDownList Web Server Control (Visual Studio)


The DropDownList Web server control enables users to select from a single-selection drop-down list box. The DropDownList
control is similar to the ListBox Web server control. It differs in that it shows only the selected item in a box, along with a drop-
down button. When users click the button, a list of items is displayed.
The topics in this section provide information about how to work with the DropDownList control. Because the control is
similar in many ways to the ListBox control, some of the links lead to topics for that control.
In This Section
DropDownList Web Server Control Overview
How to: Add DropDownList Web Server Controls to a Web Forms Page (Visual Studio)
See Also
Tasks
How to: Add Items in List Web Server Controls (Visual Studio)
How to: Populate List Web Server Controls from a Data Source (Visual Studio)
How to: Determine the Selection in List Web Server Controls
How to: Set the Selection in List Web Server Controls (Visual Studio)
Other Resources
Individual Web and HTML Controls
ASP.NET

DropDownList Web Server Control Overview


The DropDownList Web server control allows users to select an item from a predefined list. It differs from the ListBox Web
server control in that the list of items remains hidden until users click the drop-down button. In addition, the DropDownList
control differs from the ListBox control in that it does not support multi-selection mode.
Modifying the Appearance of the DropDownList Control
You can control the look of the DropDownList control by setting its height and width in pixels. Some browsers do not support
setting the height and width in pixels and will use the row-count setting instead.
You cannot specify the number of items that are displayed in the list when users click the drop-down button. The length of the
displayed list is determined by the browser.
As with other Web server controls, you can use style objects to specify the appearance of the DropDownList control. For
details, see ASP.NET Web Server Controls and CSS Styles.
List Items
The DropDownList control is actually a container for the list items, which are of type ListItem. Each ListItem object is a
separate object with its own properties. These properties are described in the following table.
Propert Description
y
Text Specifies the text that is displayed in the list.

Value Contains the value that is associated with an item. Setting this property allows you to associate a value with a specific
item without displaying it. For example, you can set the Text property to the name of a U.S. state and the Value prop
erty to its postal abbreviation.

Selected Indicates whether the item is selected by means of a Boolean.

To work with list items programmatically, use the Items collection of the DropDownList control. The Items collection is a
standard collection, and you can add item objects to it, delete items, clear the collection, and so on.
The currently selected item is available in the DropDownList control's SelectedItem property.
Binding Data to the Control
You can use a DropDownList Web server control to list options that are made available to the page using a data source
control. Each item in the DropDownList control corresponds to an item — typically a row — in the data source.
The control displays one field from the source. Optionally, you can bind the control to a second field to set the value of an item,
which does not display.
As with other Web server controls, you can bind any control properties, such as the color or size of the control, to data. For
details, see How to: Populate List Web Server Controls from a Data Source.
DropDownList Events
The DropDownList control raises an event — the SelectedIndexChanged event — when users select an item. By default, this
event does not cause the page to be posted to the server, but you can cause the control to force an immediate post by setting
the AutoPostBack property to true.
Note
The ability of a DropDownList control to post to the server when it is checked requires that the browser support ECMAScrip
t (JScript, or JavaScript) and that scripting be enabled on the user's browser.

See Also
Tasks
How to: Add Items in List Web Server Controls
How to: Determine the Selection in List Web Server Controls
How to: Populate List Web Server Controls from a Data Source
How to: Respond to Changes in List Web Server Controls
How to: Set the Selection in List Web Server Controls
Visual Web Developer

How to: Add DropDownList Web Server Controls to a Web


Forms Page (Visual Studio)
The process of adding a DropDownList Web server control to a page consists primarily of setting options that specify how
items should be displayed and whether users can select multiple items.
To add a DropDownList Web server control to a Web Forms page
From the Standard tab of the Toolbox, drag a DropDownList control onto the page.
Adding items to the control is a separate process that depends on whether you will display a static list in the control or a
list that is generated dynamically at run time. For details, see
How to: Add Items in List Web Server Controls (Visual Studio).
See Also
Reference
DropDownList Web Server Control Overview
Visual Web Developer

FileUpload Web Server Control (Visual Studio)


The topics in this section describe the FileUpload control, which enables you to provide users with a way to send a file from
their computer to the server.
In This Section
FileUpload Web Server Control Overview
How to: Upload Files with the FileUpload Web Server Control
See Also
Other Resources
Individual Web and HTML Controls
ASP.NET

FileUpload Web Server Control Overview


The FileUpload control allows you to provide users with a way to send a file from their computer to the server. The control is
useful for allowing users to upload pictures, text files, or other files.
Prompting for Files to Upload
The FileUpload control displays a text box where users can type the name of a file that they want to upload to the server. The
control also displays a Browse button that displays a file-navigation dialog box. (The dialog box that is displayed depends on
the operating system of the user's computer.) For security reasons, you cannot pre-load the name of a file into the FileUpload
control.
Handling Uploaded Files
When users have selected a file to upload and submitted the page, the file is uploaded as part of the request. The file is cached
in its entirety in server memory. When the file has finished uploading, your page code runs.
You can access the uploaded file in the following ways:
As a byte array exposed in the FileUpload control’s FileBytes property.
As a stream exposed in the FileContent property.
As an object of type HttpPostedFile in the PostedFile property. The PostedFile object exposes properties, such as the
ContentType and ContentLength properties, which provide you with information about the uploaded file.
When your code runs, you can examine the characteristics of the file, such as its name, size, and MIME type, and you can then
save it. You can work with the file as a byte array or stream. Alternatively, both the FileUpload control and the
HttpPostedFile object support a SaveAs method that writes the file to disk.
There is no inherent limitation on where you can save uploaded files. However, to save the file, the ASP.NET process must have
permission to create files in the location that you specify. In addition, your application might be configured to require an
absolute path (not a relative path) for saving the file, which is a security measure. If the requireRootedSaveAsPath attribute
of the httpRuntime Element (ASP.NET Settings Schema) configuration element is set to true (which is the default), you must
provide an absolute path when saving the uploaded file.
Note
You can create an absolute path based on the root of your application by using the MapPath method of the HttpServerUtility
class and passing to the method the tilde (~) operator, which represents the application root folder. For more information, se
e ASP.NET Web Site Paths.

The maximum size file that can be uploaded depends on the value of the MaxRequestLength configuration setting. If users
attempt to upload a file that is larger than the maximum allowed, the upload fails.
Security and the FileUpload Control
Using the FileUpload control, users can upload potentially malicious files, including script files and executable files. You
cannot limit in advance the files that a user can upload. If you want to limit the types of files that a user can upload, you must
examine the file characteristics (for example, the file name extension and the value of the file's ContentType property) after
the file has been uploaded.
Note
Before the page is submitted, you can use client script to examine the file name that a user has typed in the text box. However
, while performing a client-side check of the file name can be useful, it does not guarantee that users cannot upload an unsaf
e file type, such as an executable file.

See Also
Tasks
How to: Upload Files with the FileUpload Web Server Control
ASP.NET

How to: Upload Files with the FileUpload Web Server Control
The FileUpload Web server control allows you to provide users with a way to send a file from their computer to the server. The
file to be uploaded is submitted to the server as part of the browser request during postback. After the file has completed
uploading, you can manage the file in your code.
Note
The maximum size file that can be uploaded depends on the value of the MaxRequestLength configuration setting. If users at
tempt to upload a file that is longer than the maximum, the upload fails.

To upload a file with the FileUpload Web server control


1. Add a FileUpload control to the page.
Note
For security reasons, you cannot pre-load the name of a file into the FileUpload control.

2. In a handler for an event, such as the page's Load event, do the following:
a. Check that the FileUpload control has an uploaded file by testing its HasFile property.
b. Check the file name or MIME type of the file to make sure that users have uploaded a file that you want to accept.
To check the MIME type, get the HttpPostedFile object exposed as the FileUpload control's PostedFile property.
You can then get the MIME type by checking the posted file's ContentType property.
Security Note
MIME types for uploaded files can be spoofed under some circumstances, so checking the file's MIME type alone i
s not a reliable security check.

c. Save the file to a location you specify. You can call the SaveAs method of the HttpPostedFile object. Alternatively,
you can manage the uploaded file as a byte array or stream using the HttpPostedFile object's InputStream
property.
The following example shows how to work with an uploaded file. The code checks the file name extension of the
uploaded file against a hard-coded list of allowed file name extensions and rejects all other types of files. The file is then
written to an UploadedImages folder in the current Web site. The uploaded file is saved with the same file name that it
had on the client computer. The FileName property of the FileUpload control is used because the FileName property of
the HttpPostedFile object returns the complete path of the file on the client computer.
Security Note
Do not display the path and name of the saved file to users; doing so can reveal information that might be useful to ma
licious users.

VB
Protected Sub Page_Load(ByVal sender As Object,
ByVal e As System.EventArgs) Handles Me.Load
If IsPostBack Then
Dim path As String = Server.MapPath("~/UploadedImages/")
Dim fileOK As Boolean = False
If FileUpload1.HasFile Then
Dim fileExtension As String
fileExtension = System.IO.Path. _
GetExtension(FileUpload1.FileName).ToLower()
Dim allowedExtensions As String() = _
{".jpg", ".jpeg", ".png", ".gif"}
For i As Integer = 0 To allowedExtensions.Length - 1
If fileExtension = allowedExtensions(i) Then
fileOK = True
End If
Next
If fileOK Then
Try
FileUpload1.PostedFile.SaveAs(path & _
FileUpload1.FileName)
Label1.Text = "File uploaded!"
Catch ex As Exception
Label1.Text = "File could not be uploaded."
End Try
Else
Label1.Text = "Cannot accept files of this type."
End If
End If
End If
End Sub

C#
protected void Page_Load(object sender, EventArgs e)
{
if(IsPostBack)
{
Boolean fileOK = false;
String path = Server.MapPath("~/UploadedImages/");
if (FileUpload1.HasFile)
{
String fileExtension =
System.IO.Path.GetExtension(FileUpload1.FileName).ToLower();
String[] allowedExtensions =
{".gif", ".png", ".jpeg", ".jpg"};
for (int i = 0; i < allowedExtensions.Length; i++)
{
if (fileExtension == allowedExtensions[i])
{
fileOK = true;
}
}
}

if (fileOK)
{
try
{
FileUpload1.PostedFile.SaveAs(path
+ FileUpload1.FileName);
Label1.Text = "File uploaded!";
}
catch (Exception ex)
{
Label1.Text = "File could not be uploaded.";
}
}
else
{
Label1.Text = "Cannot accept files of this type.";
}
}
}

See Also
Concepts
FileUpload Web Server Control Overview
Visual Web Developer

HiddenField Web Server Control (Visual Studio)


The topics in this section describe the HiddenField control, which enables you to keep information in an ASP.NET Web page
without displaying it to users.
In This Section
HiddenField Web Server Control Overview
See Also
Other Resources
Individual Web and HTML Controls
ASP.NET

HiddenField Web Server Control Overview


The HiddenField control provides you with a way to store information in the page without displaying it. For example, you might
store a user-preference setting in a HiddenField control. To put information into a HiddenField control, you set its Value
property to the value you want to store between postbacks.
As with any other Web server control, the information in a HiddenField control is available during postback. The information
is not persisted outside the page.
HiddenField Control and Security
The information in a HiddenField control is not displayed when the browser renders the page, but users can see the contents
of the control by viewing the page's source. Therefore, do not store sensitive information in a HiddenField control, such as
user IDs, passwords, or credit card information.
Detecting Changed Data
Users can change the value of a HiddenField control before the page is posted back to the server, potentially compromising
the information. To help you detect this type of change, the HiddenField control raises a ValueChanged event if the value of
the control changes between postbacks. If the values of the HiddenField controls contain sensitive information or are
necessary for your application to function properly, you should handle this event for all of the HiddenField controls on the
page.
See Also
Concepts
ASP.NET State Management Overview
Visual Web Developer

HyperLink Web Server Control (Visual Studio)


The HyperLink Web server control provides a means of creating and manipulating links on a Web page from server code. The
following topics provide information that you will find useful in learning to work with the HyperLink control.
In This Section
HyperLink Web Server Control Overview
How to: Add HyperLink Web Server Controls to a Web Forms Page (Visual Studio)
See Also
Other Resources
Individual Web and HTML Controls
ASP.NET

HyperLink Web Server Control Overview


The HyperLink Web server control creates links on a Web page that allow users to move from page to page in your application.
Advantages of Using the HyperLink Control
The primary advantage of using a HyperLink control is that you can set link properties in server code. For example, you can
dynamically change the link text or target page based on conditions in your page.
Security Note
The URLs associated with a hyperlink can be tampered with by a malicious user. For more information, see
How to: Protect Against Script Exploits in a Web Application by Applying HTML Encoding to Strings.

Another advantage of using the HyperLink control is that you can use data binding to specify the target URL for the link (and
parameters to be passed with the link, if necessary). A typical example is to create HyperLink controls based on a list of
products; the target URL points to a page where the user can read more detail about the product.
Tip
If you need to create data-bound HyperLink controls, a convenient way to do so is to add them as children of these controls:
Repeater, DataList, GridView, FormView, or DetailsView.

The HyperLink control can display clickable text or an image.


Unlike most Web server controls, the HyperLink control does not raise an event in server code when users click it. Instead, the
control simply performs navigation.
See Also
Tasks
How to: Add HyperLink Web Server Controls to a Web Forms Page
Visual Web Developer

How to: Add HyperLink Web Server Controls to a Web Forms


Page (Visual Studio)
You can add a hyperlink to your Web Forms page by placing a HyperLink Web server control on the page and associating it
with a URL. You can specify that HyperLink controls render as either text or as graphics.
To add a HyperLink Web server control to a Web Forms page
1. From the Standard tab of the Toolbox, drag a HyperLink control onto the page.
2. In the Appearance category of the Properties window, specify the format of the link on the page by doing one of the
following:
To create a text link, set the control's Text property. You can include HTML formatting in the property. For example,
you can format an individual word in the text as bold by placing a <B> tag around it in the Text property.
To create a graphical link, set the control's ImageUrl property to the URL of a .gif, .jpg, or other Web graphic file.
Note
If you set both the ImageUrl and Text properties, the ImageUrl property takes precedence.

3. In the Navigation category of the Properties window, set the NavigateUrl property to the URL of the page to which you
want to link.
Security Note
The URL that is associated with a hyperlink points to an external resource. If you point to a resource that you do not ow
n, be sure it is safe for your users to work with. For more information, see Script Exploits Overview.

4. Optionally, in the Navigation category of the Properties window, specify the target by setting the ID of a target
window or frame in which to display the linked page. You can either specify a window by name or use predefined target
values, such as _top, _parent, and so on.
Note
You can change the appearance of the link text — for example, whether it is underlined — by using styles. For details, s
ee ASP.NET Web Server Controls and CSS Styles.

The following example shows how you can set the properties of a HyperLink control at run time. The method handles a
Button control's Click event and sets the control's link text and target page.
VB
Protected Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs)
Hyperlink1.Text = "Home"
Hyperlink1.NavigateUrl = "http://www.microsoft.com/net/"
End Sub

C#
protected void Button1_Click (object sender, System.EventArgs e)
{
this.HyperLink1.Text = "Home";
this.HyperLink1.NavigateUrl = "http://www.microsoft.com/net/";
}
See Also
Reference
HyperLink Web Server Control Overview
Visual Web Developer

Image Web Server Control (Visual Studio)


The Image Web server control allows you to display images on an ASP.NET Web page and manage the images in your own
code. The following topics provide information that you will find useful in learning to work with the Image control.
In This Section
Image Web Server Control Overview
How to: Add Image Web Server Controls to a Web Forms Page (Visual Studio)
See Also
Other Resources
Individual Web and HTML Controls
ASP.NET

Image Web Server Control Overview


The Image Web server control allows you to display images on an ASP.NET Web page and manage these images in your own
code.
Specifying Graphics Files
You can specify the graphics file for an Image control at design time or at run time programmatically. You can also bind the
control's ImageUrl property to a data source to display graphics based on database information.
Unlike most other Web server controls, the Image control does not support any events. For example, the Image control does
not respond to mouse clicks. Instead, you can create an interactive image by using the ImageMap or the ImageButton Web
server controls.
Specifying Text Elements
In addition to displaying a graphic, the Image control allows you to specify various types of text for the image, such as the
following:
ToolTip This is the text that is displayed in a ToolTip in some browsers.
AlternateText This is the text that is displayed if the graphics file cannot be found. If no ToolTip property is specified,
some browsers will use the AlternateText value as a ToolTip.
GenerateEmptyAlternateText If this property is set to true, the alt attribute of the rendered image element will be set to
an empty string.
See Also
Tasks
How to: Add Image Web Server Controls to a Web Forms Page
Reference
Button Web Server Controls Overview
Visual Web Developer

How to: Add Image Web Server Controls to a Web Forms Page
(Visual Studio)
The Image Web server control allows you to display images on an ASP.NET Web page and manage these images in your own
code.
To add an Image Web server control to a Web Forms page
1. From the Standard tab of the Toolbox, drag an Image control onto the page.
2. In the Appearance category of the Properties window, set the control's ImageUrl property to the URL of a .gif, .jpg, or
other Web graphic file.
Security Note
The URL that is associated with a Image control points to an external resource. If you point to a resource that you do n
ot own, be sure it is safe for your users to work with. For more information,
How to: Protect Against Script Exploits in a Web Application by Applying HTML Encoding to Strings.

Note
Click the button in the property box to display the Select Image dialog box, where you can select an image file.

3. Optionally, set the following Image control properties.


Property Description
Height and Reserve space for the graphic on the page. When the page is rendered, the image will be sized to fit the spa
Width ce you reserve.

ImageAlign Aligns the image with respect to the surrounding text, using values such as Top, Bottom, Left, Middle, an
d Right. In code, image alignment is set by using the ImageAlign enumeration.

AlternateText Displays text in place of the graphic if the graphic cannot be loaded. In some browsers, this text is also displ
ayed as a ToolTip.

See Also
Reference
Image Web Server Control Overview
Visual Web Developer

ImageMap Web Server Control (Visual Studio)


The topics in this section describe the ASP.NET ImageMap control. This control enables you to create an image that has
individual regions that users can click; these regions are called hot spots. Each of these hot spots can be a separate hyperlink or
postback event.
In This Section
ImageMap Web Server Control Overview
How to: Add ImageMap Web Server Controls to a Web Page (Visual Studio)
How to: Respond to User Clicks in ImageMap Web Server Controls
See Also
Other Resources
Individual Web and HTML Controls
ASP.NET

ImageMap Web Server Control Overview


The ASP.NET ImageMap control allows you to create an image that has individual regions that users can click, which are called
hot spots. Each of these hot spots can be a separate hyperlink or postback event.
ImageMap Elements
The ImageMap control consists primarily of two pieces. The first is an image, which can be a graphic in any standard Web
graphic format, such as a .gif, .jpg, or .png file.
The second element is a collection of hot-spot controls. Each hot-spot control is a different element. For each hot-spot control,
you define its shape—a circle, rectangle, or polygon—and the coordinates that specify the location and size of the hot spot. For
example, if you create a circle hot spot, you define the x and y coordinates of the circle's center and the circle's radius.
You can define as many or as few hot spots for the image as you require. You do not need to define hot spots to cover the
graphic entirely.
Note
You can define overlapping hot spots. Each hot spot has a z-index value, and if a user clicks an area that is defined by two or
more overlapping hot spots, the hot spot with the highest z-order is the hot spot that is selected.

Responding to User Clicks


You can specify what happens when a user clicks a hot spot on an ImageMap control. Each hot spots can be configured as a
hyperlink that goes to a URL that you provide for that hot spot. Alternatively, you can configure the control to perform a
postback when a user clicks a hot spot, providing a unique value for each hot spot. The postback raises the ImageMap
control's Click event. In the event handler, you can read the unique value that you assign to each hot spot.
See Also
Tasks
How to: Respond to User Clicks in ImageMap Web Server Controls
Visual Web Developer

How to: Add ImageMap Web Server Controls to a Web Page


(Visual Studio)
An ImageMap control creates a graphic with hotspots that users can click individually. Creating an ImageMap control consists
of creating the control, specifying the image, and then separately defining the hotspots.
To add an ImageMap control
1. From the Standard tab of the Toolbox, drag an ImageMap control onto the page.
2. In the Properties window, set the control's ImageUrl property to the URL of the graphic that you want to display.
Note
Click the button in the property box to display the Select Image dialog box.

3. Optionally, set the control's HotSpotMode property to specify whether clicking the hotspot results in navigation to
another page or in a postback.
Note
You can override the control-wide setting for each hotspot.

To define hotspots
1. In the Properties window, click the HotSpots property box to display the HotSpot Collection Editor dialog box.
2. Click the arrow button next to the Add button to select the type of hotspot that you want to create (CircleHotSpot,
RectangleHotSpot, PolygonHotSpot).
3. For each hotspot, use the properties grid to specify the coordinates for the hotspot, as listed in the following table.
Hotspot Type Coordinates
CircleHotSpot Radius

RectangleHotSpot Top

PolygonHotSpot Coordinates

4. If you want to override the control's HotSpotMode setting, set the HotSpotMode property for each hotspot to specify
whether clicking the hotspot results in navigation to another page or in a postback.
5. If a hotspot is set to navigate, specify its NavigateUrl property.
6. If a hotspot is set to perform a postback, set the PostBackValue for the hotspot to provide information about which
hotspot is clicked. You can read the value in the Click event handler.
7. When you have finished defining hotspots, click OK.
See Also
Tasks
How to: Respond to User Clicks in ImageMap Web Server Controls
Concepts
ImageMap Web Server Control Overview
ASP.NET

How to: Respond to User Clicks in ImageMap Web Server


Controls
You can configure an ImageMap control, or an individual region (hot spot) in it, so that when users click a specific hot spot, the
control either goes to another page or performs a postback. You can override the control's settings for each hot spot.
If the ImageMap control or an individual hot spot has been configured to go to a specific URL, you do not have an opportunity
to respond directly to the click. However, if the control or hot spot is configured to perform a postback, you can write a handler
for the event and determine which hot spot was clicked.
To respond to a user click in an ImageMap control
1. Add a Click event handler for the ImageMap control. The second argument of the handler must be of type
ImageMapEventArgs.
2. In the event handler, read the PostBackValue property of the ImageMapEventArgs object to determine which hot spot
was clicked.
Example
The following code example shows how to respond to a user click in an ImageMap control. The page contains an ImageMap
control with four rectangular hot spots. Each hot spot's PostBackValue property is set to a unique value. The code in the
handler checks for each value and displays an appropriate response.
VB
<%@ Page Language="VB" %>
<script runat="server">
Protected Sub ImageMap1_Click(ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.ImageMapEventArgs)
Dim region As String
Select Case e.PostBackValue
Case "NW"
region = "Northwest"
Case "NE"
region = "Northeast"
Case "SE"
region = "Southeast"
Case "SW"
region = "Southwest"
End Select
Label1.Text = "You clicked the " & region & " region."
End Sub
</script>

<html>
<body>
<form id="form1" runat="server">
<div>
<asp:Label runat="server" ID="Label1" />
<br />
<br />
<asp:ImageMap ID="ImageMap1" ImageUrl="~/Images/MapTest.PNG"
runat="server"
HotSpotMode="PostBack"
OnClick="ImageMap1_Click">
<asp:RectangleHotSpot Bottom="100" Right="100"
HotSpotMode="PostBack" PostBackValue="NW" />
<asp:RectangleHotSpot Bottom="100" Left="100" Right="200"
HotSpotMode="PostBack" PostBackValue="NE" />
<asp:RectangleHotSpot Bottom="200" Right="100" Top="100"
PostBackValue="SW" />
<asp:RectangleHotSpot Bottom="200" Left="100" Right="200"
Top="100" PostBackValue="SE" />
</asp:ImageMap>
</div>
</form>
</body>
</html>

C#
<% @ Page Language="C#" %>
<script runat="server">
protected void ImageMap1_Click(object sender, ImageMapEventArgs e)
{
String region = "";
switch(e.PostBackValue)
{
case "NW":
region = "Northwest";
break;
case "NE":
region = "Northeast";
break;
case "SE":
region = "Southeast";
break;
case "SW":
region = "Southwest";
break;
}
Label1.Text = "You clicked the " + region + " region.";
}
</script>

<html>
<body>
<form id="form1" runat="server">
<div>
<asp:Label runat="server" ID="Label1" />
<br />
<br />
<asp:ImageMap ID="ImageMap1" ImageUrl="~/Images/MapTest.PNG"
runat="server"
HotSpotMode="PostBack"
OnClick="ImageMap1_Click">
<asp:RectangleHotSpot Bottom="100" Right="100"
HotSpotMode="PostBack" PostBackValue="NW" />
<asp:RectangleHotSpot Bottom="100" Left="100" Right="200"
HotSpotMode="PostBack" PostBackValue="NE" />
<asp:RectangleHotSpot Bottom="200" Right="100" Top="100"
PostBackValue="SW" />
<asp:RectangleHotSpot Bottom="200" Left="100" Right="200"
Top="100" PostBackValue="SE" />
</asp:ImageMap>
</div>
</form>
</body>
</html>

See Also
Tasks
How to: Add ImageMap Web Server Controls to a Web Forms Page
Concepts
ImageMap Web Server Control Overview
Visual Web Developer

Label Web Server Control (Visual Studio)


The Label Web server control provides a way to display text under programmatic control in an ASP.NET Web page.
Note
If you want to display static text, you can present it using HTML; you do not need a Label control. Use a Label control only if
you need to change the contents or other characteristics of the text in server code.

The following topics provide information useful in learning the Label Web server control.
In This Section
Label Web Server Control Overview
How to: Add Label Web Server Controls to a Web Forms Page (Visual Studio)
How to: Use Label Web Server Controls as Captions
See Also
Other Resources
Individual Web and HTML Controls
ASP.NET

Label Web Server Control Overview


The Label Web server control provides you with a way to programmatically set text in an ASP.NET Web page. You typically use
the Label control when you want to change text in the page at run time, such as in response to a button click.
The Label control provides one way to display text in an ASP.NET Web page. Other options include the following:
HTML If you want to display static text, you can present it using HTML; you do not need a Label control. Use a Label
control only if you need to change the contents or other characteristics of the text in server code.
The Literal control Like the Label control, the Literal control allows you to programmatically set text to be displayed in
the page. However, the Literal control does not support style properties and does not support themes or skins.
You can set the text of the Label control at design time or at run time in a program. You can also bind the Label control's Text
property to a data source to display database information on a page.
Labels as Control Captions
You can use the Label control to act as an active caption in front of a TextBox control or other control. Users can then press an
access key to move to the control for which the Label control is the caption. For details, see
How to: Use Label Web Server Controls as Captions.
Using Labels in List Controls
The Label control is often used in list Web server controls (Repeater, DataList, GridView, DetailsView, and FormView controls)
to display read-only information from a database. The usual strategy is to add a Label control to a template for one of these
controls. You then bind the Label control to a data source. For details about templates, see
ASP.NET Web Server Controls Templates.
Security and the Label Control
You can set the Text property of the Label control to any string, including strings that contain markup. If the string contains
markup, the Label control interprets the markup. For example, if you set the Text property to <b>Test</b>, the Label control
will render the word Test in bold type.
To avoid security issues, such as the possibility of script injection, do not set the Text property to a string containing markup
that comes from an untrusted source. If you do not trust the source of the string that you are using for the Text property, you
should encode the string. For details, see
How to: Protect Against Script Exploits in a Web Application by Applying HTML Encoding to Strings.
See Also
Reference
Literal Web Server Control Overview
Visual Web Developer

How to: Add Label Web Server Controls to a Web Forms Page
(Visual Studio)
You can add Label Web server controls as self-standing controls on your ASP.NET Web page. You can also make Label
controls child controls of other controls, such as using them in Web server control templates. For details, see
ASP.NET Web Server Controls Templates.
Note
If you want to display static text, you can present it by using HTML — you do not need a Label control. Use a Label control o
nly when you need to change the contents or appearance of text programmatically.

To add a Label Web server control to a Web Forms page


1. From the Standard tab of the Toolbox, drag a Label control onto the page.
2. In the Appearance category of the Properties window, set the control's Text property to the text to display. You can
include HTML formatting in the property; for example, you can format an individual word in the text as bold by placing a
<b> tag around it in the Text property.

The following example shows how you can set the text of a Label control at run time. The method displays in the Label
control whatever the user has typed into the TextBox control named TextBox1.
Security Note
Be careful when using the Label control to display strings that come from an untrusted source. They can include potent
ially malicious client script. For details, see
How to: Protect Against Script Exploits in a Web Application by Applying HTML Encoding to Strings.

VB
Protected Sub Button1_Click(ByVal sender as Object, _
ByVal e as EventArgs)
Label1.Text = Server.HtmlEncode(TextBox1.Text)
End Sub

C#
protected void Button1_Click(object sender, System.EventArgs e) {
Label1.Text = Server.HtmlEncode(TextBox1.Text;)
}

See Also
Reference
Label Web Server Control Overview
ASP.NET

How to: Use Label Web Server Controls as Captions


You can use the Label Web server control to act as an active caption in front of another Web server control, such as a TextBox
control. The Label control cannot receive the user input focus. However, by associating the Label control with another control,
users can navigate to the associated control by simultaneously pressing the ALT key with an access key that you define for the
Label control.
To use a Label Web server control as a caption
1. Set the Label control's AssociatedControlID property to the ID of the control for which you want the Label control to be
the caption.
2. Set the Label control's AccessKey property to a single letter or number to define an access key
Note
If you associate the Label control with a button, when users simultaneously press the ALT key with the access key for t
he Label control, the button is clicked.

3. Optionally, set the Text property of the Label control to display an underlined character that indicates the access key.
The following example shows how to use a Label control as a caption for a TextBox control. When the page renders,
users will be able to press ALT+N to navigate to the text box. The letter N in the Label is underlined.

<asp:Label
AccessKey="N"
AssociatedControlID="TextBox1"
ID="Label1"
runat="server"
Text="<u>N</u>ame:">
</asp:Label>
&nbsp;
<asp:TextBox ID="TextBox1" runat="server" />

See Also
Reference
Label Web Server Control Overview
Visual Web Developer

ListBox Web Server Control (Visual Studio)


The ListBox Web server control allows users to select one or more items from a predefined list. The topics in this section
provide information that you will find useful in learning to work with the ListBox control.
In This Section
ListBox Web Server Control Overview
How to: Add ListBox Web Server Controls to a Web Forms Page (Visual Studio)
How to: Add Items in List Web Server Controls (Visual Studio)
How to: Set the Selection in List Web Server Controls (Visual Studio)
How to: Populate List Web Server Controls from a Data Source (Visual Studio)
How to: Respond to Changes in List Web Server Controls
How to: Determine the Selection in List Web Server Controls
Related Sections
How to: Add Web Server Controls to a Web Forms Page Using the Web Forms Designer
Provides directions for including Web server controls on ASP.NET Web pages.
How to: Set ASP.NET Server Control Properties (Visual Studio)
Suggests additional topics of interest concerning server control properties.
Setting Web Server Control Properties Programmatically (Visual Studio)
Provides directions for setting Web server control properties in code.
See Also
Tasks
How to: Add Items in List Web Server Controls (Visual Studio)
How to: Populate List Web Server Controls from a Data Source (Visual Studio)
How to: Set the Selection in List Web Server Controls (Visual Studio)
Other Resources
Individual Web and HTML Controls
ASP.NET

ListBox Web Server Control Overview


The ListBox Web server control enables users to select one or more items from a predefined list. It differs from a DropDownList
control in that it can display multiple items at once and it optionally enables the user to select multiple items.
ListBox Control Appearance
The ListBox control is typically used to display more than one item at once. You can control the look of the list in these ways:
Number of rows displayed. You can set the control to display a specific number of items. If the control contains more
items than that, it displays a vertical scroll bar.
Height and width. You can set the size of the control using pixels. In that case, the control ignores the number of rows
you have set and displays as many as will fit into the height of the control. Some browsers do not support setting the
height and width in pixels and will use the row count setting.
As with other Web server controls, you can use style objects to specify the appearance of the control. For details, see
ASP.NET Web Server Controls and CSS Styles.
Items
The ListBox control is a container for one or more list items. Each list item is an object of type ListItem with its own properties,
described in the following table.
Propert Description
y
Text The text displayed in the list.

Value The value associated with an item. Setting this property enables you to associate a value with a specific item without
displaying it. For example, you can set the Text property to the name of a U.S. state and the Value property to its pos
tal abbreviation.

Selected A Boolean value indicating whether the item is selected.

To work with items programmatically, you work with the Items collection of the ListBox control. The Items collection is a
standard collection, and you can add item objects to it, delete items, clear the collection, and so on.
The currently selected item is available in the ListBox control's SelectedItem property. For ease of use, the ListBox control also
supports a property called SelectedItem. If the control is set to single-selection mode, this property returns the one selected
item, making it unnecessary to loop through the entire Items collection to get at the current selection.
Single vs. Multiple Selection
Users can normally select a single item in the list by clicking it. If you set the ListBox control to enable multiple selections,
users can hold down the CTRL or SHIFT key while clicking to select multiple items.
Binding Data to the Control
You can use a ListBox Web server control to list options that are made available to the page using a data source control. Each
item in the ListBox control corresponds to an item — typically a row — in the data source.
The control displays one field from the source. Optionally, you can bind the control to a second field to set the value (which is
not displayed) of an item.
As with other server controls, you can bind any control properties, such as the color or size of the control, to data. For details,
see How to: Populate List Web Server Controls from a Data Source.
ListBox Events
The ListBox control raises the SelectedIndexChanged event when users select an item. By default, this event does not cause the
page to be posted to the server, but you can cause the control to force an immediate postback by setting the AutoPostBack
property to true.
Note
The ability of a ListBox control to post to the server when it is checked requires that the browser support ECMAScript (JScrip
t, JavaScript) and that scripting be enabled on the user's browser.

See Also
Tasks
How to: Determine the Selection in List Web Server Controls
How to: Populate List Web Server Controls from a Data Source
How to: Respond to Changes in List Web Server Controls
How to: Set the Selection in List Web Server Controls
Visual Web Developer

How to: Add ListBox Web Server Controls to a Web Forms Page
(Visual Studio)
The process of adding a ListBox Web server control consists primarily of setting options for how items should be displayed and
whether users can select multiple items.
To add a ListBox control to a Web Forms page
1. From the Standard tab of the Toolbox, drag the ListBox control onto the page.
2. In the Properties window, set the following properties:
Prope Description
rty
Rows Set to specify how many items should be displayed at once.
Note
You can also set the System.Web.UI.WebControls.WebControl.Height property to a pixel value. If you do, it take
s precedence over the value of the Rows property. However, not all browsers support the Height property, so
you should set the Rows property also.

Select Set to Single or Multiple to specify how many items users can select.
ionM
ode

3. Create items for the control in one of the following ways:


By creating them as individual items. For details, see How to: Add Items in List Web Server Controls (Visual Studio).
By data binding the control. For details, see
How to: Populate List Web Server Controls from a Data Source (Visual Studio).

See Also
Reference
ListBox Web Server Control Overview
Visual Web Developer

How to: Add Items in List Web Server Controls (Visual Studio)
The information in this topic applies to the following Web server controls:
ListBox
DropDownList
CheckBoxList
RadioButtonList
BulletedList
You can add items to a list Web server control in the following three ways:
Add static items at design time.
Add items programmatically at run time.
Add items using data binding. For details, see
How to: Populate List Web Server Controls from a Data Source (Visual Studio).
When you add a list item, you specify up to three possible properties of the item. The following table describes these
properties.
Pr Description
o
p
er
ty
T Specifies the text displayed in the list.
e
xt

V Specifies a value that is associated with an item but is not displayed. For example, you can set the Text property to the nam
al e of chemical element and the Value property to the symbol of the element.
u
e

S Indicates whether the item is selected. In a CheckBoxList control and in a multi-selection ListBox control, more than one it
el em can be selected. In a DropDownList control, RadioButtonList control, and single-selection ListBox control, only one it
e em can be selected at a time. If you set more than one selected item in these controls, the browser determines which item is
ct rendered as selected. In a BulletedList control, this setting has no effect.
e
d

To add static items at design time


1. In Design view, select the list control to which you want to add items.
In the Properties window, click the ellipsis button ( ) in the Items box.
The ListItem Collection Editor dialog box appears.
2. Click Add to add a new item.
3. Select the new item, and then in the properties grid, enter values for its Text, Value, and Selected properties.
4. Repeat steps 2 and 3 for each item you want to add, and then click OK.

To add items programmatically


1. Create a new object of type ListItem and set its Text and Value properties. Typically, you create the new ListItem by
calling the Add method.
2. Call the Add method of the control's Items collection and pass it the new object.
The following code example shows how to add ListItem objects to a ListBox control, but the procedure is identical for all
list Web server controls.
VB
Protected Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
ListBox1.Items.Add(New ListItem("Carbon", "C"))
ListBox1.Items.Add(New ListItem("Oxygen", "O"))
End Sub

C#
Protected void Button1_Click (object sender, System.EventArgs e)
{
ListBox1.Items.Add(new ListItem("Carbon", "C"));
ListBox1.Items.Add(new ListItem("Oxygen", "O"));
}

See Also
Tasks
How to: Populate List Web Server Controls from a Data Source (Visual Studio)
Visual Web Developer

How to: Set the Selection in List Web Server Controls (Visual
Studio)
The information in this topic applies to these Web server controls:
ListBox
DropDownList
CheckBoxList
RadioButtonList
Normally, users select items in a list Web server control to indicate their choice. However, you might want to pre-select items
or select items at run time (programmatically) based on some condition.
To set the selection in a list Web server control at design time
1. In the Properties window, click the ellipsis button ( ) for the Items property to open the ListItem Collection Editor
dialog box.
2. From the Members list, choose the member to be selected, and then set its Selected property to true.
3. If the control is set to allow multiple selections, repeat step 2 for each item to select, and then click OK to close the dialog
box.
To set a single selection in a list Web server control programmatically
Do one of the following:
Set the control's SelectedIndex property to the index value of the item to select. The index is zero-based. To set no
selection, set SelectedIndex to -1.
Note
If you set the SelectedIndex property of a DropDownList control to -1, the control resets the value to 0, beca
use the DropDownList control always has a list item selected.

VB
' Selects the third item
ListBox1.SelectedIndex = 2

C#
// Selects the third item
ListBox1.SelectedIndex = 2;

Set the Selected property of an individual item in the list.


VB
' Selects the item whose text is Apples
ListBox1.Items.FindByText("Apples")
If Not li Is Nothing Then
li.Selected = True
End If

// Selects the item whose text is Apples


ListItem li = ListBox1.Items.FindByText("Apples");
if(li != null)
{
li.Selected = true;
}

To set multiple selections in a list control programmatically


Loop through the control's Items collection and set the Selected property of every individual item.
Note
You can only select multiple items if the control's SelectionMode property is set to Multiple.

The following example shows how you can set selections in a multi-selection ListBox control called ListBox1. The code
selects every other item.
VB
Protected Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim i As Integer
Dim li As ListItem
For Each li In ListBox1.Items
i += 1
If (i Mod 2 = 0) Then
li.Selected = True
End If
Next
End Sub

C#
Protected void Button1_Click(object sender, System.EventArgs e)
{
// Counter
int i = 0;
foreach(ListItem li in ListBox1.Items)
{
if( (i%2) == 0)
{
li.Selected = true;
}
i += 1;
}
}

See Also
Tasks
How to: Set the Selection in List Web Server Controls (Visual Studio)
How to: Populate List Web Server Controls from a Data Source (Visual Studio)
Visual Web Developer

How to: Populate List Web Server Controls from a Data Source
(Visual Studio)
The information in this topic applies to the following Web server controls:
ListBox
DropDownList
CheckBoxList
RadioButtonList
BulletedList
You can use a list Web server control to display items that are read from a data source. Each item in the control corresponds to
an item — such as a row in a data table — in the data source. The control can display one field from the source and can
optionally use a second field as the item value.
You can combine list items that you create at design time with list items that are populated from a data source by setting the
AppendDataBoundItems property of a list control to true. A typical example is to create a list item with the text "Select an item"
as the first item for a DropDownList control. You can then populate the remaining items in the DropDownList control from
the data source.
To populate a list Web server control from a data source
1. Add a data source control to the page, such as the SqlDataSource control or the ObjectDataSource control.
2. Use the Data Source Configuration Wizard to define the connection and the query, or data-retrieval method, for the data
source control.
3. Right-click the list control and click Show Smart Tag.
4. In the task menu, click Choose Data Source.
The Data Source Configuration Wizard is displayed.
5. In the Select a data source list, click the data source control that you added in Step 1.
6. In the Select a data field to display list, click the data field that you want to display in the control.
7. Optionally, in the Select a data field for the value list, click the data field to store as the value of each item.
8. Optionally, if the control already contains statically defined list items that you want to retain when the list is populated
from a data source, set the control's AppendDataBoundItems property to true.

See Also
Tasks
Walkthrough: Creating Master/Detail Web Pages in Visual Studio
Reference
CheckBox and CheckBoxList Web Server Controls Overview
DropDownList Web Server Control Overview
ListBox Web Server Control Overview
RadioButton and RadioButtonList Web Server Controls Overview
Concepts
BulletedList Web Server Control Overview
ASP.NET

How to: Respond to Changes in List Web Server Controls


The information in this topic applies to these list Web server controls: ListBox, DropDownList, CheckBoxList, and
RadioButtonList.
When the user makes a selection in a list Web server control, the control raises an event that you can respond to directly.
Normally, you do not need to respond directly to the selection event at all. Instead, it is more typical to test which item is
selected after the form has been posted to the server by a control such as the Button control. For details about determining
which item is selected, see Determining the Selection in a List Web Server Control.
To respond directly to changes in a list Web server control
Create an event handler for the control's SelectedIndexChanged event. By default, the SelectedIndexChanged event
does not immediately cause the page to be posted to the server. Instead, the event is raised in server code the next time
the form is posted. To have the SelectedIndexChanged event cause an immediate posting, set the control's
AutoPostBack property to true.
Note
The event is raised as soon as the user makes a selection in the list control. If the AutoPostBack property is true, the f
orm is posted with each selection, but the selected items are preserved with each round trip.

The following code example shows how you can respond to a selection in a DropDownList control. The event handler
displays the user's selection in a Label control.
Security Note
Controls in an ASP.NET page can include potentially malicious client script. By default, the Web Forms page validates th
at user input does not include script or HTML elements. For more information, see
How to: Protect Against Script Exploits in a Web Application by Applying HTML Encoding to Strings.

VB
Protected Sub DropDownList1_SelectedIndexChanged(ByVal sender _
As System.Object, ByVal e As System.EventArgs) _
Handles DropDownList1.SelectedIndexChanged
Label1.Text = "You selected " & DropDownList1.SelectedItem.Text
End Sub

C#
Protected void DropDownList1_SelectedIndexChanged(object sender,
System.EventArgs e)
{
Label1.Text = "You selected " + DropDownList1.SelectedItem.Text;
}

See Also
Reference
CheckBox and CheckBoxList Web Server Controls Overview
DropDownList Web Server Control Overview
ListBox Web Server Control Overview
RadioButton and RadioButtonList Web Server Controls Overview
Concepts
BulletedList Web Server Control Overview
ASP.NET

How to: Determine the Selection in List Web Server Controls


The information in this topic applies to these Web server controls: ListBox, DropDownList, CheckBoxList, and RadioButtonList.
One of the most common tasks in working with a list Web server control is to determine what item or items users have
selected. The procedure varies depending on whether the list control allows single or multiple selections.
Use the following procedure when working with the DropDownList control, the RadioButtonList control, and a single-
selection ListBox control.
To determine the selection in a single-selection list control
Use one of the following methods:
To get the index value of the selected item, read the value of the SelectedIndex property. The index is zero-based.
If nothing has been selected, the value of the property is -1.
To get the contents of the selected item, get the control's SelectedItem property. This property returns an object
of type ListItem. You can get the contents of the selected item by getting the Text or Value property of the object.
Security Note
Controls in a Web Forms page can include potentially malicious client script. By default, the Web Forms page va
lidates that user input does not include script or HTML elements. For more information, see
How to: Protect Against Script Exploits in a Web Application by Applying HTML Encoding to Strings

The following code example shows how you can test which item is selected in a RadioButtonList control. The code first
determines whether there is a selection at all by reading the value of the SelectedIndex property, which is set to -1 until
the user selects an item. It then gets the SelectedItem object and displays that object's Text property.
VB
Protected Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
' Is anything selected? The index is -1 if nothing is selected.
If RadioButtonList1.SelectedIndex > -1 Then
Label1.Text="You chose: " & RadioButtonList1.SelectedItem.Text
End If
End Sub

C#
Protected void Button1_Click (object sender, System.EventArgs e)
{
// Is anything selected? The index is -1 if nothing is selected.
if (RadioButtonList1.SelectedIndex > -1) {
Label1.Text="You chose: " +
RadioButtonList1.SelectedItem.Text;
}
}

If the list control supports multiple selections, you must loop through the control and check for selected items one by one.
To determine the selection in a multi-selection list control
Loop through the control's Items collection and test the Selected property of every individual item.
The following code example shows how you can test selections in a multi-selection ListBox control called ListBox1. The
code displays a list of selected items in a label.
VB
Protected Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim msg As String
Dim li As ListItem
msg = ""
For Each li In ListBox1.Items
If li.Selected = True Then
msg = msg & "<br>" & li.Text & " selected."
End If
Next
Label1.Text = msg
End Sub

C#
Protected void Button1_Click(object sender, System.EventArgs e)
{
string msg = "" ;
foreach(ListItem li in ListBox1.Items)
{
if(li.Selected == true)
{
msg += "<BR>" + li.Text + " is selected.";
}
}
Label1.Text = msg;
}

See Also
Reference
CheckBox and CheckBoxList Web Server Controls Overview
DropDownList Web Server Control Overview
ListBox Web Server Control Overview
RadioButton and RadioButtonList Web Server Controls Overview
Visual Web Developer

Literal Web Server Control (Visual Studio)


The Literal control renders static text into a Web page without adding any HTML elements. You can manipulate the text
programmatically with server code.
Note
If you want to display static text, you can present it using HTML; you do not need a Literal control. Use a Literal control only
if you need to change the contents in server code.

The following topics provide information that you will find useful in learning to work with the Literal Web server control.
In This Section
Literal Web Server Control Overview
How to: Add Literal Web Server Controls to a Web Forms Page (Visual Studio)
See Also
Other Resources
Individual Web and HTML Controls
ASP.NET

Literal Web Server Control Overview


You can use a Literal Web server control as a container for other content on the page. The Literal control is used most
frequently when adding content dynamically to the page.
Comparing the Literal Control to Other Options
The Literal control represents one of several options for adding content to a page. For static content, you can add markup
directly to a page as HTML, without using a container. However, if you want to add content dynamically, you must add the
content to a container. Typical containers are the Label control, the Literal control, the Panel control, and the Placeholder
control.
The Literal control differs from the Label control in that the Literal control does not add any HTML elements to the text. (The
Label control renders a span element.) As a consequence, the Literal control does not support any style attributes, including
position attributes. However, the Literal control allows you to specify whether content is encoded.
The Panel and Placeholder controls render as div elements, which create discrete blocks in the page, unlike rendering in-line
the way the Label and Literal controls do.
In general, use a Literal control when you want to render text and controls directly into a page without any additional markup.
Encoding Content in the Literal Control
The Literal control supports the Mode property, which specifies how the control handles markup that you add to it. You can
set the Mode property to these values:
Transform. Any markup you add to the control is transformed to accommodate the protocol of the requesting browser.
This setting is useful if you are rendering content to mobile devices that use protocol other than HTML.
PassThrough. Any markup you add to the control is rendered as-is to the browser.
Encode. Any markup you add to the control is encoded using the HtmlEncode method, which converts HTML encoding
into its text representation. For example, a <b> tag is rendered as &lt;b&gt;. Encoding is useful when you want the
browser to display markup rather than interpret it. Encoding is also useful for security, to help prevent malicious markup
from being executed in the browser, and is recommended if you are displaying strings from an untrusted source. For
more information, see
How to: Protect Against Script Exploits in a Web Application by Applying HTML Encoding to Strings.
See Also
Reference
Label Web Server Control Overview
Visual Web Developer

How to: Add Literal Web Server Controls to a Web Forms Page
(Visual Studio)
You can add a Literal Web server control to your Web Forms page when you want to set text programmatically without adding
extra HTML tags. The Literal control is useful as a way to add text into a page dynamically without adding any elements that
are not part of the dynamic text. For example, you can use the Literal control to display HTML that you read from a file or from
a stream.
Note
If you want to display static text, you can present it by using HTML — you do not need a Literal control. Use a Literal control
only if you need to change the contents in server code dynamically.

To add a Literal Web server control to a Web Forms page


1. From the Standard tab of the Toolbox, drag a Literal control onto the page.
2. Optionally, in the Behavior category of the Properties window, set the Mode property to Transform, PassThrough, or
Encode. The Mode property specifies how the control handles any markup that is added to it. For details, see
Literal Web Server Control Overview.
The following example shows a simple Web page that displays a headline at run time. The body of the page, including the
Literal control, might look like this.

<body>
<form runat="server">
<h1><asp:Literal id="Headline" runat=server
mode="PassThrough"/></h1>
</form>
</body>

3. Add code to your page to set the control's Text property at run time.
The following example shows how to programmatically set the text and encoding of the Literal control. The page
contains radio buttons that allow the user to choose between encoded and pass-through text.
Note
If you are setting the Text property to text that you get from an untrusted source, set the control's Mode property to E
ncode so that the markup does not result in executable markup.

VB
<%@ Page Language="VB" %>
<script runat="server">
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs)
Literal1.Text = "This <b>text</b> is inserted dynamically."
If radioEncode.Checked = True Then
Literal1.Mode = LiteralMode.Encode
ElseIf radioPassthrough.Checked = True Then
Literal1.Mode = LiteralMode.PassThrough
End If
End Sub
</script>

<html>
<head runat="server"></head>
<body>
<form id="form1" runat="server">
<div>
<br />
<asp:RadioButton
ID="radioEncode"
runat="server"
GroupName="LiteralMode"
Checked="True"
Text="Encode"
AutoPostBack="True" />
<br />
<asp:RadioButton
ID="radioPassthrough"
runat="server"
GroupName="LiteralMode"
Text="PassThrough"
AutoPostBack="True" />
<br />
<br />
<asp:Literal ID="Literal1" runat="server"></asp:Literal>
</div>
</form>
</body>
</html>

C#
<%@ Page Language="C#" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
Literal1.Text = "This <b>text</b> is inserted dynamically.";
if (radioEncode.Checked == true)
{
Literal1.Mode = LiteralMode.Encode;
}
if(radioPassthrough.Checked == true)
{
Literal1.Mode = LiteralMode.PassThrough;
}
}
</script>
</script>

<html>
<head runat="server"></head>
<body>
<form id="form1" runat="server">
<div>
<br />
<asp:RadioButton
ID="radioEncode"
runat="server"
GroupName="LiteralMode"
Checked="True"
Text="Encode"
AutoPostBack="True" />
<br />
<asp:RadioButton
ID="radioPassthrough"
runat="server"
GroupName="LiteralMode"
Text="PassThrough"
AutoPostBack="True" />
<br />
<br />
<asp:Literal ID="Literal1" runat="server"></asp:Literal>&nbsp;</div>
</form>
</body>
</html>

See Also
Reference
Literal Web Server Control Overview
Visual Web Developer

Localize Web Server Control (Visual Studio)


The Localize Web server control enables you to display localized text in a specific area on your ASP.NET Web page.
The following topics provide information to help you effectively work with the Localize Web server control.
In This Section
Localize Web Server Control Overview
How to: Add Localize Web Server Controls to ASP.NET Web Pages (Visual Studio)
See Also
Reference
Localize Web Server Control Declarative Syntax
Localize
Other Resources
Individual Web and HTML Controls
ASP.NET

Localize Web Server Control Overview


You can add a Localize Web server control to your ASP.NET Web page when you want to display localized text in a specific area
on your page.
Comparing the Localize Control to the Literal Control
The Localize control is identical to the Literal Web server control and similar to the Label Web server control. While the Label
control allows you to apply a style to the displayed text, the Localize control does not. You can programmatically control the
text that is displayed in the Localize control by setting the Text property, which is inherited from the Literal control.
Encoding Content in the Literal Control
The Localize control supports the Mode property, which specifies how the control handles markup that you add to it. You can
set the Mode property to the following values:
Transform Any markup that you add to the control is transformed to accommodate the protocol of the requesting
browser. This setting is useful if you are rendering content to mobile devices that use a protocol other than HTML.
PassThrough Any markup that you add to the control is rendered as-is to the browser.
Encode Any markup that you add to the control is encoded using the HtmlEncode method, which converts HTML
encoding into its text representation. For example, a <b> tag is rendered as &lt;b&gt;. Encoding is useful when you want
the browser to display markup rather than interpret it. Encoding is also useful for security, to help prevent malicious
markup from being executed in the browser, and is recommended if you are displaying strings from an untrusted source.
For more information, see
How to: Protect Against Script Exploits in a Web Application by Applying HTML Encoding to Strings.
Localizing Text Using Resource Strings
You can create localized strings to display in the Text property of the Localize control by using an explicit or implicit
expression as the value of the property. Expressions are evaluated by using strings that are declared in resource (.resx) files.
Create your .resx files in folders called App_GlobalResources and App_LocalResources in the root of your application. If you
need to localize strings for multiple languages, you can create additional .resx files with locale information included in the file
name. For example, the French version of your resource file would be named ExampleLocalizedStrings.fr.resx.
For more information about expressions, see ASP.NET Expressions Overview. For information about resource files, see
Resources in ASP.NET Applications. For a code example that uses regular expressions in the Localize control, see
Localize Web Server Control Declarative Syntax.
See Also
Reference
Localize Web Server Control Declarative Syntax
Localize
Concepts
Resources in ASP.NET Applications
ASP.NET Expressions Overview
Other Resources
ASP.NET Application Security in Hosted Environments
Visual Web Developer

How to: Add Localize Web Server Controls to ASP.NET Web


Pages (Visual Studio)
You can add a Localize Web server control to your ASP.NET Web page when you want to display localized text in a specific area
on the page. The Localize control is identical to the Literal Web server control and similar to the Label Web server control.
While the Label control allows you to apply a style to the displayed text, the Localize control does not. You can
programmatically control the text that is displayed in the Localize control by setting the Text property, which is inherited from
the Literal control. For more information, see Literal Web Server Control Overview.
To add a Localize Web server control to an ASP.NET Web page
1. From the Standard tab of the Toolbox, drag a Localize control onto the page.
2. Optionally, set the Mode property to Transform, PassThrough, or Encode. The Mode property specifies how the control
handles markup that you add to it. For details, see Localize Web Server Control Overview.
3. Add code to your page to set the control's Text property at run time.
The following code example shows how to programmatically set the text and encoding of the Localize control. The page
contains radio buttons that allow the user to choose between encoded and pass-through text.
For a code example that uses resource strings, see Localize Web Server Control Declarative Syntax.
Note
If you set the Text property to text that you obtained from an untrusted source, set the control's Mode property to Enc
ode so that the markup is not executable.

VB
<%@ Page Language="VB" %>
<script runat="server">
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs)
Localize1.Text = "This <b>text</b> is inserted dynamically."
If radioEncode.Checked = True Then
Localize1.Mode = LiteralMode.Encode
ElseIf radioPassthrough.Checked = True Then
Localize1.Mode = LiteralMode.PassThrough
End If
End Sub
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<br />
<asp:RadioButton
ID="radioEncode"
runat="server"
GroupName="LocalizeMode"
Checked="True"
Text="Encode"
AutoPostBack="True" />
<br />
<asp:RadioButton
ID="radioPassthrough"
runat="server"
GroupName="LocalizeMode"
Text="PassThrough"
AutoPostBack="True" />
<br />
<br />
<asp:Localize ID="Localize1" runat="server"></asp:Localize>
</div>
</form>
</body>
</html>

C#
<%@ Page Language="C#" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
Localize1.Text = "This <b>text</b> is inserted dynamically.";
if (radioEncode.Checked == true)
{
Localize1.Mode = LiteralMode.Encode;
}
if(radioPassthrough.Checked == true)
{
Localize1.Mode = LiteralMode.PassThrough;
}
}
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<br />
<asp:RadioButton
ID="radioEncode"
runat="server"
GroupName="LocalizeMode"
Checked="True"
Text="Encode"
AutoPostBack="True" />
<br />
<asp:RadioButton
ID="radioPassthrough"
runat="server"
GroupName="LocalizeMode"
Text="PassThrough"
AutoPostBack="True" />
<br />
<br />
<asp:Localize ID="Localize1" runat="server"></asp:Localize>
</div>
</form>
</body>
</html>

See Also
Reference
Localize Web Server Control Declarative Syntax
Localize
Concepts
Localize Web Server Control Overview
Visual Web Developer

MultiView and View Web Server Controls (Visual Studio)


The MultiView control represents a control that acts as a container for groups of View controls. It allows you to define a group
of View controls, where each View control contains child controls, for example, in an online survey application. Your
application can then render a specific View control to the client based on criteria such as user identity, user preferences, or
information passed in a query string parameter.
In This Section
MultiView and View Web Server Controls Overview
How to: Add MultiView Web Server Controls to a Web Forms Page (Visual Studio)
See Also
Other Resources
Individual Web and HTML Controls
Panel Web Server Control
Wizard Web Server Control
ASP.NET

MultiView and View Web Server Controls Overview


The MultiView and View Web server controls act as containers for other controls and markup, and provide a way for you to
easily present alternate views of information. You can use the MultiView and View controls to perform tasks such as the
following:
Provide alternate sets of controls based on user choice or other conditions. For example, you might allow users to select
from a list of feeds, each of which is configured in a separate View control. You can then display the View control that
contains the user's choice of feeds. You can use the MultiView and View controls as an alternative to creating multiple
Panel controls.
Create a multi-page form. The MultiView and View controls can provide behavior that is similar to the Wizard control.
The Wizard control is particularly suited to creating forms that users fill in step by step. The Wizard control also includes
support for more built-in UI elements, such as a header and footer, for Previous and Next buttons, and for templates.
You might use a MultiView control in place of a Wizard if you wanted to create a display that changed based on
condition (rather than sequentially), or if you did not need the extra features supported by the Wizard control.
MultiView and View Structure
The MultiView control acts as an outer container for one or more View controls. The View controls, in turn, can contain any
combination of markup and controls.
The MultiView control displays one View control at a time, exposing the markup and controls within that View control. By
setting the MultiView control's ActiveViewIndex property, you can specify which View control is currently visible.
Rendering View Control Content
If a View control is not selected, it is not rendered to the page. However, instances of all Web server controls in all the View
controls are created each time the page is rendered, and their values are stored as part of the page's view state.
Neither the MultiView control nor individual View controls render any markup to the page other than the contents of the
current View control. For example, the controls do not render a div element in the same way that a Panel control does.
However, they also do not support appearance properties that can be applied as a whole to the current View control. But you
can assign a theme to the MultiView or View controls, which applies the theme to all child controls of the current View
control.
Referencing Controls
Each View control supports a Controls property that contains a collection of the controls in that View control. However, you
can reference the controls in the View controls individually in code. For details, see
Accessing ASP.NET Controls Programmatically.
Navigating Between Views
You can move between views by setting the MultiView control's ActiveViewIndex property to the index value of the View
control to display. The MultiView control also includes support for navigation buttons that you can add to each View control.
To create navigation buttons, you can add a button control (Button, LinkButton, or ImageButton) to each View control. You can
then set the CommandName and CommandArgument properties of each button to reserved values to cause the MultiView
control to move to another view. The following table lists the reserved CommandName values and the corresponding
CommandArgument values.
CommandName value CommandArgument value
NextView (no value)

PrevView (no value)

SwitchViewByID ID of the View control to switch to.

SwitchViewByIndex Index number of the View control to switch to.

The following code example shows a MultiView control with three View controls. Each View control contains a Button
control that moves to a specific View control.

<asp:MultiView ID="MultiView1" runat="server" ActiveViewIndex="0">


<asp:View ID="View1" runat="server">
View 1<br />
<br />
<asp:Button ID="Button1" runat="server"
CommandArgument="View2"
CommandName="SwitchViewByID"
Text="Go to View2" />
</asp:View>
<asp:View ID="View2" runat="server">
View 2<br />
<br />
<asp:Button ID="Button2" runat="server"
CommandArgument="View3"
CommandName="SwitchViewByID"
Text="Go to View 3" />
</asp:View>
<asp:View ID="View3" runat="server">
View 3<br />
<br />
<asp:Button ID="Button3" runat="server"
CommandArgument="View1"
CommandName="SwitchViewByID"
Text="Go to View 1" />
</asp:View>
</asp:MultiView>

See Also
Tasks
How to: Add MultiView Web Server Controls to a Web Forms Page
Visual Web Developer

How to: Add MultiView Web Server Controls to a Web Forms


Page (Visual Studio)
The MultiView and View Web server controls act as containers for other controls and markup, and provide a way for you to
display alternative sets of controls and markup. The MultiView and View controls were designed primarily for use with
browsers on mobile devices, but they are supported in any ASP.NET page.
To add a MultiView Web server control to a Web Forms page
1. From the Standard tab of the Toolbox, drag a MultiView control onto the page.
2. From the Standard tab of the Toolbox, drag a View control into the MultiView control.
3. Type any static text that you want to add into the View control. To add controls to the View control, drag them from the
Toolbox into the View control to create the layout you want.
4. Repeat step 2 and step 3 for each View control you want to create.
5. Set the MultiView control's ActiveViewIndex property to the index value of the View control to display. If you do not
want to display any View controls, set the property to -1.
6. Add code to programmatically set the ActiveViewIndex property to set which View control is displayed.
The following example shows how to work with a MultiView control. The page contains two View controls. The user
clicks a RadioButton control, and in the CheckedChanged event handler for the button, code displays the appropriate
View control by setting the ActiveViewIndex property. When the user clicks the Search button, code gets the value of
the TextBox control in the appropriate View control.
Security Note
This example has a text box that accepts user input, which is a potential security threat. By default, ASP.NET Web pages
validate that user input does not include script or HTML elements. For more information, see Script Exploits Overview.

VB
<%@ Page Language="VB" %>
<script runat="server">
Protected Enum SearchType As Integer
NotSet = -1
Products = 0
Category = 1
End Enum

Protected Sub Button1_Click(ByVal sender As Object, _


ByVal e As System.EventArgs)
If MultiView1.ActiveViewIndex > -1 Then
Dim searchTerm As String = ""
Select Case MultiView1.ActiveViewIndex
Case SearchType.Products
DoSearch(textProductName.Text, _
MultiView1.ActiveViewIndex)
Case SearchType.Category
DoSearch(textCategory.Text, _
MultiView1.ActiveViewIndex)
Case SearchType.NotSet
End Select
End If
End Sub

Protected Sub DoSearch(ByVal searchTerm As String, _


ByVal type As SearchType)
' Code here to perform a search.
End Sub

Protected Sub radioButton_CheckedChanged(ByVal sender As _


Object, ByVal e As System.EventArgs)
If radioProduct.Checked Then
MultiView1.ActiveViewIndex = SearchType.Products
ElseIf radioCategory.Checked Then
MultiView1.ActiveViewIndex = SearchType.Category
End If
End Sub
</script>

<html>
<head runat="server"></head>
<body>
<form id="form1" runat="server">
<div>
Search by product or by category?
<br />
<asp:RadioButton ID="radioProduct"
runat="server"
autopostback="true"
GroupName="SearchType"
Text="Product"
OnCheckedChanged="radioButton_CheckedChanged" />
&nbsp;
<asp:RadioButton ID="radioCategory"
runat="server"
autopostback="true"
GroupName="SearchType"
Text="Category"
OnCheckedChanged="radioButton_CheckedChanged" />
<br />
<br />
<asp:MultiView ID="MultiView1" runat="server">
<asp:View ID="viewProductSearch" runat="server">
Enter product name:
<asp:TextBox ID="textProductName"
runat="server"></asp:TextBox>
</asp:View>
<asp:View ID="viewCategorySearch" runat="server">
Enter category:
<asp:TextBox ID="textCategory"
runat="server"></asp:TextBox>
</asp:View>
</asp:MultiView>&nbsp;<br />
<br />
<asp:Button ID="btnSearch" OnClick="Button1_Click"
runat="server" Text="Search" />
</div>
</form>
</body>
</html>

C#
<%@ Page Language="C#" %>
<script runat="server">
public enum SearchType
{
NotSet = -1,
Products = 0,
Category = 1
}

protected void Button1_Click(Object sender, System.EventArgs e)


{
if(MultiView1.ActiveViewIndex > -1)
{
String searchTerm = "";
SearchType mSearchType =
(SearchType) MultiView1.ActiveViewIndex;
switch(mSearchType)
{
case SearchType.Products:
DoSearch(textProductName.Text, mSearchType);
break;
case SearchType.Category:
DoSearch(textCategory.Text, mSearchType);
break;
case SearchType.NotSet:
break;
}
}
}

protected void DoSearch(String searchTerm, SearchType type)


{
// Code here to perform a search.
}

protected void radioButton_CheckedChanged(Object sender,


System.EventArgs e)
{
if(radioProduct.Checked)
{
MultiView1.ActiveViewIndex = (int) SearchType.Products;
}
else if(radioCategory.Checked)
{
MultiView1.ActiveViewIndex = (int) SearchType.Category;
}
}
</script>

<html>
<head id="Head1" runat="server"></head>
<body>
<form id="form1" runat="server">
<div>
Search by product or by category?
<br />
<asp:RadioButton ID="radioProduct"
runat="server"
autopostback="true"
GroupName="SearchType"
Text="Product"
OnCheckedChanged="radioButton_CheckedChanged" />
&nbsp;
<asp:RadioButton ID="radioCategory"
runat="server"
autopostback="true"
GroupName="SearchType"
Text="Category"
OnCheckedChanged="radioButton_CheckedChanged" />
<br />
<br />
<asp:MultiView ID="MultiView1" runat="server">
<asp:View ID="viewProductSearch" runat="server">
Enter product name:
<asp:TextBox ID="textProductName" runat="server">
</asp:TextBox>
</asp:View>
<asp:View ID="viewCategorySearch" runat="server">
Enter category:
<asp:TextBox ID="textCategory" runat="server">
</asp:TextBox>
</asp:View>
</asp:MultiView>&nbsp;<br />
<br />
<asp:Button ID="btnSearch"
OnClick="Button1_Click"
runat="server" Text="Search" />
</div>
</form>
</body>
</html>

See Also
Tasks
Walkthrough: Creating Web Pages for Mobile Devices
Concepts
MultiView and View Web Server Controls Overview
Visual Web Developer

Panel Web Server Control (Visual Studio)


The topics in this section provide information about the Panel Web server control, which acts as a container within the page for
other controls. By putting controls into a Panel control, you can control them as a unit — for example, hiding or showing them.
You can also use a Panel control to create a distinct appearance for a group of controls.
Note
The Panel control is not required to group controls such as RadioButton controls.

In This Section
Panel Web Server Control Overview
How to: Add Panel Controls to a Web Forms Page (Visual Studio)
See Also
Other Resources
Individual Web and HTML Controls
Adding ASP.NET Controls Programmatically
ASP.NET

Panel Web Server Control Overview


The Panel Web server control provides a container control within a Web Forms page that you can use as a parent for static text
and for other controls. In addition, you can use the Panel control for a variety of other purposes.
Grouping Controls and Markup
You can manage a group of controls and associated markup as a unit by putting them in a Panel control and then
manipulating the Panel control. For example, you can hide or show a group of controls inside a panel by setting the panel's
Visible property.
Forms with Default Buttons
You can put TextBox controls and Button controls inside the Panel control and then define a default button by setting the
Panel control's DefaultButton property to the ID of a button in the panel. If users press ENTER while typing in a text box inside
the panel, it has the same effect as if the user had clicked the specified default button. This can help users work more efficiently
with entry forms.
Container for Dynamically Generated Controls
The Panel control provides a convenient container for controls that you create at run time. For details, see
Adding ASP.NET Controls Programmatically.
Adding Scrollbars to Other Controls
Some controls, such as the TreeView control, do not have built-in scrollbars. You can add scrolling behavior by placing the
control in a Panel control. To add scrollbars to the Panel control, set the Height and Width properties to constrain the Panel
control to a specific size, and then set the ScrollBars property.
Custom Areas on the Page
You can use the Panel control to create areas on the page that have custom appearance and behavior, such as the following:
Creating a grouping box with title You can set the GroupingText property to display a title. When the page renders,
the Panel control is displayed with a box around it that contains a title with the text you specify.
Note
You cannot specify both scrollbars and grouping text in the Panel control. If you set grouping text, it takes precedence
over scrollbars.

Creating areas on the page with a custom color or other appearance The Panel control supports appearance
properties such as BackColor and BorderWidth that you can set to create a unique look for a region on a page.
Note
Setting the GroupingText property automatically renders a border around the Panel control.

See Also
Tasks
How to: Add Panel Web Server Controls to a Web Forms Page
Visual Web Developer

How to: Add Panel Controls to a Web Forms Page (Visual


Studio)
To use a Panel Web server control, you add it to a page and then add controls and static text to the control.
To add a Panel control to a Web Forms page
1. In Design view, from the Standard tab of the Toolbox, drag a Panel control onto the page.
2. To create static text, click inside the control and type. To add controls, drag them from the Toolbox into the Panel control.
Note
To add static text to the Panel control at run time, you create a Literal control and set its Text property. You then progra
mmatically add the Literal object to the panel the way you would any control. For details about adding controls, see
How to: Add Controls to an ASP.NET Web Page Programmatically.

3. Optionally, drag the panel's borders to resize the control.


Note
The control automatically resizes itself to display all of its child controls, even if they exceed the height that you have se
t.

4. Optionally, set the properties of the Panel control, which are described in the following table, to specify how the pane
interacts with its child controls.
Property Description
HorizontalAlign Specifies how the child controls are aligned within the panel (left, right, centered, or justified).

Wrap Specifies whether content that is too wide for the panel is wrapped to the next line or truncated at the pa
nel's edge.

Direction Specifies whether the content of the control renders left-to-right or right-to-left. This can be useful for cr
eating areas on the page that have a different direction than the page as a whole.

ScrollBars If you have set the Height and Width properties to constrain the Panel control to a specific size, you can
add scrollbars by setting the ScrollBars property.

GroupingText Renders a border and title around the Panel control.


Note
Setting the GroupingText property causes scrollbars not to appear, if you have specified them

See Also
Reference
Panel Web Server Control Overview
Visual Web Developer

PlaceHolder Web Server Control (Visual Studio)


The PlaceHolder control enables you to place an empty container control in the page and then dynamically add child elements
to it at run time. The following topics provide information useful in learning to work with the PlaceHolder Web server control.
In This Section
PlaceHolder Web Server Control Overview
How to: Add PlaceHolder Web Server Controls to a Web Forms Page (Visual Studio)
See Also
Other Resources
Adding ASP.NET Controls Programmatically
Individual Web and HTML Controls
ASP.NET

PlaceHolder Web Server Control Overview


The Placeholder Web server control enables you to place an empty container control within the page and then dynamically
add, remove, or loop through child elements at run time. The control only renders its child elements; it has no HTML-based
output of its own.
As an example, you might want to have a variable number of buttons appear on a Web page, depending on options selected by
users. That way, users are not confronted with potentially confusing choices that are either unavailable or not relevant to their
individual needs.
See Also
Tasks
How to: Add PlaceHolder Web Server Controls to a Web Forms Page
Visual Web Developer

How to: Add PlaceHolder Web Server Controls to a Web Forms


Page (Visual Studio)
You can add a PlaceHolder Web server control to your Web Forms page when you want to dynamically add, remove, or loop
through controls at run time.
To add a PlaceHolder Web server control to a Web Forms page
From the Standard tab of the Toolbox, drag a PlaceHolder control onto the page.
To add child controls to a PlaceHolder control at run time
1. Create an instance of the control that you want to add to the PlaceHolder control.
2. Call the Add method of the PlaceHolder control's Controls property, passing it the instance that you created in the
previous step.
The following example shows how to add two Button controls as children of a PlaceHolder control. The code also adds a
Literal control in order to add a <br> tag between the buttons.
VB
Protected Sub Page_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
Dim Button1 As Button = New Button()
Button1.Text = "Button 1"
PlaceHolder1.Controls.Add(Button1)
Dim Literal1 As New Literal()
Literal1.Text = "<br>"
PlaceHolder1.Controls.Add(Literal1)
Dim Button2 As New Button()
Button2.Text = "Button 2"
PlaceHolder1.Controls.Add(Button2)
PlaceHolder1.Controls.Add(Button2)
End Sub

C#
void Page_Load(object sender, EventArgs e)
{
Button Button1 = new Button();
Button1.Text = "Button 1";
PlaceHolder1.Controls.Add(Button1);

Literal Literal1 = new Literal();


Literal1.Text = "<br>";
PlaceHolder1.Controls.Add(Literal1);

Button Button2 = new Button();


Button2.Text = "Button 2";
PlaceHolder1.Controls.Add(Button2);
}

See Also
Reference
PlaceHolder Web Server Control Overview
Visual Web Developer

RadioButton and RadioButtonList Web Server Controls (Visual


Studio)
The RadioButton and RadioButtonList Web server controls provide a way for users to select from among mutually exclusive
options.
Because there are two different controls, and because they function somewhat differently, it is important to understand their
different purposes. The topics in this section provide information on what the RadioButton and RadioButtonList are, how
they are different, and how to work with each type of control.
In This Section
RadioButton and RadioButtonList Web Server Controls Overview
How to: Add RadioButton Web Server Controls to a Web Forms Page (Visual Studio)
How to: Add RadioButtonList Web Server Controls to a Web Forms Page (Visual Studio)
How to: Set and Get the Selection in a RadioButton Web Server Control
How to: Set Layout in a RadioButtonList Web Server Control
How to: Respond to a User Selection in a RadioButton Web Server Control Group
Related Sections
How to: Add Web Server Controls to a Web Forms Page Using the Web Forms Designer
Provides instructions for including Web server controls on an ASP.NET Web page.
How to: Add Items in List Web Server Controls (Visual Studio)
Provides instructions for defining individual radio buttons in the RadioButtonList control, either at design time or
programmatically at run time.
How to: Populate List Web Server Controls from a Data Source (Visual Studio)
Provides instructions for binding a RadioButtonList control to a data source in order to display bound radio buttons.
How to: Set the Selection in List Web Server Controls (Visual Studio)
Provides instructions for preselecting items in a RadioButtonList control.
How to: Set ASP.NET Server Control Properties (Visual Studio)
Suggests additional topics of interest concerning server control properties.
Setting Web Server Control Properties Programmatically (Visual Studio)
Provides instructions for setting Web server control properties in code.
See Also
Other Resources
Individual Web and HTML Controls
ASP.NET

RadioButton and RadioButtonList Web Server Controls


Overview
You can use two types of Web server controls to add radio buttons to an ASP.NET Web page: individual RadioButton controls
or a RadioButtonList control. Both controls allow users to select from a small set of mutually exclusive, predefined choices. The
controls allow you to define any number of radio buttons with labels and to arrange them horizontally or vertically.
Note
You can also use the HtmlInputRadioButton server control to add radio buttons to an ASP.NET Web page.

Note
If you want to present users with a longer list of options or a list that might vary in length at run time, use a ListBox or
DropDownList Web server control.

RadioButton Control vs. RadioButtonList Control


You add individual RadioButton controls to a page and work with them singly. Typically, you group two or more individual
buttons together. For more information, see Adding Individual RadioButton Controls to a Web Forms Page.
In contrast, the RadioButtonList control is a single control that acts as a parent control for a collection of radio button list
items. It derives from a base ListControl, and therefore works much like the ListBox, DropDownList, BulletedList, and
CheckBoxList Web server controls. Therefore, many of the procedures for working with the RadioButtonList control are the
same as they are for the other list Web server controls.
Each type of control has advantages. Individual RadioButton controls give you more control over the layout of the radio
button group. For example, you can include text (that is, non-radio-button text) between radio buttons.
The RadioButtonList control does not permit you to insert text between the buttons, but is far easier to use if you want to
bind the buttons to a data source. It is also slightly easier to write code that determines which button has been selected.
Grouping Radio Buttons
Radio buttons are rarely used singly. Instead, they are grouped to provide a set of mutually exclusive options. Within a group,
only one radio button can be selected at a time. You can create grouped radio buttons in these ways:
Add individual RadioButton Web server controls to a page and then manually assign them all to a group. In this case,
the group is an arbitrary name; all radio buttons with the same group name are considered part of a single group.
Add a RadioButtonList Web server control to the page. The list items in the control are automatically grouped.
RadioButton Events
Events work slightly differently between individual RadioButton controls and the RadioButtonList control.
Individual RadioButton Controls
Individual RadioButton controls raise a CheckedChanged event when users click the control. By default, this event does not
cause the page to be posted to the server, but you can have the control force an immediate post by setting the AutoPostBack
property to true. For details about responding to this event directly, see
Responding to a User Selection in a RadioButton Group.
Note
The ability of a RadioButton control to post to the server when it is checked requires that the browser support ECMAScript (
JScript, JavaScript) and that scripting be enabled on the user's browser.

Whether a RadioButton control posts to the server or not, it is not usually necessary to create an event handler for the
CheckedChanged event. Instead, it is more common to test which button is selected when the form has been posted to the
server by a control such as a Button control. For details, see
Setting and Getting the Selection in a RadioButton Web Server Control.
RadioButton Control HTML Attributes
When the RadioButton control renders to the browser, it does so in two parts: an <input> element representing the radio
button, and a separate <label> element representing the caption for the radio button. The combination of the two elements is
in turn wrapped in a <span> element.
When you apply style or attribute settings to a RadioButton control, they are applied to the outer <span> element. For
example, if you set the control's BackColor property, the setting is applied to the <span> tag, and therefore affects both the
inner <input> and <label> elements.
At times, you might want to be able to make separate settings for the radio button and the label. The RadioButton control
supports two properties that you can set at run time: the InputAttributes property and the LabelAttributes property. Each
property allows you to add HTML attributes to the <input> and <label> elements, respectively. The attributes you set are
passed through as-is to the browser. For example, the following code shows how to set attributes for the <input> element so
that just the radio button, but not the label, changes color when users pass the mouse pointer over it.
VB
RadioButton1.InputAttributes.Add("onmouseover", _
"this.style.backgroundColor = 'red'")
RadioButton1.InputAttributes.Add("onmouseout", _
"this.style.backgroundColor = 'white'")

C#
RadioButton1.InputAttributes.Add("onmouseover",
"this.style.backgroundColor = 'red'");
RadioButton1.InputAttributes.Add("onmouseout",
"this.style.backgroundColor = 'white'");

RadioButtonList Control
In contrast, the RadioButtonList control raises a SelectedIndexChanged event when users change which radio button in the
list is selected. By default, the event does not cause the form to be posted to the server, although you can specify this option by
setting the AutoPostBack property to true. For details, see Responding to Changes in a List Web Server Control.
Note
The ability of a RadioButtonList control to post to the server when it is selected requires that the browser support ECMAScri
pt (JScript, JavaScript) and that scripting be enabled on the user's browser.

As with individual RadioButton controls, it is more common to test the state of the RadioButtonList control after the form
has been posted some other way. For details, see Determining the Selection in a List Web Server Control.
Binding Data to the Control
As with any Web server control, you can bind an individual RadioButton control to a data source, and you can bind any
property of the RadioButton control to any field of the data source. For example, you might set the control's Text property
from information in a database.
However, because radio buttons are used in groups, binding a single radio button to a data source isn't a common scenario.
Instead, it is more typical to bind a RadioButtonList control to a data source. In that case, the data source dynamically
generates radio buttons (list items) for each record in the data source.
See Also
Tasks
How to: Add Individual RadioButton Web Server Controls to a Web Forms Page
Visual Web Developer

How to: Add RadioButton Web Server Controls to a Web Forms


Page (Visual Studio)
You can add a radio button to a Web Forms page in two ways:
By adding an individual RadioButton Web server control.
By adding a RadioButtonList Web server control and then adding individual list items to the control.
Note
This topic addresses how to add individual RadioButton controls to the page. For information about adding items to a
RadioButtonList control, see How to: Add Items in List Web Server Controls.

For details about the differences between these approaches, see


RadioButton and RadioButtonList Web Server Controls Overview.
When you use individual RadioButton Web server controls, you typically add a set of them to the page and then group them.
You can create multiple, separate groups of buttons.
To add individual RadioButton Web server controls to a Web Forms page
1. From the Standard tab of the Toolbox, drag a RadioButton control onto the page.
2. In the Properties window, specify a caption by setting the Text property.
3. Optionally, change the orientation of the caption by setting the TextAlign property.
4. Repeat steps 1 through 3 for each radio button that you want to add to your page.
To group individual RadioButton Web server controls
Set the GroupName property of each control to the same name. You can use any string as the name, but do not include a
space. For example, you might assign the string "RadioButtonGroup1" to the GroupName property of all the buttons.
To create multiple groups of buttons, use a different group name for each.
Note
You can add RadioButton controls to the page and group them with existing groups at any point.

See Also
Reference
RadioButton and RadioButtonList Web Server Controls Overview
Visual Web Developer

How to: Add RadioButtonList Web Server Controls to a Web


Forms Page (Visual Studio)
You can add a radio button to a Web Forms page in two ways:
By adding a RadioButtonList Web server control and then adding individual list items to the control.
By adding an individual RadioButton Web server control.
Note
This topic addresses how to add a RadioButtonList Web server control and then add individual list items to the contro
l. For information about adding an individual RadioButton Web server control, see
How to: Add RadioButton Web Server Controls to a Web Forms Page (Visual Studio).

For details about the differences between these approaches, see


RadioButton and RadioButtonList Web Server Controls Overview.
When you use a RadioButtonList control, you add a single control to the page. Adding items to the control is a separate
process that depends on whether you will display a static list in the control or a list generated dynamically at run time.
To add a RadioButtonList Web server control to a Web Forms page
1. From the Standard tab of the Toolbox, drag a RadioButtonList control onto the page.
2. Optionally, in the Properties window, change the orientation of the caption by setting the TextAlign property.
3. Optionally, change the layout of the control to display multiple columns. For details, see
How to: Set Layout in a RadioButtonList Web Server Control.
4. Create items for the control in one of the following ways:
By creating them as individual items. For details, see How to: Add Items in List Web Server Controls (Visual Studio).
By binding data to the control. For details, see
How to: Populate List Web Server Controls from a Data Source (Visual Studio).

See Also
Reference
RadioButton and RadioButtonList Web Server Controls Overview
ASP.NET

How to: Set and Get the Selection in a RadioButton Web Server
Control
You can set a selected radio button at design time or at run time in code. If the radio button is in a group, setting it clears any
other selection in the group.
Note
If you are working with a RadioButtonList control, the procedure for getting and setting the value of a button is different. For
details, see How to: Determine the Selection in a List Web Server Control and
How to: Set the Selection in a List Web Server Control.

To set the selected RadioButton control


Set the control's Checked property to true. If you select more than one RadioButton control in a group, the browser
determines which button is rendered as selected.
If you set the property to false, it clears the selection but does not select another radio button. Therefore, you can clear all
selections by setting the Checked property of all radio buttons in a group to false.
Determining which RadioButton control has been selected is a matter of testing the Checked property.
To determine which RadioButton control in a group is selected
Test the control's Checked property.
Note
Testing the value of a radio button does not tell you whether the user changed the value of the control, only whether it
is selected. To check for a change in the control, write an event handler for the control's CheckedChanged event. For de
tails, see How to: Respond to a User Selection in a RadioButton Group.

To determine which button is selected in a group, you have to test each control individually, as in the following code
example.
VB
Protected Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim msg As String = "You selected "
If RadioButton1.Checked = True Then
msg = msg & RadioButton1.Text
ElseIf Radiobutton2.Checked = True Then
msg = msg & RadioButton2.Text
ElseIf Radiobutton3.Checked = True Then
msg = msg & RadioButton3.Text
End If
Label1.Text = msg
End Sub

C#
public void Button1_Click (object sender, System.EventArgs e)
{
if (RadioButton1.Checked) {
Label1.Text = "You selected " + RadioButton1.Text;
}
else if (RadioButton2.Checked) {
Label1.Text = "You selected " + RadioButton2.Text;
}
else if (RadioButton3.Checked) {
Label1.Text = "You selected " + RadioButton3.Text;
}
}

See Also
Reference
RadioButton and RadioButtonList Web Server Controls Overview
ASP.NET

How to: Set Layout in a RadioButtonList Web Server Control


By default, the RadioButtonList Web server control displays a single column of buttons. However, you can specify any number
of columns, and within the columns, you can specify how the items are ordered: vertically (the default) or horizontally. Vertical
layout in three columns results in a layout such as the following:

A D G
B E H
C F

Horizontal layout for the same items results in the following layout:

A B C
D E F
G H

Note
If you are working with individual RadioButton Web server controls, you do not set layout as a property of the control. Instea
d, you set it by simply adding the radio buttons within the page flow. For details about the differences between these control
s, see RadioButton and RadioButtonList Web Server Controls Overview.

To specify column count and ordering


1. Set the RadioButtonList control's RepeatColumns property to the number of columns you want.
2. Set the RepeatDirection property to Vertical or Horizontal using the RepeatDirection enumeration, as shown in the
following code example.
VB
Protected Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Button1.Click
' Create five radio buttons.
Dim colors() As String = _
New String() {"Red", "Blue", "Green", "Yellow", "Orange"}
RadioButtonList1.Items.Clear()
Dim i As Integer
For i = 0 To ubound(colors)
RadioButtonList1.Items.Add(colors(i))
Next
' Lay out the radio buttons horizontally.
RadioButtonList1.RepeatDirection = RepeatDirection.Horizontal
End Sub

C#
protected void Button1_Click (object sender, System.EventArgs e)
{
// Create five radio buttons.
string[] colors = {"Red", "Blue", "Green", "Yellow", "Orange"};
this.RadioButtonList1.Items.Clear();
for(int i=0;i < colors.GetLength(0);i++){
this.RadioButtonList1.Items.Add(colors[i]);
}
// Lay out the radio buttons horizontally.
this.RadioButtonList1.RepeatDirection =
RepeatDirection.Horizontal;
}

See Also
Reference
RadioButton and RadioButtonList Web Server Controls Overview
ASP.NET

How to: Respond to a User Selection in a RadioButton Web


Server Control Group
When the user selects a RadioButton control, the control raises an event that you can respond to.
Note
The RadioButtonList control raises events differently than individual RadioButton controls. For details, see
Responding to Changes in a List Web Server Control.

You might not need to respond directly to the selection event of a RadioButton control at all. You respond to the event only if
it is important to know when the user has made a change to the selection in a radio button group.
If you are only interested in knowing which radio button is selected, and not whether selection has changed, you can simply
test radio button selection after the form has been posted to the server. For details about determining which RadioButton
control is selected, see How to: Set and Get the Selection in a RadioButton Web Server Control.
Because each RadioButton server control is a separate control, each can raise an event individually; the radio button group
does not raise an event as a whole.
To respond to a selection in a RadioButton control
Create an event handler for the control's CheckedChanged event.
By default, the CheckedChanged event does not immediately cause the Web Forms page to be posted to the server.
Instead, the event is raised in server code the next time the form is posted, as when a Button Web server control is
clicked. To have the CheckedChanged event cause an immediate posting, set the RadioButton control's AutoPostBack
property to true.
Note
The ability of a RadioButton control to post to the server when it is checked requires that the browser support ECMAS
cript (JScript, JavaScript) and that scripting be enabled on the user's browser.

The following code example shows how you can respond when a user selects a RadioButton control.
VB
Sub RadioButton1_CheckedChanged(sender As Object, e As EventArgs) _
Handles RadioButton1.CheckedChanged
Label1.Text = "You selected Radio Button " & RadioButton1.Text
End Sub

C#
public void RadioButton1_CheckedChanged (object sender,
System.EventArgs e)
{
Label1.Text = "You selected Radio Button " + RadioButton1.Text;
}

See Also
Reference
RadioButton and RadioButtonList Web Server Controls Overview
Visual Web Developer

Substitution Web Server Control (Visual Studio)


The Substitution control specifies a section on an output-cached Web page that is exempt from caching. Use the Substitution
control to specify a section on an output-cached Web page where you want dynamic content substituted for the control.
In This Section
Substitution Web Server Control Overview
See Also
Concepts
ASP.NET Caching Overview
Other Resources
Individual Web and HTML Controls
ASP.NET

Substitution Web Server Control Overview


The Substitution control is used on ASP.NET Web pages that are configured to be cached. The Substitution control allows you
to create areas on the page that can be updated dynamically and then integrated into the cached page.
Dynamically Updating Portions of a Cached Page
When an ASP.NET page is cached, the entire output of the page is cached by default. On the first request, the page runs and
caches its output. On subsequent requests, the request is fulfilled from the cache and code on the page does not run.
In some circumstances, you might want to cache an ASP.NET page but update selected portions of the page on each request.
For example, you might want to cache the majority of a page but be able to dynamically update time-sensitive information on
the page.
You can use the Substitution control to insert dynamic content into the cached page. The Substitution control does not
render any markup. Instead, you bind the control to a method on the page or parent user control. You create the static method
yourself, returning any information that you want to insert into the page. The method called by the Substitution control must
meet the following criteria:
It is defined as a static method (shared in Visual Basic).
It accepts a parameter of type HttpContext.
It returns a value of type String.
Note that other controls on the page are not accessible to the Substitution control—that is, you cannot examine or change the
value of other controls. However, the code does have access to the current page context using the parameter passed to it.
When the page runs, the Substitution control calls the method and then substitutes the return value from the method for the
Substitution control on the page.
The following code example shows how to use the Substitution control to create dynamically updated content on a cached
page. Code in the page's Load event updates a Label control with the current time. Because the page's cache duration is set to
60 seconds, the text of the Label control does not change even if the page is requested multiple times during the 60-second
period. A Substitution control on the page calls the static method GetTime, which returns the current time as a string. Each
time the page is refreshed, the value represented by the Substitution control is updated.
VB
<%@ Page Language="VB" %>
<%@ OutputCache Duration=60 VaryByParam="None" %>

<script runat="server">
Sub Page_Load()
Label1.Text = DateTime.Now.ToString()
End Sub

Public Shared Function GetTime(ByVal context As HttpContext) _


As String
Return DateTime.Now.ToString()
End Function
</script>
<html>
<head runat="server"></head>
<body>
<form id="form1" runat="server">
<div>
<p>
<asp:Label runat="server" ID="Label1" />
</p>
<p>
<asp:Substitution runat="server"
ID="Substitution1"
MethodName="GetTime" />
</p>
<p>
<asp:Button runat="server" ID="Button1" Text="Submit"/>
</p>
</div>
</form>
</body>
</html>

C#
<%@ Page Language="C#" %>
<%@ OutputCache Duration=60 VaryByParam="None" %>

<script runat="server">
void Page_Load()
{
Label1.Text = DateTime.Now.ToString();
}
public static String GetTime(HttpContext context)
{
return DateTime.Now.ToString();
}
</script>
<html>
<head runat="server"></head>
<body>
<form id="form1" runat="server">
<div>
<p>
<asp:Label runat="server" ID="Label1" />
</p>
<p>
<asp:Substitution runat="server"
ID="Substitution1"
MethodName="GetTime" />
</p>
<p>
<asp:Button runat="server" ID="Button1" Text="Submit"/>
</p>
</div>
</form>
</body>
</html>

See Also
Concepts
Dynamically Updating Portions of a Cached Page
Visual Web Developer

Table, TableRow, and TableCell Web Server Controls (Visual


Studio)
The Table Web server control creates a general-purpose table on a Web Forms page. Rows in the table are created as
TableRow Web server controls, and cells within each row are implemented as TableCell Web server controls.
The following topics provide information that you will find useful in learning to work with the Table, TableRow, and
TableCell controls.
In This Section
Table Web Server Control Overview
How to: Add Table Web Server Controls to a Web Forms Page (Visual Studio)
How to: Add Rows and Cells Dynamically to a Table Web Server Control
See Also
Other Resources
Individual Web and HTML Controls
ASP.NET

Table Web Server Control Overview


The Table Web server control allows you to create server-programmable tables on ASP.NET pages. The TableRow and
TableCell Web server controls provide a way to display the actual content for the Table control.
Comparing the Table Web Server Control to Other Table Elements
Tables are typically used not only to present tabular information, but as a way to format information on a Web page. There are
a number of ways to create tables on your Web Forms page:
HTML table. You can add an HTML <table> element. If you are creating a static table (one in which you will not add or
change content at run time), you should use an HTML table and not a Table control.
HtmlTable control. This is a <table> HTML element that has been converted to an HTML server control by adding the
runat=server attribute. You can program this control in server code. For details about HTML server controls, see
ASP.NET Web Server Controls Overview.
Table. A Web control that allows you to create and manipulate tables (for example, adding table rows and cells) using an
object model that is consistent with other Web controls.
In general, you use a Table Web server control when you intend to add rows and cells (columns) to the table in code at run
time. Although you can use it as a static table with predefined rows and columns, it is easier in this case to work with the HTML
<table> element.
The Table Web server control can be easier to program than the HtmlTable control because it offers an object model with
typed properties that is consistent with other Web server controls. (The model is also consistent between the Table,
TableRow, and TableCell controls.)
Comparing the Table Web Server Control to Other List Web Server Controls
Some of the functions you might accomplish with a Table Web server control can also be accomplished with the list Web
server controls, specifically the Repeater, DataList, and GridView controls. All these controls are rendered (or have the option to
be rendered) as HTML tables.
The differences between the list controls and the Table control are these:
The list controls are data-bound. The list controls work only against a data source, whereas the Table control can display
any combination of HTML text and controls, whether or not they are data-bound.
The list controls use templates to specify the layout of their elements. The Table control supports the TableCell child
control, which you can fill as you would any HTML <td> element.
Table Web Server Control Object Model
The Table control acts as a parent control for TableRow controls. The table supports a property called Rows that is a collection
of TableRow objects. By managing this collection — adding or deleting items in it — you specify the rows for the table. The
TableRow control in turn supports a collection called Cells that contains TableCell objects.
The content to be displayed in the table is added to the TableCell control. The cell has a Text property that you set to any
HTML text. Alternatively, you can display controls in the cell by creating instances of, and adding controls to, the cell's Controls
collection.
The parent Table control supports properties to control the appearance of the entire table, such as Font, BackColor, and
ForeColor. The TableRow and TableCell controls support these properties as well, so you can specify the look of individual
rows or cells, overriding the parent table appearance.
Binding Data to the Control
Although the Table control (unlike the list Web server controls; see above) is not inherently data-bound, you can use it to
display data from a database.
As with all Web server controls, you can bind any property of a Table control to a data source. However, the Table control
does not support a property that you use to directly display data. Instead, you typically add TableCell controls to the table. You
can then either bind the Text property of individual TableCell controls to data, or you can add data-bound controls (such as a
Label or Literal control) to the cell.
See Also
Tasks
How to: Add Rows and Cells Dynamically to a Table Web Server Control
Visual Web Developer

How to: Add Table Web Server Controls to a Web Forms Page
(Visual Studio)
Adding a Table Web server control consists of two steps: adding the table itself, and separately adding the rows and cells. You
can add rows and columns at design time to create a static table, or you can add them at run time in code. For details about
adding them at run time, see How to: Add Rows and Cells Dynamically to a Table Web Server Control.
Note
In general, if you are creating a static table (one in which you will not add or change content at run time), it is better to use an
HTML table element in place of a Table Web server control.

To add a Table Web server control to a Web Forms page


From the Standard tab of the Toolbox, drag a Table control onto the page.
The table is initially displayed as a simple text control with no rows or columns.
Adding Table Rows and Cells at Design Time
To create a static table, you can add rows and cells at design time.
To add rows and cells to a Table Web server control at design time
1. Select the table, and then open the Properties window and click the ellipsis button ( ) for the Rows property.
The TableRow Collection Editor window is displayed.
2. Click Add to create a new row.
A new row is added, and its properties are displayed in a grid on the right-hand side of the dialog box.
3. Optionally, set display characteristics for the new row by changing its font, color, and so on.
Note
Settings you enter in the TableRow Collection Editor dialog box apply to only one row. To apply settings that apply t
o all rows, set properties for the table as a whole.

4. To add cells to the new row, make sure the row is selected in the Members list, and then click the ellipsis button ( ) for
the Cells property.
The TableCell Collection Editor dialog box is displayed.
5. Click Add to create a new cell, and set its properties using the grid on the right-hand side of the dialog box. To display
text in the cell, set its Text property.
6. Repeat step 5 for each cell you want to add to a row. When you are finished adding cells to a row, click OK in the
TableCell Collection Editor dialog box.
7. Repeat steps 2 through step 6 for each new row and its cells. When you are finished adding rows to the table, click OK in
the TableRow Collection Editor dialog box.
The Table control is displayed in Design view with placeholder characters for each row and cell that you have created.
See Also
Reference
Table Web Server Control Overview
ASP.NET

How to: Add Rows and Cells Dynamically to a Table Web Server
Control
It is common to add rows and cells to a Table Web server control at run time. The Table Web server control is designed
specifically for this task.
Note
To design a table visually in Design view, use an HtmlTable control. If you also need to programmatically manipulate the cont
ents of the HtmlTable control, convert its rows and cells to HtmlTableRow and HtmlTableCell controls by setting their runat
attribute to server. For details, see Converting HTML Server Controls to HTML Elements.

Rows in a Table Web server control are objects of type TableRow. The Rows property of the Table control supports a
collection of TableRow objects. To add a row to the table, you add a TableRow object to this collection.
Similarly, the TableRow object has a Cells property that supports a collection of objects of type TableCell. You can add cells to
a row by manipulating this collection.
To add rows and cells to a table dynamically
1. To add a row, create a new object of type TableRow:
VB
Dim tRow As New TableRow()
Table1.Rows.Add(tRow)

C#
TableRow tRow = new TableRow();
Table1.Rows.Add(tRow);

2. To add cells to the row, create one or more objects of type TableCell:
VB
Dim tCell As New TableCell()
tRow.Cells.Add(tCell)

C#
TableCell tCell = new TableCell();
tRow.Cells.Add(tCell);

3. Add content to the new cell. You can do this in several ways, as shown in the following table.
To add Do this
Static text Set the cell's Text property.

Controls Declare an instance of the control and add it to the cell's Controls collection.

Both text and controls in th Declare the text by creating an instance of the Literal class. Add it to the cell's Controls colle
e same cell ction as you would other controls.
Note
By default, controls that you add dynamically to a Web Forms page are added to the page's view state. If you recreate c
ontrols with each round trip, this can result in unexpected behavior when the page is processed, because view state is r
estored before the controls are recreated. You can avoid problems by setting the EnableViewState property of the cont
ainer control (for example, of the Table control) to false. For more information, see
Adding ASP.NET Controls Programmatically.

The following code example shows how you can add rows and cells to a Table control. The number of rows and columns
is determined by what the user enters into two text boxes. Each cell displays the row and cell number as static text.
VB
Protected Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Button1.Click
' Total number of rows.
Dim rowCnt As Integer
' Current row count
Dim rowCtr As Integer
' Total number of cells (columns).
Dim cellCtr As Integer
' Current cell counter.
Dim cellCnt As Integer

rowCnt = CInt(Textbox1.Text)
cellCnt = CInt(Textbox2.Text)

For rowCtr = 1 To rowCnt


Dim tRow As New TableRow()
For cellCtr = 1 To cellCnt
Dim tCell As New TableCell()
tCell.Text = "Row " & rowCtr & ", Cell " & cellCtr
' Add new TableCell object to row.
tRow.Cells.Add(tCell)
Next
' Add new row to table.
Table1.Rows.Add(tRow)
Next

End Sub

C#
protected void Button1_Click (object sender, System.EventArgs e)
{
// Total number of rows.
int rowCnt;
// Current row count.
int rowCtr;
// Total number of cells per row (columns).
int cellCtr;
// Current cell counter
int cellCnt;

rowCnt = int.Parse(TextBox1.Text);
cellCnt = int.Parse(TextBox2.Text);

for(rowCtr=1; rowCtr <= rowCnt; rowCtr++) {


// Create new row and add it to the table.
TableRow tRow = new TableRow();
Table1.Rows.Add(tRow);
for (cellCtr = 1; cellCtr <= cellCnt; cellCtr++) {
// Create a new cell and add it to the row.
TableCell tCell = new TableCell();
tCell.Text = "Row " + rowCtr + ", Cell " + cellCtr;
tRow.Cells.Add(tCell);
}
}
}

The following code example is similar to the previous one, but displays static text and a Hyperlink control in each cell. The
Hyperlink control navigates to a mocked-up URL, passing a mock product ID. Because the example mixes static text and
controls, the static text is implemented as a Literal object, which is added to the cell's Controls collection just like the
Hyperlink control is.
VB
Protected Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Button1.Click
' Total number of rows.
Dim rowCnt As Integer
' Current row count
Dim rowCtr As Integer
' Total number of cells (columns).
Dim cellCtr As Integer
' Current cell counter.
Dim cellCnt As Integer

rowCnt = CInt(TextBox1.Text)
cellCnt = CInt(TextBox2.Text)

For rowCtr = 1 To rowCnt


Dim tRow As New TableRow()
For cellCtr = 1 To cellCnt
Dim tCell As New TableCell()
' Mock up a product ID
Dim prodID As String
prodID = rowCtr & "_" & cellCtr

' Create literal text as control.


Dim s As New LiteralControl()
s.Text = "Buy: "
' Add to cell.
tCell.Controls.Add(s)
' Create Hyperlink Web Server control and add to cell.
Dim h As New HyperLink()
h.Text = rowCtr & ":" & cellCtr
h.NavigateUrl = "http://www.microsoft.com/net"
' Add cell to row.
tCell.Controls.Add(h)
' Add new TableCell object to row.
tRow.Cells.Add(tCell)
Next cellCtr
' Add new row to table.
Table1.Rows.Add(tRow)
Next rowCtr
End Sub

C#
Protected void Button1_Click (object sender, System.EventArgs e)
{
// Total number of rows.
int rowCnt;
// Current row count.
int rowCtr;
// Total number of cells per row (columns).
int cellCtr;
// Current cell counter.
int cellCnt;

rowCnt = int.Parse(TextBox1.Text);
cellCnt = int.Parse(TextBox2.Text);

for(rowCtr=1; rowCtr <= rowCnt; rowCtr++) {


// Create a new row and add it to the table.
TableRow tRow = new TableRow();
Table1.Rows.Add(tRow);
for (cellCtr = 1; cellCtr <= cellCnt; cellCtr++) {
// Create a new cell and add it to the row.
TableCell tCell = new TableCell();
tRow.Cells.Add(tCell);
// Mock up a product ID.
string prodID = rowCtr + "_" + cellCtr;

// Add a literal text as control.


tCell.Controls.Add(new LiteralControl("Buy: "));
// Create a Hyperlink Web server control and add it to the cell.
System.Web.UI.WebControls.HyperLink h = new HyperLink();
h.Text = rowCtr + ":" + cellCtr;
h.NavigateUrl = "http://www.microsoft.com/net";
tCell.Controls.Add(h);
}
}
}

See Also
Reference
Table Web Server Control Overview
Visual Web Developer

TextBox Web Server Control (Visual Studio)


The TextBox Web server control provides a way for users to type information into a Web Forms page, including text, numbers,
and dates. The following topics provide information that you will find useful in learning to work with the TextBox Web server
control.
In This Section
TextBox Web Server Control Overview
How to: Get and Set Values in TextBox Web Server Controls
How to: Respond to Changes in a TextBox Web Server Control
How to: Set a TextBox Web Server Control for Password Entry
How to: Specify Multiline Input for a TextBox Web Server Control
See Also
Other Resources
Individual Web and HTML Controls
ASP.NET

TextBox Web Server Control Overview


The TextBox Web server control provides a way for users to type information into a Web Forms page, including text, numbers,
and dates. You can configure the TextBox Web server control in several ways, as described in the following table.
Co Description
nfi
gur
ati
on
Sin Users type information in a single line. You can optionally limit the number of characters that the control accepts.
gle-
line

Pas Like a single-line TextBox control, but the characters users type are masked with asterisks (*) to hide them.
swo
rd Security Note
Using a TextBox control set for passwords can help ensure that other people will not be able to determine a user's pass
word if they observe the user entering it. However, the password text entered is not encrypted in any way, and you shoul
d protect it as you would any other confidential data. For example, for maximum security when posting a form with a pa
ssword in it, you might use Secure Sockets Layer (SSL) and encryption.

Mul Users type information in a box that displays multiple lines and allows text wrapping.
tilin
e
Security Note
User input in a Web Forms page can include potentially malicious client script. By default, the Web Forms page validates that
user input does not include script or HTML elements. For more information, see Script Exploits Overview.

TextBox Events
The TextBox control raises a TextChanged event when the user leaves the control. By default, the event is not raised
immediately; instead, it is raised on the server when the Web Forms page is submitted. However, you can specify that the
TextBox control should submit the page to the server as soon as the user leaves the field.
The TextBox Web server control does not raise an event each time the user enters a keystroke, only when the user leaves the
control. You can have the TextBox control raise client-side events that you handle in client script, which can be useful for
responding to individual keystrokes. For details, see Programming ASP.NET Web Pages with Client Script.
TextBox Captions
You can use Label controls to create captions for TextBox controls. The caption can define an access key that users can press
to navigate to the TextBox control. For details, see How to: Use Label Web Server Controls as Captions.
Auto-Completion in Text Boxes
Many browsers support an auto-completion feature that helps users fill information into text boxes based on values the users
have entered previously. The exact behavior of auto-completion depends on the browser. In general, browsers store values
based on the text box's name attribute; any text box with the same name, even on a different page, will offer the same values
to the user. Some browsers also support a vCard schema, which allows users to create a profile in the browser with predefined
values for first name, last name, telephone number, e-mail address, and so on.
The TextBox control supports an AutoCompleteType property that provides you with these options for controlling how the
browser works with auto-completion:
Disable auto-completion. If you do not want the browser to offer auto-completion for a text box, you can disable it.
Specify a vCard value to use as the auto-completion value for the field. The browser must support the vCard schema.
See Also
Tasks
How to: Get and Set Values in TextBox Web Server Controls
ASP.NET

How to: Get and Set Values in TextBox Web Server Controls
You can get or set the value of a TextBox control at run time.
Security Note
User input in a Web page can include potentially malicious client script. By default, the Web Forms page validates that user in
put does not include script or HTML elements. For more information, see
How to: Protect Against Script Exploits in a Web Application by Applying HTML Encoding to Strings.

To get or set values in the TextBox control


Get or set the value of the control's Text property.
The following code example shows how you can read the value of one TextBox control called TextBox1 and use it to set
the value of another, TextBox2.
VB
Protected Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Textbox2.Text = Server.HtmlEncode(TextBox1.Text)
End Sub

C#
protected void Button1_Click(object sender, System.EventArgs e)
{
TextBox2.Text = Server.HtmlEncode(TextBox1.Text);
}

See Also
Reference
TextBox Web Server Control Overview
ASP.NET

How to: Respond to Changes in a TextBox Web Server Control


When the user leaves a TextBox Web server control after entering information, the control raises an event that you can respond
to.
Note
The TextBox Web server control does not raise an event each time the user enters a keystroke, only when the user leaves th
e control. You can have the TextBox control raise client-side events that you handle in client script, which can be useful for r
esponding to individual keystrokes. For details, see Programming ASP.NET Web Pages with Client Script.

To respond to changes in the TextBox control


Create an event handler for the TextBox control's TextChanged event.
By default, the TextChanged event does not immediately cause the Web Forms page to be posted to the server. Instead,
the event is raised in server code the next time the form is posted. To have the TextChanged event cause an immediate
posting, set the TextBox control's AutoPostBack property to true.
Note
The ability of a TextBox control to post to the server when it is checked requires that the browser support ECMAScript
(JScript, JavaScript) and that scripting be enabled on the user's browser.

The following code example shows how you can respond to changes in the TextBox control. The code displays the
contents of the control in a label.
Security Note
User input in a Web Forms page can include potentially malicious client script. By default, the Web Forms page validate
s that user input does not include script or HTML elements. For more information, see
How to: Protect Against Script Exploits in a Web Application by Applying HTML Encoding to Strings.

VB
Protected Sub TextBox1_TextChanged(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles TextBox1.TextChanged
Label1.Text = Server.HtmlEncode(TextBox1.Text)
End Sub

C#
protected void TextBox1_TextChanged(object sender, EventArgs e)
{
Label1.Text = Server.HtmlEncode(TextBox1.Text);
}

See Also
Reference
TextBox Web Server Control Overview
ASP.NET

How to: Set a TextBox Web Server Control for Password Entry
A TextBox Web server control set for passwords hides a user's entry as it is being typed. Password text boxes can only be
single-line text boxes.
Security Note
Using a TextBox control set for passwords can help ensure that other people will not be able to determine a user's passwor
d if they observe the user entering it. However, the password text entered is not encrypted in any way, and you should protec
t it as you would any other confidential data. For example, for maximum security when posting a form with a password in it,
you might use Secure Sockets Layer (SSL) and encryption.

To create a password text box


1. Set the TextBox control's TextMode property to Password. In code, text modes are set using the TextBoxMode
enumeration.
2. Set the size of the control by setting its Width property to a value in pixels or its Columns property to the number of
characters to display. If you set both properties, Width takes precedence.
Note
The Width property does not work in browsers that do not support cascading style sheet (CSS) styles.

3. Optionally, you can limit the number of characters the user is allowed to enter by setting the control's MaxLength
property. If a user exceeds this number of characters, the control stops accepting more.
Note
You might not want to set the MaxLength property, because it can be of use to unauthorized users who are trying to g
uess the password.

See Also
Reference
TextBox Web Server Control Overview
ASP.NET

How to: Specify Multiline Input for a TextBox Web Server


Control
A multiline TextBox control allows users to type information into a box that supports wordwrapping and vertical and horizontal
scrolling.
To create a multiline TextBox Web server control
1. Set the TextBox control's TextMode property to Multiline. In code, text modes are set using the TextMode enumeration.
2. Set the size of the control by setting the following properties:
Width to a value in pixels, or Columns to the number of characters to display.
Height to a value in pixels, or Rows to the number of rows.
Note
The Height and Width properties do not work in browsers that do not support cascading style sheet (CSS) styles
.

Setting these properties does not limit the number of characters or rows the user can enter, only how many are
displayed. The control always displays a vertical scrollbar. Height and Width take precedence over Rows and Columns.
Note
By default, a multiline TextBox control includes a vertical scroll bar. To hide the scroll bar, include the style attribute ov
erflow: hidden. For example, in HTML view, the declarative syntax for the control might look as follows:

3. Set word-wrap behavior by setting the control's Wrap property. If true, text wraps automatically (without embedding
carriage-return/line feed characters). If false, the text does not wrap and the user must press ENTER to start a new line,
which embeds a carriage-return/line feed character. Setting the Wrap property to false causes the control to display a
horizontal scroll bar.
Note
The MaxLength property has no effect in a multiline text box.

See Also
Reference
TextBox Web Server Control Overview
Visual Web Developer

Wizard Web Server Control (Visual Studio)


The Wizard control allows you to build ASP.NET Web pages that present the user with multi-step procedures.
In This Section
Wizard Web Server Control Overview
Walkthrough: Creating a Basic ASP.NET Wizard Control
Walkthrough: Advanced Use of the ASP.NET Wizard Control
See Also
Other Resources
Individual Web and HTML Controls
Panel Web Server Control
ASP.NET

Wizard Web Server Control Overview


Collecting user input by using forms is a recurring task in Web development. A group of forms that is used to accomplish a
task is often called a wizard. ASP.NET provides a Wizard control to simplify many of the tasks that are associated with building
a series of forms to collect user input.
Building a series of interconnected forms to break up data collection is a common practice. You can accomplish this by
managing the navigation between forms, the data persistence, and the state management in each step.
The ASP.NET Wizard control simplifies many of the tasks that are associated with building multiple forms and collecting user
input. The Wizard control provides a simple mechanism that allows you to easily build steps, add a new step, or reorder the
steps. You can build linear and non-linear navigation and customize the control's user navigation without writing code.
Using the Wizard Control in Your Page
With the Wizard control, you use discrete steps to collect data, which allows users to navigate between steps at their discretion
and creates a simpler user experience. As a developer, you do not have to worry about making your data persist across pages
because the control maintains state while the user completes the various steps.
Wizard Steps
The Wizard control uses steps to delineate different sections of user data input. Each step within the control is given a
StepType to indicate whether it is the beginning step, intermediate step, or completion step. The wizard can have as many
intermediate steps as needed. You can add different controls, such as a TextBox or ListBox control, to collect user input. When
you reach the Complete step, all of your data is accessible. The following code example illustrates the Wizard control with two
steps.

<asp:Wizard ID="Wizard1" Runat="server">


<WizardSteps>
<asp:WizardStep Runat="server" Title="Step 1">
</asp:WizardStep>
<asp:WizardStep Runat="server" Title="Step 2">
</asp:WizardStep>
</WizardSteps>
</asp:Wizard>

Within each step, you can add controls and labels, and accept user data. The Wizard control will help manage which step to
display, and help maintain the collected data.
Wizard Navigation
The Wizard control features both linear and non-linear navigation. The control's state management allows the user to move
forward and backward between steps, and it allows the user to select individual steps at any point, as long as the sidebar is
displayed. You can customize the text for navigation in the control's root asp:Wizard element by using the
StepNextButtonText, StepPreviousButtonText, and FinishCompleteButtonText properties.

<asp:Wizard ID="Wizard1" Runat="server"


StepNextButtonText=" Next >> "
StepPreviousButtonText=" << Previous "
FinishCompleteButtonText=" Done! ">

Customizing Other Wizard Control Aspects


The Wizard control automatically displays a title and the control's current step. The title is customized with the HeaderText
property. You can adjust the header's template by using the HeaderTemplate property.
You can optionally display a cancel button by setting the DisplayCancelButton property to true.
The Wizard control's NavigationButtonStyle property provides an easy way to set all of the buttons to a common style, while
providing the flexibility to customize each button individually. The NavigationButtonStyle property applies to all of the
buttons rendered. However, you can override this style by setting the individual button's style property.
Navigation Templates
The Wizard control supports templates that allow you to further customize the interface of the control with the
StartNavigationTemplate, FinishNavigationTemplate, StepNavigationTemplate, and SideBarTemplate properties.
Wizard Control Events
You can customize the behavior of the Wizard control by using custom code and events.
For example, you can intercept the NextButtonClick event, which is raised when the user clicks the Next button and captures
the data of the current step. The WizardNavigationEventArgs parameter passed to this event includes the CurrentStepIndex
and NextStepIndex properties, enabling you to customize the behavior of the control based on the current and next steps, or to
cancel the navigation when the Next button is clicked.
Similarly, you can customize the behavior of the Previous and Finish buttons by using the PreviousButtonClick and
FinishButtonClick events. Or you can perform cleanup when the Cancel button is clicked by using the CancelButtonClick event.
See Also
Reference
CreateUserWizard
Visual Web Developer

Walkthrough: Creating a Basic ASP.NET Wizard Control


Building a series of forms to collect user data is a common task when developing Web sites. The ASP.NET Wizard control
simplifies many of the tasks associated with building forms and collecting user input by providing a mechanism that allows
you to easily build steps, add a new step, or reorder the steps. In this walkthrough, you will use the ASP.NET Wizard control to
simplify data collection as a series of independent steps without having to write code or making user data persist between
form steps. You will create a simple wizard that collects a user name and e-mail address, and then present it back to the user in
the completion step. Tasks illustrated in this walkthrough include:
Adding a Wizard control to your page.
Adding controls and text to a wizard step.
Accessing the wizard's data between steps.
Prerequisites
In order to complete this walkthrough, you will need:
Microsoft Visual Web Developer (Visual Studio).
The .NET Framework.
Creating the Web Site
If you have already created a Web site in Visual Web Developer (for example, by following the steps in
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and skip to "Adding a Wizard
Control" later in this walkthrough. Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, enter the name of the folder where you want to keep the pages of your Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click the programming language you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Adding a Wizard Control
To add a Wizard control
1. Switch to Design view for Default.aspx.
2. From the Standard group of the Toolbox, drag a Wizard control onto the page.
The control appears with two default steps already in place. Clicking the steps allows you to edit the text and controls
displayed during that step.
Editing Wizard Steps
When the Wizard control is dragged onto the page, it shows two predefined steps by default. For this walkthrough, you will
edit both steps, and add a completion step that shows the result of the first two steps: a user name and an e-mail address.
To edit the first wizard step
1. Drag one of the handles at the edge of the Wizard control to enlarge the control to about twice its default size.
2. Click the underlined text Step 1 in the Wizard control.
3. Click the edit area for the Wizard control.
You can now edit the step's display area.
4. Type Name:.
5. Drag a TextBox control onto the active area of the wizard, next to the text you just typed.
You can now edit the second step to collect a user's e-mail address.
To edit the second wizard step
1. Click Step 2 in the Wizard control.
2. Click the edit area for the Wizard control.
3. Type Email:.
4. Drag a TextBox control onto the active area of the wizard, next to your e-mail label.
5. Save the file.
Adding a Completion Step
You will now create a completion step that acts as the end point of your wizard. The Complete step has no navigational
options.
To add a completion step
1. Right-click the Wizard control.
2. Choose Show Smart Tag.
3. In the Wizard Tasks dialog box, choose Add/Remove Wizard Steps.
The WizardStep Collection Editor appears.
4. From the Add drop-down list on the Add button, select Wizard Step.
The Properties area now shows the new step.
5. Set the Title property to Finished.
6. Set the StepType property to Complete.
7. Click OK.
Now you can edit your new completion step. For the purposes of this walkthrough, configure the completion step to show the
data the user entered on the previous steps.
To edit the completion step
1. Right-click the Wizard control and choose Show Smart Tag.
2. In the Wizard Tasks dialog box, use the Step drop-down list to choose the Finished step.
Note
The name in the drop-down list will be the name you gave the step when you created it, Finished in this example.

3. Drag a Label control onto the wizard, leaving the default name of Label1.
4. Drag another Label control onto the wizard, leaving the default name of Label2.
5. Save the file.
The completion step will display the data entered by the user. Use the page's Load event to assign the values from the first two
steps to the labels you added to the completion step.
To show the user's data
1. Return to Default.aspx and, in Design view, double-click the design surface.
The page now contains a Page_Load method that is stubbed out for you.
2. Add the following highlighted code.
VB
Private Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles Me.Load
Label1.Text = TextBox1.Text
Label2.Text = TextBox2.Text
End Sub

C#
void Page_Load(Object sender, System.EventArgs e)
{
Label1.Text = TextBox1.Text;
Label2.Text = TextBox2.Text;
}

3. Save the file.


Testing the Wizard Control
Now you can test the Wizard control.
To test the Wizard control
1. View Default.aspx in Design view.
2. Display the Wizard Tasks menu on the control and select Step 1 from the Step drop-down list.
3. Click the Wizard control, and then press CTRL+F5.
4. Type a name in the name TextBox control for Step 1.
5. Click Next.
6. Type an e-mail address in the e-mail TextBox control for Step 2.
7. Click Finish.
Your data is displayed.
Next Steps
The Wizard control simplifies the creation of forms to gather user data. In addition to what has been covered here, you might
have other questions related to user data collection and forms use. For example, you might want to:
Learn more about authenticating users with Forms. For details, see How to: Implement Simple Forms Authentication
Use themes to enhance the appearance of your wizard. For details, see ASP.NET Themes and Skins Overview
Get an overview of the Wizard control. For details, see Wizard Web Server Control Overview
See Also
Reference
Wizard Web Server Control Overview
Visual Web Developer

Walkthrough: Advanced Use of the ASP.NET Wizard Control


The ASP.NET Wizard control simplifies many of the tasks associated with building forms and collecting user input. In this
walkthrough, you use the Wizard control to create a form that collects a user's address information, allows them to opt in or
opt out of e-mail updates, and then presents the data and choices back to them in a final confirmation step. Tasks illustrated in
this walkthrough include:
Editing the layout of a wizard step.
Adding a custom wizard step.
Programmatically capturing a wizard event.
Branching your wizard based on user choices.
Displaying user data in a completion step.
Prerequisites
In order to complete this walkthrough, you will need:
Microsoft Visual Web Developer.
The .NET Framework.
Creating the Web Site
If you have already created a Web site in Visual Web Developer (for example, by working with the topic
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and skip to "Adding a Wizard
Control to the Page" later in this walkthrough. Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, enter the name of the folder where you want to keep the pages of your Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click the programming language you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Adding a Wizard Control to the Page
To add a Wizard control to the page
1. Switch to Design view.
2. From the Standard group of the Toolbox, drag a Wizard control onto your page.
Collecting Name and Address Information
Next, you configure each step of your wizard to collect the user data, prompt for an e-mail address, and display the collected
data in the completion step.
First, collect the user's name, address, city, state, and postal code.
To configure the first step
1. Drag one of the handles at the edge of the Wizard control to enlarge the control to about twice its default size.
2. Click the underlined text Step 1 in the Wizard control, and then click in the edit area to the right of Step 1 in the Wizard
control.
You can now edit the display area for step 1.
3. Type Name.
4. From the Standard group of the Toolbox, drag a TextBox control next to your text.
5. In the Properties window, change the ID of the TextBox control from TextBox1 to Name.
6. Repeat the process, adding captions and TextBox controls (remember to name the controls because you will need to
refer to them later) to collect:
Address
City
State
PostalCode
7. Save the file.
Adding an E-mail Update Choice
In this part of the walkthrough, you allow the user to choose whether they would like to receive e-mail updates.
To add an e-mail update choice
1. Click Step 2.
2. Click the editable area to the right of Step 2, and type Would you like to receive e-mail updates?.
3. Beneath the question, type: Yes.
4. From the Standard group of the Toolbox, drag a RadioButton control next to the word Yes.
5. Type No.
6. Drag another RadioButton from the Toolbox onto the control next to the word No.
Adding a Custom Step to Collect an E-mail Address
In this section, you add a custom step to the wizard that collects the user's e-mail address. Later, you will add code to skip this
step if the user decides not to get e-mail updates.
To add a custom step to collect the user's email
1. Right-click the Wizard control outside of the edit areas and click Show Smart Tag.
2. In the Wizard Tasks dialog box, choose Add/Remove Wizard Steps.
The WizardStep Collection Editor appears.
3. In the Add drop-down list on the Add button, click Wizard Step.
4. Click OK.
The Wizard control displays the new step.
5. Click the new step to switch it to edit mode.
6. In the editable area, type E-mail address.
7. From the Standard group of the Toolbox, drag a TextBox control onto the control next to the words E-mail Address.
8. In Properties, change the ID of the TextBox control to EmailAddress because you will need to refer to it later in code.
Adding a Completion Step
Now you can add a completion step that will present the user's data back to them.
To add a completion step
1. Right-click the Wizard control and click Show Smart Tag.
2. In the Wizard Tasks menu on the control, choose Add/Remove Wizard Steps.
The WizardStep Collection Editor appears.
3. In the Add list, click Wizard Step.
The Properties area displays the attributes of the new step.
4. In the Properties window, set StepType to Complete.
5. Click OK.
The Wizard control adds the new step.
6. Click the new step on the control, and then click the editable area to the right of the new step.
7. From the Standard group of the Toolbox, drag a Label control onto the new step.
8. Press ENTER to create a new line.
9. Repeat step 7 five more times, for a total of six Label controls corresponding to:
Name
Address
City
Region or State
Postal Code
E-mail Address
10. Save the file.
Before you can run the wizard, you need to populate the labels in your completion step with the values the user supplied in the
first three wizard steps.
Adding Code for the Completion Step
In this walkthrough, the completion step displays the user's data. To ensure the data is displayed, you populate the step's labels
programmatically. To display the data, you write code for the page's Load event.
To add code
1. Switch to Default.aspx and, in Design view, double-click the design surface.
The code editor opens for the page, and creates a skeleton Page_Load method.
2. Add the following highlighted code to populate the completion step.
VB
Private Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
Label1.Text = Name.Text
Label2.Text = Address.Text
Label3.Text = City.Text
Label4.Text = State.Text
Label5.Text = PostalCode.Text
Label6.Text = EmailAddress.Text
End Sub

C#
void Page_Load(object sender, EventArgs e)
{
Label1.Text = Name.Text;
Label2.Text = Address.Text;
Label3.Text = City.Text;
Label4.Text = State.Text;
Label5.Text = PostalCode.Text;
Label6.Text = EmailAddress.Text;
}

3. Save the file.


Testing the Wizard Control
To test the Wizard control
1. Display Default.aspx in Design view.
2. Open the Wizard Tasks menu on the control and select Step 1 from the Step drop-down list.
3. Press CTRL+F5 to run the page.
Note
When running the page from Design view, the browser might start on the currently active wizard step, not necessarily t
he first step. Be sure the wizard's ActiveStepIndex property is set to 0 in the Properties window before launching the
page.

4. Type name and address information.


5. Click Next.
6. Select either option for e-mail.
You will write code to handle the e-mail option later in the walkthrough.
7. Type an e-mail address.
8. Click Finish.
The data you entered is displayed on the page.
In the next section, you add the code necessary to skip the third step of collecting e-mail if the user chooses not to provide an
e-mail address.
Adding Code to Skip the E-mail Step
Now that the data collection and layout portions of your wizard are complete, you will add the logic to allow the user to skip
the step that collects the e-mail address if they do not want to receive e-mail updates. You do this by handling the Wizard
control's NextButtonClick event. When you handle the event, you first check to see whether the wizard is currently on the step
where the user makes a choice. If so, check to see which RadioButton control is selected. If the user has selected No, advance
the Wizard control's ActiveStepIndex property to skip the wizard step that requests the user's e-mail address.
To add code to skip the third step
1. Click the Wizard control. In the Properties window, type Wizard1_NextButtonClick for the NextButtonClick property
and press ENTER.
The code editor window opens to the code-behind page.
2. Add the following highlighted code that checks for the correct step, determines which RadioButton control is selected,
and determines whether to skip step 3 of the wizard.
VB
Private Sub Wizard1_NextButtonClick( ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.WizardNavigationEventArgs) _
Handles Wizard1.NextButtonClick
If Wizard1.ActiveStepIndex = 1 Then
If RadioButton1.Checked Then
' Collect e-mail address.
Wizard1.ActiveStepIndex = 2
Else
Wizard1.ActiveStepIndex = 3
End If
End If
End Sub

C#
void Wizard1_NextButtonClick(object sender,
System.Web.UI.WebControls.WizardNavigationEventArgs e)
{
if (Wizard1.ActiveStepIndex == 1)
{
if (RadioButton1.Checked)
// Collect ee-mail address.
{
Wizard1.ActiveStepIndex = 2;
}
else
{
Wizard1.ActiveStepIndex = 3;
}
}
}

Setting the ActiveStepIndex property causes the wizard to move directly to the specified step.
3. Save the file.
Testing the Ability to Skip a Step
To test skipping a wizard step programmatically
1. Display Default.aspx in Design view.
2. Open the Wizard Tasks menu on the control and select Step 1 from the Step drop-down list.
3. Press CTRL+F5 to run the page.
4. Type name and address information.
5. Click Next.
6. In Step 2, select the No check box.
7. Click Next.
You arrive at the completion step.
8. Use your browser's back button to return to the first step, or close the browser and press CTRL+F5 to run the page again.
9. Type name and address information in the first step.
10. Click Next.
11. In Step 2, select the Yes check box.
12. Click Next.
13. You arrive at the e-mail address collection step.
14. Type an e-mail address.
15. Click Next.
16. You arrive at the completion step.
Next Steps
The Wizard control simplifies the creation of forms to gather user data. In addition to what has been covered here, you might
have other questions related to forms as well as to applying a different look and feel to your Wizard control. For example, you
might want to:
Override the Wizard control's default text labels. For details, see Wizard Web Server Control Overview
Validate the user's entries in the Wizard control. For details, see
Walkthrough: Validating User Input in a Web Forms Page
Learn more about basic Wizard control operation. For details, see
Walkthrough: Creating a Basic ASP.NET Wizard Control.
See Also
Reference
Wizard Web Server Control Overview
Visual Web Developer

XML Web Server Control (Visual Studio)


An Xml Web server control reads XML and writes it into a Web Forms page at the location of the control. If an XSL
transformation (XSLT) is applied to the XML, the resulting transformed output will be rendered in the Web Forms page.
The following topics provide information that you will find useful in learning to work with the XML Web server control.
In This Section
XML Web Server Control Overview
Walkthrough: Displaying an XML Document in a Web Forms Page Using Transformations
How to: Add XML Web Server Controls to a Web Forms Page (Visual Studio)
How to: Load XML Data in the XML Web Server Control
How to: Transform XML Data in the XML Web Server Control
See Also
Other Resources
Individual Web and HTML Controls
XmlDataSource Web Server Control
ASP.NET

XML Web Server Control Overview


You can use the XML Web server control to write an XML document, or the results of an XSLT transformation, into a Web page.
The XML output appears in the Web page at the location of the control.
Note
To use XML data as the source for other controls, such as the Repeater, DataList, or GridView controls, you can use the
XmlDataSource control. For details, see XmlDataSource Web Server Control.

The XML and the XSLT information can be in external documents, or you can include the XML inline. There are two ways to
reference external documents using property settings in the XML Web server control. You can provide a path to the XML
document in the control tag, or you can load the XML and XSLT documents as objects and then pass them to the control. If you
prefer to include the XML inline, write it between the opening and closing tags of the control.
See Also
Reference
XML Web Server Control Overview
Visual Web Developer

Walkthrough: Displaying an XML Document in a Web Forms


Page Using Transformations
This walkthrough illustrates how to display information on a Web page from an XML document. In the walkthrough, you will
create a simple XML file and then use an ASP.NET server control and an XSLT transformation to render the contents of the XML
file directly on the Web page.
Note
You can also use an XML file as a data source and display its contents using controls such as the GridView control. For details
, see Walkthrough: Creating a Web Page to Display XML Data.

To display XML information on a Web page, you need to provide formatting and display information — for example, you need
to provide the <TABLE> tags, <P> tags, or whatever you want to use to display the information. In addition, you must provide
instructions for how the data from the XML file fits into these tags. For example, should each element in the XML file be
displayed as a table row?
One way to provide these instructions is to create an ASP.NET Web page and then use code to parse the XML file and fill the
data into the appropriate HTML tags. Although this is a somewhat time-consuming and inflexible way to do this, it is also a
powerful way that gives you precise programmatic control over the XML file.
A better way is to use the XSL transformation language and create transformations, or XSL files. An XSL transformation
contains the following information:
A template — basically, an HTML page with the appropriate tags — that specifies how the XML information should be
displayed.
XSL processing instructions, which specify exactly how the information from the XML file fits into the template.
You can define multiple transformations and then apply them to the same XML file. By doing so, you can use the XML
information different ways, displaying it differently, selecting different data from the XML file, and so on.
Once you have XSL transformations, you need to apply them to the XML file — that is, you process the XML file by
transforming it according to one of the XSL files. The output is a new file with the XML information formatted according to the
transformation file.
Again, this is a process you can perform programmatically. However, you can also take advantage of the Xml server control.
(For an overview, see XML Web Server Control.) This control works as a placeholder on your Web Forms page. You can set its
properties to a specific XML file and XSL transformation, and when the page is processed, the control reads the XML, applies
the transformation, and displays the results.
For more information about XSL, see XSLT Transformations with the XslTransform Class.
This walkthrough will illustrate how to use the Xml server control to display XML information using XSL transformations. The
scenario is simple. You will have the following:
An XML file containing several fictional e-mail messages.
Two XSL transformations. One displays only the date, sender, and subject of the e-mail messages. The other displays the
entire e-mail message.
Note
All these files are provided as part of the walkthrough.

You will create a Web page that allows users to display the XML information two different ways. The page contains a Headers
only check box that is selected by default; the default transformation, therefore, is the one that displays only the e-mail
message headers. If users clear the check box, the XML information is redisplayed with the complete e-mail messages.
Prerequisites
In order to complete this walkthrough, you will need:
Microsoft Visual Web Developer.
The .NET Framework.
Creating a Web Site and Page
In this part of the walkthrough, you will create a Web site and add a new page to it. For this walkthrough, you will create a
file system Web site that does not require that you work with Microsoft Internet Information Services (IIS). Instead, you will
create and run your page in the local file system.
To create a file system Web site
1. Open Visual Web Developer.
2. From the File menu, choose New Web Site.
3. Under Visual Studio installed templates, select ASP.NET Web Site.
4. In the Location box, select File System and enter the name of the folder where you want to keep the pages of your Web
site.
For example, type the folder name C:\WebSites.
5. In the Language list, click Visual Basic or Visual C#.
6. Click OK.
Adding the XML File and XSL Transformations
In this part of the walkthrough, you will create an XML file and two XSLT files.
To add the XML file to your project
1. In Solution Explorer, right-click the App_Data folder, and then click Add New Item.
Note
When you put the XML file into the App_Data folder, it automatically has the correct permissions to allow ASP.NET to r
ead and write to the file at run time. In addition, it protects the file from being viewed in a browser, because the App_D
ata folder is marked as non-browsable.

2. Under Visual Studio installed templates, click XML file.


3. In the Name box, type Emails.xml.
4. Click Add.
A new XML file is created that contains only the XML directive.
5. Copy the following XML data, and then paste it into the file, overwriting what is already in the file.

<?xml version="1.0" ?>


<MESSAGES>
<MESSAGE id="101">
<TO>JoannaF</TO>
<FROM>LindaB</FROM>
<DATE>04 September 2001</DATE>
<SUBJECT>Meeting tomorrow</SUBJECT>
<BODY>Can you tell me what room the committee meeting will be in?</BODY>
</MESSAGE>
<MESSAGE id="109">
<TO>JoannaF</TO>
<FROM>JohnH</FROM>
<DATE>04 September 2001</DATE>
<SUBJECT>I updated the site</SUBJECT>
<BODY>I've posted the latest updates to our internal Web site, as you requested.
Let me know if you have any comments or questions. -- John
</BODY>
</MESSAGE>
<MESSAGE id="123">
<TO>JoannaF</TO>
<FROM>LindaB</FROM>
<DATE>05 September 2001</DATE>
<SUBJECT>re: Meeting tomorrow</SUBJECT>
<BODY>Thanks. By the way, do not forget to bring your notes from the conference.
See you later!</BODY>
</MESSAGE>
</MESSAGES>

6. Save the file and close it.


Next, you will add two XSL transformations to your project.
To add XSL transformations to your project
1. In Solution Explorer, right-click the App_Data folder, and then click Add New Item.
2. Under Visual Studio installed templates, click Text File.
There is no template for a transformation file, so you can create it as a text file with the correct extension.
3. In the Name box, type Email_headers.xslt.
Note
Be sure to use the .xslt extension.

4. Click Add.
A new blank file is created.
5. Copy the following example code and paste it into the file.

<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<HTML>
<BODY>
<TABLE cellspacing="3" cellpadding="8">
<TR bgcolor="#AAAAAA">
<TD class="heading"><B>Date</B></TD>
<TD class="heading"><B>From</B></TD>
<TD class="heading"><B>Subject</B></TD>
</TR>
<xsl:for-each select="MESSAGES/MESSAGE">
<TR bgcolor="#DDDDDD">
<TD width="25%" valign="top">
<xsl:value-of select="DATE"/>
</TD>
<TD width="20%" valign="top">
<xsl:value-of select="FROM"/>
</TD>
<TD width="55%" valign="top">
<B><xsl:value-of select="SUBJECT"/></B>
</TD>
</TR>
</xsl:for-each>
</TABLE>
</BODY>
</HTML>
</xsl:template>
</xsl:stylesheet>

Note
You can adjust this template as you like; for example, you might change colors, font sizes, styles, or other features.

6. Save the file and close it.


7. Repeat steps 1 through 4, but this time name the file Email_all.xslt.
8. Paste the following example code into the Email_all.xslt file.

<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<HTML>
<BODY>
<FONT face="Verdana" size="2">
<TABLE cellspacing="10" cellpadding="4">
<xsl:for-each select="MESSAGES/MESSAGE">
<TR bgcolor="#CCCCCC">
<TD class="info">
Date: <B><xsl:value-of select="DATE"/></B><BR></BR>
To: <B><xsl:value-of select="TO"/></B><BR></BR>
From: <B><xsl:value-of select="FROM"/></B><BR></BR>
Subject: <B><xsl:value-of select="SUBJECT"/></B><BR></BR>
<BR></BR><xsl:value-of select="BODY"/>
</TD>
</TR>
</xsl:for-each>
</TABLE>
</FONT>
</BODY>
</HTML>
</xsl:template>
</xsl:stylesheet>

9. Save the file and close it.


Adding the Xml Control to the Page
Now that you have an XML file and two transformations, you can use them to display information in a Web page. You do so
using an Xml server control.
To add an Xml control
1. Open or switch to the Default.aspx page.
2. Switch to Design view.
3. From the Standard tab of the Toolbox, drag an Xml control onto the page.
A gray box representing the Xml control is added to the page.
4. Select the control, and in the Properties window, set the following properties.
Property Setting
DocumentSource ~/App_Data/Emails.xml
TransformSource ~/App_Data/Email_headers.xslt

This will cause the Xml control to display only the e-mail message headers by default.
Adding Controls to Change Transformations
In this part of the walkthrough, you will use a check box to allow users to switch between transformations. The Xml control
currently applies a transformation that displays only the e-mail message headers.
To add a check box to apply a different transformation
1. Move the insertion point in front of the Xml control and then press ENTER a few times to make space above the Xml
control.
2. From the Standard tab of the Toolbox, drag a CheckBox control onto the form above the Xml control.
3. Set the following properties of the CheckBox control.
Property Setting
Text Headers only

Checked True

AutoPostBack TrueThis causes the form to be posted and is processed as soon as the user clicks the check box.

4. Double-click the CheckBox control.


The code editor opens with a handler for the CheckBox control's CheckChanged event called
CheckBox1_CheckedChanged.
5. Add code that switches transformations between Email_headers.xslt and Email_all.xslt, depending on the state of the
check box. The entire CheckChanged handler should look like the following code example.
VB
Protected Sub CheckBox1_CheckedChanged(ByVal sender As System.Object, ByVal e As Syste
m.EventArgs) Handles CheckBox1.CheckedChanged
If CheckBox1.Checked Then
Xml1.TransformSource = "~/App_Data/email_headers.xslt"
Else
Xml1.TransformSource = "~/App_Data/email_all.xslt"
End If
End Sub

C#
protected void CheckBox1_CheckedChanged(object sender, System.EventArgs e)
{
if (CheckBox1.Checked)
{
Xml1.TransformSource = "~/App_Data/email_headers.xslt";
}
else
{
Xml1.TransformSource = "~/App_Data/email_all.xslt";
}
}

Testing
You can now see the transformations in action.
To test the transformations
1. Press CTRL_F5 to run the page.
By default, you will see the date, sender, and subject line of the e-mail messages.
2. Clear the Headers only check box.
The e-mail messages are redisplayed, this time with a different layout and complete text.
Next Steps
This walkthrough has illustrated only the basics of how to work with an XML document and transformations. In a real
application, you will often need to work with the XML document in more depth. The following are suggestions for further
investigation:
Create more sophisticated transformations. In this walkthrough, you have seen only one example of how you can use
transformations. XSL is a powerful language, with sophisticated support not just for creating HTML pages, but also for
virtually any kind of transformation from XML to another structure.
Apply transformations programmatically. In this walkthrough, you took advantage of the Xml Web server control to do
the work of applying transformations to the raw XML data. You might find it useful in your application to do this work
yourself, for example if it is impractical in your application to use an Xml control. For details, see
XSLT Transformations with the XslTransform Class.
Write XML documents, instead of simply reading them. The Xml control makes it easy to display the contents of an XML
file in an ASP.NET Web page. However, you might want to create or amend XML files yourself. For details, see
XML Documents and Data. For an example of writing to an XML file, see
Walkthrough: Displaying and Tracking Advertisements with the AdRotator Control.
See Also
Other Resources
XML Web Server Control (Visual Studio)
Visual Web Developer

How to: Add XML Web Server Controls to a Web Forms Page
(Visual Studio)
Add XML Web server controls to the place in the page where you want the output to appear.
To add an XML Web server control to a Web Forms page
1. From the Standard tab of the Toolbox, drag an Xml control onto the page.
2. Load the XML data that you want to display into the control by setting the Document or DocumentSource property, or by
putting the XML between the control's opening and closing tags. For details, see
How to: Load XML Data in the XML Web Server Control.
Note
Make sure that when your application runs, it has the appropriate permissions to read the XML file. For details, see
ASP.NET Authorization.

To add an XML Web server control to a Web Forms page programmatically


1. Create an instance of the Xml control and set its properties, as shown in the following code example:
VB
Dim myXML As System.Web.UI.WebControls.Xml = _
New System.Web.UI.WebControls.Xml()
myXML.DocumentSource = "SourceDoc.xml"
myXML.TransformSource = "SourceTrans.xsl"

C#
System.Web.UI.WebControls.Xml myXML =
new System.Web.UI.WebControls.Xml();
myXML.DocumentSource = "SourceDoc.xml";
myXML.TransformSource = "SourceTrans.xsl";

2. Add the new control to the Controls collection of a container that is already on the page, as shown in the following code
example:
VB
PlaceHolder1.Controls.Add(myXML)

C#
PlaceHolder1.Controls.Add(myXML);

Note
Controls that you add dynamically to a Web Forms page do not automatically become part of the page's view state —
neither the controls nor their values are saved when a page performs a round trip to the server. You are therefore resp
onsible for saving the state of any dynamically-generated controls whose values you want to preserve. For details, see
ASP.NET State Management Overview.

See Also
Reference
XML Web Server Control Overview
ASP.NET

How to: Load XML Data in the XML Web Server Control
There are three ways to load XML data into the XML Web server control:
Provide a path to an external XML document, using the DocumentSource property.
Load an XML document as an XmlDocument object and pass it to the control, using the Load method event and
assigning the document to the Document property of the XML control.
Include the XML content inline, between the opening and closing tags of the control.
To provide a path to an external XML document
1. Add an XML control to the Web Forms page.
2. Set the DocumentSource property of the control to the path to the XML source document.
Note
You need to be sure that when your application runs, it has sufficient permissions to read the XML file.

The XML document will be written directly to the output stream unless you also specify the TransformSource property.
TransformSource must be a valid XSL Transformations document, which will be used to transform the XML document
before its contents are written to the output stream. The following code example shows how to refer to source
documents by using a relative path.

<body>
<h3>XML Example</h3>
<form runat=server>
<asp:Xml id="Xml1" DocumentSource="MySource.xml"
TransformSource="MyStyle.xsl" runat="server" />
</form>
</body>

To load an XML document as an object and pass it to the control


1. Add an XML control to the Web Forms page.
2. Add code to load the XML source document, and assign the source to the Document property of the control. For
example:
VB
Private Sub Page_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
Dim doc As System.Xml.XmlDocument = New System.Xml.XmlDocument()
doc.Load(Server.MapPath("MySource.xml"))
Dim trans As System.Xml.Xsl.XslTransform = _
New System.Xml.Xsl.XslTransform
trans.Load(Server.MapPath("MyStyle.xsl"))
Xml1.Document = doc
Xml1.Transform = trans
End Sub

C#
private void Page_Load(object sender, System.EventArgs e)
{
System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
doc.Load(Server.MapPath("MySource.xml"));
System.Xml.Xsl.XslTransform trans = new
System.Xml.Xsl.XslTransform();
trans.Load(Server.MapPath("MyStyle.xsl"));
Xml1.Document = doc;
Xml1.Transform = trans;
}

To include the XML content inline


1. Add an XML control to the Web Forms page.
2. Find the <asp:Xml> and </asp:Xml> tags.
3. Add your XML code between these two tags. For example:

<asp:xml TransformSource="MyStyle.xsl" runat=server>


<clients>
<name>Frank Miller</name>
<name>Judy Lew</name>
</clients>
</asp:xml>

See Also
Reference
XML Web Server Control Overview
ASP.NET

How to: Transform XML Data in the XML Web Server Control
An XSL transformations (XSLT) style sheet (.xslt or .xsl file) is used to transform the content of a source XML document into a
presentation that is tailored specifically to a particular user, media, or client. There are two ways to transform XML data in the
XML Web server control:
Point to an external .xslt file, which will automatically apply the transformation to the XML document.
Apply a transformation that is an object of type XslTransform to the XML document.
Both methods have the same results, and your choice is dependent primarily on what is most convenient in your application. If
the transformation is in the form of an .xsl or .xslt file, it is easy to load the file. If the transformation is in the form of an
object — perhaps it is being passed to your application by another process — then you can apply it as an object.
Note
The XslTransform class also allows you to load an .xsl or .xslt file into the instance of the transformation.

To apply a transformation from a file


1. Add an XML control to the Web Forms page.
2. Set the XML control's TransformSource property to the path to the XSLT document.
Note
You need to be sure that when your application runs, it has sufficient permissions to read the XML file.

The following code example shows how you can apply a transformation from a file to an XML control called Xml1.

VB
Xml1.TransformSource = "mystyle.xsl"

C#
Xml1.TransformSource = "mystyle.xsl";

To apply a transformation from an XslTransform object


1. Create an instance of the XslTransform class.
2. Set the XML control's Transform property to the instance of the transformation.
The following code example shows how you can create an instance of the transformation class and use it to apply the
transformation to an object. In this example, both the XML document and the transformation are read from files, but in a
real application, both objects might come from another component. The transformation is applied as soon as the page
loads.
VB
Private Sub Page_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
Dim doc As System.Xml.XmlDocument = New System.Xml.XmlDocument()
doc.Load(Server.MapPath("MySource.xml"))
Dim trans As System.Xml.Xsl.XslTransform = _
New System.Xml.Xsl.XslTransform
trans.Load(Server.MapPath("MyStyle.xsl"))
Xml1.Document = doc
Xml1.Transform = trans
End Sub
C#
private void Page_Load(object sender, System.EventArgs e)
{
System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
doc.Load(Server.MapPath("MySource.xml"));
System.Xml.Xsl.XslTransform trans = new
System.Xml.Xsl.XslTransform();
trans.Load(Server.MapPath("MyStyle.xsl"));
Xml1.Document = doc;
Xml1.Transform = trans;
}

See Also
Reference
XML Web Server Control Overview
ASP.NET

Securing Standard Controls


The ASP.NET standard controls are a group of controls that enable you to create forms in which users can type or select
information before a page is posted back to the server. Standard controls are Web server controls that inherit from the Control
class. Examples of Web server controls include the TextBox, Image, and AdRotator controls. The information in this topic
describes configuration and coding best practices that will help you improve the security of standard controls.
While following coding and configuration best practices can help improve the security of your application, it is also important
that you continually keep your application server up to date with the latest security updates for Microsoft Windows and
Internet Information Services (IIS), as well as any security updates for Microsoft SQL Server or other data sources.
More detailed information about best practices for writing secure code and securing applications can be found in the book
"Writing Secure Code" by Michael Howard and David LeBlanc, or through the guidance provided by
Microsoft Patterns and Practices.
Information about special security practices for other types of controls is also available in the following topics:
Securing Login Controls
Securing Web Parts Pages
Securing Data Access
AdRotator Control
The AdRotator control displays advertisements defined in an advertisement file, which by default is an XML file. Alternatively,
you can store advertisements in a database and extract them programmatically. To help secure the AdRotator control, follow
these guidelines:
If you are using an XML file to store advertisement information, place the file in the Web site's App_Data folder, because
the contents of the folder will not be served in response to Web requests.
For extra protection, do not use the .xml file name extension on advertisement files. Instead, use an extension such as
.ads, and then map the .ads extension to ASP.NET in IIS and to the forbidden handler in ASP.NET using the following
element in the site's Web.config file:

<httpHandlers>
<add verb="*" path="*.ads" type="System.Web.HttpForbiddenHandler" />
</httpHandlers>

For information on how to map a file name extension to ASP.NET in IIS, see How to: Register HTTP Handlers.
Set appropriate permissions (typically read-only) for the user account or accounts that will be reading the advertisement
file. If the Web site supports anonymous access, this is usually the local ASPNET user account or the NETWORK SERVICE
account.
If the advertisement file does not exist, the AdRotator control raises an error that displays the path and name of the file,
which reveals potentially sensitive information. Avoid this problem by following proper error-handling techniques,
including setting the customErrors element in the configuration file to redirect to a custom error page and creating a
global error handler that is called if an unhandled exception occurs anywhere in the application. For details, see
How to: Display Safe Error Messages.
If you are reading advertisement information from a database, follow the guidelines for securing access to the database.
For details, see Securing Data Access.
Carefully examine any advertisement information that you get from an untrusted source before using it with the
AdRotator control. Because the AdRotator control does not perform any validation or check the information it reads
from the advertisement file, it renders images and URLs to the Web page exactly as they appear in the ad file or database.
BulletedList, CheckBoxList, RadioButtonList, DropDownList, ListBox
The BulletedList, CheckBoxList, DropDownList, ListBox, and RadioButtonList controls render different types of HTML elements
(ul, input, and select) based on the contents of collections or on data in a database. To help secure these controls, follow these
guidelines:
If the controls read from a database, follow the guidelines for securing access to the database. For details, see
Securing Data Access.
If you are unsure whether the information to be displayed contains script or other markup, handle the control's
DataBinding event and HTML-encode the information before displaying it. For details, see
How to: Protect Against Script Exploits in a Web Application by Applying HTML Encoding to Strings.
If the BulletedList control is configured to display graphics or hyperlinks, make sure that the URL for the graphic or link
points to a trusted location.
Calendar Control
The Calendar control renders LinkButton controls to enable navigation in the calendar. LinkButton controls use client script to
perform a postback. If a browser has turned off client script for security purposes, the Calendar control will not support
navigation.
You can always use the Calendar control to display dates, even if you are not using it to enable date navigation. Do not
assume that any selected dates in a Calendar control are formatted correctly. When converting dates from the Calendar
control to an internal DateTime format, be sure to use appropriate error handling in case the date is not in the correct format.
FileUpload Control
The FileUpload control enables users to upload a file from their computer to the Web server computer. To help secure the
FileUpload control, follow these guidelines:
Do not trust files that are uploaded by users; malicious users might try to upload executable files. When you save an
uploaded file, check its file name extension or assign your own extension to the file.
Do not allow users to specify an arbitrary path for the location to save the uploaded file. Check that the name of the file
does not contain path information that you have not added yourself.
Do not reveal the internal structure of your Web site to users who are uploading files.
Set read/write permissions for the user account or accounts that will be running the application on the folder or folders
where the uploaded files will be saved. If the Web site supports anonymous access, this is generally the local ASPNET
user account or the NETWORK SERVICE account. However, limit read/write permissions to only the folder or folders
where the application stores uploaded files.
Guard against denial-of-service attacks by setting the maxRequestLength attribute of the httpRuntime element in the
configuration file. By default, the maximum request length is 4 megabytes (MB). Other configuration settings that can
affect the size of uploaded files are the requestLengthDiskThreshold attribute of the httpRuntime element and the
memoryLimit attribute of the processModel element.
Determine the size of the uploaded file by querying the ContentLength property of the HttpPostedFile object returned by
the control, and use the size to decide whether to accept the file.
HiddenField Control
The HiddenField control provides you with a way to set the contents of HTML <input type="hidden"> elements in server
code. Hidden fields are used to store information in the page that is useful during page processing but should not be seen by
users. To help secure the HiddenField control, follow these guidelines:
Do not store sensitive information in HiddenField controls. Although the information is not visible in the browser, it is
part of the page and users can easily view it in the page's source.
Do not trust information in hidden fields. Malicious users can tamper with the content of hidden fields.

Hyperlink
The Hyperlink control renders a URL to the browser. Be sure that the URL points to a trusted location.
Image and ImageMap Controls
To display graphics, the Image and ImageMap controls render a URL to the browser. Be sure that the URL points to a trusted
location.
ImageButton Control
The ImageButton control renders an image (img element) that uses client script to perform a postback. If a browser has turned
The ImageButton control renders an image (img element) that uses client script to perform a postback. If a browser has turned
off client script for security purposes, the control will not function.
To display the graphic, the control renders a URL to the browser. Be sure that the URL points to a trusted location.
Label and Literal Controls
The Label and Literal controls display text on the page by passing it through to the browser as-is. (The Label control
additionally enables you to specify formatting.) If the text contains HTML markup, by default the browser will interpret the
markup and render the text accordingly, which might include running scripts.
If you are using the Label control and are unsure whether the text might contain malicious content, use HTML encoding to
convert the HTML to its text representation. For details, see
How to: Protect Against Script Exploits in a Web Application by Applying HTML Encoding to Strings.
If you are using the Literal control and are unsure whether the text might contain malicious content, do one of the following:
Set the control's LiteralMode property to Encode, which automatically encodes HTML content.
Use HTML encoding to convert the HTML to its text representation. For details, see
How to: Protect Against Script Exploits in a Web Application by Applying HTML Encoding to Strings.
For more information, see How to: Protect Against Script Exploits in a Web Application by Applying HTML Encoding to Strings.
LinkButton Control
The LinkButton control renders a link (a element) that uses client script to perform a postback. If a browser has turned off
client script for security purposes, the control will not function.
MultiView
The MultiView control enables you to add multiple View controls and display them conditionally. This gives you the ability to
create pages that look like multi-page forms.
If you switch views based on something that can be easily tampered with, such as a URL query string, you could enable
someone to see a view that they are not supposed to see. Therefore, be sure that the mechanisms for switching views are as
secure as possible. For more information, see ASP.NET State Management.
TextBox Control
Because the TextBox control allows users to enter almost any text into the page, you must be careful when accepting user
input with this control. To help secure the TextBox control, follow these guidelines:
Use validation controls whenever possible to limit the users' input to acceptable values. For details, see
Introduction to the Validation Controls.
Ensure that the IsValid property is set to true before running your server code.
Use redundant server validation. This is especially true for CustomValidator controls; do not create only client-side
validation logic.
Set the TextBox control's MaxLength property to limit the quantity of text that users can enter. Malicious users can affect
the performance of your application and potentially cause database errors by sending huge quantities of information in a
text box.
Encode user input with the HtmlEncode method, which turns HTML into its text representation (for example, <b> becomes
&ltb&gt;), and which helps prevent the HTML from being executed in a browser. For details, see
How to: Protect Against Script Exploits in a Web Application by Applying HTML Encoding to Strings.
Set the TextMode property to Password to prevent the contents of the text box from being viewed in the text box (by
displaying dots). Note that setting the TextMode property to Password provides no other protection; the contents of the
text box are not encrypted or otherwise obfuscated, and the information is sent to the server as clear text. Therefore,
when using Password, provide additional methods for ensuring that data is secured.
If you are collecting sensitive information, such as a password or credit card number, use Secure Sockets Layer (SSL) to
secure communication between the client and server. This applies to any use of TextBox controls, including controls that
incorporate TextBox controls, such as the CreateUserWizard control.
Wizard
The Wizard control enables you to create multi-step entry forms. Be aware of the following security considerations when using
the Wizard control:
The Wizard does not inherently protect sensitive information. If you are collecting sensitive data in the wizard, use SSL to
secure communication between the client and server for the page containing the Wizard.
To support its functionality, the Wizard control includes a number of non-visible controls. A user can potentially
manipulate those controls and their values to display wizard steps out of order or to display wizard steps that should be
displayed to only some users. To help prevent this, ensure that wizard steps are displayed in the correct order, and that
steps with sensitive information are not displayed unless the correct conditions apply.

XML Control
The Xml control displays the contents of an XML file or string containing XML on a page, optionally applying an XML
transformation. To help secure the Xml control, follow these guidelines:
When you are displaying the contents of an XML file, if practical, place the XML file in the in your site's App_Data folder
because the contents of the folder will not be served in response to Web requests.
Display XML only from trusted sources.
Use transformations only from trusted sources.

See Also
Concepts
Securing Login Controls
Securing Web Parts Pages
Securing Data Access
Visual Web Developer

Data Toolbox Controls


The topics in this section describe how to work with ASP.NET Web server controls that appear on the Data tab of the Visual
Web Developer toolbox. These include data source controls that enable you to use a Web control to access data in a database,
as well as formatting controls that enable you to display and manipulate data on an ASP.NET Web page.
For complete syntax information for Web server controls, see Web Server Control Syntax.
In This Section
Data Web Server (ASP.NET) Controls (Visual Studio)
Data Source Web Server Controls (Visual Studio)
See Also
Other Resources
ASP.NET Data Access (Visual Studio)
Individual Web and HTML Controls
ASP.NET Web Server Controls (Visual Studio)
ASP.NET Web Pages (Visual Studio)
Visual Web Developer

Data Web Server (ASP.NET) Controls (Visual Studio)


This section contains topics that describe the ASP.NET controls you can use to display data on a Web page.
For complete syntax information for Web server controls, see Web Server Control Syntax.
In This Section
ASP.NET Data-Bound Web Server Controls Overview
GridView Web Server Control (Visual Studio)
DetailsView Web Server Control (Visual Studio)
FormView Web Server Control (Visual Studio)
Repeater Web Server Control (Visual Studio)
DataList Web Server Control (Visual Studio)
See Also
Other Resources
Data Toolbox Controls
ASP.NET Data Access (Visual Studio)
ASP.NET

ASP.NET Data-Bound Web Server Controls Overview


Data-bound Web server controls are controls that can be bound to a data source control to make it easy to display and modify
data in your Web application. Data-bound Web server controls are composite controls that combine other ASP.NET Web
controls, such as Label and TextBox controls, into a single layout.
For example, a data-bound control such as a DetailsView control can bind to a set of results such as a table of employees
containing each employee's name, address, job title, and so on. Within the DetailsView control, you can bind Label controls to
a single data values such as the name or address field to create the data layout in the page.
In addition to enabling you to bind the control to a set of data results, data-bound controls enable you to customize the layout
of the control using templates. They also provide a convenient model for handling and canceling events.
This topic discusses how data Web server controls bind to data as well as the data-bound controls that are included with
ASP.NET.
Binding a Data-bound Web Server Control to Data
You can work with a data-bound control by binding it to a data source control such as an ObjectDataSource or SqlDataSource
control. The data source control connects to a data source such as a database or middle-tier object and then retrieves or
updates data. The data-bound control can then use this data. To perform the binding, you set the data-bound control's
DataSourceID property to point to a data source control. When a data-bound control is bound to a data source control, little or
no additional code is required for data operations, because the data-bound control can automatically take advantage of the
data services provided by the data source control.
Note
In previous versions of ASP.NET, data-bound controls were bound to data using the DataSource property and required you t
o write code to handle operations such as displaying, paging, sorting, editing, and deleting data. Although you can still bind c
ontrols to data using the DataSource property (and use existing code), you can now performing binding using the DataSou
rceID property instead.

For more information about data source controls, see Data Source Web Server Controls.
GridView Control
The GridView control displays data as a table and provides the capability to sort columns, page through data, and edit or delete
a single record.
Note
The GridView control is the successor to the DataGrid control available in earlier versions of ASP.NET. Along with the added
ability to take advantage of the capabilities of data source controls, the GridView control offers improvements such as the a
bility to define multiple primary key fields, improved user interface customization using bound fields and templates, and a ne
w model for handling or canceling events.

For more information, see GridView Web Server Control and Comparing the GridView and DataGrid Web Server Controls.
DetailsView Control
The DetailsView control renders a single record at a time as a table and provides the capability to page through multiple
records, as well as to insert, update, and delete records. The DetailsView control is often used in master-detail scenarios
where the selected record in a master control such as a GridView control determines the record displayed by the DetailsView
control.
For more information, see DetailsView Web Server Control.
FormView Control
The FormView control renders a single record at a time from a data source and provides the capability to page through
multiple records, as well as to insert, update, and delete records, similar to the DetailsView control. However, the difference
between the FormView and the DetailsView controls is that the DetailsView control uses a table-based layout where each
field of the data record is displayed as a row in the control. In contrast, the FormView control does not specify a pre-defined
layout for displaying a record. Instead, you create templates that contain controls to display individual fields from the record.
The template contains the formatting, controls, and binding expressions used to lay out the form.
For more information, see FormView Web Server Control.
Repeater Control
The Repeater control renders a read-only list from a set of records returned from a data source. Like the FormView control,
the Repeater control does not specify a built-in layout. Instead you create the layout for the Repeater control using templates.
For more information, see Repeater Web Server Control.
DataList Control
The DataList control renders data as table and enables you to display data records in different layouts, such as ordering them
in columns or rows. You can configure the DataList control to enable users to edit or delete a record in the table. (The
DataList control does not take advantage of the capabilities of data source controls for modifying data; you must supply this
code yourself.) The DataList control differs from the Repeater control in that the DataList control explicitly places items in an
HTML table, where as the Repeater control does not.
For more information, see DataList Web Server Control.
See Also
Other Resources
ASP.NET Web Server Controls
Individual ASP.NET Web Server Controls
Data Source Web Server Controls
Visual Web Developer

GridView Web Server Control (Visual Studio)


The topics in this section describe how to work with the GridView control to select, sort, and edit the values of a data source,
and display them in a table on a Web page.
In This Section
Getting Started — GridView Web Server Control (Visual Studio)
Learning More — GridView Web Server Control (Visual Studio)
Walkthrough Topics — GridView Web Server Control (Visual Studio)
How-to Topics — GridView Web Server Control (Visual Studio)
See Also
Concepts
ASP.NET Web Server Controls Templates
Other Resources
Data Toolbox Controls
ASP.NET Data Access (Visual Studio)
Visual Web Developer

Getting Started — GridView Web Server Control (Visual Studio)


The topics below provide introductory information about using the GridView control to select, sort, and edit the values of a
data source, and display them in a table.
In This Section
GridView Web Server Control Overview
Comparing the GridView and DataGrid Web Server Controls
See Also
Other Resources
GridView Web Server Control (Visual Studio)
Data Toolbox Controls
ASP.NET Data Access (Visual Studio)
ASP.NET

GridView Web Server Control Overview


A recurring task in software development is to display tabular data. ASP.NET provides a number of tools for showing tabular
data in a grid, including the GridView control. With the GridView control, you can display, edit, and delete data from many
different kinds of data sources, including databases, XML files, and business objects that expose data.
Using the GridView you can:
Automatically bind to and display data from a data source control.
Select, sort, page through, edit, and delete data from a data source control.
Additionally, you can customize the appearance and behavior of the GridView control by:
Specifying custom columns and styles.
Utilizing templates to create custom user interface (UI) elements.
Adding your own code to the functionality of the GridView control by handling events.
Note
The GridView control is the successor to the DataGrid control. For details about differences between the controls, see
Comparing the GridView and DataGrid Web Server Controls.

Data Binding with the GridView Control


The GridView control provides you with two options for binding to data:
Data binding using the DataSourceID property, which allows you to bind the GridView control to a data source control.
This is the recommended approach because it allows the GridView control to take advantage of the capabilities of the
data source control and provide built-in functionality for sorting, paging, and updating.
Data binding using the DataSource property, which allows you to bind to various objects, including ADO.NET datasets
and data readers. This approach requires you to write code for any additional functionality such as sorting, paging, and
updating.
When you bind to a data source using the DataSourceID property, the GridView control supports two-way data binding. In
addition to the control displaying returned data, you can enable the control to automatically support update and delete
operations on the bound data.
For more information, see ASP.NET Data-Bound Web Server Controls Overview.
Formatting Data Display in the GridView Control
You can specify the layout, color, font, and alignment of the GridView control's rows. You can specify the display of text and
data contained in the rows. Additionally, you can specify whether the data rows are displayed as items, alternating items,
selected items, or edit-mode items. The GridView control also allows you to specify the format of the columns. For
information on formatting the GridView control, see the GridView class overview.
Editing and Deleting Data Using the GridView Control
By default, the GridView control displays data in read-only mode. However, the control also supports an edit mode in which it
displays a row that contains editable controls such as TextBox or CheckBox controls. You can also configure the GridView
control to display a Delete button that users can click to delete the corresponding record from the data source.
The GridView control can automatically perform editing and deleting operations with its associated data source, which allows
you to enable editing behavior without writing code. Alternatively, you can control the process of editing and deleting data
programmatically, such as in cases where the GridView control is bound to a read-only data source control.
You can customize the input controls that are used when a row is in edit mode using a template. For more information, see the
TemplateField class.
GridView Sorting Functionality
The GridView control supports sorting by a single column without requiring any programming. You can further customize the
sort functionality of the GridView control by using the sort event and providing a sort expression. For more information, see
Sorting Data in a GridView Web Server Control.
GridView Paging Functionality
The GridView control provides a simple paging functionality. You can customize the paging functionality of the GridView
control by using the PagerTemplate property of the GridView control. For more information, see
Paging in a GridView Web Server Control.
GridView Events
You can customize the functionality of the GridView control by handling events. The GridView control provides events that
occur both before and after a navigation or edit operation. For more information, see GridView Web Server Control Events.
See Also
Other Resources
GridView Web Server Control
ASP.NET

Comparing the GridView and DataGrid Web Server Controls


The GridView control is the successor to the DataGrid control. Like the DataGrid control, the GridView control was designed
to display data in an HTML table. When bound to a data source, the DataGrid and GridView controls each display a row from
a DataSource as a row in an output table.
Both the DataGrid and GridView controls are derived from the WebControl class. Although it has a similar object model to
that of the DataGrid control, the GridView control also has a number of new features and advantages over the DataGrid
control, which include:
Richer design-time capabilities.
Improved data source binding capabilities.
Automatic handling of sorting, paging, updates, and deletes.
Additional column types and design-time column operations.
A Customized pager user interface (UI) with the PagerTemplate property.
Differences between the GridView control and the DataGrid control include:
Different custom-paging support.
Different event models.
Improved Design-Time Capabilities
Sorting, paging, and in-place editing of data requires additional coding when using the DataGrid control. The GridView
control enables you to add sorting, paging, and editing capabilities without writing any code. Instead, you can automate these
tasks, along with other common tasks such as data binding to a data source, by setting properties on the control.
If you are working in a designer, such as Microsoft Visual Studio, you can take advantage of designer features built into the
GridView control. The GridView control includes support for a smart tag panel that provides a convenient interface for
performing common tasks, such as setting properties and launching template editing.
Improved Data Source Binding Capabilities
Typically a DataSet control, a DbDataReader control, or a collection, such as an Array, an ArrayList, or some other class in the
System.Collections namespace, is assigned to the DataSource property of either the DataGrid control or the GridView
control. The DataGrid control and the GridView control can bind any object that implements the IEnumerable or IListSource
interface.
While the DataGrid control can declaratively bind a DataSourceControl control, it can do so only for data selection. Sorting,
paging, updates, and deletions must be coded manually. The GridView control supports a DataSourceID property that takes
any object that implements the IDataSource interface and can, therefore, take advantage of the data source control's sorting,
paging, updating, and deleting capabilities, for example, the SqlDataSource control.
Additional Column Types
The GridView control supports the following column types: BoundField, HyperLinkField, ButtonField, CommandField
ImageField, and CheckBoxField.
Built-In and Custom Paging Support
The DataGrid control requires additional coding for paging. The GridView control automatically supports paging by setting
the PagerSettings property. The PagerSettings property supports four modes: Numeric (default), NextPrevious,
NumericFirstLast, and NextPreviousFirstLast. The Numeric mode displays numbered page links instead of "next/prev" links,
and the NumericFirstLast option adds first and last page links. The GridView control's PagerStyle property can be used to set
styles and the position of the pager.
Additionally, you can customize the pager buttons for the GridView control using a PagerTemplate.
Custom paging support in the GridView is supplied by the bound data source control as opposed to the AllowCustomPaging
mechanism supplied by the DataGrid control.
Expanded Event Model
The DataGrid and the GridView controls have different event models.
The DataGrid control raises single events for operations, while the GridView control is capable of both pre-operation and
post-operation events. The GridView control supports the Sorting event that occurs when a field is sorted. Note that this
sorting event occurs before the GridView control automatically handles the sort operation, giving you the opportunity to
examine or change the SortExpression property, or cancel this operation by setting the Cancel property to true on the passed
event arguments.
The GridView control supports the Sorted event that occurs after the GridView control completes the sort operation, giving
you the opportunity to change or format the result of the sort operation. In comparison, the DataGrid control supports the
SortCommand event that occurs when a column is sorted. Similarly, the GridView control supports RowUpdating and
RowUpdated events that occur before and after the GridView control has automatically handled the update operation. In
comparison, the DataGrid control supports the UpdateCommand event that occurs when the Update button is clicked for an
item in the grid.
For more information on GridView events, see GridView Web Server Control Events.
See Also
Concepts
Paging in a GridView Web Server Control
Modifying Data in a GridView Web Server Control
Walkthrough: Simple Sorting for the GridView Web Server Control
Visual Web Developer

Learning More — GridView Web Server Control (Visual Studio)


The topics listed below include step-by-step instructions for scenarios that use the GridView control to select, display, sort, and
edit the values of a data source.
In This Section
Walkthrough: Displaying Data Using a Stored Procedure in the GridView Web Server Control
Sorting Data in a GridView Web Server Control
Paging in a GridView Web Server Control
How to: Enable Default Selection in the GridView Web Server Control
Modifying Data in a GridView Web Server Control
How to: Enable Default Deleting in the GridView Web Server Control
GridView Web Server Control Events
Creating a Custom Column in a GridView Web Server Control
How to: Set GridView Web Server Control Column Width Dynamically
Walkthrough: Creating a Nested GridView Control
Walkthrough: Performing Bulk Updates to Rows Bound to a GridView Web Server Control
Reference
GridView
Overview of programming with the GridView class.
See Also
Other Resources
GridView Web Server Control (Visual Studio)
Data Toolbox Controls
ASP.NET Data Access (Visual Studio)
Visual Web Developer

Walkthrough: Displaying Data Using a Stored Procedure in the


GridView Web Server Control
This walkthrough shows you how to display data in the GridView control using a stored procedure. A stored procedure is an
SQL query stored in a Microsoft SQL Server database rather than in your application code. Stored procedures are more secure
than query code and often run faster. The SqlDataSource control, created by a wizard in this walkthrough, retrieves the results
of the stored procedure and acts as the data source for the GridView control. The GridView control examines the results and
creates rows and tables as needed to display the data.
During this walkthrough, you will learn how to:
Connect to a SQL Server database in Microsoft Visual Web Developer.
Use the SqlDataSource control to manage data access and binding.
Add a stored procedure to return data for display in the GridView control.
Display data returned from the stored procedure in the GridView control.
Prerequisites
In order to complete this walkthrough, you will need:
Visual Web Developer (Visual Studio).
Note
The Add New Stored Procedure feature used in this walkthrough is not supported by Visual Web Developer Express.

Microsoft Data Access Components (MDAC) version 2.7 or later.


If you are using Microsoft Windows XP or Windows Server 2003, you already have MDAC 2.7. However, if you are using
Microsoft Windows 2000, you might need to upgrade the MDAC already installed on your computer. For more
information, see "Microsoft Data Access Components (MDAC) Installation" in the MSDN Library.
Access to the SQL Server Northwind database. For information about downloading and installing the SQL Server sample
Northwind database, see Installing Sample Databases on the Microsoft SQL Server Web site.
Note
If you need information about how to log on to the computer running SQL Server, contact the server administrator.

Creating the Web Site


Create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New, and then click Web Site. If you are using Visual Web Developer Express, on the File menu,
click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the first Location box, select File System; in the second, enter the name of the folder where you want to keep the
pages of your Web site.
For example, type the folder name C:\WebSites\StoredProcedure.
5. In the Language list, click the programming language you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Adding a Stored Procedure to Return Data for Display in the GridView Control
To display data on an ASP.NET Web page, you need the following:
A connection to a data source (such as a database).
In the following procedure, you will create a connection to the SQL Server Northwind database.
A stored procedure that returns data for display.
A data source control on the page, which executes the stored procedure and manages the results.
A control on the page to display the data.
In the following procedure, you will display data in a GridView control. The GridView control will get its data from the
SqlDataSource control. The first step is to create a stored procedure.
To create a stored procedure to return data for display in the GridView control
1. In Server Explorer, right-click Data Connections, and then click Add Connection. If you are using Visual Web
Developer Express, use Database Explorer.
The Add Connection dialog box appears.
If the Data source list does not display Microsoft SQL Server (SqlClient), click Change, and in the Change Data
Source dialog box, select Microsoft SQL Server.
If the Choose Data Source dialog box appears instead of the Connection Properties dialog box, in the Data
source list, select the type of data source you will use. For this walkthrough, the data source type is Microsoft SQL
Server. In the Data provider list, click .NET Framework Data Provider for SQL Server, and then click Continue.
Note
If the Server Explorer tab is not visible in Visual Web Developer, in the View menu, click Server Explorer. In Visual W
eb Developer Express, in the View menu, click Database Explorer

2. In the Add Connection box, enter your server name in the Server Name text box.
3. For the Log on to the server section, select the appropriate option to access the running SQL Server database
(integrated security or specific ID and password) and, if required, enter a user name and password.
4. Select the Save my Password check box if you entered a password.
5. Under Select or enter a database name, enter Northwind.
6. Click Test connection, and when you are sure that it works, click OK.
Your new connection has been created under Data Connections in Server Explorer.
7. In Server Explorer, under Data Connections, expand the data connection you just created. If you are using Visual Web
Developer Express, use Database Explorer.
The data connection expands to include child connections, such as Tables, Views, and Stored Procedures.
8. Right-click Stored Procedures, and then click Add New Stored Procedure.
Note
The Add New Stored Procedure feature is not supported by Visual Web Developer Express.

9. Add the following code in the new stored procedure, overwriting any existing code.

CREATE PROCEDURE GetEmployees


AS
Select EmployeeID, LastName, FirstName from Employees
RETURN

10. Close the window and click Yes to create the stored procedure.
Note
The CREATE keyword changes to Alter when the procedure is saved.

Adding a GridView Control to Display Data


After you have established a connection to a data source, you need the following:
A data source control on the page, which executes the stored procedure and manages the results.
A control on the page to display the data.
In the following procedure, you will display data in a GridView control. The GridView control will get its data from the
SqlDataSource control.
You can add these elements to your Web site separately. However, it is easiest to begin by visualizing the data display with the
GridView control, and then using wizards to create the connection and data source control. The following procedure explains
how to create the elements that you need to display data on the page.
To add and configure a GridView control for displaying data
1. Switch to or open the Default.aspx page, and then switch to Design view.
2. In the Toolbox, from the Data group, drag a GridView control onto the page.
3. On the GridView Tasks menu, in the Choose Data Source list box, click New data source.
The Data Source Configuration Wizard dialog box appears.
4. Select Database, and then click OK.
This specifies that you want to get data from a SQL Server database.
In the Specify an ID for the data source box, a default data source control name is displayed (SqlDataSource1). Leave
this name.
The Configure Data Source SqlDataSource1 wizard displays a page where you can choose a connection.
5. In the Which data connection should your application use to connect to the database? list box, enter the
connection that you created in the previous procedure, and then click Next.
The wizard displays a page where you can choose to store the connection string in a configuration file. Storing the
connection string in the configuration file has two advantages:
It is more secure than storing it in the page.
You can use the same connection string in multiple pages.
6. Select the Yes, save this connection as check box, and then click Next.
The wizard displays a page where you can specify what data you want to retrieve from the database.
7. Select the Specify a custom SQL statement or stored procedure option, and then click Next.
8. On the Define Custom Statements or Stored Procedures page, select Stored Procedure, and then select the stored
procedure that you created (GetEmployees) earlier.
9. Click Next.
10. Click Test Query to confirm that you are getting the data you want.
11. Click Finish.
Testing the Page
You can now run the page.
To test the page
1. Press CTRL+F5 to run the page.
The page appears in the browser. The GridView control displays all the data rows from the Employees table.
2. Close the browser.

Next Steps
This walkthrough has illustrated how you can use a SQL Server stored procedure with a data source control to display data on
an ASP.NET Web page. You can use stored procedures in much the way you use any SQL statement when working with the
SqlDataSource control. Additionally, stored procedures can take parameters that you associated with values on the Web page.
Other scenarios you might want to explore with stored procedures are the ones listed here, which perform data-related
functions using SQL statements:
Walkthrough: Creating Master/Detail Web Pages in Visual Studio
Walkthrough: Editing and Inserting Data in Web Pages with the DetailsView Web Server Control
Walkthrough: Displaying a Drop-Down List While Editing in the GridView Web Server Control
Using Parameters with the SqlDataSource Control

See Also
Tasks
How to: Secure Connection Strings When Using Data Source Controls
Walkthrough: Displaying a Drop-Down List While Editing in the GridView Web Server Control
Walkthrough: Basic Data Access in Web Pages
ASP.NET

Sorting Data in a GridView Web Server Control


The GridView control provides built-in sorting functionality without requiring any coding. You can further customize the sort
functionality of the GridView control by using custom SortExpression property values for columns as well as by using the
Sorting and Sorted events.
How Sorting Works in the GridView Control
The GridView control does not perform its own sorting of columns, but rather relies on the data source control to perform
sorting on its behalf. The control provides the user interface (UI) for sorting, such as LinkButton controls displayed at the top of
each column of the grid. However, the GridView control relies on the data-sorting capabilities of the data source control to
which it is bound.
If the bound data source control can sort data, then the GridView control can interact with the data source control and request
sorted data by passing a SortExpression to the data source when data is selected. Not all data source controls support sorting;
for example, the XmlDataSource control does not. If the data source control supports sorting, however, the GridView can take
advantage of it. The following list describes data source controls and the configuration that is needed to support sorting:
The SqlDataSource and AccessDataSource controls can sort if the DataSourceMode property is set to DataSet, or the
SortParameterName property is set to either DataSet or DataReader.
The ObjectDataSource control can sort if its SortParameterName property is set to a value supported by the underlying
object.
GridView Sorting Process
You can enable the default sorting behavior in the GridView control by setting its AllowSorting property to true. Setting this
property to true causes the GridView control to render a LinkButton control in the column headers. The control also
implicitly sets the SortExpression property of each column to the name of the data field to which it is bound. For example, if
the grid contains a column that displays the City column of the Employees table in the Northwind sample database, the
SortExpression property of that column will be set to City.
At run time, users can click the LinkButton control in a column heading to sort by that column. Clicking the link causes the
page to perform a postback and raises the GridView control's Sorting event. The sort expression — by default, the name of
the data column — is passed as part of the event arguments. The default behavior for the Sorting event is that the GridView
control passes the sort expression to the data source control. The data source control executes its selection query or method,
including the sort parameters passed by the grid.
After the query has executed, the grid's Sorted event is raised. This event allows you to perform post-query logic, such as
displaying a status message. Finally, the data source control rebinds the GridView control to the results of the resorted query.
The GridView control does not check whether the data source control supports sorting; it always passes the sort expression to
the data source. If the data source control does not support sorting and a sorting operation is performed in the GridView
control, the GridView control throws the NotSupportedException exception. You can catch this exception in a handler for the
Sorting event and check the data source to determine whether sorting is supported, or by using your own sorting logic.
Controlling Sorting for Individual Columns
Setting the grid's AllowSorting property allows you to sort columns by default. You can disable sorting for individual fields
(the BoundColumn or TemplateColumn field) by setting the SortExpression property of the individual column to an empty
string ("").
Custom Sorting
If the default sort behavior is not adequate for your requirements, you can customize the grid's sorting behavior. The basic
technique for custom sorting is to handle the Sorting event. In the handler, you can do the following:
Customize the sort expression that is passed to the data source control. By default, the sort expression is the name of a
single column. You can modify the sort expression in the handler. For example, if you want to sort by two columns, you
can create a sort expression that includes both. You can then pass the modified sort expression to the data source control.
For more information, see the SortExpression property.
Create your own sorting logic. For example, if you are working with a data source that does not support sorting, you can
perform the sort in your own code and then bind the grid to the sorted data.
See Also
Concepts
ASP.NET Data-Bound Web Server Controls Overview
Visual Web Developer

Walkthrough: Simple Sorting for the GridView Web Server


Control
You can use the ASP.NET GridView control's built-in sort functionality to add single-column sorting to your data without
requiring any coding.
During this walkthrough, you will learn how to:
Enable the built-in sort functionality of the GridView control.
Prerequisites
In order to complete this walkthrough, you will need:
Microsoft Visual Web Developer (Visual Studio).
Access to the SQL Server Northwind database. For information about downloading and installing the SQL Server sample
Northwind database, see Installing Sample Databases on the Microsoft SQL Server Web site.
Note
If you need information about how to log on to the computer running SQL Server, contact the server administrator.

A user name and password for a SQL Server account that has access to the Northwind database.
Microsoft Data Access Components (MDAC) version 2.7 or later.
If you are using Microsoft Windows XP or Windows Server 2003, you already have MDAC 2.7. However, if you are using
Microsoft Windows 2000, you might need to upgrade the MDAC already installed on your computer. For more
information, see "Microsoft Data Access Components (MDAC) Installation" in the MSDN Library.
Creating the Web Site and Page
Create a new Web site by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New, and then click Web Site. If you are using Visual Web Developer Express, on the File menu,
click New Web Site.
The New Web Site dialog box is displayed.
3. Under Visual Studio installed templates, select ASP.NET Web Site.
4. In the Location box, select File System, and enter the name of the folder where you want to keep the pages of your Web
site.
For example, type the folder name C:\WebSites\SimpleSort.
5. In the Language list, click Visual Basic or Visual C#.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Displaying Data in the GridView Control
In this section, you will add a GridView control to the page and configure it to display data from the Customers table of the
Northwind database.
To display data in the GridView control
1. Switch to or open the Default.aspx file
2. Switch to Design view.
3. In the Toolbox, from the Data group, drag a GridView control onto the page.
4. On the GridView Tasks menu, in the Choose Data Source drop-down list, click <New data source>.
The Data Source Configuration wizard appears.
5. Click Database.
This specifies that you want to get data from a database that supports SQL statements, which includes SQL Server and
other OLE-DB–compatible databases.
6. In the Specify an ID for the data source box, a default data source control name, SqlDataSource1, is displayed. You
can leave this name.
7. Click OK.
The Configure Data Source wizard is displayed.
8. Click New Connection.
The Add Connection dialog box appears.
If the Data source list does not display Microsoft SQL Server (SqlClient), click Change, and in the Change Data
Source dialog box, select Microsoft SQL Server.
If the Choose Data Source page appears, in the Data source list, select the type of data source you will use. For
this walkthrough, the data source type is Microsoft SQL Server. In the Data provider list, click .NET Framework
Data Provider for SQL Server, and the click Continue.
9. In the Server name box, enter the name of your SQL Server computer.
10. In the Log on to the server section, select the option that is appropriate for your SQL Server configuration (Windows
Authentication or specific ID and password).
11. If they are required, enter a user name and password.
12. In the Select or enter a database name box, select Northwind.
13. Click the Test Connection button to test the connection. When you are sure that the connection has succeeded, click OK.
You are returned to the Configure Data Source - SqlDataSource1 wizard, where the connection information is filled
in.
14. Click Next.
The wizard displays a page where you can choose to store the connection string in the configuration file. Storing the
connection string in the configuration file has two advantages:
It is more secure than storing it in the page.
You can reuse the same connection string in multiple pages.
15. Be sure the Yes, save this connection as check box is selected, and then click Next. (You can leave the default
connection string name.)
The wizard displays a page where you can specify what data you want to retrieve from the database.
16. Under Specify columns from a table or view, in the Name drop-down list, select Customers.
17. Under Columns, select the CustomerID, CompanyName, and City check boxes.
The wizard displays the SQL statement that you are creating in a box at the bottom of the page.
Note
The wizard allows you to specify selection criteria (WHERE clauses) and other SQL query options. For this walkthrough,
you will create a simple statement with no selection or sort options.

18. Click Next.


19. Click Test Query to be sure that you are retrieving the data you want.
20. Click Finish.
The wizard creates a SqlDataSource control and adds it to the page. The GridView control you added earlier is bound to
the SqlDataSource control. If you view the properties for the SqlDataSource control, you will see that the wizard has
created values for the ConnectionString and SelectQuery properties.
21. Right-click the GridView control, click Show Smart Tag, and then, on the GridView Tasks menu, click Enable Sorting.
The column headings in the GridView control change to links.
You can now test the page.
To test the page
1. Press CTRL+F5 to run the page.
The GridView control is displayed with CustomerID, CompanyName, and City columns.
2. Click a column heading to sort by the contents of that column.
3. Click a column again to switch between ascending and descending sort order.
Next Steps
Consider enabling multi-column sorting for a GridView control as well. For more information, see
Sorting Data in a GridView Web Server Control.
See Also
Reference
GridView Web Server Control Overview
Concepts
Sorting Data in a GridView Web Server Control
ASP.NET

Paging in a GridView Web Server Control


The ASP.NET GridView control has a built-in paging capability that supports basic paging functionality. You can use the default
paging user interface (UI) or create a custom paging interface.
How Paging Works in the GridView Control
The GridView control supports paging over the items in its data source. You set the AllowPaging property to true to enable
paging. The GridView control supports paging in one of these ways:
1. If the GridView control is bound to a data source control that is capable of returning a single page of data when
requested, the GridView control will take advantage of that capability directly. The number of rows requested may vary
depending on the number of rows per page specified by the PageSize property, and whether the data source supports
getting the total row count.
Note
Of the data source controls that are included in the .NET Framework, only the ObjectDataSource control supports retur
ning a single page of data.

Note
If you are creating a data source (such as implementing a SelectCountMethod method in the source object for the Obje
ctDataSource control), it is strongly recommended that your data source return the total row count when supplying p
ages of data. This minimizes the number of records that the GridView control must request in order to retrieve a page
of data. If the total row count is supplied by the source data object, the GridView control will request only a page of ro
ws at a time. If the total row count is not supplied, the GridView control must request all rows from the data source (st
arting with the row that represents the requested page of data) and discard all rows except the row being displayed.

2. If the GridView control is bound to a data source control that does not support the paging capability directly, or if the
GridView control is bound to a data structure in code through the DataSource property, the GridView control will
perform paging by getting all of the data records from the source, displaying only the records for the current page, and
discarding the rest. This is supported only when the data source for the GridView control returns a collection that
implements the ICollection interface (including datasets).
Note
If the data source does not support paging directly and does not implement the ICollection interface, the GridView co
ntrol cannot page. For example, if you are using a SqlDataSource control and have set its DataSourceMode property to
DataReader, the GridView control cannot implement paging.

Customizing the Paging Settings and User Interface


You can customize the paging user interface of the GridView control in a number of ways. You can set the size of the page
(that is, the number of items to display at once) using the PageSize property. You can also set the current page of the
GridView control by setting the PageIndex property. You can specify more custom behavior using either the PagerSettings
property or by supplying a pager template.
Paging Modes
The PagerSettings property allows you to customize the appearance of the paging user interface (UI) that is automatically
generated by the GridView control when you set the AllowPaging property to true. The GridView control can display
direction controls that allow forward and backward navigation as well as numeric controls that allow a user to move to a
specific page.
The PagerSettings property of the GridView control is set to a PagerSettings class. You can customize the paging mode by
setting the Mode property of the GridView control. For example, you can customize the paging UI mode by setting it as
follows:

GridView1.PagerSettings.Mode = PagerButtons.NextPreviousFirstLast
The available modes are:
NextPrevious
NextPreviousFirstLast
Numeric
NumericFirstLast
Pager Control Appearance
The GridView control has numerous properties that you can use to customize the text and images for different pager modes.
For example, if you want to allow navigation using direction buttons but want to customize the text that appeared, you can
customize the button text by setting the NextPageText and PreviousPageText properties, as in the following example:

GridView1.PagerSettings.NextPageText = "Click for next page"


GridView1.PagerSettings.PreviousPageText = "Click for previous page"

You can also use images to customize the appearance of your paging controls. The PagerSettings class includes image URL
properties for the first, last, previous, and next page command buttons.
Finally, you can control the appearance of the paging commands by setting the PagerStyle property of the GridView control to
a TableItemStyle value.
Data Paging Template
If you set the AllowPaging property of the GridView control to true, the GridView control automatically adds user interface
(UI) controls for paging. You can customize the UI for paging by adding a PagerTemplate template. To specify which paging
operation to perform, include a Button control with its CommandName property set to Page and a CommandArgument set to
one of the following values:
First To move to the first page.
Last To move to the last page.
Prev To move to the previous page.
Next To move to the next page of data
A number To move to a specific page.

Paging Events
The GridView control raises two events when it moves to a new page of data. The PageIndexChanging event occurs before the
GridView control performs the paging operation. The PageIndexChanged event occurs after the new page of data has been
returned to the GridView control.
You can use the PageIndexChanging event to cancel the paging operation, if needed, or to perform a task before the
GridView control requests a new page of data. You can use the PageIndexChanged event to perform a task after the user
moves to a different page of data.
See Also
Other Resources
GridView Web Server Control
Visual Web Developer

How to: Enable Default Paging in the GridView Web Server


Control
If you are using the ASP.NET GridView control with large amounts of data, you might want to page through the rows and
display a subset of the rows on each page. The GridView control has built-in support for paging.
To enable paging using the smart tag panel
1. In Design view, right-click the GridView control and select Show Smart Tag.
2. In the smart tag panel, select Enable Paging.
Note
The Enable Editing check box appears in the smart tag panel only if the data source control to which GridView contro
l is bound supports paging.

To enable paging in the Properties window


Select the GridView control, and in the Properties window, set AllowPaging property to true.
To enable default paging declaratively
In Source view, set the AllowPaging attribute of the <asp:GridView> element to true, as in the following example:

<asp:GridView Runat="server" ID="GridView1" AllowPaging="true" />

Setting Paging Appearance


You can set the size of your page to specify how many rows are displayed at once. In addition, you can set the style of the links
used to create navigation buttons. You can choose from the following types:
Next and previous buttons. The button captions can be any text you want.
Page numbers, which allow users to jump to a specific page. You can specify how many numbers are displayed; if there
are more pages, an ellipsis (...) is displayed next to the numbers.
To change the number of rows displayed per page
Select the GridView control, and in the Properties window, set PageSize to the number of rows you want to display per
page.
To specify default paging with Next and Previous buttons
1. Set the GridView control to allow paging.
2. In the Properties window, expand the PagerSettings node.
Set Node to NextPrevious.
See Also
Reference
GridView Web Server Control Overview
Visual Web Developer

How to: Enable Default Selection in the GridView Web Server


Control
The ASP.NET GridView control has a built-in selection capability that allows users to select a row in the grid. Selecting a row in
a GridView control does not inherently perform any task. However, by adding selection capability, you can add functionality to
the grid that relies on users pointing to a specific row. Typical uses for adding selection capability to the GridView control
include:
When users select a row, the row is redisplayed with a different look.
When users select a row, related data is displayed elsewhere in the page, such as in a DetailsView control.
Procedures
To enable selection using the smart tag
1. In Design view, right-click the GridView control and click Show Smart Tag.
2. In the smart tag panel, select Enable Selection.
To enable default selection using the AutoGenerateSelectButton property
Select the GridView control, and in the Properties window, set AutoGenerateSelectButton to true.
-or-
In Source view, in the <asp:GridView> element, set the AutoGenerateSelecttButton attribute to true:

<asp:GridView Runat="server" ID="GridView1"


AutoGenerateSelectButton="true" />

To customize the look of a row in selection mode


Set properties for the SelectedRowStyle.
For example, if you set the BackColor subproperty of the SelectedRowStyle to gray, a selected row is displayed with a
gray background.

To customize the command text of the Select button


1. Select the GridView control, and in the Properties window, click the ellipsis (...) button in the Columns box.
The Fields dialog box is displayed.
2. Under Selected fields, click Select.
3. Under CommandField properties, in the SelectText box, enter text for the Select button.
To change the command text of the Select button to an image
1. Select the GridView control, and in the Properties window, click the ellipsis (...) button in the Columns box.
The Fields dialog box is displayed.
2. Under Selected fields, click Select.
3. Under CommandField properties, in the SelectImageUrl box, enter or select the URL of the image to use for the Select
button.
See Also
Reference
GridView Web Server Control Overview
Concepts
Modifying Data in a GridView Web Server Control
ASP.NET

Modifying Data in a GridView Web Server Control


The GridView control has built-in functionality for allowing users to edit or delete records without requiring programming. You
can customize the edit or delete functionality of the GridView control using events and templates.
Enabling the Built-In Editing Functionality
You can enable the built-in edit or delete functionality of the GridView control in any of the following ways:
Setting the AutoGenerateEditButton property to true to enable updating and the AutoGenerateDeleteButton property to
true to enable deleting.
Adding a CommandField with the ShowEditButton property set to true to enable updating and the ShowDeleteButton
property set to true to enable deleting.
Creating a TemplateField where the ItemTemplate contains command buttons with the CommandName set to "Edit" for
updating and "Delete" for deleting. For more information, see
Creating a Custom Column in a GridView Web Server Control.
How Editing Works in the GridView Control
The GridView control can display a user interface (UI) to enable users to edit the contents of individual rows. Typically, an
editable grid contains a column with a button or link in it that users can click to put the row into edit mode. (By default, the
button caption is "Edit.")
When users save a change, the GridView control passes the changes and primary key information to the data source control,
identified by the DataSourceID property, which invokes the appropriate update operation. For example, the SqlDataSource
control executes a SQL Update statement using the changed data as parameter values. The ObjectDataSource control calls its
update method, passing the changes as parameters to the method call.
The GridView control passes values to the data source for an update or delete operation in three dictionary collections: the
Keys dictionary, the NewValues dictionary, and the OldValues dictionary. You can access each dictionary using the
arguments passed to the GridView control's update or delete events.
The Keys dictionary contains the names and values of fields that uniquely identify the record to update or delete, and always
contains the original values of the key fields. To specify which fields are placed in the Keys dictionary, set the DataKeyNames
property to a comma-separated list of field names that represent the primary key of your data. The DataKeys collection is
populated automatically with the values associated with the fields specified for the DataKeyNames property.
Note
The original primary key values for the fields specified in the DataKeyNames property are stored in view state. If your prima
ry key values contain sensitive information, you should encrypt the view state contents by setting the page's
ViewStateEncryptionMode property to Always.

The NewValues dictionary contains the current values from the input controls in the row being edited. The OldValues
dictionary contains any original values of fields except the key fields, which are included in the Keys dictionary.
The data source control uses the values from the Keys, NewValues, and OldValues dictionaries as parameters for the update
or delete command. For information on how data source control parameters are created based on the dictionaries created for
bound values, see How a Data Source Control Creates Parameters for Data-bound Fields.
You can examine or customize the contents of any of these dictionaries before they are passed to the data source by handling
the RowUpdating or RowDeleting events. After the update or delete is complete, the GridView control raises its RowUpdated
or RowDeleted event. These events allow you to perform post-query logic such as integrity checks.
After the update or deletion is complete and all events have been raised, the GridView control rebinds to the data source
control to display the updated data.
Note
The original values for updatable fields in a GridView control are stored in ViewState. If ViewState is disabled on an ASP.NE
T page that includes an updatable GridView control, then optimistic concurrency checks cannot use the original values for u
pdatable and primary key fields that were retrieved when the GridView control was first bound to the data source. When the
page posts back in order to perform an update or delete, current values from the database are retrieved as the original value
s for the updatable and primary key fields in the GridView control because no values are stored in ViewState. The update o
r delete operation is then performed using these original values. If the original values have changed since the GridView cont
rol was first populated, the update or delete will succeed, but the optimistic concurrency check will not report a failure as wo
uld be expected.

Customizing the Editing User Interfaces in the GridView Control


You can customize the editing (UI) elements, such as the type of control displayed in edit mode for every data field. Automatic
two-way data binding allows your custom control to provide the editable and edited values, to and from the data store.
Note
If you change the update statement in a data source control or if you rearrange the columns in the GridView control, always
ensure that the values the GridView control passes to the data source match the corresponding data source configuration.

See Also
Reference
GridView Web Server Control Overview
Other Resources
Data Source Web Server Controls
Visual Web Developer

How to: Enable Default Editing in the GridView Web Server


Control
In addition to displaying data, the GridView control supports an edit mode in which users can change the contents of an
individual row. You can configure the GridView control to display an Edit button in each row. When users click the button, the
row is redisplayed in edit mode, with the data available in editable controls such as TextBox and CheckBox controls. The Edit
button becomes an Update or Save button, and when users click it, the updated row is written back to the data store. You can
add editing capability to the GridView control without writing any code.
Procedures
The following procedure illustrates how to enable default editing in the GridView control.
To enable default editing using the smart tag
1. In Design view, right-click the GridView control and click Show Smart Tag.
2. In the smart tag panel, select Enable Editing.
Note
The Enable Editing check box appears in the smart tag panel only if the data source control to which GridView contro
l is bound supports editing. For example, if the GridView control is bound to a SqlDataSource control, the SqlDataSou
rce control's UpdateQuery property must contain a SQL Update statement.

Alternatively, you can set a GridView control property.


To enable default editing using the AutoGenerateEditButton property
Select the GridView control, and in the Properties window, set AutoGenerateEditButton to true.
-Or-
In Source view, in the <asp:GridView> element, set AutoGenerateEditButton to true, as in the following example:

<asp:GridView Runat="server" ID="GridView1"


AutoGenerateEditButton="true" />

See Also
Reference
GridView Web Server Control Overview
Concepts
Modifying Data in a GridView Web Server Control
Modifying Data in a GridView Web Server Control
Visual Web Developer

How to: Customize Controls for Editing in the GridView Web


Server Control
When a row in the GridView control is put into edit mode, the row typically displays text or check boxes for individual columns
of the data, where users can change the data. If you want to use different controls for editing, you can customize the GridView
controls for edit mode. You do this by creating a template that defines the custom layout (text and controls) that you want to
display in edit mode instead of the default controls. For more information, see ASP.NET Web Server Controls Templates.
Procedures
To specify custom editing for a GridView column
1. On the GridView Tasks shortcut menu, select the Enable Editing check box.
Note
The Enable Editing check box appears on the shortcut menu only if the data source control to which the GridView co
ntrol is bound supports editing. For example, if the GridView control is bound to a SqlDataSource control, the
UpdateCommand property must contain an SQL Update statement.

2. On the shortcut menu, click Edit Columns.


The Fields dialog box appears.
3. Under Available fields, expand Bound Field to list the bound fields of the data source.
4. Under Selected fields, select one bound field, click Convert this field into a TemplateField, and then click OK to close
the Fields dialog box.
5. On the shortcut menu, click Edit Templates.
The GridView control switches to template-editing mode.
6. On the shortcut menu, in the Display list, click EditItem Template.
The GridView control displays the template editor for the EditItemTemplate property. This specifies the layout (text and
controls) that will appear for that column when the row is in edit mode.
7. From the Standard group in the Toolbox, drag a DropDownList control into the template.
You will configure the DropDownList in the next procedure.
To populate a drop-down list for editing in a GridView column
1. On the shortcut menu, in the Choose Data Source list, click New Data Source.
2. In the Data Source Configuration Wizard, select the same data source that you used in the preceding procedure.
3. Select data fields to display and corresponding values of the list from available fields in your data source, and then click
OK.
4. Press CTRL+F5 to run the page.
5. Change a column in the grid to verify that the list appears.
See Also
Reference
GridView Web Server Control Overview
GridView
Concepts
Modifying Data in a GridView Web Server Control
Visual Web Developer

Walkthrough: Displaying a Drop-Down List While Editing in the


GridView Web Server Control
The GridView control displays text boxes for editing by default. You can use the ASP.NET GridView control's built-in advanced
functionality to add a drop-down list to the editing display. Tasks illustrated in this walkthrough include:
Configuring a GridView control to display SQL data.
Displaying data in the GridView control.
Displaying a drop-down list while editing in the GridView control.
Prerequisites
In order to complete this walkthrough, you will need:
Microsoft Visual Web Developer (Visual Studio).
Microsoft Data Access Components (MDAC) version 2.7 or later.
If you are using Microsoft Windows XP or Windows Server 2003, you already have MDAC 2.7. However, if you are using
Microsoft Windows 2000, you might need to upgrade the MDAC already installed on your computer. For more
information, see "Microsoft Data Access Components (MDAC) Installation" in the MSDN Library.
Access to the SQL Server Northwind database. For information about downloading and installing the SQL Server sample
Northwind database, see Installing Sample Databases on the Microsoft SQL Server Web site.
Note
If you need information about how to log on to the computer running SQL Server, contact the server administrator.

Creating the Web Site and Page


Create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New, and then click Web Site. If you are using Visual Web Developer Express, on the File menu,
click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, select File System, and enter the name of the folder where you want to keep the pages of your Web
site.
For example, type the folder name C:\WebSites\DropDownEdit.
5. In the Language list, click the programming language you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Creating a Connection to an SQL Data Source
To start, you must create a connection to the computer running SQL Server where you have access to the Northwind database.
To create a connection to SQL Server
1. In Server Explorer, right-click Data Connections, and then click Add Connection. If you are using Visual Web
Developer Express, use Database Explorer.
The Add Connection dialog box appears.
If the Data source list does not display Microsoft SQL Server (SqlClient), click Change, and in the Change Data
Source dialog box, select Microsoft SQL Server.
If the Choose Data Source page appears, in the Data source list, select the type of data source you will use. For
this walkthrough, the data source type is Microsoft SQL Server. In the Data provider list, click .NET Framework
Data Provider for SQL Server, and then click Continue.
Note
If the Server Explorer tab is not visible in Visual Web Developer, in the View menu, click Server Explorer. If the Data
base Explorer tab is not visible, in the View menu, click Database Explorer.

2. In the Add Connection box, enter your server name in the Server Name box.
3. For the Log on to the server section, select the option that is appropriate to access the running SQL Server database
(integrated security or specific ID and password) and, if required, enter a user name and password.
4. Select the Save my Password check box.
5. Under Select or enter a database name, enter Northwind.
6. Click Test Connection, and when you are sure that it works, click OK.
Your new connection has been created under Data Connections in Server Explorer.
Configuring a GridView Control to Display Database Data
In this part of the walkthrough, you dynamically populate the grid with data.
To enable simple sorting
1. Switch to or open the Default.aspx file
2. Switch to Design view.
3. In the Toolbox, from the Data group, drag a GridView control onto the page.
4. On the GridView Tasks menu, in the Choose Data Source box, click <New data source>.
The Data Source Configuration wizard appears.
5. Click Database.
This specifies that you want to get data from a database that supports SQL statements, which includes SQL Server and
other OLE-DB–compatible databases.
6. In the Specify an ID for the data source box, a default data source control name, SqlDataSource1, is displayed. You
can leave this name.
7. Click OK.
The Configure Data Source wizard is displayed.
8. In the Which data connection should your application use to connect to the database? box, enter the connection
that you created in "To create a connection to SQL Server," and then click Next.
The wizard displays a page in which you can choose to store the connection string in a configuration file. Storing the
connection string in the configuration file has two advantages:
It is more secure than storing it in the page.
You can use the same connection string in multiple pages.
9. Select the Yes, save this connection as check box, and then click Next.
The wizard displays a page in which you can specify what data you want to retrieve from the database.
10. Under Specify columns from a table or view, in the Name box, click Employees.
11. Under Columns, select the EmployeeId, LastName, FirstName, HireDate, and City check boxes.
The wizard displays the SQL statement that you are creating in a box at the bottom of the page.
Note
The wizard allows you to specify selection criteria (WHERE clauses) and other SQL query options. For this walkthrough,
you will create a simple statement with no selection or sort options.

12. Click Advanced, select the Generate INSERT, UPDATE, and DELETE statements check box, and then click OK.
This generates Insert, Update, and Delete statements for the SqlDataSource1 control based on the Select statement that
you configured earlier.
Note
Alternatively, you could manually create the statements by selecting Specify a custom SQL statement or stored pro
cedure and entering SQL queries.

13. Click Next.


14. Click Test Query to be sure that you are retrieving the data you want.
15. Click Finish.
16. Right-click the GridView control and select Show Smart Tag. From the GridView Tasks menu, select the Enable
Editing box.
You can now test the page.
To test the page
1. Press CTRL+F5 to run the page.
The GridView control is displayed with EmployeeId, LastName, FirstName, HireDate, and City columns.
2. Click the Edit link next to a row.
The row selected for editing is displayed with LastName, FirstName, HireDate, and City columns as an editable text
box. EmployeeId is not displayed in a text box, because it is a key field and not editable.
3. Change a field such as LastName and click Update.
The GridView control is displayed with EmployeeId, LastName, FirstName, HireDate, and City columns, with
LastName updated with the new value.
4. Close the browser.
Displaying a Drop-Down List While Editing in the GridView Control
In this part of the walkthrough, you can add a drop-down list to select from while editing the rows in the grid.
To display a drop-down list while editing
1. From the Data node of the Toolbox, drag a SqlDataSource control onto the page.
A new data source control named SqlDataSource2 is created.
2. In the SqlDataSource Tasks menu, choose Configure Data Source.
3. In the Which data connection should your application use to connect to the database? box, enter the connection
that you created earlier.
4. Click Next.
5. On the Configure the Select Statement page, select Specify columns from a table or view, and then in the Name
box, click Employees.
6. Select only the City column, and then select the Return only Unique Rows check box. Click Next.
7. Click Test Query to preview the data, and then click Finish.
8. Right-click the GridView control and select Show Smart Tag. In the GridView Tasks menu, select Edit Columns.
9. In the Fields dialog box, select City from the Selected fields list box.
10. Click Convert this field into a TemplateField link.
11. Click OK to close the Fields dialog box.
12. Right-click the GridView control and select Show Smart Tag. In the GridView Tasks menu, select Edit Templates.
13. Select EditItemTemplate in the Display drop-down list.
14. Right-click the default TextBox control in the template and select Delete to remove it.
15. From the Standard tab of the Toolbox, drag a DropDownList control onto the template.
16. Right-click the DropDownList control and select Show Smart Tag. In the DropDownList Tasks menu, select Choose
Data Source.
17. Select SqlDataSource2.
18. Click OK.
19. In the DropDownList Tasks menu, choose Edit DataBindings. The SelectedValue property of the DropDownList control
is selected in the DataBindings dialog box.
20. Click the Field Binding radio button and select City for Bound To.
21. Select the Two-way databinding check box.
22. Click OK.
23. Right-click the GridView control and select Show Smart Tag. In the GridView Tasks menu, click End Template
Editing.
Security Note
User input in an ASP.NET Web page can include potentially malicious client script. By default, ASP.NET Web pages valid
ate user input to make sure input does not include script or HTML elements. As long as this validation is enabled, you d
o not need to explicitly check for script or HTML elements in user input. For more information, see
Script Exploits Overview.

You can now test the page.


To test the page
1. Press CTRL+F5 to run the page.
The GridView control is displayed with EmployeeId, LastName, FirstName, HireDate, and City columns.
2. Click the Edit link next to a row.
The current City value is preselected in the drop-down list.
Select a different City value from the drop-down list and click Update.
The City field is updated using the value selected in the drop down list.
See Also
Tasks
Walkthrough: Basic Data Access in Web Pages
How To: Secure Connection Strings when Using Data Source Controls (Visual Studio)
Other Resources
GridView Web Server Control (Visual Studio)
Visual Web Developer

How to: Enable Default Deleting in the GridView Web Server


Control
The GridView control supports a delete mode in which users can delete the current row from the data source. You can add
delete capability to the GridView control without writing any code. You can configure the GridView control to display a
Delete button in each row. When users click the button, the row is deleted from the data source and the grid is redisplayed.
Note
Deleting data using the GridView control is permanent; you cannot undo the deletion.

Procedures
To enable default deleting using the smart panel
1. Right-click the GridView control and click Show Smart Tag.
2. In the smart tag panel, select Enable Deleting.
Note
The Enable Editing check box appears in the smart tag panel only if the data source control to which GridView contro
l is bound supports deleting. For example, if the GridView control is bound to a SqlDataSource control, the SqlDataSo
urce control's DeleteQuery property must contain a SQL Delete statement.

Alternatively, you can set a GridView control property.


To enable deleting using the AutoGenerateDeleteButton property
Select the GridView control, and in the Properties window, set AutoGenerateDeleteButton to true.
-or-
In Source view, in the <asp:GridView> element, set the AutoGenerateDeleteButton property to true, as in the following
example:

<asp:GridView Runat="server" ID="GridView1" AutoGenerateDeleteButton="true" />

See Also
Reference
GridView Web Server Control Overview
Concepts
Modifying Data in a GridView Web Server Control
ASP.NET

GridView Web Server Control Events


The GridView control raises a number of events in the course of paging through and updating its bound data to which your
code can respond.
GridView Events
The GridView control exposes paging and sorting events, and events that occur when the current row is created or bound to
data. Events are also raised when a command control such as a Button control that is included as part of the GridView control
has been clicked. The following table describes the events exposed by the GridView control.
RowCommand
Occurs when a button is clicked in the GridView control. This event is often used to perform a task when a button is clicked
in the control.
PageIndexChanging
Occurs when a pager button is clicked, but before the GridView control performs the paging operation. This event is often
handled to cancel the paging operation.
PageIndexChanged
Occurs when a pager button is clicked, but after the GridView control performs the paging operation. This event is
commonly handled when you need to perform a task after the user navigates to a different page in the control.
SelectedIndexChanging
Occurs when a row's Select button (a button with its CommandName property set to "Select") within a GridView control is
clicked, but before the GridView control performs the select operation. This event is often handled to cancel the selection
operation.
SelectedIndexChanged
Occurs when a row's Select button within a GridView control is clicked, but after the GridView control performs the select
operation. This event is often handled to perform a task after a row is selected in the control.
Sorting
Occurs when the hyperlink to sort a column is clicked, but before the GridView control performs the sort operation. This
event is often handled to cancel the sorting operation or to perform a custom sorting routine.
Sorted
Occurs when the hyperlink to sort a column is clicked, but after the GridView control performs the sort operation. This event
is commonly handled to perform a task after the user clicks on a hyperlink to sort a column.
RowDataBound
Occurs when a row in the GridView control is bound to a data record. This event is often handled to modify the contents of a
row when the row is bound to data.
RowCreated
Occurs when a new row is created in the GridView control. This event is often handled to modify the layout or appearance
of a row when the row is created.
RowDeleting
Occurs when a row's Delete button (a button with its CommandName property set to "Delete") within a GridView control
is clicked, but before the GridView control deletes the record from the data source. This event is often handled to cancel the
deleting operation.
RowDeleted
Occurs when a row's Delete button is within a GridView control clicked, but after the GridView control deletes the record
from the data source. This event is often handled to check the results of the delete operation.
RowEditing
Occurs when a row's Edit button (a button with its CommandName property set to "Edit") within a GridView control is
clicked, but before the GridView control enters edit mode. This event is often handled to cancel the editing operation.
RowCancelingEdit
Occurs when a row's Cancel button (a button with its CommandName property set to "Cancel") within a GridView control
is clicked, but before the GridView control exits edit mode. This event is often handled to stop the cancel operation.
RowUpdating
Occurs when a row's Update button (a button with its CommandName property set to "Update") within a GridView
control is clicked, but before the GridView control updates the record. This event is often handled to cancel the updating
operation.
RowUpdated
Occurs when a row's Update button within a GridView control is clicked, but after the GridView control updates the record.
This event is often handled to check the results of the update operation.
DataBound
This event is inherited from the BaseDataBoundControl control and occurs after the GridView control has finished binding
to the data source.
See Also
Reference
GridView Web Server Control Overview
Other Resources
GridView Web Server Control
ASP.NET

Creating a Custom Column in a GridView Web Server Control


The GridView control can automatically generate columns from the fields provided by the data source. In addition, you can
create a collection of columns to be displayed instead of automatically generating them. However, you might encounter a
scenario where you need to customize how an individual column is displayed. In that case, you can create a TemplateField to
specify a custom column layout.
Creating Templates
A TemplateField object enables you to specify templates that contain markup and controls to customize the layout and
behavior of a column in a GridView control. Using an ItemTemplate, you can specify the layout to be used when the GridView
displays data in a column. To specify custom layout for when users edit data in a column, you can create an EditItemTemplate.
Your template can contain markup, Web server controls, and command buttons. For more information on templates, see
ASP.NET Web Server Controls Templates.
Data-Binding in a Template
In a template, you can bind controls to data using the Eval and Bind methods. You use the Eval method when the control will
only display values. You use the Bind method when users can modify a data value—that is, for data-update scenarios. You can
use the Eval method in any of the templates to display data. You use the Bind method in a template with controls in which
users might change values, such as TextBox and CheckBox controls, or a template that allows a record to be deleted. For more
information, see Data-Binding Expression Syntax.
Example
The following example shows the Columns collection of a GridView control. The collection contains a TemplateField object,
which in turn contains an ItemTemplate object. To display a date, the ItemTemplate includes a Label control that uses the
Eval method. To edit a date, the other templates use a Calendar control that uses the Bind method.
VB
<Columns>
<asp:BoundField DataField="EmployeeID" HeaderText="Employee ID" ReadOnly="true"/>

<asp:BoundField DataField="FirstName" HeaderText="First Name"/>


<asp:BoundField DataField="LastName" HeaderText="Last Name"/>
<asp:TemplateField HeaderText="Birth Date">
<ItemTemplate>
<asp:Label ID="BirthDateLabel" Runat="Server"
Text='<%# Eval("BirthDate", "{0:d}") %>' />
</ItemTemplate>
<EditItemTemplate>
<asp:Calendar ID="EditBirthDateCalendar" Runat="Server"
VisibleDate='<%# Eval("BirthDate") %>'
SelectedDate='<%# Bind("BirthDate") %>' />
</EditItemTemplate>
</asp:TemplateField>
<asp:HyperLinkField Text="Show Detail"
DataNavigateUrlFormatString="~/ShowEmployeeDetail.aspx?EmployeeID={0}
"
DataNavigateUrlFields="EmployeeID" />
</Columns>

C#
<Columns>
<asp:BoundField DataField="EmployeeID" HeaderText="Employee ID" ReadOnly="true"/>

<asp:BoundField DataField="FirstName" HeaderText="First Name"/>


<asp:BoundField DataField="LastName" HeaderText="Last Name"/>
<asp:TemplateField HeaderText="Birth Date">
<ItemTemplate>
<asp:Label ID="BirthDateLabel" Runat="Server"
Text='<%# Eval("BirthDate", "{0:d}") %>' />
</ItemTemplate>
<EditItemTemplate>
<asp:Calendar ID="EditBirthDateCalendar" Runat="Server"
VisibleDate='<%# Eval("BirthDate") %>'
SelectedDate='<%# Bind("BirthDate") %>' />
</EditItemTemplate>
</asp:TemplateField>
<asp:HyperLinkField Text="Show Detail"
DataNavigateUrlFormatString="~/ShowEmployeeDetail.aspx?EmployeeID={0}
"
DataNavigateUrlFields="EmployeeID" />
</Columns>

See Also
Reference
GridView Web Server Control Overview
Concepts
ASP.NET Data-Bound Web Server Controls Overview
Data Source Controls Overview
ASP.NET

How to: Set GridView Web Server Control Column Width


Dynamically
By default, columns in the GridView control are sized automatically. Columns render as HTML table cells (td elements) without
width information; most browsers size table cells to allow for the widest content in the column.
If it is required, you can set the width of individual columns in the GridView control programmatically. This is useful, if the
width of the column depends on information that is available only at run time. For example, you might size a column according
to its contents—that is, based on the data that the GridView control binds to.
The basic technique for setting column width involves setting the Width property of a column template. If you want the width
to be set according to its contents, you can handle the RowDataBound event. This makes the data for a row available to you for
examination.
To set column width dynamically
In code, set the Width property of the ItemStyle property for a GridView control column to the width that you want.
The following code example shows how to set the width of all the columns in the GridView1 control to the value that a
user enters in a text box.
VB
Protected Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs)
Try
Dim colWidth As Integer
colWidth = CInt(Server.HtmlEncode(TextBox1.Text))
If colWidth > 0 Then
For i As Integer = 0 To GridView1.Columns.Count - 1
GridView1.Columns(i).ItemStyle.Width = colWidth
Next
End If
Catch
' Report error.
End Try
End Sub

C#
protected void Button1_Click(object sender, EventArgs e)
{
try
{
int colWidth = Int16.Parse(Server.HtmlEncode(TextBox1.Text));
if (colWidth > 0)
{
for (int i = 0; i < GridView1.Columns.Count; i++)
{
GridView1.Columns[i].ItemStyle.Width = colWidth;
}
}
}
catch
{
// Report error.
}
}
To set column width based on data contents
1. Create a handler for the RowDataBound event.
The RowDataBound event is raised each time that a new row is data-bound in the grid and gives you access to the data
for each row.
2. In the event handler, do the following:
a. Create a DataRowView object and assign to it the DataItem value for the current grid row.
The DataItem property is typed as an object. Therefore, you must cast it.
b. Test for a data row (DataControlRowType) to make sure that you are working with a data-bound row and not a
header or footer.
c. From the DataRowView object, extract the data value that you want to examine.
d. Set the Width property for the ItemStyle property.
e. Set the Wrap property of the ItemStyle property to false.
If the Wrap property is false, the column is automatically resized.
The following code example shows how to set the width of a column (in this case, the third column) based on the width
of the widest data element of the second column. The RowDataBound event handler is called one time for each data
row that is displayed by the GridView control. The code stores the character count of the widest element in a protected
page member. The code sets the width of the column to the character count times 30 (an arbitrary multiplier).
VB
Protected widestData As Integer
Protected Sub GridView1_RowDataBound(ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs)
Dim drv As System.Data.DataRowView
drv = CType(e.Row.DataItem, System.Data.DataRowView)
If e.Row.RowType = DataControlRowType.DataRow Then
If drv IsNot Nothing Then
Dim catName As String = drv(1).ToString()
Dim catNameLen As Integer = catName.Length
If catNameLen > widestData Then
widestData = catNameLen
GridView1.Columns(2).ItemStyle.Width = _
widestData * 30
GridView1.Columns(2).ItemStyle.Wrap = False
End If
End If
End If
End Sub

Protected Sub Page_Load(ByVal sender As Object, _


ByVal e As System.EventArgs) Handles Me.Load
widestData = 0
End Sub

C#
protected int widestData;
protected void GridView1_RowDataBound(object sender,
GridViewRowEventArgs e)
{
System.Data.DataRowView drv;
drv = (System.Data.DataRowView)e.Row.DataItem;
if (e.Row.RowType == DataControlRowType.DataRow)
{
if (drv != null)
{
String catName = drv[1].ToString();
Response.Write(catName + "/");

int catNameLen = catName.Length;


if (catNameLen > widestData)
{
widestData = catNameLen;
GridView1.Columns[2].ItemStyle.Width =
widestData * 30;
GridView1.Columns[2].ItemStyle.Wrap = false;
}

}
}
}

protected void Page_Load(object sender, EventArgs e)


{
widestData = 0;
}

See Also
Other Resources
GridView Web Server Control
Walkthrough: Creating a Nested GridView Control
The GridView control displays rows of data in a grid (an HTML table), displaying one data row per grid row. This walkthrough
shows you how to extend the functionality of the GridView control so that individual grid rows can display data from a related
data table. In the walkthrough, you show related data in a nested GridView control — a GridView control inside the grid row
of the parent GridView control.
An example of nested data would be a GridView control that displays a list of customers where each row of the GridView
control includes another GridView control that displays the orders for that customer.
In this walkthrough, both GridView controls use SqlDataSource controls to retrieve the data from the data source.
During this walkthrough, you will learn how to do the following:
Connect to a SQL Server database in Microsoft Visual Web Developer.
Use the SqlDataSource control to manage data access and binding.
Display data returned from the database in the GridView control.
Create a TemplateField with nested controls to be displayed by the GridView control.
Dynamically customize the display for each row based on run-time conditions.
Optionally, use data caching with the SqlDataSource control to reduce requests made to the database.
Prerequisites
In order to complete this walkthrough, you will need:
Visual Web Developer (Visual Studio).
Microsoft Data Access Components (MDAC) version 2.7 or a later version.
If you are using Microsoft Windows XP or Windows Server 2003, you already have MDAC 2.7. However, if you are using
Microsoft Windows 2000, you might need to upgrade the MDAC already installed on your computer. For more
information, see "Microsoft Data Access Components (MDAC) Installation" in the MSDN Library.
Access to the SQL Server Northwind database. For information about how to download and install the SQL Server
sample Northwind database, see Installing Sample Databases on the Microsoft SQL Server Web site.
Note
If you need information about how to log on to the computer that is running SQL Server, contact the server administrat
or.

Creating the Web Site


If you have already created a Web site in Visual Web Developer by completing
Walkthrough: Creating a Basic Web Page in Visual Web Developer, you can use that Web site and go to the next section.
Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New, and then click Web Site. If you are using Visual Web Developer Express, on the File menu,
click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the first Location box, select File System; in the second, enter the name of the folder where you want to keep the
pages of the Web site.
For example, type the folder name C:\WebSites\NestedGridView.
5. In the Language list, click the programming language you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Adding a Data Source for the GridView Control
To display data on an ASP.NET Web page, you need the following:
A connection to a data source (such as a database). In the following procedure, you will create a connection to the SQL
Server Northwind database.
A control on the page to display the data.
In the following procedure, you will display data in a GridView control. The GridView control will get its data from the
SqlDataSource control.
To add a data source for the GridView control
1. Open or switch to the Default.aspx page.
2. Switch to Design view.
3. In the Toolbox, from the Data group, drag a SqlDataSource control onto the page.
If the SqlDataSource Tasks smart tag does not appear, right-click the SqlDataSource control and click Show Smart
Tag.
4. In the SqlDataSource Tasks panel, click Configure Data Source.
The Configure Data Source wizard appears.
5. Click New Connection.
The Add Connection dialog box appears.
If the Data source list does not display Microsoft SQL Server (SqlClient), click Change, and in the Change Data
Source dialog box, select Microsoft SQL Server.
If the Choose Data Source dialog box appears instead of the Connection Properties dialog box, in the Data
source list, select the type of data source you will use. For this walkthrough, the data source type is Microsoft SQL
Server. In the Data provider list, click .NET Framework Data Provider for SQL Server, and then click Continue.
6. On the Add Connection page, in the Server name text box, type the name of the SQL Server where the sample
Northwind database is installed.
7. For the Log on to the server section, select the appropriate option to access the running SQL Server database
(integrated security or specific ID and password). If you need to, enter a user name and password.
8. If you entered a password, select the Save my password check box.
9. Click Select or enter a database name, and then enter Northwind.
10. Click Test connection, and when you are sure that it works, click OK.
11. In the Configure Data Source wizard, click Next.
12. Ensure that the Yes, save this connection as check box is selected.
13. Name the connection NorthwindConnectionString and then click Next.
14. In the Configure the Select Statement wizard step, select Specify columns from a table or view.
15. In the Name list box, select Customers.
16. In the Columns panel, select the CustomerID and CompanyName columns.
17. Click Next.
18. Click Finish.
Adding a GridView Control to Display Data
After you have established a data source to retrieve the data, you must add a control to the page to display the data.
In the following procedure, you will display data in a GridView control. The GridView control will get its data from the
SqlDataSource control that you added previously.
To add and configure a GridView control for displaying data
1. Ensure that you are in Design view for the Default.aspx page.
2. In the Toolbox, from the Data group, drag a GridView control onto the page.
3. On the GridView Tasks menu, in the Choose Data Source list box, select the SqlDataSource control added previously,
SqlDataSource1.
4. Select the Enable Paging check box.
5. In the Properties window, expand the RowStyle property for the GridView control, and then set the VerticalAlign
property to Top. This will align the text in the grid row at the top of the cells, because the nested grid will display multiple
lines.
Adding a Nested GridView Control to Display Related Data
You must now create a nested data source and GridView control to display related data in each row. To do so, you will do the
following:
Create a TemplateField for the rows displayed by the GridView control.
Add a nested GridView control and SqlDataSource control to the TemplateField to display related data for individual
rows.
Add a procedure to handle the RowDataBound event of the parent GridView control in order to set the select parameter
value for the nested SqlDataSource control.

To add and configure a nested GridView control for displaying data


1. Ensure that you are in Design view for the Default.aspx page.
2. Right-click the GridView control and select Show Smart Tag.
3. Click Edit Columns.
The Fields dialog box appears.
4. In the Available fields panel, select a TemplateField, and then click Add.
5. In the TemplateField properties panel, set HeaderText to Orders.
6. Click OK.
7. In the GridView Tasks panel, click Edit Templates.
8. In Template Editing Mode panel, from the Display list box, select ItemTemplate.
9. In the Toolbox, from the Data group, drag a SqlDataSource control onto the page to the editable area of the
ItemTemplate.
If the SqlDataSource Tasks smart tag does not appear, right-click the SqlDataSource control and click Show Smart
Tag.
10. In the SqlDataSource Tasks smart tag, click Configure Data Source.
The Configure Data Source wizard appears.
11. For the Choose Your Data Connection step, select the NorthwindConnectionString created earlier in this
walkthrough and then click Next.
12. In the Configure the Select Statement wizard step, select Specify columns from a table or view.
13. In the Name list, select Orders.
14. In the Columns panel, select the OrderID and OrderDate columns.
15. Click WHERE to add a parameter for the SELECT statement.
16. In the Add WHERE Clause window, select CustomerID in the Column list box.
17. Select None in the Source list box.
18. Click Add.
This creates a select parameter that you will set to the CustomerID value for each row bound to the parent GridView
control.
19. Click OK.
20. Click Next.
21. Click Finish.
22. In the Toolbox, from the Data group, drag a GridView control to the editable area of the ItemTemplate.
If the GridView Tasks smart tag does not appear, right-click the GridView control and click Show Smart Tag.
23. In the GridView Tasks smart tag, in the Choose Data Source list box select the name of the nested SqlDataSource
control, SqlDataSource2.
24. Right-click the parent GridView control, GridView1, and select Show Smart Tag.
25. In the GridView Tasks panel, click End Template Editing.
Note
The nested GridView control is not displayed in Design view.

26. In the Properties panel for GridView1, click the Events button .
27. In the RowDataBound box, type GridView1_RowDataBound and then press ENTER.
Visual Web Developer creates an event handler for the RowDataBound event of the GridView control. The code will
resemble the following code example.
VB
Protected Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.
WebControls.GridViewRowEventArgs) Handles GridView1.RowDataBound

End Sub

C#
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{

28. Add the following code to the procedure:


VB
If e.Row.RowType = DataControlRowType.DataRow Then
Dim s As SqlDataSource = CType(e.Row.FindControl("SqlDataSource2"), SqlDataSource)
s.SelectParameters(0).DefaultValue = e.Row.Cells(0).Text
End If
C#
if (e.Row.RowType == DataControlRowType.DataRow)
{
SqlDataSource s = (SqlDataSource)e.Row.FindControl("SqlDataSource2");
s.SelectParameters[0].DefaultValue = e.Row.Cells[0].Text;
}

The code retrieves the CustomerID value for the current row and sets it as the select parameter value for the nested
SqlDataSource control, SqlDataSource2.
29. Save the changes to the files.

Testing the Page


You can now run the page.
To test the page
1. Press CTRL+F5 to run the page.
The GridView control displays the data rows from the Northwind Customers table with data from the Northwind Orders
table for each customer nested in each row.
2. Close the browser.
Using Caching with a Nested GridView Control
At this point in the walkthrough, you have created a page with nested GridView controls. As currently written, the page
queries the database one time for the parent GridView control, and again for each nested GridView control.
To reduce database load, you can modify your nested query to return all rows, cache the results, and then filter the results for
each nested GridView control.
Note
For large databases, this is not a practical solution. If you are retrieving data from a large database, build a data object that re
trieves only the required rows and bind to it using the ObjectDataSource control. For more information, see
ObjectDataSource Control Overview.

To configure a nested SqlDataSource control to cache query results


1. Ensure that you are in Design mode for the Default.aspx page.
2. Right-click the parent GridView control, GridView1, and then click Edit Template.
3. In the ItemTemplate for the Orders column, select the nested SqlDataSource control, SqlDataSource2.
4. In the Properties window, set the EnableCaching property to true.
5. Set the FilterExpression property to CustomerID='{0}'.
6. In the FilterParameters property, click the ellipsis button to open the Parameter Collection Editor window.
7. In the Parameter Collection Editor window, click Add Parameter.
8. In the Name box, enter CustomerID.
9. Click OK.
10. Right-click the nested SqlDataSource control, SqlDataSource2, and select Show Smart Tag.
11. Click Configure Data Source.
12. Leave the connection information unchanged and click Next.
13. In the Configure the Select Statement step, select Specify columns from a table or view.
14. In the Name list box, select Orders.
15. In the Columns section, check the OrderID, CustomerID, and OrderDate columns, and then click Next.
16. Click Finish.
17. When prompted to refresh the fields and keys for the nested GridView control, GridView2, click No.
The columns displayed by the nested GridView control will not change.
You have configured the nested SqlDataSource control, SqlDataSource2, to retrieve all the order data from the
database and cache it locally. When the nested GridView control is bound to the data, a filter is applied so that only
orders related to the CustomerID value for the current row will be displayed.
18. If using a code-behind page, right-click a blank area on the page, and then click View Code.
19. Change the code for the RowDataBound event handler to read as follows:
VB
If e.Row.RowType = DataControlRowType.DataRow Then
Dim s As SqlDataSource = CType(e.Row.FindControl("SqlDataSource2"), SqlDataSource)
s.FilterParameters(0).DefaultValue = e.Row.Cells(0).Text
End If

C#
if (e.Row.RowType == DataControlRowType.DataRow)
{
SqlDataSource s = (SqlDataSource)e.Row.FindControl("SqlDataSource2");
s.FilterParameters[0].DefaultValue = e.Row.Cells[0].Text;
}

In this version of the code, instead of setting a value in the SqlDataSource control's SelectParameters collection, you set
a value in its FilterParameters collection.
20. Save the file.

Testing the Page


You can now run the page.
To test the page
1. Press CTRL+F5 to run the page.
The GridView control displays the data rows from the Northwind Customers table with data from the Northwind Orders
table for each customer nested in each row. However, all the data that is bound to the GridView control will be
requested one time, when the first row is data bound. The data is cached for use with the remaining rows of the
GridView control.
2. Close the browser.
Next Steps
This walkthrough has illustrated how you can extend the functionality of the GridView control to display related data by using
nested GridView controls on an ASP.NET Web page. You can also extend your application to enable data to be updated and
deleted or to enable users to insert new records by using a DetailsView or FormView control. You might also use controls other
than a TextBox control, such as a DropDownList control, to change a value. For more information, see the following topics:
Walkthrough: Creating Master/Detail Web Pages in Visual Studio
Walkthrough: Editing and Inserting Data in Web Pages with the DetailsView Web Server Control
Walkthrough: Displaying a Drop-Down List While Editing in the GridView Web Server Control
See Also
Tasks
How to: Secure Connection Strings When Using Data Source Controls
Walkthrough: Displaying a Drop-Down List While Editing in the GridView Web Server Control
Walkthrough: Basic Data Access in Web Pages
Walkthrough: Performing Bulk Updates to Rows Bound to a
GridView Web Server Control
When editing is enabled for a GridView control, by default only one row can be edited at a time. This walkthrough shows you
how to extend the functionality of the GridView control so that users can modify multiple rows and then save all changes by
clicking a button. This walkthrough uses a SqlDataSource control to retrieve results from the data source and manage updates.
The SqlDataSource control acts as the data source for the GridView control.
During this walkthrough, you will learn how to:
Connect to a SQL Server database in Microsoft Visual Web Developer.
Use the SqlDataSource control to manage data access.
Display data returned from the database in the GridView control.
Configure the GridView control to enable users to edit multiple rows at one time.
Prerequisites
In order to complete this walkthrough, you will need:
Visual Web Developer (Visual Studio).
Microsoft Data Access Components (MDAC) version 2.7 or later.
If you are using Microsoft Windows XP or Windows Server 2003, you already have MDAC 2.7. However, if you are using
Microsoft Windows 2000, you might need to upgrade the MDAC already installed on your computer. For more
information, see Microsoft Data Access Components (MDAC) Installation in the MSDN library.
Access to the SQL Server Northwind database. If you need a copy of the Northwind database for SQL Server, see
Installing Sample Databases in SQL Server 2005 Books Online.
Note
If you need information about how to log on to the computer running SQL Server, contact the server administrator.

Creating the Web Site


If you have already created a Web site in Visual Web Developer by completing
Walkthrough: Creating a Basic Web Page in Visual Web Developer, you can use that Web site and go to the next section.
Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New, and then click Web Site. If you are using Visual Web Developer Express, on the File menu,
click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location list, click File System, and then enter the name of the folder where you want to keep the pages of your
Web site.
For example, enter the folder name C:\WebSites\BulkUpdate.
5. In the Language list, click the programming language you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.

Adding a Data Source for the GridView Control


To display data on an ASP.NET Web page, you need the following:
A connection to a data source such as a database.
In the following procedure, you will create a connection to the SQL Server Northwind database.
A data source control on the page, which interacts with the data source (the database) to read and write data.
A control on the page to display the data.
In the following procedure, you will display data in a GridView control. The GridView control will get its data from a
SqlDataSource control.
To add a data source for the GridView control
1. Open or switch to the Default.aspx page.
2. Switch to Design view.
3. From the Data tab in the Toolbox, drag a SqlDataSource control onto the page.
If the SqlDataSource Tasks smart tag does not appear, right-click the SqlDataSource control and click Show Smart
Tag.
4. In the SqlDataSource Tasks panel, click Configure Data Source.
The Configure Data Source wizard appears.
5. Click New Connection.
The Add Connection dialog box appears.
6. If required, do one of the following. The exact UI you see depends on what data connections you have made previously in
Visual Web Developer.
If the Data source list does not display Microsoft SQL Server (SqlClient), click Change, and in the Change Data
Source dialog box, select Microsoft SQL Server.
If the Choose Data Source dialog box appears instead of the Connection Properties dialog box, in the Data
source list, select the type of data source you will use. For this walkthrough, the data source type is Microsoft SQL
Server. In the Data provider list, click .NET Framework Data Provider for SQL Server, and then click Continue.
7. On the Add Connection page, in the Server name text box, enter the name of the computer running the SQL Server
Northwind database.
8. Under Log on to the server, select the appropriate option to access the SQL Server database (integrated security or
specific ID and password). If required, enter a user name and password.
Note
If you need information about how to log on to the computer running SQL Server, contact the server administrator.

9. If you entered a password, select the Save my password check box.


10. Click Select or enter a database name, and then enter Northwind.
11. Click Test connection, and when you are sure that it works, click OK.
12. In the Configure Data Source wizard, click Next.
13. Ensure that the Yes, save this connection as check box is selected.
14. Name the connection NorthwindConnectionString and then click Next.
15. In the Configure the Select Statement page, select Specify columns from a table or view.
16. In the Name list, select Employees.
17. Under Columns, select EmployeeID, TitleOfCourtesy, LastName, FirstName, Title, and Extension.
18. Click Advanced.
19. Select the Generate INSERT, UPDATE, and DELETE statements check box, and then click OK.
20. Click Next.
21. Click Finish.

Adding a GridView Control to Display Data


After you have configured a data source control to manage the data, you need a control on the page to display the data.
In the following procedure, you will display data in a GridView control. The GridView control will get its data from the
SqlDataSource control that you added previously.
To enable users to edit the contents of all the GridView control at once (rather than editing just one row at a time), you must
customize the GridView control. You will replace the default display elements in each column with editable elements, and then
bind them to the data source. To accomplish this, you will create TemplateField columns. In the ItemTemplate for each
TemplateField column, you will add a bound TextBox control where users can edit the data.
To add and configure a GridView control for displaying data
1. Ensure that you are in Design view for the Default.aspx page.
2. From the Data tab in the Toolbox, drag a GridView control onto the page.
In the GridView Tasks panel, in the Choose Data Source list box, select the SqlDataSource control you added
previously, SqlDataSource1.
3. Select Enable Paging.
4. Click Edit Columns.
The Fields dialog box appears.
5. Under Selected fields, select TitleOfCourtesy.
6. Click Convert this field to a TemplateField.
7. Convert the remaining fields to template fields except the EmployeeId field, using the same steps that you did for the
TitleOfCourtesy field. (The EmployeeId field contains the primary key, and is not editable.)
8. Click OK.
9. In the GridView Tasks panel, click Edit Templates.
10. In the Display list, under TitleOfCourtesy, click EditItemTemplate.
The GridView control displays an editable area with the default layout for the TitleOfCourtesy column in edit mode.
11. Right-click the TextBox control in the EditItemTemplate and then click Copy.
12. Right-click the GridView control and then click Show Smart Tag.
13. In the Display list, under TitleOfCourtesy, click ItemTemplate.
The GridView control now displays the default layout for the TitleOfCourtesy column in display mode.
14. Delete the existing Label control.
15. Right-click the ItemTemplate editable area, and then click Paste.
You have copied the TextBox control, including its data binding configuration, from the EditItemTemplate layout to
the ItemTemplate layout.
16. Select the TextBox control and in the Properties window, set the (ID) property to TitleOfCourtesyTextBox.
17. Set the MaxLength property to 25 (the maximum length of the field in the database).
This ensures that users do not enter more information than the TitleOfCourtesy field in the database is configured to
hold.
18. Repeat the preceding seven steps for each of the template fields, replacing the existing Label control with a TextBox
copied from the EditItemTemplate layout, and setting the ID property to <data field name>TextBox.
For the MaxLength property of each TextBox control, use the following values.
FirstName: 10
LastName: 20
Title: 30
Extension: 4
19. Right-click the GridView control, and then click End Template Editing.

Adding a Procedure to Perform Bulk Updates


After you have configured the GridView control to display editable data, you need to add code to perform the bulk update. In
this section, you will do the following:
Add a Button control and in its Click handler, add code to bulk update the changes from each row of the GridView
control.
Add a DataTable object that stores the original data values.
Add code to determine if a row has been modified. The current values displayed in the GridView control will be
compared to the original values stored in the DataTable object. If one or more of the displayed values do not match the
original value, the row will be updated in the database. Otherwise, the row will not be included in the bulk update.

To create a procedure for performing the bulk update


1. Switch to Design view.
2. Select the GridView control, and in the Properties window, click the Events button ( ) to display the events for the
GridView control.
3. In the RowDataBound field, type GridView1_RowDataBound and press ENTER.
Visual Web Developer creates an event handler for the RowDataBound event of the GridView control. The code will
look like the following code example.
VB
Protected Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.
WebControls.GridViewRowEventArgs) Handles GridView1.RowDataBound

End Sub

C#
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{

4. Replace the generated procedure with the following code (including the private variables).
VB
Private tableCopied As Boolean = False
Private originalDataTable As System.Data.DataTable

Protected Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.


WebControls.GridViewRowEventArgs) Handles GridView1.RowDataBound
If e.Row.RowType = DataControlRowType.DataRow Then
If Not tableCopied Then
originalDataTable = CType(e.Row.DataItem, System.Data.DataRowView).Row.Tab
le.Copy()
ViewState("originalValuesDataTable") = originalDataTable
tableCopied = True
End If
End If
End Sub

C#
private bool tableCopied = false;
private DataTable originalDataTable;

protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)


{
if (e.Row.RowType == DataControlRowType.DataRow)
if (!tableCopied)
{
originalDataTable = ((DataRowView)e.Row.DataItem).Row.Table.Copy();
ViewState["originalValuesDataTable"] = originalDataTable;
tableCopied = true;
}
}

The code runs whenever the GridView control is performing data binding. While the first row is binding, the code saves
a copy of the original database values in a DataTable object, which is in turn stored in ViewState.
5. Switch to Design view.
6. From the Standard tab in the Toolbox, drag a Button control onto the page.
7. In the Properties window, click the Properties button ( ) to display the properties for the Button control.
8. In the (ID) field, enter UpdateButton.
9. In the Text field, enter Update.
10. Click the Events button ( ) to display events for the Button control.
11. In the Click field, type UpdateButton_Click and press ENTER.
Visual Web Developer creates an event handler for the Button control's Click event. The code will look like the following
code example.
VB
Protected Sub UpdateButton_Click(ByVal sender As Object, ByVal e As EventArgs)

End Sub

C#
protected void UpdateButton_Click(object sender, EventArgs e)
{

12. Replace the generated procedure with the following code.


VB
Protected Sub UpdateButton_Click(ByVal sender As Object, ByVal e As EventArgs)
originalDataTable = CType(ViewState("originalValuesDataTable"), System.Data.DataTa
ble)

For Each r As GridViewRow In GridView1.Rows


If IsRowModified(r) Then GridView1.UpdateRow(r.RowIndex, False)
Next

' Rebind the Grid to repopulate the original values table.


tableCopied = False
GridView1.DataBind()
End Sub

Protected Function IsRowModified(ByVal r As GridViewRow) As Boolean


Dim currentID As Integer
Dim currentTitleOfCourtesy As String
Dim currentLastName As String
Dim currentFirstName As String
Dim currentTitle As String
Dim currentExtension As String

currentID = Convert.ToInt32(GridView1.DataKeys(0).Value)

currentTitleOfCourtesy = CType(r.FindControl("TitleOfCourtesyTextBox"), TextBox).T


ext
currentLastName = CType(r.FindControl("LastNameTextBox"), TextBox).Text
currentFirstName = CType(r.FindControl("FirstNameTextBox"), TextBox).Text
currentTitle = CType(r.FindControl("TitleTextBox"), TextBox).Text
currentExtension = CType(r.FindControl("ExtensionTextBox"), TextBox).Text

Dim row As System.Data.DataRow = _


originalDataTable.Select(String.Format("EmployeeID = {0}", currentID))(0)

If Not currentTitleOfCourtesy.Equals(row("TitleOfCourtesy").ToString()) Then Retur


n True
If Not currentLastName.Equals(row("LastName").ToString()) Then Return True
If Not currentFirstName.Equals(row("FirstName").ToString()) Then Return True
If Not currentTitle.Equals(row("Title").ToString()) Then Return True
If Not currentExtension.Equals(row("Extension").ToString()) Then Return True

Return False
End Function

C#
protected void UpdateButton_Click(object sender, EventArgs e)
{
originalDataTable = (DataTable)ViewState["originalValuesDataTable"];

foreach (GridViewRow r in GridView1.Rows)


if (IsRowModified(r)) { GridView1.UpdateRow(r.RowIndex, false); }

// Rebind the Grid to repopulate the original values table.


tableCopied = false;
GridView1.DataBind();
}

protected bool IsRowModified(GridViewRow r)


{
int currentID;
string currentTitleOfCourtesy;
string currentLastName;
string currentFirstName;
string currentTitle;
string currentExtension;

currentID = Convert.ToInt32(GridView1.DataKeys[0].Value);

currentTitleOfCourtesy = ((TextBox)r.FindControl("TitleOfCourtesyTextBox")).Text;
currentLastName = ((TextBox)r.FindControl("LastNameTextBox")).Text;
currentFirstName = ((TextBox)r.FindControl("FirstNameTextBox")).Text;
currentTitle = ((TextBox)r.FindControl("TitleTextBox")).Text;
currentExtension = ((TextBox)r.FindControl("ExtensionTextBox")).Text;

DataRow row =
originalDataTable.Select(String.Format("EmployeeID = {0}", currentID))[0];

if (!currentTitleOfCourtesy.Equals(row["TitleOfCourtesy"].ToString())) { return tr
ue; }
if (!currentLastName.Equals(row["LastName"].ToString())) { return true; }
if (!currentFirstName.Equals(row["FirstName"].ToString())) { return true; }
if (!currentTitle.Equals(row["Title"].ToString())) { return true; }
if (!currentExtension.Equals(row["Extension"].ToString())) { return true; }

return false;
}

Note
The procedure performs a string comparison using the value in each editable TextBox control and the value stored in t
he cached DataTable object. If you have formatted the text in the TextBox control, the values might be equivalent, but
their string representations will not match. For example, if you have formatted a DateTime value using the small date fo
rmat ({0:d}), the value in the date TextBox control might be 3/2/2005. The string representation of the date value fro
m the DataTable object would be 3/2/2005 12:00 AM. In these cases, you must add comparison logic that takes forma
ts and localization settings into account.

The procedure iterates through the rows of the GridView control and calls the custom IsRowModified function for each
row. The function compares the current row to the corresponding row in the DataTable object, and returns true if the
row has changed. For any rows that have changed, the code in the button's Click handler calls the UpdateRow method of
the GridView control.

Testing the Page


You can now run the page to test the code.
To test the page
1. Press CTRL+F5 to run the page.
The page appears in the browser. The GridView control displays the data rows from the Northwind Employees table in
editable pages of data.
2. Modify some values.
3. Click Update.
The modified rows are updated in the database.
4. Close the browser.
Next Steps
This walkthrough has illustrated how you can extend the functionality of the GridView control to enable updates of multiple
rows of data on an ASP.NET Web page. You may also want to extend your application to enable users to add new data rows
using a DetailsView or FormView control. You can also enable users to work with controls other than a TextBox control to
edit values, such as a DropDownList control. For more information, see the following topics:
Walkthrough: Creating Master/Detail Web Pages in Visual Studio
Walkthrough: Editing and Inserting Data in Web Pages with the DetailsView Web Server Control
Walkthrough: Displaying a Drop-Down List While Editing in the GridView Web Server Control
See Also
Tasks
How to: Secure Connection Strings When Using Data Source Controls
Walkthrough: Displaying a Drop-Down List While Editing in the GridView Web Server Control
Walkthrough: Basic Data Access in Web Pages
Visual Web Developer

Walkthrough Topics — GridView Web Server Control (Visual


Studio)
The following walkthrough topics demonstrate how to use the GridView control, which allows you to select, sort, and edit the
values of a data source, and then display them in a table.
Walkthrough Topics
Walkthrough: Displaying Data Using a Stored Procedure in the GridView Web Server Control
Walkthrough: Simple Sorting for the GridView Web Server Control
Walkthrough: Displaying a Drop-Down List While Editing in the GridView Web Server Control
Walkthrough: Creating a Nested GridView Control
Walkthrough: Performing Bulk Updates to Rows Bound to a GridView Web Server Control
See Also
Other Resources
GridView Web Server Control (Visual Studio)
Visual Web Developer

How-to Topics — GridView Web Server Control (Visual Studio)


The following procedures describe how to configure the features of the GridView control, which allows you to select, sort, and
edit the values of a data source, and display them in a table.
How-to Topics
How to: Enable Default Paging in the GridView Web Server Control
How to: Enable Default Selection in the GridView Web Server Control
How to: Enable Default Editing in the GridView Web Server Control
How to: Customize Controls for Editing in the GridView Web Server Control
How to: Enable Default Deleting in the GridView Web Server Control
How to: Set GridView Web Server Control Column Width Dynamically
See Also
Other Resources
GridView Web Server Control (Visual Studio)
Visual Web Developer

DetailsView Web Server Control (Visual Studio)


The DetailsView control displays a single record from a data source in a table, where each data row represents a field in the
record. It is often used in combination with a GridView control for master/detail scenarios. This section contains topics about
the DetailsView control.
In This Section
DetailsView Web Server Control Overview
Paging in a DetailsView Web Server Control
Modifying Data Using a DetailsView Web Server Control
Creating a Custom Row in a DetailsView Web Server Control
DetailsView Web Server Control Events
See Also
Concepts
ASP.NET Web Server Controls Templates
Other Resources
Data Toolbox Controls
ASP.NET Data Access (Visual Studio)
ASP.NET

DetailsView Web Server Control Overview


The DetailsView control gives you the ability to display, edit, insert, or delete a single record at a time from its associated data
source. By default, the DetailsView control displays each field of a record on its own line. The DetailsView control is typically
used for updating and inserting new records, often in a master/detail scenario where the selected record of the master control
determines the record to display in the DetailsView control. The DetailsView control displays only a single data record at a
time, even if its data source exposes multiple records.
The DetailsView control relies on the capabilities of the data source control to perform tasks such as updating, inserting, and
deleting records. The DetailsView control does not support sorting.
The DetailsView control can automatically page over the data in its associated data source, provided that the data is
represented by an object supporting the ICollection interface or that the underlying data source supports paging. The
DetailsView control provides the user interface (UI) for navigating between data records. To enable paging behavior, set the
AllowPaging property to true.
You select a particular record from the associated data source by paging to that record. The record displayed by the
DetailsView control is the current selected record.
Data Binding with the DetailsView Control
The DetailsView control provides you with these options for binding to data:
Data binding using the DataSourceID property, which allows you to bind the DetailsView control to a data source
control. This is the recommended approach because it allows the DetailsView control to take advantage of the
capabilities of the data source control and to provide built-in functionality for updating and paging.
Data binding using the DataSource property, which allows you to bind to various objects, including ADO.NET datasets
and data readers. This approach requires you to write the code for any additional functionality such as updating and
paging.
When you bind to a data source using the DataSourceID property, the DetailsView control supports two-way data binding.
In addition to the control displaying data, you can enable the control to automatically support insert, update, and delete
operations on the bound data.
Working with the DetailsView Control Data
The DetailsView control binds to a data source control, which in turn handles the tasks of connecting to a data store and
returning the selected data. Binding the DetailsView control to data is as simple as setting the DataSourceID property
declaratively. You can also bind to a data source in code.
To enable editing, set the AutoGenerateEditButton property to true. The DetailsView control will then render an Edit button in
addition to the data fields. Clicking the Edit button causes the DetailsView control to enter edit mode. In edit mode, the
DetailsView control's CurrentMode property changes from ReadOnly to Edit and each field of the control renders its edit UI,
such as a text box or check box. You can also customize the edit UI by using styles, DataControlField objects, and templates.
Note
For the DetailsView control to support editing, the bound data source must support update operations on the data.

You can configure the DetailsView control to display a Delete and an Insert button so that you can delete the corresponding
data record from the data source or insert a new data record. Similar to the AutoGenerateEditButton property, when the
AutoGenerateInsertButton property is set to true on the DetailsView control, it renders a New button. When the New button
is clicked, the DetailsView control's CurrentMode property changes to Insert. The DetailsView control renders appropriate
UI input controls for each bound field, unless the InsertVisible property of the bound field is set to false.
Customizing the DetailsView Control User Interface
The DetailsView control supports a Fields collection property, which contains DataControlField objects of type BoundField,
CommandField, or HyperLinkField. This is similar in function to the Columns collection of the GridView control, except that the
DetailsView control renders each field as a row instead of a column.
As with the GridView control, you can customize the UI of the DetailsView control by using style properties such as the
HeaderStyle, RowStyle, AlternatingRowStyle, CommandRowStyle, FooterStyle, PagerStyle, and EmptyDataRowStyle properties.
The DetailsView control offers you additional customization through templates, which give you more control over the
rendering of certain elements. You can define your own EmptyDataTemplate, HeaderTemplate, FooterTemplate, and
PagerTemplate properties for the DetailsView control. You can also create a template for an individual field by adding a
TemplateField object to the Fields collection.
The DetailsView control exposes several events that you can handle to execute your own code. The events are raised before
and after the insert, update, and and delete operations of the associated data source control. You can also write handlers for
the ItemCreated and ItemCommand events. For more information, see DetailsView Web Server Control Events.
Note
The event model of the DetailsView control is similar to that of the GridView control. However, the DetailsView control do
es not support a selection event, because the current record is always the selected item.

See Also
Reference
GridView Web Server Control Overview
ASP.NET

Paging in a DetailsView Web Server Control


The ASP.NET DetailsView control has built-in support to enable users to page through records one at a time. The control also
supports customizing the paging user interface (UI). In the DetailsView control, a page of data is a single bound row.
How Paging Works in the DetailsView Control
The DetailsView control supports paging over the records in its data source. To enable paging behavior, you set the
AllowPaging property to true. The page size requested by the DetailsView control is always one row.
If the DetailsView control is bound to a data source control or to any data structure that implements the ICollection interface
(including datasets), the control gets all the records from the data source, displays the record for the current page, and discards
the rest. When the user moves to another page, the DetailsView control repeats the process, displaying a different record.
Note
If the data source does not implement the ICollection interface, the DetailsView control cannot page. For example, if you ar
e using a SqlDataSource control and have set its DataSourceMode property to DataReader, the DetailsView control cannot i
mplement paging.

Some data sources, such as the ObjectDataSource control, offer more advanced paging capabilities. In these cases the
DetailsView control takes advantage of the data source's more advanced capabilities to gain better performance and
flexibility while paging. The number of rows requested may vary depending on whether the data source supports getting the
total row count.
Note
If you are creating a data source (such as implementing a SelectCountMethod method in the source object for the ObjectDa
taSource control), it is strongly recommended that your data source return the total row count when supplying pages of dat
a. This minimizes the number of records that the DetailsView control must request in order to retrieve a page of data. If the
total row count is supplied by the source data object, the DetailsView control will request only a single row at a time for eac
h page. If the total row count is not supplied, the DetailsView control must request all rows from the data source (starting w
ith the row that represents the requested page of data) and discard all rows except the row being displayed.

Customizing the Paging Settings and User Interface


You can customize the user interface (UI) of the DetailsView paging in a number of ways.
Paging Modes
The PagerSettings property enables you to customize the appearance of the paging user interface (UI) generated by the
DetailsView control when you set the AllowPaging property to true. The DetailsView control can display direction controls
that enable forward and backward navigation as well as numeric controls that enable a user to move to a specific page.
The PagerSettings property of the DetailsView control is set to a PagerSettings class. You can customize the paging mode by
setting the Mode property of the DetailsView control to a PagerButtons value. For example, you can customize the paging UI
mode by setting it as follows:

DetailsView1.PagerSettings.Mode = PagerButtons.NextPreviousFirstLast

The available modes are:


NextPrevious
NextPreviousFirstLast
Numeric
NumericFirstLast
Pager Control Appearance
The DetailsView control has numerous properties that you can use to customize the text and images for different pager
modes. For example, if you set the paging mode of a DetailsView control to NextPrevious and want to customize the text
that is displayed, you can set the NextPageText and PreviousPageText properties to your own values. By default, the
PreviousPageText and NextPageText properties are set to "<" and ">", respectively.
You can also use images to customize the appearance of your paging controls. The PagerSettings class includes image URL
properties for the first, last, previous, and next page command buttons.
Finally, you can control the appearance of the paging commands by setting the PagerStyle property of the DetailsView
control to a TableItemStyle value.
Data Paging Template
If you set the AllowPaging property of the DetailsView control to true, the DetailsView control automatically adds user
interface (UI) controls for paging. You can customize the UI for paging by adding a PagerTemplate template. To specify which
paging operation to perform, add a Button control to the template, and then set its CommandName property to Page and its
CommandArgument property to one of the following values:
First To navigate to the first page.
Last To navigate to the last page.
Prev To navigate to the previous page.
Next To navigate to the next page of data
A number To indicate a specific page.
The following code example shows a DetailsView control configured to provide paging.
VB
<%@ Page language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>DetailsView Example</title>
</head>
<body>
<form id="form1" runat="server">
<h3>DetailsView Example</h3>
<table cellspacing="10">
<tr>
<td valign="top">
<asp:DetailsView ID="EmployeesDetailsView"
DataSourceID="EmployeesSqlDataSource"
AutoGenerateRows="false"
AllowPaging="true"
DataKeyNames="EmployeeID"
runat="server">
<HeaderStyle forecolor="white" backcolor="Blue" />

<Fields>
<asp:BoundField Datafield="EmployeeID" HeaderText="Employee ID" ReadOnly=
"true"/>
<asp:BoundField Datafield="FirstName" HeaderText="First Name"/>
<asp:BoundField Datafield="LastName" HeaderText="Last Name"/>
</Fields>

<PagerSettings Mode="NextPreviousFirstLast"
FirstPageText="<<"
LastPageText=">>"
PageButtonCount="1"
Position="Top"/>
</asp:DetailsView>
</td>
</tr>
</table>

<asp:SqlDataSource ID="EmployeesSqlDataSource"
SelectCommand="SELECT * FROM [Employees]"
connectionstring="<%$ ConnectionStrings:NorthwindConnection %>"
RunAt="server"/>

</form>
</body>
</html>

C#
<%@ Page language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>DetailsView Example</title>
</head>
<body>
<form id="form1" runat="server">
<h3>DetailsView Example</h3>
<table cellspacing="10">
<tr>
<td valign="top">

<asp:DetailsView ID="EmployeesDetailsView"
DataSourceID="EmployeesSqlDataSource"
AutoGenerateRows="false"
AllowPaging="true"
DataKeyNames="EmployeeID"
runat="server">

<HeaderStyle forecolor="white" backcolor="Blue" />


<Fields>
<asp:BoundField Datafield="EmployeeID" HeaderText="Employee ID" ReadOnly=
"true"/>
<asp:BoundField Datafield="FirstName" HeaderText="First Name"/>
<asp:BoundField Datafield="LastName" HeaderText="Last Name"/>

</Fields>

<PagerSettings Mode="NextPreviousFirstLast"
FirstPageText="<<"
LastPageText=">>"
PageButtonCount="1"
Position="Top"/>
</asp:DetailsView>

</td>
</tr>
</table>

<asp:SqlDataSource ID="EmployeesSqlDataSource"
SelectCommand="SELECT * FROM [Employees]"
connectionstring="<%$ ConnectionStrings:NorthwindConnection %>"
RunAt="server"/>

</form>
</body>
</html>
See Also
Other Resources
DetailsView Web Server Control
ASP.NET

Modifying Data Using a DetailsView Web Server Control


The DetailsView control has built-in functionality for allowing users to edit or delete records without requiring programming.
You can customize the editing functionality of the DetailsView control using events and templates.
Enabling the Built-In Editing Functionality
You can enable the built-in editing functionality of the DetailsView control by setting one or more of the
AutoGenerateEditButton, AutoGenerateInsertButton, and AutoGenerateDeleteButton properties to true. The DetailsView
control will automatically add the functionality to allow users to edit or delete the current bound record and to insert a new
record, provided the data source for the DetailsView control supports edits.
How the DetailsView Control Modifies Bound Data
The DetailsView control provides a user interface (UI) that allows users to modify the contents of a bound record. Typically, an
editable view displays an additional row that contains command buttons with the text Edit, Insert, and Delete. By default, the
row is added to the bottom of the DetailsView control.
When the user clicks a command button, the DetailsView control redisplays the row with controls that allow users to modify
the contents of the row. The edit button is replaced with buttons that allow the user to save changes or cancel editing a row.
The DetailsView control uses text boxes to display data in a BoundField and for data displayed automatically when the
AutoGenerateRows property is set to true. Boolean data is displayed using check boxes. You can customize the input control
displayed in edit mode by using a TemplateField. For more information, see
Creating a Custom Row in a DetailsView Web Server Control.
When the DetailsView control is performing an insert operation, it passes the values to be inserted in the data source using
the Values dictionary collection.
For an update or delete operation, the DetailsView control passes values to the data source in three dictionary collections: the
Keys dictionary, the NewValues dictionary, and the OldValues dictionary. You can access each dictionary using the event
arguments passed to the insert, update, or delete events raised by the DetailsView control.
The Keys dictionary contains the names and values of fields that uniquely identify the record to update or delete, and always
contains the original values of the key fields before the record was edited. To specify which fields are placed in the Keys
dictionary, set the DataKeyNames property to a comma-separated list of field names that represent the primary key of your
data. The Keys collection is automatically populated with the values associated with the fields specified for the
DataKeyNames property.
Note
The original primary key values for the fields specified in the DataKeyNames property are stored in view state. If your prima
ry key values contain sensitive information, you should encrypt the view state contents by setting the page's
ViewStateEncryptionMode property to Always.

The Values and NewValues dictionaries contain the current values from the input controls in the record being inserted or
edited, respectively. The OldValues dictionary contains any original values of fields except the key fields, which are included in
the Keys dictionary. New values for key fields are included in the NewValues dictionary.
The data source control uses the values from the Keys, Values, NewValues, and OldValues dictionaries as parameters for its
insert, update, or delete command. For information on how data source control parameters are created based on the
dictionaries created for bound values, see How a Data Source Control Creates Parameters for Data-bound Fields.
After an update, the DetailsView control raises its ItemUpdated event. This event allows you to perform post-update logic,
such as integrity checks. Similarly, the DetailsView control raises its ItemInserted event after an insert and its ItemDeleted
event after a delete.
After the update is complete and all events have been raised, the DetailsView control rebinds to the data source control to
display the updated data.
Customizing the Editing User Interface in the DetailsView Control
By default, the DetailsView control automatically generates a row for each bound field from the data source. You can
customize which fields are bound to the DetailsView control by setting the AutoGenerateRows property to false and
specifying a BoundField control for each field that you want displayed in the DetailsView control.
To customize how command buttons are displayed, you can set the DetailsView control's AutoGenerateEditButton
property to false. You can then add individual CommandField objects for a row. For example, to place the current displayed
row into edit mode, you can add a CommandField field with the ShowEditButton property set to true.
You can specify whether a bound field is editable using the ReadOnly property of the BoundField control. When the
ReadOnly property is set to false, the field will be editable when the user clicks the Edit command button. When the
ReadOnly property is true, the bound field will be displayed, but the user will not be able to edit the field.
Similarly, you can specify whether a value can be inserted for a bound field using the InsertVisible property of the BoundField
control. If the InsertVisible property is false, then the bound field will not be displayed when the user clicks the New
command button. This is especially useful when the bound field is automatically generated by the data source, such as a date
and time stamp or an auto-incrementing primary key.
Example
The following code example uses a GridView control and a DetailsView control to display data. The DetailsView control is
configured to allow the data to be modified.
VB
<%@ Page language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">

Sub EmployeesDropDownList_OnSelectedIndexChanged(sender As Object, e As EventArgs)


EmployeeDetailsView.DataBind()
End Sub
Sub EmployeeDetailsView_ItemUpdated(sender As Object, e As DetailsViewUpdatedEventArgs)
EmployeesDropDownList.DataBind()
EmployeesDropDownList.SelectedValue = e.Keys("EmployeeID").ToString()
EmployeeDetailsView.DataBind()
End Sub

Sub EmployeeDetailsView_ItemDeleted(sender As Object, e As DetailsViewDeletedEventArgs)


EmployeesDropDownList.DataBind()
End Sub

Sub EmployeeDetailsSqlDataSource_OnInserted(sender As Object, e As SqlDataSourceStatusEve


ntArgs)
Dim command As System.Data.Common.DbCommand = e.Command
EmployeesDropDownList.DataBind()
EmployeesDropDownList.SelectedValue = _
command.Parameters("@EmpID").Value.ToString()
EmployeeDetailsView.DataBind()
End Sub

</script>

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>Northwind Employees</title>
</head>
<body>
<form id="form1" runat="server">

<h3>Northwind Employees</h3>

<table cellspacing="10">
<tr>
<td valign="top">
<asp:DropDownList ID="EmployeesDropDownList"
DataSourceID="EmployeesSqlDataSource"
DataValueField="EmployeeID"
DataTextField="FullName"
AutoPostBack="True"
OnSelectedIndexChanged="EmployeesDropDownList_OnSelectedIndexChanged"
RunAt="Server" />
</td>

<td valign="top">
<asp:DetailsView ID="EmployeeDetailsView"
DataSourceID="EmployeeDetailsSqlDataSource"
AutoGenerateRows="false"
AutoGenerateInsertbutton="true"
AutoGenerateEditbutton="true"
AutoGenerateDeletebutton="true"
DataKeyNames="EmployeeID"
Gridlines="Both"
OnItemUpdated="EmployeeDetailsView_ItemUpdated"
OnItemDeleted="EmployeeDetailsView_ItemDeleted"
RunAt="server">
<HeaderStyle backcolor="Navy"
forecolor="White"/>

<RowStyle backcolor="White"/>

<AlternatingRowStyle backcolor="LightGray"/>

<EditRowStyle backcolor="LightCyan"/>
<Fields>
<asp:BoundField DataField="EmployeeID" HeaderText="Employee ID" InsertVis
ible="False" ReadOnly="true"/>
<asp:BoundField DataField="FirstName" HeaderText="First Name"/>
<asp:BoundField DataField="LastName" HeaderText="Last Name"/>

<asp:BoundField DataField="Address" HeaderText="Address"/>


<asp:BoundField DataField="City" HeaderText="City"/>

<asp:BoundField DataField="Region" HeaderText="Region"/>


<asp:BoundField DataField="PostalCode" HeaderText="Postal Code"/>

</Fields>
</asp:DetailsView>
</td>
</tr>
</table>

<asp:SqlDataSource ID="EmployeesSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName + ', ' + FirstName AS FullName FROM Em
ployees"
Connectionstring="<%$ ConnectionStrings:NorthwindConnection %>"
RunAt="server">
</asp:SqlDataSource>

<asp:SqlDataSource ID="EmployeeDetailsSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName, FirstName, Address, City, Region, Pos
talCode
FROM Employees WHERE EmployeeID = @EmpID"

InsertCommand="INSERT INTO Employees(LastName, FirstName, Address, City, Region,


PostalCode)
VALUES (@LastName, @FirstName, @Address, @City, @Region, @PostalCo
de);
SELECT @EmpID = SCOPE_IDENTITY()"

UpdateCommand="UPDATE Employees SET LastName=@LastName, FirstName=@FirstName, Add


ress=@Address,
City=@City, Region=@Region, PostalCode=@PostalCode
WHERE EmployeeID=@EmployeeID"
DeleteCommand="DELETE Employees WHERE EmployeeID=@EmployeeID"

ConnectionString="<%$ ConnectionStrings:NorthwindConnection %>"


OnInserted="EmployeeDetailsSqlDataSource_OnInserted"
RunAt="server">

<SelectParameters>
<asp:ControlParameter ControlID="EmployeesDropDownList" PropertyName="SelectedV
alue"
Name="EmpID" Type="Int32" DefaultValue="0" />
</SelectParameters>

<InsertParameters>
<asp:Parameter Name="LastName" Type="String" />
<asp:Parameter Name="FirstName" Type="String" />
<asp:Parameter Name="Address" Type="String" />
<asp:Parameter Name="City" Type="String" />
<asp:Parameter Name="Region" Type="String" />
<asp:Parameter Name="PostalCode" Type="String" />
<asp:Parameter Name="EmpID" Direction="Output" Type="Int32" DefaultValue="0" />
</InsertParameters>

<UpdateParameters>
<asp:Parameter Name="LastName" Type="String" />
<asp:Parameter Name="FirstName" Type="String" />
<asp:Parameter Name="Address" Type="String" />
<asp:Parameter Name="City" Type="String" />
<asp:Parameter Name="Region" Type="String" />
<asp:Parameter Name="PostalCode" Type="String" />
<asp:Parameter Name="EmployeeID" Type="Int32" DefaultValue="0" />
</UpdateParameters>

<DeleteParameters>
<asp:Parameter Name="EmployeeID" Type="Int32" DefaultValue="0" />
</DeleteParameters>

</asp:SqlDataSource>
</form>
</body>
</html>

C#
<%@ Page language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">

void EmployeesDropDownList_OnSelectedIndexChanged(Object sender, EventArgs e)


{
EmployeeDetailsView.DataBind();
}
void EmployeeDetailsView_ItemUpdated(Object sender, DetailsViewUpdatedEventArgs e)
{
EmployeesDropDownList.DataBind();
EmployeesDropDownList.SelectedValue = e.Keys["EmployeeID"].ToString();
EmployeeDetailsView.DataBind();
}

void EmployeeDetailsView_ItemDeleted(Object sender, DetailsViewDeletedEventArgs e)


{
EmployeesDropDownList.DataBind();
}
void EmployeeDetailsSqlDataSource_OnInserted(Object sender, SqlDataSourceStatusEventArgs
e)
{
System.Data.Common.DbCommand command = e.Command;
EmployeesDropDownList.DataBind();
EmployeesDropDownList.SelectedValue =
command.Parameters["@EmpID"].Value.ToString();
EmployeeDetailsView.DataBind();
}

</script>

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>Northwind Employees</title>
</head>
<body>
<form id="form1" runat="server">

<h3>Northwind Employees</h3>

<table cellspacing="10">

<tr>
<td valign="top">
<asp:DropDownList ID="EmployeesDropDownList"
DataSourceID="EmployeesSqlDataSource"
DataValueField="EmployeeID"
DataTextField="FullName"
AutoPostBack="True"
OnSelectedIndexChanged="EmployeesDropDownList_OnSelectedIndexChanged"
RunAt="Server" />
</td>
<td valign="top">
<asp:DetailsView ID="EmployeeDetailsView"
DataSourceID="EmployeeDetailsSqlDataSource"
AutoGenerateRows="false"
AutoGenerateInsertbutton="true"
AutoGenerateEditbutton="true"
AutoGenerateDeletebutton="true"
DataKeyNames="EmployeeID"
Gridlines="Both"
OnItemUpdated="EmployeeDetailsView_ItemUpdated"
OnItemDeleted="EmployeeDetailsView_ItemDeleted"
RunAt="server">

<HeaderStyle backcolor="Navy"
forecolor="White"/>
<RowStyle backcolor="White"/>

<AlternatingRowStyle backcolor="LightGray"/>

<EditRowStyle backcolor="LightCyan"/>

<Fields>
<asp:BoundField DataField="EmployeeID" HeaderText="Employee ID" InsertVis
ible="False" ReadOnly="true"/>
<asp:BoundField DataField="FirstName" HeaderText="First Name"/>
<asp:BoundField DataField="LastName" HeaderText="Last Name"/>

<asp:BoundField DataField="Address" HeaderText="Address"/>

<asp:BoundField DataField="City" HeaderText="City"/>


<asp:BoundField DataField="Region" HeaderText="Region"/>
<asp:BoundField DataField="PostalCode" HeaderText="Postal Code"/>
</Fields>
</asp:DetailsView>
</td>
</tr>
</table>
<asp:SqlDataSource ID="EmployeesSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName + ', ' + FirstName AS FullName FROM Em
ployees"
Connectionstring="<%$ ConnectionStrings:NorthwindConnection %>"
RunAt="server">
</asp:SqlDataSource>

<asp:SqlDataSource ID="EmployeeDetailsSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName, FirstName, Address, City, Region, Pos
talCode
FROM Employees WHERE EmployeeID = @EmpID"

InsertCommand="INSERT INTO Employees(LastName, FirstName, Address, City, Region,


PostalCode)
VALUES (@LastName, @FirstName, @Address, @City, @Region, @PostalCo
de);
SELECT @EmpID = SCOPE_IDENTITY()"

UpdateCommand="UPDATE Employees SET LastName=@LastName, FirstName=@FirstName, Add


ress=@Address,
City=@City, Region=@Region, PostalCode=@PostalCode
WHERE EmployeeID=@EmployeeID"
DeleteCommand="DELETE Employees WHERE EmployeeID=@EmployeeID"

ConnectionString="<%$ ConnectionStrings:NorthwindConnection %>"


OnInserted="EmployeeDetailsSqlDataSource_OnInserted"
RunAt="server">

<SelectParameters>
<asp:ControlParameter ControlID="EmployeesDropDownList" PropertyName="SelectedV
alue"
Name="EmpID" Type="Int32" DefaultValue="0" />
</SelectParameters>

<InsertParameters>
<asp:Parameter Name="LastName" Type="String" />
<asp:Parameter Name="FirstName" Type="String" />
<asp:Parameter Name="Address" Type="String" />
<asp:Parameter Name="City" Type="String" />
<asp:Parameter Name="Region" Type="String" />
<asp:Parameter Name="PostalCode" Type="String" />
<asp:Parameter Name="EmpID" Direction="Output" Type="Int32" DefaultValue="0" />
</InsertParameters>

<UpdateParameters>
<asp:Parameter Name="LastName" Type="String" />
<asp:Parameter Name="FirstName" Type="String" />
<asp:Parameter Name="Address" Type="String" />
<asp:Parameter Name="City" Type="String" />
<asp:Parameter Name="Region" Type="String" />
<asp:Parameter Name="PostalCode" Type="String" />
<asp:Parameter Name="EmployeeID" Type="Int32" DefaultValue="0" />
</UpdateParameters>
<DeleteParameters>
<asp:Parameter Name="EmployeeID" Type="Int32" DefaultValue="0" />
</DeleteParameters>

</asp:SqlDataSource>
</form>
</body>
</html>

See Also
Reference
DetailsView Web Server Control Overview
ASP.NET

Creating a Custom Row in a DetailsView Web Server Control


The DetailsView control can automatically generate rows from the fields provided by the data source. In addition, you can
specifically identify a collection of rows to be displayed instead of automatically generating them. However, you might
encounter a scenario where you need to customize how an individual row is displayed. In that case, you can create a
TemplateField to specify a custom layout.
Creating Templates
A TemplateField object enables you to specify templates that contain markup and controls to customize the layout and
behavior of a row in a DetailsView control. Using an ItemTemplate, you can specify the layout to be used when the
DetailsView control displays a row. To specify a custom layout for when users insert a new data row, you can create a
InsertItemTemplate. To specify a custom layout for when users edit a data row, you can create an EditItemTemplate.
Your template can contain markup, Web server controls, and command buttons. For more information on templates, see
ASP.NET Web Server Controls Templates.
Data Binding in a Template
In a template, you can bind controls to data using the Eval and Bind methods. You use the Eval method when the control will
only display values. You use the Bind method when users can modify a data value—that is, for data-update scenarios. You can
use the Eval method in any of the templates to display data. You use the Bind method in a template with controls in which
users might change values, such as TextBox and CheckBox controls, or a template that allows a record to be deleted. For more
information, see Data-Binding Expression Syntax.
Example
The following example shows the Fields collection of a DetailsView control. The collection contains a TemplateField object,
which in turn contains ItemTemplate, InsertItemTemplate, EditItemTemplate objects. To display a date, the
ItemTemplate includes a Label control that uses the Eval method. To insert or edit a date, the other templates use a Calendar
control that uses the Bind method.
VB
<Fields>
<asp:BoundField DataField="EmployeeID" HeaderText="Employee ID" InsertVisible="False" Rea
dOnly="true"/>
<asp:BoundField DataField="FirstName" HeaderText="First Name"/>
<asp:BoundField DataField="LastName" HeaderText="Last Name"/>
<asp:TemplateField HeaderText="Birth Date">
<ItemTemplate>
<asp:Label ID="BirthDateLabel" Runat="Server"
Text='<%# Eval("BirthDate", "{0:d}") %>' />
</ItemTemplate>
<InsertItemTemplate>
<asp:Calendar ID="InsertBirthDateCalendar" Runat="Server"
SelectedDate='<%# Bind("BirthDate") %>' />
</InsertItemTemplate>
<EditItemTemplate>
<asp:Calendar ID="EditBirthDateCalendar" Runat="Server"
VisibleDate='<%# Eval("BirthDate") %>'
SelectedDate='<%# Bind("BirthDate") %>' />
</EditItemTemplate>
</asp:TemplateField>
</Fields>

C#
<Fields>
<asp:BoundField DataField="EmployeeID" HeaderText="Employee ID" InsertVisible="False" Rea
dOnly="true"/>
<asp:BoundField DataField="FirstName" HeaderText="First Name"/>
<asp:BoundField DataField="LastName" HeaderText="Last Name"/>
<asp:TemplateField HeaderText="Birth Date">
<ItemTemplate>
<asp:Label ID="BirthDateLabel" Runat="Server"
Text='<%# Eval("BirthDate", "{0:d}") %>' />
</ItemTemplate>
<InsertItemTemplate>
<asp:Calendar ID="InsertBirthDateCalendar" Runat="Server"
SelectedDate='<%# Bind("BirthDate") %>' />
</InsertItemTemplate>
<EditItemTemplate>
<asp:Calendar ID="EditBirthDateCalendar" Runat="Server"
VisibleDate='<%# Eval("BirthDate") %>'
SelectedDate='<%# Bind("BirthDate") %>' />
</EditItemTemplate>
</asp:TemplateField>
</Fields>

See Also
Reference
DetailsView Web Server Control Overview
Concepts
ASP.NET Data-Bound Web Server Controls Overview
Data Source Controls Overview
ASP.NET

DetailsView Web Server Control Events


The DetailsView control raises a number of events in the course of navigating and updating its bound data to which your code
can respond. For an example that uses some of the DetailsView events, see
Modifying Data Using a DetailsView Web Server Control.
Navigation Events
The DetailsView control raises events that occur when the current record is displayed or changed. Events are also raised when
a command control such as a Button that is part of the DetailsView control has been clicked. The following table describes the
events exposed by the DetailsView control.
PageIndexChanging
Occurs when a Page button (a button with its CommandName property set to "Page") has been clicked, but before
navigating to a new page of data.
PageIndexChanged
Occurs when a Page button has been clicked, but after a navigating to a new page of data.
ItemCommand
Occurs when a button within a DetailsView control is clicked.
ItemCreated
Occurs when a record is created in a DetailsView control.
ItemDeleting
Occurs when a Delete button (a button with its CommandName property set to "Delete") within a DetailsView control is
clicked, but before the delete operation.
ItemDeleted
Occurs when a Delete button within a DetailsView control is clicked, but after the delete operation.
ItemInserting
Occurs when an Insert button (a button with its CommandName property set to "Insert") within a DetailsView control is
clicked, but before the insert operation.
ItemInserted
Occurs when an Insert button within a DetailsView control is clicked, but after the insert operation.
ItemUpdating
Occurs when an Update button (a button with its CommandName property set to "Update") within a DetailsView control
is clicked, but before the update operation.
ItemUpdated
Occurs when an Update button within a DetailsView control is clicked, but after the update operation.
ModeChanging
Occurs when a DetailsView control attempts to change between edit, insert, and read-only modes, but before the
CurrentMode property is updated.
ModeChanged
Occurs when a DetailsView control attempts to change between edit, insert, and read-only modes, but after the
CurrentMode property is updated.
DataBound
This event is inherited from the BaseDataBoundControl control and occurs after the DetailsView control has finished
binding to the data source.
See Also
Reference
DetailsView Web Server Control Overview
Other Resources
DetailsView Web Server Control
Visual Web Developer

FormView Web Server Control (Visual Studio)


The FormView control is used to display a single record from a data source in a table. When using the FormView control, you
specify templates to display and edit bound values. The templates contain formatting, controls, and binding expressions to
create the form. The FormView control is often used in combination with a GridView control for master/detail scenarios.
This section contains the following topics about the FormView control.
In This Section
FormView Web Server Control Overview
Walkthrough: Displaying Formatted Data in Web Pages with the FormView Web Server Control
Creating Templates for the FormView Web Server Control
Paging in a FormView Web Server Control
Modifying Data Using a FormView Web Server Control
FormView Web Server Control Events
See Also
Concepts
ASP.NET Web Server Controls Templates
Other Resources
Data Toolbox Controls
ASP.NET Data Access (Visual Studio)
ASP.NET

FormView Web Server Control Overview


The FormView control gives you the ability to work with a single record from a data source, similar to the DetailsView control.
The difference between the FormView and the DetailsView controls is that the DetailsView control uses a tabular layout
where each field of the record is displayed as a row of its own. In contrast, the FormView control does not specify a pre-
defined layout for displaying the record. Instead, you create a template containing controls to display individual fields from the
record. The template contains the formatting, controls, and binding expressions used to create the form.
The FormView control is typically used for updating and inserting new records, and is often used in master/detail scenarios
where the selected record of the master control determines the record to display in the FormView control. For more
information and an example, see Modifying Data Using a FormView Web Server Control.
The FormView control relies on the capabilities of the data source control to perform tasks such as updating, inserting, and
deleting records. The FormView control renders only a single data record at a time, even if its data source exposes multiple
records.
The FormView control can automatically page over the data in its associated data source one record at a time, provided that
the data is represented by an object implementing the ICollection interface, or that the underlying data source supports paging.
The FormView control provides the user interface (UI) for navigating between records. To enable paging behavior, set the
AllowPaging property to true and specify a PagerTemplate value.
The FormView control exposes several events that you can handle to execute your own code. The events are raised before and
after insert, update, and delete operations of the associated data source control. You can also write handlers for the
ItemCreated and ItemCommand events. For more information, see FormView Web Server Control Events.
Note
The event model of the FormView control is similar to that of the GridView control. However, the FormView control does n
ot support a selection event, because the current record is always the selected item.

Data Binding with the FormView Control


The FormView control provides you with these options for binding to data:
Data binding using the DataSourceID property, which allows you to bind the FormView control to a data source control.
This is the recommended approach because it allows the FormView control to take advantage of the capabilities of the
data source control and to provide built-in functionality for updating and paging.
Data binding using the DataSource property, which allows you to bind to various objects, including ADO.NET datasets
and data readers. This approach requires you to write the code for any additional functionality such as updating and
paging.
When you bind to a data source using the DataSourceID property, the FormView control supports two-way data binding. In
addition to the control displaying data, you can enable the control to automatically support insert, update, and delete
operations on the bound data.
For more information, see Data Source Web Server Controls.
Creating the FormView Control User Interface
You build the user interface (UI) for the FormView control by creating templates. You specify different templates for different
actions. You create an ItemTemplate template for display, insert, and edit modes. You can control paging using a
PagerTemplate template, and you can customize the FormView control's header and footer using a HeaderTemplate and
FooterTemplate, respectively. Using an EmptyDataTemplate, you can also specify a template to display when the data source
does not return any data. For more information, see Creating Templates for the FormView Web Server Control.
The item templates that you create for the FormView control specify the content of the control. As with the DetailsView
control, you can also customize the display format of the FormView control by using style properties such as the
EditRowStyle, EmptyDataRowStyle, FooterStyle, HeaderStyle, InsertRowStyle, PagerStyle, and RowStyle properties.
The following example shows a simple ASP.NET page that uses a FormView control to display data.
VB
<%@ Page language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>FormView Example</title>
</head>
<body>
<form id="form1" runat="server">
<h3>FormView Example</h3>
<table cellspacing="10">
<tr>
<td valign="top">
<asp:FormView ID="ProductsFormView"
DataSourceID="ProductsSqlDataSource"
AllowPaging="true"
runat="server">
<HeaderStyle forecolor="white" backcolor="Blue" />

<ItemTemplate>
<table>
<tr>
<td align="right"><b>Product ID:</b></td>
<td><asp:Label id="ProductIDLabel" runat="server" Text='<%# Eval("Pro
ductID") %>' /></td>
</tr>
<tr>
<td align="right"><b>Product Name:</b></td>
<td><asp:Label id="ProductNameLabel" runat="server" Text='<%# Eval("P
roductName") %>' /></td>
</tr>
<tr>
<td align="right"><b>Category ID:</b></td>
<td><asp:Label id="CategoryIDLabel" runat="server" Text='<%# Eval("Ca
tegoryID") %>' /></td>
</tr>
<tr>
<td align="right"><b>Quantity Per Unit:</b></td>
<td><asp:Label id="QuantityPerUnitLabel" runat="server" Text='<%# Eva
l("QuantityPerUnit") %>' /></td>
</tr>
<tr>
<td align="right"><b>Unit Price:</b></td>
<td><asp:Label id="UnitPriceLabel" runat="server" Text='<%# Eval("Uni
tPrice") %>' /></td>
</tr>
</table>
</ItemTemplate>

<PagerTemplate>
<table>
<tr>
<td><asp:LinkButton ID="FirstButton" CommandName="Page" CommandArgume
nt="First" Text="<<" RunAt="server"/></td>
<td><asp:LinkButton ID="PrevButton" CommandName="Page" CommandArgume
nt="Prev" Text="<" RunAt="server"/></td>
<td><asp:LinkButton ID="NextButton" CommandName="Page" CommandArgume
nt="Next" Text=">" RunAt="server"/></td>
<td><asp:LinkButton ID="LastButton" CommandName="Page" CommandArgume
nt="Last" Text=">>" RunAt="server"/></td>
</tr>
</table>
</PagerTemplate>

</asp:FormView>

</td>
</tr>
</table>

<asp:SqlDataSource ID="ProductsSqlDataSource"
SelectCommand="SELECT * FROM [Products]"
connectionstring="<%$ ConnectionStrings:NorthwindConnection %>"
RunAt="server"/>

</form>
</body>
</html>

C#
<%@ Page language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>FormView Example</title>
</head>
<body>
<form id="form1" runat="server">
<h3>FormView Example</h3>
<table cellspacing="10">
<tr>
<td valign="top">

<asp:FormView ID="ProductsFormView"
DataSourceID="ProductsSqlDataSource"
AllowPaging="true"
runat="server">

<HeaderStyle forecolor="white" backcolor="Blue" />

<ItemTemplate>
<table>
<tr>
<td align="right"><b>Product ID:</b></td>
<td><asp:Label id="ProductIDLabel" runat="server" Text='<%# Eval("Pro
ductID") %>' /></td>
</tr>
<tr>
<td align="right"><b>Product Name:</b></td>
<td><asp:Label id="ProductNameLabel" runat="server" Text='<%# Eval("P
roductName") %>' /></td>
</tr>
<tr>
<td align="right"><b>Category ID:</b></td>
<td><asp:Label id="CategoryIDLabel" runat="server" Text='<%# Eval("Ca
tegoryID") %>' /></td>
</tr>
<tr>
<td align="right"><b>Quantity Per Unit:</b></td>
<td><asp:Label id="QuantityPerUnitLabel" runat="server" Text='<%# Eva
l("QuantityPerUnit") %>' /></td>
</tr>
<tr>
<td align="right"><b>Unit Price:</b></td>
<td><asp:Label id="UnitPriceLabel" runat="server" Text='<%# Eval("Uni
tPrice") %>' /></td>
</tr>
</table>
</ItemTemplate>
<PagerTemplate>
<table>
<tr>
<td><asp:LinkButton ID="FirstButton" CommandName="Page" CommandArgume
nt="First" Text="<<" RunAt="server"/></td>
<td><asp:LinkButton ID="PrevButton" CommandName="Page" CommandArgume
nt="Prev" Text="<" RunAt="server"/></td>
<td><asp:LinkButton ID="NextButton" CommandName="Page" CommandArgume
nt="Next" Text=">" RunAt="server"/></td>
<td><asp:LinkButton ID="LastButton" CommandName="Page" CommandArgume
nt="Last" Text=">>" RunAt="server"/></td>
</tr>
</table>
</PagerTemplate>

</asp:FormView>

</td>
</tr>
</table>

<asp:SqlDataSource ID="ProductsSqlDataSource"
SelectCommand="SELECT ProductID, ProductName, CategoryID, QuantityPerUnit, UnitPr
ice FROM [Products]"
connectionstring="<%$ ConnectionStrings:NorthwindConnection %>"
RunAt="server"/>

</form>
</body>
</html>

See Also
Other Resources
FormView Web Server Control
Visual Web Developer

Walkthrough: Displaying Formatted Data in Web Pages with


the FormView Web Server Control
ASP.NET provides various controls that allow you to display and edit data records. In this walkthrough, you will work with the
FormView control, which works with a single data record at a time. The FormView control's primary feature is that it allows
you to create the record layout yourself by defining templates. By working with templates, you can have complete control over
the layout and appearance of the data within the control. The FormView control also supports updates such as editing,
inserting, and deleting data records. If the data source provides more than one record to the FormView control, the control
allows you to page through the records individually.
Note
You can also edit individual data records with the DetailsView control, which provides a predefined layout for the data. For de
tails, see DetailsView Web Server Control (Visual Studio).

Tasks illustrated in this walkthrough include:


Creating a page to display master/detail information.
Using a FormView control to create a free-form layout for a data record.
Configuring the FormView control to allow editing.
Prerequisites
In order to complete this walkthrough, you will need:
Microsoft Visual Web Developer.
Access to the SQL Server Northwind database. For information about downloading and installing the SQL Server sample
Northwind database, see Installing Sample Databases on the Microsoft SQL Server Web site.
Note
If you need information about how to log on to the computer running SQL Server, contact the server administrator.

Microsoft Data Access Components (MDAC) version 2.7 or later.


If you are using Microsoft Windows XP or Windows Server 2003, you already have MDAC 2.7. However, if you are using
Microsoft Windows 2000, you might need to upgrade the MDAC already installed on your computer. For more
information, see "Microsoft Data Access Components (MDAC) Installation" in the MSDN Library.
Creating the Web Site
Create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New, and then click Web Site. If you are using Visual Web Developer Express, on the File menu,
click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, enter the name of the folder where you want to keep the pages of your Web site.
For example, type the folder name C:\WebSites\FormViewData.
5. In the Language list, click the programming language you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Using a Drop-Down List as the Master
In this part of the walkthrough, you will add a drop-down list to a page and populate it with a list of product names. When
users select a product, the page will display the details for that product in a FormView control.
To create and populate a drop-down list
1. Switch to or open the Default.aspx page. If you are working with a Web site you had already created, add or open a page
that you can work with in this walkthrough.
2. Switch to Design view.
3. Type Display Product Information in the page.
4. From the Standard group in the Toolbox, drag a DropDownList control onto the page.
5. If the DropDownList Tasks menu does not appear, right-click the DropDownList control, and then click Show Smart
Tag.
6. On the DropDownList Tasks menu, select the Enable AutoPostBack check box.
7. Click Choose Data Source to open the Data Source Configuration Wizard.
8. In the Select a data source list, click <New Data Source>.
9. Click Database.
This specifies that you want to get data from a database that supports SQL statements.
In the Specify an ID for the data source box, a default data source control name is displayed. You can leave this name.
10. Click OK.
The wizard displays a page where you can select a connection.
11. Click the New Connection button.
The Add Connection dialog box appears.
If the Data source list does not display Microsoft SQL Server (SqlClient), click Change, and in the Change Data
Source dialog box, select Microsoft SQL Server.
If the Choose Data Source page appears, in the Data source list, select the type of data source you will use. For
this walkthrough, the data source type is Microsoft SQL Server. In the Data provider list, click .NET Framework
Data Provider for SQL Server, and then click Continue.
12. In the Add Connection dialog box, do the following:
a. In the Server name box, enter the name of the computer running SQL Server.
b. For the logon credentials, select the option that is appropriate to access the running the SQL Server database
(integrated security or specific ID and password) and, if required, enter a user name and password. Select the Save
my Password check box if you entered a password.
c. Select the Select or enter a database name button, and then enter Northwind.
d. Click Test connection, and when you are sure that the connection works, click OK.
You are returned to the wizard, and the connection information is filled in.
13. Click Next.
14. Be sure that the Yes, save this connection as check box is selected, and then click Next. (You can leave the default
connection string name.)
The wizard displays a page where you can specify what data you want to retrieve from the database.
15. Click Specify columns from a table or view.
16. In the Name list, click Products.
17. Under Columns, select ProductID and ProductName.
18. Click Next.
19. Click Test Query to be sure that you are retrieving the data you want.
20. Click Finish.
You are returned to the wizard.
21. In the Select a data field to display in the DropDownList list, click ProductName.
22. From the Select a data field for the value of the DropDownList list, select ProductID.
This specifies that when an item is selected, the ProductID field will be returned as the value of the item.
23. Click OK.
Before proceeding, test the drop-down list.
To test the drop-down list
1. Press CTRL+F5 to run the page.
2. When the page is displayed, examine the drop-down list.
3. Select a product name to be sure that the list performs a postback.
Adding a FormView Control
You will now add a FormView control to display product details. The FormView control gets its data from a second data
source control that you add to the page. The second data source control contains a parameterized query that gets the product
record for the item currently selected in the DropDownList control.
To add a FormView control
1. From the Data group in the Toolbox, drag a FormView control onto page.
2. If the FormView Tasks menu does not appear, right-click the FormView control, and then click Show Smart Tag.
3. On the FormView Tasks menu, in the Choose Data Source list, click <New Data Source>.
The Data Source Configuration Wizard dialog box appears.
4. Click Database.
The FormView control will get data from the same table as the DropDownList control.
In the Specify an ID for the data source box, a default data source control name is displayed. You can leave this name.
5. Click OK.
The Configure Data Source wizard starts.
6. From the Which data connection should your application use to connect to the database? list, select the
connection you created and stored earlier in the walkthrough.
7. Click Next.
The wizard displays a page where you can create a SQL statement.
8. From the Name list under Specify columns from a table or view, select Products.
9. In the Columns box, select ProductID, ProductName, and UnitPrice.
10. Click the WHERE button.
The Add WHERE Clause dialog box is displayed.
11. From the Column list, select ProductID.
12. From the Operator list, select =.
13. From the Source list, select Control.
14. Under Parameter properties, in the Control ID list, select DropDownList1.
The last two steps specify that the query will get the search value for the product ID from the DropDownList control you
added earlier.
15. Click Add.
16. Click OK to close the Add WHERE Clause dialog box.
17. Click Advanced.
The Advanced SQL Generation Options dialog box appears.
18. Select the Generate INSERT, UPDATE, and DELETE statements check box.
This option causes the wizard to create SQL update statements based on the Select statement you have configured. Later
in the walkthrough you will use the FormView control to edit and insert records, which requires update statements in
the data source control.
19. Click OK.
20. Click Next.
21. In the Preview page, click Test Query.
The wizard displays a dialog box that prompts you for a value to use in the WHERE clause.
22. In the Value box, type 4 and then click OK.
The product information appears.
23. Click Finish.
Customizing the Layout in the FormView Control
The reason to use the FormView control is that you can define the layout of the record that it displays. In this section of the
walkthrough, you will customize the record layout by editing a template. For your layout, you will use an HTML table.
To format the layout
1. Click the FormView control to select it, and then drag the resize handle on the right side of the control to make the
control as wide as the current page.
2. Drag the resize handle on the bottom of the control to change the height of the control to about 400 pixels. (The exact
height is not important.)
3. Right-click the control, click Edit Template, and then click ItemTemplate.
The control is redisplayed in item template editing mode. The item template contains the static text and controls that are
used to display the data record when the page runs. By default, Visual Web Developer populates the item template with a
data-bound Label control for each data column in the data source. In addition, Visual Web Developer generates static text
for each label to act as a caption.
The template is also generated with three LinkButton controls with the text Edit, Delete, and New.
4. Put the insertion point at the top of the item template, press ENTER a few times to make room, and then at the top of the
template type Product Details to act as a heading.
5. Put the insertion point below the controls and static text and, in the Layout menu, click Insert Table.
You are creating an HTML table as a container for the text and controls.
6. In the Insert Table dialog box, do the following:
a. Set Rows to 4.
b. Set Columns to 2.
c. Click the Cell Properties button, and set Width to 35 pixels (px) and Height to 30 pixels (px).
7. Click OK to close the Cell Properties dialog box, and then click OK to close the Insert Table dialog box.
8. Drag the ProductIdLabel control into the top right-hand cell.
9. Drag the ProductNameLabel control into the second right-hand cell.
10. Drag the UnitPriceLabel control into the third right-hand cell.
11. In the left-hand column, type static text to act as captions for the Label controls. For example, in the cell next to the
ProductIdLabel control, type ID. You can type any caption text that you like.
12. Right-click the left-hand column, click Select, and then click Column.
13. In the Properties window, set align to right to make the caption text right-aligned.
14. Select the right-hand column and drag its right-hand border to make the table wide enough to display long product
names.
15. Select the text generated by Visual Web Developer (for example, the text ProductID) and delete it.
16. Right-click the FormView control's title bar and click End Template Editing.
The template editor closes and the control appears with the layout you have created.
Testing the FormView Control
You can now test your layout.
To test the FormView control
1. Press CTRL+F5 to run the page.
2. In the DropDownList control, click a product name.
The FormView control displays details about that product.
3. Select a different product and confirm that the FormView control displays the product details.
4. Close the browser.
Adding Edit and Insert Capabilities to the FormView Control
The FormView control can display individual records and also supports editing, deleting, and inserting.
In this part of the walkthrough, you will add the ability to edit the currently displayed record. To edit the record, you define a
different template that contains text boxes (and potentially other controls).
To add editing capability to the FormView control
1. Right-click the FormView control, click Edit Template, and click EditItemTemplate.
The template editor appears, displaying the EditItemTemplate property, which defines how records are laid out when the
control is in edit mode. Visual Web Developer populates the edit template with a TextBox control for each data column
that is not a key and adds static text for captions. This is similar to the way the item template was generated, except that
in the edit template, Visual Web Developer generates text boxes.
As before, the template is generated with Update and Cancel LinkButton controls that are used to save and discard
changes while editing.
2. Optionally, add a layout table and arrange the controls as you did when working with the item template earlier in the
walkthrough.
3. Right-click the FormView control, click Edit Template, and then click InsertItemTemplate.
As with the EditItemTemplate property, Visual Web Developer automatically creates a template layout of labels and
TextBox controls. The controls will be displayed when users want to insert a new record into the Products table. The
template is also generated with Insert and Cancel LinkButton controls.
4. Optionally, add a layout table and arrange the controls as you did when working with the edit item template.
5. Right-click the FormView control and click End Template Editing.
Security Note
User input in an ASP.NET Web page can include potentially malicious client script. By default, ASP.NET Web pages valid
ate user input to make sure input does not include script or HTML elements. As long as this validation is enabled, you d
o not need to explicitly check for script or HTML elements in user input. For more information, see
Script Exploits Overview.

Testing Editing and Inserting


You can now test editing and inserting.
To test editing capabilities of the FormView control
1. Press CTRL+F5 to run the page.
2. Select a product in the DropDownList control.
The product details appear in the FormView control.
3. Click Edit.
The FormView control switches to edit mode.
4. Make a change to the product name or unit price.
5. Click Update.
The record is saved and the FormView control switches to display mode. The change is reflected in the display.
6. Select a different product.
7. Click Edit.
8. Make a change to the product name.
9. Click Cancel.
Confirm that the change was not saved.

To test insert capabilities of the FormView control


1. Click New in the FormView control.
The FormView control switches to insert mode, displaying two empty text boxes.
2. Enter a new product name and price, and then click Insert.
The record is saved in the database and the FormView control switches to display (ItemTemplate) view.
Note
The new record is not displayed in the drop-down list. You will add that capability in the next section.

Redisplaying Updated Product Names in the Drop-Down List


Your page now allows you to view, edit, or delete records in the Products database table. However, the drop-down list is not
yet synchronized with changes that you make in the FormView control. For example, if you insert a new Products record, the
drop-down list does not display the new record unless you close the page and reopen it. In addition, the page is displayed
initially with the first record in the Products table, which might not be what you want.
You can add some code to fix these minor issues. In this section of the walkthrough, you will do the following:
Update the drop-down list whenever users edit or insert a record.
Add the text "(Select)" to the drop-down list when the page first appears, and remove it when the user has made the first
selection.

To update the drop-down list when records are edited or inserted


1. In Design view of the page, select the FormView control.
2. In the Properties window, click the Events button to display a list of events for the FormView control.
3. Double-click the ItemInserted box.
Visual Web Developer switches to code-editing view and creates a handler for the ItemInserted event.
4. Add the following highlighted code to the event handler.
VB
Protected Sub FormView1_ItemInserted(ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.FormViewInsertedEventArgs) _
Handles FormView1.ItemInserted
DropDownList1.DataBind()
End Sub

C#
protected void FormView1_ItemInserted(object sender,
FormViewInsertedEventArgs e)
{
DropDownList1.DataBind();
}

The code runs after the new record has been inserted. It re-binds the drop-down list to the Products table, which causes
the contents of the list to be refreshed.
5. Switch to Design view. (If you are working with a code-behind page, switch to the Default.aspx page and then switch to
Design view.)
6. In the Properties window, click the Events button to display a list of events for the FormView control.
7. Double-click the ItemUpdated box.
Visual Web Developer switches to code-editing view and creates an event handler for the ItemUpdated event.
8. Add the following highlighted code.
VB
Protected Sub FormView1_ItemUpdated(ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.FormViewUpdatedEventArgs) _
Handles FormView1.ItemUpdated
DropDownList1.DataBind()
End Sub

C#
protected void FormView1_ItemUpdated(object sender,
FormViewUpdatedEventArgs e)
{
DropDownList1.DataBind();
}

The code runs after the record has been updated. It re-binds the drop-down list to the Products table, which causes the
contents of the list to be refreshed.
9. Press CTRL+F5 to run the page.
10. Edit the product name of a record, click Update, and then examine the drop-down list to be sure that the updated name
is displayed.
11. Insert a new product record, click Insert, and then examine the drop-down list to be sure that the new name has been
added to the list.
The final step is to change the drop-down list to display "(Select)" and to display the FormView control only when users have
made a selection.
To add a Select entry to the DropDownList control
1. In Design view, double-click a blank part of the page.
Visual Web Developer creates an event handler for the page's Load event.
2. In the handler, add the following highlighted code.
VB
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
FormView1.Visible = False
End If
End Sub

C#
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
FormView1.Visible = false;
}
}

The code runs when the page runs. It tests first to see if this is a postback; if not, this is the first time the page has run. If it
is not a postback, the code hides the FormView control, because you want to display it only when the user has explicitly
selected a record to view or edit.
3. In Design view for the page, select the DropDownList control.
4. In the Properties window, click the ellipsis (...) in the Items box.
The ListItem Collection Editor dialog box appears.
5. Click Add to create a new item.
6. Under ListItem properties, in the Text box, type (Select).
7. Click OK to close the ListItem Collection Editor dialog box.
8. In the Properties box, set AppendDataBoundItems to true.
When the drop-down list is populated during data binding, the product information will be added to the (Select) item
you defined.
9. In the Properties window, click the Events button to display a list of events for the DropDownList control.
10. Double-click the SelectedIndexChanged box.
11. Add the following highlighted code.
VB
Protected Sub DropDownList1_SelectedIndexChanged(ByVal sender _
As Object, ByVal e As System.EventArgs) _
Handles DropDownList1.SelectedIndexChanged
If DropDownList1.Items(0).Text = "(Select)" Then
DropDownList1.Items.RemoveAt(0)
End If
FormView1.Visible = True
End Sub
C#
protected void DropDownList1_SelectedIndexChanged(object sender,
EventArgs e)
{
if(DropDownList1.Items[0].Text == "(Select)")
{
DropDownList1.Items.RemoveAt(0);
}
FormView1.Visible = true;
}

The code runs when users select an item in the DropDownList control. It removes the "(Select)" item that you added
earlier (checking first to be sure it exists), because after the first time users have selected an item, you no longer need to
prompt them to select an item. The code also displays (un-hides) the FormView control so that users can see the record
they have selected.
12. Press CTRL+F5 to run the page.
The page displays only the drop-down list, with the word (Select) displayed.
13. Select an item in the list.
The item is displayed in the FormView control.
14. Examine the drop-down list and note that the word (Select) is no longer in the list.
Next Steps
This walkthrough has shown you the basic steps for using a FormView control to display and edit individual data records
using a custom layout. The FormView control allows you to perform more sophisticated formatting than what you have done
in this walkthrough. In addition, you can create templates for other modes, including selection mode and insertion mode, and
for headers and footers that are displayed with the record. For other scenarios to explore with the FormView, see the
following:
Creating Templates for the FormView Web Server Control
Modifying Data Using a FormView Web Server Control
See Also
Other Resources
FormView Web Server Control
DetailsView Web Server Control
ASP.NET

Creating Templates for the FormView Web Server Control


You can customize the FormView control by adding templates that allow the user to view or modify the data displayed by the
control. The contents of each template consist of markup, controls with data-binding expressions, and command buttons that
change the mode of the FormView control.
Note
For more information about data-binding expressions, see Data-Binding Expression Syntax.

Display Templates
The primary display template for the FormView control is the ItemTemplate template. The ItemTemplate template displays
bound data in read-only mode. The controls included in an ItemTemplate are controls that only display data, such as a Label
control. The template can also contain command buttons to change the FormView control's mode to insert or edit, or to delete
the current record. You bind controls in the template to data using a data-binding expression that includes the Eval method for
one-way data binding, as shown in the following example.
VB
<asp:FormView ID="FormView1"
DataSourceID="SqlDataSource1"
DataKeyNames="ProductID"
RunAt="server">

<ItemTemplate>
<table>
<tr><td align="right"><b>Product ID:</b></td> <td><%# Eval("ProductID") %></td>
</tr>
<tr><td align="right"><b>Product Name:</b></td> <td><%# Eval("ProductName") %></t
d></tr>
<tr><td align="right"><b>Category ID:</b></td> <td><%# Eval("CategoryID") %></td
></tr>
<tr><td align="right"><b>Quantity Per Unit:</b></td><td><%# Eval("QuantityPerUnit") %
></td></tr>
<tr><td align="right"><b>Unit Price:</b></td> <td><%# Eval("UnitPrice") %></td>
</tr>
</table>
</ItemTemplate>
</asp:FormView>

C#
<asp:FormView ID="FormView1"
DataSourceID="SqlDataSource1"
DataKeyNames="ProductID"
RunAt="server">

<ItemTemplate>
<table>
<tr><td align="right"><b>Product ID:</b></td> <td><%# Eval("ProductID") %></td>
</tr>
<tr><td align="right"><b>Product Name:</b></td> <td><%# Eval("ProductName") %></t
d></tr>
<tr><td align="right"><b>Category ID:</b></td> <td><%# Eval("CategoryID") %></td
></tr>
<tr><td align="right"><b>Quantity Per Unit:</b></td><td><%# Eval("QuantityPerUnit") %
></td></tr>
<tr><td align="right"><b>Unit Price:</b></td> <td><%# Eval("UnitPrice") %></td>
</tr>
</table>
</ItemTemplate>
</asp:FormView>
The ItemTemplate template can include LinkButton controls that change the mode of the FormView control based on the
CommandName value. A CommandName value of New puts the record into insert mode and loads the InsertItemTemplate
template, which allows the user to enter values for a new record. You can add a button with a CommandName value of Edit
to the ItemTemplate template to put the FormView control into edit mode. A button with a CommandName value of
Delete can be added to the ItemTemplate template to allow users to delete the current record from the data source.
The other display templates that you can use with the FormView control are the EmptyDataTemplate template, which is
displayed when there is no current record to bind to, and the HeaderTemplate template and FooterTemplate template, which
define the content of the header and footer, respectively.
Edit and Insert Templates
You can use the EditItemTemplate template to allow users to modify an existing record, and the InsertItemTemplate template
to gather values for a new record to be inserted into the data source. In the EditItemTemplate and InsertItemTemplate
templates you typically include controls that take user input, such as TextBox, CheckBox, or DropDownList controls. You might
also add controls to display read-only data, and command buttons to allow users to edit the current record, insert a new
record, or cancel current action. You bind controls in the EditItemTemplate and InsertItemTemplate templates to data
using a data-binding expression that includes the Bind method for two-way data binding, as shown in the following example.
VB
<asp:sqlDataSource ID="EmployeeDetailsSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName, FirstName FROM Employees WHERE EmployeeID = @
EmpID"

InsertCommand="INSERT INTO Employees(LastName, FirstName) VALUES (@LastName, @FirstName);


SELECT @EmpID = SCOPE_IDENTITY()"
UpdateCommand="UPDATE Employees SET LastName=@LastName, FirstName=@FirstName
WHERE EmployeeID=@EmployeeID"
DeleteCommand="DELETE Employees WHERE EmployeeID=@EmployeeID"

ConnectionString="<%$ ConnectionStrings:NorthwindConnection %>"


OnInserted="EmployeeDetailsSqlDataSource_OnInserted"
RunAt="server">

<SelectParameters>
<asp:Parameter Name="EmpID" Type="Int32" DefaultValue="0" />
</SelectParameters>

<InsertParameters>
<asp:Parameter Name="EmpID" Direction="Output" Type="Int32" DefaultValue="0" />
</InsertParameters>

</asp:sqlDataSource>

C#
<asp:sqlDataSource ID="EmployeeDetailsSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName, FirstName FROM Employees WHERE EmployeeID = @
EmpID"

InsertCommand="INSERT INTO Employees(LastName, FirstName) VALUES (@LastName, @FirstName);


SELECT @EmpID = SCOPE_IDENTITY()"
UpdateCommand="UPDATE Employees SET LastName=@LastName, FirstName=@FirstName
WHERE EmployeeID=@EmployeeID"
DeleteCommand="DELETE Employees WHERE EmployeeID=@EmployeeID"

ConnectionString="<%$ ConnectionStrings:NorthwindConnection %>"


OnInserted="EmployeeDetailsSqlDataSource_OnInserted"
RunAt="server">
<SelectParameters>
<asp:Parameter Name="EmpID" Type="Int32" DefaultValue="0" />
</SelectParameters>

<InsertParameters>
<asp:Parameter Name="EmpID" Direction="Output" Type="Int32" DefaultValue="0" />
</InsertParameters>

</asp:sqlDataSource>

Note
When you use a ListControl control such as a DropDownList control, you might want the value of the DropDownList contr
ol to be bound to a field in the current bound record while the list values for the DropDownList control are bound to a separ
ate list of possible values. In that case, use the Bind expression to bind the SelectedValue property of the DropDownList con
trol to the current bound record, and specify the data source, DataTextField property, and DataValueField property of the Dro
pDownList control to the list of possible values.

The EditItemTemplate template is loaded when users click a command button with a CommandName value of Edit. You
can add a LinkButton command button with a CommandName of Update to take the current bound values and send them
to the data source control for update. You can add a LinkButton command button with a CommandName of Cancel to
discard the current bound values and return the FormView control to read-only mode and load the ItemTemplate template.
The InsertItemTemplate template is loaded when users click a command button with a CommandName of New. You can
add a LinkButton command button with a CommandName of Insert to send values for a new record to the data source
control. You can add a LinkButton command button with a CommandName of Cancel to discard the new values and return
the FormView to read-only mode and load the ItemTemplate template.
For an example of using the FormView control to edit data, see Modifying Data Using a FormView Web Server Control.
Data Paging Template
In the FormView control, a page of data is a single bound record. If you set the AllowPaging property of the FormView
control to true, the FormView control automatically adds user interface (UI) controls for paging. You can customize the UI for
paging by adding a PagerTemplate template. For details, see Paging in a FormView Web Server Control.
For an example of a PagerTemplate template for a FormView control, see Paging in a FormView Web Server Control.
See Also
Other Resources
FormView Web Server Control
ASP.NET

Paging in a FormView Web Server Control


The ASP.NET FormView control has built-in support to allow users to page through records one at a time. The control also
supports customizing the paging user interface (UI). In the FormView control, a page of data is a single bound record.
How Paging Works in the FormView Control
The FormView control supports paging over the items in its data source. To enable paging behavior, you can set the
AllowPaging property to true. The page size for the FormView control is always one row per page.
If the FormView control is bound to a data source control, or to any data structure that implements the ICollection interface
(including datasets), the control gets all the records from the data source, displays the record for the current page, and discards
the rest. When the user moves to another page, the FormView control repeats the process, displaying a different record.
Note
If the data source does not implement the ICollection interface, the FormView control cannot page. For example, if you are
using a SqlDataSource control and have set its DataSourceMode property to DataReader, the FormView control cannot impl
ement paging.

Some data sources, such as the ObjectDataSource control, offer more advanced paging capabilities. In these cases the
FormView control takes advantage of the data source's more advanced capabilities to gain better performance and flexibility
while paging. The number of rows requested may vary depending on whether the data source supports retrieving the total row
count.
Note
If you are creating a data source (such as implementing a SelectCountMethod method in the source object for the ObjectDa
taSource control), it is strongly recommended that your data source return the total row count when supplying pages of dat
a. This minimizes the number of records that the FormView control must request in order to retrieve a page of data. If the to
tal row count is supplied by the source data object, the FormView control will request only a single row at a time for each pa
ge. If the total row count is not supplied, the FormView control must request all rows from the data source (starting with the
row that represents the requested page of data) and discard all rows except the row being displayed.

Customizing the Paging Settings and User Interface


You can customize the user interface (UI) of the FormView paging in a number of ways.
Paging Modes
The PagerSettings property allows you to customize the appearance of the paging user interface (UI) generated by the
FormView control when you set the AllowPaging property to true. The FormView control can display direction controls that
allow forward and backward navigation as well as numeric controls that allow a user to move to a specific page.
The PagerSettings property of the FormView control is set to a PagerSettings class. You can customize the paging mode by
setting the Mode property of the FormView control to a PagerButtons value. For example, you can customize the paging UI
mode by setting it as follows:

FormView1.PagerSettings.Mode = PagerButtons.NextPreviousFirstLast

The available modes are:


NextPrevious
NextPreviousFirstLast
Numeric
NumericFirstLast
Pager Control Appearance
The FormView control has numerous properties that you can use to customize the text and images for different pager modes.
For example, if you set the paging mode of a FormView control to NextPrevious and want to customize the text that is
displayed, you can set the NextPageText and PreviousPageText properties to your own values. By default, the
PreviousPageText and NextPageText properties are set to "<" and ">", respectively.
You can also use images to customize the appearance of your paging controls. The PagerSettings class includes image URL
properties for the first, last, previous, and next page command buttons.
Finally, you can control the appearance of the paging commands by setting the PagerStyle property of the FormView control
to a TableItemStyle.
Data Paging Template
If you set the AllowPaging property of the FormView control to true, the FormView control automatically adds user
interface (UI) controls for paging. You can customize the UI for paging by adding a PagerTemplate template. To specify which
paging operation to perform, add a Button control to the template, and then set its CommandName property to Page and its
CommandArgument property to one of the following values:
First To navigate to the first page.
Last To navigate to the last page.
Prev To navigate to the previous page.
Next To navigate to the next page of data
A number To indicate a specific page.
The following code example shows a FormView control configured to provide paging.
VB
<%@ Page language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>FormView Example</title>
</head>
<body>
<form id="form1" runat="server">
<h3>FormView Example</h3>
<table cellspacing="10">
<tr>
<td valign="top">
<asp:FormView ID="ProductsFormView"
DataSourceID="ProductsSqlDataSource"
AllowPaging="true"
runat="server">

<HeaderStyle forecolor="white" backcolor="Blue" />


<ItemTemplate>
<table>
<tr>
<td align="right"><b>Product ID:</b></td>
<td><asp:Label id="ProductIDLabel" runat="server" Text='<%# Eval("Pro
ductID") %>' /></td>
</tr>
<tr>
<td align="right"><b>Product Name:</b></td>
<td><asp:Label id="ProductNameLabel" runat="server" Text='<%# Eval("P
roductName") %>' /></td>
</tr>
<tr>
<td align="right"><b>Category ID:</b></td>
<td><asp:Label id="CategoryIDLabel" runat="server" Text='<%# Eval("Ca
tegoryID") %>' /></td>
</tr>
<tr>
<td align="right"><b>Quantity Per Unit:</b></td>
<td><asp:Label id="QuantityPerUnitLabel" runat="server" Text='<%# Eva
l("QuantityPerUnit") %>' /></td>
</tr>
<tr>
<td align="right"><b>Unit Price:</b></td>
<td><asp:Label id="UnitPriceLabel" runat="server" Text='<%# Eval("Uni
tPrice") %>' /></td>
</tr>
</table>
</ItemTemplate>

<PagerTemplate>
<table>
<tr>
<td><asp:LinkButton ID="FirstButton" CommandName="Page" CommandArgume
nt="First" Text="<<" RunAt="server"/></td>
<td><asp:LinkButton ID="PrevButton" CommandName="Page" CommandArgume
nt="Prev" Text="<" RunAt="server"/></td>
<td><asp:LinkButton ID="NextButton" CommandName="Page" CommandArgume
nt="Next" Text=">" RunAt="server"/></td>
<td><asp:LinkButton ID="LastButton" CommandName="Page" CommandArgume
nt="Last" Text=">>" RunAt="server"/></td>
</tr>
</table>
</PagerTemplate>

</asp:FormView>

</td>
</tr>
</table>

<asp:SqlDataSource ID="ProductsSqlDataSource"
SelectCommand="SELECT * FROM [Products]"
connectionstring="<%$ ConnectionStrings:NorthwindConnection %>"
RunAt="server"/>

</form>
</body>
</html>

C#
<%@ Page language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>FormView Example</title>
</head>
<body>
<form id="form1" runat="server">
<h3>FormView Example</h3>
<table cellspacing="10">
<tr>
<td valign="top">

<asp:FormView ID="ProductsFormView"
DataSourceID="ProductsSqlDataSource"
AllowPaging="true"
runat="server">

<HeaderStyle forecolor="white" backcolor="Blue" />


<ItemTemplate>
<table>
<tr>
<td align="right"><b>Product ID:</b></td>
<td><asp:Label id="ProductIDLabel" runat="server" Text='<%# Eval("Pro
ductID") %>' /></td>
</tr>
<tr>
<td align="right"><b>Product Name:</b></td>
<td><asp:Label id="ProductNameLabel" runat="server" Text='<%# Eval("P
roductName") %>' /></td>
</tr>
<tr>
<td align="right"><b>Category ID:</b></td>
<td><asp:Label id="CategoryIDLabel" runat="server" Text='<%# Eval("Ca
tegoryID") %>' /></td>
</tr>
<tr>
<td align="right"><b>Quantity Per Unit:</b></td>
<td><asp:Label id="QuantityPerUnitLabel" runat="server" Text='<%# Eva
l("QuantityPerUnit") %>' /></td>
</tr>
<tr>
<td align="right"><b>Unit Price:</b></td>
<td><asp:Label id="UnitPriceLabel" runat="server" Text='<%# Eval("Uni
tPrice") %>' /></td>
</tr>
</table>
</ItemTemplate>
<PagerTemplate>
<table>
<tr>
<td><asp:LinkButton ID="FirstButton" CommandName="Page" CommandArgume
nt="First" Text="<<" RunAt="server"/></td>
<td><asp:LinkButton ID="PrevButton" CommandName="Page" CommandArgume
nt="Prev" Text="<" RunAt="server"/></td>
<td><asp:LinkButton ID="NextButton" CommandName="Page" CommandArgume
nt="Next" Text=">" RunAt="server"/></td>
<td><asp:LinkButton ID="LastButton" CommandName="Page" CommandArgume
nt="Last" Text=">>" RunAt="server"/></td>
</tr>
</table>
</PagerTemplate>

</asp:FormView>
</td>
</tr>
</table>

<asp:SqlDataSource ID="ProductsSqlDataSource"
SelectCommand="SELECT ProductID, ProductName, CategoryID, QuantityPerUnit, UnitPr
ice FROM [Products]"
connectionstring="<%$ ConnectionStrings:NorthwindConnection %>"
RunAt="server"/>

</form>
</body>
</html>

See Also
Concepts
FormView Web Server Control Overview
ASP.NET

Modifying Data Using a FormView Web Server Control


The FormView control provides templates to allow users to edit records without requiring programming. You can specify a
template in the FormView control for different rendering modes. You can specify an ItemTemplate template for read-only
mode, an InsertItemTemplate template for insert mode, and an EditItemTemplate template for edit mode. For more
information about FormView templates, see Creating Templates for the FormView Web Server Control.
How the FormView Control Modifies Bound Data
The FormView control displays the specified templates to provide a user interface (UI) that allows users to modify the contents
of a record. Each template contains the command buttons that a user can click to perform an edit or insert action. When the
user clicks a command button, the FormView control redisplays the bound record with the specified edit or insert template to
allow users to modify the record.
An insert or edit template typically includes an "Insert" button to allow users to display a blank record or an "Update" button to
save a change. When users click the insert or update button, the FormView control passes the bound values and primary key
information to the associated data source control, which performs the appropriate update. For example, the SqlDataSource
control executes a SQL Update statement using the changed data as parameter values. The ObjectDataSource control calls its
update method, passing the changes as part of the method call.
When the FormView control is performing an insert operation, it passes the values to be inserted in the data source using the
Values dictionary collection.
The FormView control passes values to the data source for an update or delete operation in three dictionary collections: the
Keys dictionary, the NewValues dictionary, and the OldValues dictionary. You can access each dictionary using the
arguments passed to the FormView control's insert, update or delete events.
The Keys dictionary contains the names and values of fields that uniquely identify the record to update or delete, and always
contains the original values of the key fields. To specify which fields are placed in the Keys dictionary, set the DataKeyNames
property to a comma-separated list of field names that represent the primary key of your data. An array is automatically
populated with the values associated with the fields specified for the DataKeyNames property.
Note
The original primary key values for the fields specified in the DataKeyNames property are stored in view state. If your prima
ry key values contain sensitive information, you should encrypt the view state contents by setting the page's
ViewStateEncryptionMode property to Always.

The Values and NewValues dictionaries contain the current values from the controls in the record being inserted or edited in
the FormView control. The OldValues dictionary contains any original values of fields except the key fields, which are
included in the Keys dictionary. New values for editable key fields are contained in the NewValues dictionary.
The data source control uses the values from the Keys, Values, NewValues, and OldValues dictionaries as parameters for the
insert, update, or delete command. For information about how data source control parameters are created based on the
dictionaries created for bound values, see How a Data Source Control Creates Parameters for Data-bound Fields.
After the update is complete, the FormView control raises its ItemUpdated event. This event allows you to perform post-query
logic such as integrity checks. Similarly, the FormView control raises its ItemInserted event after an insert, and its ItemDeleted
event after a delete.
After the update is complete and all events have been raised, the FormView control rebinds to the data source control.
Example
The following code example uses a GridView control and a FormView control to display data. The FormView control is
configured to allow the data to be modified.
Security Note
This code example contains a text box that accepts user input, which is a potential security threat. By default, ASP.NET Web pa
ges validate that user input does not include script or HTML elements. For more information, see Script Exploits Overview.

VB
<%@ Page language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
Sub EmployeesGridView_OnSelectedIndexChanged(sender As Object, e As EventArgs)
EmployeeDetailsSqlDataSource.SelectParameters("EmpID").DefaultValue = _
EmployeesGridView.SelectedValue.ToString()
EmployeeFormView.DataBind()
End Sub

Sub EmployeeFormView_ItemUpdated(sender As Object, e As FormViewUpdatedEventArgs)


EmployeesGridView.DataBind()
End Sub

Sub EmployeeFormView_ItemDeleted(sender As Object, e As FormViewDeletedEventArgs)


EmployeesGridView.DataBind()
End Sub
Sub EmployeeDetailsSqlDataSource_OnInserted(sender As Object, e As SqlDataSourceStatusEve
ntArgs)
Dim command As System.Data.Common.DbCommand = e.Command

EmployeeDetailsSqlDataSource.SelectParameters("EmpID").DefaultValue = _
command.Parameters("@EmpID").Value.ToString()
EmployeesGridView.DataBind()
EmployeeFormView.DataBind()
End Sub

</script>

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>FormView Example</title>
</head>
<body>
<form id="form1" runat="server">

<h3>FormView Example</h3>

<table cellspacing="10">
<tr>
<td>
<asp:GridView ID="EmployeesGridView"
DataSourceID="EmployeesSqlDataSource"
AutoGenerateColumns="false"
DataKeyNames="EmployeeID"
OnSelectedIndexChanged="EmployeesGridView_OnSelectedIndexChanged"
RunAt="Server">
<HeaderStyle backcolor="Navy"
forecolor="White" />

<Columns>

<asp:ButtonField Text="Details..."
HeaderText="Show<BR>Details"
CommandName="Select"/>

<asp:BoundField DataField="EmployeeID" HeaderText="Employee ID"/>


<asp:BoundField DataField="LastName" HeaderText="Last Name"/>

<asp:BoundField DataField="FirstName" HeaderText="First Name"/>


</Columns>
</asp:GridView>

</td>

<td valign="top">

<asp:FormView ID="EmployeeFormView"
DataSourceID="EmployeeDetailsSqlDataSource"
DataKeyNames="EmployeeID"
Gridlines="Both"
OnItemUpdated="EmployeeFormView_ItemUpdated"
OnItemDeleted="EmployeeFormView_ItemDeleted"
RunAt="server">

<HeaderStyle backcolor="Navy"
forecolor="White"/>

<RowStyle backcolor="White"/>

<EditRowStyle backcolor="LightCyan"/>

<ItemTemplate>
<table>
<tr><td align="right"><b>Employee ID:</b></td><td><%# Eval("EmployeeID"
) %></td></tr>
<tr><td align="right"><b>First Name:</b></td> <td><%# Eval("FirstName")
%></td></tr>
<tr><td align="right"><b>Last Name:</b></td> <td><%# Eval("LastName")
%></td></tr>
<tr>
<td colspan="2">
<asp:LinkButton ID="EditButton"
Text="Edit"
CommandName="Edit"
RunAt="server"/>
&nbsp;
<asp:LinkButton ID="NewButton"
Text="New"
CommandName="New"
RunAt="server"/>
&nbsp;
<asp:LinkButton ID="DeleteButton"
Text="Delete"
CommandName="Delete"
RunAt="server"/>
</td>
</tr>
</table>
</ItemTemplate>

<EditItemTemplate>
<table>
<tr><td align="right"><b>Employee ID:</b></td><td><%# Eval("EmployeeID"
) %></td></tr>

<tr><td align="right"><b>First Name:</b></td>


<td><asp:TextBox ID="EditFirstNameTextBox"
Text='<%# Bind("FirstName") %>'
RunAt="Server" /></td></tr>

<tr><td align="right"><b>Last Name:</b></td>


<td><asp:TextBox ID="EditLastNameTextBox"
Text='<%# Bind("LastName") %>'
RunAt="Server" /></td></tr>
<tr>
<td colspan="2">
<asp:LinkButton ID="UpdateButton"
Text="Update"
CommandName="Update"
RunAt="server"/>
&nbsp;
<asp:LinkButton ID="CancelUpdateButton"
Text="Cancel"
CommandName="Cancel"
RunAt="server"/>
</td>
</tr>
</table>
</EditItemTemplate>

<InsertItemTemplate>
<table>
<tr><td align="right"><b>First Name:</b></td>
<td><asp:TextBox ID="InsertFirstNameTextBox"
Text='<%# Bind("FirstName") %>'
RunAt="Server" /></td></tr>

<tr><td align="right"><b>Last Name:</b></td>


<td><asp:TextBox ID="InsertLastNameTextBox"
Text='<%# Bind("LastName") %>'
RunAt="Server" /></td></tr>

<tr>
<td colspan="2">
<asp:LinkButton ID="InsertButton"
Text="Insert"
CommandName="Insert"
RunAt="server"/>
&nbsp;
<asp:LinkButton ID="CancelInsertButton"
Text="Cancel"
CommandName="Cancel"
RunAt="server"/>
</td>
</tr>
</table>
</InsertItemTemplate>

</asp:FormView>
</td>

</tr>

</table>

<asp:sqlDataSource ID="EmployeesSqlDataSource"
selectCommand="SELECT EmployeeID, FirstName, LastName FROM Employees"
connectionstring="<%$ ConnectionStrings:NorthwindConnection %>"
RunAt="server">
</asp:sqlDataSource>

<asp:sqlDataSource ID="EmployeeDetailsSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName, FirstName FROM Employees WHERE Employ
eeID = @EmpID"
InsertCommand="INSERT INTO Employees(LastName, FirstName) VALUES (@LastName, @Fir
stName);
SELECT @EmpID = SCOPE_IDENTITY()"
UpdateCommand="UPDATE Employees SET LastName=@LastName, FirstName=@FirstName
WHERE EmployeeID=@EmployeeID"
DeleteCommand="DELETE Employees WHERE EmployeeID=@EmployeeID"

ConnectionString="<%$ ConnectionStrings:NorthwindConnection %>"


OnInserted="EmployeeDetailsSqlDataSource_OnInserted"
RunAt="server">

<SelectParameters>
<asp:Parameter Name="EmpID" Type="Int32" DefaultValue="0" />
</SelectParameters>

<InsertParameters>
<asp:Parameter Name="EmpID" Direction="Output" Type="Int32" DefaultValue="0" />
</InsertParameters>

</asp:sqlDataSource>

</form>
</body>
</html>

C#

<%@ Page language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">

void EmployeesGridView_OnSelectedIndexChanged(Object sender, EventArgs e)


{
EmployeeDetailsSqlDataSource.SelectParameters["EmpID"].DefaultValue =
EmployeesGridView.SelectedValue.ToString();
EmployeeFormView.DataBind();
}

void EmployeeFormView_ItemUpdated(Object sender, FormViewUpdatedEventArgs e)


{
EmployeesGridView.DataBind();
}

void EmployeeFormView_ItemDeleted(Object sender, FormViewDeletedEventArgs e)


{
EmployeesGridView.DataBind();
}

void EmployeeDetailsSqlDataSource_OnInserted(Object sender, SqlDataSourceStatusEventArgs


e)
{
System.Data.Common.DbCommand command = e.Command;

EmployeeDetailsSqlDataSource.SelectParameters["EmpID"].DefaultValue =
command.Parameters["@EmpID"].Value.ToString();

EmployeesGridView.DataBind();
EmployeeFormView.DataBind();
}

</script>

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>FormView Example</title>
</head>
<body>
<form id="form1" runat="server">

<h3>FormView Example</h3>
<table cellspacing="10">

<tr>
<td>
<asp:GridView ID="EmployeesGridView"
DataSourceID="EmployeesSqlDataSource"
AutoGenerateColumns="false"
DataKeyNames="EmployeeID"
OnSelectedIndexChanged="EmployeesGridView_OnSelectedIndexChanged"
RunAt="Server">

<HeaderStyle backcolor="Navy"
forecolor="White" />

<Columns>

<asp:ButtonField Text="Details..."
HeaderText="Show<BR>Details"
CommandName="Select"/>

<asp:BoundField DataField="EmployeeID" HeaderText="Employee ID"/>


<asp:BoundField DataField="LastName" HeaderText="Last Name"/>

<asp:BoundField DataField="FirstName" HeaderText="First Name"/>

</Columns>

</asp:GridView>

</td>
<td valign="top">

<asp:FormView ID="EmployeeFormView"
DataSourceID="EmployeeDetailsSqlDataSource"
DataKeyNames="EmployeeID"
Gridlines="Both"
OnItemUpdated="EmployeeFormView_ItemUpdated"
OnItemDeleted="EmployeeFormView_ItemDeleted"
RunAt="server">

<HeaderStyle backcolor="Navy"
forecolor="White"/>

<RowStyle backcolor="White"/>

<EditRowStyle backcolor="LightCyan"/>

<ItemTemplate>
<table>
<tr><td align="right"><b>Employee ID:</b></td><td><%# Eval("EmployeeID"
) %></td></tr>
<tr><td align="right"><b>First Name:</b></td> <td><%# Eval("FirstName")
%></td></tr>
<tr><td align="right"><b>Last Name:</b></td> <td><%# Eval("LastName")
%></td></tr>
<tr>
<td colspan="2">
<asp:LinkButton ID="EditButton"
Text="Edit"
CommandName="Edit"
RunAt="server"/>
&nbsp;
<asp:LinkButton ID="NewButton"
Text="New"
CommandName="New"
RunAt="server"/>
&nbsp;
<asp:LinkButton ID="DeleteButton"
Text="Delete"
CommandName="Delete"
RunAt="server"/>
</td>
</tr>
</table>
</ItemTemplate>

<EditItemTemplate>
<table>
<tr><td align="right"><b>Employee ID:</b></td><td><%# Eval("EmployeeID"
) %></td></tr>

<tr><td align="right"><b>First Name:</b></td>


<td><asp:TextBox ID="EditFirstNameTextBox"
Text='<%# Bind("FirstName") %>'
RunAt="Server" /></td></tr>

<tr><td align="right"><b>Last Name:</b></td>


<td><asp:TextBox ID="EditLastNameTextBox"
Text='<%# Bind("LastName") %>'
RunAt="Server" /></td></tr>
<tr>
<td colspan="2">
<asp:LinkButton ID="UpdateButton"
Text="Update"
CommandName="Update"
RunAt="server"/>
&nbsp;
<asp:LinkButton ID="CancelUpdateButton"
Text="Cancel"
CommandName="Cancel"
RunAt="server"/>
</td>
</tr>
</table>
</EditItemTemplate>

<InsertItemTemplate>
<table>
<tr><td align="right"><b>First Name:</b></td>
<td><asp:TextBox ID="InsertFirstNameTextBox"
Text='<%# Bind("FirstName") %>'
RunAt="Server" /></td></tr>

<tr><td align="right"><b>Last Name:</b></td>


<td><asp:TextBox ID="InsertLastNameTextBox"
Text='<%# Bind("LastName") %>'
RunAt="Server" /></td></tr>

<tr>
<td colspan="2">
<asp:LinkButton ID="InsertButton"
Text="Insert"
CommandName="Insert"
RunAt="server"/>
&nbsp;
<asp:LinkButton ID="CancelInsertButton"
Text="Cancel"
CommandName="Cancel"
RunAt="server"/>
</td>
</tr>
</table>
</InsertItemTemplate>

</asp:FormView>
</td>

</tr>

</table>

<asp:sqlDataSource ID="EmployeesSqlDataSource"
selectCommand="SELECT EmployeeID, FirstName, LastName FROM Employees"
connectionstring="<%$ ConnectionStrings:NorthwindConnection %>"
RunAt="server">
</asp:sqlDataSource>

<asp:sqlDataSource ID="EmployeeDetailsSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName, FirstName FROM Employees WHERE Employ
eeID = @EmpID"

InsertCommand="INSERT INTO Employees(LastName, FirstName) VALUES (@LastName, @Fir


stName);
SELECT @EmpID = SCOPE_IDENTITY()"
UpdateCommand="UPDATE Employees SET LastName=@LastName, FirstName=@FirstName
WHERE EmployeeID=@EmployeeID"
DeleteCommand="DELETE Employees WHERE EmployeeID=@EmployeeID"

ConnectionString="<%$ ConnectionStrings:NorthwindConnection %>"


OnInserted="EmployeeDetailsSqlDataSource_OnInserted"
RunAt="server">

<SelectParameters>
<asp:Parameter Name="EmpID" Type="Int32" DefaultValue="0" />
</SelectParameters>

<InsertParameters>
<asp:Parameter Name="EmpID" Direction="Output" Type="Int32" DefaultValue="0" />
</InsertParameters>

</asp:sqlDataSource>

</form>
</body>
</html>

See Also
Concepts
FormView Web Server Control Overview
Other Resources
Data Source Web Server Controls
ASP.NET

FormView Web Server Control Events


The FormView control raises a number of events in the course of paging through and updating its bound data to which your
code can respond.
For an example that uses some of the FormView control events, see Modifying Data Using a FormView Web Server Control.
FormView Events
The FormView control raises events that occur when the current record displayed or changed. Events are also raised when a
command control such as a Button that is part of the FormView control has been clicked. The following table describes the
events exposed by the FormView control.
PageIndexChanging
Occurs when one of the pager buttons is clicked, but before the FormView control performs the paging operation. This
event is often handled to cancel the paging operation.
PageIndexChanged
Occurs when one of the pager buttons is clicked, but after the FormView control performs the paging operation. This event
is commonly handled when you need to perform a task after the user navigates to a different record in the control.
ItemCommand
Occurs when a button within a FormView control is clicked. This event is often handled to perform a task when a button is
clicked in the control.
ItemCreated
Occurs after all FormViewRow objects are created in the FormView control. This event is often handled to modify the values
to be displayed in a row before the row is displayed.
ItemDeleting
Occurs when a Delete button (a button with its CommandName property set to "Delete") is clicked, but before the
FormView control deletes the record from the data source. This event is often used to cancel the delete operation.
ItemDeleted
Occurs when a Delete button is clicked, but after the FormView control deletes the record from the data source. This event
is often handled to check the results of the delete operation.
ItemInserting
Occurs when an Insert button (a button with its CommandName property set to "Insert") is clicked, but before the
FormView control inserts the record. This event is often handled to cancel the insert operation.
ItemInserted
Occurs when an Insert button is clicked, but after the FormView control inserts the record. This event is often handled to
check the results of the insert operation.
ItemUpdating
Occurs when an Update button (a button with its CommandName property set to "Update") is clicked, but before the
FormView control updates the record. This event is often used to cancel the update operation.
ItemUpdated
Occurs when an Update button is clicked, but after the FormView control updates the row. This event is often used to check
the results of the update operation.
ModeChanging
Occurs before the FormView control changes modes (to edit, insert, or read-only mode). This event is often handled to
cancel a mode change.
ModeChanged
Occurs after the FormView control changes modes (to edit, insert, or read-only mode). This event is often handled to
perform a task when the FormView control changes modes.
DataBound
This event is inherited from the BaseDataBoundControl control and occurs after the FormView control has finished binding
to the data source.
See Also
Reference
FormView
Concepts
FormView Web Server Control Overview
Other Resources
FormView Web Server Control
Visual Web Developer

Repeater Web Server Control (Visual Studio)


The Repeater Web server control is a data-bound container control that produces a list of individual items. You define the
layout of individual items on a Web page using templates. When the page runs, the control repeats the layout for each item in
the data source.
The following topics provide information on the structure of a Repeater control and how to add it to an ASP.NET Web page.
In This Section
Repeater Web Server Control Overview
How to: Add Repeater Web Server Controls to a Web Forms Page (Visual Studio)
See Also
Concepts
ASP.NET Web Server Controls Templates
Other Resources
Data Toolbox Controls
ASP.NET Data Access (Visual Studio)
ASP.NET

Repeater Web Server Control Overview


The Repeater Web server control is a container control that allows you to create custom lists out of any data that is available to
the page. The Repeater control does not have a built-in rendering of its own, which means that you must provide the layout
for the Repeater control by creating templates. When the page runs, the Repeater control loops through the records in the
data source and renders an item for each record.
Because the Repeater control has no default look, you can use it to create many kinds of lists, including the following:
A table layout
A comma-delimited list (for example, a, b, c, d, and so on)
An XML formatted list
Using Templates with the Repeater Control
To use the Repeater control, you create templates that define the layout of the control's content. Templates can contain any
combination of markup and controls. If no templates are defined, or if none of the templates contain elements, the control does
not appear on the page when the application is run.
The following table describes the templates that are supported by the Repeater control.
Template property Description
ItemTemplate Contains the HTML elements and controls to render once for each data item in the data source.

AlternatingItemTemplate Contains the HTML elements and controls to render once for every other data item in the data source
. Typically, this template is used to create a different look for the alternating items, such as a different
background color than the color that is specified in the ItemTemplate.

HeaderTemplate and Contains the text and controls to render at the beginning and end of the list, respectively.
FooterTemplate

SeparatorTemplate Contains the elements to render between each item. A typical example might be a line (using an hr el
ement).

For more information, see ASP.NET Web Server Controls Templates.


Binding Data to the Repeater Control
The Repeater control must be bound to a data source. The most common data source is a data source control, such as a
SqlDataSource or ObjectDataSource control. Alternatively, you can bind a Repeater control to any class that implements the
IEnumerable interface, which includes the ADO.NET datasets (DataSet class), data readers (SqlDataReader or OleDbDataReader
classes), or most collections.
When binding data, you specify a data source for the Repeater control as a whole. When you add controls to the Repeater
control — for example, when you add Label or TextBox controls in a template — you use data-binding syntax to bind the
individual control to a field of the items returned by the data source. The following example shows an ItemTemplate that
contains a data-bound Label control.
VB
<%@ Page Language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>ASP.NET Repeater Example</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="SqlDataSource1">
<HeaderTemplate>
<table>
<tr>
<th>
Name</th>
<th>
Description</th>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td style="background-color:#CCFFCC">
<asp:Label runat="server" ID="Label1" Text='<%# Eval("CategoryName") %>' />
</td>
<td style="background-color:#CCFFCC">
<asp:Label runat="server" ID="Label2" Text='<%# Eval("Description") %>' />
</td>
</tr>
</ItemTemplate>
<AlternatingItemTemplate>
<tr>
<td>
<asp:Label runat="server" ID="Label3" Text='<%# Eval("CategoryName") %>' />
</td>
<td>
<asp:Label runat="server" ID="Label4" Text='<%# Eval("Description") %>' />
</td>
</tr>
</AlternatingItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
<asp:SqlDataSource ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString
%>"
ID="SqlDataSource1" runat="server" SelectCommand="SELECT [CategoryID], [CategoryNam
e],
[Description] FROM [Categories]"></asp:SqlDataSource>
</div>
</form>
</body>
</html>

C#
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>ASP.NET Repeater Example</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="SqlDataSource1">
<HeaderTemplate>
<table>
<tr>
<th>
Name</th>
<th>
Description</th>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td style="background-color:#CCFFCC">
<asp:Label runat="server" ID="Label1" Text='<%# Eval("CategoryName") %>' />
</td>
<td style="background-color:#CCFFCC">
<asp:Label runat="server" ID="Label2" Text='<%# Eval("Description") %>' />
</td>
</tr>
</ItemTemplate>
<AlternatingItemTemplate>
<tr>
<td>
<asp:Label runat="server" ID="Label3" Text='<%# Eval("CategoryName") %>' />
</td>
<td>
<asp:Label runat="server" ID="Label4" Text='<%# Eval("Description") %>' />
</td>
</tr>
</AlternatingItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
<asp:SqlDataSource ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString
%>"
ID="SqlDataSource1" runat="server" SelectCommand="SELECT [CategoryID], [CategoryNam
e],
[Description] FROM [Categories]"></asp:SqlDataSource>
</div>
</form>
</body>
</html>

Note
You cannot bind controls in the header, footer, and separator templates using the Eval data binding function. If you have con
trols in these templates, you can simply define their properties statically.

For an overview of data binding in Web server controls, see Walkthrough: Basic Data Access in Web Pages and
How to: Add a Repeater Control to a Web Forms Page.
Events Supported by the Repeater Control
The Repeater control supports several events. One of them, the ItemCreated event, gives you a way to customize the item-
creation process at run time. The ItemDataBound event also gives you the ability to customize the Repeater control, but after
the data is available for inspection. For example, if you were using the Repeater control to display a to-do list, you could
display overdue items in red text, completed items in black text, and other tasks in green text. Either event can be used to
override formatting from the template definition.
The ItemCommand event is raised in response to button clicks in individual items. This event is designed to allow you to
embed a Button, LinkButton, or ImageButton Web server control in an item template and then be notified when the button is
clicked. When a user clicks the button, the event is sent to the button's container — the Repeater control. The most common
uses for the ItemCommand event are to program update and delete behaviors to the Repeater control. Since every button
click raises the same ItemCommand event, you can determine which button was clicked by setting each button's
CommandName property to a unique string value. The CommandSource property of the RepeaterCommandEventArgs
parameter contains the CommandName property of the button that was clicked.
For more information, see How to: Respond to Button Events in DataList, Repeater, or GridView Items.
See Also
Tasks
How to: Add a Repeater Control to a Web Forms Page
Reference
DataList Web Server Control Overview
Visual Web Developer

How to: Add Repeater Web Server Controls to a Web Forms


Page (Visual Studio)
The Repeater Web server control is a data-bound container control that produces a list of individual items. You define the
layout of individual items on a Web page using templates. When the page is run, the control repeats the layout for each item in
the data source. You must complete several steps to add a Repeater Web server control to a Web forms page. The following
procedure describes the minimum that you must do to create a working Repeater control.
To add a Repeater Web server control to a Web Forms page
1. In Design view, from the Data tab of the Toolbox, drag a data source control onto the page, such as the SqlDataSource
control or the ObjectDataSource control.
2. Use the Configure Data Source wizard to define the connection and the query, or data-retrieval method, for the data
source control. The Configure Data Source wizard is available to all data sources except the SiteMapDataSource
control, which only needs the presence of a site map to populate the control. To open the Configure Data Source
wizard, follow these steps:
a. Right-click the data source control, and then click Show Smart Tag.
b. In the data source tasks window, click Configure Data Source.
3. From the Data tab of the Toolbox, drag a Repeater control onto the page.
4. Right-click the Repeater control and then click Show Smart Tag.
5. Under Choose Data Source list, click the name of the data source control that you created in steps 1 and 2.
This sets the control's DataSourceID property. If the query includes a primary key, the controls' DataKeyField property is
set as well.
6. Click Source to switch to Source view.
To define templates, you must be in Source view.
7. Add an <ItemTemplate> element to the page as a child of the Repeater control. For syntax, see
Repeater Web Server Control Declarative Syntax
Note
To render at run time, the Repeater control must contain an ItemTemplate that, in turn, contains data-binding expressi
ons that are of the form <%# Eval("field name") %> where field name is the name of a field in the database. For backg
round information about using templates, see ASP.NET Web Server Controls Templates.

8. Add HTML and any other Web server controls or HTML server controls to the ItemTemplate.
9. Optionally, define the following templates: AlternatingItemTemplate SeparatorTemplate, HeaderTemplate,
FooterTemplate.
The following code example shows how to use a Repeater control to display data in an HTML table. The table element
begins in the HeaderTemplate and ends in the FooterTemplate. Within the body of the Repeater control, table cells
are used to display columns from the data source. The AlternatingItemTemplate element is identical to the
ItemTemplate item except that the background color of the table cells is different.
VB
<%@ Page Language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>ASP.NET Repeater Example</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="SqlDataSource1">
<HeaderTemplate>
<table>
<tr>
<th>
Name</th>
<th>
Description</th>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td style="background-color:#CCFFCC">
<asp:Label runat="server" ID="Label1" Text='<%# Eval("CategoryName") %>'
/>
</td>
<td style="background-color:#CCFFCC">
<asp:Label runat="server" ID="Label2" Text='<%# Eval("Description") %>'
/>
</td>
</tr>
</ItemTemplate>
<AlternatingItemTemplate>
<tr>
<td>
<asp:Label runat="server" ID="Label3" Text='<%# Eval("CategoryName") %>'
/>
</td>
<td>
<asp:Label runat="server" ID="Label4" Text='<%# Eval("Description") %>'
/>
</td>
</tr>
</AlternatingItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
<asp:SqlDataSource ConnectionString="<%$ ConnectionStrings:NorthwindConnectionSt
ring %>"
ID="SqlDataSource1" runat="server" SelectCommand="SELECT [CategoryID], [Catego
ryName],
[Description] FROM [Categories]"></asp:SqlDataSource>
</div>
</form>
</body>
</html>

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

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>ASP.NET Repeater Example</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="SqlDataSource1">
<HeaderTemplate>
<table>
<tr>
<th>
Name</th>
<th>
Description</th>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td style="background-color:#CCFFCC">
<asp:Label runat="server" ID="Label1" Text='<%# Eval("CategoryName") %>'
/>
</td>
<td style="background-color:#CCFFCC">
<asp:Label runat="server" ID="Label2" Text='<%# Eval("Description") %>'
/>
</td>
</tr>
</ItemTemplate>
<AlternatingItemTemplate>
<tr>
<td>
<asp:Label runat="server" ID="Label3" Text='<%# Eval("CategoryName") %>'
/>
</td>
<td>
<asp:Label runat="server" ID="Label4" Text='<%# Eval("Description") %>'
/>
</td>
</tr>
</AlternatingItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
<asp:SqlDataSource ConnectionString="<%$ ConnectionStrings:NorthwindConnectionSt
ring %>"
ID="SqlDataSource1" runat="server" SelectCommand="SELECT [CategoryID], [Catego
ryName],
[Description] FROM [Categories]"></asp:SqlDataSource>
</div>
</form>
</body>
</html>

See Also
Reference
Repeater Web Server Control Overview
Visual Web Developer

DataList Web Server Control (Visual Studio)


The DataList Web server control displays rows of database information in a customizable format. The format for displaying the
data is defined in templates that you create. You can create templates for items, alternating items, selected items, and edit
items. Header, footer, and separator templates are also available to let you customize the overall appearance of the DataList.
By including Button Web server controls in the templates, you can connect the list items to code that allows users to switch
between display, selection, and editing modes.
The following topics provide information on how to add DataList controls to your ASP.NET Web pages, and how to program
them.
In This Section
Getting Started — DataList Web Server Control (Visual Studio)
Learning More — DataList Web Server Control (Visual Studio)
Walkthrough Topics — DataList Web Server Control (Visual Studio)
How-to Topics — DataList Web Server Control (Visual Studio)
See Also
Concepts
ASP.NET Web Server Controls Templates
Other Resources
Data Toolbox Controls
ASP.NET Data Access (Visual Studio)
Visual Web Developer

Getting Started — DataList Web Server Control (Visual Studio)


The topics in this section provide essential information on working with ASP.NET DataList Web server controls, including
information on how to add them to an ASP.NET Web page.
In This Section
DataList Web Server Control Overview
Walkthrough: Displaying and Formatting Data with the DataList Web Server Control
How to: Add DataList Web Server Controls to an ASP.NET Web Page (Visual Studio)
How to: Specify Flow or Table Format in DataList Web Server Controls
How to: Specify Horizontal or Vertical Layout in DataList Web Server Controls
See Also
Concepts
ASP.NET Web Server Controls Templates
Other Resources
Data Toolbox Controls
ASP.NET Data Access (Visual Studio)
ASP.NET

DataList Web Server Control Overview


The DataList Web server control displays data in a format that you can define using templates and styles. The DataList control
is useful for data in any repeating structure, such as a table. The DataList control can display rows in different layouts, such as
ordering them in columns or rows.
Note
The DataList control renders items in a list using HTML table elements. To precisely control the HTML that is used to render
a list, use the Repeater Web server control instead of the DataList control.

Optionally, you can configure the DataList control to allow users to edit or delete information. You can also customize the
control to support other functionality, such as selecting rows.
You use templates to define the layout of data items by including HTML text and controls. For example, you might use a Label
Web server control in an item to display a field from the data source.
The following sections introduce you to the features of the DataList control.
Binding Data to the Control
The DataList Web server control must be bound to a data source. The most common data source is a data source control, such
as a SqlDataSource or ObjectDataSource control. Alternatively, you can bind a DataList control to any class that implements
the IEnumerable interface, which includes the ADO.NET datasets (the DataSet class), data readers (the SqlDataReader or
OleDbDataReader classes), or most collections. When binding data, you specify a data source for the DataList control as a
whole. When you add other controls to this control — for example, labels or text boxes in list items — you can bind the child
controls' properties to fields in the current data item.
Defining Templates for DataList Items
In the DataList control, you can define the layout of your information by using templates.
Note
For an overview of using templates, see ASP.NET Web Server Controls Templates.

The following table describes the templates that are supported by the DataList control.
Template property Description
ItemTemplate Contains the HTML elements and controls to render once for each row in the data source.

AlternatingItemTemplate Contains the HTML elements and controls to render once for every other row in the data source. Typi
cally, you use this template to create a different look for the alternating rows, such as a different back
ground color than the color that is specified in the ItemTemplate property.

SelectedItemTemplate Contains the elements to render when the user selects an item in the DataList control. Typically, you
use this template to visually distinguish the selected row with a different background or font color. Y
ou can also expand the item by displaying additional fields from the data source.

EditItemTemplate Specifies the layout of an item when it is in edit mode. This template typically contains editing control
s, such as TextBox controls.

HeaderTemplate and Contains the text and controls to render at the beginning and end of the list, respectively.
FooterTemplate

SeparatorTemplate Contains the elements to render between each item. A typical example might be a line (using an HR e
lement).
Styles
To specify the appearance of items in a template, you can set the template's style. For example, you might specify the following:
Items are rendered with black text on a white background.
Alternating items are rendered with black text on a light gray background.
The selected item is rendered with bold, black text on a yellow background.
Items being edited are rendered with black text on a light blue background.
Each template supports its own style object, the properties of which you can set at design time and at run time. The styles you
can work with are the following:
AlternatingItemStyle
EditItemStyle
FooterStyle
HeaderStyle
ItemStyle
SelectedItemStyle
SeparatorStyle
For an overview, see ASP.NET Web Server Controls and CSS Styles.
Item Layout
The DataList control uses an HTML table to lay out the rendering of items to which the template is applied. You can control the
order, direction, and number of columns for the individual table cells used to render DataList items. The following table
describes the layout options that are supported by the DataList control.
Layout Description
option
Flow lay In flow layout, list items are rendered inline, as in a word-processing document.
out

Table la In table layout, the items are rendered in an HTML table. This gives you more options for specifying the look of items
yout because it allows you to set table-cell properties, such as gridlines. For details, see
How to: Specify Flow or Table Format in DataList Web Server Controls.

Vertical By default, the items in a DataList control are displayed in a single vertical column. However, you can specify that the
and hori control contain more than one column. If so, you can further specify whether the items are ordered vertically (like ne
zontal la wspaper columns) or horizontally (like days in a calendar). For details, see
yout How to: Specify Horizontal or Vertical Layout in DataList Web Server Controls.

Number Whether items in a DataList control are ordered vertically or horizontally, you can specify how many columns the list
of colu will have. This permits you to control the rendered width of the Web page, usually to avoid horizontal scrolling.
mns
Events
The DataList control supports several events. One of them, the ItemCreated event, gives you a way to customize the item-
creation process at run time. The ItemDataBound event also gives you the ability to customize the DataList control, but after
the data is available for inspection. For example, if you were using the DataList control to display a to-do list, you could display
overdue items in red text, completed items in black text, and other tasks in green text. Either event can be used to override
formatting from the template definition.
The remaining events are raised in response to button clicks in list items. They are designed to help you respond to the most
commonly used functionality of the DataList control. Four events of this type are supported:
EditCommand
DeleteCommand
UpdateCommand
CancelCommand
To cause these events to be raised, add Button, LinkButton, or ImageButton controls to the templates in the DataList control
and set the buttons' CommandName property to a keyword, such as edit, delete, update, or cancel. When a user clicks a
button in an item, the event is sent to the button's container — the DataList control. The exact event that the button raises
depends on the value of the CommandName property of the button that was clicked. For example, if the CommandName
property of a button is set to edit, the button raises an EditCommand event when clicked. If the CommandName property is
set to delete, the button raises a DeleteCommand event, and so on.
The DataList control also supports the ItemCommand event that is raised when a user clicks a button that does not have a
predefined command, such as edit or delete. You can use this event for custom functionality by setting a button's
CommandName property to a value that you need and then testing for it in the ItemCommand event handler. For example,
you could use this approach when selecting an item, as described in
How to: Allow Users to Select Items in DataList Web Server Controls.
For more information about Web Forms events, see ASP.NET Web Server Control Event Model.
Editing and Selecting Items
You can allow users to edit individual items in the control. Other data controls, such as the GridView, DetailsView, and
FormView controls, can interact with data source controls to support automatic updates and paging. In contrast, the DataList
control cannot automatically take advantage of the update capabilities of data source controls, or of automatic paging or
sorting. To perform updates, paging, and sorting using the DataList control, you must perform the update task in code that
you write.
The general strategy is to create an EditItemTemplate that provides the appropriate layout and controls for editing. You must
also provide a way for users to indicate that they want to edit the item. The most common way do this is to include a button in
the item template (and if you are using it, in the AlternatingItemTemplate property), and then set the button's
CommandName property to edit. Then, when the button is clicked, the DataList control automatically raises the
EditCommand event. In the code that you write for the event handler, set the item to edit mode, which displays the
EditItemTemplate.
The EditItemTemplate usually includes buttons that allow users to save or discard their changes (for example, the Update
and Cancel buttons). These buttons work similarly to the Edit button — they send a predefined command message (update
or cancel) to the DataList control, which raises an UpdateCommand or CancelCommand event that you can respond to
appropriately. For more information, see How to: Allow Users to Edit Items in DataList Web Server Controls.
The process for selecting an item is similar, using the SelectedIndexChanged event. You add a button to the ItemTemplate
and set its CommandName property to select. You then write an event handler for the SelectedIndexChanged event. The
SelectedIndexChanged event is raised when the user clicks the Select button. For details, see
How to: Allow Users to Select Items in DataList Web Server Controls. For more information, see
How to: Allow Users to Select Items in DataList Web Server Controls.
See Also
Tasks
How to: Allow Users to Select Items in DataList Web Server Controls
How to: Allow Users to Edit Items in DataList Web Server Controls
How to: Allow Users to Delete Items in DataList Web Server Controls
Visual Web Developer

Walkthrough: Displaying and Formatting Data with the


DataList Web Server Control
A common task in Web pages is to display data — in effect, to create data reports. In this walkthrough, you will work with the
DataList control, which allows you to create free-form layout for records that you display on an ASP.NET Web page.
During this walkthrough you will learn how to:
Add a DataList control and use templates to lay out the data that is displayed by the DataList control.
Bind the DataList control to a data source.
Add a child data control and some code to the DataList control to display data in a master/detail relationship.
Prerequisites
In order to complete this walkthrough, you will need:
Microsoft Visual Web Developer (Visual Studio).
Access to the SQL Server Northwind database. For information about downloading and installing the SQL Server sample
Northwind database, see Installing Sample Databases on the Microsoft SQL Server Web site.
Note
If you need information about how to log on to the computer running SQL Server, contact the server administrator.

Microsoft Data Access Components (MDAC) version 2.7 or later.


If you are using Microsoft Windows XP or Windows Server 2003, you already have MDAC 2.7. However, if you are using
Microsoft Windows 2000, you might need to upgrade the MDAC already installed on your computer. For more
information, see "Microsoft Data Access Components (MDAC) Installation" in the MSDN Library.
Creating the Web Site
Create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New, and then click Web Site. If you are using Visual Web Developer Express, on the File menu,
click New Web Site.
The New Web Site dialog box is displayed.
3. Under Visual Studio installed templates, select ASP.NET Web Site.
4. In the Location box, select File System, and enter the name of the folder where you want to keep the pages of your Web
site.
For example, type the folder name C:\WebSites\FormatDataList.
5. In the Language list, click the programming language you prefer to work in.
The programming language you choose will be the default for your Web site, but you can set the programming language
for each page individually.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Adding a DataList Control
For the first part of this walkthrough, you will add a DataList control, and then configure its data source.
To add and configure a DataList control to display data in a grid
1. Switch to Design view.
2. In the Toolbox, from the Data group, drag a DataList control onto the page.
3. Right-click the DataList control, and then click Show Smart Tag.
4. On the DataList Tasks menu, in the Choose Data Source list, click New Data Source.
The Configure Data Source wizard appears.
5. Click Database.
This specifies that you want to get data from a database that supports SQL statements. (This includes SQL Server and
other OLE-DB–compatible databases.)
6. In the Specify an ID for the data source box, a default data source control name is displayed (SqlDataSource1). You
can leave this name.
7. Click OK.
The Configure Data Source wizard displays a page in which you can create a connection.
8. Click New Connection.
If the Choose Data Source page appears, in the Data source list, select the type of data source you will use. For
this walkthrough, the data source type is Microsoft SQL Server. In the Data provider list, click .NET Framework
Data Provider for SQL Server, and the click Continue.
The Add Connection page appears.
9. On the Add Connection page, in the Server name text box, type the name of the computer running the SQL Server
database.
10. For the logon credentials, select the option that is appropriate for accessing the computer running the SQL Server
database (either integrated security or a specific ID and password) and, if required, enter a user name and password.
11. Select the Save my Password check box.
12. Click the Select or enter a database name button, and then enter Northwind.
13. Click Test Connection, and when you are sure that it works, click OK.
The Configure Data Source wizard appears with the connection information filled in.
14. Click Next.
The Configure Data Source wizard displays a page in which you can choose to store the connection string in the
configuration file. Storing the connection string in the configuration file has two advantages:
It is more secure than storing it in the page.
You can reuse the same connection string in multiple pages.
15. Be sure that the Yes, save this connection as check box is selected, and then click Next. You can leave the default
connection string.
The Configure Data Source wizard displays a page in which you can specify what data you want to fetch from the
database.
16. Make sure that Specify columns from a table or view is selected.
17. In the Name list, click Categories.
18. Under Columns, select the CategoryID and CategoryName check boxes.
The Configure Data Source wizard displays the SQL statement that you are creating in a box at the bottom of the page.
Note
The Configure Data Source wizard allows you to specify selection criteria (a WHERE clause) and other SQL query opti
ons. For this part of the walkthrough, you will create a simple statement with no selection or sort options.

19. Click Next.


20. Click Test Query to be sure that you are getting the data you want.
21. Click Finish.
The Configure Data Source wizard closes and you are returned to the SqlDataSource control. If you view the
properties for the SqlDataSource control, you can see that the Configure Data Source wizard has created values for
the ConnectionString and SelectQuery properties. Even though Properties in Visual Web Developer displays the full
connection string, only the connection string identifier is saved in the page (in this case, NorthwindConnectionString).
Formatting the Layout of the DataList Control
At this point, you have a DataList control on the page with a default layout for information from the Categories table. The
benefit of the DataList control is that you can create a free-form layout for the data. In this section, you will work with a
template and configure it with text and controls to customize the data display.
To format the layout in the DataList control
1. Right-click the DataList control, click Edit Template, and then click Item Templates.
The DataList control switches to template editing mode and displays template boxes for these templates:
ItemTemplate, which contains the text and controls that are displayed by default in the DataList control.
AlternatingItemTemplate, which is an optional template in which you can create a layout that is used for every
other data record. Typically, the AlternatingItemTemplate property is similar to the ItemTemplate property, but the
AlternatingItemTemplate property uses a different background color for a banded effect.
SelectedItemTemplate, which defines the layout for a data record that is explicitly selected using a button click or
other gesture. Typical uses for this template are to provide an expanded view of a data record or to serve as the
master record for a master/detail relationship. You must write code to support putting a record into selected mode.
(You will not do so in this walkthrough. For more information, see
How to: Allow Users to Select Items in DataList Web Server Controls and
Walkthrough: Creating Master/Detail Web Pages in Visual Studio.)
EditItemTemplate, which defines the layout for edit mode for a data record. Typically, the EditItemTemplate
property includes editable controls, such as the TextBox and CheckBox controls in which users can modify the data
record. You must write code to support putting a record into edit mode and to handle saving the record when the
edits are complete. (You will not do so in this walkthrough. For information about writing code to edit records, see
How to: Allow Users to Edit Items in DataList Web Server Controls.)
By default, Visual Web Developer populates the item template with a data-bound Label control for each data column in
the data source. In addition, Visual Web Developer generates static text for each label to act as a caption.
2. Drag the right-hand resize handle to widen the DataList control so it takes up most of the page width.
3. Edit the item template to rearrange the Label controls and create a new caption so that the template contents look
similar to the following code example.

Name: [CategoryNameLabel] (ID: [CategoryIDLabel])

4. Click the CategoryNameLabel control. In Properties, expand the Font node, and then set Bold to true.
5. In Design view, on the DataList control, right-click the title bar, click Edit Template, and then click Separator Template.
The separator template allows you to specify what text or other elements are displayed between data records.
6. In the Toolbox, from the HTML group, drag a Horizontal Rule element into the separator template.
7. On the DataList control, right-click the title bar, and then click End Template Editing.
Testing the DataList Control
You can now test the layout that you have created.
To test the DataList control
Press CTRL+F5 to run the page.
The page displays a list of category names and IDs, with a line between each record.
Displaying Related Information Inside the DataList Control
The DataList control that you are using currently displays individual Category records, using the custom layout that you
defined previously. You changed the default layout only a little bit, but you can see that by working with the template, you can
arrange text and controls, format the content, and modify the data record display in other ways.
The layout can include the current record, as well as related records. In this part of the walkthrough, you will change the layout
so that each row displays a category and the products in that category. In effect, you will display a master/detail relationship
within each row of the DataList control. You will need to write a short piece of code to enable this scenario.
To display related information inside the DataList control
1. Right-click the DataList control, click Edit Templates, and then click Item Templates.
2. In the Toolbox, from the Standard group, drag a BulletedList control onto the item template, and then drop the
BulletedList control below the category information.
The BulletedList control can display data, with one data column per bulleted item.
3. Right-click the BulletedList control, and then click Show Smart Tag.
4. Click Choose Data Source.
You will create a second data source control to read the related records.
5. In the Choose Data Source dialog box, in the Select a data source list, click New Data Source.
6. Click Database.
7. In the Specify an ID for the data source box, type bulletedListDataSource.
Although you can usually leave the default name for the data source, in this case it is useful to assign a specific,
predictable name to the data source so that you can reference it later in code.
8. Click OK.
The Configure Data Source wizard appears.
9. In the Which data connection should your application use to connect to the database? list, click the name of the
connection that you created earlier in this walkthrough, and then click Next.
The Configure Data Source wizard displays a page in which you can create an SQL statement.
10. Under Specify columns from a table or view, in the Name box, click Products.
11. In the Columns box, select the ProductName box.
The BulletedList control displays only one column.
12. Click the WHERE button.
The Add WHERE Clause dialog box appears.
13. In the Column list, click CategoryID.
14. In the Operator list, click =.
15. In the Source list, click None.
This indicates that the value of the CategoryID column will be provided in a variable.
16. Click Add, click OK, click Next, and then click Finish.
Testing the query will not work with the variable.
17. In the Select a data field to display in the BulletedList list, click ProductName. Click OK.
18. In the DataList control, right-click the title bar, and then click End Template Editing.
Writing Code to Set the Category ID
The SQL statement that you created for the bulletedListDataSource control looks similar to the following code:

SELECT [ProductName] FROM [Products] WHERE ([CategoryID] = @CategoryID)

At run time, the DataList control displays a list of category records, which includes both the category name and the category
ID. In the preceding section, you added a BulletedList control that will display all the products for each category. As each
category record is being displayed, the DataList control executes a query to get the products for that category, using the
preceding query.
For each record being displayed, you must provide the category ID to the query. You can do this by writing a short piece of
code that gets the category ID from the record that is currently being displayed, and then passes the category ID as a
parameter to the query in the bulletedListDataSource control.
To write code to set the category ID
1. Click the DataList control, and then in Properties, on the toolbar, click Events.
2. Double-click ItemDataBound to create an event handler for that event.
3. Copy the following code into the handler.
VB
If e.Item.ItemType = ListItemType.Item Or _
e.Item.ItemType = ListItemType.AlternatingItem Then
Dim ds As SqlDataSource
ds = CType(e.Item.FindControl("bulletedListDataSource"), _
SqlDataSource)
Dim categoryID As String
categoryID = DataBinder.Eval(e.Item.DataItem, _
"categoryid").ToString()
ds.SelectParameters("CategoryID").DefaultValue = _
categoryID
End If

C#
if (e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem)
{
SqlDataSource ds;
ds = e.Item.FindControl("bulletedListDataSource")
as SqlDataSource;
ds.SelectParameters["CategoryID"].DefaultValue =
DataBinder.Eval(e.Item.DataItem,
"categoryid").ToString();
}

The ItemDataBound event is raised for each data record being displayed, providing you with an opportunity to read or
modify the data. This code does the following:
a. Checks to be sure that the event is occurring while binding an ItemTemplate or AlternatingItemTemplate
object (and not a SeparatorTemplate object or other type of template).
b. Uses the FindControl method to get a reference to the SqlDataSource control instance that is created inside each
item template.
c. Gets the value of the CategoryID data column by evaluating the current DataItem property.
d. Sets the CategoryID variable of the parameterized query by setting its DefaultValue property in the
SelectParameters collection.
Testing the Code
You can now test your code.
To test the code to set the category ID
Press CTRL+F5 to run the page.
The DataList control displays each category record, and for each record, it also displays, in a bulleted list, the products
that belong to that category.
Next Steps
This walkthrough has illustrated a simple but complete scenario for displaying and formatting data with the DataList Web
server control. You can create more sophisticated data-driven pages and applications using the techniques and controls
illustrated in the walkthrough. For example, you might want to:
Write code to allow users to select items in the DataList Web server control. For more information, see
How to: Allow Users to Select Items in DataList Web Server Controls.
Create a master record for a master/detail relationship. For more information, see
Walkthrough: Creating Master/Detail Web Pages in Visual Studio.
Learn how to use output caching in your data applications to improve performance. For more information, see
Walkthrough: Using Output Caching to Enhance Web Site Performance.
See Also
Tasks
How to: Allow Users to Select Items in DataList Web Server Controls
Walkthrough: Creating Master/Detail Web Pages in Visual Studio
Reference
DataList
Concepts
Walkthrough Topics — ASP.NET Data Access (Visual Studio)
Visual Web Developer

How to: Add DataList Web Server Controls to an ASP.NET Web


Page (Visual Studio)
To add a DataList Web server control to a page requires several steps. The following procedure describes steps that you can
follow to create a working DataList control.
To add a DataList Web server control to an ASP.NET Web page
1. In Design view, from the Data tab of the Toolbox, drag a data source control onto the page, such as a SqlDataSource
control or a ObjectDataSource control.
2. Use the Configure Data Source Wizard to define the connection and the query, or data-retrieval method, for the data
source control.
Note
If you want to use the DataList control to update data (for example, by writing code for the control's UpdateCommand
or DeleteCommand event), you must be sure that the data source control is defined with appropriate queries and that t
he queries include a primary key. In the Configure Select Statement step of the Configure Data Source Wizard, you c
an click Advanced to display advanced options where you can have the wizard generate update queries.

3. In Design view, from the Data tab of the Toolbox, drag a DataList control onto the page.
4. Right-click the DataList control and click Show Smart Tag.
5. In Choose Data Source list, click the name of the data source control that you created in steps 1 and 2.
This sets the control's DataSourceID property. If the query includes a primary key, the controls' DataKeyField property is
set as well.
6. In Design view, right-click the DataList control, point to Edit Template, and then click Item Templates. The control
displays the ItemTemplate, AlternatingItemTemplate, SelectedItemTemplate, and EditItemTemplate in template-editing
mode.
By default, the ItemTemplate template is populated with static text for captions and with data-bound Label controls to
display the fields from the data source.
7. Add to the templates any HTML text and other Web server controls or HTML server controls that you need. For detailed
information about editing templates, see How to: Create Web Server Control Templates Using the Designer.
8. When you are finished editing the templates, right-click the DataList control and then click End Template Editing.
See Also
Tasks
Walkthrough: Displaying and Formatting Data with the DataList Web Server Control
How to: Allow Users to Select Items in DataList Web Server Controls
How to: Allow Users to Edit Items in DataList Web Server Controls
How to: Allow Users to Delete Items in DataList Web Server Controls
Reference
DataList Web Server Control Overview
Concepts
ASP.NET Web Server Controls Templates
ASP.NET

How to: Specify Flow or Table Format in DataList Web Server


Controls
The DataList control allows you to display the items in the control in a variety of ways. You can specify that the control renders
items in either flow mode (like a Word document) or in table mode (like an HTML table). Flow mode is suitable for simple
layouts. Table mode gives you more precise control of the layout than flow mode, and it allows you to use table attributes, such
as CellPadding.
To specify flow or table format at design time
Set the DataList control's RepeatLayout property to either Flow or Table.
To specify flow or table format programmatically
Use the RepeatLayout enumeration, as shown in the following code example.
VB
DataList1.RepeatLayout = RepeatLayout.Flow

C#
DataList1.RepeatLayout = RepeatLayout.Flow;

See Also
Reference
DataList Web Server Control Overview
ASP.NET

How to: Specify Horizontal or Vertical Layout in DataList Web


Server Controls
By default, the DataList Web server control displays a single column. However, you can specify any number of columns. Within
the columns, you can specify how the items are ordered: vertically (which is the default) or horizontally. Vertical layout in three
columns results in a layout such as the following:

1 4 7
2 5 8
3 6

Horizontal layout for the same items results in the following layout:

1 2 3
4 5 6
7 8

To specify column count and ordering at design time


1. Set the DataList control's RepeatColumns property to the number of columns that you want.
2. Set the RepeatDirection property to either Vertical or Horizontal.
To specify column count and ordering programmatically
Specify the number of columns that want by using the RepeatColumns property, and then specify how you want the
items in the columns to be ordered by using the RepeatDirection enumeration, as shown in the following code
example.
VB
DataList1.RepeatColumns = 2
DataList1.RepeatDirection = RepeatDirection.Horizontal

C#
DataList1.RepeatColumns = 2;
DataList1.RepeatDirection = RepeatDirection.Horizontal;

See Also
Reference
DataList Web Server Control Overview
Visual Web Developer

Learning More — DataList Web Server Control (Visual Studio)


The topics in this section provide in-depth information on working with ASP.NET DataList Web server controls, including how
to program events raised by the control.
In This Section
How to: Allow Users to Select Items in DataList Web Server Controls
How to: Allow Users to Edit Items in DataList Web Server Controls
How to: Allow Users to Delete Items in DataList Web Server Controls
How to: Respond to Button Events in DataList, Repeater, or GridView Items
How to: Customize DataList Items at Run Time
How to: Customize Items Dynamically in the DataList Web Server Control
How to: Create Templates Dynamically in DataList Web Server Controls
See Also
Concepts
ASP.NET Web Server Controls Templates
Other Resources
Data Toolbox Controls
ASP.NET Data Access (Visual Studio)
ASP.NET

How to: Allow Users to Select Items in DataList Web Server


Controls
You can specify that users can select individual items in the DataList Web server control. Typically, selecting an item highlights
it visually. In addition, you might display different information for a selected item.
To allow users to select items in a DataList control
1. Create a SelectedItemTemplate to define the layout of markup and controls for a selected item. For details, see
ASP.NET Web Server Controls Templates.
2. Set the control's SelectedItemStyle properties. For details, see ASP.NET Web Server Controls and CSS Styles.
3. In the ItemTemplate (and AlternatingItemTemplate, if you are using it), add a Button or LinkButton Web server
control.
4. Set the CommandName property of the button from Step 3 to select (case-sensitive).
5. Create an event handler for the DataList control's SelectedIndexChanged event. In the event handler, call the control's
DataBind method to refresh the information in the control. The complete code would look something like this:
VB
Protected Sub DataList1_SelectedIndexChanged(ByVal sender As _
System.Object, ByVal e As System.EventArgs) _
Handles DataList1.SelectedIndexChanged
DataList1.DataBind()
End Sub

C#
protected void DataList1_SelectedIndexChanged (object sender,
System.EventArgs e)
{
DataList1.DataBind();
}

To cancel the selection, set the control's SelectedIndex property to -1. To accomplish this, you could add a Button Web server
control to the SelectedItem template and set its CommandName property to "unselect". The Click event for this button
would also be forwarded to the DataGrid control's ItemCommand event.
The complete code might look something like the following:
VB
Protected Sub DataList1_ItemCommand(ByVal source As Object, _
ByVal e As DataListCommandEventArgs) _
Handles DataList1.ItemCommand
If e.CommandName = "unselect" Then
DataList1.SelectedIndex = -1
End If
DataList1.DataBind()
End Sub

See Also
Reference
DataList Web Server Control Overview
ASP.NET

How to: Allow Users to Edit Items in DataList Web Server


Controls
You can allow users to edit individual items in the DataList Web server control. When an individual item is set to edit mode, the
values that can be changed are usually displayed in text boxes or other controls in which users can make their changes.
To allow users to edit items in a DataList control
1. Set the DataList control's DataKeyField property to the name of the field in the data that contains the primary key.
2. Create an ItemTemplate (and, if you are using it, an AlternatingItemTemplate), and then add a Button Web server control
to it. Set the CommandName property for this button to edit.
Note
You can use a LinkButton or an ImageButton control in any step that calls for a Button Web server control.

3. Create an EditItemTemplate for the DataList control that includes the following:
Controls for all of the values that users can change. For example, include TextBox controls for all character and
numeric data. Use the declarative Eval method to specify which field each control is bound to, as in this example:
Security Note
This example has a text box that accepts user input, which is a potential security threat. By default, ASP.NET Web p
ages validate that user input does not include script or HTML elements. For more information, see
Script Exploits Overview.

<asp:TextBox ID="TextBox1"
runat="server"
Text='<%# Eval("ProductName") %>' />

A Button control with its Text property set to "Update" and its CommandName property set to update (case-
sensitive).
A Button control with its Text property set to "Cancel" and its CommandName property set to cancel.
The Update button will allow users to specify that they are finished editing and will save any changes. The Cancel
button will allow them to quit editing without saving changes.
4. Write code to perform the following tasks:
Handle the DataList control's EditCommand event that sets the DataList control's EditItemIndex property to the
index value of the item to put into edit mode. The index of the item that the user clicked is available via the Item
object's ItemIndex property. Then call the control's DataBind method.
Handle the DataList control's CancelCommand event that sets the DataList control's EditItemIndex property to -
1 and then calls the control's DataBind method.
Handle the DataList control's UpdateCommand event. In the code, extract the values from the controls in the
current item and pass them to the data source control for an update operation. The exact code you use depends on
the type of data source control that you are working with.
Example
The following code example shows an ASP.NET page that uses a DataList control and a SqlDataSource control to display
information from the Categories table in the Northwind database. Users can edit the items.
Security Note
This example has a text box that accepts user input, which is a potential security threat. By default, ASP.NET Web pages valida
te that user input does not include script or HTML elements. For more information, see Script Exploits Overview.

VB
<%@ Page Language="VB" %>
<script runat="server">
Protected Sub DataList1_EditCommand(ByVal source As Object, _
ByVal e As System.Web.UI.WebControls.DataListCommandEventArgs)
DataList1.EditItemIndex = e.Item.ItemIndex
DataList1.DataBind()
End Sub
Protected Sub DataList1_CancelCommand(ByVal source As Object, _
ByVal e As System.Web.UI.WebControls.DataListCommandEventArgs)
DataList1.EditItemIndex = -1
DataList1.DataBind()
End Sub
Protected Sub DataList1_UpdateCommand(ByVal source As Object, _
ByVal e As System.Web.UI.WebControls.DataListCommandEventArgs)
Dim categoryID As String = _
DataList1.DataKeys(e.Item.ItemIndex).ToString()
Dim categoryName As TextBox = _
CType(e.Item.FindControl("textCategoryName"), TextBox)
Dim description As TextBox = _
CType(e.Item.FindControl("textDescription"), TextBox)
SqlDataSource1.UpdateParameters("original_CategoryID"). _
DefaultValue = categoryID
SqlDataSource1.UpdateParameters("categoryName"). _
DefaultValue = categoryName.Text
SqlDataSource1.UpdateParameters("Description"). _
DefaultValue = description.Text
SqlDataSource1.Update()
DataList1.EditItemIndex = -1
DataList1.DataBind()
End Sub
</script>

<html>
<head runat="server"></head>
<body>
<form id="form1" runat="server">
<div>
<br />
<asp:DataList runat="server"
DataKeyField="CategoryID"
DataSourceID="SqlDataSource1" ID="DataList1"
OnEditCommand="DataList1_EditCommand"
OnCancelCommand="DataList1_CancelCommand"
OnUpdateCommand="DataList1_UpdateCommand">
<EditItemTemplate>
ID: <asp:Label ID="Label1" runat="server"
Text='<%# Eval("CategoryID") %>'>
</asp:Label>
<br />
Name: <asp:TextBox ID="textCategoryName" runat="server"
Text='<%# Eval("CategoryName") %>'>
</asp:TextBox>
<br />
Description: <asp:TextBox ID="textDescription"
runat="server"
Text='<%# Eval("Description") %>'>
</asp:TextBox>
<br />
<asp:LinkButton ID="LinkButton1" runat="server"
CommandName="update" >
Save
</asp:LinkButton>
&nbsp;
<asp:LinkButton ID="LinkButton2" runat="server">
CommandName="cancel"
Cancel
</asp:LinkButton>
</EditItemTemplate>
<ItemTemplate>
CategoryID:
<asp:Label ID="CategoryIDLabel" runat="server"
Text='<%# Eval("CategoryID") %>'>
</asp:Label>
<br />
CategoryName:
<asp:Label ID="CategoryNameLabel" runat="server"
Text='<%# Eval("CategoryName") %>'>
</asp:Label>
<br />
Description:
<asp:Label ID="DescriptionLabel" runat="server"
Text='<%# Eval("Description") %>'>
</asp:Label>
<br />
<asp:LinkButton runat="server" ID="LinkButton1"
CommandName="edit" >
Edit
</asp:LinkButton><br />
</ItemTemplate>
</asp:DataList>

<asp:SqlDataSource ID="SqlDataSource1" runat="server"


ConnectionString=
"<%$ ConnectionStrings:NorthwindConnectionString %>"
SelectCommand="SELECT [CategoryID], [CategoryName],
[Description] FROM [Categories]"
UpdateCommand="UPDATE [Categories] SET [CategoryName] =
@CategoryName, [Description] = @Description
WHERE [CategoryID] = @original_CategoryID">
<UpdateParameters>
<asp:Parameter Name="CategoryName" Type="String" />
<asp:Parameter Name="Description" Type="String" />
<asp:Parameter Name="original_CategoryID" Type="Int32" />
</UpdateParameters>
</asp:SqlDataSource>
</div>
</form>
</body>
</html>

C#
<%@ Page Language="C#" %>
<script runat="server">
protected void DataList1_EditCommand(object source,
DataListCommandEventArgs e)
{
DataList1.EditItemIndex = e.Item.ItemIndex;
DataList1.DataBind();
}

protected void DataList1_CancelCommand(object source,


DataListCommandEventArgs e)
{
DataList1.EditItemIndex = -1;
DataList1.DataBind();
}
protected void DataList1_UpdateCommand(object source,
DataListCommandEventArgs e)
{
String categoryID =
DataList1.DataKeys[e.Item.ItemIndex].ToString();
String categoryName =
((TextBox)e.Item.FindControl("textCategoryName")).Text;
String description =
((TextBox) e.Item.FindControl("textDescription")).Text;
SqlDataSource1.UpdateParameters["original_CategoryID"].DefaultValue
= categoryID;
SqlDataSource1.UpdateParameters["categoryName"].DefaultValue
= categoryName;
SqlDataSource1.UpdateParameters["Description"].DefaultValue
= description;
SqlDataSource1.Update();

DataList1.EditItemIndex = -1;
DataList1.DataBind();
}
</script>
<html>
<head runat="server"></head>
<body>
<form id="form1" runat="server">
<div>
<br />
<asp:DataList runat="server"
DataKeyField="CategoryID"
DataSourceID="SqlDataSource1" ID="DataList1"
OnEditCommand="DataList1_EditCommand"
OnCancelCommand="DataList1_CancelCommand"
OnUpdateCommand="DataList1_UpdateCommand">
<EditItemTemplate>
ID: <asp:Label ID="Label1" runat="server"
Text='<%# Eval("CategoryID") %>'>
</asp:Label>
<br />
Name: <asp:TextBox ID="textCategoryName" runat="server"
Text='<%# Eval("CategoryName") %>'>
</asp:TextBox>
<br />
Description: <asp:TextBox ID="textDescription"
runat="server"
Text='<%# Eval("Description") %>'>
</asp:TextBox>
<br />
<asp:LinkButton ID="LinkButton1" runat="server"
CommandName="update" >
Save
</asp:LinkButton>
&nbsp;
<asp:LinkButton ID="LinkButton2" runat="server">
CommandName="cancel"
Cancel
</asp:LinkButton>
</EditItemTemplate>
<ItemTemplate>
CategoryID:
<asp:Label ID="CategoryIDLabel" runat="server"
Text='<%# Eval("CategoryID") %>'>
</asp:Label>
<br />
CategoryName:
<asp:Label ID="CategoryNameLabel" runat="server"
Text='<%# Eval("CategoryName") %>'>
</asp:Label>
<br />
Description:
<asp:Label ID="DescriptionLabel" runat="server"
Text='<%# Eval("Description") %>'>
</asp:Label>
<br />
<asp:LinkButton runat="server" ID="LinkButton1"
CommandName="edit" >
Edit
</asp:LinkButton><br />
</ItemTemplate>
</asp:DataList>

<asp:SqlDataSource ID="SqlDataSource1" runat="server"


ConnectionString=
"<%$ ConnectionStrings:NorthwindConnectionString %>"
SelectCommand="SELECT [CategoryID], [CategoryName],
[Description] FROM [Categories]"
UpdateCommand="UPDATE [Categories] SET [CategoryName] =
@CategoryName, [Description] = @Description
WHERE [CategoryID] = @original_CategoryID">
<UpdateParameters>
<asp:Parameter Name="CategoryName" Type="String" />
<asp:Parameter Name="Description" Type="String" />
<asp:Parameter Name="original_CategoryID" Type="Int32" />
</UpdateParameters>
</asp:SqlDataSource>
</div>
</form>
</body>
</html>

To update data, you need the primary key of the record that is being updated. You can get that value from the DataKeyField
property, which contains an array of keys.
To get the value of a specific control in the item, use the FindControl method of the Item event-argument object.
The values that you set in the SqlDataSource1.UpdateParameters dictionary must match the names that you set in the
UpdateParameters element.
Compiling the Code
The code requires that you have a connection string named NorthwindConnectionString. The database you connect to is
assumed to have a table named Categories with the fields CategoryID, CategoryName, and Description.
The account under which the page connects to the database must have permission to update the Category table.
Robust Programming
The code in the example does not perform the following tasks that you would normally do in a production environment:
The code does not include error checking to be sure that the FindControl method returns a valid control. For more
robust code, make sure that the value returned by the FindControl method is not a null reference (Nothing in Visual
Basic).
The code does not check whether the update was successful.

Security
User input in a Web Forms page can include potentially malicious client script. By default, the Web Forms page validates that
user input does not include script or HTML elements. For more information, see Script Exploits Overview.
See Also
Reference
DataList Web Server Control Overview
Concepts
Modifying Data using the SqlDataSource Control
Using Parameters with the SqlDataSource Control
ASP.NET

How to: Allow Users to Delete Items in DataList Web Server


Controls
You can allow users to delete items in a DataList control in a variety of ways. One way is to include a Delete button in an item
and to delete that item immediately when the user clicks it.
Another way is to include a check box in individual items. Users can then check all the items they want to remove and then click
a separate Delete button to delete them in a batch. This method is used in programs such as MSN Hotmail.
To allow users to delete individual items
1. Add a data source control to the page.
2. Define the delete command or method for the data source control.
For example, if you are using a SqlDataSource control, set the data source control's DeleteCommand property to a SQL
Delete statement that includes a placeholder for the ID, as in the following example:

DELETE FROM Categories WHERE CategoryID = @CategoryID

If you are using an ObjectDataSource control, set the DeleteMethod property to the name of a method that performs the
deletion.
3. In the data source control, create an entry for the DeleteParameters property that includes a single parameter for the ID
of the record to delete.
For example, a SqlDataSource element might look like the following:

<asp:SqlDataSource ID="SqlDataSource1"
Runat="server"
ConnectionString=
"<%$ ConnectionStrings:NorthwindConnectionString %>"
DeleteCommand="DELETE FROM [Categories]
WHERE [CategoryID] = @CategoryID">
<DeleteParameters>
<asp:Parameter Type="Int32"
Name="CategoryID">
</asp:Parameter>
</DeleteParameters>
</asp:SqlDataSource>

Note
Other commands, such as the SelectCommand and UpdateCommand are not shown in the example.

An ObjectDataSource element might look like the following:

<asp:ObjectDataSource ID="ObjectDataSource1" Runat="server"


DeleteMethod="DeleteCategory()">
<DeleteParameters>
<asp:Parameter Name="example"></asp:Parameter>
</DeleteParameters>
</asp:ObjectDataSource>

4. In the DataList control, set the DataKeyField property to the primary key of the table you want to delete records from.
5. In the ItemTemplate (and AlternatingItemTemplate, if you are using it), add a Button or LinkButton Web server control.
6. Set the CommandName property for the button to delete.
The markup for the DataList control element might look like the following:

<asp:DataList ID="DataList1" Runat="server"


DataSourceID="SqlDataSource1"
DataKeyField="CategoryID"
OnDeleteCommand="DataList1_DeleteCommand">
<ItemTemplate>
CategoryName: <asp:Label ID="CategoryNameLabel"
Runat="server"
Text='<%# Eval("CategoryName") %>'>
</asp:Label>
<br />
Description: <asp:Label ID="DescriptionLabel"
Runat="server"
Text='<%# Eval("Description") %>'>
</asp:Label>
<br />
<asp:Button ID="Delete" Runat="server"
Text="Delete"
CommandName="delete" />
</ItemTemplate>
</asp:DataList>

7. Create an event handler for the DataList control's DeleteCommand event. In the method:
a. Get the ID of the record to delete from the DataList control's DataKeys collection. You can get the key for the
current record using the index returned by the ItemIndex property of the current item.
b. Set the DefaultValue property of the parameter you created in step 3.
c. Call the data source control's Delete method.
The following code illustrates these tasks, using a SqlDataSource control named SqlDataSource1 as the data source:
VB
Protected Sub DataList1_DeleteCommand(ByVal source As Object,
ByVal e As DataListCommandEventArgs)
Dim id As Integer = _
CInt(DataList1.DataKeys(e.Item.ItemIndex))
SqlDataSource1.DeleteParameters("CategoryID").DefaultValue _
= id
SqlDataSource1.Delete()
End Sub

C#
protected void DataList1_DeleteCommand(object source,
DataListCommandEventArgs e)
{
int id = (int)DataList1.DataKeys[e.Item.ItemIndex];
SqlDataSource1.DeleteParameters["CategoryID"].DefaultValue
= id;
SqlDataSource1.Delete();
}

To allow users to delete multiple items at once


1. Add a data source control to the page, configure its delete command or method, and create a parameter as described in
the preceding procedure.
2. In the DataList control's ItemTemplate (and AlternatingItemTemplate , if you are using that), add a CheckBox Web
server control and set its ID property to a specific name, such as "Delete." Make sure that the AutoPostBack property of
the CheckBox control is set to false.
3. Add a Button Web server control to the page. Set the Text property to "Delete All" and the ID property to DeleteAll. This
button is not added to one of the DataList templates.
4. Create a method for the Click event of the Delete All button. In the method:
a. Loop through the Items collection of the DataList control, extracting each item in turn.
b. Within the item, use the item's FindControl method to get the CheckBox control from Step 1 and test its Checked
property.
c. If the box is checked, delete the corresponding item from the data source.
The following example shows an event handler for the DeleteAll button that deletes items in a batch using the
procedure outlined above.
[Visual Basic]
[C#]
See Also
Reference
DataList Web Server Control Overview
ASP.NET

How to: Respond to Button Events in DataList, Repeater, or


GridView Items
If your DataList, Repeater, or GridView control template includes Button, LinkButton, or ImageButton Web Server controls,
these buttons can send their Click events to the containing DataList, Repeater, or GridView control. This allows you to
include buttons for functions not already defined for the DataList and GridView controls (edit, delete, update, and cancel) and
to define functionality for the Repeater control.
To respond to button events in DataList, Repeater, and GridView controls
1. Include a Button, LinkButton, or ImageButton in a control template.
2. Set the button's CommandName property to a string that identifies its function, such as "sort" or "copy".
3. Create a method for the ItemCommand event of the containing control. In the method, do the following:
a. Check the CommandName property of the event-argument object to see what string was passed.
b. Perform the appropriate logic for the button that the user clicked.
The following example shows how you can respond to a button click in a DataList control. In the example, the
ItemTemplate contains an ImageButton control that displays a shopping cart. The button sends the command
AddToCart. The ItemCommand event handler determines which button was clicked, and — if it was the shopping cart
button — performs the appropriate logic.
VB
Protected Sub DataList1_ItemCommand(ByVal source As Object, _
ByVal e As DataListCommandEventArgs)
If e.CommandName = "AddToCart" Then
' Add code here to add the item to the shopping cart.
' Use the value of e.Item.ItemIndex to find the data row
' in the data source.
End If
End Sub

C#
protected void DataList1_ItemCommand(object source,
DataListCommandEventArgs e)
{
if (e.CommandName == "AddToCart")
{
// Add code here to add the item to the shopping cart.
// Use the value of e.Item.ItemIndex to find the data row
// in the data source.
}
}

For an example using the DataList Web server control, see


How to: Allow Users to Select Items in DataList Web Server Controls.
See Also
Tasks
How to: Allow Users to Edit Items in DataList Web Server Controls
How to: Allow Users to Delete Items in DataList Web Server Controls
Reference
DataList Web Server Control Overview
ASP.NET

How to: Customize DataList Items at Run Time


During page processing, the DataList control creates individual items that it will render to the page. To allow you to customize
the items as they are being created, the DataList control raises two events:
The ItemCreated event is raised as the DataList control creates each item, alternating item, header, footer, and so on.
The ItemDataBound event is raised after the controls in an item have been data bound. You can use the event parameters
to access the data being used for data binding. Use this event if the customization depends on the data.
By responding to these events, you can change the items. A typical use is to change the appearance of the item based on the
data being displayed in it. For example, if a numeric value you read from a database is negative, you might set the item's
background color to red.
To customize items at run time using the ItemCreated event
1. Create an event handler for the DataList control's ItemCreated event.
2. In the event handler, get the current item using the Item object from the e event-argument object. The index of the
current item is available through the Item object's ItemIndex property, and its type is available through its ItemType
property (which is defined using the ListItemType enumeration).
Note
The ItemIndex property returns a positive value only for Item, AlternatingItem, and SelectedItem objects. The index val
ue for header, footer, and separator items is -1.

The following example shows how you can modify the background color of an item conditionally. The example uses the
ItemType property and the ListItemType enumeration to set the background colors of the items. Items are set to
LightGoldenrodYellow, alternating items are set to DarkGoldenrod, and the selected item is set to Yellow.
VB
Protected Sub DataList1_ItemCreated(ByVal sender As Object, _
ByVal e As EventArgs)
Select Case e.Item.ItemType
Case ListItemType.Item
e.Item.BackColor = _
System.Drawing.Color.LightGoldenrodYellow
Case ListItemType.AlternatingItem
e.Item.BackColor = System.Drawing.Color.DarkGoldenrod
Case ListItemType.SelectedItem
e.Item.BackColor = System.Drawing.Color.Yellow
Case Else
' Add code here to hand the header, footer, and
' separator templates.
End Select
End Sub

C#
protected void DataList1_ItemCreated(object sender,
EventArgs e)
{
switch (e.Item.ItemType)
{
case ListItemType.Item :
e.Item.BackColor =
System.Drawing.Color.LightGoldenrodYellow;
break;
case ListItemType.AlternatingItem :
e.Item.BackColor = System.Drawing.Color.DarkGoldenrod;
break;
case ListItemType.SelectedItem :
e.Item.BackColor = System.Drawing.Color.Yellow;
break;
default :
// Add code here to handle the header, footer, and
// separator templates.
break;
}
}

At the time that the ItemCreated event is raised, the individual controls in the templates have not yet been bound to data.
However, the data is available in the ItemDataBound event.
To customize items at run time using the ItemDataBound event
1. Create an event handler for the DataList control's ItemDataBound event.
2. In the event handler, test that you are working with an Item, AlternatingItem, or EditItem and not with a header or
footer.
3. Use the DataItem property to test the data that will be bound to the control and base a comparison on that.
The following example shows how you can make a conditional test based on data. The example casts the DataItem
property of the event argument as a DataRowView object. It then extracts the field called Quantity from the current
DataItem. If the quantity is less than 10, the item in the DataList control is colored red.
VB
Protected Sub DataList1_ItemDataBound(ByVal sender As Object, _
ByVal e As DataListItemEventArgs)
If e.Item.ItemType = ListItemType.Item Or _
e.Item.ItemType = ListItemType.AlternatingItem Then
Dim drv As System.Data.DataRowView = _
CType(e.Item.DataItem, System.Data.DataRowView)
Dim quantity As Integer = _
Integer.Parse(drv.Row("Quantity").ToString())
If (quantity < 10) Then
e.Item.BackColor = System.Drawing.Color.Red
End If
End If
End Sub

C#
protected void DataList1_ItemDataBound(object sender,
DataListItemEventArgs e)
{
if(e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem)
{
System.Data.DataRowView drv =
(System.Data.DataRowView)(e.Item.DataItem);
int quantity = int.Parse(drv.Row["Quantity"].ToString());
if (quantity < 10)
{
e.Item.BackColor = Color.Red;
}
}
}

See Also
Reference
DataList Web Server Control Overview
ASP.NET

How to: Customize Items Dynamically in the DataList Web


Server Control
You can customize items in the DataList control dynamically, which is useful if you want to set item characteristics based on
information available at run time. This topic contains two examples that show how to customize the items in a DataList
control.
The first code example shows how to customize an individual item when the customization does not involve data. The example
displays different types of templates with different background colors.
The second code example shows how to customize the contents of a DataList control item based on the data being displayed
in it. The code examines the contents of a data-bound label in the item to extract a date (date of birth). If the date-of-birth
month is the same as the current month, the item is highlighted using color.
Example
VB
' Example 1
Private Sub DataList1_ItemCreated(ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.DataListItemEventArgs) _
Handles DataList1.ItemCreated
Select Case e.Item.ItemType
Case ListItemType.Item
e.Item.BackColor = Color.LightGoldenrodYellow
Case ListItemType.AlternatingItem
e.Item.BackColor = Color.DarkGoldenrod
Case ListItemType.SelectedItem
e.Item.BackColor = Color.Yellow
Case Else
' Add code here to handle the header, footer, and
' separator templates.
End Select
End Sub

' Example 2
Private Sub DataList1_ItemDataBound(ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.DataListItemEventArgs) _
Handles DataList1.ItemDataBound
Dim dob As DateTime
Dim doblabel As Label
doblabel = CType(e.Item.FindControl("Label1"), Label)
dob = CType(doblabel.Text, DateTime)
If dob.Month = Today.Month Then
e.Item.BackColor = Color.Yellow
End If
End Sub

Compiling the Code


These examples require:
A DataList control named DataList1 that is bound to the Employees table of the Northwind database. For information
on binding a DataList control to a data source, see
How to: Add DataList Web Server Controls to an ASP.NET Web Page (Visual Studio).
An item template containing at least one Label control called Label1. This label should be bound to the BirthDate field of
the Employees table. For information on binding controls to fields, see Data-Binding Expression Syntax.
Robust Programming
The most reliable way to extract the value of a control in a DataList control template is to:
1. Assign an ID to the control at design time.
2. Use the FindControl method of the naming container (in this example, a DataListItem object).
The FindControl method returns an object of type Control. You must cast this object to the appropriate control type. If no
object is found and you try to extract its value, the control throws an exception of type NullReferenceException.
See Also
Tasks
How to: Customize DataList Items at Run Time
Concepts
Web Forms Control Identification
ASP.NET

How to: Create Templates Dynamically in DataList Web Server


Controls
Templates do not have to be assigned at design time. In some situations, you might be able to lay out the template at design
time, but changes you know you will make during run time are so extensive that loading a new template at run time simplifies
the programming. In other cases, you may have several possible templates but want to change the template at run time.
To create a template definition file
1. Create a new text file with an .ascx extension.
2. Add template definition statements to the template file and save it, using the same markup that you would use in any
declarative template.
The following example shows the content of an .ascx file with the markup for a template that contains data-bound Label
controls. The data binding will be resolved at run time against the data source that is bound to the DataList control.

Name: <asp:Label ID="CategoryNameLabel" runat="server"


Text='<%# Eval("CategoryName") %>'>
</asp:Label>
<br />
Description: <asp:Label ID="DescriptionLabel" runat="server"
Text='<%# Eval("Description") %>'>
</asp:Label>

To create templates dynamically


Add code to your Web Forms page to load the template using the LoadTemplate method. This method reads a template
definition from a file and creates an ITemplate object. You can then assign this object to any of the templates in a
DataList control.
The following code uses the Page_Load event handler to load a template created as shown above and named
NewTemplate.ascx.
VB
Protected Sub Page_Init(ByVal Sender As System.Object, _
ByVal e As System.EventArgs)
If (Not Page.IsPostBack) Then
DataList1.AlternatingItemTemplate = _
Page.LoadTemplate("NewTemplate.ascx")
End If
End Sub

C#
protected void Page_Init(object sender, EventArgs e)
{
DataList1.AlternatingItemTemplate =
Page.LoadTemplate("NewTemplate.ascx");
}

See Also
Reference
DataList Web Server Control Overview
Visual Web Developer

Walkthrough Topics — DataList Web Server Control (Visual


Studio)
The following walkthrough topic demonstrates how to create and program ASP.NET DataList Web server controls.
Walkthrough Topics
Walkthrough: Displaying and Formatting Data with the DataList Web Server Control
See Also
Other Resources
DataList Web Server Control (Visual Studio)
Visual Web Developer

How-to Topics — DataList Web Server Control (Visual Studio)


The following procedures describe how to create and program ASP.NET DataList Web server controls.
How-to Topics
How to: Add DataList Web Server Controls to an ASP.NET Web Page (Visual Studio)
How to: Specify Flow or Table Format in DataList Web Server Controls
How to: Specify Horizontal or Vertical Layout in DataList Web Server Controls
How to: Allow Users to Select Items in DataList Web Server Controls
How to: Allow Users to Edit Items in DataList Web Server Controls
How to: Allow Users to Delete Items in DataList Web Server Controls
How to: Respond to Button Events in DataList, Repeater, or GridView Items
How to: Customize DataList Items at Run Time
How to: Customize Items Dynamically in the DataList Web Server Control
How to: Create Templates Dynamically in DataList Web Server Controls
See Also
Other Resources
DataList Web Server Control (Visual Studio)
Visual Web Developer

Data Source Web Server Controls (Visual Studio)


Data-bound Web server controls are controls that can be bound to a data source control to make it easy to display and modify
data in your Web application. Data-bound Web server controls are composite controls that combine other ASP.NET Web
controls, such as Label and TextBox controls, into a single layout.
The topics in this section provide information on the built-in data source controls in ASP.NET and how to use them to connect
to data sources.
For complete syntax information for Web server controls, see Web Server Control Syntax.
In This Section
Data Source Controls Overview
Binding to Data Using a Data Source Control
Sorting Data with Data Source Controls
Using Parameters with Data Source Controls
Modifying Data using Data Source Controls
Filtering Data Using Data Source Controls
Caching Data Using Data Source Controls
Handling Null Database Values Using Data Source Controls
SqlDataSource Web Server Control (Visual Studio)
AccessDataSource Control (Visual Studio)
ObjectDataSource Web Server Control (Visual Studio)
XmlDataSource Web Server Control (Visual Studio)
SiteMapDataSource Web Server Control (Visual Studio)
See Also
Other Resources
Data Toolbox Controls
ASP.NET Data Access (Visual Studio)
ASP.NET

Data Source Controls Overview


ASP.NET includes data source controls that allow you to work with different types of data sources such as a database, an XML
file, or a middle-tier business object. Data source controls connect to and retrieve data from a data source and make it available
for other controls to bind to, without requiring code. They can also support modifying data.
This topic provides information about the different types of data source controls in ASP.NET. The data source control model is
extensible, so you can also create your own data source controls that interact with different data sources or that provide
additional functionality for an existing data source.
Data Source Control Comparison
The .NET Framework includes data source controls to support different data-binding scenarios. The following table describes
the built-in data source controls. More detail about each type of data source control is provided later in this topic.
Data source contr Description
ol
ObjectDataSource Enables you to work with a business object or other class and create Web applications that rely on middle
-tier objects to manage data. Supports advanced sorting and paging scenarios unavailable with the other
data source controls.

SqlDataSource Enables you to work with Microsoft SQL Server, OLE DB, ODBC, or Oracle databases. When used with SQL
Server, supports advanced caching capabilities. The control also supports sorting, filtering, and paging wh
en data is returned as a DataSet object.

AccessDataSource Enables you to work with a Microsoft Access database. Supports sorting, filtering, and paging when data is
returned as a DataSet object.

XmlDataSource Enables you to work with an XML file, especially for hierarchical ASP.NET server controls such as the
TreeView or Menu control. Supports filtering capabilities using XPath expressions and enables you to appl
y an XSLT transformation to the data. The XmlDataSource allows you to update data by saving the entire
XML document with changes.

SiteMapDataSource Used with ASP.NET site navigation. For more information, see ASP.NET Site Navigation Overview.

ObjectDataSource Control
The ObjectDataSource control works with a business object or other class in Web applications that rely on middle-tier
business objects to manage data. The control is designed to interact with an object that implements one or more methods to
retrieve or modify data. When data-bound controls interact with the ObjectDataSource control to retrieve or modify data, the
ObjectDataSource control passes values from the bound control to the source object as parameters in method calls.
The source object's data-retrieval methods must return a DataSet, DataTable, or DataView object, or an object that implements
the IEnumerable interface. If the data is returned as a DataSet, DataTable, or DataView object, the ObjectDataSource
control can cache and filter the data. You can also implement advanced paging scenarios if the source object accepts page size
and record index information from the ObjectDataSource control.
For more information, see ObjectDataSource Web Server Control.
SqlDataSource Control
The SqlDataSource control retrieves and modifies data using SQL commands. The SqlDataSource control works with
Microsoft SQL Server, OLE DB, ODBC, and Oracle databases.
The SqlDataSource control can return results as a DataReader or a DataSet object. It supports sorting, filtering, and caching
when the results are returned as a DataSet. When you are working with Microsoft SQL Server, the control has the added
benefit that cache results can be invalidated when the database changes, using a SqlCacheDependency object.
For more information, see SqlDataSource Web Server Control.
AccessDataSource Control
The AccessDataSource control is a specialized version of the SqlDataSource control, designed to work specifically with
The AccessDataSource control is a specialized version of the SqlDataSource control, designed to work specifically with
Microsoft Access .mdb files. As with the SqlDataSource control, you use SQL statements to define how the control fetches and
retrieves data.
For more information, see AccessDataSource Web Server Control.
XmlDataSource Control
The XmlDataSource control reads and writes XML data so that you can work with it using controls such as the TreeView and
Menu controls. The XmlDataSource control can read either an XML file or string of XML. If the control is working with an XML
file, it can write modified XML back to the source file. If a schema is available that describes the data, the XmlDataSource
control can use the schema to expose data using typed members.
You can apply an XSLT transformation to the XML data, which allows you to restructure the raw data from the XML file into a
format better suited to the control you want to bind to the XML data.
You can also apply XPath expressions to the XML data, which allows you to filter the XML data to return only certain nodes in
the XML tree, to look for nodes that have specific values in them, and so on. Using an XPath expression disables the ability to
insert new data.
For more information, see XmlDataSource Web Server Control.
SiteMapDataSource Control
The SiteMapDataSource control works with ASP.NET site maps and provides site navigation data. It is most commonly used
with the Menu control. The SiteMapDataSource control is also useful when you want to customize site navigation using site
map data with Web server controls that are not specifically designed for navigation, such as the TreeView or DropDownList
controls.
For more information, see SiteMapDataSource Web Server Control.
See Also
Concepts
ASP.NET Data Access Overview
Binding to Databases
Using Parameters with Data Source Controls
ASP.NET

Binding to Data Using a Data Source Control


Data source controls greatly expand the capabilities of data-bound controls such as the GridView, FormView, and DetailsView
controls. Working together, data source controls and data-bound controls allow you retrieve, modify, page, sort, and filter data
from different data sources with little or no code.
Binding Using the DataSourceID Property
You can work with data in a data-bound control by binding the data-bound control to a data source control such as an
ObjectDataSource or SqlDataSource control. The data source control connects to a data source such as a database or middle-
tier object and then retrieves or updates data. The data-bound control can then use this data. To perform the binding, you set
the data-bound control's DataSourceID property to point to a data source control. When a data-bound control is bound to a
data source control, little or no additional code is required for data operations, because the data-bound control can
automatically take advantage of the data services provided by the data source control.
Note
In previous versions of ASP.NET, data-bound controls were bound to data using the DataSource property and required you t
o write code to handle operations such as displaying, paging, sorting, editing, and deleting data. Although you can still bind c
ontrols to data using the DataSource property (and use existing code), you can now performing binding using the DataSou
rceID property instead.

The following code example shows a FormView control bound to a SqlDataSource control to display data from a database.
VB
<%@ Page language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>FormView Example</title>
</head>
<body>
<form id="form1" runat="server">
<h3>FormView Example</h3>
<table cellspacing="10">
<tr>
<td valign="top">

<asp:FormView ID="ProductsFormView"
DataSourceID="ProductsSqlDataSource"
AllowPaging="true"
runat="server">
<HeaderStyle forecolor="white" backcolor="Blue" />

<ItemTemplate>
<table>
<tr>
<td align="right"><b>Product ID:</b></td>
<td><asp:Label id="ProductIDLabel" runat="server" Text='<%# Eval("Pro
ductID") %>' /></td>
</tr>
<tr>
<td align="right"><b>Product Name:</b></td>
<td><asp:Label id="ProductNameLabel" runat="server" Text='<%# Eval("P
roductName") %>' /></td>
</tr>
<tr>
<td align="right"><b>Category ID:</b></td>
<td><asp:Label id="CategoryIDLabel" runat="server" Text='<%# Eval("Ca
tegoryID") %>' /></td>
</tr>
<tr>
<td align="right"><b>Quantity Per Unit:</b></td>
<td><asp:Label id="QuantityPerUnitLabel" runat="server" Text='<%# Eva
l("QuantityPerUnit") %>' /></td>
</tr>
<tr>
<td align="right"><b>Unit Price:</b></td>
<td><asp:Label id="UnitPriceLabel" runat="server" Text='<%# Eval("Uni
tPrice") %>' /></td>
</tr>
</table>
</ItemTemplate>
<PagerTemplate>
<table>
<tr>
<td><asp:LinkButton ID="FirstButton" CommandName="Page" CommandArgume
nt="First" Text="<<" RunAt="server"/></td>
<td><asp:LinkButton ID="PrevButton" CommandName="Page" CommandArgume
nt="Prev" Text="<" RunAt="server"/></td>
<td><asp:LinkButton ID="NextButton" CommandName="Page" CommandArgume
nt="Next" Text=">" RunAt="server"/></td>
<td><asp:LinkButton ID="LastButton" CommandName="Page" CommandArgume
nt="Last" Text=">>" RunAt="server"/></td>
</tr>
</table>
</PagerTemplate>
</asp:FormView>

</td>
</tr>
</table>

<asp:SqlDataSource ID="ProductsSqlDataSource"
SelectCommand="SELECT * FROM [Products]"
connectionstring="<%$ ConnectionStrings:NorthwindConnection %>"
RunAt="server"/>

</form>
</body>
</html>

C#
<%@ Page language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>FormView Example</title>
</head>
<body>
<form id="form1" runat="server">
<h3>FormView Example</h3>
<table cellspacing="10">
<tr>
<td valign="top">

<asp:FormView ID="ProductsFormView"
DataSourceID="ProductsSqlDataSource"
AllowPaging="true"
runat="server">
<HeaderStyle forecolor="white" backcolor="Blue" />

<ItemTemplate>
<table>
<tr>
<td align="right"><b>Product ID:</b></td>
<td><asp:Label id="ProductIDLabel" runat="server" Text='<%# Eval("Pro
ductID") %>' /></td>
</tr>
<tr>
<td align="right"><b>Product Name:</b></td>
<td><asp:Label id="ProductNameLabel" runat="server" Text='<%# Eval("P
roductName") %>' /></td>
</tr>
<tr>
<td align="right"><b>Category ID:</b></td>
<td><asp:Label id="CategoryIDLabel" runat="server" Text='<%# Eval("Ca
tegoryID") %>' /></td>
</tr>
<tr>
<td align="right"><b>Quantity Per Unit:</b></td>
<td><asp:Label id="QuantityPerUnitLabel" runat="server" Text='<%# Eva
l("QuantityPerUnit") %>' /></td>
</tr>
<tr>
<td align="right"><b>Unit Price:</b></td>
<td><asp:Label id="UnitPriceLabel" runat="server" Text='<%# Eval("Uni
tPrice") %>' /></td>
</tr>
</table>
</ItemTemplate>

<PagerTemplate>
<table>
<tr>
<td><asp:LinkButton ID="FirstButton" CommandName="Page" CommandArgume
nt="First" Text="<<" RunAt="server"/></td>
<td><asp:LinkButton ID="PrevButton" CommandName="Page" CommandArgume
nt="Prev" Text="<" RunAt="server"/></td>
<td><asp:LinkButton ID="NextButton" CommandName="Page" CommandArgume
nt="Next" Text=">" RunAt="server"/></td>
<td><asp:LinkButton ID="LastButton" CommandName="Page" CommandArgume
nt="Last" Text=">>" RunAt="server"/></td>
</tr>
</table>
</PagerTemplate>

</asp:FormView>

</td>
</tr>
</table>

<asp:SqlDataSource ID="ProductsSqlDataSource"
SelectCommand="SELECT ProductID, ProductName, CategoryID, QuantityPerUnit, UnitPr
ice FROM [Products]"
connectionstring="<%$ ConnectionStrings:NorthwindConnection %>"
RunAt="server"/>

</form>
</body>
</html>

For more information on data source controls, see Data Source Web Server Controls.
Selecting Data
The way in which a data source control retrieves data is determined by the control itself. The ObjectDataSource control reads
data by calling the method specified in the SelectMethod property. The following code example shows an ObjectDataSource
control that returns data using the GetAllEmployees method of the EmployeeLogic class:
VB
<%@ Register TagPrefix="aspSample" Namespace="Samples.AspNet.VB" Assembly="Samples.AspNet.V
B" %>
<%@ Page language="vb" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>ObjectDataSource - Visual Basic Example</title>
</head>
<body>
<form id="Form1" method="post" runat="server">

<asp:gridview
id="GridView1"
runat="server"
datasourceid="ObjectDataSource1" />

<asp:objectdatasource
id="ObjectDataSource1"
runat="server"
selectmethod="GetAllEmployees"
typename="Samples.AspNet.VB.EmployeeLogic" />

</form>
</body>
</html>

C#
<%@ Register TagPrefix="aspSample" Namespace="Samples.AspNet.CS" Assembly="Samples.AspNet.C
S" %>
<%@ Page language="c#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>ObjectDataSource - C# Example</title>
</head>
<body>
<form id="Form1" method="post" runat="server">

<asp:gridview
id="GridView1"
runat="server"
datasourceid="ObjectDataSource1" />

<asp:objectdatasource
id="ObjectDataSource1"
runat="server"
selectmethod="GetAllEmployees"
typename="Samples.AspNet.CS.EmployeeLogic" />

</form>
</body>
</html>

J#
<%@ Register TagPrefix="aspSample" Namespace="Samples.AspNet.JSL" Assembly="Samples.AspNet.
JSL" %>
<%@ Page language="VJ#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>ObjectDataSource - VJ# Example</title>
</head>
<body>
<form id="Form1" method="post" runat="server">

<asp:gridview
id="GridView1"
runat="server"
datasourceid="ObjectDataSource1" />

<asp:objectdatasource
id="ObjectDataSource1"
runat="server"
selectmethod="GetAllEmployees"
typename="Samples.AspNet.JSL.EmployeeLogic" />
</form>
</body>
</html>

For more information, see ObjectDataSource Control Overview.


The SqlDataSource and AccessDataSource controls select data by running a SQL query specified in the SelectCommand
property. The following code example shows a SqlDataSource control that returns data from the Employees table of the
Northwind sample database:
VB
<%@ Page language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">
<asp:SqlDataSource
id="SqlDataSource1"
runat="server"
DataSourceMode="DataReader"
ConnectionString="<%$ ConnectionStrings:MyNorthwind%>"
SelectCommand="SELECT LastName FROM Employees">
</asp:SqlDataSource>
<asp:ListBox
id="ListBox1"
runat="server"
DataTextField="LastName"
DataSourceID="SqlDataSource1">
</asp:ListBox>

</form>
</body>
</html>

C#
<%@ Page language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1


/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">
<asp:SqlDataSource
id="SqlDataSource1"
runat="server"
DataSourceMode="DataReader"
ConnectionString="<%$ ConnectionStrings:MyNorthwind%>"
SelectCommand="SELECT LastName FROM Employees">
</asp:SqlDataSource>

<asp:ListBox
id="ListBox1"
runat="server"
DataTextField="LastName"
DataSourceID="SqlDataSource1">
</asp:ListBox>

</form>
</body>
</html>

J#
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">
<asp:SqlDataSource
id="SqlDataSource1"
runat="server"
DataSourceMode="DataReader"
ConnectionString="Data Source=localhost;Integrated Security=SSPI;Initial Catalog=
Northwind;"
SelectCommand="SELECT LastName FROM Employees">
</asp:SqlDataSource>

<asp:ListBox
id="ListBox1"
runat="server"
DataTextField="LastName"
DataSourceID="SqlDataSource1">
</asp:ListBox>

</form>
</body>
</html>

For more information, see Selecting Data Using the SqlDataSource Control.
The XmlDataSource does not allow you to select specific elements from the source XML data. However, you can specify a filter
using the XPath property. For more information, see Filtering Data Using the XmlDataSource Control.
Modifying Data
The ObjectDataSource and SqlDataSource controls support modifying bound data. For more information, see
Modifying Data using Data Source Controls.
See Also
Other Resources
Data Source Web Server Controls
ASP.NET

Sorting Data with Data Source Controls


The GridView control can order the data that it is bound to by taking advantage of the sorting capabilities provided by data
source controls.
Enabling Sorting in a Data Source Control
The data source controls that support sorting are the ObjectDataSource, SqlDataSource, and AccessDataSource controls. The
SqlDataSource and AccessDataSource controls support sorting only when their DataSourceMode property is set to
DataSet (the default) as in the following example:
VB
<asp:GridView ID="EmployeesGridView"
DataSourceID="EmployeesSqlDataSource"
DataKeyNames="EmployeeID"
AllowSorting="True"
RunAt="Server" />
<asp:SqlDataSource ID="EmployeesSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName, FirstName FROM Employees"
Connectionstring="<%$ ConnectionStrings:NorthwindConnectionString %>"
RunAt="server" />

C#
<asp:GridView ID="EmployeesGridView"
DataSourceID="EmployeesSqlDataSource"
DataKeyNames="EmployeeID"
AllowSorting="True"
RunAt="Server" />

<asp:SqlDataSource ID="EmployeesSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName, FirstName FROM Employees"
Connectionstring="<%$ ConnectionStrings:NorthwindConnectionString %>"
RunAt="server" />

The ObjectDataSource control supports sorting if the object returned by the SelectMethod is a DataSet, DataTable, or
DataView object. The ObjectDataSource also supports retrieving results in sorted order from the data source.
Custom Sorting
When using the ObjectDataSource or SqlDataSource controls, you can take advantage of sorting capabilities using the
SortParameterName property. You can set the SortParameterName property to the name of the parameter that contains a
sort expression being passed to the data source control. The sort expression is a comma-delimited list of fields to sort by (and
optionally the DESC identifier to sort in descending order). For details about the format of the sort expression, see the
System.Data.DataView.Sort property.
The parameter identified by the SortParameterName property is passed to the ObjectDataSource control's SelectMethod
or passed as part of the parameter collection to the SqlDataSource control's SelectCommand. The ObjectDataSource
control can use the information passed to it in the sort parameter to return the data in sorted order. For the SqlDataSource
control, you must supply the name of a stored procedure that can take the sort parameter and return the sorted data, because
you cannot pass a parameter as part of an ORDER BY clause.
The following code example shows an ObjectDataSource control declaration that identifies a parameter named sortColumns
as the sort parameter name:
VB
<asp:ObjectDataSource
ID="EmployeesObjectDataSource"
runat="server"
TypeName="Samples.AspNet.Controls.NorthwindEmployee"
SortParameterName="SortColumns"
EnablePaging="true"
StartRowIndexParameterName="StartRecord"
MaximumRowsParameterName="MaxRecords"
SelectMethod="GetAllEmployees" >
</asp:ObjectDataSource>

C#
<asp:ObjectDataSource
ID="EmployeesObjectDataSource"
runat="server"
TypeName="Samples.AspNet.Controls.NorthwindEmployee"
SortParameterName="SortColumns"
EnablePaging="true"
StartRowIndexParameterName="StartRecord"
MaximumRowsParameterName="MaxRecords"
SelectMethod="GetAllEmployees" >
</asp:ObjectDataSource>

The following code example shows a method in the source object for the ObjectDataSource control. The method is identified
as the SelectMethod. The parameter identified by the SortParameterName property is used to sort the data retrieved from
the database.
VB
Public Shared Sub Initialize()
' Initialize data source. Use "Northwind" connection string from configuration.

If ConfigurationManager.ConnectionStrings("Northwind") Is Nothing OrElse _


ConfigurationManager.ConnectionStrings("Northwind").ConnectionString.Trim() = "" Then

Throw New Exception("A connection string named 'Northwind' with a valid connection stri
ng " & _
"must exist in the <connectionStrings> configuration section for th
e application.")
End If

_connectionString = _
ConfigurationManager.ConnectionStrings("Northwind").ConnectionString

_initialized = True
End Sub

' Select all employees.

<DataObjectMethod(DataObjectMethodType.Select, True)> _
Public Shared Function GetAllEmployees(sortColumns As String, startRecord As Integer, maxRe
cords As Integer) As DataTable
VerifySortColumns(sortColumns)

If Not _initialized Then Initialize()

Dim sqlCommand As String = "SELECT EmployeeID, LastName, FirstName, Address, City, Region
, PostalCode FROM Employees "
If sortColumns.Trim() = "" Then
sqlCommand &= "ORDER BY EmployeeID"
Else
sqlCommand &= "ORDER BY " & sortColumns
End If

Dim conn As SqlConnection = New SqlConnection(_connectionString)


Dim da As SqlDataAdapter = New SqlDataAdapter(sqlCommand, conn)
Dim ds As DataSet = New DataSet()

Try
conn.Open()
da.Fill(ds, startRecord, maxRecords, "Employees")
Catch e As SqlException
' Handle exception.
Finally
conn.Close()
End Try

If ds.Tables("Employees") IsNot Nothing Then _


Return ds.Tables("Employees")

Return Nothing
End Function

'''''
' Verify that only valid columns are specified in the sort expression to aSub a SQL Injecti
on attack.

Private Shared Sub VerifySortColumns(sortColumns As String)


If sortColumns.ToLowerInvariant().EndsWith(" desc") Then _
sortColumns = sortColumns.Substring(0, sortColumns.Length - 5)

Dim columnNames() As String = sortColumns.Split(",")

For Each columnName As String In columnNames


Select Case columnName.Trim().ToLowerInvariant()
Case "employeeid"
Case "lastname"
Case "firstname"
Case ""
Case Else
Throw New ArgumentException("SortColumns contains an invalid column name.")
End Select
Next
End Sub

C#
public static void Initialize()
{
// Initialize data source. Use "Northwind" connection string from configuration.
if (ConfigurationManager.ConnectionStrings["Northwind"] == null ||
ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString.Trim() == "")
{
throw new Exception("A connection string named 'Northwind' with a valid connection stri
ng " +
"must exist in the <connectionStrings> configuration section for th
e application.");
}

_connectionString =
ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString;

_initialized = true;
}

// Select all employees.


[DataObjectMethod(DataObjectMethodType.Select, true)]
public static DataTable GetAllEmployees(string sortColumns, int startRecord, int maxRecords
)
{
VerifySortColumns(sortColumns);

if (!_initialized) { Initialize(); }

string sqlCommand = "SELECT EmployeeID, LastName, FirstName, Address, City, Region, Posta
lCode FROM Employees ";
if (sortColumns.Trim() == "")
sqlCommand += "ORDER BY EmployeeID";
else
sqlCommand += "ORDER BY " + sortColumns;

SqlConnection conn = new SqlConnection(_connectionString);


SqlDataAdapter da = new SqlDataAdapter(sqlCommand, conn);

DataSet ds = new DataSet();

try
{
conn.Open();
da.Fill(ds, startRecord, maxRecords, "Employees");
}
catch (SqlException e)
{
// Handle exception.
}
finally
{
conn.Close();
}

if (ds.Tables["Employees"] != null)
return ds.Tables["Employees"];

return null;
}

//////////
// Verify that only valid columns are specified in the sort expression to avoid a SQL Injec
tion attack.

private static void VerifySortColumns(string sortColumns)


{
if (sortColumns.ToLowerInvariant().EndsWith(" desc"))
sortColumns = sortColumns.Substring(0, sortColumns.Length - 5);

string[] columnNames = sortColumns.Split(',');

foreach (string columnName in columnNames)


{
switch (columnName.Trim().ToLowerInvariant())
{
case "employeeid":
break;
case "lastname":
break;
case "firstname":
break;
case "":
break;
default:
throw new ArgumentException("SortColumns contains an invalid column name.");
break;
}
}
}

For more information, see Creating an ObjectDataSource Control Source Object.


See Also
Other Resources
Data Source Web Server Controls
ASP.NET

Using Parameters with Data Source Controls


ASP.NET data source controls can accept input parameters so that you can pass values to them at run time. You can use
parameters to supply search criteria for data retrieval; to supply values to be inserted, updated, or deleted in a data store; and
to supply values for sorting, paging, and filtering. Using parameters enables you to filter data and create master-detail
applications with little or no custom code.
You can also use parameter to customize the values passed to a data source by a data-bound control, such as a GridView or
FormView control, that supports automatic update, insert, and delete operations. For example, you can use parameter objects
to strongly type values or to retrieve output values from the data source. Additionally, parameterized queries can make an
application more secure by protecting against SQL injection attacks.
Parameter values can be obtained from a variety of sources. Parameter objects allow you to supply values to parameterized
data operations from Web server control properties, cookies, session state, QueryString fields, user profile properties, and
other sources.
Parameter Types
You can specify several types of parameter objects in your Web application. The type of the parameter object determines
where the parameter value comes from. The Parameter class is the base class for all parameter objects and includes Name,
Type, Direction, and DefaultValue properties that are common to all parameter types. You typically use the Parameter base
class to specify how a data source should handle parameter values obtained from an associated data-bound control, such as
the values passed by a GridView control for an Update or Delete operation.
You can use parameter types that derive from the Parameter class to obtain values from other sources, as described in the
following table.
Parameter Type Description
ControlParameter Sets a parameter to the property value of a Control on an ASP.NET Web page. You specify the Control
using the ControlID property. You specify the name of the property that supplies the parameter value u
sing the ControlParameter object's PropertyName property.
Some controls that derive from Control define a ControlValuePropertyAttribute, which determines the
default property from which to retrieve the control's value. The default property is used whenever the
PropertyName property is not explicitly set. The ControlValuePropertyAttribute is applied to the fo
llowing control properties:
System.Web.UI.WebControls.Calendar.SelectedDate
System.Web.UI.WebControls.CheckBox.Checked
System.Web.UI.WebControls.DetailsView.SelectedValue
System.Web.UI.WebControls.FileUpload.FileBytes
System.Web.UI.WebControls.GridView.SelectedValue
System.Web.UI.WebControls.Label.Text
System.Web.UI.WebControls.TextBox.Text
System.Web.UI.WebControls.TreeView.SelectedValue

CookieParameter Sets a parameter to the value of an HttpCookie object. You specify the name of the HttpCookie object
using the CookieName property. If the specified HttpCookie object does not exist, then the value of th
e DefaultValue property is used as the parameter value.
Note
Only single-valued cookies are supported.

FormParameter Sets a parameter to the value of an HTML form field. You specify the name of the HTML form field usin
g the FormField property. If the specified HTML form field value does not exist, then the value of the De
faultValue property is used as the parameter value.
ProfileParameter Sets a parameter to the value of a property from the current user profile (Profile). You specify the name
of the profile property using the PropertyName property. If the specified profile property does not exist
, then the value of the DefaultValue property is used as the parameter value.
For information about user profiles, see ASP.NET Profile Properties.

QueryStringParameter Sets a parameter to the value of a QueryString field. You specify the name of the QueryString field us
ing the QueryStringField property. If the specified QueryString field does not exist, then the value of th
e DefaultValue property is used as the parameter value.

SessionParameter Sets a parameter to the value of a Session object. You specify the name of the Session object using the
SessionField property. If the specified Session object does not exist, then the value of the DefaultValu
e property is used as the parameter value.
Strongly Typing Parameter Values
By default, parameters are typed as Object. If a parameter value is of another type, such as DateTime or Int32, you can create
Parameter objects explicitly and set the parameter's Type property to a TypeCode value.
Parameter Direction
Parameters are input parameters by default. In some cases, such as when you use stored procedures, you might need to read a
value returned from the data source. If so, you can set the Parameter object's Direction property to ensure that you capture
information that the data source returns to your Web application. The supported parameter direction settings are Input,
InputOutput, Output, and ReturnValue. You will typically handle a data source control event, such as an Inserted or Updated
event, to obtain the parameter's return value after the data operation is completed.
Data Source Controls and Parameters
Data source controls support parameterized operations in different ways. For example, the SqlDataSource and
AccessDataSource controls allow you to specify parameter placeholders in an SQL statement, such as the SelectCommand. The
ObjectDataSource control uses parameters to determine the appropriate method signature to call for a particular data
operation, such as the SelectMethod. For more information, see Using Parameters with the SqlDataSource Control and
Using Parameters with the ObjectDataSource Control.
Data source controls typically include a parameter collection for each data operation. When selecting data, you can specify a
SelectParameters collection, when updating a data item you can specify an UpdateParameters collection, and so on. The
contents of the parameters collection for a particular action are then used to supply values to the underlying data source.
When inserting, updating, or deleting data, the data source control creates parameters for bound fields, combines them with
the explicitly specified parameters collection (if any), and then passes the resulting collection to the data source. For
information on the parameter names and values that a data source control creates based on data from a bound control, see
How a Data Source Control Creates Parameters for Data-bound Fields.
The following example shows a SqlDataSource control that retrieves information based on a value from a QueryString field.

<asp:SqlDataSource id="Employees1" runat="server"


ConnectionString="<%$ ConnectionStrings:Northwind %>"
SelectCommand="SELECT EmployeeID, LastName, FirstName FROM Employees
WHERE EmployeeID = @empId">
<SelectParameters>
<asp:QueryStringParameter Name="empId" QueryStringField="empId" />
</SelectParameters>
</asp:SqlDataSource>

The following example shows a SqlDataSource control that retrieves information based on a value from another control on
the page.

<asp:DropDownList id="DropDownList1" runat="server"


autopostback="True">
<asp:listitem selected>Sales Representative</asp:listitem>
<asp:listitem>Sales Manager</asp:listitem>
<asp:listitem>Vice President, Sales</asp:listitem>
</asp:DropDownList></p>
<asp:SqlDataSource id="Employees" runat="server"
ConnectionString="<%$ ConnectionStrings:Northwind%>"
SelectCommand="SELECT LastName FROM Employees WHERE Title = @Title">
<SelectParameters>
<asp:ControlParameter Name="Title"
ControlID="DropDownList1"
PropertyName="SelectedValue"/>
</SelectParameters>
</asp:sqldatasource>

The following code example shows a SqlDataSource control that uses parameterized commands to query and modify data
from a data-bound control. Parameters are explicitly specified in order to strongly type parameter values and to specify output
parameters.
VB
<%@ Page language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
Sub EmployeesDropDownList_OnSelectedIndexChanged(sender As Object, e As EventArgs)
EmployeeDetailsView.DataBind()
End Sub

Sub EmployeeDetailsView_ItemUpdated(sender As Object, e As DetailsViewUpdatedEventArgs)


EmployeesDropDownList.DataBind()
EmployeesDropDownList.SelectedValue = e.Keys("EmployeeID").ToString()
EmployeeDetailsView.DataBind()
End Sub

Sub EmployeeDetailsView_ItemDeleted(sender As Object, e As DetailsViewDeletedEventArgs)


EmployeesDropDownList.DataBind()
End Sub

Sub EmployeeDetailsSqlDataSource_OnInserted(sender As Object, e As SqlDataSourceStatusEve


ntArgs)
Dim command As System.Data.Common.DbCommand = e.Command
EmployeesDropDownList.DataBind()
EmployeesDropDownList.SelectedValue = _
command.Parameters("@EmpID").Value.ToString()
EmployeeDetailsView.DataBind()
End Sub

</script>

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>Northwind Employees</title>
</head>
<body>
<form id="form1" runat="server">

<h3>Northwind Employees</h3>

<table cellspacing="10">

<tr>
<td valign="top">
<asp:DropDownList ID="EmployeesDropDownList"
DataSourceID="EmployeesSqlDataSource"
DataValueField="EmployeeID"
DataTextField="FullName"
AutoPostBack="True"
OnSelectedIndexChanged="EmployeesDropDownList_OnSelectedIndexChanged"
RunAt="Server" />
</td>
<td valign="top">
<asp:DetailsView ID="EmployeeDetailsView"
DataSourceID="EmployeeDetailsSqlDataSource"
AutoGenerateRows="false"
AutoGenerateInsertbutton="true"
AutoGenerateEditbutton="true"
AutoGenerateDeletebutton="true"
DataKeyNames="EmployeeID"
Gridlines="Both"
OnItemUpdated="EmployeeDetailsView_ItemUpdated"
OnItemDeleted="EmployeeDetailsView_ItemDeleted"
RunAt="server">

<HeaderStyle backcolor="Navy"
forecolor="White"/>

<RowStyle backcolor="White"/>

<AlternatingRowStyle backcolor="LightGray"/>

<EditRowStyle backcolor="LightCyan"/>

<Fields>
<asp:BoundField DataField="EmployeeID" HeaderText="Employee ID" InsertVis
ible="False" ReadOnly="true"/>
<asp:BoundField DataField="FirstName" HeaderText="First Name"/>
<asp:BoundField DataField="LastName" HeaderText="Last Name"/>

<asp:BoundField DataField="Address" HeaderText="Address"/>

<asp:BoundField DataField="City" HeaderText="City"/>

<asp:BoundField DataField="Region" HeaderText="Region"/>


<asp:BoundField DataField="PostalCode" HeaderText="Postal Code"/>

</Fields>
</asp:DetailsView>
</td>
</tr>
</table>

<asp:SqlDataSource ID="EmployeesSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName + ', ' + FirstName AS FullName FROM Em
ployees"
Connectionstring="<%$ ConnectionStrings:NorthwindConnection %>"
RunAt="server">
</asp:SqlDataSource>

<asp:SqlDataSource ID="EmployeeDetailsSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName, FirstName, Address, City, Region, Pos
talCode
FROM Employees WHERE EmployeeID = @EmpID"

InsertCommand="INSERT INTO Employees(LastName, FirstName, Address, City, Region,


PostalCode)
VALUES (@LastName, @FirstName, @Address, @City, @Region, @PostalCo
de);
SELECT @EmpID = SCOPE_IDENTITY()"
UpdateCommand="UPDATE Employees SET LastName=@LastName, FirstName=@FirstName, Add
ress=@Address,
City=@City, Region=@Region, PostalCode=@PostalCode
WHERE EmployeeID=@EmployeeID"

DeleteCommand="DELETE Employees WHERE EmployeeID=@EmployeeID"


ConnectionString="<%$ ConnectionStrings:NorthwindConnection %>"
OnInserted="EmployeeDetailsSqlDataSource_OnInserted"
RunAt="server">

<SelectParameters>
<asp:ControlParameter ControlID="EmployeesDropDownList" PropertyName="SelectedV
alue"
Name="EmpID" Type="Int32" DefaultValue="0" />
</SelectParameters>

<InsertParameters>
<asp:Parameter Name="LastName" Type="String" />
<asp:Parameter Name="FirstName" Type="String" />
<asp:Parameter Name="Address" Type="String" />
<asp:Parameter Name="City" Type="String" />
<asp:Parameter Name="Region" Type="String" />
<asp:Parameter Name="PostalCode" Type="String" />
<asp:Parameter Name="EmpID" Direction="Output" Type="Int32" DefaultValue="0" />
</InsertParameters>

<UpdateParameters>
<asp:Parameter Name="LastName" Type="String" />
<asp:Parameter Name="FirstName" Type="String" />
<asp:Parameter Name="Address" Type="String" />
<asp:Parameter Name="City" Type="String" />
<asp:Parameter Name="Region" Type="String" />
<asp:Parameter Name="PostalCode" Type="String" />
<asp:Parameter Name="EmployeeID" Type="Int32" DefaultValue="0" />
</UpdateParameters>

<DeleteParameters>
<asp:Parameter Name="EmployeeID" Type="Int32" DefaultValue="0" />
</DeleteParameters>
</asp:SqlDataSource>
</form>
</body>
</html>

C#
<%@ Page language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">

void EmployeesDropDownList_OnSelectedIndexChanged(Object sender, EventArgs e)


{
EmployeeDetailsView.DataBind();
}

void EmployeeDetailsView_ItemUpdated(Object sender, DetailsViewUpdatedEventArgs e)


{
EmployeesDropDownList.DataBind();
EmployeesDropDownList.SelectedValue = e.Keys["EmployeeID"].ToString();
EmployeeDetailsView.DataBind();
}

void EmployeeDetailsView_ItemDeleted(Object sender, DetailsViewDeletedEventArgs e)


{
EmployeesDropDownList.DataBind();
}

void EmployeeDetailsSqlDataSource_OnInserted(Object sender, SqlDataSourceStatusEventArgs


e)
{
System.Data.Common.DbCommand command = e.Command;
EmployeesDropDownList.DataBind();
EmployeesDropDownList.SelectedValue =
command.Parameters["@EmpID"].Value.ToString();
EmployeeDetailsView.DataBind();
}
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>Northwind Employees</title>
</head>
<body>
<form id="form1" runat="server">

<h3>Northwind Employees</h3>

<table cellspacing="10">

<tr>
<td valign="top">
<asp:DropDownList ID="EmployeesDropDownList"
DataSourceID="EmployeesSqlDataSource"
DataValueField="EmployeeID"
DataTextField="FullName"
AutoPostBack="True"
OnSelectedIndexChanged="EmployeesDropDownList_OnSelectedIndexChanged"
RunAt="Server" />
</td>
<td valign="top">
<asp:DetailsView ID="EmployeeDetailsView"
DataSourceID="EmployeeDetailsSqlDataSource"
AutoGenerateRows="false"
AutoGenerateInsertbutton="true"
AutoGenerateEditbutton="true"
AutoGenerateDeletebutton="true"
DataKeyNames="EmployeeID"
Gridlines="Both"
OnItemUpdated="EmployeeDetailsView_ItemUpdated"
OnItemDeleted="EmployeeDetailsView_ItemDeleted"
RunAt="server">

<HeaderStyle backcolor="Navy"
forecolor="White"/>

<RowStyle backcolor="White"/>

<AlternatingRowStyle backcolor="LightGray"/>

<EditRowStyle backcolor="LightCyan"/>

<Fields>
<asp:BoundField DataField="EmployeeID" HeaderText="Employee ID" InsertVis
ible="False" ReadOnly="true"/>
<asp:BoundField DataField="FirstName" HeaderText="First Name"/>
<asp:BoundField DataField="LastName" HeaderText="Last Name"/>

<asp:BoundField DataField="Address" HeaderText="Address"/>

<asp:BoundField DataField="City" HeaderText="City"/>


<asp:BoundField DataField="Region" HeaderText="Region"/>
<asp:BoundField DataField="PostalCode" HeaderText="Postal Code"/>

</Fields>
</asp:DetailsView>
</td>
</tr>
</table>

<asp:SqlDataSource ID="EmployeesSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName + ', ' + FirstName AS FullName FROM Em
ployees"
Connectionstring="<%$ ConnectionStrings:NorthwindConnection %>"
RunAt="server">
</asp:SqlDataSource>

<asp:SqlDataSource ID="EmployeeDetailsSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName, FirstName, Address, City, Region, Pos
talCode
FROM Employees WHERE EmployeeID = @EmpID"

InsertCommand="INSERT INTO Employees(LastName, FirstName, Address, City, Region,


PostalCode)
VALUES (@LastName, @FirstName, @Address, @City, @Region, @PostalCo
de);
SELECT @EmpID = SCOPE_IDENTITY()"

UpdateCommand="UPDATE Employees SET LastName=@LastName, FirstName=@FirstName, Add


ress=@Address,
City=@City, Region=@Region, PostalCode=@PostalCode
WHERE EmployeeID=@EmployeeID"

DeleteCommand="DELETE Employees WHERE EmployeeID=@EmployeeID"

ConnectionString="<%$ ConnectionStrings:NorthwindConnection %>"


OnInserted="EmployeeDetailsSqlDataSource_OnInserted"
RunAt="server">

<SelectParameters>
<asp:ControlParameter ControlID="EmployeesDropDownList" PropertyName="SelectedV
alue"
Name="EmpID" Type="Int32" DefaultValue="0" />
</SelectParameters>

<InsertParameters>
<asp:Parameter Name="LastName" Type="String" />
<asp:Parameter Name="FirstName" Type="String" />
<asp:Parameter Name="Address" Type="String" />
<asp:Parameter Name="City" Type="String" />
<asp:Parameter Name="Region" Type="String" />
<asp:Parameter Name="PostalCode" Type="String" />
<asp:Parameter Name="EmpID" Direction="Output" Type="Int32" DefaultValue="0" />
</InsertParameters>

<UpdateParameters>
<asp:Parameter Name="LastName" Type="String" />
<asp:Parameter Name="FirstName" Type="String" />
<asp:Parameter Name="Address" Type="String" />
<asp:Parameter Name="City" Type="String" />
<asp:Parameter Name="Region" Type="String" />
<asp:Parameter Name="PostalCode" Type="String" />
<asp:Parameter Name="EmployeeID" Type="Int32" DefaultValue="0" />
</UpdateParameters>

<DeleteParameters>
<asp:Parameter Name="EmployeeID" Type="Int32" DefaultValue="0" />
</DeleteParameters>

</asp:SqlDataSource>
</form>
</body>
</html>
See Also
Reference
Parameter
Concepts
Using Parameters with the SqlDataSource Control
Using Parameters with the ObjectDataSource Control
How a Data Source Control Creates Parameters for Data-bound Fields
Data Source Controls Overview
ASP.NET

How a Data Source Control Creates Parameters for Data-bound


Fields
When you use a data-bound control such as a GridView, DetailsView, or FormView control with an ASP.NET data source
control, the data-bound control can pass parameter names and values to the data source control based on the bound fields in
the data-bound control. The data source control then includes the field names and values in the parameter collection for select
or update operations. For more information, see Using Parameters with the SqlDataSource Control and
Using Parameters with the ObjectDataSource Control.
Dictionaries Passed to Data Source Controls
When a data-bound control requests an operation from the data source control, it passes one or more IDictionary collections
containing parameter names and values for the requested data operation. The values of the name/value pairs in the dictionary
are derived from child controls. For example, in an update operation, the data-bound control reads parameter values from
TextBox or CheckBox controls that are displayed in edit mode. The names for the name/value pairs are taken from the names
of the fields bound to child controls and from the field names specified in the DataKeyNames property. For an update or
delete operation, the data-bound control might also pass a dictionary containing the original values of the data record.
Name/value pairs are passed using the following IDictionary collections:
Values collection Passed for an insert operation. Contains the name/value pairs for a new record. Field names and
values for the Values collection are taken from child controls in an InsertItemTemplate or from bound fields in a
DetailsView control whose InsertVisible property is set to true.
Keys collection Passed for update and delete operations. Contains the primary key or keys for the record being updated
or deleted. If the key fields can be modified at the data source, the Keys collection also contains the original values of the
key fields. When a data-bound control is populated with data from the data source control, it maintains that data in view
state. When an update or delete operation is requested, the Keys collection is populated with values stored earlier in view
state. If the data-bound control's EnableViewState property is set to false, the Keys collection is not populated for the
update or delete operation.
NewValues collection Passed for an update operation. Contains the name/value pairs with new values for the updated
item, including new values for updatable key fields. Field names and values for the NewValues collection are taken from
child controls in an EditItemTemplate or from bound fields in a DetailsView control whose ReadOnly property is set
to false.
OldValues collection Passed for update or delete operations. Contains the original values for the data record to use for
optimistic concurrency checking. (For information on optimistic concurrency checking, see the ConflictDetection
property of the data source control you are working with.) Values for key fields identified by the DataKeyNames
property are not included in the OldValues collection. Key field names and values are included only in the Keys
collection. When a data-bound control is populated with data from the data source control, it maintains that data in view
state. When an update or delete operation is requested, the OldValues collection is populated with values stored earlier
in view state. If the data-bound control's EnableViewState property is set to false, the OldValues collection is not
populated for the update or delete operation.
You can access all of these collections using the arguments passed with the data-bound control event for the requested
operation. For example, in the GridView control's RowUpdating event, the GridViewUpdateEventArgs class provides access to
the NewValues collection.
Parameter Names
The data source control creates parameters automatically for the values passed in the IDictionary collections. For an insert
operation, the data source control populates its InsertParameters collection with values from the name/value pairs in the
Values collection. For an update operation, the data source control populates its UpdateParameters collection with values
from the name/value pairs in the Keys, NewValues, and OldValues collections. For a delete operation, the data source control
populates its DeleteParameters collection with values from the name/value pairs in the Keys and OldValues collections.
The OldValues collection is not populated by default. It is populated only when the data-source control's ConflictDetection
property is set to CompareAllValues.
For an update or delete operation, only parameters for current bound values are created, by default. If you need to access both
current and original bound values, such as a scenario where you must support optimistic concurrency checks, you can have the
data source control create parameters for both current and original values. To do this, you must establish a naming convention
for parameters that will contain original values. The format of the parameters for original values is determined by the
OldValuesParameterFormatString property. Set the OldValuesParameterFormatString property to a string that includes
"{0}" as a placeholder for the name of the field. For example, if you are using the SqlDataSource control, and you set the
OldValuesParameterFormatString property to "old_{0}", the names of the original-value parameters will resolve to the field
name prefixed with "@old_" (the SqlDataSource control appends an "@" character to the beginning of all parameter names.)
Consider an update operation that involves a field named LastModifiedDate. The current value for the field is passed in the
Values dictionary and the original value for the field is passed in the OldValues dictionary. A parameter named
@LastModifiedDate is created to pass the current value and a parameter named @old_LastModifiedDate is created to pass the
original value. You can then include both parameters in an SQL statement to differentiate between the current and original
values for the field, as shown in the following example:

UPDATE Table1 SET LastModifiedDate = @LastModifiedDate


WHERE Key = @Key AND LastModifiedDate = @old_LastModifiedDate

You do not need to access the name/value IDictionary collections directly. You can simply include the automatically generated
parameter names in your SQL statements (if your data source supports named parameters), or as the names of the parameters
for the data methods in a business object you are accessing with an ObjectDataSource control.
Optionally, you can define Parameter objects in the data source control's UpdateParameters, InsertParameters, or
DeleteParameters collections in order to customize the values passed by the data-bound control. You might create
Parameter objects to strongly type the value or to specify a default value if null is passed.
The following code example shows a DetailsView control bound to a SqlDataSource control. The SqlDataSource control's
InsertCommand, UpdateCommand, and DeleteCommand properties use the parameter names that are automatically
generated by the SqlDataSource control. The parameter values are populated based on the Keys and NewValues
dictionaries. The OldValues dictionary is not used because the ConflictDetection property is set to OverWriteChanges, the
default.
VB
<%@ Page language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">

Sub EmployeesDropDownList_OnSelectedIndexChanged(sender As Object, e As EventArgs)


EmployeeDetailsView.DataBind()
End Sub

Sub EmployeeDetailsView_ItemUpdated(sender As Object, e As DetailsViewUpdatedEventArgs)


EmployeesDropDownList.DataBind()
EmployeesDropDownList.SelectedValue = e.Keys("EmployeeID").ToString()
EmployeeDetailsView.DataBind()
End Sub

Sub EmployeeDetailsView_ItemDeleted(sender As Object, e As DetailsViewDeletedEventArgs)


EmployeesDropDownList.DataBind()
End Sub
Sub EmployeeDetailsSqlDataSource_OnInserted(sender As Object, e As SqlDataSourceStatusEve
ntArgs)
Dim command As System.Data.Common.DbCommand = e.Command
EmployeesDropDownList.DataBind()
EmployeesDropDownList.SelectedValue = _
command.Parameters("@EmpID").Value.ToString()
EmployeeDetailsView.DataBind()
End Sub

</script>

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>Northwind Employees</title>
</head>
<body>
<form id="form1" runat="server">

<h3>Northwind Employees</h3>

<table cellspacing="10">

<tr>
<td valign="top">
<asp:DropDownList ID="EmployeesDropDownList"
DataSourceID="EmployeesSqlDataSource"
DataValueField="EmployeeID"
DataTextField="FullName"
AutoPostBack="True"
OnSelectedIndexChanged="EmployeesDropDownList_OnSelectedIndexChanged"
RunAt="Server" />
</td>
<td valign="top">
<asp:DetailsView ID="EmployeeDetailsView"
DataSourceID="EmployeeDetailsSqlDataSource"
AutoGenerateRows="false"
AutoGenerateInsertbutton="true"
AutoGenerateEditbutton="true"
AutoGenerateDeletebutton="true"
DataKeyNames="EmployeeID"
Gridlines="Both"
OnItemUpdated="EmployeeDetailsView_ItemUpdated"
OnItemDeleted="EmployeeDetailsView_ItemDeleted"
RunAt="server">

<HeaderStyle backcolor="Navy"
forecolor="White"/>
<RowStyle backcolor="White"/>

<AlternatingRowStyle backcolor="LightGray"/>

<EditRowStyle backcolor="LightCyan"/>

<Fields>
<asp:BoundField DataField="EmployeeID" HeaderText="Employee ID" InsertVis
ible="False" ReadOnly="true"/>
<asp:BoundField DataField="FirstName" HeaderText="First Name"/>
<asp:BoundField DataField="LastName" HeaderText="Last Name"/>

<asp:BoundField DataField="Address" HeaderText="Address"/>

<asp:BoundField DataField="City" HeaderText="City"/>

<asp:BoundField DataField="Region" HeaderText="Region"/>


<asp:BoundField DataField="PostalCode" HeaderText="Postal Code"/>

</Fields>
</asp:DetailsView>
</td>
</tr>
</table>

<asp:SqlDataSource ID="EmployeesSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName + ', ' + FirstName AS FullName FROM Em
ployees"
Connectionstring="<%$ ConnectionStrings:NorthwindConnection %>"
RunAt="server">
</asp:SqlDataSource>

<asp:SqlDataSource ID="EmployeeDetailsSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName, FirstName, Address, City, Region, Pos
talCode
FROM Employees WHERE EmployeeID = @EmpID"

InsertCommand="INSERT INTO Employees(LastName, FirstName, Address, City, Region,


PostalCode)
VALUES (@LastName, @FirstName, @Address, @City, @Region, @PostalCo
de);
SELECT @EmpID = SCOPE_IDENTITY()"

UpdateCommand="UPDATE Employees SET LastName=@LastName, FirstName=@FirstName, Add


ress=@Address,
City=@City, Region=@Region, PostalCode=@PostalCode
WHERE EmployeeID=@EmployeeID"

DeleteCommand="DELETE Employees WHERE EmployeeID=@EmployeeID"

ConnectionString="<%$ ConnectionStrings:NorthwindConnection %>"


OnInserted="EmployeeDetailsSqlDataSource_OnInserted"
RunAt="server">

<SelectParameters>
<asp:ControlParameter ControlID="EmployeesDropDownList" PropertyName="SelectedV
alue"
Name="EmpID" Type="Int32" DefaultValue="0" />
</SelectParameters>
<InsertParameters>
<asp:Parameter Name="LastName" Type="String" />
<asp:Parameter Name="FirstName" Type="String" />
<asp:Parameter Name="Address" Type="String" />
<asp:Parameter Name="City" Type="String" />
<asp:Parameter Name="Region" Type="String" />
<asp:Parameter Name="PostalCode" Type="String" />
<asp:Parameter Name="EmpID" Direction="Output" Type="Int32" DefaultValue="0" />
</InsertParameters>

<UpdateParameters>
<asp:Parameter Name="LastName" Type="String" />
<asp:Parameter Name="FirstName" Type="String" />
<asp:Parameter Name="Address" Type="String" />
<asp:Parameter Name="City" Type="String" />
<asp:Parameter Name="Region" Type="String" />
<asp:Parameter Name="PostalCode" Type="String" />
<asp:Parameter Name="EmployeeID" Type="Int32" DefaultValue="0" />
</UpdateParameters>

<DeleteParameters>
<asp:Parameter Name="EmployeeID" Type="Int32" DefaultValue="0" />
</DeleteParameters>

</asp:SqlDataSource>
</form>
</body>
</html>

C#
<%@ Page language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">

void EmployeesDropDownList_OnSelectedIndexChanged(Object sender, EventArgs e)


{
EmployeeDetailsView.DataBind();
}

void EmployeeDetailsView_ItemUpdated(Object sender, DetailsViewUpdatedEventArgs e)


{
EmployeesDropDownList.DataBind();
EmployeesDropDownList.SelectedValue = e.Keys["EmployeeID"].ToString();
EmployeeDetailsView.DataBind();
}

void EmployeeDetailsView_ItemDeleted(Object sender, DetailsViewDeletedEventArgs e)


{
EmployeesDropDownList.DataBind();
}

void EmployeeDetailsSqlDataSource_OnInserted(Object sender, SqlDataSourceStatusEventArgs


e)
{
System.Data.Common.DbCommand command = e.Command;
EmployeesDropDownList.DataBind();
EmployeesDropDownList.SelectedValue =
command.Parameters["@EmpID"].Value.ToString();
EmployeeDetailsView.DataBind();
}

</script>

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>Northwind Employees</title>
</head>
<body>
<form id="form1" runat="server">
<h3>Northwind Employees</h3>

<table cellspacing="10">

<tr>
<td valign="top">
<asp:DropDownList ID="EmployeesDropDownList"
DataSourceID="EmployeesSqlDataSource"
DataValueField="EmployeeID"
DataTextField="FullName"
AutoPostBack="True"
OnSelectedIndexChanged="EmployeesDropDownList_OnSelectedIndexChanged"
RunAt="Server" />
</td>

<td valign="top">
<asp:DetailsView ID="EmployeeDetailsView"
DataSourceID="EmployeeDetailsSqlDataSource"
AutoGenerateRows="false"
AutoGenerateInsertbutton="true"
AutoGenerateEditbutton="true"
AutoGenerateDeletebutton="true"
DataKeyNames="EmployeeID"
Gridlines="Both"
OnItemUpdated="EmployeeDetailsView_ItemUpdated"
OnItemDeleted="EmployeeDetailsView_ItemDeleted"
RunAt="server">

<HeaderStyle backcolor="Navy"
forecolor="White"/>

<RowStyle backcolor="White"/>
<AlternatingRowStyle backcolor="LightGray"/>
<EditRowStyle backcolor="LightCyan"/>

<Fields>
<asp:BoundField DataField="EmployeeID" HeaderText="Employee ID" InsertVis
ible="False" ReadOnly="true"/>
<asp:BoundField DataField="FirstName" HeaderText="First Name"/>
<asp:BoundField DataField="LastName" HeaderText="Last Name"/>

<asp:BoundField DataField="Address" HeaderText="Address"/>

<asp:BoundField DataField="City" HeaderText="City"/>

<asp:BoundField DataField="Region" HeaderText="Region"/>


<asp:BoundField DataField="PostalCode" HeaderText="Postal Code"/>

</Fields>
</asp:DetailsView>
</td>
</tr>
</table>

<asp:SqlDataSource ID="EmployeesSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName + ', ' + FirstName AS FullName FROM Em
ployees"
Connectionstring="<%$ ConnectionStrings:NorthwindConnection %>"
RunAt="server">
</asp:SqlDataSource>

<asp:SqlDataSource ID="EmployeeDetailsSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName, FirstName, Address, City, Region, Pos
talCode
FROM Employees WHERE EmployeeID = @EmpID"

InsertCommand="INSERT INTO Employees(LastName, FirstName, Address, City, Region,


PostalCode)
VALUES (@LastName, @FirstName, @Address, @City, @Region, @PostalCo
de);
SELECT @EmpID = SCOPE_IDENTITY()"

UpdateCommand="UPDATE Employees SET LastName=@LastName, FirstName=@FirstName, Add


ress=@Address,
City=@City, Region=@Region, PostalCode=@PostalCode
WHERE EmployeeID=@EmployeeID"

DeleteCommand="DELETE Employees WHERE EmployeeID=@EmployeeID"

ConnectionString="<%$ ConnectionStrings:NorthwindConnection %>"


OnInserted="EmployeeDetailsSqlDataSource_OnInserted"
RunAt="server">

<SelectParameters>
<asp:ControlParameter ControlID="EmployeesDropDownList" PropertyName="SelectedV
alue"
Name="EmpID" Type="Int32" DefaultValue="0" />
</SelectParameters>

<InsertParameters>
<asp:Parameter Name="LastName" Type="String" />
<asp:Parameter Name="FirstName" Type="String" />
<asp:Parameter Name="Address" Type="String" />
<asp:Parameter Name="City" Type="String" />
<asp:Parameter Name="Region" Type="String" />
<asp:Parameter Name="PostalCode" Type="String" />
<asp:Parameter Name="EmpID" Direction="Output" Type="Int32" DefaultValue="0" />
</InsertParameters>

<UpdateParameters>
<asp:Parameter Name="LastName" Type="String" />
<asp:Parameter Name="FirstName" Type="String" />
<asp:Parameter Name="Address" Type="String" />
<asp:Parameter Name="City" Type="String" />
<asp:Parameter Name="Region" Type="String" />
<asp:Parameter Name="PostalCode" Type="String" />
<asp:Parameter Name="EmployeeID" Type="Int32" DefaultValue="0" />
</UpdateParameters>

<DeleteParameters>
<asp:Parameter Name="EmployeeID" Type="Int32" DefaultValue="0" />
</DeleteParameters>

</asp:SqlDataSource>
</form>
</body>
</html>

See Also
Concepts
Using Parameters with Data Source Controls
Using Parameters with the SqlDataSource Control
Using Parameters with the ObjectDataSource Control
Data Source Controls Overview
ASP.NET

Modifying Data using Data Source Controls


Data source controls greatly expand the capabilities of data-bound controls such as the GridView, FormView, and DetailsView
controls to modify data at the data source without requiring extensive additional code. The data source control performs the
data modification, so data-bound controls can support updates without requiring specific information about the database or
other data source. You can use different data source controls with any combination of controls on the page. In addition, you
can change the database or data source that a data-bound control works with by changing its DataSourceID to point to a
different data source control.
Data Modification Commands
You can configure the ObjectDataSource, SqlDataSource, and AccessDataSource controls with data commands to insert,
update, and delete data in their associated data store.
Modifying Data with the ObjectDataSource Control
The ObjectDataSource control enables you to specify a data object method for performing a specific type of update. The
InsertMethod property specifies the data object method that is called when the ObjectDataSource control inserts an item into
the data source. Similarly, the UpdateMethod property specifies the data object method used for item updates, and the
DeleteMethod property specifies the method used to delete an item from the data source.
The following code example shows an ObjectDataSource control with its InsertMethod, UpdateMethod, and
DeleteMethod properties configured with the names of methods from the underlying data object.
VB
<asp:ObjectDataSource
ID="EmployeeDetailsObjectDataSource"
runat="server"
TypeName="Samples.AspNet.Controls.NorthwindEmployee"
SelectMethod="GetEmployee"
UpdateMethod="UpdateEmployee"
DeleteMethod="DeleteEmployee"
InsertMethod="InsertEmployee"
OnInserted="EmployeeDetailsObjectDataSource_OnInserted" >
<SelectParameters>
<asp:Parameter Name="EmployeeID" />
</SelectParameters>
<InsertParameters>
<asp:Parameter Name="NewEmployeeID" Direction="Output"
Type="Int32" DefaultValue="0" />
</InsertParameters>
</asp:ObjectDataSource>

C#
<asp:ObjectDataSource
ID="EmployeeDetailsObjectDataSource"
runat="server"
TypeName="Samples.AspNet.Controls.NorthwindEmployee"
SelectMethod="GetEmployee"
UpdateMethod="UpdateEmployee"
DeleteMethod="DeleteEmployee"
InsertMethod="InsertEmployee"
OnInserted="EmployeeDetailsObjectDataSource_OnInserted" >
<SelectParameters>
<asp:Parameter Name="EmployeeID" />
</SelectParameters>
<InsertParameters>
<asp:Parameter Name="NewEmployeeID" Direction="Output"
Type="Int32" DefaultValue="0" />
</InsertParameters>
</asp:ObjectDataSource>
For more information, see Creating an ObjectDataSource Control Source Object.
Modifying Data with SQL Commands
The SqlDataSource and AccessDataSource controls enable you to supply SQL commands for modifying data at the data
source. The InsertCommand property specifies a SQL command to insert a record into the data source. Similarly, the
UpdateCommand property specifies a command used for record updates, and the DeleteCommand property specifies a
command used to delete a record from the data source.
The following code example shows a SqlDataSource control with its InsertCommand, UpdateCommand, and
DeleteCommand properties configured with SQL commands that perform update tasks.
VB
<asp:sqlDataSource ID="EmployeeDetailsSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName, FirstName FROM Employees WHERE EmployeeID = @
EmpID"
InsertCommand="INSERT INTO Employees(LastName, FirstName) VALUES (@LastName, @FirstName);

SELECT @EmpID = SCOPE_IDENTITY()"


UpdateCommand="UPDATE Employees SET LastName=@LastName, FirstName=@FirstName
WHERE EmployeeID=@EmployeeID"
DeleteCommand="DELETE Employees WHERE EmployeeID=@EmployeeID"

ConnectionString="<%$ ConnectionStrings:NorthwindConnection %>"


OnInserted="EmployeeDetailsSqlDataSource_OnInserted"
RunAt="server">

<SelectParameters>
<asp:Parameter Name="EmpID" Type="Int32" DefaultValue="0" />
</SelectParameters>

<InsertParameters>
<asp:Parameter Name="EmpID" Direction="Output" Type="Int32" DefaultValue="0" />
</InsertParameters>

</asp:sqlDataSource>

C#
<asp:sqlDataSource ID="EmployeeDetailsSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName, FirstName FROM Employees WHERE EmployeeID = @
EmpID"

InsertCommand="INSERT INTO Employees(LastName, FirstName) VALUES (@LastName, @FirstName);


SELECT @EmpID = SCOPE_IDENTITY()"
UpdateCommand="UPDATE Employees SET LastName=@LastName, FirstName=@FirstName
WHERE EmployeeID=@EmployeeID"
DeleteCommand="DELETE Employees WHERE EmployeeID=@EmployeeID"

ConnectionString="<%$ ConnectionStrings:NorthwindConnection %>"


OnInserted="EmployeeDetailsSqlDataSource_OnInserted"
RunAt="server">
<SelectParameters>
<asp:Parameter Name="EmpID" Type="Int32" DefaultValue="0" />
</SelectParameters>

<InsertParameters>
<asp:Parameter Name="EmpID" Direction="Output" Type="Int32" DefaultValue="0" />
</InsertParameters>
</asp:sqlDataSource>
For more information, see Modifying Data using the SqlDataSource Control.
Parameters
You can make your data-update scenarios more flexible secure by using parameters to pass values to be inserted, updated, or
deleted in a data store. Parameter values can include the values of controls on the page, ASP.NET application variables, session
values, and so on.
Parameter values typically come from data-bound controls when those controls invoke an update, insert, or delete operation.
Additionally, you can create explicit parameter objects for the data source control for a given operation, which allows you to
customize the parameters. For example, you can use an explicit parameter object to specify the type or direction of a
parameter, or to define a default value for a parameter in case a null value is passed.
For the ObjectDataSource control, parameter values are passed as arguments when calling the appropriate method of the
underlying data object. For the SqlDataSource or AccessDataSource control, parameters are passed to the SQL command
used for the update. For more information and examples, see Using Parameters with Data Source Controls.
Events
Data source controls raise events both before and after data is modified. You can use these events to execute code before the
data operation occurs, including canceling the operation, and after the data operation has taken place. For example, you can
use the Deleting event of the SqlDataSource control to log information about a record about to be deleted. You can also use
the Inserted event of the SqlDataSource control to retrieve an auto-generated identity value for the newly inserted record.
See Also
Other Resources
Data Source Web Server Controls
ASP.NET

Filtering Data Using Data Source Controls


Data source controls provide a number of data services that make it easier to add advanced capabilities to your applications.
This includes filtering data based on search criteria that you specify. Filtering is especially convenient when working with
cached data, because you can provide search capabilities without having to re-run queries or call methods to read data.
To filter data, a data source control must be configured in these ways:
For the SqlDataSource or AccessDataSource controls, the DataSourceMode property must be set to DataSet.
For the ObjectDataSource control, the underlying source object must return a DataSet or DataTable object.
When using the XmlDataSource control, you can filter data using XPath queries. For more information, see
Filtering Data Using the XmlDataSource Control.
Setting the Filter Expression
You specify the filter to be applied to the data returned by an ObjectDataSource, SqlDataSource, or AccessDataSource
control by setting the data source control's FilterExpression property. The syntax for the filter expression is based on the
syntax of the Expression property of the DataColumn class. The filter expression is applied when the data source control's
Select method is called.
Providing Filter Parameters
You can provide a parameterized filter expression for an ObjectDataSource, SqlDataSource, or AccessDataSource control,
which enables you to provide filter values at run time without writing any code to explicitly set the FilterExpression property.
You specify filter expression parameters using the data source control's FilterParameters collection. The parameters can
retrieve data from controls, the QueryString object, session state, user profile properties, and so on. For information on the
types of parameters that can be used in the FilterParameters collection, see Using Parameters with Data Source Controls.
In the filter expression, you create placeholders that correspond to items in the data source control's FilterParameters
collection. The placeholders are numbered, with 0 representing the first parameter in the collection. You specify a placeholder
in the filter expression by placing the number of the filter parameter in '{' and '}' characters, as shown in the following example:

Country = '{0}' AND LastName LIKE '{1}'

Security Note
Because values from the FilterParameters collection are substituted into the FilterExpression string without encoding, you
should validate all filter parameter values before applying a filter. You can use the Filtering event of the data source control t
o access and validate filter parameter values before the filter is applied.

The following example shows a SqlDataSource control named EmployeeDetailsSqlDataSource that includes filter
parameters. The parameter values used in the FilterExpression property are filled at run time from the property values of
controls elsewhere on the page.
VB
<%@ Page language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Northwind Employees</title>
</head>
<body>
<form id="form1" runat="server">

<h3>Northwind Employees</h3>
<table cellspacing="10">
<tr>
<td valign="top">
<table border="0">
<tr>
<td valign="top">Country</td>
<td><asp:DropDownList runat="server" id="CountryListBox" AppendDataBoundI
tems="True"
DataSourceID="CountrySqlDataSource"
DataTextField="Country" DataValueField="Country" >
<asp:ListItem Selected="True" Value="" >(Show All)</asp:ListItem>
</asp:DropDownList>
</td>
</tr>
<tr>
<td>Last Name</td>
<td><asp:TextBox runat="server" id="LastNameTextBox" Text="*" /></td>
</tr>
<tr>
<td></td>
<td><asp:Button runat="server" id="FilterButton" Text="Filter Results" />
</td>
</tr>
</table>
</td>

<td valign="top">
<asp:GridView ID="EmployeesGridView"
DataSourceID="EmployeeDetailsSqlDataSource"
AutoGenerateColumns="false"
AllowSorting="True"
DataKeyNames="EmployeeID"
Gridlines="Both"
RunAt="server">

<HeaderStyle backcolor="Navy"
forecolor="White"/>
<RowStyle backcolor="White"/>

<AlternatingRowStyle backcolor="LightGray"/>

<EditRowStyle backcolor="LightCyan"/>

<Columns>
<asp:BoundField DataField="EmployeeID" HeaderText="Employee ID" ReadOnly=
"true"/>
<asp:BoundField DataField="FirstName" HeaderText="First Name"/>
<asp:BoundField DataField="LastName" HeaderText="Last Name"/>

<asp:BoundField DataField="Country" HeaderText="Country"/>

</Columns>
</asp:GridView>
</td>
</tr>
</table>

<asp:SqlDataSource ID="CountrySqlDataSource"
SelectCommand="SELECT DISTINCT Country FROM Employees"
EnableCaching="True"
CacheDuration="60"
ConnectionString="<%$ ConnectionStrings:NorthwindConnection %>"
RunAt="server" />

<asp:SqlDataSource ID="EmployeeDetailsSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName, FirstName, Country FROM Employees"
EnableCaching="True"
CacheDuration="60"
ConnectionString="<%$ ConnectionStrings:NorthwindConnection %>"
FilterExpression="Country LIKE '{0}' AND LastName LIKE '{1}'"
RunAt="server">

<FilterParameters>
<asp:ControlParameter ControlID="CountryListBox" PropertyName="SelectedValue"
/>
<asp:ControlParameter ControlID="LastNameTextBox" PropertyName="Text" />
</FilterParameters>
</asp:SqlDataSource>
</form>
</body>
</html>

C#
<%@ Page language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Northwind Employees</title>
</head>
<body>
<form id="form1" runat="server">

<h3>Northwind Employees</h3>

<table cellspacing="10">
<tr>
<td valign="top">
<table border="0">
<tr>
<td valign="top">Country</td>
<td><asp:DropDownList runat="server" id="CountryListBox" AppendDataBoundI
tems="True"
DataSourceID="CountrySqlDataSource"
DataTextField="Country" DataValueField="Country" >
<asp:ListItem Selected="True" Value="" >(Show All)</asp:ListItem>
</asp:DropDownList>
</td>
</tr>
<tr>
<td>Last Name</td>
<td><asp:TextBox runat="server" id="LastNameTextBox" Text="*" /></td>
</tr>
<tr>
<td></td>
<td><asp:Button runat="server" id="FilterButton" Text="Filter Results" />
</td>
</tr>
</table>
</td>

<td valign="top">
<asp:GridView ID="EmployeesGridView"
DataSourceID="EmployeeDetailsSqlDataSource"
AutoGenerateColumns="false"
AllowSorting="true"
DataKeyNames="EmployeeID"
Gridlines="Both"
RunAt="server">

<HeaderStyle backcolor="Navy"
forecolor="White"/>
<RowStyle backcolor="White"/>
<AlternatingRowStyle backcolor="LightGray"/>

<EditRowStyle backcolor="LightCyan"/>

<Columns>
<asp:BoundField DataField="EmployeeID" HeaderText="Employee ID" ReadOnly=
"true"/>
<asp:BoundField DataField="FirstName" HeaderText="First Name"/>
<asp:BoundField DataField="LastName" HeaderText="Last Name"/>
<asp:BoundField DataField="Country" HeaderText="Country"/>

</Columns>
</asp:GridView>
</td>
</tr>
</table>

<asp:SqlDataSource ID="CountrySqlDataSource"
SelectCommand="SELECT DISTINCT Country FROM Employees"
EnableCaching="True"
CacheDuration="60"
ConnectionString="<%$ ConnectionStrings:NorthwindConnection %>"
RunAt="server" />

<asp:SqlDataSource ID="EmployeeDetailsSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName, FirstName, Country FROM Employees"
EnableCaching="True"
CacheDuration="60"
ConnectionString="<%$ ConnectionStrings:NorthwindConnection %>"
FilterExpression="Country LIKE '{0}' AND LastName LIKE '{1}'"
RunAt="server">

<FilterParameters>
<asp:ControlParameter ControlID="CountryListBox" PropertyName="SelectedValue"
/>
<asp:ControlParameter ControlID="LastNameTextBox" PropertyName="Text" />
</FilterParameters>
</asp:SqlDataSource>
</form>
</body>
</html>

See Also
Other Resources
Data Source Web Server Controls
ASP.NET

Caching Data Using Data Source Controls


Data source controls provide data services to data-bound controls such as the GridView, FormView, and DetailsView controls.
These services include caching data to help improve the performance of applications in which the data does not change
frequently.
To cache data using the SqlDataSource or AccessDataSource controls, you must set the DataSourceMode property of those
controls to DataSet. The ObjectDataSource control can cache objects returned by the underlying business object. However, you
should not cache objects that hold resources or that maintain state that cannot be shared among multiple requests, such as an
open DataReader object.
Enabling Caching with a Data Source Control
Caching is not enabled by default for data source controls, but you can enable it by setting the control's EnableCaching
property to true. Cached data is refreshed based on the number of seconds you specify using the CacheDuration property.
You can further refine the behavior of a data source control's caching behavior by setting its CacheExpirationPolicy
property. Setting the property's value to Absolute forces the cache to be refreshed when the CacheDuration value is
exceeded. Setting the CacheExpirationPolicy property to Sliding refreshes the cache only if the CacheDuration value has
been exceeded since the last time the cached item was accessed.
Important
It is recommended that you set the EnableCaching property to false when client impersonation is enabled and the results f
rom the data source are retrieved based on the client identity. If caching is enabled, cached data for a single user can be view
ed by all users and sensitive information could be exposed to an unwanted source. Client impersonation is enabled when the
impersonate attribute of the identity configuration element is set to true and anonymous identification is disabled for the a
pplication at the Web server.

The following code example shows a SqlDataSource control configured to refresh data every 20 seconds:
VB
<%@ Page language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1


/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">

<asp:SqlDataSource
id="SqlDataSource1"
runat="server"
DataSourceMode="DataSet"
ConnectionString="<%$ ConnectionStrings:MyNorthwind%>"
EnableCaching="True"
CacheDuration="20"
SelectCommand="SELECT EmployeeID,FirstName,LastName,Title FROM Employees">
</asp:SqlDataSource>
<asp:GridView
id="GridView1"
runat="server"
AutoGenerateColumns="False"
DataSourceID="SqlDataSource1">
<columns>
<asp:BoundField HeaderText="First Name" DataField="FirstName" />
<asp:BoundField HeaderText="Last Name" DataField="LastName" />
<asp:BoundField HeaderText="Title" DataField="Title" />
</columns>
</asp:GridView>
</form>
</body>
</html>

C#
<%@ Page language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">

<asp:SqlDataSource
id="SqlDataSource1"
runat="server"
DataSourceMode="DataSet"
ConnectionString="<%$ ConnectionStrings:MyNorthwind%>"
EnableCaching="True"
CacheDuration="20"
SelectCommand="SELECT EmployeeID,FirstName,LastName,Title FROM Employees">
</asp:SqlDataSource>

<asp:GridView
id="GridView1"
runat="server"
AutoGenerateColumns="False"
DataSourceID="SqlDataSource1">
<columns>
<asp:BoundField HeaderText="First Name" DataField="FirstName" />
<asp:BoundField HeaderText="Last Name" DataField="LastName" />
<asp:BoundField HeaderText="Title" DataField="Title" />
</columns>
</asp:GridView>

</form>
</body>
</html>

J#
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">

<asp:SqlDataSource
id="SqlDataSource1"
runat="server"
DataSourceMode="DataSet"
ConnectionString="Data Source=localhost;Integrated Security=SSPI;Initial Ca
talog=Northwind;"
EnableCaching="True"
CacheDuration="20"
SelectCommand="SELECT EmployeeID,FirstName,LastName,Title FROM Employees">
</asp:SqlDataSource>

<asp:GridView
id="GridView1"
runat="server"
AutoGenerateColumns="False"
DataSourceID="SqlDataSource1">
<Columns>
<asp:BoundField HeaderText="First Name" DataField="FirstName" />
<asp:BoundField HeaderText="Last Name" DataField="LastName" />
<asp:BoundField HeaderText="Title" DataField="Title" />
</Columns>
</asp:GridView>

</form>
</body>
</html>

Advanced Caching Scenarios


If you are using the SqlDataSource control with the System.Data.SqlClient provider, you can take advantage of the
SqlCacheDependency class to ensure that cached data is refreshed only when the source table in the database has been
modified. For more information, see Caching Data with the SqlDataSource Control.
See Also
Other Resources
Data Source Web Server Controls
Handling Null Database Values Using Data Source Controls
In many cases, columns in database tables return null when no value is stored in that column. However, a null value can
present challenges when working with ASP.NET code or with data-bound Web controls. For example, an exception is thrown if
you try to bind the SelectedValue of a DropDownList control to null.
ASP.NET provides some built-in functionality for working with null values. If your scenario is not solved using the built-in
ASP.NET capabilities, there are some additional techniques you can use for working with null values.
The NullDisplayText Property
You can set the NullDisplayText property of bound fields in data source controls (such as the BoundField, CheckBoxField, and
ImageField objects) to substitute a specific value (such as a string) for null values returned from the data source. Controls will
then display that value as the text of the bound control. When a data-bound row is modified during an edit operation, if the
value for a bound field matches the NullDisplayText (whether the value was not modified or the user entered the same value
as the NullDisplayText), the field passes null to the data source as the field value. If the NullDisplayText property is not set,
null values are displayed as empty strings ("").
For example, if you set the NullDisplayText property for a BoundField object to "(no value)", and if the bound data column is
null, the Text property for Label or TextBox objects rendered by the BoundField object is set to "(no value)". If the user edits
the row and changes the value from "(no value)" to "Custom Value", the value "Custom Value" is passed to the data source as
the value for the field. But if the value of the bound control is still "(no value)", the data control passes null to the data source
as the field value.
The ConvertEmptyStringToNull Property
Parameter objects, TemplateField objects, and bound fields (BoundField, CheckBoxField, ImageField, and
AutoGeneratedField objects) support a ConvertEmptyStringToNull property that determines how the object will treat empty
string ("") values during update, insert, or delete operations. If the ConvertEmptyStringToNull property is true for an object,
and if the value for that object is an empty string, the object passes null to the data source as the object value. If the
ConvertEmptyStringToNull property is false for an object, and the value of the object is an empty string, an empty string is
passed to the data source as the object value.
Converting Null in Template Fields
The TemplateField object does not have a NullDisplayText property, because the template might contain multiple bound
fields. However, you can create your own null handling procedure for a bound field. You can then pass the data-bound value
to the procedure with data-binding syntax, using the Eval or Bind methods, as shown in the following example.
VB
<%@ Page Language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1


/DTD/xhtml1-transitional.dtd">
<script runat="server">
Public Function GetReportsTo(reportsTo As Object) As Integer
If reportsTo Is DBNull.Value Then
Return 0
Else
Return CInt(reportsTo)
End If
End Function
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Northwind Employees</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyName
s="EmployeeID"
DataSourceID="SqlDataSource1">
<Columns>
<asp:CommandField ShowEditButton="True" />
<asp:BoundField DataField="EmployeeID" HeaderText="EmployeeID" InsertVisibl
e="False"
ReadOnly="True" SortExpression="EmployeeID" />
<asp:BoundField DataField="LastName" HeaderText="LastName" SortExpression="
LastName" />
<asp:BoundField DataField="FirstName" HeaderText="FirstName" SortExpression
="FirstName" />
<asp:TemplateField HeaderText="ReportsTo" SortExpression="ReportsTo">
<ItemTemplate>
<asp:DropDownList ID="DropDownList1" runat="server" Enabled="False"
DataSourceID="SqlDataSource2"
DataTextField="Name" DataValueField="EmployeeID" SelectedValue=
'<%# GetReportsTo(Eval("ReportsTo")) %>' AppendDataBoundItems="True">
<asp:ListItem Selected="True" Value="0">(none)</asp:ListItem>
</asp:DropDownList>
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="DropDownList2" runat="server" DataSourceID="S
qlDataSource2"
DataTextField="Name" DataValueField="EmployeeID" SelectedValue=
'<%# GetReportsTo(Eval("ReportsTo")) %>' AppendDataBoundItems="True">
<asp:ListItem Selected="True" Value="0">(none)</asp:ListItem>
</asp:DropDownList>
</EditItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ Connect
ionStrings:Northwind %>"
SelectCommand="SELECT [EmployeeID], [LastName], [FirstName], [ReportsTo] FROM [
Employees]"
UpdateCommand="UPDATE [Employees] SET [LastName] = @LastName, [FirstName] = @Fi
rstName, [ReportsTo] = @ReportsTo WHERE [EmployeeID] = @EmployeeID">
<UpdateParameters>
<asp:Parameter Name="LastName" Type="String" />
<asp:Parameter Name="FirstName" Type="String" />
<asp:Parameter Name="ReportsTo" Type="Int32" />
<asp:Parameter Name="EmployeeID" Type="Int32" />
</UpdateParameters>
</asp:SqlDataSource>
<asp:SqlDataSource ID="SqlDataSource2" runat="server" ConnectionString="<%$ Connect
ionStrings:Northwind %>"
SelectCommand="SELECT EmployeeID, LastName + ', ' + FirstName As Name From Empl
oyees">
</asp:SqlDataSource>
</div>
</form>
</body>
</html>

C#
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">

<script runat="server">
public int GetReportsTo(object reportsTo)
{
if (reportsTo == DBNull.Value)
return 0;
else
return (int)reportsTo;
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Northwind Employees</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyName
s="EmployeeID"
DataSourceID="SqlDataSource1">
<Columns>
<asp:CommandField ShowEditButton="True" />
<asp:BoundField DataField="EmployeeID" HeaderText="EmployeeID" InsertVisibl
e="False"
ReadOnly="True" SortExpression="EmployeeID" />
<asp:BoundField DataField="LastName" HeaderText="LastName" SortExpression="
LastName" />
<asp:BoundField DataField="FirstName" HeaderText="FirstName" SortExpression
="FirstName" />
<asp:TemplateField HeaderText="ReportsTo" SortExpression="ReportsTo">
<ItemTemplate>
<asp:DropDownList ID="DropDownList1" runat="server" Enabled="False"
DataSourceID="SqlDataSource2"
DataTextField="Name" DataValueField="EmployeeID" SelectedValue=
'<%# GetReportsTo(Eval("ReportsTo")) %>' AppendDataBoundItems="True">
<asp:ListItem Selected="True" Value="0">(none)</asp:ListItem>
</asp:DropDownList>
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="DropDownList2" runat="server" DataSourceID="S
qlDataSource2"
DataTextField="Name" DataValueField="EmployeeID" SelectedValue=
'<%# GetReportsTo(Eval("ReportsTo")) %>' AppendDataBoundItems="True">
<asp:ListItem Selected="True" Value="0">(none)</asp:ListItem>
</asp:DropDownList>
</EditItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ Connect
ionStrings:Northwind %>"
SelectCommand="SELECT [EmployeeID], [LastName], [FirstName], [ReportsTo] FROM [
Employees]"
UpdateCommand="UPDATE [Employees] SET [LastName] = @LastName, [FirstName] = @Fi
rstName, [ReportsTo] = @ReportsTo WHERE [EmployeeID] = @EmployeeID">
<UpdateParameters>
<asp:Parameter Name="LastName" Type="String" />
<asp:Parameter Name="FirstName" Type="String" />
<asp:Parameter Name="ReportsTo" Type="Int32" />
<asp:Parameter Name="EmployeeID" Type="Int32" />
</UpdateParameters>
</asp:SqlDataSource>
<asp:SqlDataSource ID="SqlDataSource2" runat="server" ConnectionString="<%$ Connect
ionStrings:Northwind %>"
SelectCommand="SELECT EmployeeID, LastName + ', ' + FirstName As Name From Empl
oyees">
</asp:SqlDataSource>
</div>
</form>
</body>
</html>

For more information on the Eval and Bind methods, see Data-Binding Expression Syntax.
Techniques for Working with Null Using the ObjectDataSource Control
When you create an object to act as the source for an ObjectDataSource control, you can manage the conversion of null values
within the object's code. Two options are available: nullable types and annotations for strongly typed objects such as datasets.
Note
For more information about the ObjectDataSource control, see ObjectDataSource Control Overview.

Using Nullable Types


When you create the select, insert, update, and delete methods of the source object for a ObjectDataSource control, if the
parameter value can be null in the data source, you can define parameters and return values for those methods as nullable
types. Nullable types are value types such as an integer or a Boolean that can be either a regular value or a null value.
For information on using nullable types with Visual Basic, see Value Types that Might Not Have a Defined Value. For
information on using nullable types with C#, see Using Nullable Types (C# Programming Guide).
Annotating a Strongly Typed Dataset
A common source object for the ObjectDataSource control is a strongly typed DataSet object. To have a strongly typed
DataSet convert null values returned from a data source to a value that you specify, you can annotate the strongly typed
DataSet using the nullValue annotation. For more information, see Using Annotations with a Typed DataSet.
See Also
Concepts
Data Source Controls Overview
ASP.NET Data-Bound Web Server Controls Overview
Data-Binding Expression Syntax
Visual Web Developer

SqlDataSource Web Server Control (Visual Studio)


The topics in this section describe how to work with the SqlDataSource control to represent an SQL data source to data-bound
controls.
In This Section
Getting Started — SqlDataSource Web Server Control (Visual Studio)
Learning More — SqlDataSource Web Server Control (Visual Studio)
Walkthough Topics — SqlDataSource Web Server Control (Visual Studio)
How-to Topics — SqlDataSource Web Server Control (Visual Studio)
See Also
Other Resources
Data Toolbox Controls
ASP.NET Data Access (Visual Studio)
Visual Web Developer

Getting Started — SqlDataSource Web Server Control (Visual


Studio)
The topics below provide introductory information about using the SqlDataSource control to represent an SQL data source to
data-bound controls.
In This Section
SqlDataSource Web Server Control Overview
How to: Connect to a SQL Server Database Using the SqlDataSource Control (Visual Studio)
How to: Connect to an Access Database Using the SqlDataSource Control (Visual Studio)
How to: Connect to an ODBC Database Using the SqlDataSource Control (Visual Studio)
How to: Connect to an Oracle Database Using the SqlDataSource Control (Visual Studio)
Selecting Data Using the SqlDataSource Control
How to: Enable Filtering for SqlDataSource Controls (Visual Studio)
See Also
Other Resources
SqlDataSource Web Server Control (Visual Studio)
Data Toolbox Controls
ASP.NET Data Access (Visual Studio)
ASP.NET

SqlDataSource Web Server Control Overview


The SqlDataSource control enables you to use a Web control to access data located in a relational data base, including
Microsoft SQL Server and Oracle databases, as well as OLE DB and ODBC data sources. You can use the SqlDataSource
control with other controls that display data, such as the GridView, FormView, and DetailsView controls, to display and
manipulate data on an ASP.NET Web page, using little or no code.
The SqlDataSource control uses ADO.NET classes to interact with any database supported by ADO.NET. This includes
Microsoft SQL Server (using the System.Data.SqlClient provider), System.Data.OleDb, System.Data.Odbc, and Oracle (using the
System.Data.OracleClient provider). Using a SqlDataSource control allows you to access and manipulate data in an ASP.NET
page without using ADO.NET classes directly. You provide a connection string to connect to your database and define the SQL
statements or stored procedures that work with your data. At run time, the SqlDataSource control automatically opens the
database connection, executes the SQL statement or stored procedure, returns the selected data (if any), and then closes the
connection.
Connecting the SqlDataSource Control to a Data Source
When you configure a SqlDataSource control, you set the ProviderName property to the type of database (the default is
System.Data.SqlClient) and the ConnectionString property to a connection string that includes information required to
connect to the database. The contents of a connection string differ depending on what type of database the data source control
is accessing. For example, the SqlDataSource control requires a server name, database (catalog) name, and information about
how to authenticate the user when connecting to a SQL Server. For information on valid connection strings, see the
ConnectionString property topics for the SqlConnection, OracleConnection, OleDbConnection, and OdbcConnection classes.
Instead of setting connection strings at design time as property settings in the SqlDataSource control, you can store them
centrally as part of your application's configuration settings using the connectionStrings configuration element. This enables
you to manage connection strings independently of your ASP.NET code, including encrypting them using
Protected Configuration. The following example shows a connection to the SQL Server Northwind sample database using a
connection string stored in the <connectionStrings> configuration element named MyNorthwind.
VB
<%@ Page language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1


/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">
<asp:SqlDataSource
id="SqlDataSource1"
runat="server"
DataSourceMode="DataReader"
ConnectionString="<%$ ConnectionStrings:MyNorthwind%>"
SelectCommand="SELECT LastName FROM Employees">
</asp:SqlDataSource>
<asp:ListBox
id="ListBox1"
runat="server"
DataTextField="LastName"
DataSourceID="SqlDataSource1">
</asp:ListBox>
</form>
</body>
</html>

C#
<%@ Page language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">
<asp:SqlDataSource
id="SqlDataSource1"
runat="server"
DataSourceMode="DataReader"
ConnectionString="<%$ ConnectionStrings:MyNorthwind%>"
SelectCommand="SELECT LastName FROM Employees">
</asp:SqlDataSource>
<asp:ListBox
id="ListBox1"
runat="server"
DataTextField="LastName"
DataSourceID="SqlDataSource1">
</asp:ListBox>

</form>
</body>
</html>

J#
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">
<asp:SqlDataSource
id="SqlDataSource1"
runat="server"
DataSourceMode="DataReader"
ConnectionString="Data Source=localhost;Integrated Security=SSPI;Initial Catalog=
Northwind;"
SelectCommand="SELECT LastName FROM Employees">
</asp:SqlDataSource>

<asp:ListBox
id="ListBox1"
runat="server"
DataTextField="LastName"
DataSourceID="SqlDataSource1">
</asp:ListBox>
</form>
</body>
</html>

Issuing Data Commands with the SqlDataSource Control


You can specify up to four commands (SQL queries) for the SqlDataSource command: a SelectCommand, UpdateCommand,
DeleteCommand, and an InsertCommand. Each command is a separate property of the data source control. For each command
property, you specify a SQL statement for the data source control to execute. If the data source control connects to a database
that supports stored procedures, you can specify the name of a stored procedure in place of the SQL statement.
You can create parameterized commands that include placeholders for values to be supplied at run time. The following
example shows a typical parameterized SQL Select command:
Select CustomerID, CompanyName From Customers Where City = @city

You can create parameter objects that specify where the command should get parameter values at run time, such as from
another control, from a query string, and so on. Alternatively, you can specify parameter values programmatically. For more
information, see Using Parameters with the SqlDataSource Control.
The data source control executes the commands when its corresponding Select, Update, Delete, or Insert method is called. The
Select method is called automatically when you call the DataBind method of the page or of a control bound to the data source
control. You can also call any of the four methods explicitly when you want the data source control to execute a command.
Some controls, such as the GridView control, can call the methods automatically, without requiring that you call the methods
or that you explicitly call the DataBind method. For more information, see Selecting Data Using the SqlDataSource Control
and Modifying Data using the SqlDataSource Control.
Returning DataSet or DataReader Objects
The SqlDataSource control can return data in two forms: as a DataSet object or as an ADO.NET data reader. You can specify
which form to return by setting the data source control's DataSourceMode property. A DataSet object contains all the data in
server 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. As a rule, you choose to return a dataset if you want to filter, sort, or page through data
after retrieving it or if you want to maintain a cache. In contrast, you use a data reader when you simply want to return the data
and are using a control on the page to display that data. For example, using a data reader is ideal for returning data that you
want to display in a ListBox, DropDownList, or GridView control where a list of results is displayed in a read-only format.
Caching with the SqlDataSource Control
The SqlDataSource control can cache data that it has retrieved, which can enhance the performance of your applications by
avoiding expensive queries. Caching is practical in almost any situation where the data is not highly volatile and the cached
results are small enough to avoid utilizing too much system memory.
Caching is not enabled by default. You can enable it by setting EnableCaching to true. The caching mechanism is based on
time; you can set the CacheDuration property to the number of seconds to cache data. The data source control maintains a
separate cache entry for each combination of connection, select command, select parameters, and cache settings.
The SqlDataSource control can also take advantage of the cache dependency feature of SQL Server (if available in your
version of SQL Server). This feature allows you to specify that the data in the cache is maintained until SQL Server reports a
change in the specified table. This type of caching allows you to improve the performance of data access in your Web
applications, because you can minimize data retrieval to only those times when it is necessary to get refreshed data.
For more information, see Caching Data with the SqlDataSource Control.
Filtering with the SqlDataSource Control
If you have enabled caching for the SqlDataSource control and have specified a dataset as the format for data returned by a
Select query, you can also filter the data without re-running the query. The SqlDataSource control supports a FilterExpression
property that allows you to specify selection criteria that are applied to the data maintained by the data source control. You can
also parameterize the filter expression by creating special FilterParameters objects that provide values at run time to the filter
expression.
Sorting with the SqlDataSource Control
The SqlDataSource control supports sort requests from the bound control when the DataSourceMode is set to DataSet. For
more information, see Sorting Data with Data Source Controls.
See Also
Other Resources
Data Source Web Server Controls
Visual Web Developer

How to: Connect to a SQL Server Database Using the


SqlDataSource Control (Visual Studio)
You can connect to a Microsoft SQL Server database using the SqlDataSource control. To do this, you need a connection string
and access rights to a SQL Server database. Then, you can use the SqlDataSource control to provide data to any data-bound
control that supports the DataSourceID property, such as the GridView control.
To connect to a SQL Server database using the SqlDataSource control
1. In Microsoft Visual Studio, open a Web site, add an ASP.NET page (Web Form), and switch to Design view.
2. From the Data group in the Toolbox, drag a SqlDataSource control onto the page.
3. On the SqlDataSource Tasks shortcut menu, click Configure Data Source - <Datasourcename>.
If the SqlDataSource Tasks shortcut menu is not displayed, right-click the
T:System.Web.UI.WebControls.SqlDataSource control, and then click Configure Data Source.
4. Click New Connection.
If the Choose Data Source dialog box appears, click Microsoft SQL Server, and then click Continue.
5. In the Add Connection dialog box, click Change.
6. In the Change Data Source dialog box, click Microsoft SQL Server, and then click OK.
7. In the Server name box, enter the name for your SQL Server database, and then under Logon to the server, enter the
logon credentials.
For the logon credentials, select the option that is appropriate for accessing and running the SQL Server database
(either by using Microsoft Windows integrated security or by providing a specific ID and password) and, if it is
required, enter a user name and password.
8. In the Select or enter a database name list, enter a valid database on the server, such as Northwind.
9. Optionally, click Test connection to verify that your connection works.
10. Click OK.
Notice that your new connection is selected in the Configure Data Source - <Datasourcename> dialog box.
11. Click Next.
12. Select Yes, save this connection as, and enter a name for your connection for when it is stored in the application
configuration file, and then click Next.
13. Select the database table, view, or stored procedure from which to retrieve results or specify your own SQL statement.
14. Optionally, click WHERE to supply search criteria and ORDER BY to specify sort order.
If you want to support insert, update, and delete operations, click Advanced, and then select the option to generate
INSERT, UPDATE, and DELETE statements for your SqlDataSource control. You can also specify whether you want
the commands to use optimistic concurrency checks to determine whether the data has been modified before an
update or delete operation is performed.
15. To test your query, click Next, and then click Test Query.
16. Click Finish.
You can now drag a data-bound control, such as a GridView control, onto the page and specify your SqlDataSource
control as the data source.
See Also
Reference
SqlDataSource
Concepts
Data Source Controls Overview
Visual Web Developer

How to: Connect to an Access Database Using the


SqlDataSource Control (Visual Studio)
You can connect to a Microsoft Access database using the SqlDataSource control. To do this, you need a connection string and
an Access data file. Then, you can use the SqlDataSource control to provide data to any data-bound control that supports the
DataSourceID property, such as the GridView control.
Note
You can also connect to an Access database using the AccessDataSource control, which supports a DataFile property for spec
ifying the name of the .mdb file to connect to. However, connecting to an Access database using the SqlDataSource control l
ets you specify additional connection properties, such as authentication credentials. Generally, if the Access database that you
are connecting to requires a password, you should connect to it with the SqlDataSource control, store the authentication cre
dentials in a connection string in the Web.config file, and help protect the connection string by encrypting it.

To connect to an Access database using the SqlDataSource control


1. In Microsoft Visual Studio, open a Web site, add an ASP.NET page (Web Form), and switch to Design view.
2. From the Data group in the Toolbox, drag a SqlDataSource control onto the page.
3. On the SqlDataSource Tasks shortcut menu, click Configure Data Source.
If the SqlDataSource Tasks shortcut menu does not appear, right-click the SqlDataSource control, and then click
Configure Data Source.
4. Click New Connection.
If the Choose Data Source dialog box appears, click Microsoft Access Database File, and then click Continue.
5. In the Add Connection dialog box, click Change, in the Change Data Source dialog box, click Microsoft Access
Database File, and then click OK.
6. In the Database file name box, enter a path to the Access database, and then under Log on to the database, enter
your logon credentials, if they are required.
7. Optionally, click Test connection to verify that the connection to the Access database succeeds.
8. Click OK.
Notice that in the Configure Data Source - <Datasourcename> dialog box, your new connection is selected.
9. Click Next.
10. Select the Yes, save this connection as check box, enter a name for your connection for when the connection is stored
in the application configuration file, and then click Next.
11. Select the database table, view (Access Query), or stored procedure (Access Query) from which to retrieve results or
enter your own SQL statement.
12. Optionally, you can click WHERE to supply search criteria and ORDER BY to specify sort order.
If you want to support insert, update, and delete operations, click Advanced, and then select Generate INSERT,
UPDATE, and DELETE statements for your SqlDataSource control. You can also select Use optimistic
concurrency to specify that you want the commands to determine whether the data has been modified before an
update or delete operation is performed.
13. To test your query, click Next, and then click Test Query.
14. Click Finish.
You can now drag a data-bound control, such as a GridView control, onto the page and specify your SqlDataSource
control as the data source.
See Also
Reference
SqlDataSource
AccessDataSource
Concepts
Data Source Controls Overview
Visual Web Developer

How to: Connect to an ODBC Database Using the


SqlDataSource Control (Visual Studio)
You can use the SqlDataSource control to connect to any ODBC–compliant data source. You connect the control to an ODBC
data source by specifying the appropriate ODBC driver in the connection string along with relevant server and authentication
information.
To use the SqlDataSource control to connect to an ODBC database
1. Open the page from which you want to connect to an ODBC database.
2. Switch to Design view.
3. From the Data group on the Toolbox, drag a SqlDataSource control onto the page.
4. If the smart tag panel is not displayed, right-click the control and then click Show Smart Tag.
5. In the SqlDataSource Tasks list, click Configure Data Source.
The Configure Data Source wizard is displayed.
6. In the Configure Data Source dialog box, click New Connection.
7. If the Add Connection dialog box is displayed, click Change to display the Change Data Source dialog box.
8. In the Change Data Source dialog box, click Microsoft ODBC Data Source in the Data source list, and then click OK.
The Add Connection dialog box is displayed.
9. If you have an existing ODBC data source, click Use user or system data source name and select an existing ODBC data
source from the list.
10. If you do not have an existing ODBC data source, click Use connection string and then type the connection string or
click Build to display the Select Data Source dialog box where you can build an ODBC data source name (DSN).
11. If necessary, enter the user name and password required to connect to the database.
12. Click Test connection to verify the connection to the ODBC data source, and then close the Add Connection dialog box
to return to the Configure Data Source wizard.
13. Click Next, and then click Next again to have the connection string information saved as part of the Web.config file
under the name you provide.
14. In the Configure the Select Statement pane, if you want to use the wizard to create a SQL query, click Specify
columns from a table or view and use the options in the pane to configure your query.
Note
To have the wizard generate Insert, Update, and Delete statements based on the Select statement you are creating, click
Advanced.

15. If you want to use the query builder or write your Select query, click Specify a custom SQL statement or stored
procedure, click Next, and then write your SQL statement. Click the UPDATE, INSERT, or DELETE tabs to create update
statements.
16. Click Next.
17. In the Test Query pane, click Test Query to determine whether the query returns the results you want, and then click
Finish.
See Also
Tasks
Walkthrough: Basic Data Access in Web Pages
How to: Connect to an ODBC Database Using the SqlDataSource Control
Concepts
Data Source Controls Overview
Binding to Data Using a Data Source Control
Visual Web Developer

How to: Connect to an Oracle Database Using the


SqlDataSource Control (Visual Studio)
You can use the SqlDataSource control to connect to an Oracle database. You connect the control to an Oracle database by first
establishing connection information in the Web.config file, and then by referencing the connection information in a
SqlDataSource control.
Note
The System.Data.OracleClient provider requires Oracle client software version 8.1.7 or later to be installed on the computer t
hat connects to the Oracle database; in this case, on the computer that runs ASP.NET pages.

To use the SqlDataSource control to connect to an Oracle database


1. Open the page from which you want to connect to an Oracle database.
2. Switch to Design view.
3. From the Data tab of the Toolbox, drag a SqlDataSource control onto your page.
4. If the SqlDataSource Tasks smart tag does not appear, right-click the control and click Show Smart Tag.
5. In the SqlDataSource Tasks list, click Configure Data Source.
6. In the Configure Data Source dialog box, click New Connection.
The Choose Data Source dialog box is displayed.
7. In the Data source list, click Oracle Database and then click Continue.
The Add Connection dialog box is displayed.
8. In the Server name box, type the name of the Oracle server.
9. Type the user name and password to connect with the database.
10. Select the Save my password box to save authentication information as part of the connection string, and then click OK.
Note
If you include explicit authentication information in a connection string, you should encrypt the ConnectionStrings secti
on of the Web.config file. For details, see Encrypting Configuration Information Using Protected Configuration.

You are returned to the Configure Data Source dialog with the new connection string information displayed.
11. Click Next.
12. Make sure that the Yes, save this connection check box is selected, change the name of the connection string if you
want, and then click Next to have the connection string information saved in the application's Web.config file.
The Configure the Select Statement pane appears.
13. Click Specify a custom SQL statement or stored procedure if you want to type in your own SQL statement, or
Specify columns from a table or view to use the wizard to create the query.
14. If you clicked Specify columns from a table or view, in the Name list click the name of the table or view to use, and
then in the Columns list select the columns to return.
Note
To generate update statements, click Advanced and then click Generate INSERT, UPDATE, and DELETE statements.

15. If you clicked Specify a custom SQL statement or stored procedure, click Next to move to the Define Custom
Statements or Stored Procedures pane to write your query.
Note
To define update statements, click the UPDATE, INSERT, and DELETE tabs and specify the SQL command or stored pr
ocedure to use for each operation.

16. Click Next.


17. Click the Test Query button to test your query against the database, and then click Finish.
See Also
Concepts
Data Source Controls Overview
Binding to Data Using a Data Source Control
ASP.NET

Selecting Data Using the SqlDataSource Control


You can use the SqlDataSource control to retrieve data from a database with little or no code. The SqlDataSource control can
work with any database that has an associated ADO.NET provider configured in the DbProviderFactories section of the
configuration, including Microsoft SQL Server, Oracle, ODBC, or OLE DB databases such as Microsoft Access. The database you
use will dictate the syntax of the SQL statements you configure the SqlDataSource to use and whether you can use more
advanced database features such as stored procedures. However, the data source control operates the same for all databases.
To retrieve data from a database using the SqlDataSource control, you need to set at least the following properties:
ProviderName Set to the name of the ADO.NET provider that represents the database you are working with. If you are
working with Microsoft SQL Server, set the ProviderName property to "System.Data.SqlClient"; if you are working with
an Oracle database, set the ProviderName property to "System.Data.OracleClient"; and so on.
ConnectionString Set to a connection string that works for your database.
SelectCommand Set to an SQL query or stored procedure that returns data from the database. The query that you set
for the SelectCommand property is the same query that you set for the CommandText property of an ADO.NET
IDbCommand object when writing ADO.NET data-access code. The actual syntax of the SQL query depends on the
schema of your data and which database you are using.
The following sections describe these properties in more detail.
Specifying a Provider Name
You set the ProviderName property to the name of the ADO.NET provider associated with the type of database in which your
data is stored. The list of allowable providers is registered in the DbProviderFactories section of the configuration file, either
in the Machine.config or Web.config file. By default, the SqlDataSource control uses the System.Data.SqlClient ADO.NET
provider, which corresponds to Microsoft SQL Server. Therefore, if you are connecting to a SQL Server database, you do not
need to explicitly specify a provider. However, you can also specify the System.Data.OracleClient, System.Data.Odbc, or
System.Data.OleDb providers. For more information, see ADO.NET.
Note
Do not set the ProviderName property to the value of an unmanaged ADO provider, such as SQLOLEDB or MSDAORA.

Specifying a Connection String


You set the ConnectionString property to a connection string used for a specific database. However, setting
ConnectionString property of a SqlDataSource control to a specific connection string is not a very maintainable strategy for
large sites. Additionally, the connection string is then stored in plain text in the ASP.NET page. To make your Web application
more maintainable and more secure, it is recommended that you store connection strings in the connectionStrings element in
the application's configuration file. You can then reference the stored connection string using a connection expression like that
in the following example:

<asp:SqlDataSource
ID="SqlDataSource1"
runat="server"
ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
SelectCommand="SELECT * FROM [Categories]">
</asp:SqlDataSource>

For additional security, you can encrypt the contents of the <connectionStrings> configuration section. For more
information, see Encrypting and Decrypting Configuration Sections.
Specifying the Select Command
You can specify an SQL query for the SqlDataSource control to execute by setting its SelectCommand property. The
following example demonstrates an SQL query that retrieves a result set consisting of the last names of all the employees in an
Employees table:

SELECT LastName FROM Employees;


The following code example shows how you can set the ConnectionString and SelectCommand properties of a
SqlDataSource control to display the Employees data in a GridView control:
VB
<%@ Page language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1


/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">
<asp:SqlDataSource
id="SqlDataSource1"
runat="server"
DataSourceMode="DataReader"
ConnectionString="<%$ ConnectionStrings:MyNorthwind%>"
SelectCommand="SELECT LastName FROM Employees">
</asp:SqlDataSource>

<asp:ListBox
id="ListBox1"
runat="server"
DataTextField="LastName"
DataSourceID="SqlDataSource1">
</asp:ListBox>

</form>
</body>
</html>

C#
<%@ Page language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">
<asp:SqlDataSource
id="SqlDataSource1"
runat="server"
DataSourceMode="DataReader"
ConnectionString="<%$ ConnectionStrings:MyNorthwind%>"
SelectCommand="SELECT LastName FROM Employees">
</asp:SqlDataSource>

<asp:ListBox
id="ListBox1"
runat="server"
DataTextField="LastName"
DataSourceID="SqlDataSource1">
</asp:ListBox>
</form>
</body>
</html>
J#
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">
<asp:SqlDataSource
id="SqlDataSource1"
runat="server"
DataSourceMode="DataReader"
ConnectionString="Data Source=localhost;Integrated Security=SSPI;Initial Catalog=
Northwind;"
SelectCommand="SELECT LastName FROM Employees">
</asp:SqlDataSource>
<asp:ListBox
id="ListBox1"
runat="server"
DataTextField="LastName"
DataSourceID="SqlDataSource1">
</asp:ListBox>

</form>
</body>
</html>

If the database you are working with supports stored procedures, you can set the SelectCommand property to the name of
the stored procedure and the SelectCommandType property StoredProcedure to indicate that the SelectCommand property
refers to a stored procedure. The following example demonstrates a simple stored procedure that you can create in SQL
Server:

CREATE PROCEDURE sp_GetAllEmployees AS


SELECT * FROM Employees;
GO

To configure the SqlDataSource to use this stored procedure, set the SelectCommand text to "sp_GetAllEmployees" and the
SelectCommandType property to StoredProcedure.
Most stored procedures use parameters. For more information about using stored procedures with parameters, see
Using Parameters with the SqlDataSource Control.
At run time, SqlDataSource control submits the text in the SelectCommand property to the database, and the database
returns the result of the query or stored procedure to the SqlDataSource control. Any Web controls that are bound to the data
source control display the result set on your ASP.NET page.
Passing Parameters to SQL Statements
Users often interact with data based on parameters that can be resolved or evaluated only at run time. For example, data
displayed on an ASP.NET Web page might represent a report for a specific date. If the user selects a different date, the data in
the report might also change. Whether the date is changed explicitly by the user or programmatically by the Web application,
the SQL query that you submit to the database can be made more flexible and more maintainable if it is a parameterized SQL
query, in which elements of the SQL statement are bound to Web application variables and evaluated at run time.
The SqlDataSource control supports parameterized SQL queries by associating parameters you add to the SelectParameters
collection with placeholders in the SelectCommand query. Parameter values can be read from another control on the page,
from session state, from the user profile, and from other elements. For more information, see
Using Parameters with the SqlDataSource Control.
The syntax used for the placeholders varies, depending on the type of your database. If you are working with SQL Server, the
parameter name begins with the '@' character, and its name corresponds to the name of the Parameter object in the
SelectParameters collection. If you are working with an ODBC or OLE DB database, parameters in a parameterized statement
are not named and instead are specified with the placeholder character '?'.
The following example demonstrates how a parameterized SQL query retrieves all the orders in the SQL Server Northwind
database, based on the employee ID of the currently logged-in employee.

SELECT * FROM Orders WHERE EmployeeID = @empid

In this example, the @empid expression is the parameter that is evaluated at run time.
The following code example demonstrates a parameterized SQL query which takes the parameter value from another control
on the page:
VB
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">

<p><asp:dropdownlist
id="DropDownList1"
runat="server"
autopostback="True">
<asp:listitem selected="True">Sales Representative</asp:listitem>
<asp:listitem>Sales Manager</asp:listitem>
<asp:listitem>Vice President, Sales</asp:listitem>
</asp:dropdownlist></p>

<asp:sqldatasource
id="SqlDataSource1"
runat="server"
connectionstring="<%$ ConnectionStrings:MyNorthwind%>"
selectcommand="SELECT LastName FROM Employees WHERE Title = @Title">
<selectparameters>
<asp:controlparameter name="Title" controlid="DropDownList1" propertyname="Se
lectedValue"/>
</selectparameters>
</asp:sqldatasource>
<p><asp:listbox
id="ListBox1"
runat="server"
datasourceid="SqlDataSource1"
datatextfield="LastName">
</asp:listbox></p>

</form>
</body>
</html>

C#
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">

<p><asp:dropdownlist
id="DropDownList1"
runat="server"
autopostback="True">
<asp:listitem selected="True">Sales Representative</asp:listitem>
<asp:listitem>Sales Manager</asp:listitem>
<asp:listitem>Vice President, Sales</asp:listitem>
</asp:dropdownlist></p>

<asp:sqldatasource
id="SqlDataSource1"
runat="server"
connectionstring="<%$ ConnectionStrings:MyNorthwind%>"
selectcommand="SELECT LastName FROM Employees WHERE Title = @Title">
<selectparameters>
<asp:controlparameter name="Title" controlid="DropDownList1" propertyname="Se
lectedValue"/>
</selectparameters>
</asp:sqldatasource>

<p><asp:listbox
id="ListBox1"
runat="server"
datasourceid="SqlDataSource1"
datatextfield="LastName">
</asp:listbox></p>

</form>
</body>
</html>

J#
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">

<p><asp:DropDownList
id="DropDownList1"
runat="server"
AutoPostBack="True">
<asp:ListItem Selected="True">Sales Representative</asp:ListItem>
<asp:ListItem>Sales Manager</asp:ListItem>
<asp:ListItem>Vice President, Sales</asp:ListItem>
</asp:DropDownList></p>

<asp:SqlDataSource
id="SqlDataSource1"
runat="server"
ConnectionString="Data Source=localhost;Integrated Security=SSPI;Initial Catalog=
Northwind;"
SelectCommand="SELECT LastName FROM Employees WHERE Title = @Title">
<SelectParameters>
<asp:ControlParameter Name="Title" ControlId="DropDownList1" PropertyName="Se
lectedValue"/>
</SelectParameters>
</asp:SqlDataSource>

<p><asp:ListBox
id="ListBox1"
runat="server"
DataSourceID="SqlDataSource1"
DataTextField="LastName">
</asp:ListBox></p>

</form>
</body>
</html>

For more information about using parameters with the SqlDataSource control, see
Using Parameters with the SqlDataSource Control. For more general information about using data source parameters, see
Using Parameters with Data Source Controls.
Specifying How Data Is Returned
The SqlDataSource control's DataSourceMode property determines how data is maintained by the SqlDataSource control.
By default, the DataSourceMode property is set to DataSet, which means that the result set returned from the database is
stored in server memory by the SqlDataSource control. When the SqlDataSource control retrieves data in DataSet mode,
associated data-bound controls such as GridView and DetailsView can offer rich data display capabilities such as automatic
sorting and paging.
Alternatively, you can set the DataSourceMode property to DataReader, which means that the result set is not stored in
memory. For scenarios where you do not need to keep a result set in memory on the server, use DataReader mode.
The following code example demonstrates how to set the DataSourceMode property of the SqlDataSource control to
DataReader for a scenario that requires no sorting, paging, or filtering.
VB
<%@ Page language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1


/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">
<asp:SqlDataSource
id="SqlDataSource1"
runat="server"
DataSourceMode="DataReader"
ConnectionString="<%$ ConnectionStrings:MyNorthwind%>"
SelectCommand="SELECT LastName FROM Employees">
</asp:SqlDataSource>

<asp:ListBox
id="ListBox1"
runat="server"
DataTextField="LastName"
DataSourceID="SqlDataSource1">
</asp:ListBox>

</form>
</body>
</html>

C#
<%@ Page language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1


/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">
<asp:SqlDataSource
id="SqlDataSource1"
runat="server"
DataSourceMode="DataReader"
ConnectionString="<%$ ConnectionStrings:MyNorthwind%>"
SelectCommand="SELECT LastName FROM Employees">
</asp:SqlDataSource>

<asp:ListBox
id="ListBox1"
runat="server"
DataTextField="LastName"
DataSourceID="SqlDataSource1">
</asp:ListBox>
</form>
</body>
</html>

J#
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">
<asp:SqlDataSource
id="SqlDataSource1"
runat="server"
DataSourceMode="DataReader"
ConnectionString="Data Source=localhost;Integrated Security=SSPI;Initial Catalog=
Northwind;"
SelectCommand="SELECT LastName FROM Employees">
</asp:SqlDataSource>

<asp:ListBox
id="ListBox1"
runat="server"
DataTextField="LastName"
DataSourceID="SqlDataSource1">
</asp:ListBox>

</form>
</body>
</html>

Adding Custom Processing Using SqlDataSource Control Events


The SqlDataSource control exposes events that you can handle to run your own code before and after the control performs a
data retrieval operation.
The SqlDataSource control raises the Selecting event before it calls the Select method to execute the SQL query set in the
SelectCommand property. You can handle the Selecting event to examine the SQL query before it is run and to validate
parameters that are contained in the SelectParameters collection or to perform any additional work prior to retrieving data.
For example, if you are using a FormParameter with the SqlDataSource control, you might handle the Selecting event to
validate the value of the parameter before retrieving data. (The FormParameter takes the value posted in an HTML element
and submits it to the database without any validation.) If the value is not acceptable, you can cancel the query by setting the
Cancel property of the SqlDataSourceSelectingEventArgs object to true.
The SqlDataSource control raises the Selected event after the data has been retrieved. You can handle the Selected event to
determine whether an exception was thrown during the database operation or to examine any values returned by the data
operation.
Displaying the Data
To display data on an ASP.NET page, you use a data-bound control such as a GridView, DetailsView, or FormView control, or
controls such as the ListBox or DropDownList controls. The data-bound control acts as a consumer of the data that the
SqlDataSource control retrieves. Set the data-bound control's DataSourceID property to the ID of the SqlDataSource
control. When the page is rendered, the SqlDataSource control retrieves the data and makes it available to the data-bound
control, which in turn displays the data. For more information about data-bound controls and how to use them with data
source controls to display data, see ASP.NET Data-Bound Web Server Controls Overview.
The following code example demonstrates how to display the results of the query using a GridView control.
VB
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">

<asp:SqlDataSource
id="SqlDataSource1"
runat="server"
DataSourceMode="DataReader"
ConnectionString="<%$ ConnectionStrings:MyNorthwind%>"
SelectCommand="SELECT FirstName, LastName, Title FROM Employees">
</asp:SqlDataSource>

<asp:GridView
id="GridView1"
runat="server"
DataSourceID="SqlDataSource1">
</asp:GridView>

</form>
</body>
</html>

C#
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">

<asp:SqlDataSource
id="SqlDataSource1"
runat="server"
DataSourceMode="DataReader"
ConnectionString="<%$ ConnectionStrings:MyNorthwind%>"
SelectCommand="SELECT FirstName, LastName, Title FROM Employees">
</asp:SqlDataSource>

<asp:GridView
id="GridView1"
runat="server"
DataSourceID="SqlDataSource1">
</asp:GridView>

</form>
</body>
</html>

J#
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">

<asp:SqlDataSource
id="SqlDataSource1"
runat="server"
DataSourceMode="DataReader"
ConnectionString="Data Source=localhost;Integrated Security=SSPI;Initial Catalog=
Northwind;"
SelectCommand="SELECT FirstName, LastName, Title FROM Employees">
</asp:SqlDataSource>

<asp:GridView
id="GridView1"
runat="server"
DataSourceID="SqlDataSource1">
</asp:GridView>

</form>
</body>
</html>

See Also
Other Resources
SqlDataSource Web Server Control
Visual Web Developer

How to: Enable Filtering for SqlDataSource Controls (Visual


Studio)
The SqlDataSource control allows you to filter (sort or select) the results of a query without rerunning the query. By adding
filtering to a SqlDataSource control, you can change what data is made available by the SqlDataSource control after a query
has been run, without returning to the database.
This topic shows you how to enable filtering for a SqlDataSource control. Data-bound controls that are bound to the
SqlDataSource control, such as a GridView control, will show only the filtered results.
To use filtering, you must set the SqlDataSource control to return information in a dataset and to cache its results. You can
then specify a filter expression that is applied as a RowFilter property to the DataView object that underlies the SqlDataSource
control.
The filtering can also include parameters that are based on the values of another control, cookies, sessions, or query strings.
For example, if a DropDownList control contains city names, you can use the selected city as your filtering parameter.
Note
Creating a filter expression with parameters is not the same as creating a parameterized SelectCommand property and specif
ying SelectParameters property values. A parameterized filter applies different views of the data to a cached dataset. A param
eterized select command performs a query against the data source.

To enable filtering for a SqlDataSource control


1. In Design view, from the Data tab of the Toolbox, drag a SqlDataSource control onto the page.
2. Right-click the control and click Show Smart Tag.
3. In the SqlDataSource Tasks menu, click Configure Data Source.
4. Follow the Configure Data Source wizard to create or choose a connection and to create a query to return data from the
data source. For details, see Walkthrough: Basic Data Access in Web Pages.
5. In the Properties window, set the DataSourceMode property to DataSet.
6. Set the EnableCaching property to true.
7. Set the CacheDuration property to the number of seconds that you want the data to be cached. The number you choose
depends on your application.
8. Set the FilterExpression property to an expression specifying the data to return, as shown in the following example
expression.

city = 'Seattle'

For information about the syntax of filter expressions, see RowFilter.


Filtering with Parameters
At times, you might want to filter the results of a query based on values that are known only at run time. You can create filter
expressions that include parameter placeholders, and then define filter parameters to fill the placeholders. The filter parameters
can get their values from controls, query strings, cookies, session variables, profile properties, or Form property values.
To filter a SqlDataSource control using parameters
1. In Design view, click the SqlDataSource control to which you want to add filtering parameters.
2. In the Properties window, set the FilterExpression property to an expression that includes a placeholder for the filter
parameter value. The placeholders use the syntax {n}, where n indicates the sequential order of the parameter.
The following examples show parameterized filter expressions. The second expression includes multiple parameter
placeholders.
category = '{0}
state = '{0}' AND city = '{1}'

For information about the syntax of filter expressions, see RowFilter.


3. In the Properties window, click the ellipsis button next to FilterParameter.
4. In the Parameter Collection Editor dialog box, click Add Parameter.
5. In the Name field, type the name that you want to assign to the parameter.
The Name property for the parameter is required. However, parameters are matched to placeholders in sequential order,
not by name.
Note
To edit the name after creating the parameter, click the name and then press F2 to put the name into editing mode.

6. In the Parameter source drop down list, select the appropriate source for the parameter, such as a control on the Web
page.
Depending on which parameter source that you have selected, the dialog box changes to include a way to specify the ID
of the property value.
7. If you selected Control as the parameter source, in the ControlID drop-down list, select the ID for the control that will
provide the value for the parameter. Optionally, add a default value for the parameter; and then click OK.
8. Repeat steps 4 through 7 for each parameter that you want to create.
9. When you are finished creating parameters, click OK to close the Parameter Collection Editor dialog box.

See Also
Tasks
How to: Connect to a SQL Server Database Using the SqlDataSource Control (Visual Studio)
Walkthrough: Basic Data Access in Web Pages
Concepts
Caching Data Using Data Source Controls
Visual Web Developer

Learning More — SqlDataSource Web Server Control (Visual


Studio)
The topics listed below include step-by-step instructions of involved scenarios that use the SqlDataSource control to represent
an SQL data source to data-bound controls.
In This Section
Using Parameters with the SqlDataSource Control
Modifying Data using the SqlDataSource Control
Caching Data with the SqlDataSource Control
See Also
Other Resources
SqlDataSource Web Server Control (Visual Studio)
Data Toolbox Controls
ASP.NET Data Access (Visual Studio)
ASP.NET

Using Parameters with the SqlDataSource Control


SQL statements and stored procedures often include parameters that are evaluated at run time. An SQL statement written with
parameters is referred to as a parameterized SQL statement.
When using the SqlDataSource control, you can specify SQL queries and statements that use parameters. This helps make your
data-binding scenarios more flexible by reading and writing database information based on values that are evaluated at run
time. You can get parameter values from various sources, including ASP.NET application variables, user identities, and user-
selected values. You can use parameters to supply search criteria for data retrieval; to supply values to be inserted, updated, or
deleted in a data store; and to supply values for sorting, paging, and filtering.
Using Parameters
Like all data source controls, the SqlDataSource control accepts input parameters at run time and manages them in
parameter collections. Each data operation has a related parameter collection. For select operations, you can use the
SelectParameters collection; for updates, you can use the UpdateParameters collection; and so on.
You can specify a name, type, direction, and default value for each parameter. Parameters that get values from a specific object,
such as a control, session variable, or the user profile, require you to set additional properties. For example, a ControlParameter
requires that you set the ControlID to identify the control to take the parameter value from, and set the PropertyName
property to specify the property that contains the parameter value. For more information, see
Using Parameters with Data Source Controls.
The SqlDataSource control will also automatically create parameters based on values passed by a data-bound control (such
as a GridView or FormView control) that supports automatic update, insert, and delete operations. For more information, see
How a Data Source Control Creates Parameters for Data-bound Fields.
Specifying Parameters in Commands
When you use the SqlDataSource control, you can set the control's command properties to parameterized SQL statements or
to the name of a stored procedure. If you specify a stored procedure for a command, you must specify that the command type
of the command is StoredProcedure.
Parameter Names
The SqlDataSource control adds the value of the ParameterPrefix property to the beginning of all parameter names. (The
default prefix is "@".)
If a data-bound control such as a GridView control is bound to the SqlDataSource control, during an update or delete
operation the data-bound control passes both current and original record values to the SqlDataSource control. The current
values are passed in the Values dictionary. The original values are passed in the Keys or OldValues dictionaries. The contents
of these dictionaries are appended to the underlying DbCommand object's Parameters collection for a given data operation.
In the SqlDataSource control's SQL commands, you use a naming convention to match parameter placeholders to the old
values passed into the command. You establish the format of the placeholder name by setting the SqlDataSource control's
OldValuesParameterFormatString property. Set the OldValuesParameterFormatString property to a string that includes "
{0}" as a placeholder for the name of the field. For example, if you set the OldValuesParameterFormatString property to
"old_{0}", the names of the original-value parameters will resolve to the field name prefixed with "@old_". Consider an update
operation that involves a field named LastModifiedDate. The current value for the field is passed in the Values dictionary and
the original value for the field is passed in the OldValues dictionary. A parameter named @LastModifiedDate is created to
pass the current value and a parameter named @old_LastModifiedDate is created to pass the original value. You can then
include both parameters in an SQL statement to differentiate between the current and original values for the field, as shown in
the following example:

UPDATE Table1 SET LastModifiedDate = @LastModifiedDate


WHERE Key = @Key AND LastModifiedDate = @old_LastModifiedDate

The ability to separate current and original values in a command is essential when performing optimistic concurrency checks
or working with a data source where the primary key can be modified.
For more information on the dictionaries passed by a data-bound control, see
How a Data Source Control Creates Parameters for Data-bound Fields.
Using Parameters with the SqlClient Provider
By default, the SqlDataSource control uses the System.Data.SqlClient data provider to work with SQL Server as the data
source. The System.Data.SqlClient provider supports named parameters as placeholders, as shown in the following example:

SELECT * FROM Employees WHERE LastName = @LastName


AND FirstName = @FirstName

With named parameters, the order in which the parameters is specified in the command's parameters collection is not
important. However, you must ensure that the parameter names that you use in your SQL command correspond to the names
of the parameters in the associated collection.
The following example shows how to use named parameters in an SQL command for a SqlDataSource control that uses the
System.Data.SqlClient provider.
VB
<asp:sqlDataSource ID="EmployeeDetailsSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName, FirstName FROM Employees WHERE EmployeeID = @
EmpID"
InsertCommand="INSERT INTO Employees(LastName, FirstName) VALUES (@LastName, @FirstName);
SELECT @EmpID = SCOPE_IDENTITY()"
UpdateCommand="UPDATE Employees SET LastName=@LastName, FirstName=@FirstName
WHERE EmployeeID=@EmployeeID"
DeleteCommand="DELETE Employees WHERE EmployeeID=@EmployeeID"

ConnectionString="<%$ ConnectionStrings:NorthwindConnection %>"


OnInserted="EmployeeDetailsSqlDataSource_OnInserted"
RunAt="server">

<SelectParameters>
<asp:Parameter Name="EmpID" Type="Int32" DefaultValue="0" />
</SelectParameters>

<InsertParameters>
<asp:Parameter Name="EmpID" Direction="Output" Type="Int32" DefaultValue="0" />
</InsertParameters>

</asp:sqlDataSource>

C#
<asp:sqlDataSource ID="EmployeeDetailsSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName, FirstName FROM Employees WHERE EmployeeID = @
EmpID"

InsertCommand="INSERT INTO Employees(LastName, FirstName) VALUES (@LastName, @FirstName);


SELECT @EmpID = SCOPE_IDENTITY()"
UpdateCommand="UPDATE Employees SET LastName=@LastName, FirstName=@FirstName
WHERE EmployeeID=@EmployeeID"
DeleteCommand="DELETE Employees WHERE EmployeeID=@EmployeeID"

ConnectionString="<%$ ConnectionStrings:NorthwindConnection %>"


OnInserted="EmployeeDetailsSqlDataSource_OnInserted"
RunAt="server">
<SelectParameters>
<asp:Parameter Name="EmpID" Type="Int32" DefaultValue="0" />
</SelectParameters>

<InsertParameters>
<asp:Parameter Name="EmpID" Direction="Output" Type="Int32" DefaultValue="0" />
</InsertParameters>
</asp:sqlDataSource>
Using Parameters with the OleDb and Odbc Providers
If you are connecting to an OLE DB or ODBC data source, you can configure the SqlDataSource control to use the
System.Data.OleDb or System.Data.Odbc provider to work with your data source, respectively. The System.Data.OleDb and
System.Data.Odbc providers support only positional parameters identified by the "?" character, as shown in the following
example:

SELECT * FROM Employees WHERE LastName = ? AND FirstName = ?

When you use the System.Data.OleDb and System.Data.Odbc providers with parameterized SQL statements, the order in
which you specify the parameter placeholders must match the order of the parameters in the related parameter collection. You
can control the order of parameters by explicitly specifying them in the collection for the related data operation, such as the
UpdateParameters collection for the related UpdateCommand. When you explicitly create a parameter collection for
parameters that are automatically created from values passed by a data-bound control, the explicitly created parameters
overwrite any parameters that are automatically generated. This way you ensure that the parameters are passed in the order
that you want. If you call a stored procedure that returns a value, you must specify a parameter with a Direction value of
ReturnValue as the first parameter in the command parameters collection.
Note
By default, parameters based on bound fields from a data-bound control are added to the command from the parameter dict
ionaries in the following order: Values, Keys, OldValues. For delete operations, only the Keys dictionary is used. For insert o
perations, only the Values dictionary is used. For more information on the dictionaries passed by a data-bound control, see
How a Data Source Control Creates Parameters for Data-bound Fields.

The following example shows how to specify parameters for a SqlDataSource control that uses the System.Data.OleDb
provider. Parameters are explicitly specified to ensure the order of the parameters in the collection matches the order of the
placeholders in the SQL statements.
VB
<Fields>
<asp:BoundField DataField="EmployeeID" HeaderText="Employee ID" InsertVisible="False" Rea
dOnly="true"/>
<asp:BoundField DataField="FirstName" HeaderText="First Name"/>
<asp:BoundField DataField="LastName" HeaderText="Last Name"/>
<asp:TemplateField HeaderText="Birth Date">
<ItemTemplate>
<asp:Label ID="BirthDateLabel" Runat="Server"
Text='<%# Eval("BirthDate", "{0:d}") %>' />
</ItemTemplate>
<InsertItemTemplate>
<asp:Calendar ID="InsertBirthDateCalendar" Runat="Server"
SelectedDate='<%# Bind("BirthDate") %>' />
</InsertItemTemplate>
<EditItemTemplate>
<asp:Calendar ID="EditBirthDateCalendar" Runat="Server"
VisibleDate='<%# Eval("BirthDate") %>'
SelectedDate='<%# Bind("BirthDate") %>' />
</EditItemTemplate>
</asp:TemplateField>
</Fields>

C#
<Fields>
<asp:BoundField DataField="EmployeeID" HeaderText="Employee ID" InsertVisible="False" Rea
dOnly="true"/>
<asp:BoundField DataField="FirstName" HeaderText="First Name"/>
<asp:BoundField DataField="LastName" HeaderText="Last Name"/>
<asp:TemplateField HeaderText="Birth Date">
<ItemTemplate>
<asp:Label ID="BirthDateLabel" Runat="Server"
Text='<%# Eval("BirthDate", "{0:d}") %>' />
</ItemTemplate>
<InsertItemTemplate>
<asp:Calendar ID="InsertBirthDateCalendar" Runat="Server"
SelectedDate='<%# Bind("BirthDate") %>' />
</InsertItemTemplate>
<EditItemTemplate>
<asp:Calendar ID="EditBirthDateCalendar" Runat="Server"
VisibleDate='<%# Eval("BirthDate") %>'
SelectedDate='<%# Bind("BirthDate") %>' />
</EditItemTemplate>
</asp:TemplateField>
</Fields>

See Also
Reference
SqlDataSource
AccessDataSource
Concepts
Selecting Data Using the SqlDataSource Control
Modifying Data using the SqlDataSource Control
ASP.NET

Modifying Data using the SqlDataSource Control


You can use the SqlDataSource control to modify data in a database. The most common way to use the SqlDataSource
control in update scenarios is to retrieve data and display it using a data-bound Web server control, such as a GridView,
DetailsView, or FormView control. You configure the data-bound control and the SqlDataSource to update the data. Most
data-bound controls allow you to configure them to support insert, update, and delete operations, and they pass the values to
be updated to the data source control. The data source control then submits the updated values to the database using an SQL
statement or stored procedure.
The SqlDataSource control is designed to update data one record at a time. If you need to perform batch updates, you must
write explicit looping logic in your ASP.NET application.
The Basics
To modify data in a database using the SqlDataSource control, you need to set at least the following properties:
ProviderName Set to the name of the ADO.NET provider that represents the database you are working with.
ConnectionString Set to a connection string that works for your database.
SqlDataSource command properties Set to SQL statements that modify data in the database.
The following sections describe these properties in more detail.
Provider Name
Set the ProviderName property to the name of the ADO.NET provider for the type of database in which your data is stored,
which can include the following:
If you are working with Microsoft SQL Server, set the ProviderName property to "System.Data.SqlClient". This is the
default provider if you do not specify a different one.
If you are working with an Oracle database, set the ProviderName property to "System.Data.OracleClient".
If you are working with an OLE DB data source, set the ProviderName property to "System.Data.OleDb".
If you are working with an ODBC data source, set the ProviderName property to "System.Data.Odbc".
Connection String
Set the ConnectionString property to connect to a specific database. It is recommended that you store connection strings in
the ConnectionStrings element in the application's configuration file. You can then reference the stored connection strings
using the <%$ ConnectionStrings:connectionStringName %> syntax in control markup. The connection string must be a valid
connection string for the specified ProviderName.
Commands
The SqlDataSource control has three command properties that can contain SQL statement that modifies data: the
InsertCommand, UpdateCommand, and DeleteCommand properties. The command properties can be set to an SQL statement
or to the name of a stored procedure if your data source supports stored procedures. The actual syntax of the SQL statement
depends on the schema of your data and on which database you are using. The statement can include parameters if the data
source supports them.
Note
The statement that you set for the command property is the same statement that you set for the CommandText property of a
n ADO.NET IDbCommand object when writing ADO.NET data-manipulation code.

The SQL statement in the UpdateCommand property is executed every time the Update method is called. The Update
method is called implicitly by data-bound controls when a user clicks an Update button in a GridView, FormView, or
DetailsView control. You can also call this method explicitly from your own code. The SqlDataSource control's Insert and
Delete methods work similarly.
The following code example shows how you can use a SqlDataSource control to insert, update, and delete records using a
FormView control. The sample connects to the SQL Server Northwind database.
VB

<%@ Page language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">

Sub EmployeesGridView_OnSelectedIndexChanged(sender As Object, e As EventArgs)


EmployeeDetailsSqlDataSource.SelectParameters("EmpID").DefaultValue = _
EmployeesGridView.SelectedValue.ToString()
EmployeeFormView.DataBind()
End Sub
Sub EmployeeFormView_ItemUpdated(sender As Object, e As FormViewUpdatedEventArgs)
EmployeesGridView.DataBind()
End Sub
Sub EmployeeFormView_ItemDeleted(sender As Object, e As FormViewDeletedEventArgs)
EmployeesGridView.DataBind()
End Sub

Sub EmployeeDetailsSqlDataSource_OnInserted(sender As Object, e As SqlDataSourceStatusEve


ntArgs)
Dim command As System.Data.Common.DbCommand = e.Command

EmployeeDetailsSqlDataSource.SelectParameters("EmpID").DefaultValue = _
command.Parameters("@EmpID").Value.ToString()
EmployeesGridView.DataBind()
EmployeeFormView.DataBind()
End Sub

</script>

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>FormView Example</title>
</head>
<body>
<form id="form1" runat="server">

<h3>FormView Example</h3>
<table cellspacing="10">

<tr>
<td>
<asp:GridView ID="EmployeesGridView"
DataSourceID="EmployeesSqlDataSource"
AutoGenerateColumns="false"
DataKeyNames="EmployeeID"
OnSelectedIndexChanged="EmployeesGridView_OnSelectedIndexChanged"
RunAt="Server">

<HeaderStyle backcolor="Navy"
forecolor="White" />

<Columns>
<asp:ButtonField Text="Details..."
HeaderText="Show<BR>Details"
CommandName="Select"/>

<asp:BoundField DataField="EmployeeID" HeaderText="Employee ID"/>


<asp:BoundField DataField="LastName" HeaderText="Last Name"/>
<asp:BoundField DataField="FirstName" HeaderText="First Name"/>
</Columns>

</asp:GridView>

</td>

<td valign="top">
<asp:FormView ID="EmployeeFormView"
DataSourceID="EmployeeDetailsSqlDataSource"
DataKeyNames="EmployeeID"
Gridlines="Both"
OnItemUpdated="EmployeeFormView_ItemUpdated"
OnItemDeleted="EmployeeFormView_ItemDeleted"
RunAt="server">
<HeaderStyle backcolor="Navy"
forecolor="White"/>

<RowStyle backcolor="White"/>

<EditRowStyle backcolor="LightCyan"/>
<ItemTemplate>
<table>
<tr><td align="right"><b>Employee ID:</b></td><td><%# Eval("EmployeeID"
) %></td></tr>
<tr><td align="right"><b>First Name:</b></td> <td><%# Eval("FirstName")
%></td></tr>
<tr><td align="right"><b>Last Name:</b></td> <td><%# Eval("LastName")
%></td></tr>
<tr>
<td colspan="2">
<asp:LinkButton ID="EditButton"
Text="Edit"
CommandName="Edit"
RunAt="server"/>
&nbsp;
<asp:LinkButton ID="NewButton"
Text="New"
CommandName="New"
RunAt="server"/>
&nbsp;
<asp:LinkButton ID="DeleteButton"
Text="Delete"
CommandName="Delete"
RunAt="server"/>
</td>
</tr>
</table>
</ItemTemplate>
<EditItemTemplate>
<table>
<tr><td align="right"><b>Employee ID:</b></td><td><%# Eval("EmployeeID"
) %></td></tr>

<tr><td align="right"><b>First Name:</b></td>


<td><asp:TextBox ID="EditFirstNameTextBox"
Text='<%# Bind("FirstName") %>'
RunAt="Server" /></td></tr>

<tr><td align="right"><b>Last Name:</b></td>


<td><asp:TextBox ID="EditLastNameTextBox"
Text='<%# Bind("LastName") %>'
RunAt="Server" /></td></tr>
<tr>
<td colspan="2">
<asp:LinkButton ID="UpdateButton"
Text="Update"
CommandName="Update"
RunAt="server"/>
&nbsp;
<asp:LinkButton ID="CancelUpdateButton"
Text="Cancel"
CommandName="Cancel"
RunAt="server"/>
</td>
</tr>
</table>
</EditItemTemplate>

<InsertItemTemplate>
<table>
<tr><td align="right"><b>First Name:</b></td>
<td><asp:TextBox ID="InsertFirstNameTextBox"
Text='<%# Bind("FirstName") %>'
RunAt="Server" /></td></tr>

<tr><td align="right"><b>Last Name:</b></td>


<td><asp:TextBox ID="InsertLastNameTextBox"
Text='<%# Bind("LastName") %>'
RunAt="Server" /></td></tr>
<tr>
<td colspan="2">
<asp:LinkButton ID="InsertButton"
Text="Insert"
CommandName="Insert"
RunAt="server"/>
&nbsp;
<asp:LinkButton ID="CancelInsertButton"
Text="Cancel"
CommandName="Cancel"
RunAt="server"/>
</td>
</tr>
</table>
</InsertItemTemplate>
</asp:FormView>

</td>

</tr>

</table>

<asp:sqlDataSource ID="EmployeesSqlDataSource"
selectCommand="SELECT EmployeeID, FirstName, LastName FROM Employees"
connectionstring="<%$ ConnectionStrings:NorthwindConnection %>"
RunAt="server">
</asp:sqlDataSource>

<asp:sqlDataSource ID="EmployeeDetailsSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName, FirstName FROM Employees WHERE Employ
eeID = @EmpID"

InsertCommand="INSERT INTO Employees(LastName, FirstName) VALUES (@LastName, @Fir


stName);
SELECT @EmpID = SCOPE_IDENTITY()"
UpdateCommand="UPDATE Employees SET LastName=@LastName, FirstName=@FirstName
WHERE EmployeeID=@EmployeeID"
DeleteCommand="DELETE Employees WHERE EmployeeID=@EmployeeID"
ConnectionString="<%$ ConnectionStrings:NorthwindConnection %>"
OnInserted="EmployeeDetailsSqlDataSource_OnInserted"
RunAt="server">

<SelectParameters>
<asp:Parameter Name="EmpID" Type="Int32" DefaultValue="0" />
</SelectParameters>

<InsertParameters>
<asp:Parameter Name="EmpID" Direction="Output" Type="Int32" DefaultValue="0" />
</InsertParameters>

</asp:sqlDataSource>

</form>
</body>
</html>

C#

<%@ Page language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
void EmployeesGridView_OnSelectedIndexChanged(Object sender, EventArgs e)
{
EmployeeDetailsSqlDataSource.SelectParameters["EmpID"].DefaultValue =
EmployeesGridView.SelectedValue.ToString();
EmployeeFormView.DataBind();
}

void EmployeeFormView_ItemUpdated(Object sender, FormViewUpdatedEventArgs e)


{
EmployeesGridView.DataBind();
}

void EmployeeFormView_ItemDeleted(Object sender, FormViewDeletedEventArgs e)


{
EmployeesGridView.DataBind();
}
void EmployeeDetailsSqlDataSource_OnInserted(Object sender, SqlDataSourceStatusEventArgs
e)
{
System.Data.Common.DbCommand command = e.Command;

EmployeeDetailsSqlDataSource.SelectParameters["EmpID"].DefaultValue =
command.Parameters["@EmpID"].Value.ToString();

EmployeesGridView.DataBind();
EmployeeFormView.DataBind();
}

</script>

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>FormView Example</title>
</head>
<body>
<form id="form1" runat="server">
<h3>FormView Example</h3>

<table cellspacing="10">

<tr>
<td>
<asp:GridView ID="EmployeesGridView"
DataSourceID="EmployeesSqlDataSource"
AutoGenerateColumns="false"
DataKeyNames="EmployeeID"
OnSelectedIndexChanged="EmployeesGridView_OnSelectedIndexChanged"
RunAt="Server">

<HeaderStyle backcolor="Navy"
forecolor="White" />

<Columns>

<asp:ButtonField Text="Details..."
HeaderText="Show<BR>Details"
CommandName="Select"/>

<asp:BoundField DataField="EmployeeID" HeaderText="Employee ID"/>


<asp:BoundField DataField="LastName" HeaderText="Last Name"/>

<asp:BoundField DataField="FirstName" HeaderText="First Name"/>

</Columns>

</asp:GridView>
</td>

<td valign="top">

<asp:FormView ID="EmployeeFormView"
DataSourceID="EmployeeDetailsSqlDataSource"
DataKeyNames="EmployeeID"
Gridlines="Both"
OnItemUpdated="EmployeeFormView_ItemUpdated"
OnItemDeleted="EmployeeFormView_ItemDeleted"
RunAt="server">

<HeaderStyle backcolor="Navy"
forecolor="White"/>

<RowStyle backcolor="White"/>

<EditRowStyle backcolor="LightCyan"/>

<ItemTemplate>
<table>
<tr><td align="right"><b>Employee ID:</b></td><td><%# Eval("EmployeeID"
) %></td></tr>
<tr><td align="right"><b>First Name:</b></td> <td><%# Eval("FirstName")
%></td></tr>
<tr><td align="right"><b>Last Name:</b></td> <td><%# Eval("LastName")
%></td></tr>
<tr>
<td colspan="2">
<asp:LinkButton ID="EditButton"
Text="Edit"
CommandName="Edit"
RunAt="server"/>
&nbsp;
<asp:LinkButton ID="NewButton"
Text="New"
CommandName="New"
RunAt="server"/>
&nbsp;
<asp:LinkButton ID="DeleteButton"
Text="Delete"
CommandName="Delete"
RunAt="server"/>
</td>
</tr>
</table>
</ItemTemplate>

<EditItemTemplate>
<table>
<tr><td align="right"><b>Employee ID:</b></td><td><%# Eval("EmployeeID"
) %></td></tr>

<tr><td align="right"><b>First Name:</b></td>


<td><asp:TextBox ID="EditFirstNameTextBox"
Text='<%# Bind("FirstName") %>'
RunAt="Server" /></td></tr>
<tr><td align="right"><b>Last Name:</b></td>
<td><asp:TextBox ID="EditLastNameTextBox"
Text='<%# Bind("LastName") %>'
RunAt="Server" /></td></tr>
<tr>
<td colspan="2">
<asp:LinkButton ID="UpdateButton"
Text="Update"
CommandName="Update"
RunAt="server"/>
&nbsp;
<asp:LinkButton ID="CancelUpdateButton"
Text="Cancel"
CommandName="Cancel"
RunAt="server"/>
</td>
</tr>
</table>
</EditItemTemplate>

<InsertItemTemplate>
<table>
<tr><td align="right"><b>First Name:</b></td>
<td><asp:TextBox ID="InsertFirstNameTextBox"
Text='<%# Bind("FirstName") %>'
RunAt="Server" /></td></tr>

<tr><td align="right"><b>Last Name:</b></td>


<td><asp:TextBox ID="InsertLastNameTextBox"
Text='<%# Bind("LastName") %>'
RunAt="Server" /></td></tr>
<tr>
<td colspan="2">
<asp:LinkButton ID="InsertButton"
Text="Insert"
CommandName="Insert"
RunAt="server"/>
&nbsp;
<asp:LinkButton ID="CancelInsertButton"
Text="Cancel"
CommandName="Cancel"
RunAt="server"/>
</td>
</tr>
</table>
</InsertItemTemplate>
</asp:FormView>

</td>

</tr>

</table>

<asp:sqlDataSource ID="EmployeesSqlDataSource"
selectCommand="SELECT EmployeeID, FirstName, LastName FROM Employees"
connectionstring="<%$ ConnectionStrings:NorthwindConnection %>"
RunAt="server">
</asp:sqlDataSource>

<asp:sqlDataSource ID="EmployeeDetailsSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName, FirstName FROM Employees WHERE Employ
eeID = @EmpID"

InsertCommand="INSERT INTO Employees(LastName, FirstName) VALUES (@LastName, @Fir


stName);
SELECT @EmpID = SCOPE_IDENTITY()"
UpdateCommand="UPDATE Employees SET LastName=@LastName, FirstName=@FirstName
WHERE EmployeeID=@EmployeeID"
DeleteCommand="DELETE Employees WHERE EmployeeID=@EmployeeID"

ConnectionString="<%$ ConnectionStrings:NorthwindConnection %>"


OnInserted="EmployeeDetailsSqlDataSource_OnInserted"
RunAt="server">

<SelectParameters>
<asp:Parameter Name="EmpID" Type="Int32" DefaultValue="0" />
</SelectParameters>

<InsertParameters>
<asp:Parameter Name="EmpID" Direction="Output" Type="Int32" DefaultValue="0" />
</InsertParameters>

</asp:sqlDataSource>

</form>
</body>
</html>

The command can be the name of a stored procedure if the database you are working with supports stored procedures. If you
use stored procedures to update data, you must set the UpdateCommandType property to StoredProcedure.
Parameters
Parameters are used to send values for insert, update, and delete operations to the data source. Parameter names and values
are based on data fields bound to a control or alternatively on parameter objects that you define explicitly. Parameters from a
data-bound control include both values for the data operation and for key values to identify a specific row, as defined by the
DataKeyNames property of the bound control.
You can create explicit Parameter definitions to specify parameter order, parameter type, and parameter direction as well as
additional parameters other than those based on fields bound to a control. An example of this would be an output parameter
that returns a value automatically generated by the data source such as an auto-incrementing primary key or a date-time
stamp.
Note
Explicitly specifying parameters is especially important when working with the System.Data.OleDb and System.Data.Odbc pr
oviders that do not support named parameters in SQL statements and instead use the '?' placeholder to specify a parameter.
In those cases you should define parameters in the order specified in the associated SQL statement.
For more information and for examples of using parameters, see Using Parameters with the SqlDataSource Control and
How a Data Source Control Creates Parameters for Data-bound Fields.
Events
The SqlDataSource control raises events that you can handle to run your own code before and after the control performs an
insert, update, or delete operation.
The SqlDataSource control raises the Inserting, Updating, or Deleting events before it executes the SQL statement for the
corresponding command property. You can add a handler for these events to manipulate, reorder, or validate parameters for a
statement before it is executed, as well as to cancel the command. For example, if you are using a QueryStringParameter with
the SqlDataSource control, you might handle the Updating event to validate the value of the parameter before performing
an update. (By default, the QueryStringParameter takes the value of a query string variable and submits it to the database
without any validation.) If the value is not acceptable, you can cancel the update by setting the Cancel property of the event's
SqlDataSourceCommandEventArgs object to true.
The SqlDataSource control raises the Inserted, Updated, or Deleted events after the database operation completes. You can
handle these events to determine whether an exception was thrown during the database operation, to learn how many records
were affected by the operation, or to examine any output values the database operation returns.
For example, the following code example uses the Updating and Updated events to execute the UpdateCommand within a
transaction.
VB
<%@Page Language="VB" %>
<%@Import Namespace="System.Data" %>
<%@Import Namespace="System.Data.Common" %>
<%@Import Namespace="System.Diagnostics" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">

<script runat="server">

Sub On_Click(ByVal source As Object, ByVal e As EventArgs)


SqlDataSource1.Update()
End Sub 'On_Click

Sub On_Sql_Updating(ByVal source As Object, ByVal e As SqlDataSourceCommandEventArgs)


Dim command as DbCommand
Dim connection as DbConnection
Dim transaction as DbTransaction

command = e.Command
connection = command.Connection
connection.Open()
transaction = connection.BeginTransaction()
command.Transaction = transaction

End Sub 'On_Sql_Updating

Sub On_Sql_Updated(ByVal source As Object, ByVal e As SqlDataSourceStatusEventArgs)

Dim command As DbCommand


Dim transaction As DbTransaction

command = e.Command
transaction = command.Transaction
' In this code example the OtherProcessSucceeded variable represents
' the outcome of some other process that occurs whenever the data is
' updated, and must succeed for the data change to be committed. For
' simplicity, we set this value to true.
Dim OtherProcessSucceeded as Boolean = True

If (OtherProcessSucceeded) Then
transaction.Commit()
Label2.Text="The record was updated successfully!"
Else
transaction.Rollback()
Label2.Text="The record was not updated."
End If
End Sub ' On_Sql_Updated
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">
<asp:SqlDataSource
id="SqlDataSource1"
runat="server"
ConnectionString="<%$ ConnectionStrings:MyNorthwind%>"
SelectCommand="SELECT EmployeeID, LastName, Address FROM Employees"
UpdateCommand="UPDATE Employees SET Address=@Address WHERE EmployeeID=@EmployeeID
"
OnUpdating="On_Sql_Updating"
OnUpdated ="On_Sql_Updated">
<UpdateParameters>
<asp:ControlParameter Name="Address" ControlId="TextBox1" PropertyName="Text"
/>
<asp:ControlParameter Name="EmployeeID" ControlId="DropDownList1" PropertyNam
e="SelectedValue"/>
</UpdateParameters>
</asp:SqlDataSource>

<asp:DropDownList
id="DropDownList1"
runat="server"
DataTextField="LastName"
DataValueField="EmployeeID"
DataSourceID="SqlDataSource1">
</asp:DropDownList>

<br />
<asp:Label id="Label1" runat="server" Text="Enter a new address for the selected user
."
AssociatedControlID="TextBox1" />
<asp:TextBox id="TextBox1" runat="server" />
<asp:Button id="Submit" runat="server" Text="Submit" OnClick="On_Click" />

<br /><asp:Label id="Label2" runat="server" Text="" />

</form>
</body>
</html>

C#
<%@Page Language="C#" %>
<%@Import Namespace="System.Data" %>
<%@Import Namespace="System.Data.Common" %>
<%@Import Namespace="System.Data.SqlClient" %>
<%@Import Namespace="System.Diagnostics" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">

<script runat="server">

private void On_Click(Object source, EventArgs e) {


SqlDataSource1.Update();
}

private void OnSqlUpdating(Object source, SqlDataSourceCommandEventArgs e) {


DbCommand command = e.Command;
DbConnection cx = command.Connection;
cx.Open();
DbTransaction tx = cx.BeginTransaction();
command.Transaction = tx;
}

private void OnSqlUpdated(Object source, SqlDataSourceStatusEventArgs e) {


DbCommand command = e.Command;
DbTransaction tx = command.Transaction;
// In this code example the OtherProcessSucceeded variable represents
// the outcome of some other process that occurs whenever the data is
// updated, and must succeed for the data change to be committed. For
// simplicity, we set this value to true.
bool OtherProcessSucceeded = true;

if (OtherProcessSucceeded) {
tx.Commit();
Label2.Text="The record was updated successfully!";
}
else {
tx.Rollback();
Label2.Text="The record was not updated.";
}
}

</script>

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">
<asp:SqlDataSource
id="SqlDataSource1"
runat="server"
ConnectionString="<%$ ConnectionStrings:MyNorthwind%>"
SelectCommand="SELECT EmployeeID, LastName, Address FROM Employees"
UpdateCommand="UPDATE Employees SET Address=@Address WHERE EmployeeID=@EmployeeID
"
OnUpdating="OnSqlUpdating"
OnUpdated ="OnSqlUpdated">
<UpdateParameters>
<asp:ControlParameter Name="Address" ControlId="TextBox1" PropertyName="Text"
/>
<asp:ControlParameter Name="EmployeeID" ControlId="DropDownList1" PropertyNam
e="SelectedValue"/>
</UpdateParameters>
</asp:SqlDataSource>

<asp:DropDownList
id="DropDownList1"
runat="server"
DataTextField="LastName"
DataValueField="EmployeeID"
DataSourceID="SqlDataSource1">
</asp:DropDownList>
<br />
<asp:Label id="Label1" runat="server" Text="Enter a new address for the selected user
."
AssociatedControlID="TextBox1" />
<asp:TextBox id="TextBox1" runat="server" />
<asp:Button id="Submit" runat="server" Text="Submit" OnClick="On_Click" />

<br /><asp:Label id="Label2" runat="server" Text="" />


</form>
</body>
</html>

J#
<%@Page Language="VJ#" %>
<%@Import Namespace="System.Data" %>
<%@Import Namespace="System.Data.Common" %>
<%@Import Namespace="System.Diagnostics" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">

<script runat="server">

private void On_Click(Object source, System.EventArgs e)


{
try {
SqlDataSource1.Update();
}
catch (System.Exception except) {
// Handle Exception
}

Label2.set_Text("The record was updated successfully!");


} //On_Click

private void OnSqlUpdate(Object source, SqlDataSourceCommandEventArgs e)


{
// Log the command in the Event Log on the Web server.
String logInfo = e.get_Command().get_CommandText()
+ " is being submitted to the database.";

IEnumerator ie = e.get_Command().get_Parameters().GetEnumerator();
while (ie.MoveNext()) {
DbParameter param = ((DbParameter)(ie.get_Current()));
logInfo = logInfo + " " + param.get_ParameterName()+ "="
+ param.get_Value();
}

EventLog log = new EventLog();


log.set_Log("Application");
log.set_Source("ASP.NET Example");
log.WriteEntry(logInfo);
} //OnSqlUpdate

</script>

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">
<asp:SqlDataSource
id="SqlDataSource1"
runat="server"
ConnectionString="Data Source=localhost;Integrated Security=SSPI;Initial Catalog=
Northwind;"
SelectCommand="SELECT EmployeeID, LastName, Address FROM Employees"
UpdateCommand="UPDATE Employees SET Address=@Address WHERE EmployeeID=@EmployeeID
"
OnUpdating="OnSqlUpdate">
<UpdateParameters>
<asp:ControlParameter Name="Address" ControlId="TextBox1" PropertyName="Text"
/>
<asp:ControlParameter Name="EmployeeID" ControlId="DropDownList1" PropertyNam
e="SelectedValue"/>
</UpdateParameters>
</asp:SqlDataSource>

<asp:DropDownList
id="DropDownList1"
runat="server"
DataTextField="LastName"
DataValueField="EmployeeID"
DataSourceID="SqlDataSource1">
</asp:DropDownList>

<br />
<asp:Label id="Label1" runat="server" Text="Enter a new address for the selected user
."
AssociatedControlID="TextBox1" />
<asp:TextBox id="TextBox1" runat="server" />
<asp:Button id="Submit" runat="server" Text="Submit" OnClick="On_Click" />

<br /><asp:Label id="Label2" runat="server" Text="" />

</form>
</body>
</html>

Conflict Detection
The SqlDataSource control can perform update and delete operations using optimistic concurrency. Optimistic concurrency is
a database strategy that protects against losing changes at a data source in scenarios where multiple users are manipulating
the data at the same time. The SqlDataSource control uses the ConflictDetection property to determine what level of
optimistic concurrency checking to use when performing update and delete operations.
By default, the ConflictDetection property is set to System.Web.UI.ConflictOptions.OverwriteChanges, which means that
update operations overwrite any existing values in the record without determining whether the record has been modified by
another source. This scenario is sometimes called "last writer wins."
You can set the ConflictDetection property to System.Web.UI.ConflictOptions.CompareAllValues to ensure that the
SqlDataSource control includes all original values during the update or delete command. This allows you to write your SQL
statement in such a way that if the data currently in the database does not match the data that was initially read from the
database, the update operation is not performed. For an example, see Using Optimistic Concurrency. You can handle the
Updated event to check how many records are affected by an update operation; if no records are updated, a concurrency
violation has occurred.
See Also
Other Resources
SqlDataSource Web Server Control
ASP.NET

Caching Data with the SqlDataSource Control


The SqlDataSource control can cache data that it has retrieved, which can enhance the performance of your applications by
avoiding the need to re-run resource-intensive queries. Caching is useful primarily in situations where the data does not
change frequently.
Additionally, when using the SqlDataSource control with the System.Data.SqlClient provider, you can make use of the
SqlCacheDependency object. This enables the SqlDataSource control to refresh the cache only if the data returned by the
SelectCommand has been modified in the database.
Enabling Caching with the SqlDataSource Control
The SqlDataSource control can cache data when its DataSourceMode property is set to DataSet. Caching is not enabled by
default, but you can enable it by setting the EnableCaching property to true.
Cached data is refreshed based on a time interval. You can set the CacheDuration property to the number of seconds to wait
before the cache is refreshed. The SqlDataSource control maintains a separate cache item for each combination of
ConnectionString, SelectCommand, and SelectParameters values.
You can further control the behavior of the SqlDataSource cache by setting the CacheExpirationPolicy property. A value of
Absolute forces the cache to be refreshed when the CacheDuration value is exceeded. Setting the CacheExpirationPolicy
property to Sliding refreshes the cache only if the CacheDuration value has been exceeded since the last time the cached item
was accessed.
The following code example shows a SqlDataSource control configured to refresh data every 20 seconds:
VB
<%@ Page language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1


/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">

<asp:SqlDataSource
id="SqlDataSource1"
runat="server"
DataSourceMode="DataSet"
ConnectionString="<%$ ConnectionStrings:MyNorthwind%>"
EnableCaching="True"
CacheDuration="20"
SelectCommand="SELECT EmployeeID,FirstName,LastName,Title FROM Employees">
</asp:SqlDataSource>
<asp:GridView
id="GridView1"
runat="server"
AutoGenerateColumns="False"
DataSourceID="SqlDataSource1">
<columns>
<asp:BoundField HeaderText="First Name" DataField="FirstName" />
<asp:BoundField HeaderText="Last Name" DataField="LastName" />
<asp:BoundField HeaderText="Title" DataField="Title" />
</columns>
</asp:GridView>

</form>
</body>
</html>
C#
<%@ Page language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">

<asp:SqlDataSource
id="SqlDataSource1"
runat="server"
DataSourceMode="DataSet"
ConnectionString="<%$ ConnectionStrings:MyNorthwind%>"
EnableCaching="True"
CacheDuration="20"
SelectCommand="SELECT EmployeeID,FirstName,LastName,Title FROM Employees">
</asp:SqlDataSource>

<asp:GridView
id="GridView1"
runat="server"
AutoGenerateColumns="False"
DataSourceID="SqlDataSource1">
<columns>
<asp:BoundField HeaderText="First Name" DataField="FirstName" />
<asp:BoundField HeaderText="Last Name" DataField="LastName" />
<asp:BoundField HeaderText="Title" DataField="Title" />
</columns>
</asp:GridView>

</form>
</body>
</html>

J#
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">

<asp:SqlDataSource
id="SqlDataSource1"
runat="server"
DataSourceMode="DataSet"
ConnectionString="Data Source=localhost;Integrated Security=SSPI;Initial Ca
talog=Northwind;"
EnableCaching="True"
CacheDuration="20"
SelectCommand="SELECT EmployeeID,FirstName,LastName,Title FROM Employees">
</asp:SqlDataSource>

<asp:GridView
id="GridView1"
runat="server"
AutoGenerateColumns="False"
DataSourceID="SqlDataSource1">
<Columns>
<asp:BoundField HeaderText="First Name" DataField="FirstName" />
<asp:BoundField HeaderText="Last Name" DataField="LastName" />
<asp:BoundField HeaderText="Title" DataField="Title" />
</Columns>
</asp:GridView>
</form>
</body>
</html>

Using the SqlCacheDependency Object


The SqlDataSource control supports an optional expiration policy based on a SqlCacheDependency object. You can use the
SqlCacheDependency object to ensure that cached data is refreshed only when the source table in the database has been
modified. In order to use the SqlCacheDependency object, the Microsoft SQL Server notification service must be running for
the database server.
When your data source is SQL Server 7.0 or later, you can use the SqlCacheDependency object to poll the database for
changes by setting the SqlDataSource control's SqlCacheDependency property to a string consisting of a connection string
and table identifiers in the form "ConnectionString:Table". If the SqlCacheDependency involves more than one table, the
connection string and table name pairs are separated by semicolons, as in the following example:
"ConnectionString1:Table1;ConnectionString2:Table2".
When your data source is Microsoft SQL Server 2005, you have the additional option to have SQL Server notify your
application of changes instead of polling for changes. You can use the notification model by setting the
SqlCacheDependency property to the string "CommandNotification". For more information on the SqlCacheDependency
object, see Caching in ASP.NET with the SqlCacheDependency Class.
The following code example demonstrates how to create a Microsoft SQL Server cache dependency and set the
SqlCacheDependency property of a SqlDataSource control. In the example, the database is polled every 120 seconds. If the
data in the Northwind Employees table changes during that time, the data cached by the SqlDataSource control and
displayed by the GridView control is refreshed the next time the database is polled.
VB
<%@ Page language="vb" %>
<!--

The page uses an example configuration that includes


connection strings and a defined SqlCacheDependecy.

<?xml version="1.0"?>
<configuration>

<connectionStrings>
<add name="MyNorthwind"
connectionString="Data Source="localhost";Integrated Security="SSPI";Initial Catal
og="Northwind""
providerName="System.Data.SqlClient" />
</connectionStrings>

<system.web>
<cache>
<sqlCacheDependency enabled="true">
<databases>
<add
name="Northwind"
connectionStringName="MyNorthwind"
pollTime="120000" />
</databases>
</sqlCacheDependency>
</cache>
</system.web>
</configuration>
-->

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="Form1" method="post" runat="server">

<asp:gridview
id="GridView1"
runat="server"
datasourceid="SqlDataSource1" />

<asp:sqldatasource
id="SqlDataSource1"
runat="server"
connectionstring="<%$ ConnectionStrings:MyNorthwind%>"
selectcommand="SELECT EmployeeID,FirstName,Lastname FROM Employees"
enablecaching="True"
cacheduration="300"
cacheexpirationpolicy="Absolute"
sqlcachedependency="Northwind:Employees" />

</form>
</body>
</html>

C#
<%@ Page language="c#" %>

<!--
The page uses an example configuration that includes
connection strings and a defined SqlCacheDependecy.

<?xml version="1.0"?>
<configuration>

<connectionStrings>
<add name="MyNorthwind"
connectionString="Data Source="localhost";Integrated Security="SSPI";Initial Catal
og="Northwind""
providerName="System.Data.SqlClient" />
</connectionStrings>

<system.web>
<cache>
<sqlCacheDependency enabled="true">
<databases>
<add
name="Northwind"
connectionStringName="MyNorthwind"
pollTime="120000" />
</databases>
</sqlCacheDependency>
</cache>

</system.web>
</configuration>
-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="Form1" method="post" runat="server">

<asp:gridview
id="GridView1"
runat="server"
datasourceid="SqlDataSource1" />

<asp:sqldatasource
id="SqlDataSource1"
runat="server"
connectionstring="<%$ ConnectionStrings:MyNorthwind%>"
selectcommand="SELECT EmployeeID,FirstName,Lastname FROM Employees"
enablecaching="True"
cacheduration="300"
cacheexpirationpolicy="Absolute"
sqlcachedependency="Northwind:Employees" />

</form>
</body>
</html>

J#
<%@ Page language="VJ#" %>

<!--

The page uses an example configuration that includes


connection strings and a defined SqlCacheDependecy.

<?xml version="1.0"?>
<configuration>

<connectionStrings>
<add name = "NorthwindConnection" connectionString = "Data Source="localhost";Integrate
d Security="SSPI";Initial Catalog="Northwind"" />
</connectionStrings>
<system.web>

...

<cache>
<sqlCacheDependency enabled="true">
<databases>
<add
name="Northwind_Remote"
connectionStringName="NorthwindConnection"
pollTime="120000" />
</databases>
</sqlCacheDependency>
</cache>
</system.web>
</configuration>
-->

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="Form1" method="post" runat="server">
<asp:gridview
id="GridView1"
runat="server"
datasourceid="SqlDataSource1" />

<asp:sqldatasource
id="SqlDataSource1"
runat="server"
connectionstring="Data Source=localhost;Integrated Security=SSPI;Initial Catalog=
Northwind"
selectcommand="SELECT EmployeeID,FirstName,Lastname FROM Employees"
enablecaching="True"
cacheduration="300"
cacheexpirationpolicy="Absolute"
sqlcachedependency="Northwind_Remote:Employees" />

</form>
</body>
</html>

See Also
Other Resources
ASP.NET Caching
SqlDataSource Web Server Control
Data Source Web Server Controls
Visual Web Developer

Walkthough Topics — SqlDataSource Web Server Control


(Visual Studio)
The walkthroughs provided below give step-by-step instructions for common scenarios that use the SqlDataSource control to
represent an SQL data source to data-bound controls.
In This Section
Walkthrough: Basic Data Access in Web Pages
Walkthrough: Creating Master/Detail Web Pages in Visual Studio
Walkthrough: Editing and Inserting Data in Web Pages with the DetailsView Web Server Control
See Also
Tasks
How to: Connect to an Oracle Database Using the SqlDataSource Control
Other Resources
SqlDataSource Web Server Control (Visual Studio)
Data Toolbox Controls
ASP.NET Data Access (Visual Studio)
Visual Web Developer

How-to Topics — SqlDataSource Web Server Control (Visual


Studio)
The following procedures describe how to use the SqlDataSource control to connect to databases and make data available to
other controls on an ASP.NET Web page.
How-to Topics
How to: Connect to a SQL Server Database Using the SqlDataSource Control (Visual Studio)
How to: Connect to an Access Database Using the SqlDataSource Control (Visual Studio)
How to: Connect to an ODBC Database Using the SqlDataSource Control (Visual Studio)
How to: Connect to an Oracle Database Using the SqlDataSource Control (Visual Studio)
How to: Enable Filtering for SqlDataSource Controls (Visual Studio)
See Also
Other Resources
SqlDataSource Web Server Control (Visual Studio)
Visual Web Developer

AccessDataSource Control (Visual Studio)


The topics in this section describe how to work with the AccessDataSource control to connect to a Microsoft Access database.
In This Section
Retrieving Data Using the AccessDataSource Web Server Control
Walkthrough: Creating a Web Page to Display Access Database Data
How to: Connect to an Access Database Using the AccessDataSource Control (Visual Studio)
See Also
Other Resources
SqlDataSource Web Server Control (Visual Studio)
Data Toolbox Controls
ASP.NET Data Access (Visual Studio)
ASP.NET

Retrieving Data Using the AccessDataSource Web Server


Control
The AccessDataSource control enables you to retrieve data from a Microsoft Access database (.mdb file). You can then display
the data in data-bound controls, such as the GridView, FormView, and DetailsView controls.
The AccessDataSource control inherits the SqlDataSource class and replaces the ConnectionString property with a DataFile
property to make it more convenient to connect to a Microsoft Access database. The AccessDataSource control uses the
System.Data.OleDb provider to connect to Access databases using the Microsoft.Jet.OLEDB.4.0 OLE DB provider.
Connecting to a Database using the AccessDataSource Control
The AccessDataSource control connects to the Microsoft Access database file (.mdb file) identified in the DataFile property.
You can set the DataFile property to a universal naming convention (UNC) path that points to an Access database file. The
following example demonstrates how you can use a root-relative path to identify an Access database that is located in the
App_Data folder of the current Web application.

<asp:AccessDataSource
id="AccessDataSource1"
DataFile="~/App_Data/Northwind.mdb"
runat="server"
SelectCommand="SELECT EmployeeID, LastName, FirstName FROM Employees">
</asp:AccessDataSource>

If you are storing an Access database file with your Web application, it is recommended that you store it in the App_Data folder
to keep the database private. ASP.NET does not allow files in the App_Data folder to be returned if requested directly. The
ASP.NET process identity must be granted read and write file permissions to the Access databases stored in the App_Data
folder. For information on the ASP.NET process identity, see Configuring ASP.NET Process Identity.
The AccessDataSource control sets the ProviderName property of the base SqlDataSource class to the System.Data.OleDb
provider and connects using the Microsoft.Jet.OLEDB.4.0 OLE DB provider. You cannot set the ProviderName or
ConnectionString properties of the AccessDataSource control.
Note
The AccessDataSource will not connect to an Access database that is password-protected; to retrieve data from a password
-protected Access database, use the SqlDataSource control.

Selecting Data Using the AccessDataSource Control


You can specify an SQL query for the AccessDataSource control to execute by setting its SelectCommand property as shown
in the following code example.
VB
<form id="form1" runat="server">
<asp:AccessDataSource
id="EmployeesAccessDataSource"
DataFile="~/App_Data/Northwind.mdb"
runat="server"
SelectCommand="SELECT EmployeeID, FirstName, LastName FROM Employees" />

<asp:GridView
id="EmployeesGridView"
runat="server"
AutoGenerateColumns="True"
DataSourceid="EmployeesAccessDataSource" />

C#
<form id="form1" runat="server">
<asp:AccessDataSource
id="EmployeesAccessDataSource"
DataFile="~/App_Data/Northwind.mdb"
runat="server"
SelectCommand="SELECT EmployeeID, FirstName, LastName FROM Employees" />
<asp:GridView
id="EmployeesGridView"
runat="server"
AutoGenerateColumns="True"
DataSourceid="EmployeesAccessDataSource" />

You can return results from a Microsoft Access query by setting the SelectCommandType property of your SelectCommand
to StoredProcedure as shown in the following code example.
VB
<asp:AccessDataSource
id="InvoiceAccessDataSource"
DataFile="~/App_Data/Northwind.mdb"
runat="server"
SelectCommand="[Employee Sales By Country]"
SelectCommandType="StoredProcedure">
<SelectParameters>
<asp:Parameter Name="Beginning Date" Type="DateTime" defaultValue="1/1/1997" />
<asp:Parameter Name="Ending Date" Type="DateTime" defaultValue="1/31/1997" />
</SelectParameters>
</asp:AccessDataSource>

<asp:GridView
id="InvoiceGridView"
runat="server"
AutoGenerateColumns="True"
DataSourceid="InvoiceAccessDataSource" />

C#
<asp:AccessDataSource
id="InvoiceAccessDataSource"
DataFile="~/App_Data/Northwind.mdb"
runat="server"
SelectCommand="[Employee Sales By Country]"
SelectCommandType="StoredProcedure">
<SelectParameters>
<asp:Parameter Name="Beginning Date" Type="DateTime" defaultValue="1/1/1997" />
<asp:Parameter Name="Ending Date" Type="DateTime" defaultValue="1/31/1997" />
</SelectParameters>
</asp:AccessDataSource>

<asp:GridView
id="InvoiceGridView"
runat="server"
AutoGenerateColumns="True"
DataSourceid="InvoiceAccessDataSource" />

For information on modifying data using the AccessDataSource control, see


Modifying Data using the SqlDataSource Control; that topic applies to working with the AccessDataSource control because
the control inherits the capability of the SqlDataSource control and implicitly makes use of the System.Data.OleDb provider.
Using Parameters with the AccessDataSource Control
You can use parameterized queries for commands and supply parameters at run time. Additionally, you can specify parameters
at run time when calling a Microsoft Access query. (To call a Microsoft Access query, you set the command type property for
the command to StoredProcedure). For more information, see Using Parameters with Data Source Controls.
Because the AccessDataSource control extends the SqlDataSource class and uses the System.Data.OleDb provider, you
specify parameter placeholders using the "?" placeholder character. The System.Data.OleDb provider does not support
named parameters; instead, the parameter values are applied in the order they are specified in the parameters collection. You
must ensure that the order of the parameters in the parameters collection matches the order of the parameter placeholders in
your SQL statement or Microsoft Access query. For more information and examples, see
Using Parameters with the SqlDataSource Control.
See Also
Concepts
Selecting Data Using the SqlDataSource Control
Visual Web Developer

Walkthrough: Creating a Web Page to Display Access Database


Data
Using the Microsoft Visual Web Developer Web development tool, you can create Web pages that work with data from a
variety of sources, including databases, XML files, and business objects. This walkthrough shows you how to work with data in
a Microsoft Access database (.mdb file).
During this walkthrough, you will learn how to do the following:
Configure permissions for .mdb files.
Connect to the database that has an AccessDataSource control.
Display Access data.
Access databases do not have the same capacity and are not as scalable as other types of databases, such as Microsoft SQL
Server. Generally, if you are creating a Web site that will support only light traffic or a limited number of users, an Access
database is sufficient. However, if the Web site will support more throughput or a larger number of users, you should consider
using SQL Server or another database that is suited for production Web sites.
Prerequisites
In order to complete this walkthrough, you will need the following:
The Northwind.mdb file that contains the Access version of the sample Northwind database.
Alternatively, you can use another Access .mdb file and adjust the steps in the walkthrough to match the tables that you
are using.
Microsoft Data Access Components (MDAC) version 2.7 or later.
If you are using Microsoft Windows XP or Windows Server 2003, you already have MDAC 2.7. However, if you using
Microsoft Windows 2000, you might to have to upgrade the MDAC version that is already installed on the computer. To
download the current MDAC version, see the Data Access and Storage Developer Center..
Optionally, Microsoft Internet Information Services (IIS) installed locally on the computer.
This lets you test that the Web site has adequate user rights to use an Access database in a production environment.
Creating the Web Site and Page
If you have already created a Web site in Visual Web Developer by completing
Walkthrough: Creating a Basic Web Page in Visual Web Developer, you can use that Web site and go to the next section.
Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the left-most Location box, click HTTP.
5. Click Browse.
The Choose Location page appears.
6. Click Local IIS, and then click Default Web Site.
7. Click the create new Web application icon ( ), and then name the new Web application AccessSample.
8. Click Open.
The New Web Site dialog box appears with the location of your new Web application in the right-most Location box.
9. In the Language list, click the programming language that you prefer to work in.
The programming language that you choose will be the default for the Web site, but you can set the programming
language for each page individually.
10. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx. The Web site is displayed in Solution
Explorer.
Configuring Permissions for an Access Database
An important aspect of working with an Access .mdb file is to correctly configure permissions. When a Web application uses an
Access database, the application must have Read permission to the .mdb file so the application can access the data.
Additionally, the application must have Write permission to the folder that contains the .mdb file. Write permission is required
because Access creates an additional file that has the extension .ldb in which it maintains information about database locks for
concurrent users. The .ldb file is created at run time.
By default, ASP.NET Web applications run in the context of a local machine account named ASPNET (for Windows 2000 and
Windows XP) or in the context of the account NETWORK SERVICE (for Windows Server 2003). For example, for Windows 2000
or Windows XP Professional, if the Web server is named ABCServer, ASP.NET applications on the ABCServer computer run in
the context of the local account ABCServer\ASPNET. Therefore, to use an Access database in an ASP.NET Web application, you
must configure the folder that contains the Access database to have both Read and Write permissions for the local ASPNET
user account.
When you create a Web site in Visual Web Developer, Visual Web Developer creates a folder named App_Data below the
current root folder. The folder is designed to be a store for application data, including Access databases. The App_Data folder is
also used by ASP.NET to store databases that the system maintains, such as the database for membership and roles. When
Visual Web Developer creates the App_Data folder, it grants Read and Write permissions for the folder to the ASPNET or
NETWORK SERVICE user account.
Note
As a security measure, files in the App_data folder are not served by the Web server. Do not store any Web pages in the App_
Data folder, because users will see an error if they request a page from that folder.

In this part of the walkthrough, you will examine the permissions of the App_Data folder to make sure that it will work correctly
when the application runs.
To set permissions in the App_Data folder
1. In Windows Explorer, move to the root folder for the Web site.
The default location for your new Web site is c:\inetpub\wwwroot\AccessSample.
2. If the App_Data folder does not already exist, create one.
By default, Visual Web Developer creates the folder when you create a new Web site.
3. Right-click the App_Data folder, click Properties, and then click the Security tab.
4. Under Group or user names, look for either of these user accounts:
If the computer is running Windows XP Professional or Windows 2000, look for computer\ASPNET.
If the computer is running Windows Server 2003, look for NETWORK SERVICE.
5. Verify that the account has Read and Write permissions for the App_Data folder.
Using Access Data on an ASP.NET Web Page
You can now use your Access database in a Web page. You will use an AccessDataSource control.
To add an AccessDataSource control to the page
1. In Visual Web Developer, in Solution Explorer, right-click the App_Data folder, and then click Add Existing Item.
2. Locate the Northwind.mdb file (or other Access .mdb file) that you want to use for this walkthrough.
3. In the App_Data folder, click the .mdb file, and then click Add.
The .mdb file is added to your application.
4. Open the Default.aspx page and switch to Design view.
5. From the Data group in the Toolbox, drag an AccessDataSource control onto the page.
If the Access Data Source Tasks shortcut menu does not appear, right-click the AccessDataSource control, and
then click Show Smart Tag.
6. On the Access Data Source Tasks shortcut menu, click Configure Data Source.
The Configure Data Source - <DataSourceName> wizard appears.
7. On the Choose a database page, in the Microsoft Access Data file box, type ~/App_Data/Northwind.mdb.
Alternatively, click Browse, and then in the Select Microsoft Access Database dialog box, move to the
Northwind.mdb file in the App_Data folder.
8. Click Next.
The Configure Select Statement page appears.
9. Click Specify columns from a table or view.
10. In the Name list, click Categories.
11. Select the CategoryID, CategoryName, and Description check boxes.
12. Click Next.
The Test Query page appears.
Optionally, click Test Query to test your query.
13. Click Finish.
14. From the Data group in the Toolbox, drag a GridView control onto the page.
If the GridView Tasks shortcut menu does not appear, right-click the GridView control, and then click Show
Smart Tag.
15. On the GridView Tasks menu, in the Choose Data Source box, click AccessDataSource1.
Testing the Page
You can now run the page.
To test the page
Press CTRL+F5 to run the page.
The GridView control displays all data rows from the Categories table.
Next Steps
This walkthrough describes the basic steps that are required to work with Access data in an ASP.NET Web page. The ASP.NET
data binding model lets you work with data from different sources in the same way. For example, you can do the following:
Use controls to filter the data that the page displays.
For detailed information, see Walkthrough: Basic Data Access in Web Pages.
Update, insert, or delete data from an Access database.
For detailed information, see
Walkthrough: Editing and Inserting Data in Web Pages with the DetailsView Web Server Control.
Create pages to display Access data from tables that have a master-detail relationship.
For detailed information, see Walkthrough: Creating Master/Detail Web Pages in Visual Studio.
See Also
Concepts
ASP.NET Data Access Overview
Binding to Data Using a Data Source Control
Visual Web Developer

How to: Connect to an Access Database Using the


AccessDataSource Control (Visual Studio)
You can connect the AccessDataSource control to a Microsoft Access database and then display or edit data using controls
such as the GridView control.
To use the AccessDataSource control to connect to an Access database
1. Open the page from which you want to connect to an Access database.
2. Switch to Design view.
3. From the Data group on the Toolbox, drag an AccessDataSource control onto your page.
4. If the Smart Tag panel is not displayed, right-click the control and click Show Smart Tag.
5. In the AccessDataSource Tasks list, click Configure Data Source.
The Configure Data Source wizard is displayed.
6. In the Choose a Database pane, type or select the path to your Microsoft Access database, which will have .mdb as the
file name extension.
Note
We recommend that you store your Access database in the Web site's App_Data folder to ensure that the Web server w
ill not return the .mdb file in response to a Web request. In addition, for local Web sites, Visual Web Developer ensures
that the Web server has permissions to read and write files in the App_Data folder. For Web sites on other computers, y
ou will need to set those permissions manually.

7. Click Next.
8. In the Configure the Select Statement pane, if you want to use the wizard to create a SQL query, click Specify
columns from a table or view and use the options in the pane to configure your query.
Note
To have the wizard generate Insert, Update, and Delete statements based on the Select statement you are creating, click
Advanced.

9. If you want to use the query builder or write your Select query, click Specify a custom SQL statement or stored
procedure, click Next, and then write your SQL statement. Click the UPDATE, INSERT, or DELETE tabs to create update
statements.
10. Click Next.
11. In the Test Query pane, click Test Query to determine whether the query returns the results you want.
12. Click Finish.
You can now bind data controls such as the GridView control to the AccessDataSource control.
See Also
Tasks
Walkthrough: Basic Data Access in Web Pages
Walkthrough: Creating a Web Page to Display Access Database Data
Concepts
Data Source Controls Overview
Other Resources
AccessDataSource Web Server Control
Visual Web Developer

ObjectDataSource Web Server Control (Visual Studio)


The topics in this section describe how to work with the ObjectDataSource control to represent a business object that provides
data to data-bound controls in multi-tier Web application architectures.
In This Section
ObjectDataSource Control Overview
Walkthrough: Data Binding Web Pages with a Visual Studio Data Component
Using Parameters with the ObjectDataSource Control
Walkthrough: Data Binding to a Custom Business Object
Creating an ObjectDataSource Control Source Object
See Also
Other Resources
Data Toolbox Controls
ASP.NET Data Access (Visual Studio)
ASP.NET

ObjectDataSource Control Overview


The ASP.NET ObjectDataSource control represents a middle-tier object with data retrieval and update capabilities. The
ObjectDataSource control acts as a data interface for data-bound controls such as the GridView, FormView, or DetailsView
controls, and enables those controls to display and edit data from a middle-tier business object on an ASP.NET Web page.
Retrieving and Modifying Data
Most ASP.NET data source controls, such as the SqlDataSource, are used in a two-tier application architecture where the
presentation layer (the ASP.NET Web page) communicates directly with the data tier (the database, an XML file, and so on).
However, a common application design practice is to separate the presentation layer from business logic and encapsulate the
business logic in business objects. These business objects form a layer between the presentation layer and the data tier,
resulting in a three-tier application architecture. The ObjectDataSource control supports a three-tier architecture by providing
a way for you to bind data controls on the page to a middle-tier business object. The ObjectDataSource works with a middle-
tier business object to select, insert, update, delete, page, sort, cache, and filter data declaratively without extensive code.
The ObjectDataSource control uses reflection to call methods of a business object to select, update, insert, and delete data.
You set the ObjectDataSource control's TypeName property to specify the name of the class to use as a source object. For
details on how to create a source data object to be used with the ObjectDataSource control, see
Creating an ObjectDataSource Control Source Object.
Sorting and Paging
The ObjectDataSource control can support additional sorting and paging capabilities by passing sort and page information in
requests from a data-bound control, such as a GridView control, to the data object for processing. The source data object or
the data source control itself can then sort data and return data in pages.
For information on passing sorting and paging parameters to an ObjectDataSource control's data object, see
Using Parameters with the ObjectDataSource Control.
Caching
The ObjectDataSource control can cache objects returned by the underlying business object. However, you should not cache
objects that hold resources or that maintain state that cannot be shared among multiple requests, such as an open DataReader
object.
Filtering
If the object returned to the ObjectDataSource control by the source data object is a DataSet or DataTable object, the
ObjectDataSource control supports filtering using the syntax of the Expression property of the DataColumn class. Filtering
enables you to expose only rows that match particular search criteria, without having to re-query the data source with new
selection criteria. For more information, see Filtering Data Using Data Source Controls.
Conflict Detection
By setting the ObjectDataSource control's ConflictDetection property to true, you can specify that the ObjectDataSource
control should include original values when calling update methods of the source data object. The original values can then be
included in checks for optimistic concurrency. For more information, see Using Parameters with the ObjectDataSource Control.
For information on optimistic concurrency checking, see Using Optimistic Concurrency.
See Also
Other Resources
ObjectDataSource Web Server Control
Visual Web Developer

Walkthrough: Data Binding Web Pages with a Visual Studio


Data Component
Many Web applications are built by using multiple tiers, with one or more components in the middle tier that combine data
access together with business logic. This walkthrough shows you how to build a data-access component in a Web site and bind
a Web server control (a GridView control) to the data that is managed by the component. The data component interacts with a
Microsoft SQL Server database, and can both read and write data.
Tasks illustrated in this walkthrough include the following:
Creating a component that can read and write data.
Referencing the data component as a data source on a Web page.
Binding a control to the data that is returned by the data component.
Reading and writing data using the data component.
Prerequisites
In order to complete this walkthrough, you will need the following:
Access to the SQL Server Northwind database. For information about downloading and installing the SQL Server sample
Northwind database, see Installing Sample Databases on the Microsoft SQL Server Web site.
Note
If you need information about how to log on to the computer running SQL Server, contact the server administrator.

Microsoft Data Access Components (MDAC) version 2.7 or later.


If you are using Microsoft Windows XP or Windows Server 2003, you already have MDAC 2.7. However, if you using
Microsoft Windows 2000, you might to have to upgrade the MDAC version that is already installed on the computer. To
download the current MDAC version, see the Data Access and Storage Developer Center.
Creating the Web Site
If you have already created a Web site in Visual Web Developer by completing
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and go to the next section.
Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the left-most Location list, click File System, and then in the right-most Location textbox, enter the name of the folder
where you want to keep the pages of the Web site.
For example, type the folder name C:\WebSites\ComponentSample.
5. In the Language list, click the programming language that you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Creating a Data-Access Component
In this walkthrough, you will use a wizard to generate a component that reads data from and writes data to the Northwind
database. The component includes a schema file (.xsd) describing the data that you want and the methods that will be used to
read and write data. You will not have to write any code. At run time, the .xsd file is compiled into an assembly that performs
the tasks that you specify in the wizard.
To create a data-access component
1. If the Web site does not already have an App_Code folder, do the following:
a. In Solution Explorer, right-click the name of the Web site.
b. Point to Add Folder, and then click App_Code Folder.
2. Right-click the App_Code folder, and then click Add New Item.
The Add New Item dialog box appears.
3. Under Visual Studio installed templates, click DataSet.
4. In the Name box, type EmployeesObject, and then click Add.
The TableAdapter Configuration wizard appears.
5. Click New Connection.
6. If the Choose Data Source dialog box appears, click Microsoft SQL Server and then click Continue.
7. In the Server name box, enter the name of the computer that is running SQL Server.
8. For the logon credentials, select the option that is appropriate for accessing the SQL Server database (integrated security
or specific ID and password) and if it is required, enter a user name and password.
If you specify explicit credentials, select the Save my password check box.
9. Click Select or enter a database name, and then enter Northwind.
10. Click Test connection, and when you are sure that the connection works, click OK.
The TableAdapter Configuration wizard appears with the connection information filled in.
11. Click Next.
A page where you can choose to store the connection string in the configuration file appears.
12. Select the Yes, save this connection as check box, and then click Next.
You can leave the default connection string name.
A page where you can choose to use SQL statements or stored procedures appears.
13. Click Use SQL statements, and then click Next.
Using stored procedures has some advantages, including performance and security. However, for simplicity in this
walkthrough, you will use an SQL statement.
A page where you can define the SQL statement appears.
14. Under What data should be loaded into the table, type the following SQL statement:

SELECT EmployeeID, LastName, FirstName, HireDate FROM Employees

Note
You can click Query Builder to use a builder tool, if you prefer.

15. Click Next.


A page where you can define the methods that the component will expose appears.
16. Click to clear the Fill a DataTable check box, and then select the Return a DataTable and Create methods to send
updates directly to the database check boxes.
You do not need a method to fill a data table for this walkthrough. However, you will need a method that returns the data
and you also want the component to contain methods that update the database.
17. In the Method Name box, type GetEmployees.
You are naming the method that will be used later to obtain data.
18. Click Finish.
The wizard configures the component and displays it in the component designer, displaying the data that the component
manages and the methods that the component exposes.
19. Save the data component, and then close the component designer.
20. On the Build menu, click Build Web Site to make sure that the component compiles correctly.
Using the Data Component on a Page
You can now use the data component as a data source in an ASP.NET Web page. To access the data component, you will use an
ObjectDataSource control, configuring it to call the data-access methods that are exposed by the data component. You can
then add controls to the page and bind them to the data source control.
To add a data source control to the page
1. Open the Default.aspx page and switch to Design view.
2. From the Data group in the Toolbox, drag an ObjectDataSource control onto the page.
If the ObjectDataSource Tasks shortcut menu does not appear, right-click the ObjectDataSource control, and
then click Show Smart Tag.
3. On the ObjectDataSource Tasks shortcut menu, click Configure Data Source.
The Configure Data Source wizard appears.
4. In the Choose your business object list, click EmployeesObjectTableAdapters.EmployeesTableAdapter.
This is the type name (namespace and class name) of the component that you created in the preceding section.
5. Click Next.
6. On the Select tab, in the Choose a method list, click GetEmployees(), returns EmployeesDataTable.
The GetEmployees method is a method that was defined in the component that you created in the preceding section. It
returns the results of the SQL statement, available in a DataTable object that data controls can bind to.
7. Click Finish.
You can now add data controls to the page and bind them to the ObjectDataSource control. In this walkthrough, you will
work with the GridView control.
To add a GridView control to the page and bind it to the data
1. From the Data group in the Toolbox, drag a GridView control onto the page.
If the GridView Tasks shortcut menu does not appear, right-click the GridView control, and then click Show
Smart Tag.
2. On the GridView Tasks shortcut menu, in the Choose Data Source list, click ObjectDataSource1, which is the ID of
the control that you configured in the preceding section.
The GridView control reappears with a column for each data column that is returned by the SQL statement.
3. In Properties, verify that the DataKeyNames is set to EmployeeID.
Testing the Page
Now that all controls that you need are on the page, you can test the page.
To test the page
1. Press CTRL+F5 to run the page.
2. Confirm that the EmployeeID, LastName, FirstName, and HireDate columns from the Employees table are displayed in
the grid.
3. Close the browser.
The GridView control requests data from the ObjectDataSource control. In turn, the ObjectDataSource control creates an
instance of the data component and calls GetEmployees method for the data component. The GetEmployees method
returns a DataTable object, which the ObjectDataSource control returns to the GridView control.
Adding Updates to the Page
The data component that you created includes SQL statements to update the database (update, insert, and delete records). The
update facilities of the data component are exposed by methods that were generated automatically when the wizard created
the component. The GridView control and ObjectDataSource control can interact to automatically start the update methods.
Note
The GridView control does not support Insert.

To enable updates and deletes


1. Right-click the GridView control, and then click Show Smart Tag.
2. Select the Enable Editing check box.
3. Select the Enable Deleting check box.
Note
Enabling deletion lets you permanently remove records from the database. Do not enable deletion unless you are work
ing with expendable test data.

Testing Updates
You can now test to make sure that you can use the component to update the database.
To test updates
1. Press CTRL+F5 to run the page.
This time, the GridView control displays Edit and Delete links in each row.
2. Click the Edit link that is next to a row.
3. Make a change to the row, and then click Update.
The grid is redisplayed with the updated date.
4. Click the Delete link that is in a row.
The row is permanently deleted from the database. The grid is redisplayed without that row.
5. Close the browser.
Next Steps
This walkthrough illustrates how to work with a data component. You might want to experiment with additional features of
navigation. For example, you might want to do the following:
Create a custom data component instead of using the wizard.
For an example, see Walkthrough: Data Binding to a Custom Business Object.
Restrict which users can change the data. A typical method is to add membership and roles to the Web site, and then
establish rules that the business component can check before allowing changes to data.
For detailed information, see Walkthrough: Creating a Web Site with Membership and User Login (Visual Studio) and
Walkthrough: Managing Web Site Users with Roles.
See Also
Tasks
Walkthrough: Using Shared Code in Web Sites in Visual Web Developer
Walkthrough: Creating a Basic Web Page in Visual Web Developer
Concepts
Data Source Controls Overview
Using Parameters with Data Source Controls
ASP.NET

Using Parameters with the ObjectDataSource Control


The ObjectDataSource control calls business object methods based on the name of the method identified in the SelectMethod,
InsertMethod, UpdateMethod, or DeleteMethod property, and based additionally on the parameter names that make up the
business object method's signature. When you create methods in a business object, you must ensure that the parameter
names and types accepted by the business object method match the parameter names and types that the ObjectDataSource
control passes. (Parameter order is not important.)
Using Parameters
Like all data source controls, the ObjectDataSource control accepts input parameters at run time and manages them in
parameter collections. Each data operation has a related parameter collection. For select operations, you can use the
SelectParameters collection; for updates, you can use the UpdateParameters collection; and so on.
You can specify a name, type, direction, and default value for each parameter. Parameters that get values from a specific object,
such as a control, session variable, or the user profile, require you to set additional properties. For example, a ControlParameter
object requires that you set the ControlID property to identify the control to take the parameter value, and set the
PropertyName property to identify the property that contains the parameter value. For more information, see
Using Parameters with Data Source Controls.
The following code example shows a select method that can be called by an ObjectDataSource control. The method takes a
parameter and selects a single record from the data source.
VB
<DataObjectMethod(DataObjectMethodType.Select)> _
Public Shared Function GetEmployee(EmployeeID As Integer) As DataTable

If Not _initialized Then Initialize()

Dim conn As SqlConnection = New SqlConnection(_connectionString)


Dim da As SqlDataAdapter = _
New SqlDataAdapter("SELECT EmployeeID, LastName, FirstName, Address, City, Region, Post
alCode FROM Employees WHERE EmployeeID = @EmployeeID", conn)
da.SelectCommand.Parameters.Add("@EmployeeID", SqlDbType.Int).Value = EmployeeID

Dim ds As DataSet = New DataSet()

Try
conn.Open()
da.Fill(ds, "Employees")
Catch e As SqlException
' Handle exception.
Finally
conn.Close()
End Try

If ds.Tables("Employees") IsNot Nothing Then _


Return ds.Tables("Employees")
Return Nothing
End Function

C#
[DataObjectMethod(DataObjectMethodType.Select)]
public static DataTable GetEmployee(int EmployeeID)
{
if (!_initialized) { Initialize(); }
SqlConnection conn = new SqlConnection(_connectionString);
SqlDataAdapter da =
new SqlDataAdapter("SELECT EmployeeID, LastName, FirstName, Address, City, Region, Post
alCode FROM Employees WHERE EmployeeID = @EmployeeID", conn);
da.SelectCommand.Parameters.Add("@EmployeeID", SqlDbType.Int).Value = EmployeeID;
DataSet ds = new DataSet();

try
{
conn.Open();
da.Fill(ds, "Employees");
}
catch (SqlException e)
{
// Handle exception.
}
finally
{
conn.Close();
}
if (ds.Tables["Employees"] != null)
return ds.Tables["Employees"];
return null;
}

Passing Parameters to Insert, Update, and Delete Methods


The ObjectDataSource control determines the method to call for an insert, update, or delete operation based on the
InsertParameters, UpdateParameters, and DeleteParameters collections, respectively. Additionally, the ObjectDataSource
control will automatically create parameters based on values passed by a data-bound control, such as a GridView or FormView
control, that supports automatic update, insert, and delete operations. For more information, see
How a Data Source Control Creates Parameters for Data-bound Fields.
The following code example shows a method callable by an ObjectDataSource control. The method updates employee
information in the Northwind sample database.
VB
<DataObjectMethod(DataObjectMethodType.Update)> _
Public Shared Function UpdateEmployee(EmployeeID As Integer, _
FirstName As String, _
LastName As String, _
Address As String, _
City As String, _
Region As String, _
PostalCode As String) As Boolean
If String.IsNullOrEmpty(FirstName) Then _
Throw New ArgumentException("FirstName cannot be null or an empty string.")
If String.IsNullOrEmpty(LastName) Then _
Throw New ArgumentException("LastName cannot be null or an empty string.")

If Address Is Nothing Then Address = String.Empty


If City Is Nothing Then City = String.Empty
If Region Is Nothing Then Region = String.Empty
If PostalCode Is Nothing Then PostalCode = String.Empty
If Not _initialized Then Initialize()

Dim conn As SqlConnection = New SqlConnection(_connectionString)


Dim cmd As SqlCommand = New SqlCommand("UPDATE Employees " & _
" SET FirstName=@FirstName, LastName=@LastNa
me, " & _
" Address=@Address, City=@City, Region=@Regi
on, " & _
" PostalCode=@PostalCode " & _
" WHERE EmployeeID=@EmployeeID", conn)
cmd.Parameters.Add("@FirstName", SqlDbType.VarChar, 10).Value = FirstName
cmd.Parameters.Add("@LastName", SqlDbType.VarChar, 20).Value = LastName
cmd.Parameters.Add("@Address", SqlDbType.VarChar, 60).Value = Address
cmd.Parameters.Add("@City", SqlDbType.VarChar, 15).Value = City
cmd.Parameters.Add("@Region", SqlDbType.VarChar, 15).Value = Region
cmd.Parameters.Add("@PostalCode", SqlDbType.VarChar, 10).Value = PostalCode
cmd.Parameters.Add("@EmployeeID", SqlDbType.Int).Value = EmployeeID

Try
conn.Open()

If cmd.ExecuteNonQuery() <> 0 Then _


Return False
Catch e As SqlException
' Handle exception.
Finally
conn.Close()
End Try

Return True
End Function

C#
[DataObjectMethod(DataObjectMethodType.Update)]
public static bool UpdateEmployee(int EmployeeID, string FirstName, string LastName,
string Address, string City, string Region, string Postal
Code)
{
if (String.IsNullOrEmpty(FirstName))
throw new ArgumentException("FirstName cannot be null or an empty string.");
if (String.IsNullOrEmpty(LastName))
throw new ArgumentException("LastName cannot be null or an empty string.");

if (Address == null) { Address = String.Empty; }


if (City == null) { City = String.Empty; }
if (Region == null) { Region = String.Empty; }
if (PostalCode == null) { PostalCode = String.Empty; }

if (!_initialized) { Initialize(); }

SqlConnection conn = new SqlConnection(_connectionString);


SqlCommand cmd = new SqlCommand("UPDATE Employees " +
" SET FirstName=@FirstName, LastName=@LastName, " +
" Address=@Address, City=@City, Region=@Region, " +
" PostalCode=@PostalCode " +
" WHERE EmployeeID=@EmployeeID", conn);

cmd.Parameters.Add("@FirstName", SqlDbType.VarChar, 10).Value = FirstName;


cmd.Parameters.Add("@LastName", SqlDbType.VarChar, 20).Value = LastName;
cmd.Parameters.Add("@Address", SqlDbType.VarChar, 60).Value = Address;
cmd.Parameters.Add("@City", SqlDbType.VarChar, 15).Value = City;
cmd.Parameters.Add("@Region", SqlDbType.VarChar, 15).Value = Region;
cmd.Parameters.Add("@PostalCode", SqlDbType.VarChar, 10).Value = PostalCode;
cmd.Parameters.Add("@EmployeeID", SqlDbType.Int).Value = EmployeeID;

try
{
conn.Open();

if (cmd.ExecuteNonQuery() == 0)
return false;
}
catch (SqlException e)
{
// Handle exception.
}
finally
{
conn.Close();
}

return true;
}

The code example assumes that the ConflictDetection property of the ObjectDataSource control has been set to
OverwriteChanges. If the ConflictDetection property is set to CompareAllValues, the business object method must accept
parameters for the original values of the data fields. You can differentiate between parameters for current and original values
using the OldValuesParameterFormatString property. You set the OldValuesParameterFormatString property to a string
expression that is used to format the names for original-value parameters, where the {0} characters represent the field name.
For example, if you set the OldValuesParameterFormatString property to original_{0}, the current value for a field named
FirstName would be passed in a parameter named FirstName, and the original value for the field would be passed in a
parameter named original_FirstName.
Identifying Parameters for Sorting and Paging
In addition to specifying SelectParameters objects for a Select business object method, you can include parameters for
sorting and paging. This enables you to sort data in the data source object as well as restrict the results returned from your
data source object to only the requested page of data.
Identifying a Sort Parameter
You can specify a sort parameter for a Select business object method using the ObjectDataSource control's
SortParameterName property. The SortParameterName property identifies the name of the parameter used to pass sort
column names to the business object method. The parameter is of type string.
Certain data-bound controls such as the GridView control can pass sort parameters to the ObjectDataSource control
automatically. When a data-bound control that supports sorting is bound to the ObjectDataSource control, the data-bound
control passes a sort expression that identifies the data columns to use for sorting the results. For example, the GridView
control passes sort values in its SortExpression property. The ObjectDataSource control sets the value of the parameter
identified by the SortParameterName property based on the sort expression passed to it. The sort expression can specify
more than one column; if so, the column names are separated by commas. To specify a descending sort, the sort expression
can include a sort column name followed by the DESC modifier. For example, a sort expression that identifies the LastName
and FirstName columns as the columns to use for sorting would be "LastName, FirstName" for an ascending sort and
"LastName, FirstName DESC" for a descending sort.
Identifying Paging Parameters
You can specify additional parameters for a Select method that identify a page of data to be returned. The ObjectDataSource
control supports two properties that identify paging parameters:
The StartRowIndexParameterName property identifies the name of a parameter in the business object's select method
that is used to specify the starting row of the page of data.
The MaximumRowsParameterName property identifies the name of a parameter in a in the business object's select
method that is used to specify the number of rows in the page of data.
Both parameters identified by the StartRowIndexParameterName and MaximumRowsParameterName properties are of
type Int32.
The following code example shows an ObjectDataSource control configured to pass sort and page parameters to the Select
method of the specified business object:
VB
<asp:ObjectDataSource
ID="EmployeesObjectDataSource"
runat="server"
TypeName="Samples.AspNet.Controls.NorthwindEmployee"
SortParameterName="SortColumns"
EnablePaging="true"
StartRowIndexParameterName="StartRecord"
MaximumRowsParameterName="MaxRecords"
SelectMethod="GetAllEmployees" >
</asp:ObjectDataSource>

C#
<asp:ObjectDataSource
ID="EmployeesObjectDataSource"
runat="server"
TypeName="Samples.AspNet.Controls.NorthwindEmployee"
SortParameterName="SortColumns"
EnablePaging="true"
StartRowIndexParameterName="StartRecord"
MaximumRowsParameterName="MaxRecords"
SelectMethod="GetAllEmployees" >
</asp:ObjectDataSource>

The following code example shows the Select business object method called in the preceding example. The business object
method returns a page of data from the Northwind sample database, sorted in the specified order.
VB
Public Shared Sub Initialize()
' Initialize data source. Use "Northwind" connection string from configuration.

If ConfigurationManager.ConnectionStrings("Northwind") Is Nothing OrElse _


ConfigurationManager.ConnectionStrings("Northwind").ConnectionString.Trim() = "" Then

Throw New Exception("A connection string named 'Northwind' with a valid connection stri
ng " & _
"must exist in the <connectionStrings> configuration section for th
e application.")
End If

_connectionString = _
ConfigurationManager.ConnectionStrings("Northwind").ConnectionString

_initialized = True
End Sub

' Select all employees.

<DataObjectMethod(DataObjectMethodType.Select, True)> _
Public Shared Function GetAllEmployees(sortColumns As String, startRecord As Integer, maxRe
cords As Integer) As DataTable

VerifySortColumns(sortColumns)

If Not _initialized Then Initialize()


Dim sqlCommand As String = "SELECT EmployeeID, LastName, FirstName, Address, City, Region
, PostalCode FROM Employees "

If sortColumns.Trim() = "" Then


sqlCommand &= "ORDER BY EmployeeID"
Else
sqlCommand &= "ORDER BY " & sortColumns
End If

Dim conn As SqlConnection = New SqlConnection(_connectionString)


Dim da As SqlDataAdapter = New SqlDataAdapter(sqlCommand, conn)

Dim ds As DataSet = New DataSet()

Try
conn.Open()
da.Fill(ds, startRecord, maxRecords, "Employees")
Catch e As SqlException
' Handle exception.
Finally
conn.Close()
End Try
If ds.Tables("Employees") IsNot Nothing Then _
Return ds.Tables("Employees")

Return Nothing
End Function

'''''
' Verify that only valid columns are specified in the sort expression to aSub a SQL Injecti
on attack.

Private Shared Sub VerifySortColumns(sortColumns As String)

If sortColumns.ToLowerInvariant().EndsWith(" desc") Then _


sortColumns = sortColumns.Substring(0, sortColumns.Length - 5)

Dim columnNames() As String = sortColumns.Split(",")

For Each columnName As String In columnNames


Select Case columnName.Trim().ToLowerInvariant()
Case "employeeid"
Case "lastname"
Case "firstname"
Case ""
Case Else
Throw New ArgumentException("SortColumns contains an invalid column name.")
End Select
Next
End Sub

C#
public static void Initialize()
{
// Initialize data source. Use "Northwind" connection string from configuration.

if (ConfigurationManager.ConnectionStrings["Northwind"] == null ||
ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString.Trim() == "")
{
throw new Exception("A connection string named 'Northwind' with a valid connection stri
ng " +
"must exist in the <connectionStrings> configuration section for th
e application.");
}

_connectionString =
ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString;

_initialized = true;
}

// Select all employees.

[DataObjectMethod(DataObjectMethodType.Select, true)]
public static DataTable GetAllEmployees(string sortColumns, int startRecord, int maxRecords
)
{
VerifySortColumns(sortColumns);
if (!_initialized) { Initialize(); }

string sqlCommand = "SELECT EmployeeID, LastName, FirstName, Address, City, Region, Posta
lCode FROM Employees ";

if (sortColumns.Trim() == "")
sqlCommand += "ORDER BY EmployeeID";
else
sqlCommand += "ORDER BY " + sortColumns;

SqlConnection conn = new SqlConnection(_connectionString);


SqlDataAdapter da = new SqlDataAdapter(sqlCommand, conn);

DataSet ds = new DataSet();

try
{
conn.Open();
da.Fill(ds, startRecord, maxRecords, "Employees");
}
catch (SqlException e)
{
// Handle exception.
}
finally
{
conn.Close();
}

if (ds.Tables["Employees"] != null)
return ds.Tables["Employees"];

return null;
}

//////////
// Verify that only valid columns are specified in the sort expression to avoid a SQL Injec
tion attack.

private static void VerifySortColumns(string sortColumns)


{
if (sortColumns.ToLowerInvariant().EndsWith(" desc"))
sortColumns = sortColumns.Substring(0, sortColumns.Length - 5);

string[] columnNames = sortColumns.Split(',');

foreach (string columnName in columnNames)


{
switch (columnName.Trim().ToLowerInvariant())
{
case "employeeid":
break;
case "lastname":
break;
case "firstname":
break;
case "":
break;
default:
throw new ArgumentException("SortColumns contains an invalid column name.");
break;
}
}
}
Parameter Direction
By default, all parameters for business object methods are input parameters. If the business object method includes an out
parameter that returns a value to the ObjectDataSource control, you must explicitly specify a parameter with a parameter
direction as described in Using Parameters with Data Source Controls.
The following code example shows an ObjectDataSource control configured to accept an output parameter of type Int32. The
out parameter returns an automatically generated primary key value from the method specified by the InsertMethod
property.
VB
<asp:ObjectDataSource
ID="EmployeeDetailsObjectDataSource"
runat="server"
TypeName="Samples.AspNet.Controls.NorthwindEmployee"
SelectMethod="GetEmployee"
UpdateMethod="UpdateEmployee"
DeleteMethod="DeleteEmployee"
InsertMethod="InsertEmployee"
OnInserted="EmployeeDetailsObjectDataSource_OnInserted" >
<SelectParameters>
<asp:Parameter Name="EmployeeID" />
</SelectParameters>
<InsertParameters>
<asp:Parameter Name="NewEmployeeID" Direction="Output"
Type="Int32" DefaultValue="0" />
</InsertParameters>
</asp:ObjectDataSource>

C#
<asp:ObjectDataSource
ID="EmployeeDetailsObjectDataSource"
runat="server"
TypeName="Samples.AspNet.Controls.NorthwindEmployee"
SelectMethod="GetEmployee"
UpdateMethod="UpdateEmployee"
DeleteMethod="DeleteEmployee"
InsertMethod="InsertEmployee"
OnInserted="EmployeeDetailsObjectDataSource_OnInserted" >
<SelectParameters>
<asp:Parameter Name="EmployeeID" />
</SelectParameters>
<InsertParameters>
<asp:Parameter Name="NewEmployeeID" Direction="Output"
Type="Int32" DefaultValue="0" />
</InsertParameters>
</asp:ObjectDataSource>

The following code example shows the Insert business object method that returns the primary key value as an out parameter:
VB
<DataObjectMethod(DataObjectMethodType.Insert)> _
Public Shared Function InsertEmployee(ByRef NewEmployeeID As Integer, _
FirstName As String, _
LastName As String, _
Address As String, _
City As String, _
Region As String, _
PostalCode As String) As Boolean

If String.IsNullOrEmpty(FirstName) Then _
Throw New ArgumentException("FirstName cannot be null or an empty string.")
If String.IsNullOrEmpty(LastName) Then _
Throw New ArgumentException("LastName cannot be null or an empty string.")

If Address Is Nothing Then Address = String.Empty


If City Is Nothing Then City = String.Empty
If Region Is Nothing Then Region = String.Empty
If PostalCode Is Nothing Then PostalCode = String.Empty

If Not _initialized Then Initialize()

NewEmployeeID = -1

Dim conn As SqlConnection = New SqlConnection(_connectionString)


Dim cmd As SqlCommand = New SqlCommand("INSERT INTO Employees " & _
" (FirstName, LastName, Address, City, Regio
n, PostalCode) " & _
" Values(@FirstName, @LastName, @Address, @C
ity, @Region, @PostalCode) " & _
"SELECT @EmployeeID = SCOPE_IDENTITY()", conn
)

cmd.Parameters.Add("@FirstName", SqlDbType.VarChar, 10).Value = FirstName


cmd.Parameters.Add("@LastName", SqlDbType.VarChar, 20).Value = LastName
cmd.Parameters.Add("@Address", SqlDbType.VarChar, 60).Value = Address
cmd.Parameters.Add("@City", SqlDbType.VarChar, 15).Value = City
cmd.Parameters.Add("@Region", SqlDbType.VarChar, 15).Value = Region
cmd.Parameters.Add("@PostalCode", SqlDbType.VarChar, 10).Value = PostalCode
Dim p As SqlParameter = cmd.Parameters.Add("@EmployeeID", SqlDbType.Int)
p.Direction = ParameterDirection.Output

Try
conn.Open()
cmd.ExecuteNonQuery()

NewEmployeeID = CInt(p.Value)
Catch e As SqlException
' Handle exception.
Finally
conn.Close()
End Try

Return True
End Function

C#
[DataObjectMethod(DataObjectMethodType.Insert)]
public static bool InsertEmployee(out int NewEmployeeID, string FirstName, string LastName,

string Address, string City, string Region, string Postal


Code)
{
if (String.IsNullOrEmpty(FirstName))
throw new ArgumentException("FirstName cannot be null or an empty string.");
if (String.IsNullOrEmpty(LastName))
throw new ArgumentException("LastName cannot be null or an empty string.");

if (Address == null) { Address = String.Empty; }


if (City == null) { City = String.Empty; }
if (Region == null) { Region = String.Empty; }
if (PostalCode == null) { PostalCode = String.Empty; }

if (!_initialized) { Initialize(); }

NewEmployeeID = -1;

SqlConnection conn = new SqlConnection(_connectionString);


SqlCommand cmd = new SqlCommand("INSERT INTO Employees " +
" (FirstName, LastName, Address, City, Region, Posta
lCode) " +
" Values(@FirstName, @LastName, @Address, @City, @Re
gion, @PostalCode); " +
"SELECT @EmployeeID = SCOPE_IDENTITY()", conn);

cmd.Parameters.Add("@FirstName", SqlDbType.VarChar, 10).Value = FirstName;


cmd.Parameters.Add("@LastName", SqlDbType.VarChar, 20).Value = LastName;
cmd.Parameters.Add("@Address", SqlDbType.VarChar, 60).Value = Address;
cmd.Parameters.Add("@City", SqlDbType.VarChar, 15).Value = City;
cmd.Parameters.Add("@Region", SqlDbType.VarChar, 15).Value = Region;
cmd.Parameters.Add("@PostalCode", SqlDbType.VarChar, 10).Value = PostalCode;
SqlParameter p = cmd.Parameters.Add("@EmployeeID", SqlDbType.Int);
p.Direction = ParameterDirection.Output;

try
{
conn.Open();

cmd.ExecuteNonQuery();
NewEmployeeID = (int)p.Value;
}
catch (SqlException e)
{
// Handle exception.
}
finally
{
conn.Close();
}

return true;
}

Parameter Data Types


By default, all parameters for business object methods are typed as Object. If your business object method includes parameters
of different types, you must explicitly specify strongly typed parameters. For details, see
Using Parameters with Data Source Controls.
Passing Custom Parameter Types
Most business object method signatures take parameters of type String and Int32. However, you might be working with a
business object method that takes one or more parameters typed as a complex or user-defined type. To work with complex or
user-defined parameter types, you can use the ObjectDataSource control's DataObjectTypeName property.
In your business object, creating methods with long parameter lists that map control values one-to-one to data store values
can result in code that is not easily reusable. A better practice is to encapsulate your data in a custom class and then pass an
instance of the class as a parameter. That way, the data that makes up an instance of the class, such as an employee record, can
change without requiring any changes to the public interfaces exposed by the data source object. The following code example
shows a class named NorthwindExployee that defines the employee data and that can be passed as a parameter to a business
object.
C#
public class NorthwindEmployee {
public NorthwindEmployee() { }
private int _empId;
private string _firstName;
public int EmpId {
get { return _empId; }
set { _empId = value; }
}
public string FirstName {
get { return _firstName; }
set { _firstName = value; }
}
// Additional code for the class.
}

VB
Public Class NorthwindEmployee
Public Sub New()
End Sub

Private _empId As String


Public Property EmpId() As Integer
Get
Return _empId
End Get
Set
_empId = value
End Set
End Property

Private _firstName As String


Public Property FirstName() As String
Get
Return _firstName
End Get
Set
_firstName = value
End Set
End Property

' Additional code for the class.


End Class

To accept an instance of the preceding class as a parameter, the business object's UpdateEmployeeInfo method might be
defined using the following signature:
C#
public void UpdateEmployeeInfo(NorthwindEmployee emp) {
}

VB
Public Sub UpdateEmployeeInfo(emp As NorthwindEmployee)
End Sub

Although you cannot set the Type of a parameter to the name of a custom class, you can set the ObjectDataSource control's
DataObjectTypeName property to the name of a custom user-defined type, such as the NorthwindEmployee class, and then
pass an instance of the type to a business object data method. To pass user-defined objects to a data source object, the
following conditions must be met:
The user-defined type must have a default constructor (a constructor that takes no parameters).
The user-defined type must define public properties whose names match those of the dictionary entries passed to the
data source control from data-bound controls such as GridView and DetailsView. For details about these dictionaries,
see Using Parameters with Data Source Controls.
The data source object's public properties must expose both get and set accessors.
The following example shows an ObjectDataSource control that performs an update operation by calling the
UpdateEmployeeInfo method of a business object named EmployeeLogic. The ObjectDataSource control is configured to pass
an instance of the NorthwindEmployee class to the update method.

<asp:objectdatasource
runat="server"
id="ObjectDataSource1"
typename="EmployeeLogic"
selectmethod="GetAllEmployees"
updatemethod="UpdateEmployeeInfo"
dataobjecttypename="NorthwindEmployee" />

In some cases, the business object method will have a parameter list that contains multiple complex parameter types. In that
case, you can use the ObjectDataSource control, but you must add your parameters to the ObjectDataSource control
programmatically. To do this, handle the event that is raised before the data operation is performed, such as the Inserting,
Updating, or Deleting event, and set values in the InputParameters collection exposed by the
ObjectDataSourceMethodEventArgs class.
See Also
Reference
ObjectDataSource
Parameter
Other Resources
ObjectDataSource Web Server Control
Visual Web Developer

Walkthrough: Data Binding to a Custom Business Object


Many Web applications are built by using multiple tiers, with one or more components in the middle tier to provide data
access. Microsoft Visual Web Developer includes a wizard that helps you create a data component you can use as a middle-tier
data object, as described in Walkthrough: Data Binding Web Pages with a Visual Studio Data Component.
However, you might also want to build a custom business object, rather than relying on the data component created by the
wizard. Creating a custom business object allows you to implement your own business logic. This walkthrough illustrates how
to create a basic business object that you can use as a data source for ASP.NET Web pages.
During this walkthrough, you will learn how to:
Create a component that can return data to a Web page. The component uses an XML file for its data.
Reference the business object as a data source on a Web page.
Bind a control to the data returned by the business object.
Read and write data by using the business object.
Prerequisites
In order to complete this walkthrough, you will need:
Visual Web Developer (Visual Studio).
The .NET Framework.
This walkthrough assumes that you have a general understanding of how to use Visual Web Developer.
Creating the Web Site
If you have already created a Web site in Visual Web Developer (for example, by following the steps in
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and go to the next section,
"Creating an XML File for Business Data." Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, enter the name of the folder where you want to keep the pages of your Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click the programming language you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Creating an XML File for Business Data
In the following procedure, you will create a simple XML file for the business component data.
To create the XML file
1. In Solution Explorer, right-click App_Data, and then click Add New Item.
Note
Be sure you create the XML file in the App_Data folder. The App_Data folder has permissions set on it that will allow t
he Web page to read and write data to the XML file.
2. Under Visual Studio installed templates, click XML file.
3. In the Name box, type Authors.xml.
4. Click Add.
A new XML file is created that contains only the XML directive.
5. Copy the following XML data, and then paste it into the file, overwriting what is already in the file.
The XML file includes schema information that identifies the database structure of the data, including a primary-key
constraint for the key.
Note
Business components can work with data in any way that is suitable for your application. This walkthrough uses an XM
L file.

<?xml version="1.0" standalone="yes"?>


<dsPubs xmlns="http://www.tempuri.org/dsPubs.xsd">
<xs:schema id="dsPubs" targetNamespace="http://www.tempuri.org/dsPubs.xsd" xmlns:mstns
="http://www.tempuri.org/dsPubs.xsd" xmlns="http://www.tempuri.org/dsPubs.xsd" xmlns:x
s="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdat
a" attributeFormDefault="qualified" elementFormDefault="qualified">
<xs:element name="dsPubs" msdata:IsDataSet="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="authors">
<xs:complexType>
<xs:sequence>
<xs:element name="au_id" type="xs:string" />
<xs:element name="au_lname" type="xs:string" />
<xs:element name="au_fname" type="xs:string" />
<xs:element name="au_phone" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
<xs:unique name="Constraint1" msdata:PrimaryKey="true">
<xs:selector xpath=".//mstns:authors" />
<xs:field xpath="mstns:au_id" />
</xs:unique>
</xs:element>
</xs:schema>
<authors>
<au_id>172-32-1176</au_id>
<au_lname>West</au_lname>
<au_fname>Paul</au_fname>
<au_phone>408 555-0123</au_phone>
</authors>
<authors>
<au_id>213-46-8915</au_id>
<au_lname>Gray</au_lname>
<au_fname>Chris</au_fname>
<au_phone>415 555-0120</au_phone>
</authors>
</dsPubs>

6. Save the Authors.xml file, and then close it.


Creating a Component
The next step is to create a class to act as your business component. You will keep the component in the App_Code folder of
your Web site. In a real application, you can keep the component in any convenient store, including the global assembly cache.
If your Web site does not already have a directory named App_Code, you must create one.
To create an App_Code folder
In Solution Explorer, right-click the name of your Web site, click Add ASP.NET Folder, and then click App_Code.
Note
The folder must be named App_Code.

You can now add the component to your site.


To create the business component
1. In Solution Explorer, right-click the App_Code folder, and then click Add New Item.
Note
Be sure to create the new item in the App_Code folder.

The Add New Item dialog box appears.


2. Under Visual Studio installed templates, click Class.
3. In the Language box, click the programming language you prefer.
4. In the Name box, type BusinessObject.
5. Click Add.
Visual Web Developer creates the new class file and opens the code editor.
6. Copy the following code, and then paste it into the file, overwriting what is already in the file.
VB
Imports Microsoft.VisualBasic
Imports System
Imports System.Web
Imports System.Data
Namespace PubsClasses
Public Class AuthorClass
Private dsAuthors As DataSet = _
New System.Data.DataSet("ds1")
Private filePath As String = _
HttpContext.Current.Server.MapPath _
("~/App_Data/authors.xml")
Public Sub New()
dsAuthors.ReadXml(filePath, Data.XmlReadMode.ReadSchema)
End Sub

Public Function GetAuthors() As DataSet


Return dsAuthors
End Function
End Class
End Namespace

C#
using System;
using System.Web;
using System.Data;
namespace PubsClasses
{
public class AuthorClass
{
private DataSet dsAuthors = new DataSet("ds1");
private String filePath =
HttpContext.Current.Server.MapPath
("~/App_Data/Authors.xml");
public AuthorClass()
{
dsAuthors.ReadXml (filePath, XmlReadMode.ReadSchema);
}
public DataSet GetAuthors ()
{
return dsAuthors;
}
}
}

Note
Make sure the value of the filePath variable references the name of the XML file that you created previously.

When an instance of the class is created, it reads the XML file and translates it into a dataset. The class's GetAuthors
method returns the dataset.
7. Save the file. You must save the file for the next section to work properly.
Displaying Data by Using the Business Component
You can now invoke the business component in a Web page and display its data. To reference the component, you use an
ObjectDataSource control, which is specifically designed to work with objects.
To create an ObjectDataSource control that references the component
1. Switch to or open the Default.aspx page.
Note
If you do not have a Default.aspx page, you can use another page. Alternatively, you can add a new page to the Web sit
e. In Solution Explorer, right-click the name of your Web site, click Add New Item, and then add a Web Form.

2. Switch to Design view.


3. In the Toolbox, from the Data folder, drag an ObjectDataSource control onto the page.
4. In the Properties window, set ID to AuthorsObjectDataSource.
5. Right-click the ObjectDataSource control, and then click the smart tag to display the ObjectDataSource Tasks menu.
6. On the ObjectDataSource Tasks menu, click Configure Data Source.
The Configure Data Source wizard appears.
7. In the Choose your business object list, click PubsClasses.AuthorClass.
8. Click Next.
9. In the Select tab, in the Choose a method list, click GetAuthors(), returns Dataset.
The GetAuthors method is defined in the business class you created previously. It returns a dataset containing the data
from the Authors.xml file.
10. Click Finish.
The configuration information you have entered specifies that to get data from the component, the component's
GetAuthors method should be called.

Note
The name of the method you specify for the SelectMethod property is case-sensitive, even if you are programming in V
isual Basic .NET.

You can now get data from the component by using the ObjectDataSource control. You will display the data in a GridView
control on the page.
To display data from the component
1. In the Toolbox, from the Data folder, drag a GridView control onto the page.
2. Right-click the GridView control, and then click the smart tag if the Common GridView Tasks menu is not showing.
3. On the Common GridView Tasks menu, in the Choose Data Source box, click AuthorsObjectDataSource.
4. Press CTRL+F5 to run the page.
The GridView control with the XML data in it is displayed.
Inserting Data by Using the Business Component
As with other data source controls, such as the SqlDataSource control, the ObjectDataSource control supports updating
(inserting, updating, and deleting). In this section, you will modify the business component with a method that inserts an
author record. Then you will change the page so that users can type new author information and modify the
ObjectDataSource control to perform the insertion.
Note
During this part of the walkthrough, the Authors.xml file you created previously will be updated. It is important that the appli
cation have permission to write to the file at run time or the Web page will display an error when you try to update the file. If
you created the Authors.xml file in the App_Data folder, permissions are set automatically.

To modify the business component to allow inserts


1. Switch to the BusinessObject file.
2. Add the following method as the final member of AuthorClass.
VB
Public Sub InsertAuthor(ByVal au_id As String, _
ByVal au_lname As String, _
ByVal au_fname As String, ByVal au_phone As String)
Dim workRow As DataRow = dsAuthors.Tables(0).NewRow
workRow.BeginEdit()
workRow(0) = au_id
workRow(1) = au_lname
workRow(2) = au_fname
workRow(3) = au_phone
workRow.EndEdit()
dsAuthors.Tables(0).Rows.Add(workRow)
dsAuthors.WriteXml(filePath, Data.XmlWriteMode.WriteSchema)
End Sub

C#
public void InsertAuthor (String au_id, String au_lname,
String au_fname, String au_phone)
{
DataRow workRow = dsAuthors.Tables[0].NewRow ();
workRow.BeginEdit ();
workRow[0] = au_id;
workRow[1] = au_lname;
workRow[2] = au_fname;
workRow[3] = au_phone;
workRow.EndEdit ();
dsAuthors.Tables[0].Rows.Add (workRow);
dsAuthors.WriteXml (filePath, XmlWriteMode.WriteSchema);
}

Note
Pay close attention to the names of the variables used to pass author information into the method (au_id, au_lname, au
_fname, and au_phone). They must match the column names defined in the schema of the XML file you created previous
ly.

The new method takes four values to insert, which you will provide in the page as parameters. The method creates a new
row in the dataset, and then writes the updated dataset out as an XML file.
3. Save the file.
The next step is to change the page so that users can enter new author information. For the following procedure, you will use
the DetailsView control.
To add a control for inserting data
1. Switch to or open the Default.aspx page.
2. Switch to Design view.
3. In the Toolbox, from the Data folder, drag a DetailsView control onto the page.
Note
The exact layout of the page is not important.

4. On the DetailsView Tasks menu, in the Choose Data Source box, click AuthorsObjectDataSource.
Note
If the DetailsView Tasks menu is not visible, click the smart tag.

5. In the Properties window, set AutoGenerateInsertButton to true.


This causes the DetailsView control to render a New button that users can click to put the control into data-entry mode.
Finally, you must configure the ObjectDataSource control to specify what action the control should take to insert data.
To configure the data source control for inserting data
Right-click AuthorsObjectDataSource, click Properties, and then set InsertMethod to InsertAuthor.
This is the name of the method that you added to the business component.
You can now insert new authors into the XML file.
To test insertion
1. Press CTRL+F5 to run the Default.aspx page.
2. In the DetailsView control, click the New button.
The control is redisplayed with text boxes.
3. Enter new author information, and then click Insert.
The new author information is added to the XML file. The GridView control immediately reflects the new record.
Next Steps
This walkthrough illustrates how to work with a data component. You might want to experiment with additional features of
navigation. For example, you might want to:
Add update and delete functionality. To do so, you would add methods to the component. Doing so is similar to adding
the insertion logic — you add a method to the component, configure the data source control to invoke the component
method, add appropriate parameters, and add a line of code to call the Update and Delete methods of the data source
control. For details, see Walkthrough: Editing and Inserting Data in Web Pages with the DetailsView Web Server Control.
Change the business component to work with database data instead of with an XML file. You do not need to make any
changes to the controls on the page.
Restrict which users can make changes to the data. A typical method is to add membership and roles to your Web site,
and then establish rules that the business component can check before allowing changes to data. For details, see
Walkthrough: Creating a Web Site with Membership and User Login (Visual Studio) and
Walkthrough: Managing Web Site Users with Roles.
See Also
Tasks
Walkthrough: Data Binding Web Pages with a Visual Studio Data Component
Walkthrough: Using Shared Code in Web Sites in Visual Web Developer
Walkthrough: Creating a Basic Web Page in Visual Web Developer
Concepts
Data Source Controls Overview
Using Parameters with Data Source Controls
ASP.NET

Creating an ObjectDataSource Control Source Object


The source object for an ObjectDataSource control retrieves data and performs updates in the underlying data source as
requested by the ObjectDataSource control. The source object for an ObjectDataSource control can be any class that the
ObjectDataSource control can create an instance of, or that exposes public static (Shared in Microsoft Visual Basic) methods
that the ObjectDataSource control can call.
For an example of a source object and the ASP.NET page that includes an ObjectDataSource control that uses the source
object, see ObjectDataSource Source Object Example or ObjectDataSource Strongly Typed Source Object Example.
Object Creation
The ObjectDataSource control will create an instance of the source object, call the specified method, and dispose of the object
instance all within the scope of a single request, if your object has instance methods instead of static methods (Shared in
Visual Basic). Therefore, your object must be stateless. That is, your object should acquire and release all required resources
within the span of a single request.
You can control how the source object is created by handling the ObjectCreating event of the ObjectDataSource control. You
can create an instance of the source object, and then set the ObjectInstance property of the ObjectDataSourceEventArgs class
to that instance. The ObjectDataSource control will use the instance that is created in the ObjectCreating event instead of
creating an instance on its own.
Specifying a Class Constructor
If the source object for an ObjectDataSource control exposes public static methods (Shared in Visual Basic) that can be
called to retrieve and modify data, an ObjectDataSource control will call those methods directly. If an ObjectDataSource
control must create an instance of the source object in order to make method calls, the object must include a public constructor
that takes no parameters. The ObjectDataSource control will call this constructor when it creates a new instance of the source
object.
If the source object does not contain a public constructor without parameters, you can create an instance of the source object
that will be used by the ObjectDataSource control in the ObjectCreating event, as discussed in "Object Creation," earlier in
this topic.
Specifying Object Methods
The source object for an ObjectDataSource control can contain any number of methods that are used to select, insert, update,
or delete data. These methods are called by the ObjectDataSource control based on the name of the method, as identified by
using either the SelectMethod, InsertMethod, UpdateMethod, or DeleteMethod property of the ObjectDataSource control and
the names of the parameters that are in the related parameter collection for the selected action. For detailed information, see
Using Parameters with the ObjectDataSource Control.
The source object can also include an optional SelectCount method, which is identified by the ObjectDataSource control
using the SelectCountMethod property, that returns the count of the total number of objects at the data source. The
ObjectDataSource control will call the SelectCount method after a Select method has been called to retrieve the total
number of records at the data source for use when paging.
Note
It is strongly recommended that you implement a SelectCount method if your object supports paging. This will minimize th
e number of records that a data-bound control, such as the GridView control, must request to retrieve a page of data. If the to
tal row count is supplied by the source data object, a data-bound control will request only a single page of rows at a time for
each page. If the total row count is not supplied, a data-bound control must request all rows from the data source (starting wi
th the first row of the requested page of data) and discard any rows that are not in the current page.

Working with Strongly Typed Objects


Your source object can return and receive strongly typed objects based on the data from your data source. The
ObjectDataSource control identifies the type of these objects using the DataObjectTypeName property. In this scenario,
instead of passing one or more parameters to a method, one object is passed that aggregates all parameter values. For more
information about how to pass a specific object type as a parameter for a source object method, see
Using Parameters with the ObjectDataSource Control.
When the ConflictDetection property of an ObjectDataSource control is set to the CompareAllValues value, and the
OldValuesParameterFormatString property is set to a value that distinguishes parameters for original values from parameters
for current values, the ObjectDataSource will do the following:
Call the Update method from the source object that takes parameters for both current and original values.
Call the Delete method from the source object that takes parameters for original values.
When it uses a strongly typed object, the ObjectDataSource control will call the Update method from the source object that
takes both a strongly typed object that is populated with current values and a strongly typed object that is populated with
original values. However, when the ObjectDataSource control calls the Delete method and passes a strongly typed object, it
calls the method that takes a single strongly typed object as a parameter, regardless of the ConflictDetection or
OldValuesParameterFormatString setting. If the ConflictDetection property is set to the OverwriteChanges value, the
object that is passed to the Delete method is populated with current primary key values only (the other properties of the
object are null). If the ConflictDetection property is set to the CompareAllValues value, the object that is passed to the
Delete method is populated with original primary key values and original values for the rest of the object properties.
Working with Designers
Optionally, you can apply attributes to your source object that describe it to a designer, such as the Microsoft Visual Web
Developer Web development tool, as a data object. This can improve the experience of the developer who is using the designer
by specifically identifying which methods of your object are used for select, insert, update, and delete operations.
To identify your object as a source object for an ObjectDataSource control, use the DataObjectAttribute attribute, as shown in
the following example.
VB
<DataObject(True)> _
Public Class NorthwindEmployee

C#
[DataObject(true)]
public class NorthwindEmployee

To identify a method as a data object method, use the DataObjectMethodAttribute attribute. When you apply the
DataObjectMethodAttribute attribute, include one of the DataObjectMethodType enumeration values to identify the type of
method (either select, insert, update, or delete). The following code example uses the DataObjectMethodAttribute attribute
to identify a method as a Delete method.
VB
<DataObjectMethod(DataObjectMethodType.Delete)> _
Public Shared Function DeleteEmployee(EmployeeID As Integer) As Boolean

If Not _initialized Then Initialize()

Dim conn As SqlConnection = New SqlConnection(_connectionString)


Dim cmd As SqlCommand = New SqlCommand("DELETE FROM Employees WHERE EmployeeID = @Em
ployeeID", conn)
cmd.Parameters.Add("@EmployeeID", SqlDbType.Int).Value = EmployeeID

Try
conn.Open()

If cmd.ExecuteNonQuery() <> 0 Then _


Return False
Catch e As SqlException
' Handle exception.
Finally
conn.Close()
End Try

Return True
End Function

C#
[DataObjectMethod(DataObjectMethodType.Delete)]
public static bool DeleteEmployee(int EmployeeID)
{
if (!_initialized) { Initialize(); }

SqlConnection conn = new SqlConnection(_connectionString);


SqlCommand cmd = new SqlCommand("DELETE FROM Employees WHERE EmployeeID = @EmployeeID
", conn);
cmd.Parameters.Add("@EmployeeID", SqlDbType.Int).Value = EmployeeID;

try
{
conn.Open();

if (cmd.ExecuteNonQuery() == 0)
return false;
}
catch (SqlException e)
{
// Handle exception.
}
finally
{
conn.Close();
}
return true;
}

See Also
Concepts
ObjectDataSource Source Object Example
Using Parameters with the ObjectDataSource Control
Other Resources
ObjectDataSource Web Server Control
ASP.NET

ObjectDataSource Source Object Example


Illustrates a custom middle-tier business object that can be used with an ObjectDataSource control.
Example
The following code example illustrates a custom middle-tier business object that can be used with an ObjectDataSource
control. This topic also illustrates an example ASP.NET page that uses the business object as the source for an
ObjectDataSource control. The page includes a GridView control and a DetailsView control that are bound to the
ObjectDataSource control.
To use the code, you can create a code file in your Web application's App_Code subdirectory and copy the code into the file.
The business object will then be compiled dynamically and included as part of your Web application. Alternatively, you can
compile the business object and place it in the Bin directory of an ASP.NET application or in the Global Assembly Cache (GAC).
For more information on the App_Code and Bin directories, see Shared Code Folders in ASP.NET Web Sites.
VB
Imports System
Imports System.Configuration
Imports System.Data
Imports System.Data.SqlClient
Imports System.Collections.Generic
Imports System.Web.UI
Imports System.Web.UI.WebControls

Namespace Samples.AspNet.ObjectDataSource
'
' Northwind Employee Data Factory
'

Public Class NorthwindData

Private _connectionString As String

Public Sub New()


Initialize()
End Sub

Public Sub Initialize()


' Initialize data source. Use "Northwind" connection string from configuration.

If ConfigurationManager.ConnectionStrings("Northwind") Is Nothing OrElse _


ConfigurationManager.ConnectionStrings("Northwind").ConnectionString.Trim() = ""
Then
Throw New Exception("A connection string named 'Northwind' with a valid connection
string " & _
"must exist in the <connectionStrings> configuration section fo
r the application.")
End If

_connectionString = _
ConfigurationManager.ConnectionStrings("Northwind").ConnectionString
End Sub

' Select all employees.

Public Function GetAllEmployees(sortColumns As String, startRecord As Integer, maxRecor


ds As Integer) As DataTable
VerifySortColumns(sortColumns)
Dim sqlCmd As String = "SELECT EmployeeID, LastName, FirstName, Address, City, Region
, PostalCode FROM Employees "

If sortColumns.Trim() = "" Then


sqlCmd &= "ORDER BY EmployeeID"
Else
sqlCmd &= "ORDER BY " & sortColumns
End If
Dim conn As SqlConnection = New SqlConnection(_connectionString)
Dim da As SqlDataAdapter = New SqlDataAdapter(sqlCmd, conn)

Dim ds As DataSet = New DataSet()


Try
conn.Open()

da.Fill(ds, startRecord, maxRecords, "Employees")


Catch e As SqlException
' Handle exception.
Finally
conn.Close()
End Try

Return ds.Tables("Employees")
End Function

Public Function SelectCount() As Integer

Dim conn As SqlConnection = New SqlConnection(_connectionString)


Dim cmd As SqlCommand = New SqlCommand("SELECT COUNT(*) FROM Employees", conn)

Dim result As Integer = 0

Try
conn.Open()

result = CInt(cmd.ExecuteScalar())
Catch e As SqlException
' Handle exception.
Finally

conn.Close()
End Try

Return result
End Function

'''''
' Verify that only valid columns are specified in the sort expression to aSub a SQL Inj
ection attack.

Private Sub VerifySortColumns(sortColumns As String)


If sortColumns.ToLowerInvariant().EndsWith(" desc") Then _
sortColumns = sortColumns.Substring(0, sortColumns.Length - 5)

Dim columnNames() As String = sortColumns.Split(",")


For Each columnName As String In columnNames
Select Case columnName.Trim().ToLowerInvariant()
Case "employeeid"
Case "lastname"
Case "firstname"
Case ""
Case Else
Throw New ArgumentException("SortColumns contains an invalid column name.")
End Select
Next
End Sub

' Select an employee.

Public Function GetEmployee(EmployeeID As Integer) As DataTable


Dim conn As SqlConnection = New SqlConnection(_connectionString)
Dim da As SqlDataAdapter = _
New SqlDataAdapter("SELECT EmployeeID, LastName, FirstName, Address, City, Region,
PostalCode " & _
" FROM Employees WHERE EmployeeID = @EmployeeID", conn)
da.SelectCommand.Parameters.Add("@EmployeeID", SqlDbType.Int).Value = EmployeeID

Dim ds As DataSet = New DataSet()


Try
conn.Open()

da.Fill(ds, "Employees")
Catch e As SqlException
' Handle exception.
Finally
conn.Close()
End Try

Return ds.Tables("Employees")
End Function

' Delete the Employee by ID.


Public Function DeleteEmployee(EmployeeID As Integer) As Integer
Dim conn As SqlConnection = New SqlConnection(_connectionString)
Dim cmd As SqlCommand = New SqlCommand("DELETE FROM Employees WHERE EmployeeID =
@EmployeeID", conn)
cmd.Parameters.Add("@EmployeeID", SqlDbType.Int).Value = EmployeeID

Dim result As Integer = 0


Try
conn.Open()

result = cmd.ExecuteNonQuery()
Catch e As SqlException
' Handle exception.
Finally
conn.Close()
End Try

Return result
End Function

' Update the Employee by original ID.

Public Function UpdateEmployee(EmployeeID As Integer, LastName As String, FirstName As


String, _
Address As String, City As String, Region As String, _
PostalCode As String) As Integer

If String.IsNullOrEmpty(FirstName) Then _
Throw New ArgumentException("FirstName cannot be null or an empty string.")
If String.IsNullOrEmpty(LastName) Then _
Throw New ArgumentException("LastName cannot be null or an empty string.")
If Address Is Nothing Then Address = String.Empty
If City Is Nothing Then City = String.Empty
If Region Is Nothing Then Region = String.Empty
If PostalCode Is Nothing Then PostalCode = String.Empty

Dim conn As SqlConnection = New SqlConnection(_connectionString)


Dim cmd As SqlCommand = New SqlCommand("UPDATE Employees " & _
" SET FirstName=@FirstName, LastName=@LastName,
" & _
" Address=@Address, City=@City, Region=@Region,
" & _
" PostalCode=@PostalCode " & _
" WHERE EmployeeID=@EmployeeID", conn)

cmd.Parameters.Add("@FirstName", SqlDbType.VarChar, 10).Value = FirstName


cmd.Parameters.Add("@LastName", SqlDbType.VarChar, 20).Value = LastName
cmd.Parameters.Add("@Address", SqlDbType.VarChar, 60).Value = Address
cmd.Parameters.Add("@City", SqlDbType.VarChar, 15).Value = City
cmd.Parameters.Add("@Region", SqlDbType.VarChar, 15).Value = Region
cmd.Parameters.Add("@PostalCode", SqlDbType.VarChar, 10).Value = PostalCode
cmd.Parameters.Add("@EmployeeID", SqlDbType.Int).Value = EmployeeID

Dim result As Integer = 0

Try
conn.Open()
result = cmd.ExecuteNonQuery()
Catch e As SqlException
' Handle exception.
Finally
conn.Close()
End Try

Return result
End Function

' Insert an Employee.

Public Function InsertEmployee(LastName As String, FirstName As String, Address As Stri


ng, _
City As String, Region As String, PostalCode As String)
As Integer

If String.IsNullOrEmpty(FirstName) Then _
Throw New ArgumentException("FirstName cannot be null or an empty string.")
If String.IsNullOrEmpty(LastName) Then _
Throw New ArgumentException("LastName cannot be null or an empty string.")

If Address Is Nothing Then Address = String.Empty


If City Is Nothing Then City = String.Empty
If Region Is Nothing Then Region = String.Empty
If PostalCode Is Nothing Then PostalCode = String.Empty

Dim conn As SqlConnection = New SqlConnection(_connectionString)


Dim cmd As SqlCommand = New SqlCommand("INSERT INTO Employees " & _
" (FirstName, LastName, Address, City, Region, P
ostalCode) " & _
" Values(@FirstName, @LastName, @Address, @City,
@Region, @PostalCode) " & _
"SELECT @EmployeeID = SCOPE_IDENTITY()", conn)

cmd.Parameters.Add("@FirstName", SqlDbType.VarChar, 10).Value = FirstName


cmd.Parameters.Add("@LastName", SqlDbType.VarChar, 20).Value = LastName
cmd.Parameters.Add("@Address", SqlDbType.VarChar, 60).Value = Address
cmd.Parameters.Add("@City", SqlDbType.VarChar, 15).Value = City
cmd.Parameters.Add("@Region", SqlDbType.VarChar, 15).Value = Region
cmd.Parameters.Add("@PostalCode", SqlDbType.VarChar, 10).Value = PostalCode
Dim p As SqlParameter = cmd.Parameters.Add("@EmployeeID", SqlDbType.Int)
p.Direction = ParameterDirection.Output

Dim newEmployeeID As Integer = 0

Try
conn.Open()

cmd.ExecuteNonQuery()

newEmployeeID = CInt(p.Value)
Catch e As SqlException
' Handle exception.
Finally
conn.Close()
End Try

Return newEmployeeID
End Function

'
' Methods that support Optimistic Concurrency checks.
'

' Delete the Employee by ID.

Public Function DeleteEmployee(original_EmployeeID As Integer, original_LastName As Str


ing, _
original_FirstName As String, original_Address As String
, _
original_City As String, original_Region As String, _
original_PostalCode As String) As Integer

If String.IsNullOrEmpty(original_FirstName) Then _
Throw New ArgumentException("FirstName cannot be null or an empty string.")
If String.IsNullOrEmpty(original_LastName) Then _
Throw New ArgumentException("LastName cannot be null or an empty string.")

If original_Address Is Nothing Then original_Address = String.Empty


If original_City Is Nothing Then original_City = String.Empty
If original_Region Is Nothing Then original_Region = String.Empty
If original_PostalCode Is Nothing Then original_PostalCode = String.Empty

Dim sqlCmd As String = "DELETE FROM Employees WHERE EmployeeID = @original_EmployeeID


" & _
" AND LastName = @original_LastName AND FirstName = @original_FirstNa
me " & _
" AND Address = @original_Address AND City = @original_City " & _
" AND Region = @original_Region AND PostalCode = @original_PostalCode
"

Dim conn As SqlConnection = New SqlConnection(_connectionString)


Dim cmd As SqlCommand = New SqlCommand(sqlCmd, conn)

cmd.Parameters.Add("@original_EmployeeID", SqlDbType.Int).Value = original_EmployeeID


cmd.Parameters.Add("@original_FirstName", SqlDbType.VarChar, 10).Value = original_Fi
rstName
cmd.Parameters.Add("@original_LastName", SqlDbType.VarChar, 20).Value = original_La
stName
cmd.Parameters.Add("@original_Address", SqlDbType.VarChar, 60).Value = original_Ad
dress
cmd.Parameters.Add("@original_City", SqlDbType.VarChar, 15).Value = original_Ci
ty
cmd.Parameters.Add("@original_Region", SqlDbType.VarChar, 15).Value = original_Re
gion
cmd.Parameters.Add("@original_PostalCode", SqlDbType.VarChar, 10).Value = original_Po
stalCode

Dim result As Integer = 0


Try
conn.Open()

result = cmd.ExecuteNonQuery()
Catch e As SqlException
' Handle exception.
Finally
conn.Close()
End Try

Return result
End Function

' Update the Employee by original ID.

Public Function UpdateEmployee(EmployeeID As Integer, LastName As String, FirstName As


String, _
Address As String, City As String, Region As String, _
PostalCode As String, _
original_EmployeeID As Integer, original_LastName As Str
ing, _
original_FirstName As String, original_Address As String
, _
original_City As String, original_Region As String, _
original_PostalCode As String) As Integer

If String.IsNullOrEmpty(FirstName) Then _
Throw New ArgumentException("FirstName cannot be null or an empty string.")
If String.IsNullOrEmpty(LastName) Then _
Throw New ArgumentException("LastName cannot be null or an empty string.")

If Address Is Nothing Then Address = String.Empty


If City Is Nothing Then City = String.Empty
If Region Is Nothing Then Region = String.Empty
If PostalCode Is Nothing Then PostalCode = String.Empty

If original_Address Is Nothing Then original_Address = String.Empty


If original_City Is Nothing Then original_City = String.Empty
If original_Region Is Nothing Then original_Region = String.Empty
If original_PostalCode Is Nothing Then original_PostalCode = String.Empty

Dim sqlCmd As String = "UPDATE Employees " & _


" SET FirstName = @FirstName, LastName = @LastName, " & _
" Address = @Address, City = @City, Region = @Region, " & _
" PostalCode = @PostalCode " * _
" WHERE EmployeeID = @original_EmployeeID " & _
" AND LastName = @original_LastName AND FirstName = @original_FirstNa
me " & _
" AND Address = @original_Address AND City = @original_City " & _
" AND Region = @original_Region AND PostalCode = @original_PostalCode
"

Dim conn As SqlConnection = New SqlConnection(_connectionString)


Dim cmd As SqlCommand = New SqlCommand(sqlCmd, conn)

cmd.Parameters.Add("@FirstName", SqlDbType.VarChar, 10).Value = FirstName


cmd.Parameters.Add("@LastName", SqlDbType.VarChar, 20).Value = LastName
cmd.Parameters.Add("@Address", SqlDbType.VarChar, 60).Value = Address
cmd.Parameters.Add("@City", SqlDbType.VarChar, 15).Value = City
cmd.Parameters.Add("@Region", SqlDbType.VarChar, 15).Value = Region
cmd.Parameters.Add("@PostalCode", SqlDbType.VarChar, 10).Value = PostalCode
cmd.Parameters.Add("@original_EmployeeID", SqlDbType.Int).Value = original_EmployeeID
cmd.Parameters.Add("@original_FirstName", SqlDbType.VarChar, 10).Value = original_Fi
rstName
cmd.Parameters.Add("@original_LastName", SqlDbType.VarChar, 20).Value = original_La
stName
cmd.Parameters.Add("@original_Address", SqlDbType.VarChar, 60).Value = original_Ad
dress
cmd.Parameters.Add("@original_City", SqlDbType.VarChar, 15).Value = original_Ci
ty
cmd.Parameters.Add("@original_Region", SqlDbType.VarChar, 15).Value = original_Re
gion
cmd.Parameters.Add("@original_PostalCode", SqlDbType.VarChar, 10).Value = original_Po
stalCode

Dim result As Integer = 0

Try
conn.Open()

result = cmd.ExecuteNonQuery()
Catch e As SqlException
' Handle exception.
Finally
conn.Close()
End Try

Return result
End Function

End Class
End Namespace

C#
using System;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Collections.Generic;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Samples.AspNet.ObjectDataSource
{
//
// Northwind Employee Data Factory
//
public class NorthwindData
{

private string _connectionString;

public NorthwindData()
{
Initialize();
}

public void Initialize()


{
// Initialize data source. Use "Northwind" connection string from configuration.

if (ConfigurationManager.ConnectionStrings["Northwind"] == null ||
ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString.Trim() == ""
)
{
throw new Exception("A connection string named 'Northwind' with a valid connection
string " +
"must exist in the <connectionStrings> configuration section fo
r the application.");
}

_connectionString =
ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString;
}

// Select all employees.

public DataTable GetAllEmployees(string sortColumns, int startRecord, int maxRecords)


{
VerifySortColumns(sortColumns);

string sqlCmd = "SELECT EmployeeID, LastName, FirstName, Address, City, Region, Posta
lCode FROM Employees ";

if (sortColumns.Trim() == "")
sqlCmd += "ORDER BY EmployeeID";
else
sqlCmd += "ORDER BY " + sortColumns;

SqlConnection conn = new SqlConnection(_connectionString);


SqlDataAdapter da = new SqlDataAdapter(sqlCmd, conn);

DataSet ds = new DataSet();

try
{
conn.Open();

da.Fill(ds, startRecord, maxRecords, "Employees");


}
catch (SqlException e)
{
// Handle exception.
}
finally
{
conn.Close();
}

return ds.Tables["Employees"];
}

public int SelectCount()


{
SqlConnection conn = new SqlConnection(_connectionString);
SqlCommand cmd = new SqlCommand("SELECT COUNT(*) FROM Employees", conn);

int result = 0;

try
{
conn.Open();

result = (int)cmd.ExecuteScalar();
}
catch (SqlException e)
{
// Handle exception.
}
finally
{
conn.Close();
}

return result;
}

//////////
// Verify that only valid columns are specified in the sort expression to avoid a SQL I
njection attack.

private void VerifySortColumns(string sortColumns)


{
if (sortColumns.ToLowerInvariant().EndsWith(" desc"))
sortColumns = sortColumns.Substring(0, sortColumns.Length - 5);

string[] columnNames = sortColumns.Split(',');

foreach (string columnName in columnNames)


{
switch (columnName.Trim().ToLowerInvariant())
{
case "employeeid":
break;
case "lastname":
break;
case "firstname":
break;
case "":
break;
default:
throw new ArgumentException("SortColumns contains an invalid column name.");
break;
}
}
}

// Select an employee.

public DataTable GetEmployee(int EmployeeID)


{
SqlConnection conn = new SqlConnection(_connectionString);
SqlDataAdapter da =
new SqlDataAdapter("SELECT EmployeeID, LastName, FirstName, Address, City, Region,
PostalCode " +
" FROM Employees WHERE EmployeeID = @EmployeeID", conn);
da.SelectCommand.Parameters.Add("@EmployeeID", SqlDbType.Int).Value = EmployeeID;

DataSet ds = new DataSet();

try
{
conn.Open();

da.Fill(ds, "Employees");
}
catch (SqlException e)
{
// Handle exception.
}
finally
{
conn.Close();
}
return ds.Tables["Employees"];
}

// Delete the Employee by ID.

public int DeleteEmployee(int EmployeeID)


{
SqlConnection conn = new SqlConnection(_connectionString);
SqlCommand cmd = new SqlCommand("DELETE FROM Employees WHERE EmployeeID = @Employ
eeID", conn);
cmd.Parameters.Add("@EmployeeID", SqlDbType.Int).Value = EmployeeID;

int result = 0;

try
{
conn.Open();

result = cmd.ExecuteNonQuery();
}
catch (SqlException e)
{
// Handle exception.
}
finally
{
conn.Close();
}

return result;
}

// Update the Employee by original ID.

public int UpdateEmployee(int EmployeeID, string LastName, string FirstName,


string Address, string City, string Region, string PostalCode
)
{
if (String.IsNullOrEmpty(FirstName))
throw new ArgumentException("FirstName cannot be null or an empty string.");
if (String.IsNullOrEmpty(LastName))
throw new ArgumentException("LastName cannot be null or an empty string.");

if (Address == null) { Address = String.Empty; }


if (City == null) { City = String.Empty; }
if (Region == null) { Region = String.Empty; }
if (PostalCode == null) { PostalCode = String.Empty; }

SqlConnection conn = new SqlConnection(_connectionString);


SqlCommand cmd = new SqlCommand("UPDATE Employees " +
" SET FirstName=@FirstName, LastName=@LastName,
" +
" Address=@Address, City=@City, Region=@Region,
" +
" PostalCode=@PostalCode " +
" WHERE EmployeeID=@EmployeeID", conn);

cmd.Parameters.Add("@FirstName", SqlDbType.VarChar, 10).Value = FirstName;


cmd.Parameters.Add("@LastName", SqlDbType.VarChar, 20).Value = LastName;
cmd.Parameters.Add("@Address", SqlDbType.VarChar, 60).Value = Address;
cmd.Parameters.Add("@City", SqlDbType.VarChar, 15).Value = City;
cmd.Parameters.Add("@Region", SqlDbType.VarChar, 15).Value = Region;
cmd.Parameters.Add("@PostalCode", SqlDbType.VarChar, 10).Value = PostalCode;
cmd.Parameters.Add("@EmployeeID", SqlDbType.Int).Value = EmployeeID;
int result = 0;

try
{
conn.Open();

result = cmd.ExecuteNonQuery();
}
catch (SqlException e)
{
// Handle exception.
}
finally
{
conn.Close();
}

return result;
}

// Insert an Employee.

public int InsertEmployee(string LastName, string FirstName,


string Address, string City, string Region, string PostalCod
e)
{
if (String.IsNullOrEmpty(FirstName))
throw new ArgumentException("FirstName cannot be null or an empty string.");
if (String.IsNullOrEmpty(LastName))
throw new ArgumentException("LastName cannot be null or an empty string.");

if (Address == null) { Address = String.Empty; }


if (City == null) { City = String.Empty; }
if (Region == null) { Region = String.Empty; }
if (PostalCode == null) { PostalCode = String.Empty; }

SqlConnection conn = new SqlConnection(_connectionString);


SqlCommand cmd = new SqlCommand("INSERT INTO Employees " +
" (FirstName, LastName, Address, City, Region, P
ostalCode) " +
" Values(@FirstName, @LastName, @Address, @City,
@Region, @PostalCode); " +
"SELECT @EmployeeID = SCOPE_IDENTITY()", conn);

cmd.Parameters.Add("@FirstName", SqlDbType.VarChar, 10).Value = FirstName;


cmd.Parameters.Add("@LastName", SqlDbType.VarChar, 20).Value = LastName;
cmd.Parameters.Add("@Address", SqlDbType.VarChar, 60).Value = Address;
cmd.Parameters.Add("@City", SqlDbType.VarChar, 15).Value = City;
cmd.Parameters.Add("@Region", SqlDbType.VarChar, 15).Value = Region;
cmd.Parameters.Add("@PostalCode", SqlDbType.VarChar, 10).Value = PostalCode;
SqlParameter p = cmd.Parameters.Add("@EmployeeID", SqlDbType.Int);
p.Direction = ParameterDirection.Output;

int newEmployeeID = 0;

try
{
conn.Open();
cmd.ExecuteNonQuery();

newEmployeeID = (int)p.Value;
}
catch (SqlException e)
{
// Handle exception.
}
finally
{
conn.Close();
}

return newEmployeeID;
}

//
// Methods that support Optimistic Concurrency checks.
//

// Delete the Employee by ID.

public int DeleteEmployee(int original_EmployeeID, string original_LastName,


string original_FirstName, string original_Address,
string original_City, string original_Region,
string original_PostalCode)
{
if (String.IsNullOrEmpty(original_FirstName))
throw new ArgumentException("FirstName cannot be null or an empty string.");
if (String.IsNullOrEmpty(original_LastName))
throw new ArgumentException("LastName cannot be null or an empty string.");

if (original_Address == null) { original_Address = String.Empty; }


if (original_City == null) { original_City = String.Empty; }
if (original_Region == null) { original_Region = String.Empty; }
if (original_PostalCode == null) { original_PostalCode = String.Empty; }

string sqlCmd = "DELETE FROM Employees WHERE EmployeeID = @original_EmployeeID " +


" AND LastName = @original_LastName AND FirstName = @original_FirstNa
me " +
" AND Address = @original_Address AND City = @original_City " +
" AND Region = @original_Region AND PostalCode = @original_PostalCode
";

SqlConnection conn = new SqlConnection(_connectionString);


SqlCommand cmd = new SqlCommand(sqlCmd, conn);

cmd.Parameters.Add("@original_EmployeeID", SqlDbType.Int).Value = original_EmployeeID


;
cmd.Parameters.Add("@original_FirstName", SqlDbType.VarChar, 10).Value = original_Fi
rstName;
cmd.Parameters.Add("@original_LastName", SqlDbType.VarChar, 20).Value = original_La
stName;
cmd.Parameters.Add("@original_Address", SqlDbType.VarChar, 60).Value = original_Ad
dress;
cmd.Parameters.Add("@original_City", SqlDbType.VarChar, 15).Value = original_Ci
ty;
cmd.Parameters.Add("@original_Region", SqlDbType.VarChar, 15).Value = original_Re
gion;
cmd.Parameters.Add("@original_PostalCode", SqlDbType.VarChar, 10).Value = original_Po
stalCode;

int result = 0;

try
{
conn.Open();

result = cmd.ExecuteNonQuery();
}
catch (SqlException e)
{
// Handle exception.
}
finally
{
conn.Close();
}

return result;
}

// Update the Employee by original ID.

public int UpdateEmployee(int EmployeeID, string LastName, string FirstName,


string Address, string City, string Region, string PostalCode
,
int original_EmployeeID, string original_LastName,
string original_FirstName, string original_Address,
string original_City, string original_Region,
string original_PostalCode)
{
if (String.IsNullOrEmpty(FirstName))
throw new ArgumentException("FirstName cannot be null or an empty string.");
if (String.IsNullOrEmpty(LastName))
throw new ArgumentException("LastName cannot be null or an empty string.");

if (Address == null) { Address = String.Empty; }


if (City == null) { City = String.Empty; }
if (Region == null) { Region = String.Empty; }
if (PostalCode == null) { PostalCode = String.Empty; }

if (original_Address == null) { original_Address = String.Empty; }


if (original_City == null) { original_City = String.Empty; }
if (original_Region == null) { original_Region = String.Empty; }
if (original_PostalCode == null) { original_PostalCode = String.Empty; }

string sqlCmd = "UPDATE Employees " +


" SET FirstName = @FirstName, LastName = @LastName, " +
" Address = @Address, City = @City, Region = @Region, " +
" PostalCode = @PostalCode " +
" WHERE EmployeeID = @original_EmployeeID " +
" AND LastName = @original_LastName AND FirstName = @original_FirstNa
me " +
" AND Address = @original_Address AND City = @original_City " +
" AND Region = @original_Region AND PostalCode = @original_PostalCode
";

SqlConnection conn = new SqlConnection(_connectionString);


SqlCommand cmd = new SqlCommand(sqlCmd, conn);

cmd.Parameters.Add("@FirstName", SqlDbType.VarChar, 10).Value = FirstName;


cmd.Parameters.Add("@LastName", SqlDbType.VarChar, 20).Value = LastName;
cmd.Parameters.Add("@Address", SqlDbType.VarChar, 60).Value = Address;
cmd.Parameters.Add("@City", SqlDbType.VarChar, 15).Value = City;
cmd.Parameters.Add("@Region", SqlDbType.VarChar, 15).Value = Region;
cmd.Parameters.Add("@PostalCode", SqlDbType.VarChar, 10).Value = PostalCode;
cmd.Parameters.Add("@original_EmployeeID", SqlDbType.Int).Value = original_EmployeeID
;
cmd.Parameters.Add("@original_FirstName", SqlDbType.VarChar, 10).Value = original_Fi
rstName;
cmd.Parameters.Add("@original_LastName", SqlDbType.VarChar, 20).Value = original_La
stName;
cmd.Parameters.Add("@original_Address", SqlDbType.VarChar, 60).Value = original_Ad
dress;
cmd.Parameters.Add("@original_City", SqlDbType.VarChar, 15).Value = original_Ci
ty;
cmd.Parameters.Add("@original_Region", SqlDbType.VarChar, 15).Value = original_Re
gion;
cmd.Parameters.Add("@original_PostalCode", SqlDbType.VarChar, 10).Value = original_Po
stalCode;
int result = 0;

try
{
conn.Open();

result = cmd.ExecuteNonQuery();
}
catch (SqlException e)
{
// Handle exception.
}
finally
{
conn.Close();
}

return result;
}

}
}

VB
<%@ Page language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">

Sub EmployeesDetailsView_ItemInserted(sender As Object, e As DetailsViewInsertedEventArgs


)
EmployeesGridView.DataBind()
End Sub

Sub EmployeesDetailsView_ItemUpdated(sender As Object, e As DetailsViewUpdatedEventArgs)

EmployeesGridView.DataBind()
End Sub

Sub EmployeesDetailsView_ItemDeleted(sender As Object, e As DetailsViewDeletedEventArgs)

EmployeesGridView.DataBind()
End Sub

Sub EmployeesGridView_OnSelectedIndexChanged(sender As Object, e As EventArgs)


EmployeeDetailsObjectDataSource.SelectParameters("EmployeeID").DefaultValue = _
EmployeesGridView.SelectedDataKey.Value.ToString()
EmployeesDetailsView.DataBind()
End Sub

Sub EmployeeDetailsObjectDataSource_OnInserted(sender As Object, e As ObjectDataSourceSta


tusEventArgs)
EmployeeDetailsObjectDataSource.SelectParameters("EmployeeID").DefaultValue = _
e.ReturnValue.ToString()
EmployeesDetailsView.DataBind()
End Sub

Sub EmployeeDetailsObjectDataSource_OnUpdated(sender As Object, e As ObjectDataSourceStat


usEventArgs)
If CInt(e.ReturnValue) = 0 Then _
Msg.Text = "Employee was not updated. Please try again."
End Sub
Sub EmployeeDetailsObjectDataSource_OnDeleted(sender As Object, e As ObjectDataSourceStat
usEventArgs)
If CInt(e.ReturnValue) = 0 Then _
Msg.Text = "Employee was not deleted. Please try again."
End Sub

Sub Page_Load()
Msg.Text = ""
End Sub

</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>ObjectDataSource Example</title>
</head>
<body>
<form id="form1" runat="server">
<h3>ObjectDataSource Example</h3>
<asp:Label id="Msg" runat="server" ForeColor="Red" />

<asp:ObjectDataSource
ID="EmployeesObjectDataSource"
runat="server"
TypeName="Samples.AspNet.ObjectDataSource.NorthwindData"
SortParameterName="SortColumns"
EnablePaging="true"
SelectCountMethod="SelectCount"
StartRowIndexParameterName="StartRecord"
MaximumRowsParameterName="MaxRecords"
SelectMethod="GetAllEmployees" >
</asp:ObjectDataSource>

<asp:ObjectDataSource
ID="EmployeeDetailsObjectDataSource"
runat="server"
TypeName="Samples.AspNet.ObjectDataSource.NorthwindData"
ConflictDetection="CompareAllValues"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetEmployee"
InsertMethod="InsertEmployee"
UpdateMethod="UpdateEmployee"
DeleteMethod="DeleteEmployee"
OnInserted="EmployeeDetailsObjectDataSource_OnInserted"
OnUpdated="EmployeeDetailsObjectDataSource_OnUpdated"
OnDeleted="EmployeeDetailsObjectDataSource_OnDeleted">
<SelectParameters>
<asp:Parameter Name="EmployeeID" Type="Int32" />
</SelectParameters>
</asp:ObjectDataSource>

<table cellspacing="10">
<tr>
<td valign="top">
<asp:GridView ID="EmployeesGridView"
DataSourceID="EmployeesObjectDataSource"
AutoGenerateColumns="false"
AllowSorting="true"
AllowPaging="true"
PageSize="5"
DataKeyNames="EmployeeID"
OnSelectedIndexChanged="EmployeesGridView_OnSelectedIndexChanged"
RunAt="server">

<HeaderStyle backcolor="lightblue" forecolor="black"/>


<Columns>
<asp:ButtonField Text="Details..."
HeaderText="Show Details"
CommandName="Select"/>

<asp:BoundField DataField="EmployeeID" HeaderText="Employee ID" SortExpress


ion="EmployeeID" />
<asp:BoundField DataField="FirstName" HeaderText="First Name" SortExpressi
on="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="Last Name" SortExpressio
n="LastName, FirstName" />
</Columns>
</asp:GridView>
</td>
<td valign="top">
<asp:DetailsView ID="EmployeesDetailsView"
DataSourceID="EmployeeDetailsObjectDataSource"
AutoGenerateRows="false"
EmptyDataText="No records."
DataKeyNames="EmployeeID"
Gridlines="Both"
AutoGenerateInsertButton="true"
AutoGenerateEditButton="true"
AutoGenerateDeleteButton="true"
OnItemInserted="EmployeesDetailsView_ItemInserted"
OnItemUpdated="EmployeesDetailsView_ItemUpdated"
OnItemDeleted="EmployeesDetailsView_ItemDeleted"
RunAt="server">

<HeaderStyle backcolor="Navy" forecolor="White"/>

<RowStyle backcolor="White"/>

<AlternatingRowStyle backcolor="LightGray"/>

<EditRowStyle backcolor="LightCyan"/>

<Fields>
<asp:BoundField DataField="EmployeeID" HeaderText="Employee ID" InsertVisib
le="False" ReadOnly="true"/>
<asp:BoundField DataField="FirstName" HeaderText="First Name"/>
<asp:BoundField DataField="LastName" HeaderText="Last Name"/>

<asp:BoundField DataField="Address" HeaderText="Address"/>

<asp:BoundField DataField="City" HeaderText="City"/>

<asp:BoundField DataField="Region" HeaderText="Region"/>


<asp:BoundField DataField="PostalCode" HeaderText="Postal Code"/>

</Fields>
</asp:DetailsView>
</td>
</tr>
</table>
</form>
</body>
</html>

C#
<%@ Page language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">

void EmployeesDetailsView_ItemInserted(Object sender, DetailsViewInsertedEventArgs e)


{
EmployeesGridView.DataBind();
}

void EmployeesDetailsView_ItemUpdated(Object sender, DetailsViewUpdatedEventArgs e)


{
EmployeesGridView.DataBind();
}

void EmployeesDetailsView_ItemDeleted(Object sender, DetailsViewDeletedEventArgs e)


{
EmployeesGridView.DataBind();
}

void EmployeesGridView_OnSelectedIndexChanged(object sender, EventArgs e)


{
EmployeeDetailsObjectDataSource.SelectParameters["EmployeeID"].DefaultValue =
EmployeesGridView.SelectedDataKey.Value.ToString();
EmployeesDetailsView.DataBind();
}

void EmployeeDetailsObjectDataSource_OnInserted(object sender, ObjectDataSourceStatusEven


tArgs e)
{
EmployeeDetailsObjectDataSource.SelectParameters["EmployeeID"].DefaultValue =
e.ReturnValue.ToString();
EmployeesDetailsView.DataBind();
}
void EmployeeDetailsObjectDataSource_OnUpdated(object sender, ObjectDataSourceStatusEvent
Args e)
{
if ((int)e.ReturnValue == 0)
Msg.Text = "Employee was not updated. Please try again.";
}

void EmployeeDetailsObjectDataSource_OnDeleted(object sender, ObjectDataSourceStatusEvent


Args e)
{
if ((int)e.ReturnValue == 0)
Msg.Text = "Employee was not deleted. Please try again.";
}

void Page_Load()
{
Msg.Text = "";
}

</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>ObjectDataSource Example</title>
</head>
<body>
<form id="form1" runat="server">

<h3>ObjectDataSource Example</h3>
<asp:Label id="Msg" runat="server" ForeColor="Red" />

<asp:ObjectDataSource
ID="EmployeesObjectDataSource"
runat="server"
TypeName="Samples.AspNet.ObjectDataSource.NorthwindData"
SortParameterName="SortColumns"
EnablePaging="true"
SelectCountMethod="SelectCount"
StartRowIndexParameterName="StartRecord"
MaximumRowsParameterName="MaxRecords"
SelectMethod="GetAllEmployees" >
</asp:ObjectDataSource>

<asp:ObjectDataSource
ID="EmployeeDetailsObjectDataSource"
runat="server"
TypeName="Samples.AspNet.ObjectDataSource.NorthwindData"
ConflictDetection="CompareAllValues"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetEmployee"
InsertMethod="InsertEmployee"
UpdateMethod="UpdateEmployee"
DeleteMethod="DeleteEmployee"
OnInserted="EmployeeDetailsObjectDataSource_OnInserted"
OnUpdated="EmployeeDetailsObjectDataSource_OnUpdated"
OnDeleted="EmployeeDetailsObjectDataSource_OnDeleted">
<SelectParameters>
<asp:Parameter Name="EmployeeID" Type="Int32" />
</SelectParameters>
</asp:ObjectDataSource>

<table cellspacing="10">
<tr>
<td valign="top">
<asp:GridView ID="EmployeesGridView"
DataSourceID="EmployeesObjectDataSource"
AutoGenerateColumns="false"
AllowSorting="true"
AllowPaging="true"
PageSize="5"
DataKeyNames="EmployeeID"
OnSelectedIndexChanged="EmployeesGridView_OnSelectedIndexChanged"
RunAt="server">

<HeaderStyle backcolor="lightblue" forecolor="black"/>

<Columns>
<asp:ButtonField Text="Details..."
HeaderText="Show Details"
CommandName="Select"/>

<asp:BoundField DataField="EmployeeID" HeaderText="Employee ID" SortExpress


ion="EmployeeID" />
<asp:BoundField DataField="FirstName" HeaderText="First Name" SortExpressi
on="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="Last Name" SortExpressio
n="LastName, FirstName" />
</Columns>
</asp:GridView>
</td>
<td valign="top">
<asp:DetailsView ID="EmployeesDetailsView"
DataSourceID="EmployeeDetailsObjectDataSource"
AutoGenerateRows="false"
EmptyDataText="No records."
DataKeyNames="EmployeeID"
Gridlines="Both"
AutoGenerateInsertButton="true"
AutoGenerateEditButton="true"
AutoGenerateDeleteButton="true"
OnItemInserted="EmployeesDetailsView_ItemInserted"
OnItemUpdated="EmployeesDetailsView_ItemUpdated"
OnItemDeleted="EmployeesDetailsView_ItemDeleted"
RunAt="server">
<HeaderStyle backcolor="Navy" forecolor="White"/>

<RowStyle backcolor="White"/>

<AlternatingRowStyle backcolor="LightGray"/>

<EditRowStyle backcolor="LightCyan"/>
<Fields>
<asp:BoundField DataField="EmployeeID" HeaderText="Employee ID" InsertVisib
le="False" ReadOnly="true"/>
<asp:BoundField DataField="FirstName" HeaderText="First Name"/>
<asp:BoundField DataField="LastName" HeaderText="Last Name"/>

<asp:BoundField DataField="Address" HeaderText="Address"/>

<asp:BoundField DataField="City" HeaderText="City"/>

<asp:BoundField DataField="Region" HeaderText="Region"/>


<asp:BoundField DataField="PostalCode" HeaderText="Postal Code"/>

</Fields>
</asp:DetailsView>
</td>
</tr>
</table>
</form>
</body>
</html>

The example requires a connection string for the sample Northwind database on a SQL Server. The connection string must be
defined in the <connectionStrings> element of the application's configuration file. The connectionStrings section might look
like the following example:

<configuration>
<system.web>
<connectionStrings>
<add
name="Northwind"
connectionString="Data Source=localhost;Integrated Security=SSPI;Initial Catalog=No
rthwind;" />
</connectionStrings>
</system.web>
</configuration>

See Also
Reference
ObjectDataSource
Other Resources
ObjectDataSource Web Server Control
ASP.NET

ObjectDataSource Strongly Typed Source Object Example


Illustrates a custom middle-tier business object that can be used with an ObjectDataSource control.
Example
The following code example illustrates a custom middle-tier business object that can be used with an ObjectDataSource
control that specifies a strongly typed source object using the DataObjectTypeName property. This topic also illustrates an
example ASP.NET page that uses the business object as the source for an ObjectDataSource control. The page includes a
GridView control and a DetailsView control that are bound to the ObjectDataSource control.
To use the code, you can create a code file in your Web application's App_Code subdirectory and copy the code into the file.
The business object will then be compiled dynamically and included as part of your Web application. Alternatively, you can
compile the business object and place it in the Bin directory of an ASP.NET application or in the Global Assembly Cache (GAC).
For more information on the App_Code and Bin directories, see Shared Code Folders in ASP.NET Web Sites.
VB
Imports System
Imports System.Configuration
Imports System.Data
Imports System.Data.SqlClient
Imports System.Collections.Generic
Imports System.Web.UI
Imports System.Web.UI.WebControls

Namespace Samples.AspNet.ObjectDataSource

Public Class NorthwindEmployee


Private _employeeID As Integer
Private _lastName As String
Private _firstName As String
Private _address As String
Private _city As String
Private _region As String
Private _postalCode As String

Public Sub New()


End Sub

Public Property EmployeeID As Integer


Get
Return _employeeID
End Get
Set
_employeeID = value
End Set
End Property

Public Property LastName As String


Get
Return _lastName
End Get
Set
_lastName = value
End Set
End Property

Public Property FirstName As String


Get
Return _firstName
End Get
Set
_firstName = value
End Set
End Property
Public Property Address As String
Get
Return _address
End Get
Set
_address = value
End Set
End Property
Public Property City As String
Get
Return _city
End Get
Set
_city = value
End Set
End Property
Public Property Region As String
Get
Return _region
End Get
Set
_region = value
End Set
End Property
Public Property PostalCode As String
Get
Return _postalCode
End Get
Set
_postalCode = value
End Set
End Property
End Class

'
' Northwind Employee Data Factory
'

Public Class NorthwindEmployeeData


Private _connectionString As String

Public Sub New()


Initialize()
End Sub

Public Sub Initialize()


' Initialize data source. Use "Northwind" connection string from configuration.
If ConfigurationManager.ConnectionStrings("Northwind") Is Nothing OrElse _
ConfigurationManager.ConnectionStrings("Northwind").ConnectionString.Trim() = ""
Then
Throw New Exception("A connection string named 'Northwind' with a valid connection
string " & _
"must exist in the <connectionStrings> configuration section fo
r the application.")
End If

_connectionString = _
ConfigurationManager.ConnectionStrings("Northwind").ConnectionString
End Sub

' Select all employees.


Public Function GetAllEmployees(sortColumns As String, startRecord As Integer, _
maxRecords As Integer) As List(of NorthwindEmployee)

VerifySortColumns(sortColumns)

Dim sqlCmd As String = "SELECT EmployeeID, LastName, FirstName, Address, City, Region
, PostalCode FROM Employees "
If sortColumns.Trim() = "" Then
sqlCmd &= "ORDER BY EmployeeID"
Else
sqlCmd &= "ORDER BY " & sortColumns
End If

Dim conn As SqlConnection = New SqlConnection(_connectionString)


Dim cmd As SqlCommand = New SqlCommand(sqlCmd, conn)
Dim reader As SqlDataReader = Nothing
Dim employees As List(of NorthwindEmployee) = New List(of NorthwindEmployee)()
Dim count As Integer = 0

Try
conn.Open()
reader = cmd.ExecuteReader()

Do While reader.Read()
If count >= startRecord Then
If employees.Count < maxRecords Then
employees.Add(GetNorthwindEmployeeFromReader(reader))
Else
cmd.Cancel()
End If
End If

count += 1
Loop
Catch e As SqlException
' Handle exception.
Finally
If reader IsNot Nothing Then reader.Close()
conn.Close()
End Try

Return employees
End Function

'''''
' Verify that only valid columns are specified in the sort expression to aSub a SQL Inj
ection attack.

Private Sub VerifySortColumns(sortColumns As String)


If sortColumns.ToLowerInvariant().EndsWith(" desc") Then _
sortColumns = sortColumns.Substring(0, sortColumns.Length - 5)

Dim columnNames() As String = sortColumns.Split(",")

For Each columnName As String In columnNames


Select Case columnName.Trim().ToLowerInvariant()
Case "employeeid"
Case "lastname"
Case "firstname"
Case ""
Case Else
Throw New ArgumentException("SortColumns contains an invalid column name.")
End Select
Next
End Sub

Private Function GetNorthwindEmployeeFromReader(reader As SqlDataReader) As NorthwindEm


ployee
Dim employee As NorthwindEmployee = New NorthwindEmployee()

employee.EmployeeID = reader.GetInt32(0)
employee.LastName = reader.GetString(1)
employee.FirstName = reader.GetString(2)
If reader.GetValue(3) IsNot DBNull.Value Then _
employee.Address = reader.GetString(3)

If reader.GetValue(4) IsNot DBNull.Value Then _


employee.City = reader.GetString(4)

If reader.GetValue(5) IsNot DBNull.Value Then _


employee.Region = reader.GetString(5)

If reader.GetValue(6) IsNot DBNull.Value Then _


employee.PostalCode = reader.GetString(6)

Return employee
End Function

' Select an employee.

Public Function GetEmployee(EmployeeID As Integer) As List(of NorthwindEmployee)


Dim conn As SqlConnection = New SqlConnection(_connectionString)
Dim cmd As SqlCommand = _
New SqlCommand("SELECT EmployeeID, LastName, FirstName, Address, City, Region, Post
alCode " & _
" FROM Employees WHERE EmployeeID = @EmployeeID", conn)
cmd.Parameters.Add("@EmployeeID", SqlDbType.Int).Value = EmployeeID

Dim reader As SqlDataReader = Nothing


Dim employees As List(of NorthwindEmployee) = New List(of NorthwindEmployee)()

Try
conn.Open()
reader = cmd.ExecuteReader(CommandBehavior.SingleRow)

Do While reader.Read()
employees.Add(GetNorthwindEmployeeFromReader(reader))
Loop
Catch e As SqlException
' Handle exception.
Finally
If reader IsNot Nothing Then reader.Close()
conn.Close()
End Try

Return employees
End Function

'
' Update the Employee by ID.
' This method assumes that ConflictDetection is Set to OverwriteValues.

Public Function UpdateEmployee(employee As NorthwindEmployee) As Integer

If String.IsNullOrEmpty(employee.FirstName) Then _
Throw New ArgumentException("FirstName cannot be null or an empty string.")
If String.IsNullOrEmpty(employee.LastName) Then _
Throw New ArgumentException("LastName cannot be null or an empty string.")

If employee.Address Is Nothing Then employee.Address = String.Empty


If employee.City Is Nothing Then employee.City = String.Empty
If employee.Region Is Nothing Then employee.Region = String.Empty
If employee.PostalCode Is Nothing Then employee.PostalCode = String.Empty

Dim conn As SqlConnection = New SqlConnection(_connectionString)


Dim cmd As SqlCommand = New SqlCommand("UPDATE Employees " & _
" SET FirstName=@FirstName, LastName=@LastName,
" & _
" Address=@Address, City=@City, Region=@Region,
" & _
" PostalCode=@PostalCode " & _
" WHERE EmployeeID=@EmployeeID", conn)
cmd.Parameters.Add("@FirstName", SqlDbType.VarChar, 10).Value = employee.FirstName
cmd.Parameters.Add("@LastName", SqlDbType.VarChar, 20).Value = employee.LastName
cmd.Parameters.Add("@Address", SqlDbType.VarChar, 60).Value = employee.Address
cmd.Parameters.Add("@City", SqlDbType.VarChar, 15).Value = employee.City
cmd.Parameters.Add("@Region", SqlDbType.VarChar, 15).Value = employee.Region
cmd.Parameters.Add("@PostalCode", SqlDbType.VarChar, 10).Value = employee.PostalCode
cmd.Parameters.Add("@EmployeeID", SqlDbType.Int).Value = employee.EmployeeID

Dim result As Integer = 0

Try
conn.Open()

result = cmd.ExecuteNonQuery()
Catch e As SqlException
' Handle exception.
Finally
conn.Close()
End Try

Return result
End Function

' Insert an Employee.

Public Function InsertEmployee(employee As NorthwindEmployee) As Integer


If String.IsNullOrEmpty(employee.FirstName) Then _
Throw New ArgumentException("FirstName cannot be null or an empty string.")
If String.IsNullOrEmpty(employee.LastName) Then _
Throw New ArgumentException("LastName cannot be null or an empty string.")
If employee.Address Is Nothing Then employee.Address = String.Empty
If employee.City Is Nothing Then employee.City = String.Empty
If employee.Region Is Nothing Then employee.Region = String.Empty
If employee.PostalCode Is Nothing Then employee.PostalCode = String.Empty

Dim conn As SqlConnection = New SqlConnection(_connectionString)


Dim cmd As SqlCommand = New SqlCommand("INSERT INTO Employees " & _
" (FirstName, LastName, Address, City, Region, P
ostalCode) " & _
" Values(@FirstName, @LastName, @Address, @City,
@Region, @PostalCode) " & _
"SELECT @EmployeeID = SCOPE_IDENTITY()", conn)

cmd.Parameters.Add("@FirstName", SqlDbType.VarChar, 10).Value = employee.FirstName


cmd.Parameters.Add("@LastName", SqlDbType.VarChar, 20).Value = employee.LastName
cmd.Parameters.Add("@Address", SqlDbType.VarChar, 60).Value = employee.Address
cmd.Parameters.Add("@City", SqlDbType.VarChar, 15).Value = employee.City
cmd.Parameters.Add("@Region", SqlDbType.VarChar, 15).Value = employee.Region
cmd.Parameters.Add("@PostalCode", SqlDbType.VarChar, 10).Value = employee.PostalCode
Dim p As SqlParameter = cmd.Parameters.Add("@EmployeeID", SqlDbType.Int)
p.Direction = ParameterDirection.Output

Dim newEmployeeID As Integer= 0


Try
conn.Open()

cmd.ExecuteNonQuery()

newEmployeeID = CInt(p.Value)
Catch e As SqlException
' Handle exception.
Finally
conn.Close()
End Try

Return newEmployeeID
End Function

'
' Delete the Employee by ID.
' This method assumes that ConflictDetection is Set to OverwriteValues.

Public Function DeleteEmployee(employee As NorthwindEmployee) As Integer


Dim sqlCmd As String = "DELETE FROM Employees WHERE EmployeeID = @EmployeeID"

Dim conn As SqlConnection = New SqlConnection(_connectionString)


Dim cmd As SqlCommand = New SqlCommand(sqlCmd, conn)
cmd.Parameters.Add("@EmployeeID", SqlDbType.Int).Value = employee.EmployeeID

Dim result As Integer = 0

Try
conn.Open()

result = cmd.ExecuteNonQuery()
Catch e As SqlException
' Handle exception.
Finally
conn.Close()
End Try

Return result
End Function

End Class
End Namespace

C#
using System;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Collections.Generic;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Samples.AspNet.ObjectDataSource
{
public class NorthwindEmployee
{
private int _employeeID;
private string _lastName;
private string _firstName;
private string _address;
private string _city;
private string _region;
private string _postalCode;

public NorthwindEmployee()
{
}

public int EmployeeID


{
get { return _employeeID; }
set { _employeeID = value; }
}

public string LastName


{
get { return _lastName; }
set { _lastName = value; }
}

public string FirstName


{
get { return _firstName; }
set { _firstName = value; }
}

public string Address


{
get { return _address; }
set { _address = value; }
}

public string City


{
get { return _city; }
set { _city = value; }
}

public string Region


{
get { return _region; }
set { _region = value; }
}

public string PostalCode


{
get { return _postalCode; }
set { _postalCode = value; }
}
}
//
// Northwind Employee Data Factory
//

public class NorthwindEmployeeData


{

private string _connectionString;

public NorthwindEmployeeData()
{
Initialize();
}
public void Initialize()
{
// Initialize data source. Use "Northwind" connection string from configuration.

if (ConfigurationManager.ConnectionStrings["Northwind"] == null ||
ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString.Trim() == ""
)
{
throw new Exception("A connection string named 'Northwind' with a valid connection
string " +
"must exist in the <connectionStrings> configuration section fo
r the application.");
}

_connectionString =
ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString;
}

// Select all employees.

public List<NorthwindEmployee> GetAllEmployees(string sortColumns, int startRecord, int


maxRecords)
{
VerifySortColumns(sortColumns);

string sqlCmd = "SELECT EmployeeID, LastName, FirstName, Address, City, Region, Posta
lCode FROM Employees ";

if (sortColumns.Trim() == "")
sqlCmd += "ORDER BY EmployeeID";
else
sqlCmd += "ORDER BY " + sortColumns;

SqlConnection conn = new SqlConnection(_connectionString);


SqlCommand cmd = new SqlCommand(sqlCmd, conn);

SqlDataReader reader = null;


List<NorthwindEmployee> employees = new List<NorthwindEmployee>();
int count = 0;

try
{
conn.Open();

reader = cmd.ExecuteReader();

while (reader.Read())
{
if (count >= startRecord)
{
if (employees.Count < maxRecords)
employees.Add(GetNorthwindEmployeeFromReader(reader));
else
cmd.Cancel();
}

count++;
}

}
catch (SqlException e)
{
// Handle exception.
}
finally
{
if (reader != null) { reader.Close(); }
conn.Close();
}

return employees;
}

//////////
// Verify that only valid columns are specified in the sort expression to avoid a SQL I
njection attack.

private void VerifySortColumns(string sortColumns)


{
if (sortColumns.ToLowerInvariant().EndsWith(" desc"))
sortColumns = sortColumns.Substring(0, sortColumns.Length - 5);

string[] columnNames = sortColumns.Split(',');

foreach (string columnName in columnNames)


{
switch (columnName.Trim().ToLowerInvariant())
{
case "employeeid":
break;
case "lastname":
break;
case "firstname":
break;
case "":
break;
default:
throw new ArgumentException("SortColumns contains an invalid column name.");
break;
}
}
}

private NorthwindEmployee GetNorthwindEmployeeFromReader(SqlDataReader reader)


{
NorthwindEmployee employee = new NorthwindEmployee();

employee.EmployeeID = reader.GetInt32(0);
employee.LastName = reader.GetString(1);
employee.FirstName = reader.GetString(2);

if (reader.GetValue(3) != DBNull.Value)
employee.Address = reader.GetString(3);

if (reader.GetValue(4) != DBNull.Value)
employee.City = reader.GetString(4);

if (reader.GetValue(5) != DBNull.Value)
employee.Region = reader.GetString(5);

if (reader.GetValue(6) != DBNull.Value)
employee.PostalCode = reader.GetString(6);

return employee;
}

// Select an employee.
public List<NorthwindEmployee> GetEmployee(int EmployeeID)
{
SqlConnection conn = new SqlConnection(_connectionString);
SqlCommand cmd =
new SqlCommand("SELECT EmployeeID, LastName, FirstName, Address, City, Region, Post
alCode " +
" FROM Employees WHERE EmployeeID = @EmployeeID", conn);
cmd.Parameters.Add("@EmployeeID", SqlDbType.Int).Value = EmployeeID;

SqlDataReader reader = null;


List<NorthwindEmployee> employees = new List<NorthwindEmployee>();

try
{
conn.Open();

reader = cmd.ExecuteReader(CommandBehavior.SingleRow);

while (reader.Read())
employees.Add(GetNorthwindEmployeeFromReader(reader));
}
catch (SqlException e)
{
// Handle exception.
}
finally
{
if (reader != null) { reader.Close(); }

conn.Close();
}

return employees;
}

//
// Update the Employee by ID.
// This method assumes that ConflictDetection is set to OverwriteValues.

public int UpdateEmployee(NorthwindEmployee employee)


{
if (String.IsNullOrEmpty(employee.FirstName))
throw new ArgumentException("FirstName cannot be null or an empty string.");
if (String.IsNullOrEmpty(employee.LastName))
throw new ArgumentException("LastName cannot be null or an empty string.");

if (employee.Address == null) { employee.Address = String.Empty; }


if (employee.City == null) { employee.City = String.Empty; }
if (employee.Region == null) { employee.Region = String.Empty; }
if (employee.PostalCode == null) { employee.PostalCode = String.Empty; }

SqlConnection conn = new SqlConnection(_connectionString);


SqlCommand cmd = new SqlCommand("UPDATE Employees " +
" SET FirstName=@FirstName, LastName=@LastName,
" +
" Address=@Address, City=@City, Region=@Region,
" +
" PostalCode=@PostalCode " +
" WHERE EmployeeID=@EmployeeID", conn);

cmd.Parameters.Add("@FirstName", SqlDbType.VarChar, 10).Value = employee.FirstName;


cmd.Parameters.Add("@LastName", SqlDbType.VarChar, 20).Value = employee.LastName;
cmd.Parameters.Add("@Address", SqlDbType.VarChar, 60).Value = employee.Address;
cmd.Parameters.Add("@City", SqlDbType.VarChar, 15).Value = employee.City;
cmd.Parameters.Add("@Region", SqlDbType.VarChar, 15).Value = employee.Region;
cmd.Parameters.Add("@PostalCode", SqlDbType.VarChar, 10).Value = employee.PostalCode;
cmd.Parameters.Add("@EmployeeID", SqlDbType.Int).Value = employee.EmployeeID;

int result = 0;
try
{
conn.Open();

result = cmd.ExecuteNonQuery();
}
catch (SqlException e)
{
// Handle exception.
}
finally
{
conn.Close();
}

return result;
}

// Insert an Employee.

public int InsertEmployee(NorthwindEmployee employee)


{
if (String.IsNullOrEmpty(employee.FirstName))
throw new ArgumentException("FirstName cannot be null or an empty string.");
if (String.IsNullOrEmpty(employee.LastName))
throw new ArgumentException("LastName cannot be null or an empty string.");

if (employee.Address == null) { employee.Address = String.Empty; }


if (employee.City == null) { employee.City = String.Empty; }
if (employee.Region == null) { employee.Region = String.Empty; }
if (employee.PostalCode == null) { employee.PostalCode = String.Empty; }

SqlConnection conn = new SqlConnection(_connectionString);


SqlCommand cmd = new SqlCommand("INSERT INTO Employees " +
" (FirstName, LastName, Address, City, Region, P
ostalCode) " +
" Values(@FirstName, @LastName, @Address, @City,
@Region, @PostalCode); " +
"SELECT @EmployeeID = SCOPE_IDENTITY()", conn);

cmd.Parameters.Add("@FirstName", SqlDbType.VarChar, 10).Value = employee.FirstName;


cmd.Parameters.Add("@LastName", SqlDbType.VarChar, 20).Value = employee.LastName;
cmd.Parameters.Add("@Address", SqlDbType.VarChar, 60).Value = employee.Address;
cmd.Parameters.Add("@City", SqlDbType.VarChar, 15).Value = employee.City;
cmd.Parameters.Add("@Region", SqlDbType.VarChar, 15).Value = employee.Region;
cmd.Parameters.Add("@PostalCode", SqlDbType.VarChar, 10).Value = employee.PostalCode;
SqlParameter p = cmd.Parameters.Add("@EmployeeID", SqlDbType.Int);
p.Direction = ParameterDirection.Output;

int newEmployeeID = 0;

try
{
conn.Open();

cmd.ExecuteNonQuery();

newEmployeeID = (int)p.Value;
}
catch (SqlException e)
{
// Handle exception.
}
finally
{
conn.Close();
}

return newEmployeeID;
}

//
// Delete the Employee by ID.
// This method assumes that ConflictDetection is set to OverwriteValues.

public int DeleteEmployee(NorthwindEmployee employee)


{
string sqlCmd = "DELETE FROM Employees WHERE EmployeeID = @EmployeeID";

SqlConnection conn = new SqlConnection(_connectionString);


SqlCommand cmd = new SqlCommand(sqlCmd, conn);
cmd.Parameters.Add("@EmployeeID", SqlDbType.Int).Value = employee.EmployeeID;

int result = 0;

try
{
conn.Open();

result = cmd.ExecuteNonQuery();
}
catch (SqlException e)
{
// Handle exception.
}
finally
{
conn.Close();
}

return result;
}

}
}

VB
<%@ Page language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">

Sub EmployeesDetailsView_ItemInserted(sender As Object, e As DetailsViewInsertedEventArgs


)
EmployeesGridView.DataBind()
End Sub

Sub EmployeesDetailsView_ItemUpdated(sender As Object, e As DetailsViewUpdatedEventArgs)

EmployeesGridView.DataBind()
End Sub

Sub EmployeesDetailsView_ItemDeleted(sender As Object, e As DetailsViewDeletedEventArgs)

EmployeesGridView.DataBind()
End Sub

Sub EmployeesGridView_OnSelectedIndexChanged(sender As Object, e As EventArgs)


EmployeeDetailsObjectDataSource.SelectParameters("EmployeeID").DefaultValue = _
EmployeesGridView.SelectedDataKey.Value.ToString()
EmployeesDetailsView.DataBind()
End Sub

Sub EmployeeDetailsObjectDataSource_OnInserted(sender As Object, e As ObjectDataSourceSta


tusEventArgs)
EmployeeDetailsObjectDataSource.SelectParameters("EmployeeID").DefaultValue = _
e.ReturnValue.ToString()
EmployeesDetailsView.DataBind()
End Sub

Sub EmployeeDetailsObjectDataSource_OnUpdated(sender As Object, e As ObjectDataSourceStat


usEventArgs)
If CInt(e.ReturnValue) = 0 Then _
Msg.Text = "Employee was not updated. Please try again."
End Sub

Sub EmployeeDetailsObjectDataSource_OnDeleted(sender As Object, e As ObjectDataSourceStat


usEventArgs)
If CInt(e.ReturnValue) = 0 Then _
Msg.Text = "Employee was not deleted. Please try again."
End Sub

Sub Page_Load()
Msg.Text = ""
End Sub

</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>ObjectDataSource Example</title>
</head>
<body>
<form id="form1" runat="server">

<h3>ObjectDataSource Example</h3>
<asp:Label id="Msg" runat="server" ForeColor="Red" />

<asp:ObjectDataSource
ID="EmployeesObjectDataSource"
runat="server"
TypeName="Samples.AspNet.ObjectDataSource.NorthwindEmployeeData"
DataObjectTypeName="Samples.AspNet.ObjectDataSource.NorthwindEmployee"
SortParameterName="SortColumns"
EnablePaging="true"
StartRowIndexParameterName="StartRecord"
MaximumRowsParameterName="MaxRecords"
SelectMethod="GetAllEmployees" >
</asp:ObjectDataSource>

<asp:ObjectDataSource
ID="EmployeeDetailsObjectDataSource"
runat="server"
TypeName="Samples.AspNet.ObjectDataSource.NorthwindEmployeeData"
DataObjectTypeName="Samples.AspNet.ObjectDataSource.NorthwindEmployee"
SelectMethod="GetEmployee"
InsertMethod="InsertEmployee"
UpdateMethod="UpdateEmployee"
DeleteMethod="DeleteEmployee"
OnInserted="EmployeeDetailsObjectDataSource_OnInserted"
OnUpdated="EmployeeDetailsObjectDataSource_OnUpdated"
OnDeleted="EmployeeDetailsObjectDataSource_OnDeleted">
<SelectParameters>
<asp:Parameter Name="EmployeeID" Type="Int32" />
</SelectParameters>
</asp:ObjectDataSource>

<table cellspacing="10">
<tr>
<td valign="top">
<asp:GridView ID="EmployeesGridView"
DataSourceID="EmployeesObjectDataSource"
AutoGenerateColumns="false"
AllowSorting="true"
AllowPaging="true"
PageSize="5"
DataKeyNames="EmployeeID"
OnSelectedIndexChanged="EmployeesGridView_OnSelectedIndexChanged"
RunAt="server">

<HeaderStyle backcolor="lightblue" forecolor="black"/>

<Columns>
<asp:ButtonField Text="Details..."
HeaderText="Show Details"
CommandName="Select"/>

<asp:BoundField DataField="EmployeeID" HeaderText="Employee ID" SortExpress


ion="EmployeeID" />
<asp:BoundField DataField="FirstName" HeaderText="First Name" SortExpressi
on="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="Last Name" SortExpressio
n="LastName, FirstName" />
</Columns>
</asp:GridView>
</td>
<td valign="top">
<asp:DetailsView ID="EmployeesDetailsView"
DataSourceID="EmployeeDetailsObjectDataSource"
AutoGenerateRows="false"
EmptyDataText="No records."
DataKeyNames="EmployeeID"
Gridlines="Both"
AutoGenerateInsertButton="true"
AutoGenerateEditButton="true"
AutoGenerateDeleteButton="true"
OnItemInserted="EmployeesDetailsView_ItemInserted"
OnItemUpdated="EmployeesDetailsView_ItemUpdated"
OnItemDeleted="EmployeesDetailsView_ItemDeleted"
RunAt="server">

<HeaderStyle backcolor="Navy" forecolor="White"/>

<RowStyle backcolor="White"/>

<AlternatingRowStyle backcolor="LightGray"/>

<EditRowStyle backcolor="LightCyan"/>

<Fields>
<asp:BoundField DataField="EmployeeID" HeaderText="Employee ID" InsertVisib
le="False" ReadOnly="true"/>
<asp:BoundField DataField="FirstName" HeaderText="First Name"/>
<asp:BoundField DataField="LastName" HeaderText="Last Name"/>

<asp:BoundField DataField="Address" HeaderText="Address"/>

<asp:BoundField DataField="City" HeaderText="City"/>

<asp:BoundField DataField="Region" HeaderText="Region"/>


<asp:BoundField DataField="PostalCode" HeaderText="Postal Code"/>

</Fields>
</asp:DetailsView>
</td>
</tr>
</table>
</form>
</body>
</html>

C#
<%@ Page language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">

void EmployeesDetailsView_ItemInserted(Object sender, DetailsViewInsertedEventArgs e)


{
EmployeesGridView.DataBind();
}

void EmployeesDetailsView_ItemUpdated(Object sender, DetailsViewUpdatedEventArgs e)


{
EmployeesGridView.DataBind();
}

void EmployeesDetailsView_ItemDeleted(Object sender, DetailsViewDeletedEventArgs e)


{
EmployeesGridView.DataBind();
}

void EmployeesGridView_OnSelectedIndexChanged(object sender, EventArgs e)


{
EmployeeDetailsObjectDataSource.SelectParameters["EmployeeID"].DefaultValue =
EmployeesGridView.SelectedDataKey.Value.ToString();
EmployeesDetailsView.DataBind();
}

void EmployeeDetailsObjectDataSource_OnInserted(object sender, ObjectDataSourceStatusEven


tArgs e)
{
EmployeeDetailsObjectDataSource.SelectParameters["EmployeeID"].DefaultValue =
e.ReturnValue.ToString();
EmployeesDetailsView.DataBind();
}

void EmployeeDetailsObjectDataSource_OnUpdated(object sender, ObjectDataSourceStatusEvent


Args e)
{
if ((int)e.ReturnValue == 0)
Msg.Text = "Employee was not updated. Please try again.";
}

void EmployeeDetailsObjectDataSource_OnDeleted(object sender, ObjectDataSourceStatusEvent


Args e)
{
if ((int)e.ReturnValue == 0)
Msg.Text = "Employee was not deleted. Please try again.";
}

void Page_Load()
{
Msg.Text = "";
}

</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>ObjectDataSource Example</title>
</head>
<body>
<form id="form1" runat="server">

<h3>ObjectDataSource Example</h3>
<asp:Label id="Msg" runat="server" ForeColor="Red" />

<asp:ObjectDataSource
ID="EmployeesObjectDataSource"
runat="server"
TypeName="Samples.AspNet.ObjectDataSource.NorthwindEmployeeData"
DataObjectTypeName="Samples.AspNet.ObjectDataSource.NorthwindEmployee"
SortParameterName="SortColumns"
EnablePaging="true"
StartRowIndexParameterName="StartRecord"
MaximumRowsParameterName="MaxRecords"
SelectMethod="GetAllEmployees" >
</asp:ObjectDataSource>

<asp:ObjectDataSource
ID="EmployeeDetailsObjectDataSource"
runat="server"
TypeName="Samples.AspNet.ObjectDataSource.NorthwindEmployeeData"
DataObjectTypeName="Samples.AspNet.ObjectDataSource.NorthwindEmployee"
SelectMethod="GetEmployee"
InsertMethod="InsertEmployee"
UpdateMethod="UpdateEmployee"
DeleteMethod="DeleteEmployee"
OnInserted="EmployeeDetailsObjectDataSource_OnInserted"
OnUpdated="EmployeeDetailsObjectDataSource_OnUpdated"
OnDeleted="EmployeeDetailsObjectDataSource_OnDeleted">
<SelectParameters>
<asp:Parameter Name="EmployeeID" Type="Int32" />
</SelectParameters>
</asp:ObjectDataSource>

<table cellspacing="10">
<tr>
<td valign="top">
<asp:GridView ID="EmployeesGridView"
DataSourceID="EmployeesObjectDataSource"
AutoGenerateColumns="false"
AllowSorting="true"
AllowPaging="true"
PageSize="5"
DataKeyNames="EmployeeID"
OnSelectedIndexChanged="EmployeesGridView_OnSelectedIndexChanged"
RunAt="server">

<HeaderStyle backcolor="lightblue" forecolor="black"/>

<Columns>
<asp:ButtonField Text="Details..."
HeaderText="Show Details"
CommandName="Select"/>

<asp:BoundField DataField="EmployeeID" HeaderText="Employee ID" SortExpress


ion="EmployeeID" />
<asp:BoundField DataField="FirstName" HeaderText="First Name" SortExpressi
on="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="Last Name" SortExpressio
n="LastName, FirstName" />
</Columns>
</asp:GridView>
</td>
<td valign="top">
<asp:DetailsView ID="EmployeesDetailsView"
DataSourceID="EmployeeDetailsObjectDataSource"
AutoGenerateRows="false"
EmptyDataText="No records."
DataKeyNames="EmployeeID"
Gridlines="Both"
AutoGenerateInsertButton="true"
AutoGenerateEditButton="true"
AutoGenerateDeleteButton="true"
OnItemInserted="EmployeesDetailsView_ItemInserted"
OnItemUpdated="EmployeesDetailsView_ItemUpdated"
OnItemDeleted="EmployeesDetailsView_ItemDeleted"
RunAt="server">

<HeaderStyle backcolor="Navy" forecolor="White"/>

<RowStyle backcolor="White"/>

<AlternatingRowStyle backcolor="LightGray"/>

<EditRowStyle backcolor="LightCyan"/>

<Fields>
<asp:BoundField DataField="EmployeeID" HeaderText="Employee ID" InsertVisib
le="False" ReadOnly="true"/>
<asp:BoundField DataField="FirstName" HeaderText="First Name"/>
<asp:BoundField DataField="LastName" HeaderText="Last Name"/>

<asp:BoundField DataField="Address" HeaderText="Address"/>

<asp:BoundField DataField="City" HeaderText="City"/>

<asp:BoundField DataField="Region" HeaderText="Region"/>


<asp:BoundField DataField="PostalCode" HeaderText="Postal Code"/>

</Fields>
</asp:DetailsView>
</td>
</tr>
</table>
</form>
</body>
</html>

The example requires a connection string for the sample Northwind database on a SQL Server. The connection string must be
defined in the <connectionStrings> element of the application's configuration file. The connectionStrings section might look
like the following example:

<configuration>
<system.web>
<connectionStrings>
<add
name="Northwind"
connectionString="Data Source=localhost;Integrated Security=SSPI;Initial Catalog=No
rthwind;" />
</connectionStrings>

</system.web>
</configuration>

See Also
Reference
ObjectDataSource
Other Resources
ObjectDataSource Web Server Control
Visual Web Developer

XmlDataSource Web Server Control (Visual Studio)


The topics in this section describe how to work with the XmlDataSource control to represent an XML data source to data-
bound controls in a Web page.
In This Section
XmlDataSource Control Overview
Walkthrough: Creating a Web Page to Display XML Data
Filtering Data Using the XmlDataSource Control
Binding a Tabular Control to the XmlDataSource Control
See Also
Other Resources
Data Toolbox Controls
ASP.NET Data Access (Visual Studio)
ASP.NET

XmlDataSource Control Overview


The XmlDataSource control makes XML data available to data-bound controls. You can use it to display both hierarchical and
tabular data, although the XmlDataSource control is typically used to display hierarchical XML data in read-only scenarios.
Retrieving Data Using the XmlDataSource Control
The XmlDataSource loads XML data from an XML file specified using the DataFile property. XML data can also be loaded from
a string using the Data property.
The XmlDataSource control exposes attributes of XML elements as data-bindable fields. If you want to bind to values that are
not attributes, you can specify a transformation using an Extensible Sylesheet Language (XSL) style sheet. In control templates,
such as in a FormView or GridView controls, you can also bind a control in a template to XML data using the XPath data-
binding function. For information about using an XPath expression, see
Binding a Tabular Control to the XmlDataSource Control.
The following code example shows an XmlDataSource and a TreeView control bound to it. The source XML is shown after the
code example.
VB
<%@ Page Language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">
<asp:XmlDataSource
id="PeopleDataSource"
runat="server"
DataFile="~/App_Data/people.xml" />

<asp:TreeView
id="PeopleTreeView"
runat="server"
DataSourceID="PeopleDataSource">
<DataBindings>
<asp:TreeNodeBinding DataMember="LastName" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="FirstName" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="Street" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="City" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="Region" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="ZipCode" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="Title" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="Description" TextField="#InnerText" />
</DataBindings>
</asp:TreeView>

</form>
</body>
</html>

C#
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">
<asp:XmlDataSource
id="PeopleDataSource"
runat="server"
DataFile="~/App_Data/people.xml" />

<asp:TreeView
id="PeopleTreeView"
runat="server"
DataSourceID="PeopleDataSource">
<DataBindings>
<asp:TreeNodeBinding DataMember="LastName" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="FirstName" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="Street" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="City" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="Region" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="ZipCode" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="Title" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="Description" TextField="#InnerText" />
</DataBindings>
</asp:TreeView>

</form>
</body>
</html>

The following shows the XML data used by the preceding code example.

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


<People>
<Person>
<Name>
<FirstName>Manoj</FirstName>
<LastName>Syamala</LastName>
</Name>
<Address>
<Street>345 Maple St.</Street>
<City>Redmond</City>
<Region>WA</Region>
<ZipCode>01434</ZipCode>
</Address>
<Job>
<Title>CEO</Title>
<Description>Develops company strategies.</Description>
</Job>
</Person>

<Person>
<Name>
<FirstName>Jared</FirstName>
<LastName>Stivers</LastName>
</Name>
<Address>
<Street>123 Elm St.</Street>
<City>Seattle</City>
<Region>WA</Region>
<ZipCode>11223</ZipCode>
</Address>
<Job>
<Title>Attorney</Title>
<Description>Reviews legal issues.</Description>
</Job>
</Person>
<Person>
<Name>
<FirstName>Karina</FirstName>
<LastName>Agerby</LastName>
</Name>
<Address>
<Street>34 Palm Avenue</Street>
<City>Renton</City>
<Region>WA</Region>
<ZipCode>63910</ZipCode>
</Address>
<Job>
<Title>IT Director</Title>
<Description>In charge of corporate network.</Description>
</Job>
</Person>
</People>

Transforming XML Data Using the XmlDataSource Control


If you want to transform the XML data before it is displayed by a data-bound control, you can provide an Extensible Sylesheet
Language (XSL) style sheet for the XmlDataSource control. As with XML data, you typically load the style sheet from a file,
which you specify using the TransformFile property. However, you can also load the style sheet directly from a string using the
Transform property.
To supply dynamic XSLT style sheet arguments to be used by the XSL style sheet during the transformation, you can set the
TransformArgumentList property.
Note
If you specify an XPath filtering expression using the XPath property, the filter is applied after the transformation takes place.

The following code example shows an XmlDataSource and a TreeView control bound to it. The sample uses the XML data
from the preceding example. The XSL style sheet used by the example is shown after the code example.
VB
<%@ Page Language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">
<asp:XmlDataSource
id="PeopleDataSource"
runat="server"
TransformFile="~/App_Data/names.xsl"
DataFile="~/App_Data/people.xml" />

<asp:TreeView
id="PeopleTreeView"
runat="server"
DataSourceID="PeopleDataSource">
<DataBindings>
<asp:TreeNodeBinding DataMember="Name" TextField="#InnerText" />
</DataBindings>
</asp:TreeView>

</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">
<asp:XmlDataSource
id="PeopleDataSource"
runat="server"
TransformFile="~/App_Data/names.xsl"
DataFile="~/App_Data/people.xml" />

<asp:TreeView
id="PeopleTreeView"
runat="server"
DataSourceID="PeopleDataSource">
<DataBindings>
<asp:TreeNodeBinding DataMember="Name" TextField="#InnerText" />
</DataBindings>
</asp:TreeView>

</form>
</body>
</html>

The following shows the XSL style sheet used by the preceding code example.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">


<xsl:template match="People">
<Names>
<xsl:apply-templates select="Person"/>
</Names>
</xsl:template>

<xsl:template match="Person">
<xsl:apply-templates select="Name"/>
</xsl:template>

<xsl:template match="Name">
<name><xsl:value-of select="LastName"/>, <xsl:value-of select="FirstName"/></name>
</xsl:template>

</xsl:stylesheet>

Editing XML Data Using the XmlDataSource Control


The XmlDataSource control is commonly used in read-only data scenarios where a data-bound control displays XML data.
However, you can also use the XmlDataSource to edit XML data. Note that automatic update, insert, and delete operations
that work with other data source controls will not work. You must write custom code to modify data using the
XmlDataSource control.
To edit the XML data, call the GetXmlDocument method to retrieve an XmlDocument object, which is an in-memory
representation of the XML data. You can then use the object model exposed by the XmlDocument object and its XmlNode
objects, or you can use an XPath expression to manipulate data in the document. When you have made changes to the in-
memory representation of the XML data, you can save the data to disk by calling the Save method. This overwrites the XML file
on disk in its entirety.
The following list indicates some restrictions on editing XML data using the XmlDataSource control:
The XML data must be loaded from an XML file specified with the DataFile property, and not from a string of XML
specified in the Data property.
No XSLT transformation can be specified in the Transform or TransformFile properties.
The Save method does not handle concurrent save operations by different requests. If more than one user is editing an
XML file using the XmlDataSource control, there is no guarantee that all users are operating with the same data, and no
guarantee that one user will not overwrite changes from another user. It is also possible for a Save operation to fail
because of another user is writing to the XML file and has an exclusive lock on the file.

Filtering XML Data using the XmlDataSource Control


By default, the XmlDataSource control exposes all of the XML data specified by the DataFile or Data properties. However,
you can filter the data using an XPath expression. The XPath property allows you to specify an XPath filter expression that is
applied after XML data is loaded and has had any transformations applied to it. For an example, see
Filtering Data Using the XmlDataSource Control.
Caching XML Data using the XmlDataSource Control
The XmlDataSource control is typically used with an XML file, and opening and reading an XML file every time a page
requested can affect the performance of your application. Therefore, caching is enabled for the XmlDataSource control by
default. Caching lets you reduce the processing load on your server at the expense of memory on the Web server; in most
cases this is an acceptable trade-off. The XmlDataSource control caches data when the EnableCaching property is set to true,
which is the default. You set the CacheDuration property to the number of seconds that the control should cache data. You can
use the CacheExpirationPolicy to fine-tune the caching behavior of the XmlDataSource control.
Important
It is recommended that you set the EnableCaching property to false when client impersonation is enabled and the source fi
le for the XmlDataSource control is retrieved based on the client identity. If caching is enabled, cached XML data for a single
user can be viewed by all users and sensitive information could be exposed to an unwanted source. Client impersonation is e
nabled when the impersonate attribute of the identity configuration element is set to true and anonymous identification is
disabled for the application at the Web server.

See Also
Other Resources
XmlDataSource Web Server Control
Visual Web Developer

Walkthrough: Creating a Web Page to Display XML Data


Data is often made available to Web applications in XML format. However, XML data is inherently hierarchical, and you might
want to be able to use the XML data in list-based controls, such as the GridView or DropDownList control. This walkthrough
shows you how to work with XML data as if it were in a tabular database table.
During this walkthrough, you will learn how to:
Use a data source control to read XML data and make it available to list controls.
Bind the GridView and DataList controls to XML data.
Create a master-detail page that displays logically related XML data.
Apply a transformation to an .xml file to make the file usable as tabular data.
Note
You can also work with XML in hierarchical form. For details, see
Walkthrough: Displaying Hierarchical Data in a TreeView Control.

Prerequisites
In order to complete this walkthrough, you will need:
Microsoft Visual Web Developer
The .NET Framework
This walkthrough assumes that you know how to use Visual Web Developer.
Creating a Web Site
If you have already created a Web site in Visual Web Developer (for example, by following the steps in
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and skip to the next section.
Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, point to New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, click File System, and then enter the name of the folder where you want to keep your Web site.
For example, type the folder name C:\WebSites\XMLWalkthrough.
5. In the Language list, click the programming language you prefer to work in, such as Visual Basic or Visual C#.
The programming language you choose will be the default for your Web site, but you can set the programming language
for each page individually.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Creating an .xml file for Data
To have XML data to work with, create an .xml file in the Web site.
To create the .xml file
1. In Solution Explorer, right-click the App_Data folder, and then click Add New Item.
Note
When you put the .xml file in the App_Data folder, the .xml file has the correct permissions to allow ASP.NET to read fro
m and write to the file at run time. In addition, keeping files in the App_Data folder protects them from being viewed in
a browser, because the App_Data folder is marked as non-browsable.

2. Under Visual Studio installed templates, click XML file.


3. In the Name box, type Bookstore.xml.
4. Click Add.
A new .xml file is created containing only the XML directive.
5. Copy the following XML data, and then paste it into the file, overwriting what is already in the file.

<?xml version="1.0" standalone="yes"?>


<bookstore>
<book ISBN="10-000000-001"
title="The Iliad and The Odyssey"
price="12.95">
<comments>
<userComment rating="4"
comment="Best translation I've read." />
<userComment rating="2"
comment="I like other versions better." />
</comments>
</book>
<book ISBN="10-000000-999"
title="Anthology of World Literature"
price="24.95">
<comments>
<userComment rating="3"
comment="Needs more modern literature." />
<userComment rating="4"
comment="Excellent overview of world literature." />
</comments>
</book>
<book ISBN="11-000000-002"
title="Computer Dictionary"
price="24.95" >
<comments>
<userComment rating="3"
comment="A valuable resource." />
</comments>
</book>
<book ISBN="11-000000-003"
title="Cooking on a Budget"
price="23.95" >
<comments>
<userComment rating="4"
comment="Delicious!" />
</comments>
</book>
<book ISBN="11-000000-004"
title="Great Works of Art"
price="29.95" >
</book>
</bookstore>
The Bookstore.xml file contains information about books that might be available from an online bookstore. Notice the
following about the .xml file:
The property values for elements are all expressed as attributes.
The file contains a nested structure — each book can contain its property values, as well as one or more comments
as separate elements.
6. Save the Bookstore.xml file, and then close it.
Displaying XML Data in a List Control
To make data available to the controls on an ASP.NET Web page, you use a data source control.
To configure data access to the .xml file
1. Open the Default.aspx file, and then switch to Design view.
2. In the Toolbox, from the Data group, drag an XmlDataSource control onto the page.
3. On the XmlDataSource Tasks menu, click Configure Data Source.
The Configure Data Source <DataSourceName> dialog box appears.
4. In the Data file box, type ~/App_Data/Bookstore.xml.
5. Click OK.
The XmlDataSource control makes the data in the .xml file available to controls that are on the page. The data is available in
two formats: hierarchical and tabular. Controls that bind to the XmlDataSource control can get the data in the format that
works for them.
In this case, the hierarchy of the Bookstore.xml file lends itself to a relational interpretation. The two levels of the file (books and
comments) can be thought of as two related tables.
You can now display the XML data in a list control. To begin, display some of the XML data in a GridView control.
To use a GridView control for basic display of XML data
1. In the Toolbox, from the Data group, drag a GridView control onto the page.
2. On the GridView Tasks menu, in the Choose Data Source list, click XmlDataSource1.
3. Press CTRL+F5 to run the page.
The page displays the XML data in a grid.
The data displayed in the GridView control illustrates the following points about how the XML data is interpreted:
When the XML data is represented as a data record, by default, the columns are created from attributes (such as ISBN).
Child elements are treated as part of a separate related table. For this example, the GridView control does not bind to the
comments elements in the file.
Filtering XML Data Using an XPath Expression
In the first part of this walkthrough, you relied on the default behavior of the XmlDataSource and GridView controls to
extract information from the .xml file. However, the control displays only some of the XML data.
In this part of the walkthrough, you will add a second GridView control and use it to show master-detail information. Users
will be able to select an individual book in the first GridView control, and the second GridView control will display the related
user comments, if any, for that book. To display comments, you will use an XPath expression, which allows you to specify which
level of the XML data file you want to extract. Because you want to display comments for a specific book only, you will create
the XPath expression dynamically, depending on which book the user has selected.
To begin, you will add a second GridView control to the page, and then configure the GridView control so that it will display
user comments.
To add a GridView control to display user comments
1. Switch to Design view.
2. In the Toolbox, from the Data group, drag a GridView control onto the page and place it below the first GridView
control.
The GridView Tasks menu appears.
3. In the Choose Data Source box, click New data source.
The Data Source Configuration Wizard appears.
4. Click XML File as the data source.
5. In the Specify an ID for the data source box, leave the default, XmlDataSource2.
6. Click OK.
The Configure Data Source dialog box appears.
7. In the Data file box, type ~/App_Data/Bookstore.xml.
You will use the same .xml file that you used previously in this walkthrough, but you will extract different information
from it for the second GridView control.
8. In the XPath Expression box, type the following expression:
/bookstore/book/comments/userComment
Later, you will change the XPath property dynamically in code. However, by defining an XPath expression for the data
source now, you will help the tools in Visual Web Designer determine what information will ultimately be displayed in
the control.
9. Click OK.
The second GridView control appears, showing ratings and user comments as sample data.
10. Select the GridView2 control, and in Properties, set Visible to False.
The second GridView control will appear only when the user has selected a book in the first GridView control.
You can now configure the first GridView control to allow users to select a book. You will also add code that creates an XPath
expression based on the user's selection and assigns it to the XmlDataSource2 control. The end result is that the second
GridView control will display the user comments for the selected book.
To configure the GridView control for selection
1. Switch to Design view, and then select the first GridView control.
2. On the GridView Tasks menu, select Enable Selection.
A new column is added to the GridView control containing a link button with the text Select.
3. In Properties, set DataKeyNames to ISBN.
You can click the property box to select the value.
This configures the GridView control to treat the ISBN property as the primary key for each element in the XML data.
4. Click the GridView control. In the Properties window, select Events from the drop-down list at the top of the
Properties window. This will display all events associated with the control.
5. Double-click the box for the SelectedIndexChanged event.
This switches you to the code editor and creates a skeleton handler for the SelectedIndexChanged event.
6. Add the following highlighted code to the handler.
VB
Protected Sub GridView1_SelectedIndexChanged(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles GridView1.SelectedIndexChanged
Dim currentIndex As Integer
currentIndex = GridView1.SelectedIndex
Dim isbn As String
isbn = CStr(GridView1.DataKeys(currentIndex).Value)
XmlDataSource2.XPath = _
String.Format( _
"/bookstore/book[@ISBN='{0}']/comments/userComment", _
isbn)
GridView2.Visible = true
End Sub

C#
protected void GridView1_SelectedIndexChanged(Object sender, EventArgs e)
{
String isbn = (String)
GridView1.DataKeys[GridView1.SelectedIndex].Value;
XmlDataSource2.XPath =
String.Format(
"/bookstore/book[@ISBN='{0}']/comments/userComment",
isbn);
GridView2.Visible = true;
}

The code does the following:


It uses the SelectedIndex property (of the GridView control) to index into the array of data keys, and then return
the primary key of the selected row. Previously, you set the DataKeyNames property to contain ISBN numbers.
It creates a new XPath expression that includes the selected ISBN.
It assigns the new XPath expression to the XPath property (of the XmlDataSource2 control). Assigning a new XPath
expression to the XPath property causes the XmlDataSource control to re-evaluate the data it returns. The
GridView control, in turn, rebinds to the data.
It sets the Visible property to true, which causes the second GridView control to be displayed. You declaratively
set the visibility to false when you created the second GridView control so that it does not appear until the user
selects a book.
You can now test the page.
To test filtering with the XPath expression
1. View the Default.aspx page and press CTRL+F5 to run the page.
The page is displayed with a grid of information about books.
2. Click the Select link next to the first book.
The comments about that book are displayed in a second grid.
3. Click the Select link next to the last book.
No comments are displayed, because there are none for this book.
Displaying XML Data with a Custom Layout
To create a custom layout for data, you can use a DataList control. In the DataList control, you can define one or more
templates. Each template contains a combination of static text and controls that you can arrange in any layout you want.
In this part of the walkthrough, you will use a DataList control to display the same information that you previously displayed
using the GridView2 control. However, you will be able to create a custom layout for the user comments.
To display XML data with a custom layout
1. Switch to Design view, click the GridView2 control, and then press DELETE to remove it from the page.
2. In the Toolbox, from the Data group, drag a DataList control onto the page.
3. On the DataList Tasks menu, in the Choose Data Source list, click XmlDataSource2.
You will use the same data source for the DataList control that you used for the GridView2 control.
4. In Properties, set Visible to false.
5. If the smart tag does not appear, right-click the DataList control and then click Show Smart Tag.
6. On the DataList Tasks menu, click Edit Templates, and then in the Display box, click Item Template.
The DataList control appears with an editable region for the item template. The template contains a default layout that
consists of static text and Label controls that are bound to the Rating and Comment columns in the data record. (The
DataList control is able to infer the structure of the data that it will display because you defined a static XPath expression
for the XmlDataSource2 control earlier in this walkthrough.)
7. In the editable region, change the first caption to User rating:.
8. Change the caption comment to Comment:.
9. Right-click the title bar of the DataList control, point to Edit Template, and then click Separator Template.
Another editable region is displayed in the DataList control, this one for defining the layout of the elements that will
appear between each data record.
10. In the Toolbox, from the HTML group, drag a Horizontal Rule control onto the editable region.
11. Right-click the DataList control, and then click End Template Editing.
12. Right-click the page, and then click View Code to switch to the code for the page.
13. In the GridView1_SelectedIndexChanged handler, change the following line:
VB
GridView2.Visible = True

C#
GridView2.Visible = true;

to the following:
VB
DataList1.Visible = True

C#
DataList1.Visible = true;

You can now test the custom layout.


To test the custom layout
1. View the Default.aspx page and press CTRL+F5 to run the page.
The page is displayed with a grid of information about books.
2. Click the Select link next to the first book.
The comments about the first book are displayed in a list.
3. Click the Select link next to the last book.
No comments are displayed, because there are none for this book.
Using Transformations to Restructure XML Data
The .xml file that you have used in this walkthrough is structured so that the properties of each element are expressed as
attributes. In many cases, .xml files that you work with are structured differently. For example, values in an .xml file are often
created as elements with inner text.
If you have an .xml file in which property values are expressed in a format other than attributes, you can create a
transformation file (.xslt) that can dynamically reformat the .xml file so that it is compatible with the XmlDataSource control.
In this part of the walkthrough, you will work with an .xml file that contains the same data as the Bookstore.xml file that you
used previously. However, the data will be structured differently than it was in the Bookstore.xml file, so you will use a
transformation to dynamically reformat it.
To begin this section, you will create a second .xml file.
To create the second .xml file
1. In Solution Explorer, right-click the App_Data folder, and then click Add New Item.
2. Under Visual Studio installed templates, click XML file.
3. In the Name box, type Bookstore2.xml.
4. Click Add.
A new .xml file is created containing only the XML directive.
5. Copy the following XML data, and then paste it into the file, overwriting what is already in the file.

<?xml version="1.0" standalone="yes"?>


<bookstore>
<book ISBN="10-000000-001">
<title>The Iliad and The Odyssey</title>
<price>12.95</price>
<comments>
<userComment rating="4">
Best translation I've read.
</userComment>
<userComment rating="2">
I like other versions better.
</userComment>
</comments>
</book>
<book ISBN="10-000000-999">
<title>Anthology of World Literature</title>
<price>24.95</price>
<comments>
<userComment rating="3">
Needs more modern literature.
</userComment>
<userComment rating="4">
Excellent overview of world literature.
</userComment>
</comments>
</book>
<book ISBN="11-000000-002">
<title>Computer Dictionary</title>
<price>24.95</price>
<comments>
<userComment rating="3">
A valuable resource.
</userComment>
</comments>
</book>
<book ISBN="11-000000-003">
<title>Cooking on a Budget</title>
<price>23.95</price>
<comments>
<userComment rating="4">Delicious!</userComment>
</comments>
</book>
<book ISBN="11-000000-004">
<title>Great Works of Art</title>
<price>29.95</price>
</book>
</bookstore>

6. Save the Bookstore2.xml file, and then close it.


You now need a transformation file that will convert the data in the Bookstore2.xml file into the attribute-based format that is
used by the XmlDataSource control.
To create the transformation file
1. In Solution Explorer, right-click the App_Data folder, and then click Add New Item.
2. Under Visual Studio installed templates, click Text File.
There is no template for a transform file, so you can create it as a text file with the correct extension.
3. In the Name box, type Bookstore2.xsl.
Note
Be sure to use the .xsl extension.

4. Click Add.
A new blank file is created.
5. Copy the following transformation code, and then paste it into the file.

<?xml version="1.0"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
>
<xsl:strip-space elements="*"/>
<xsl:output method="xml"
omit-xml-declaration="yes"
indent="yes"
standalone="yes" />

<xsl:template match="/">
<xsl:for-each select="bookstore">
<xsl:element name="bookstore">
<xsl:for-each select="book">
<xsl:element name="book">
<xsl:attribute name="ISBN">
<xsl:value-of select="@ISBN"/>
</xsl:attribute>
<xsl:attribute name="title">
<xsl:value-of select="title"/>
</xsl:attribute>
<xsl:attribute name="price">
<xsl:value-of select="price"/>
</xsl:attribute>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

6. Save the Bookstore2.xsl file, and then close it.


From this point, working with the XML data is very similar to what you did earlier in this walkthrough, except that you can
specify the transformation file when you configure the XmlDataSource control. For the last part of this walkthrough, you will
create a new page, and then repeat some of the steps from the first part of this walkthrough. However, this time you will show
the data from the Bookstore2.xml file.
To configure data access to the .xml file
1. In Solution Explorer, right-click the name of your Web site, and then click Add New Item.
2. Under Visual Studio installed templates, click Web Form.
3. In the Name box, type Bookstore2.aspx.
4. Click Add.
5. Switch to Design view.
6. In the Toolbox, from the Data group, drag an XmlDataSource control onto the page.
7. On the XmlDataSource Tasks menu, click Configure Data Source.
The Configure Data Source dialog box appears.
8. In the Data file box, type ~/App_Data/Bookstore2.xml.
9. In the Transform file box, type ~/App_Data/Bookstore2.xsl.
10. Click OK.
11. In the Toolbox, from the Data group, drag a GridView control onto the page.
12. On the GridView Tasks menu, in the Choose Data Source list, click XmlDataSource1.
13. Press CTRL+F5 to run the page.
The page displays the XML data in a grid. The data will appear in the grid the same as it did in the first page, even though
the format of the underlying .xml file is different this time.
Next Steps
This walkthrough has illustrated only the basics of how to work with an XML document and transformations. In a real
application, you will often need to work with the XML document in more depth. The following are suggestions for further
investigation:
Creating more sophisticated transformations. In this walkthrough, you have seen only one example of how you can use
transformations. XSL is a powerful language, with sophisticated support not just for creating HTML pages, but also for
virtually any kind of transformation from XML to another structure.
Writing XML documents (instead of simply reading them). The Xml control makes it easy to display the contents of an
XML file in an ASP.NET Web page. However, you might want to create or amend XML files yourself. For details, see
XML Documents and Data. For an example of writing to an XML file, see
Walkthrough: Displaying and Tracking Advertisements with the AdRotator Control.
See Also
Tasks
Walkthrough: Displaying Hierarchical Data in a TreeView Control
Walkthrough: Creating a Basic Web Page in Visual Web Developer
ASP.NET

Filtering Data Using the XmlDataSource Control


You can filter the XML data exposed by an XmlDataSource control by setting the control's XPath property to an XPath filtering
expression. If you have specified an Extensible Stylesheet Language (XSL) style sheet to transform the data exposed by your
XmlDataSource control, the XPath filtering expression is applied after the transformation takes place.
The following code example shows an XmlDataSource control bound to a TreeView control. The XML data is filtered using an
XPath query.
VB
<%@ Page Language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">

<script runat="server">

Sub SelectRegion(sender As Object, e As EventArgs)


If RegionDropDownList.SelectedValue = "(Show All)" Then
PeopleDataSource.XPath = "/People/Person"
Else
Dim selectedValue As String = ""

Select Case RegionDropDownList.SelectedValue


Case "CA"
selectedValue = "CA"
Case "HI"
selectedValue = "HI"
Case "WA"
selectedValue = "WA"
Case Else
' Invalid value.
End Select

PeopleDataSource.XPath = "/People/Person[Address/Region='" & selectedValue & "']"


End If

PeopleTreeView.DataBind()
End Sub

</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">
<table border="0" cellpadding="3">
<tr>
<td valign="top">
<b>Select Region:</b>
<asp:DropDownList runat="server" id="RegionDropDownList" AutoPostBack="True"
OnSelectedIndexChanged="SelectRegion">

<asp:ListItem Selected="True">(Show All)</asp:ListItem>


<asp:ListItem>CA</asp:ListItem>
<asp:ListItem>HI</asp:ListItem>
<asp:ListItem>WA</asp:ListItem>
</asp:DropDownList>
</td>
<td valign="top">
<asp:XmlDataSource
id="PeopleDataSource"
runat="server"
XPath="/People/Person"
DataFile="~/App_Data/people.xml" />
<asp:TreeView
id="PeopleTreeView"
runat="server"
DataSourceID="PeopleDataSource">
<DataBindings>
<asp:TreeNodeBinding DataMember="LastName" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="FirstName" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="Street" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="City" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="Region" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="ZipCode" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="Title" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="Description" TextField="#InnerText" />
</DataBindings>
</asp:TreeView>
</td>
</tr>
</table>
</form>
</body>
</html>

C#
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">

<script runat="server">
void SelectRegion(object sender, EventArgs e)
{
if (RegionDropDownList.SelectedValue == "(Show All)")
PeopleDataSource.XPath = "/People/Person";
else
{
string selectedValue = "";
switch (RegionDropDownList.SelectedValue)
{
case "CA":
selectedValue = "CA";
break;
case "HI":
selectedValue = "HI";
break;
case "WA":
selectedValue = "WA";
break;
default:
// Invalid value.
break;
}
PeopleDataSource.XPath = "/People/Person[Address/Region='" + selectedValue + "']";
}

PeopleTreeView.DataBind();
}

</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">
<table border="0" cellpadding="3">
<tr>
<td valign="top">
<b>Select Region:</b>
<asp:DropDownList runat="server" id="RegionDropDownList" AutoPostBack="True"
OnSelectedIndexChanged="SelectRegion">
<asp:ListItem Selected="True">(Show All)</asp:ListItem>
<asp:ListItem>CA</asp:ListItem>
<asp:ListItem>HI</asp:ListItem>
<asp:ListItem>WA</asp:ListItem>
</asp:DropDownList>
</td>
<td valign="top">
<asp:XmlDataSource
id="PeopleDataSource"
runat="server"
XPath="/People/Person"
DataFile="~/App_Data/people.xml" />

<asp:TreeView
id="PeopleTreeView"
runat="server"
DataSourceID="PeopleDataSource">
<DataBindings>
<asp:TreeNodeBinding DataMember="LastName" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="FirstName" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="Street" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="City" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="Region" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="ZipCode" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="Title" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="Description" TextField="#InnerText" />
</DataBindings>
</asp:TreeView>
</td>
</tr>
</table>
</form>
</body>
</html>

See Also
Other Resources
XmlDataSource Web Server Control
ASP.NET

Binding a Tabular Control to the XmlDataSource Control


The XmlDataSource control is used primarily to expose hierarchical XML data to bound controls such as the TreeView or Menu
controls. You can also bind tabular data-bound controls such as a GridView or DataList control to the XmlDataSource control.
Binding to Fields in XML Data
When you bind a tabular data-bound control to the XmlDataSource control, the control renders only the first level of the XML
hierarchy. The XmlDataSource control exposes the attributes of the first-level nodes as the equivalent of columns in a data
table. As a result, you can specify an attribute name from the first-level node as the name of a DataField for a BoundField
object. You can also specify an attribute name in an Eval data-binding expression in a control template.
Data Binding to the XML Hierarchy using the XPath Method
Tabular controls allow you to bind controls in a template to data using the Eval or Bind methods. If you are binding the
tabular control to an XmlDataSource control, you can additionally use the XPath method, which enables you to specify an
XPath query for read-only data binding.
The XPath data-binding method navigates the XML hierarchy and returns a value from a node or an attribute anywhere in the
hierarchy. When using the XPath data-binding method, you pass an XPath query and an optional second parameter to specify
a format for the returned string. The string format parameter uses the syntax defined for the Format method of the String
class.
The following code example shows a DataList control bound to an XmlDataSource control. The data-binding expression in
the template uses the XPath method to return values from the XML data. For details about the People.xml file used for in the
example, see XmlDataSource Control Overview.
VB
<%@ Page Language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">
<asp:XmlDataSource
id="PeopleDataSource"
runat="server"
XPath="/People/Person"
DataFile="~/App_Data/people.xml" />

<asp:DataList
id="PeopleDataList"
DataSourceID="PeopleDataSource"
Runat="server">
<ItemTemplate>
<table cellpadding="4" cellspacing="4">
<tr>
<td style="vertical-align:top; width:120">
<asp:Label id="LastNameLabel" Text='<%# XPath("Name/LastName")%>' runat="se
rver" />,
<asp:Label id="FirstNameLabel" Text='<%# XPath("Name/FirstName")%>' runat="
server" />
</td>
<td valign="top">
<asp:Label id="StreetLabel" Text='<%# XPath("Address/Street") %>' runat="s
erver" /><br />
<asp:Label id="CityLabel" Text='<%# XPath("Address/City") %>' runat="serve
r" />,
<asp:Label id="RegionLabel" Text='<%# XPath("Address/Region") %>' runat="s
erver" />
<asp:Label id="ZipCodeLabel" Text='<%# XPath("Address/ZipCode") %>' runat=
"server" />
</td>
</tr>
</table>
</ItemTemplate>
</asp:DataList>
</form>
</body>
</html>

C#
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">
<asp:XmlDataSource
id="PeopleDataSource"
runat="server"
XPath="/People/Person"
DataFile="~/App_Data/people.xml" />

<asp:DataList
id="PeopleDataList"
DataSourceID="PeopleDataSource"
Runat="server">

<ItemTemplate>
<table cellpadding="4" cellspacing="4">
<tr>
<td style="vertical-align:top; width:120">
<asp:Label id="LastNameLabel" Text='<%# XPath("Name/LastName")%>' runat="se
rver" />,
<asp:Label id="FirstNameLabel" Text='<%# XPath("Name/FirstName")%>' runat="
server" />
</td>
<td valign="top">
<asp:Label id="StreetLabel" Text='<%# XPath("Address/Street") %>' runat="s
erver" /><br />
<asp:Label id="CityLabel" Text='<%# XPath("Address/City") %>' runat="serve
r" />,
<asp:Label id="RegionLabel" Text='<%# XPath("Address/Region") %>' runat="s
erver" />
<asp:Label id="ZipCodeLabel" Text='<%# XPath("Address/ZipCode") %>' runat=
"server" />
</td>
</tr>
</table>
</ItemTemplate>
</asp:DataList>
</form>
</body>
</html>

Using XPathSelect to Return Selected Nodes


You can bind a nested tabular data control in an item template to a list of nodes selected from the data supplied by an
XmlDataSource control. To do so, you can use the XPathSelect method. The XPathSelect method returns a list of nodes that
match an XPath expression, which the tabular data control can work with as if they were a collection of data records. The
following example shows how to use the XPathSelect method with a nested DataList control to display the Order_Details
nodes from within the XML hierarchy.

<asp:XmlDataSource
id="OrdersDataSource"
runat="server"
DataFile="~\App_Data\orders.xml" />

<asp:DataList
id="OrdersDataList"
DataSourceID="OrdersDataSource"
Runat="server">

<ItemTemplate>
Order ID: <asp:Label id="OrderIDLabel" runat="server"
Text='<%# XPath("OrderID") %> /><BR>

<asp:DataList id="ProductsDataList" runat="server"


DataSource='<%# XPathSelect("Order_Details") %>' >
<ItemTemplate>
<br>Product ID:<%# XPath("ProductID")%>
<br>Quantity: <%# XPath("Quantity") %>
</ItemTemplate>
</asp:DataList>

</ItemTemplate>
</asp:DataList>

See Also
Other Resources
Data Source Web Server Controls
Visual Web Developer

SiteMapDataSource Web Server Control (Visual Studio)


The SiteMapDataSource Web server control is used with ASP.NET Site Navigation. The SiteMapDataSource retrieves
navigation data from a site map provider and passes the data to controls that can display that data, such as the TreeView and
Menu controls.
For information about site map files, see ASP.NET Site Maps.
In This Section
SiteMapDataSource Web Server Control Overview
See Also
Tasks
How to: Add Simple Site Navigation
Walkthrough: Adding Site Navigation to a Web Site
How to: Filter the Nodes Retrieved by SiteMapDataSource Web Server Controls
How to: Display Site-Map Data in Non-Hierarchical Web Server Controls
Concepts
Securing ASP.NET Site Navigation
Securing Data Access
Other Resources
Data Toolbox Controls
Creating Web Site Navigation
ASP.NET Application Security in Hosted Environments
Data Web Server (ASP.NET) Controls
Individual ASP.NET Web Server Controls
ASP.NET

SiteMapDataSource Web Server Control Overview


The SiteMapDataSource Web server control retrieves navigation data from a site-map provider, and then passes the data to
controls that can display that data, such as the TreeView and Menu controls.
Note
The SiteMap control also displays navigation data, but it does not need to bind to the SiteMapDataSource control. For mor
e information, see ASP.NET Site Navigation Overview.

The SiteMapDataSource control obtains navigation data from a site map. This data includes information about the pages in
your Web site, such as the URL, title, description, and location in the navigation hierarchy. Storing your navigation data in one
place makes it easier to add and remove items in the navigational menus of your Web site.
In earlier versions of ASP and ASP.NET, when you added a page to your Web site and then added a link to that new page from
every other page in the Web site, you had to add the links manually, include a common file, or develop custom navigation
functionality. ASP.NET version 2.0 includes navigation controls that make it easier for you to create, customize, and maintain
navigational menus.
See Also
Tasks
How to: Display Site-Map Data in Non-Hierarchical Web Server Controls
How to: Add Simple Site Navigation
How to: Filter the Nodes Retrieved by SiteMapDataSource Web Server Controls
Reference
SiteMapDataSource
SiteMapPath
TreeView
Menu
XmlSiteMapProvider
Concepts
ASP.NET Site Navigation Overview
Securing ASP.NET Site Navigation
Securing Data Access
Other Resources
ASP.NET Application Security in Hosted Environments
Visual Web Developer

Validation Toolbox Controls


The topics in this section describe how to work with ASP.NET Web server controls that appear on the Standard tab of the
Visual Web Developer Toolbox. Validation controls can be used to validate user input entered in a Web form. You can validate
against a specific pattern or value as well as against a range of values. You can also specify custom error messages.
For complete syntax information for Web server controls, see Web Server Control Syntax.
In This Section
Getting Started — Validation Controls
Learning More — Validation Controls
Walkthrough Topics — Validation Controls
How-to Topics — Validation Controls
See Also
Other Resources
Individual Web and HTML Controls
ASP.NET Web Server Controls (Visual Studio)
ASP.NET Web Pages (Visual Studio)
Visual Web Developer

Getting Started — Validation Controls


The topics in this section provide essential information about the ASP.NET validation controls, including how they work and
how to add them to your ASP.NET Web pages.
In This Section
Validating User Input in ASP.NET Web Pages
Walkthrough: Validating User Input in a Web Forms Page
Types of Validation for ASP.NET Server Controls
Specifying Validation Groups
See Also
Other Resources
Validation Toolbox Controls
Individual Web and HTML Controls
ASP.NET

Validating User Input in ASP.NET Web Pages


You can add input validation to ASP.NET Web pages using validation controls. Validation controls provide an easy-to-use
mechanism for all common types of standard validation—for example, testing for valid dates or values within a range—plus
ways to provide custom-written validation. In addition, validation controls allow you to customize how error information is
displayed to the user.
Validation controls can be used with any controls you put on an ASP.NET Web page, including both HTML and Web server
controls. For more information, see ASP.NET Web Server Controls Overview.
Security Note
By default, ASP.NET Web pages automatically check for potentially malicious input. For more information, see
Script Exploits Overview.

Using Validation Controls


You enable validation of user input by adding validation controls to your page as you would add other server controls. There
are controls for different types of validation, such as range checking or pattern matching. For a complete list of validation
types, see Types of Validation for ASP.NET Server Controls. Each validation control references an input control (a server
control) elsewhere on the page. When user input is being processed (for example, when a page is submitted), the validation
control tests the user input and sets a property to indicate whether the entry passed the test. After all of the validation controls
have been called, a property on the page is set indicating whether any validation check has failed.
Validation controls can be associated into validation groups so that validation controls belonging to a common group are
validated together. You can use validation groups to selectively enable or disable validation for related controls on a page.
Other validation operations, such as displaying a ValidationSummary control or calling the GetValidators method, can
reference the validation group.
You can test the state of the page and of individual controls in your own code. For example, you would test the state of the
validation controls before updating a data record with information entered by the user. If you detect an invalid state, you
bypass the update. Typically, if any validation checks fail, you skip all of your own processing and return the page to the user.
Validation controls that detect errors then produce an error message that appears on the page. You can display all validation
errors in one place using a ValidationSummary control.
Note
Data-bound controls that update, insert, and delete data, such as the GridView, FormView, and DetailsView controls, automati
cally verify that validation checks have passed before performing a data update operation.

When Validation Occurs


Validation controls perform input checking in server code. When the user submits a page to the server, the validation controls
are invoked to check the user input, control by control. If a validation error is detected in any of the input controls, the page
itself is set to an invalid state so you can test for validity before your code runs. Validation occurs after page initialization (that
is, after view state and postback data have been processed) but before any change or click event handlers are called.
If the user is working with a browser that supports ECMAScript (Javascript), the validation controls can also perform validation
using client script. This can improve response time in the page because errors are detected immediately and error messages
are displayed as soon as the user leaves the control containing the error. If client-side validation is available, you have greater
control over the layout of error messages and can display an error summary in a message box. For more information, see
Client-Side Validation for ASP.NET Server Controls.
ASP.NET performs validation on the server even if the validation controls have already performed it on the client, so that you
can test for validity within your server-based event handlers. In addition, re-testing on the server helps prevent users from
being able to bypass validation by disabling or changing the client script check.
You can invoke validation in your own code by calling a validation control's Validate method. For more information, see
How to: Validate Programmatically for ASP.NET Server Controls.
Validating for Multiple Conditions
Each validation control typically performs one test. However, you might want to check for multiple conditions. For example,
you might want to specify both that a user entry is required and that the user entry is limited to accepting dates within a
specific range.
You can attach more than one validation control to an input control on a page. In that case, the tests performed by the controls
are resolved using a logical AND operator, which means that the data entered by the user must pass all of the tests in order to
be considered valid.
In some instances, entries in several different formats might be valid. For example, if you are prompting for a phone number,
you might allow users to enter a local number, a long-distance number, or an international number. Using multiple validation
controls would not work in this instance because the user input must pass all tests to be valid. To perform this type of test—a
logical OR operation where only one test must pass—use the RegularExpressionValidator validation control and specify
multiple valid patterns within the control. Alternatively, you can use the CustomValidator validation control and write your own
validation code.
Displaying Error Information
Validation controls are not normally visible in the rendered page. However, if the control detects an error, it displays the error
message text that you specify. The error message can be displayed in a variety of ways, as listed in the following table.
Display Description
metho
d
Inline Each validation control can individually display an error message in place (usually next to the control where the error
occurred).

Summa Validation errors can be collected and displayed in one place—for example, at the top of the page. This strategy is ofte
ry n used in combination with displaying a message next to the input fields with errors. If the user is working in Internet
Explorer 4.0 or later, the summary can be displayed in a message box.
If you are using validation groups, you need a ValidationSummary control for each separate group.

In place The error message can be different in the summary and in place. You can use this option to show a shorter error mes
and su sage in place with more detail in the summary.
mmary

Custom You can customize the error message display by capturing the error information and designing your own output.

If you use the in-place or summary display options, you can format the error message text using HTML.
Security Note
If you create custom error messages, make sure that you do not display information that might help a malicious user compr
omise your application. For more information, see How to: Display Safe Error Messages.

Validation Object Model


You can interact with validation controls by using the object model that is exposed by individual validation controls and by the
page. Each validation control exposes its own IsValid property that you can test to determine whether a validation test has
passed or failed for that control. The page also exposes an IsValid property that summarizes the IsValid state of all the
validation controls on the page. This property allows you to perform a single test to determine whether you can proceed with
your own processing.
The page also exposes a Validators collection containing a list of all the validation controls on the page. You can loop through
this collection to examine the state of individual validation controls.
Note
There are a few differences in the object model for client-side validation. For more information, see
Client-Side Validation for ASP.NET Server Controls.

Customizing Validation
You can customize the validation process in the following ways:
You can specify the format, text, and location of error messages. In addition, you can specify whether the error messages
appear individually or as a summary.
You can create custom validation using CustomValidator control. The control calls your logic but otherwise functions
like other validation controls in setting error state, displaying error messages, and so on. This provides an easy way to
create custom validation logic while still using in the validation framework of the page.
For client-side validation, you can intercept the validation call and substitute or add your own validation logic.
See Also
Other Resources
Validation ASP.NET Controls
ASP.NET

What's New in Validation


ASP.NET validation controls provide a common way of tracking validation errors across a series of controls and presenting
these errors to the user in a single place by using the ValidationSummary control.
Validation Groups
The ValidationGroup property is a new feature on many controls that allows you to associate individual controls with
validation groups and then use multiple ValidationSummary controls to collect and report errors for those groups.
If a validation group is not specified, then validation functionality is equivalent to the validation functionality in ASP.NET
version 1.0. If multiple validation groups are specified across multiple controls, then multiple validation summary controls
must be displayed because a validation summary displays validation errors only for an individual group.
Controls that post back to the server and that currently have a CausesValidation property also introduce this
ValidationGroup property, which determines the group of controls that should be validated when the control causes a
postback. If no validation group is specified, the default group, which consists of all validators without an explicit group
assignment, is validated.
Page Class Additions
The Page class now supports the GetValidators method, which retrieves validators that belong to the specified validation
group.
The Page class also exposes an overload of the Validate method with a validation group as a parameter.
ASP.NET 1.0 Compatibility
Validation code from previous versions of ASP.NET will continue to work with the current release.
See Also
Tasks
How to: Control Validation Error Message Display for ASP.NET Server Controls
Reference
Validating User Input in ASP.NET Web Pages
Visual Web Developer

Walkthrough: Validating User Input in a Web Forms Page


This walkthrough illustrates how to use ASP.NET validator controls to check user input in a Web page. You will work with some
controls that perform all checking automatically, requiring no code. You will also create a custom validator with code that you
write, which illustrates how you can add your own logic to the validation framework in the page. Finally, you will learn how you
can validate user input conditionally, depending on choices that the user makes in a page.
In the walkthrough, you will create a page for a Web site that allows visitors to request a reservation. Because the purpose of
the walkthrough is to illustrate `validation, the nature of the reservation is not important for this walkthrough (for example, if
could be for a restaurant, a community center meeting room, or something else), and the page does not actually process the
reservation.
The page you create will prompt the user for an e-mail address, the number of people to reserve for, and a preferred date. The
page also allows the user to request a telephone confirmation of the reservation. (The default for this page, if implemented,
would be e-mail confirmation.)
Security Note
By default, the Web Forms page automatically validates that malicious users are not attempting to send script to your applica
tion. For more information, see Script Exploits Overview.

During this walkthrough, you will learn how to:


Use validator controls to check user input in an ASP.NET Web page.
Format the display of validation error messages.
Create custom validation by writing code.
Prerequisites
In order to complete this walkthrough, you will need:
Visual Studio and the .NET Framework.
Creating the Web Site and Page
In the first part of the walkthrough, you will create a Web site and a page where you can work with styles.
If you have already created a Web site in Visual Studio (for example, by working with the topic
Walkthrough: Creating a Basic Web Page in Visual Web Developer ), you can use that Web site and skip to "Adding Controls"
later in this walkthrough. Otherwise, create a new Web site and page using the following steps.
To create a file system Web site
1. Open Visual Studio.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. In the Language list, click the programming language you prefer to work in.
The programming language you choose will be the default for your Web site, but you can set the programming
languages for each page individually.
4. Under Visual Studio installed templates, click ASP.NET Web Site.
5. In the Location box, enter the name of the folder where you want to keep the pages of your Web site.
For example, type the folder name C:\WebSites.
6. Click OK.
Visual Studio creates the folder and a new page named Default.aspx.
Adding Controls
You will use only a few controls to prompt the user the information required for the reservation.
You will use only a few controls to prompt the user the information required for the reservation.
To add controls and text
1. Switch to Design view.
2. Type a page heading such as Submit a Reservation.
3. From Standard group of the Toolbox, drag the following controls onto the page and set their properties as indicated.

a. Control a. Properties

TextBox ID: textEmail

TextBox ID: textNumberInParty

TextBox ID: textPreferredDate

Button ID: buttonSubmit


Text: Submit Request
ValidationGroup: AllValidators

Label ID: labelMessage


Text: (blank)
Note
The exact layout of the page is not important.

4. Type text in front of the text boxes as captions.


5. Double-click the Submit Request button to create a handler for its Click event and then add the following highlighted
code:
VB
Protected Sub buttonSubmit_Click(ByVal sender As Object, _
ByVal e As System.EventArgs)
If Page.IsValid Then
labelMessage.Text = "Your reservation has been processed."
End If
End Sub

C#
protected void buttonSubmit_Click(object sender, EventArgs e)
{
if (Page.IsValid)
{
labelMessage.Text = "Your reservation has been processed.";
}
}

The button handler simply displays a message; it performs no actual processing. However, the message display will allow
you to test the effect of validation later in the walkthrough.
6. Switch to Design view, double-click a blank area in the page to create a Page_Load handler, and then add the following
highlighted code:
VB
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As EventArgs)
labelMessage.Text = ""
End Sub

C#
protected void Page_Load(object sender, EventArgs e)
{
labelMessage.Text = "";
}

This code clears the message displayed by the page when all validation passes. The code helps with testing later in the
walkthrough.
Adding Basic Validation
For your imaginary reservation system, you will want to enforce the following validation checks:
The e-mail address is required, and it must be formatted properly; for example, someone@example.com. (It is generally
not practical to check that an e-mail address is someone's real address; however, you can check that the address
conforms to the proper pattern for e-mail addresses.)
The number of people is also required, and it must be numeric.
The preferred date is required.
You can add all of this validation using validator controls, which perform all of the checks for you and automatically display
errors.
Note
Later in the walkthrough you will add another check to be sure that users enter a valid date.

To add basic validation


1. Switch to Design view. From the Validation group of the Toolbox, drag a RequiredFieldValidator control and drop it next
to the textEmail text box.
2. Set the following properties of the RequiredFieldValidator control:
Property Setting
ControlToValidate textEmail
Binds the validator control to the text box whose contents you want to validate.

Display Dynamic
Specifies that the control renders (and takes up space in the page) only if required in order to display
an error.

ErrorMessage E-mail address is required.


Displays text in a summary error, which you will configure later in the walkthrough.

Text *
A star is a conventional way of indicating that a field is required. This text will be displayed only if ther
e is an error.
ValidationGroup AllValidators
As with radio buttons, you can group validators into groups that are treated as a unit. You will learn m
ore about grouping validators later in the walkthrough.

What you have done is added a test to be sure the user enters an e-mail address. The validator control performs all the
checking and error display with requiring you to add code to the page.
3. From the Validation group of the Toolbox, drag a RegularExpressionValidator control and drop it next to the
RequiredFieldValidator you just added.
4. Set the following properties of the RegularExpressionValidator control:

a. Proper a. Setting
ty

ControlToV textEmail
alidate
You are again validating the user's entry in the e-mail box.

Display Dynamic

ErrorMessag E-mail addresses must be in the format of name@domain.xyz.


e
A longer error message.

Text Invalid format!


A short error message.

ValidationG AllValidators
roup
As with radio buttons, you can group validators into groups that are treated as a unit. You will learn more
about grouping validators later in the walkthrough.

5. With the RegularExpressionValidator control still selected, in the Property window click the ellipsis button in the
ValidationExpression box.
Regular expressions constitute a language that can be used to find precisely defined patterns in strings. In the
RegularExpressionValidator control, you define a regular expression for the pattern that is valid — in this case, the
pattern for a valid e-mail address.
The Regular Expression Editor contains a list of commonly used regular expressions so that you can use the validator
control without learning regular expression syntax.
6. In the Standard Expressions list, click Internet E-mail Address.
The regular expression for an e-mail address is put in the Validation Expression box.
7. Click OK to close the dialog box.
8. Add another RequiredFieldValidator control, using the instructions from Steps 1-3. This time, however, bind it to the
textNumberInParty text box and set its ErrorMessage property to Please indicate how many people are in your
party.
9. From the Validation group of the Toolbox, drag a RangeValidator control and drop it next to the
RequiredFieldValidator you just added.
10. Set the following properties of the RangeValidator control:

a. Property a. Setting

ControlToValidate textNumberInParty
Display Dynamic
ErrorMessage Enter a number between 1 and 20 for the number of people in your party.

MaximumValue 20
In this case, an arbitrary but high value.

MinimumValue 1
In this application, a reservation requires at least one person.

Text Enter a number between 1 and 20.

ValidationGroup AllValidators

The RangeValidator control performs two functions: it ensures that the data a user enters is numeric, and it checks that
the number is between the specified minimum and maximum values.
Testing the Page
You can now test the validator controls that you have so far.
To test basic validation
1. Press CTRL+F5 to run the page.
2. When the page appears in the browser, click the Submit Request button.
Several validation errors are displayed, because you have not filled in some required fields. Note that the validation
errors are displayed immediately — the page is not submitted. By default, the validator controls inject client-side
ECMAScript (JavaScript) into the page to perform validation checking in the browser. This gives users instant feedback on
validation errors; without the client script, checking for validation errors would require a round trip to the server, which
could be slow at times. In fact, you cannot submit the page until the client-side validation checks all pass. (The same
validation check is performed again when the page is submitted as a security precaution.)
3. Check the validation on the textEmail text box by typing an invalid e-mail address, and then again with a valid e-mail
address such as your own.
4. Check that you can enter only numeric values between 1 and 20 in the Number of people in party text box.
5. When you have entered valid values, click the Submit Request button. If the validation passes for all controls, you will
see the message Your reservation has been processed.
6. After you have confirmed that validation is working as expected, close the browser.
If validation is not working as expected, double-check that you have made all the property settings listed above and then run
the page again.
Alternative Ways to Display Error Information
By default, validator controls display error text in-place; that is, they display the value of the control's Text property at the
control's location in the page. At times you might want to display error information in different ways. The ASP.NET validator
controls provide you with these additional options:
Summarize all validation errors in one place. You can do this in addition to or instead of showing in-place errors.
Displaying error summaries also allows you to display longer error messages.
Display a pop-up message in the browser with error information. This option works only on script-enabled browsers.
You can add both of these display options using the ValidationSummary control. In this part of the walkthrough, you'll add
both display features to the page.
To display validation information in alternative ways
1. From the Validation group of the Toolbox, drag a ValidationSummary control onto the page.
2. Set the ValidationSummary control's ValidationGroup property to AllValidators.
3. Run the page.
4. Perform the same testing you did earlier in the walkthrough.
For each error, you see error information in two places. A short error message (the validator's Text property value) is
displayed where the validator control is. The longer error message (the control's ErrorMessage property value) is
displayed in the ValidationSummary control.
5. Close the browser.
6. Set the ValidationSummary control's ShowMessageBox property to true.
7. Run the page.
8. Perform the same tests.
This time, each error results in a pop-up message in the browser.
9. Close the browser.
Adding Custom Validation to Check Date Entry
The ASP.NET validation controls do not include a control that automatically checks for a valid date. However, you can use the
CustomValidator control for that purpose. The custom validator allows you to write your own validation code to check for any
condition your application requires. In this walkthrough, you will use the CustomValidator to check that the value the user
enters into the textPreferredDate text box can be converted to a date value.
You will add two blocks of custom validation code. The first is the custom validation code that runs when the page is
submitted. You must always have server-side validation logic for a CustomValidator control. You will also write some client
script (ECMAScript or JavaScript) that performs a similar check in the browser, so that the user can have immediate feedback.
To use a CustomValidator control to check for a valid date
1. From the Validation group of the Toolbox, drag a CustomValidator control onto the page and position it next to the
textPreferredDate text box.
2. Set the following properties of the CustomValidator control:
Property Setting
ControlToValidate textPreferredDate

Display Dynamic

ErrorMessage Enter a date in the format m/d/yyyy.

Text Invalid date format (requires m/d/yyyy).

ValidationGroup AllValidators

3. Double-click the CustomValidator control to create a handler for its ServerValidate event and then add the following
highlighted code:
VB
Protected Sub CustomValidator1_ServerValidate( _
ByVal source As Object, _
ByVal args As System.Web.UI.WebControls.ServerValidateEventArgs)
Try
DateTime.ParseExact(args.Value, "d", Nothing)
args.IsValid = True
Catch
args.IsValid = False
End Try
End Sub

C#
protected void CustomValidator1_ServerValidate(object source,
ServerValidateEventArgs args)
{
try
{
DateTime.ParseExact(args.Value, "d", null);
args.IsValid = true;
}
catch
{
args.IsValid = false;
}
}

This code runs when the user submits the page. The code interacts with the validator control using the
ServerValidateEventArgs (args) object passed into the handler. The value that the user has entered into the
textPreferredDate text box is passed as the args object's Value property. After you have checked whether the user's
entry is valid, you set the args object's IsValid property to true or false. If you set it to false, the validator will display its
error message.
In this example, the code uses a try-catch block to determine whether the user's entry can be converted into a DateTime
object. If the user enters an invalid value (anything that does not conform to a date in the format m/d/yyyy, the
DateTime object's ParseExact method throws an exception, and the Catch block is executed.
4. In the Button_Click handler, add the following highlighted code:
VB
Protected Sub buttonSubmit_Click(ByVal sender As Object, _
ByVal e As System.EventArgs)
If Page.IsValid Then
labelMessage.Text = "Your reservation has been processed."
else
labelMessage.Text = "Page is not valid."
End If
End Sub

C#
protected void buttonSubmit_Click(object sender, EventArgs e)
{
if(Page.IsValid)
{
labelMessage.Text = "Your reservation has been processed.";
}
else
labelMessage.Text = "Page is not valid."
}
}

When you use a CustomValidator control, you must check the System.Web.UI.Page.IsValid property in any server-side
processing to be sure that all the validation checks have passed. The IsValid property returns the cumulative state of all
the validator controls on the page. This property is used to make sure that all validation checks have passed any server-
side processing.
You have now added the server-side code for the CustomValidator control to check for a valid date. As you know from earlier
in the walkthrough, validator controls also check a user's entry using client script. You can add client script to the
CustomValidator control as well. In effect, you write client script that duplicates the logic that your server-side validation
performs. Writing client-side custom validation code is not always practical (for example, if the custom code validates a user's
entry by looking in a server-side database). However, in this case you can create client-side code that performs essentially the
same check that your server-side code is performing.
To add client script to the CustomValidator control
1. Open or switch to Default.aspx.
2. In the <head> element of the page, add the following client script block:

<script language="javascript">
function validateDate(oSrc, args)
{
var iDay, iMonth, iYear;
var arrValues;
arrValues = args.Value.split("/");
iMonth = arrValues[0];
iDay = arrValues[1];
iYear = arrValues[2];

var testDate = new Date(iYear, iMonth - 1, iDay);


if ((testDate.getDate() != iDay) ||
(testDate.getMonth() != iMonth - 1) ||
(testDate.getFullYear() != iYear))
{
args.IsValid = false;
return;
}

return true;
}</script>

Note
ECMAScript (JavaScript) is case-sensitive; enter the code exactly as you see it here.

This code is similar to the server-side validation check, but not as strict. The user's entry is passed into the function as the
args object's Value property, and you can set the object's IsValid property to indicate whether the value passes
validation. In this example, the code checks to make sure valid numeric dates were entered.
Note that the code for the custom validation is slightly different in client script than it is in server code. ECMAScript does
not provide exactly the same functionality as that in the .NET Framework. Therefore, the ECMAScript parses the entered
text instead of the System.DateTime.ParseExact code that you use on the server to check the date. However, the two
validation checks (client and server) are similar enough to provide the functionality you need.
3. Put the insertion point in the <asp:customvalidator> element to select it.
4. In the Properties window, set the control's ClientValidationFunction property to validateDate, which is the name of the
ECMAScript function that you just created.
You have now added a custom validation check that works both in client script to check the user's entry immediately and
then again when the page is submitted to the server.
Testing Custom Validation
You can now test that your custom validation is working properly.
To test custom validation
1. Temporarily disable the client-side validation by setting the EnableClientScript property of the CustomValidator control
to false.
2. Press CTRL+F5 to run the page.
3. Fill in an e-mail address and the number of people in the party so that the validation for those fields passes.
4. In the date text box, enter a string that is obviously not a date and then click the Submit Request button.
Your page performs a round trip to the Web server, where the server-side validation fails. The test for IsValid fails and
labelMessage says "Page is not valid."

5. Fill in a valid date value (such as 11/17/2005) and click the button.
This time, the date value passes validation, so you see the confirmation message created in the button's Click handler.
6. Close the browser.
7. Re-enable client-side validation by setting the EnableClientScript property of the CustomValidator control back to
true.
8. Run the page again and enter valid values for the e-mail address and number of people in the party.
Enter an invalid date value into the date text box and then press the TAB key. (Do not click the button.)
As soon as the date text box loses focus, the client-side validation script runs and you see an error message.
Note
If you are using the auto-complete option in Internet Explorer, selecting a value from the auto-complete list will fill a val
ue into the text box, but the client-side validator will not run.

9. Click the Submit Request button.


Because the client-side validation for the date text box has failed, the page is not submitted.
10. Correct the date value and press the TAB key again.
The error message disappears. You can now submit the form.
Adding Optional Controls with Conditional Validation
In the final part of the walkthrough, you will add some optional information to the reservation form. Users can check a box to
indicate that they want telephone confirmation of their reservation. If they do, they must enter their telephone number. The
page will therefore contain two additional controls: a check box and a text box.
As before, you will use validation to check the user's entries. You will use a RequiredFieldValidator control to be sure that
users enter a phone number, and a RegularExpressionValidator control to check its format. The telephone number is
optional; you need to check the phone number only if the user has selected the Confirm reservation by phone check box.
You therefore will write some simple code that turns validation on or off for the telephone number depending on the state of
the check box.
To add conditional validation
1. From the Standard group of the Toolbox, drag a CheckBox control onto the page and set the following properties:
Property Setting
ID checkPhoneConfirmation

AutoPostBack True
When the user clicks the check box, the page will perform a round trip and conditionally enable the text
box and the validation for it.

CausesValidation False
Clicking the CheckBox will not automatically cause validation.
Text Confirm reservation by telephone.

2. Drag a TextBox control onto the page underneath the CheckBox control and set the following properties:

a. Property a. Settings

ID textPhoneNumber

Enabled False
The text box will not be enabled until the user clicks the check box.

3. Type text such as Telephone number: next to the phone number text box as a caption.
4. From the Validation group of the Toolbox, drag a RequiredFieldValidator onto the page and set the following
properties:
Propert Setting
y
ID validatorRequiredPhoneNumber
You did not set the ID of validator controls earlier in the walkthrough, but in this case you will be referring to th
e validator control in code, so you it is helpful to give it a mnemonic ID.

Control textPhoneNumber
ToValid
ate

Display Dynamic

ErrorMe You must provide a phone number.


ssage

Text *

Validati (Leave blank)


onGrou
p If this property is blank, the validator does not belong to the AllValidators group that you established for the o
ther validator controls on the page. As a consequence, by default this validator is not checked when the button
Submit control is clicked.

5. Drag a RegularExpressionValidator control onto the page and set the following properties:
Property Setting
ID validatorRegExPhoneNumber

ControlToValidate textPhoneNumber

Display Dynamic

ErrorMessage Phone number format is invalid

Text Invalid format

ValidationExpress (Use the Regular Expression Editor dialog box to select U.S. Phone Number or another phone numb
ion er expression.)
ValidationGroup (Leave blank)

6. Double-click the checkPhoneConfirmation control to create a handler for its CheckedChanged event and then add the
following highlighted code:
VB
Protected Sub checkPhoneConfirmation_CheckedChanged( _
ByVal sender As Object, _
ByVal e As System.EventArgs)
If checkPhoneConfirmation.Checked = True Then
textPhoneNumber.Enabled = True
validatorRequiredPhoneNumber.ValidationGroup = "AllValidators"
validatorRegExPhoneNumber.ValidationGroup = "AllValidators"
Else
textPhoneNumber.Enabled = False
validatorRequiredPhoneNumber.ValidationGroup = ""
validatorRegExPhoneNumber.ValidationGroup = ""
End If
End Sub

C#
protected void checkPhoneConfirmation_CheckedChanged(
object sender, EventArgs e)
{
if(checkPhoneConfirmation.Checked)
{
textPhoneNumber.Enabled = true;
validatorRequiredPhoneNumber.ValidationGroup =
"AllValidators";
validatorRegExPhoneNumber.ValidationGroup = "AllValidators";
}
else
{
textPhoneNumber.Enabled = false;
validatorRequiredPhoneNumber.ValidationGroup = "";
validatorRegExPhoneNumber.ValidationGroup = "";
}
}

When the user clicks the check box, the two validators associated with the text box are added to the validation group that
the other validator controls belong to. The effect is that all the validators on the page, including those for the phone
number, will be checked when the user submits the page. If the user clears the check box, the validators are removed
from the group and are therefore not processed when the Submit Request button is clicked.
Testing Conditional Validation
You can now test that conditional validation is working properly.
To test conditional validation
1. Press CTRL+F5 to run the page.
2. Enter valid information for the e-mail address, number of people in the party, and date.
3. Click Submit Request.
The page is submitted and you see the confirmation message.
4. Select the Confirm reservation by phone check box.
5. Click Submit Request again.
This time, you see an error message (a star next to the phone text box). When you clicked the check box, you enabled
validation for the text box.
6. Enter an invalid phone number and then click Submit Request again to confirm that the text box will not accept an
invalid phone number.
7. Enter a correctly formatted phone number and click the submit button to confirm that the validator control accepts well-
formed data.
Next Steps
The validation you added to the Web Forms page illustrates the basic concepts of Web validation controls.
An important aspect of validation is understanding how it helps you increase the security for your Web site. For details, see
Web Application Security Threats Overview (Visual Studio).
See Also
Reference
Validating User Input in ASP.NET Web Pages
Concepts
Script Exploits Overview
ASP.NET

Types of Validation for ASP.NET Server Controls


The following table lists ASP.NET validation controls and how you can use them.
Security Note
By default, ASP.NET Web pages automatically validate that malicious users are not attempting to send script to your applicati
on. For more information, see Script Exploits Overview.

Type Control to use Description


of vali
datio
n
Requir RequiredFieldValidator Ensures that the user does not skip an entry. For details, see
ed ent How to: Validate Required Entries for ASP.NET Server Controls.
ry

Comp CompareValidator Compares a user's entry against a constant value, against the value of another control (usi
arison ng a comparison operator such as less than, equal, or greater than), or for a specific data ty
to a va pe. For details, see How to: Validate Against a Specific Value for ASP.NET Server Controls a
lue nd How to: Validate Against a Data Type for ASP.NET Server Controls.

Range RangeValidator Checks that a user's entry is between specified lower and upper boundaries. You can check
checki ranges within pairs of numbers, alphabetic characters, and dates. For details, see
ng How to: Validate Against a Range of Values for ASP.NET Server Controls.

Patter RegularExpressionValidator Checks that the entry matches a pattern defined by a regular expression. This type of valida
n matc tion enables you to check for predictable sequences of characters, such as those in e-mail a
hing ddresses, telephone numbers, postal codes, and so on. For details, see
How to: Validate Against Patterns for ASP.NET Server Controls.

User-d CustomValidator Checks the user's entry using validation logic that you write yourself. This type of validatio
efined n enables you to check for values derived at run time. For details, see
How to: Validate with a Custom Function for ASP.NET Server Controls and
How to: Validate Against Values in a Database for ASP.NET Server Controls.

You can attach more than one validation control to an input control. For example, you might specify that a control is required
and that it also contains a specific range of values.
A related control, the ValidationSummary control, does not perform validation, but is often used in conjunction with other
validation controls to display the error messages from all the validation controls on the page together. For more information,
see How to: Control Validation Error Message Display for ASP.NET Server Controls.
See Also
Other Resources
Validation ASP.NET Controls
ASP.NET

How to: Validate Required Entries for ASP.NET Server Controls


You can specify that a user must provide information in a specific control on an ASP.NET Web page by adding a
RequiredFieldValidator control to the page and linking it to the required control. For example, you can specify that users must
fill in a Name text box before they can submit a registration form.
If validation is being performed on the client, the user can leave a required field blank (or with its default value) while working
in the page, but must provide a non-default value before submitting the page. However, once a value has been entered in the
field, the user cannot clear the field (or return it to its default value). If the field is cleared, the user sees an error message
immediately when leaving the field. In server-side validation, no checking is done until the page is submitted, so the user will
not see an error message until after the page is submitted.
Note
Required-entry validation is frequently used in conjunction with other types of validation. You can use as many validation co
ntrols for a user-entry field as needed.

To validate a required entry


1. Add a RequiredFieldValidator control to the page and set the following properties:
Property Description
ControlToValidate The ID of the control for which the user must provide a value.

ErrorMessage, Properties that specify the text and location of the error or errors that will appear if the user skips the
Text, Display control. For details, see How to: Control Validation Error Message Display for ASP.NET Server Controls
.

2. Add a test in your ASP.NET Web page code to check for validity. For details, see
How to: Test Validity Programmatically for ASP.NET Server Controls.
The following example shows the .aspx file of a TextBox server control with required field validation.
Security Note
This example has a text box that accepts user input, which is a potential security threat. By default, ASP.NET Web pages
validate that user input does not include script or HTML elements. For more information, see Script Exploits Overview.

VB
<asp:Textbox id="txtLastName" runat="server"></asp:Textbox>
<asp:RequiredFieldValidator id="RequiredFieldValidator1" runat="server"
ControlToValidate="txtLastName"
ErrorMessage="Last name is a required field."
ForeColor="Red">
</asp:RequiredFieldValidator>

C#
<asp:Textbox id="txtLastName" runat="server"></asp:Textbox>
<asp:RequiredFieldValidator id="RequiredFieldValidator1" runat="server"
ControlToValidate="txtLastName"
ErrorMessage="Last name is a required field."
ForeColor="Red">
</asp:RequiredFieldValidator>
See Also
Concepts
Types of Validation for ASP.NET Server Controls
Other Resources
Validation ASP.NET Controls
ASP.NET

How to: Validate Against a Specific Value for ASP.NET Server


Controls
Using ASP.NET validation controls, you can validate a user's entry against a specific value using logical operators. For example,
you can specify that the user's entry is a date after January 1, 1950 or that it is an integer value greater than or equal to zero.
Alternatively, you can specify that the user's entry be compared against a value from another control.
Security Note
User input in ASP.NET Web pages can include potentially malicious client script. For more information, see
Script Exploits Overview.

To validate against a specific value


1. Add a CompareValidator control to the page and set the following properties:
Property Description
ControlToValidate The ID of the control for which the user must provide a value.

ErrorMessage, Properties that specify the text and location of the error or errors that will appear if the user skips the
Text, Display control. For details, see How to: Control Validation Error Message Display for ASP.NET Server Controls
.

2. Set the value to compare to by setting the following properties:


Property Description
ValueToCompare An expression entered as a string. To compare to a constant value, set the ValueToCompare proper
ty. To compare against the value of another control, set the ControlToCompare property to the ID o
- or - f that control. (The CompareValidator control compares the user's entry against whatever property
ControlToCompare is specified by the other control's ValidationPropertyAttribute). If you set both ValueToCompare an
d ControlToCompare, ControlToCompare takes precedence.

Type The data type of the two values to be compared. Types are specified using the ValidationDataType en
umeration, which enables you to use the type name String, Integer, Double, Date, or Currency. The va
lues are converted to this type before the comparison is performed. For more information, see
How to: Validate Against a Data Type for ASP.NET Server Controls.

Operator The comparison to use. Specify an operator using one of the following values defined in the
ValidationCompareOperator enumeration:
Equal
NotEqual
GreaterThan
GreaterThanEqual
LessThan
LessThanEqual
DataTypeCheck
Note
When validation is done against another control, invalid values in the other control are ignored and the validation pass
es. For details, see Special-Case Validation Results for ASP.NET Server Controls.
3. Add a test in your code to check for validity. For details, see
How to: Test Validity Programmatically for ASP.NET Server Controls.
The following code example shows a TextBox control validated using a CompareValidator control:
VB
<table>
<tr>
<td>
<asp:Textbox id="txtAge" runat="server"></asp:Textbox>
</td>
<td>
<asp:CompareValidator id="CompareFieldValidator1" runat="server"
ForeColor="Red"
ControlToValidate="txtAge"
ValueToCompare="0"
Type="Integer"
Operator="GreaterThanEqual"
ErrorMessage="Please enter a whole number zero or greater.">
</asp:CompareValidator >
</td>
</tr>
</table>

C#
<table>
<tr>
<td>
<asp:Textbox id="txtAge" runat="server"></asp:Textbox>
</td>
<td>
<asp:CompareValidator id="CompareFieldValidator1" runat="server"
ForeColor="Red"
ControlToValidate="txtAge"
ValueToCompare="0"
Type="Integer"
Operator="GreaterThanEqual"
ErrorMessage="Please enter a whole number zero or greater.">
</asp:CompareValidator >
</td>
</tr>
</table>

The following code example shows a CompareValidator that compares the user's entry against the value in another
control. The page enables users to make reservations at a hotel. The validator checks that the user does not enter a
departure date earlier than the arrival date. (In a real application, the departure date would be required and validated as a
date as well.)
VB
<table>
<tr>
<td>
Arrive<asp:Textbox id="txtArrivalDate" runat="server"></asp:Textbox>
Depart<asp:Textbox id="txtDepartureDate" runat="server"></asp:Textbox>
</td>
<td>
<asp:CompareValidator id="CompareValidator1" runat="server"
ForeColor="Red"
ControlToValidate="txtDepartureDate"
ControlToCompare="txtArrivalDate"
Type="Date"
Operator="GreaterThanEqual"
ErrorMessage="Departure date cannot be earlier than arrival date.">
</asp:CompareValidator >
</td>
</tr>
</table>

C#
<table>
<tr>
<td>
Arrive<asp:Textbox id="txtArrivalDate" runat="server"></asp:Textbox>
Depart<asp:Textbox id="txtDepartureDate" runat="server"></asp:Textbox>
</td>
<td>
<asp:CompareValidator id="CompareValidator1" runat="server"
ForeColor="Red"
ControlToValidate="txtDepartureDate"
ControlToCompare="txtArrivalDate"
Type="Date"
Operator="GreaterThanEqual"
ErrorMessage="Departure date cannot be earlier than arrival date.">
</asp:CompareValidator >
</td>
</tr>
</table>

See Also
Concepts
Types of Validation for ASP.NET Server Controls
Other Resources
Validation ASP.NET Controls
ASP.NET

How to: Validate Against a Data Type for ASP.NET Server


Controls
You can validate a user's entry in an ASP.NET Web page against a specific data type to be sure that what the user has entered is
a number, or a date, and so on. For example, if you want to collect birth date information on a user registration page, you can
use a CompareValidator control to make sure that the date is in a recognized format before it is submitted.
To validate against a data type
1. Add a CompareValidator control to the page and set the following properties:
Property Description
ControlToValidate The ID of the control for which you are checking the data type.

ErrorMessage, Properties that specify the text and location of the error or errors that will display if the validation fails.
Text, Display For details, see How to: Control Validation Error Message Display for ASP.NET Server Controls.

2. Set the data type to compare to by setting the following properties:


Propert Description
y
Type The data type to check against. The type is specified using the ValidationDataType enumeration, which enables
you to use the type names String, Integer, Double, Date, or Currency.

Operator DataTypeCheck
Note
If the user leaves a control blank, the control passes the comparison validation. To force the user to enter a value, add a
RequiredFieldValidator control as well. For details, see How to: Validate Required Entries for ASP.NET Server Controls.

3. Add a test in your ASP.NET Web page code to check for validity. For details, see
How to: Test Validity Programmatically for ASP.NET Server Controls.

See Also
Concepts
Types of Validation for ASP.NET Server Controls
Other Resources
Validation ASP.NET Controls
ASP.NET

How to: Validate Against Patterns for ASP.NET Server Controls


You can check that a user's entry matches a predefined pattern, such as a phone number, postal code, e-mail address, and so
on. To do so, you use a regular expression. For more information on regular expressions, see
.NET Framework Regular Expressions.
Security Note
By default, ASP.NET Web pages automatically validate that malicious users are not attempting to send script or HTML elemen
ts to your application. For more information, see Script Exploits Overview.

To validate against a regular expression


1. Add a RegularExpressionValidator control to the page and set the following properties:
Property Description
ControlToValidate The ID of the control you are validating.

ErrorMessage, Properties that specify the text and location of the error or errors that will display if the validation fails.
Text, Display For details, see How to: Control Validation Error Message Display for ASP.NET Server Controls.

2. Set the pattern to compare to by setting the ValidationExpression property to a regular expression.
Note
If you are using a visual designer such as Visual Studio .NET 2005, you can select from predefined patterns defined in t
he RegularExpressionValidator control.

If you want to allow multiple valid patterns, use the bar character (|) to separate expressions.
Note
In client-side validation, regular expressions are evaluated using ECMAScript (JavaScript). This differs in minor ways fro
m server-side regular-expression checking.

3. Add a test in your ASP.NET Web page code to check for validity. For details, see
How to: Test Validity Programmatically for ASP.NET Server Controls.
The following code example shows how you can use a RegularExpressionValidator control to check whether users
have entered a valid United States ZIP code. The validator checks for two patterns: five digits, and five digits plus a
hyphen plus four more digits.
VB
ZIP: <asp:TextBox id="txtZIP" runat="SERVER"></asp:TextBox>
<asp:RegularExpressionValidator
id="txtZIP_validation" runat="SERVER"
ControlToValidate="txtZIP"
ErrorMessage="Enter a valid US ZIP code."
ValidationExpression="\d{5}(-\d{4})?">
</asp:RegularExpressionValidator>

C#
ZIP: <asp:TextBox id="txtZIP" runat="SERVER"></asp:TextBox>
<asp:RegularExpressionValidator
id="txtZIP_validation" runat="SERVER"
ControlToValidate="txtZIP"
ErrorMessage="Enter a valid US ZIP code."
ValidationExpression="\d{5}(-\d{4})?">
</asp:RegularExpressionValidator>

See Also
Concepts
Types of Validation for ASP.NET Server Controls
Other Resources
Validation ASP.NET Controls
ASP.NET

How to: Validate Against a Range of Values for ASP.NET Server


Controls
You can use the ASP.NET RangeValidator control to determine whether a user's entry falls within a specific range of values—
for example, between two numbers, between two dates, or between alphabetic characters. You set the upper and lower bounds
of the range as properties of a RangeValidator control. You must also specify the data type of the values that the control will
validate. If the user's entry cannot be converted to the specified data type—for example, it cannot be converted to a date—the
validation fails.
To validate against a range of values
1. Add a RangeValidator control to the page and set the following properties:
Property Description
ControlToValidate The ID of the control for which the user must provide a value.

ErrorMessage, Properties that specify the text and location of the error or errors that will appear if the user skips the
Text, Display control. For details, see How to: Control Validation Error Message Display for ASP.NET Server Controls
.

2. Set the low and high values of the range using the MinimumValue and MaximumValue properties.
3. Set the Type property to specify the data type of the range settings. Use the ValidationDataType enumeration, which
enables you to specify the following types:
String
Integer
Double
Date
Currency
Note
If the user leaves a control blank, the control passes the range validation. To force the user to enter a value, add a
RequiredFieldValidator control as well. For details, see How to: Validate Required Entries for ASP.NET Server Controls.

4. Add a test in your ASP.NET Web page code to check for validity. For details, see
How to: Test Validity Programmatically for ASP.NET Server Controls.
See Also
Concepts
Types of Validation for ASP.NET Server Controls
Other Resources
Validation ASP.NET Controls
ASP.NET

How to: Validate Against Values in a Database for ASP.NET


Server Controls
You can validate a user's entry against a database to be sure that what the user has entered is a recognized value. To do this,
you must write code in a CustomValidator control that looks for data matches in a database.
To validate against a database
1. Add a CustomValidator control to the page and set the following properties:
Property Description
ControlToValidate The ID of the control you are validating.

ErrorMessage, Properties that specify the text and location of the error or errors that will display if the validation fails.
Text, Display For details, see How to: Control Validation Error Message Display for ASP.NET Server Controls.

2. Create an event handler for the CustomValidator control's ServerValidate event. In the event handler, add code to look
through the database and check the user's input against the dataset.
Note
If the user leaves a control blank, the control passes the comparison validation. To force the user to enter a value, add a
RequiredFieldValidator control as well. For details, see How to: Validate Required Entries for ASP.NET Server Controls.

3. Add a test in your ASP.NET Web page code to check for validity. For details, see
How to: Test Validity Programmatically for ASP.NET Server Controls.
The following code example shows how you can validate a user's entry by looking it up in a database table. In this
instance, the user has entered an e-mail address that is validated against e-mail addresses stored in a table. The custom
validation logic loops through the rows in a table that is part of the dataset available to the page.
VB
Private Sub CustomValidator1_ServerValidate(ByVal _
source As System.Object, ByVal args As _
System.Web.UI.WebControls.ServerValidateEventArgs) _
Handles CustomValidator1.ServerValidate

Dim dv As DataView
Dim dataset11 As New Data.DataSet

dv = dataset11.Tables(0).DefaultView

Dim datarow As DataRowView


Dim txtEmail As String
args.IsValid = False ' Assume False
' Loop through table and compare each record against user's entry
For Each datarow In dv
' Extract e-mail address from the current row
txtEmail = datarow.Item("Alias").ToString()
' Compare e-mail address against user's entry
If txtEmail = args.Value Then
args.IsValid = True
Exit For
End If
Next
End Sub
C#
private void CustomValidator1_ServerValidate(object source, System.Web.UI.WebControls.
ServerValidateEventArgs args)
{
DataView dv;
DataSet dataSet11 = new DataSet();

dv = dataSet11.Tables[0].DefaultView;
string txtEmail;
args.IsValid = false; // Assume False
// Loop through table and compare each record against user's entry
foreach (DataRowView datarow in dv)
{
// Extract e-mail address from the current row
txtEmail = datarow["Alias "].ToString();
// Compare e-mail address against user's entry
if (txtEmail == args.Value)
{
args.IsValid = true;
}
}
}

See Also
Concepts
Types of Validation for ASP.NET Server Controls
Other Resources
Validation ASP.NET Controls
ASP.NET

How to: Validate with a Custom Function for ASP.NET Server


Controls
If existing ASP.NET validation controls do not suit your needs, you can define a custom server-side validation function and call
it using the CustomValidator control. You can also add client-side validation to check user input before the page is submitted
by writing a function in ECMAScript (JavaScript) that duplicates the logic of the server-side method.
You should perform server-side validation even if you use a client-side check. Server-side validation helps prevent users from
bypassing validation by disabling or changing the client script.
Security Note
By default, ASP.NET Web pages automatically validate that malicious users are not attempting to send script or HTML elemen
ts to your application. For more information, see Script Exploits Overview.

To validate on the server using a custom function


1. Add a CustomValidator control to the page and set the following properties:
Property Description
ControlToValidate The ID of the control you are validating.

ErrorMessage, Properties that specify the text and location of the error or errors that will display if the validation fails.
Text, Display For details, see How to: Control Validation Error Message Display for ASP.NET Server Controls.

2. Create a server-based event handler for the control's ServerValidate event. This event is called to perform the validation.
The method has a signature such as the following:
VB
Protected Sub CustomValidator1_ServerValidate(ByVal _
source As System.Object, ByVal args As _
System.Web.UI.WebControls.ServerValidateEventArgs) _
Handles CustomValidator1.ServerValidate
End Sub

C#
protected void ValidationFunctionName(object source, ServerValidateEventArgs args)
{

The source parameter is a reference to the custom validation control raising this event. The property args.Value will
contain the user input to validate. Set args.IsValid to true if the value is valid, otherwise false.
The following code example shows how you can create custom validation. The event handler determines whether the
user's entry is eight characters long or longer.
VB
Protected Sub TextValidate(ByVal source As System.Object, _
ByVal args As System.Web.UI.WebControls.ServerValidateEventArgs) _
Handles CustomValidator1.ServerValidate
args.IsValid = (args.Value.Length >= 8)
End Sub
C#
protected void TextValidate(object source, ServerValidateEventArgs args)
{
args.IsValid = (args.Value.Length >= 8);
}

3. Bind the event handler to the method using code such as the following:
VB
<asp:textbox id="TextBox1" runat="server"></asp:textbox>
<asp:CustomValidator id="CustomValidator1" runat="server"
OnServerValidate="TextValidate"
ControlToValidate="TextBox1"
ErrorMessage="Text must be 8 or more characters.">
</asp:CustomValidator>

C#
<asp:textbox id="TextBox1" runat="server"></asp:textbox>
<asp:CustomValidator id="CustomValidator1" runat="server"
OnServerValidate="TextValidate"
ControlToValidate="TextBox1"
ErrorMessage="Text must be 8 or more characters.">
</asp:CustomValidator>

4. Add a test in your ASP.NET Web page code to check for validity. For details, see
How to: Test Validity Programmatically for ASP.NET Server Controls.

To create custom validation logic on the client


1. Create a validation function in ECMAScript (JavaScript, JScript).
The following code example illustrates custom client-side validation. An excerpt from the page shows a TextBox control
referenced by a CustomValidator control. The validation control calls a client script function named validateLength to
make sure that the user has entered at least eight characters into the TextBox control.
VB
<script type="text/javascript">
function validateLength(oSrc, args){
args.IsValid = (args.Value.length >= 8);
}
</script>

C#
<script type="text/javascript">
function validateLength(oSrc, args){
args.IsValid = (args.Value.length >= 8);
}
</script>
VB
<asp:Textbox id="text1" runat="server" text=""></asp:Textbox>
<asp:CustomValidator id="CustomValidator2" runat="server"
ControlToValidate = "text1"
ErrorMessage = "You must enter at least 8 characters!"
ClientValidationFunction="validateLength" >
</asp:CustomValidator>

C#
<asp:Textbox id="text1" runat="server" text=""></asp:Textbox>
<asp:CustomValidator id="CustomValidator2" runat="server"
ControlToValidate = "text1"
ErrorMessage = "You must enter at least 8 characters!"
ClientValidationFunction="validateLength" >
</asp:CustomValidator>

2. Add a test in your ASP.NET Web page code to check for validity. For details, see
How to: Test Validity Programmatically for ASP.NET Server Controls.
See Also
Concepts
Types of Validation for ASP.NET Server Controls
Other Resources
Validation ASP.NET Controls
ASP.NET

Specifying Validation Groups


Validation groups allow you to organize validation controls on a page as a set. Each validation group can perform validation
independently from other validation groups on the page.
You create a validation group by setting the ValidationGroup property to the same name (a string) for all the controls you
want to group. You can assign any name to a validation group, but you must use the same name for all members of the group.
During postback, the Page class's IsValid property is set based only on the validation controls in the current validation group.
The current validation group is determined by the control that caused validation to occur. For example, if a button control with
a validation group of LoginForm is clicked, then the IsValid property will return true if all validation controls whose
ValidationGroup property is set to LoginForm are valid. Other controls such as a DropDownList control can also trigger
validation if the control's CausesValidation property is set to true (and the AutoPostBack property is set to true.)
To validate programmatically, you can call the Validate method overload that takes the validationGroup parameter to force
validation for only that validation group. Note that when you call the Validate method, the IsValid property reflects the
validity of all groups validated so far. This could include both a group that was validated as a result of a postback, and the
programmatically validated group. If any control in either group is invalid, the IsValid property returns false.
The following code example demonstrates how to use the ValidationGroup property to specify the controls to validate when
a Button control posts back to the server. The page contains three text boxes to capture data from the user and three
RequiredFieldValidator controls to ensure that the user does not leave a text box blank. The RequiredFieldValidator controls
for the first two text boxes are in the PersonalInfoGroup validation group and the RequiredFieldValidator control for the
third text box is in the LocationInfoGroup validation group. When Button1 is clicked, only the controls in validation group
PersonalInfoGroup are validated. When Button2 is clicked, only the control in validation group LocationInfoGroup is
validated.
VB
<%@ page language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Button.ValidationGroup Example</title>
</head>
<body>
<form id="form1" runat="server">
<h3>Button.ValidationGroup Example</h3>

<asp:label id="NameLabel"
text="Enter your name:"
runat="Server"
AssociatedControlID="NameTextBox">
</asp:label>
&nbsp

<asp:textbox id="NameTextBox"
runat="Server">
</asp:textbox>

&nbsp
<asp:requiredfieldvalidator id="RequiredFieldValidator1"
controltovalidate="NameTextBox"
validationgroup="PersonalInfoGroup"
errormessage="Enter your name."
runat="Server">
</asp:requiredfieldvalidator>

<br /><br />


<asp:label id="AgeLabel"
text="Enter your age:"
runat="Server"
AssociatedControlID="AgeTextbox">
</asp:label>
&nbsp

<asp:textbox id="AgeTextbox"
runat="Server">
</asp:textbox>

&nbsp
<asp:requiredfieldvalidator id="RequiredFieldValidator2"
controltovalidate="AgeTextBox"
validationgroup="PersonalInfoGroup"
errormessage="Enter your age."
runat="Server">
</asp:requiredfieldvalidator>

<br /><br />


<!--When Button1 is clicked, only validation
controls that are a part of PersonalInfoGroup
are validated.-->
<asp:button id="Button1"
text="Validate"
causesvalidation="true"
validationgroup="PersonalInfoGroup"
runat="Server" />

<br /><br />

<asp:label id="CityLabel"
text="Enter your city of residence:"
runat="Server"
AssociatedControlID="CityTextbox">
</asp:label>

&nbsp

<asp:textbox id="CityTextbox"
runat="Server">
</asp:textbox>
&nbsp

<asp:requiredfieldvalidator id="RequiredFieldValidator3"
controltovalidate="CityTextBox"
validationgroup="LocationInfoGroup"
errormessage="Enter a city name."
runat="Server">
</asp:requiredfieldvalidator>

<br /><br />

<!--When Button2 is clicked, only validation


controls that are a part of LocationInfoGroup
are validated.-->
<asp:button id="Button2"
text="Validate"
causesvalidation="true"
validationgroup="LocationInfoGroup"
runat="Server" />

</form>
</body>
</html>
C#
<%@ page language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="head1" runat="server">
<title>Button.ValidationGroup Example</title>
</head>
<body>
<form id="form1" runat="server">

<h3>Button.ValidationGroup Example</h3>

<asp:label id="NameLabel"
text="Enter your name:"
runat="Server"
AssociatedControlID="NameTextBox">
</asp:label>
&nbsp

<asp:textbox id="NameTextBox"
runat="Server">
</asp:textbox>

&nbsp
<asp:requiredfieldvalidator id="RequiredFieldValidator1"
controltovalidate="NameTextBox"
validationgroup="PersonalInfoGroup"
errormessage="Enter your name."
runat="Server">
</asp:requiredfieldvalidator>
<br /><br />

<asp:label id="AgeLabel"
text="Enter your age:"
runat="Server"
AssociatedControlID="AgeTextBox">
</asp:label>

&nbsp

<asp:textbox id="AgeTextBox"
runat="Server">
</asp:textbox>

&nbsp

<asp:requiredfieldvalidator id="RequiredFieldValidator2"
controltovalidate="AgeTextBox"
validationgroup="PersonalInfoGroup"
errormessage="Enter your age."
runat="Server">
</asp:requiredfieldvalidator>

<br /><br />

<!--When Button1 is clicked, only validation


controls that are a part of PersonalInfoGroup
are validated.-->
<asp:button id="Button1"
text="Validate"
causesvalidation="true"
validationgroup="PersonalInfoGroup"
runat="Server" />

<br /><br />

<asp:label id="CityLabel"
text="Enter your city of residence:"
runat="Server"
AssociatedControlID="CityTextBox">
</asp:label>
&nbsp

<asp:textbox id="CityTextBox"
runat="Server">
</asp:textbox>

&nbsp

<asp:requiredfieldvalidator id="RequiredFieldValidator3"
controltovalidate="CityTextBox"
validationgroup="LocationInfoGroup"
errormessage="Enter a city name."
runat="Server">
</asp:requiredfieldvalidator>
<br /><br />

<!--When Button2 is clicked, only validation


controls that are a part of LocationInfoGroup
are validated.-->
<asp:button id="Button2"
text="Validate"
causesvalidation="true"
validationgroup="LocationInfoGroup"
runat="Server" />

</form>
</body>
</html>

See Also
Other Resources
Validation ASP.NET Controls
Visual Web Developer

Learning More — Validation Controls


The topics in this section provide in-depth information about the ASP.NET validation controls, including how to customize
them and how to work with them programmatically.
In This Section
Client-Side Validation for ASP.NET Server Controls
Special-Case Validation Results for ASP.NET Server Controls
Validation Error Message Layout for ASP.NET Server Controls
How to: Test Validity Programmatically for ASP.NET Server Controls
How to: Disable Validation for ASP.NET Server Controls
How to: Validate Programmatically for ASP.NET Server Controls
See Also
Other Resources
Validation Toolbox Controls
Individual Web and HTML Controls
ASP.NET

Client-Side Validation for ASP.NET Server Controls


If the user is working with a browser that supports dynamic HTML (DHTML), ASP.NET validation controls can perform
validation using client script. Because the controls can provide immediate feedback without a round trip to the server, the user
experience with the page is enhanced.
Under most circumstances, you do not have to make any changes to your page or to the validation controls to use client-side
validation. The controls automatically detect if the browser supports DHTML and perform their checking accordingly. Client-
side validation uses the same error display mechanism as server-side validation.
Security Note
Validation is performed on the server even if it was already performed on the client. This enables you to determine validation
status in server code and provides security against users bypassing client-side validation.

Differences in Client-Side Validation


If validation is performed on the client, validation controls include some additional features:
If you are summarizing validation error messages, you can display them in a message box that appears when the user
submits the page. For details, see How to: Control Validation Error Message Display for ASP.NET Server Controls.
The object model for validation controls is slightly different on the client. See Client Validation Object Model later in this
topic.
There are a few minor differences associated with client-side validation:
If client-side validation is enabled, the page includes references to script libraries that are used to perform the client-side
validation.
When you use a RegularExpressionValidator control, the expressions can be checked on the client if an ECMAScript-
compatible language (such as Microsoft JScript) is available. Client-side regular expressions differ in small details from
the regular expression checking done on the server using the Regex class.
The page includes a client-side method to intercept and handle the Click event before the page is submitted.
Client Validation Object Model
Validation controls present almost the same object model on the client as on the server. For example, you can test validation by
reading a validation control's IsValid property the same way on both the client and the server.
However, there are differences in the validation information exposed at the page level. On the server, the page supports
properties; on the client, it contains global variables. The following table compares the information exposed on the page.
Client Page Variable Server Page Property
Page_IsValid IsValid

Page_Validators (array) Contains references to all validation controls on the page. Validators (collection) Contains re
ferences to all validation controls.

Page_ValidationActive A Boolean value that indicates whether validation should take (no equivalent)
place. Set this variable to false to turn off client-side validation programmatically.
Note
All page-related validation information should be considered read-only.

Posting Pages with Client-Side Validation Errors


In some instances, you might prefer not to use client-side validation and to use only server-side validation, even if client-side
validation is available. For example, client-side validation might not be possible if validation requires information or resources
that are available only on the server, such as access to a database.
By default, when client-side validation is being performed, the user cannot post the page to the server if there are errors on the
page. However, you might find it necessary to enable the user to post even with errors. For example, you might have a cancel
button or a navigation button on a page, and you want the button to submit the page even if some controls would fail
validation. For more information, see How to: Disable Validation for ASP.NET Server Controls.
See Also
Concepts
Types of Validation for ASP.NET Server Controls
Other Resources
Validation ASP.NET Controls
ASP.NET

Special-Case Validation Results for ASP.NET Server Controls


Validation ensures that what the user has entered meets criteria that you specify. In most cases, this is a straightforward
operation. However, at times the situations under which input is validated introduce special conditions. It is important that you
understand what those conditions are, how validation is performed, and what the results of a validation attempt can be.
Comparing Against Blank Fields
All validation controls except the RequiredFieldValidator control consider a field valid if it is blank. You must use the
RequiredFieldValidator control to prevent a user from leaving a field blank. For example, if you attach a RangeValidator
control to a date field, validation passes if the user enters a date in the specified range, or if the field is left blank. If you want to
ensure that the user enters a date, you must add a RequiredFieldValidator control to the date field along with the range
check.
Comparing Against Another Control
When using the CompareValidator control, you can specify that validation be performed against the value of another control.
For example, you might have two fields for entering dates, a start date and an end date. Using a CompareValidator control,
you can ensure that the start date is less than or equal to the end date.
Security Note
User input in an ASP.NET Web page can include potentially malicious client script. By default, the page validates that user inp
ut does not include script or HTML elements. For more information, see Script Exploits Overview.

If the validation controls are unable to resolve the value in the other control, they do not raise an error; instead, the validation
check passes. This occurs if the value in the other control is missing or cannot be converted to the data type of the
CompareValidator control.
The specific tests performed by these controls, and possible results, are:
If the target control entered in the originating control's ControlToValidate property does not have a value, the IsValid
property is considered true and validation passes.
If the value of the target control in the ControlToValidate property cannot be converted to the appropriate data type,
IsValid is considered false.
If the value of the target control in the ControlToCompare property cannot be converted to the appropriate data type,
then IsValid is considered true.
Finally, if all of these tests have passed, then both controls are non-empty and can be converted to the data type, so the
control performs the actual comparison and sets IsValid appropriately.
This strategy prevents multiple errors from being reported for the same invalid entry. Validation controls are designed to test
and report on only one value and to be able to display as precise a message as possible when an error is encountered.
For example, in the example of the end date, imagine that the user enters an invalid start date. The user then enters an end
date. When the validation check is performed (usually on the server), the same bad date could potentially raise an error both
for the start date field and for the end date. To prevent this from occurring, the end-date validation—the validation dependent
on another field—does not raise an error.
You should therefore ensure that you provide sufficient validation for each individual field. In the example, it would be up to
you to make sure that the user has entered a proper date in the start date field. In many cases, you should include a
RequiredFieldValidator control in addition to a validation control that tests the contents of a specific entry. It is also useful in
some cases to add a CompareValidator control with its Operator property set to DataTypeCheck, which does a simple type
check without doing a comparison to another value or control.
See Also
Concepts
Types of Validation for ASP.NET Server Controls
Other Resources
Validation ASP.NET Controls
ASP.NET

Validation Error Message Layout for ASP.NET Server Controls


When an error message appears on the page, it becomes part of the layout of the page. You need to design the layout of your
page to accommodate any error text that might appear.
If validation is being performed on the server, validation controls are not rendered to the page unless an error occurs and they
therefore take up no space whatsoever. If an error has occurred, the page is recreated during the round trip and the error text
is added to the page.
If the user has a browser that supports dynamic HTML (DHTML), validation occurs dynamically on the client. In that case, in-
place error message text appears immediately and can potentially change the layout of the page.
To control how error message text is displayed with client validation, you can set the Display property of validation controls to
one of three options:
Layo Description
ut O
ptio
n
Static Each validation control takes up space even when no error message text is visible, enables you to define a fixed layout fo
r the page. Multiple validation controls cannot occupy the same space on the page, so you must give them each separate
locations on the page. This setting only works in Internet Explorer 4.0 and later; in other browsers the layout effectively b
ecomes Dynamic.

Dyn Validation controls take up no space unless they are displaying an error message, which enables them to share the same
amic location (a table cell, for example). However, when the error message is displayed, the layout of the page changes, somet
imes causing controls to change positions.

None The validation control does not appear on the page.


Note
Dynamic layout requires a browser that supports dynamic HTML (DHTML). If your Web application will be used with browser
s that do not support DHTML, it is advisable instead to lay out the validation controls in a table cell or a Panel control.

See Also
Tasks
How to: Specify Layout for In-Place Messages On ASP.NET Server Controls
Other Resources
Validation ASP.NET Controls
ASP.NET

How to: Control Validation Error Message Display for ASP.NET


Server Controls
In Microsoft Visual Web Developer, you can display error message text in four different ways, as described in the following
table.
Display Description
metho
d
Inline The error message appears next to the control, in the place where the validation control is located.

Summa The error message is displayed in a separate summary of all errors, which is available only when the user submits the
ry page. Optionally, the error message can appear in a message box, but this option is available only in browsers that su
pport dynamic HTML (DHTML).

Inline an The error message can be different in the summary and inline. You can use this option to show a shorter error messa
d summ ge inline, with more detail in the summary, or to show an error glyph next to the input field and an error message in t
ary he summary.

Custom You can create your own error message display. For more information, see
How to: Display Server Side Custom Validation Messages for ASP.NET Server Controls.

If you want to display summarized error messages, you need to add a control to the page.
To display summarized error messages
1. Add a ValidationSummary control to the page at the location where you want to display the collected error messages.
2. Set the ErrorMessage and Display properties of the individual validation controls.
3. Set the DisplayMode property of the summary control to format the error messages, using one of the following values
that are defined in the ValidationSummaryDisplayMode enumeration:
Value Display
BulletList (Default) Each error message appears as a bulleted item.

List Each error message appears on its own line.

SingleParagraph Each error message appears as a sentence in a paragraph.

4. If you are associating individual validation controls with validation groups, then you will need to use one
ValidationSummary control for each validation group.
To display error messages inline and as a summary, you need to set different combinations of properties in the individual
validation controls.
To display inline and summarized error messages
1. Add a ValidationSummary control as described in the previous procedure.
2. Set the ErrorMessage, Text, and Display properties of the individual validation controls according to the following
table:
Option Requires ValidationSummary Property settings on validation control
control
Inline only No Display = Static or Dynamic
ErrorMessage = <error text> or Text = <
error text>

Summary only (including optional messag Yes Display = None


e box)
ErrorMessage = <error text> or Text = <
error text>

Inline and summary (including optional me Yes Display = Static or Dynamic


ssage box)
ErrorMessage = <error text for summary
>
Text = <inline error text or glyph>

If the client is running a browser that supports DHTML, summarized error messages can also appear in a message box.
To display summarized error messages in a message box
1. Set the ShowMessageBox property of the ValidationSummary control to true.
When the user submits the page, errors are displayed in both the ValidationSummary control and the message box.
2. To display summarized error messages only in a message box, set the ShowSummary property to false.

See Also
Tasks
How to: Specify Layout for In-Place Messages On ASP.NET Server Controls
Reference
Validating User Input in ASP.NET Web Pages
ASP.NET

How to: Format Validation Error Messages for ASP.NET Server


Controls
When using ASP.NET validation controls, you can control the format—font, size, and so on—of error text, or you can substitute
a marker for error text. For example, you can have the validation control display an asterisk (*) when an error occurs.
Note
Using a marker in place of text can detract from the accessibility of the page. For more information, see ASP.NET Accessibility
.

You can also include a detailed error message in the ErrorMessage property of the validation control and add a
ValidationSummary control to the page. The detailed ErrorMessage property text will appear on the page in the location of the
ValidationSummary control.
You can provide formatting within an error message by using HTML elements in the text for the ErrorMessage and Text
properties. For example, to apply italics to only one word in the error message, you can enclose the word in <i> and </i> tags.
Note
To display reserved HTML characters within the error message text, encode them. For example, to display "<", use the charact
er sequence &lt;.

If you are displaying validation errors in a summary, you can specify that a marker appear in place of the individual validation
control.
To format error messages
Set validation control properties such as the following:
Property Description
ForeColor The color of the error message text.

BackColor The color behind the text.

Font The font face, size, weight, and so on.

BorderWidth, BorderColor, and The size and color of a border around the error message.
BorderStyle

Style and CssClass Style settings that are used if the user is working with a browser that supports CSS
style sheets.
Note
Some of the settings you make with these properties may not be supported in all browsers.

To display markers next to input controls


1. Set the ErrorMessage property of each validation control to the error text that should appear in the
ValidationSummary control.
2. Set the Text property of each validation control to the marker to display. The marker can consist of any valid HTML,
including text (such as an asterisk) or an image.
Note
The marker is displayed in place of the validation control. It is up to you to lay out the validation control in such a way t
hat the marker displays properly.

See Also
Tasks
How to: Control Validation Error Message Display for ASP.NET Server Controls
How to: Specify Layout for In-Place Messages On ASP.NET Server Controls
Concepts
Types of Validation for ASP.NET Server Controls
Other Resources
Validation ASP.NET Controls
ASP.NET

How to: Specify Layout for In-Place Messages On ASP.NET


Server Controls
When an ASP.NET validation error message appears on the page, it becomes part of the layout of the page. You can specify
that the layout be fixed—the error message does not change the page layout when it appears—or dynamic. For details about
layout options, see Validation Error Message Layout for ASP.NET Server Controls.
To specify fixed or dynamic layout for client error messages
Set the Display property of each validation control to one of the following values from the ValidatorDisplay enumeration:
Option Description
None Used when you are using only the summary control

Static For a fixed layout

Dynamic For a dynamic layout


Note
A browser that supports dynamic HTML (DHTML) is necessary to view static layout.

See Also
Tasks
How to: Control Validation Error Message Display for ASP.NET Server Controls
How to: Format Validation Error Messages for ASP.NET Server Controls
Concepts
Types of Validation for ASP.NET Server Controls
Other Resources
Validation ASP.NET Controls
ASP.NET

How to: Display Server Side Custom Validation Messages for


ASP.NET Server Controls
You do not have to use the validation control to output a response when the validator or page IsValid property is false. On
both the client and server side you can create a custom response, such as a color change in a control or a font change for text
on a label.
To display custom validation messages
1. In the Page_Load event handler, call the Validate method of the validation control or of the page.
2. Check the IsValid property of the validation control or page and conditionally add text or a control, or change the
properties (for example, color) of a control.
The following code example displays the text "All entries are valid" when the IsValid property is true, and the text "There
are one or more invalid entries" when the property is false.
VB
If (Me.IsPostBack) Then
ValidationControl1.Validate()
If (ValidationControl1.IsValid) Then
lblOutput.Text = "All entries are valid."
Else
lblOutput.Text = "There are one or more invalid entries."
End If
End If

C#
if (this.IsPostBack)
{
ValidationControl1.Validate();
if (ValidationControl1.IsValid)
{
lblOutput.Text = "All entries are valid.";
}
else
{
lblOutput.Text = "There are one or more invalid entries.";
}
}

See Also
Tasks
How to: Control Validation Error Message Display for ASP.NET Server Controls
How to: Format Validation Error Messages for ASP.NET Server Controls
Concepts
Types of Validation for ASP.NET Server Controls
Client-Side Validation for ASP.NET Server Controls
Other Resources
Validation ASP.NET Controls
ASP.NET

How to: Test Validity Programmatically for ASP.NET Server


Controls
Validation controls test user input, set an error state, and produce error messages. They do not change the flow of page
processing—for example, they do not bypass your code if they detect a user input error. Instead, you test the state of the
controls in your code before performing application-specific logic. If you detect an error, you prevent your own code from
running; the page continues to process and is returned to the user with error messages.
Security Note
By default, ASP.NET Web pages automatically validate that malicious users are not attempting to send script or HTML elemen
ts to your application. For more information, see Script Exploits Overview.

You can test for a general, page-wide state, and you can test the state of individual controls. Typically, you do these things in
the event handlers that you create for a page.
To test for a general error state
In your code, test the page's IsValid property. This property rolls up the values of the IsValid properties of all the
validation controls on the page (using a logical AND); if any one validation control is set to invalid, the page's property
will return false.
Note
Validation information is not available during a page's initialization or load stage. However, you can call the Validate m
ethod manually during Page_Load and then test the page's IsValid property. For details about page states, see
ASP.NET Page Life Cycle Overview.

The following code example shows the event handler for a button. The code tests the page's IsValid property. Note that
there is no need for an else clause, because the page will be returned automatically to the browser and the validation
controls will display their own error messages.
VB
Public Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click

If Me.IsValid Then
' Perform database updates or other logic here
End If
End Sub

C#
void Button1_Click(object sender, System.EventArgs e)
{
if (IsValid)
{
// Perform database updates or other logic here.
}
}

To test for the error state of individual controls


Loop through the page's Validators collection, which contains references to all the validation controls. You can then
examine the IsValid property of each validation control.
Note
If you want to perform this check during Page_Load, you must manually call the Validate method first.

The following code example shows how you can get the state of individual validation controls.
VB
If (Me.IsPostBack) Then
Me.Validate()
If (Not Me.IsValid) Then
Dim msg As String
' Loop through all validation controls to see which
' generated the error(s).
Dim oValidator As IValidator
For Each oValidator In Validators
If oValidator.IsValid = False Then
msg = msg & "<br />" & oValidator.ErrorMessage
End If
Next
Label1.Text = msg
End If
End If

C#
if (this.IsPostBack)
{
this.Validate();
if (!this.IsValid)
{
string msg = "";
// Loop through all validation controls to see which
// generated the errors.
foreach (IValidator aValidator in this.Validators)
{
if (!aValidator.IsValid)
{
msg += "<br />" + aValidator.ErrorMessage;
}
}
Label1.Text = msg;
}
}

See Also
Tasks
How to: Control Validation Error Message Display for ASP.NET Server Controls
How to: Validate Programmatically for ASP.NET Server Controls
Reference
Validating User Input in ASP.NET Web Pages
ASP.NET

How to: Disable Validation for ASP.NET Server Controls


You might want to bypass validation under certain circumstances. For example, you might have a page in which users should
be able to post even if they did not fill out all the validated fields correctly. You can set an ASP.NET server control to bypass
validation on both the server and the client, or just on the client.
Security Note
By default, ASP.NET Web pages perform request validation to ensure that user input does not include script or HTML elemen
ts. You can disable this feature explicitly. For more information, see Script Exploits.

You can also disable a validation control so that it is not rendered to the page at all and no validation takes place using that
control.
If you want to perform validation on the server but not on the client, you can set an individual validation control to not emit
client-side script. This is useful if dynamic updating on the client creates problems with the layout of the page, or if you want to
execute some server code before validation takes place.
To disable validation in a specific control
Set the control's CausesValidation property to false.
The following example shows how you can create a Cancel button that bypasses a validation check:
VB
<asp:Button id="Button1" runat="server"
Text="Cancel" CausesValidation="False">
</asp:Button>

C#
<asp:Button id="Button1" runat="server"
Text="Cancel" CausesValidation="False">
</asp:Button>

To disable a validation control


Set the validation control's Enabled property to false.
To disable client-side validation
Set the validation control's EnableClientScript property to false.
See Also
Reference
Validating User Input in ASP.NET Web Pages
Concepts
Client-Side Validation for ASP.NET Server Controls
ASP.NET

How to: Validate Programmatically for ASP.NET Server


Controls
By default, ASP.NET validation controls perform validation automatically when the page is posted back to the server, after page
initialization (that is, after view-state and postback data have been processed) and before your event-handling code is called.
The controls might also perform validation in the browser if the browser supports client script.
However, there are times when you might want to perform validation yourself programmatically. You might validate
programmatically under these circumstances:
If validation values are not set until run time. For example, if you are working with a RangeValidator control, you might
be setting its MinimumValue and MaximumValue properties at run time based on values entered by the user. In that
case, default validation does not work, because at the time that the page calls the validation controls to perform
validation, there is insufficient information in the RangeValidator control.
If you want to determine the validity of a control (or of the page as a whole) in the Page_Load event handler. At that
stage of page processing, the validation controls have not yet been invoked, so the IsValid property of the page or of
individual controls is not set. (An exception is thrown if you try to get the value of this property.) However, if you want to
determine validity, you can programmatically call validation.
If you are adding controls (either input controls or validation controls) at run time.
More generally, you can validate programmatically any time when you want to have precise control over when validation is
carried out.
Security Note
By default, the ASP.NET Web pages automatically validate that malicious users are not attempting to send script or HTML ele
ments to your application. If you have disabled this feature, you can call the ValidateInput method yourself. For more informa
tion, see Script Exploits Overview.

To validate programmatically
Call the validation control's Validate method.
The control will perform its check and will set the IsValid property of the control and the page. If an error has been
detected, when the page is returned to the user, error messages will be displayed as usual.
The following code example shows how you can set properties programmatically. In this case, an ASP.NET Web page
takes reservations at a resort that features a free tour during every visit. Users must enter an arrival date and a departure
date, and then schedule the tour during their visit. A RangeValidator control is used to ensure that the user entered a
typical date format, and that the tour date falls between the arrival and departure dates.
Note
If a user enters a value that cannot be converted to a date, the validator control will throw an exception. For clarity, this
example does not include error handling.

The arrival and departure dates come from two TextBox Web server controls on the page, txtArrival and txtDeparture.
The tour date is entered in a third TextBox control, txtTourDate, which is validated by the RangeValidator control.
Note
When validating programmatically, you should disable client script so that the control will not show the wrong error m
essage before your server-side validation code executes. For details, see
How to: Disable Validation for ASP.NET Server Controls.

VB
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As _
System.EventArgs) Handles Button1.Click
RangeValidator1.MinimumValue = txtArrival.Text
RangeValidator1.MaximumValue = txtDeparture.Text
RangeValidator1.Type = ValidationDataType.Date
RangeValidator1.Validate()

If Not RangeValidator1.IsValid Then


RangeValidator1.ErrorMessage = "The tour date must " & _
"fall between the arrival and departure dates."
End If
End Sub

C#
private void Button1_Click(object sender, System.EventArgs e)
{
RangeValidator1.MinimumValue = txtArrival.Text;
RangeValidator1.MaximumValue = txtDeparture.Text;
RangeValidator1.Type = ValidationDataType.Date;
RangeValidator1.Validate();

if (!RangeValidator1.IsValid)
{
RangeValidator1.ErrorMessage = "The tour date must " +
"fall between the arrival and departure dates.";
}
}

See Also
Concepts
Types of Validation for ASP.NET Server Controls
Other Resources
Validation ASP.NET Controls
Visual Web Developer

Walkthrough Topics — Validation Controls


The following walkthrough topic demonstrates how to use ASP.NET validation controls to check user input.
Walkthrough Topics
Walkthrough: Validating User Input in a Web Forms Page
See Also
Other Resources
Validation Toolbox Controls
Visual Web Developer

How-to Topics — Validation Controls


The following procedures describe how to use ASP.NET validation controls to check user input.
How-to Topics
How to: Validate Required Entries for ASP.NET Server Controls
How to: Validate Against a Specific Value for ASP.NET Server Controls
How to: Validate Against a Data Type for ASP.NET Server Controls
How to: Validate Against Patterns for ASP.NET Server Controls
How to: Validate Against a Range of Values for ASP.NET Server Controls
How to: Validate Against Values in a Database for ASP.NET Server Controls
How to: Validate with a Custom Function for ASP.NET Server Controls
How to: Control Validation Error Message Display for ASP.NET Server Controls
How to: Format Validation Error Messages for ASP.NET Server Controls
How to: Specify Layout for In-Place Messages On ASP.NET Server Controls
How to: Display Server Side Custom Validation Messages for ASP.NET Server Controls
How to: Test Validity Programmatically for ASP.NET Server Controls
How to: Disable Validation for ASP.NET Server Controls
How to: Validate Programmatically for ASP.NET Server Controls
See Also
Other Resources
Validation Toolbox Controls
Visual Web Developer

Navigation Toolbox Controls


The topics in this section describe how to work with ASP.NET Web server controls that appear on the Navigation tab of the
Visual Web Developer Toolbox. You can use these controls to create menus and other navigation aids on ASP.NET Web pages.
For complete syntax information for Web server controls, see Web Server Control Syntax.
In This Section
Menu Web Server Control (Visual Studio)
SiteMapPath Web Server Control Overview
TreeView Control (Visual Studio)
See Also
Other Resources
Creating Web Site Navigation
Individual Web and HTML Controls
ASP.NET Web Server Controls (Visual Studio)
ASP.NET Web Pages (Visual Studio)
Visual Web Developer

Menu Web Server Control (Visual Studio)


The ASP.NET Menu control enables you to add navigational functionality to your Web pages. The Menu control supports a
main menu and submenus, and allows you to define dynamic menus (sometimes called "fly-out" menus). This section includes
information on how to work with the Menu control to create navigation using static items and data from various sources.
In This Section
ASP.NET Menu Control Overview
Walkthrough: Displaying a Menu on Web Pages
Walkthrough: Controlling ASP.NET Menus Programmatically
See Also
Other Resources
Creating Web Site Navigation
Navigation Toolbox Controls
Individual Web and HTML Controls
ASP.NET

ASP.NET Menu Control Overview


The ASP.NET Menu control allows you to develop both statically and dynamically displayed menus for your ASP.NET Web
pages. You can configure the contents of the Menu control directly in the control, or you can specify the contents by binding
the control to a data source.
Without writing any code, you can control the appearance, orientation, and content of an ASP.NET Menu control. In addition to
the visual properties exposed by the control, the control supports ASP.NET control skins and themes. For more information on
skins and themes, see ASP.NET Themes and Skins Overview.
Static Display and Dynamic Display
The Menu control has two modes of display: static and dynamic. Static display means that the Menu control is fully expanded
all the time. The entire structure is visible, and a user can click on any part. In a dynamically displayed menu, only the portions
you specify are static, while their child menu items are displayed when the user holds the mouse pointer over the parent node.
Static Display Behavior
You can control static display behavior by using the StaticDisplayLevels property of the Menu control. The
StaticDisplayLevels property indicates how many levels to display statically from the root of the menu. For example, if
StaticDisplayLevels is set to 3, your menu will be expanded to statically display its first three levels. The minimum static
display level is 1, and the control will throw an exception if the value is set to 0 or a negative number.
Dynamic Display Behavior
The MaximumDynamicDisplayLevels property specifies how many levels of dynamically appearing menu nodes should be
displayed after the static display level. For example, if your menu has a static level of 3 and a dynamic level of 2, the first three
levels of your menu would be statically displayed, while the next two levels would be dynamic.
If MaximumDynamicDisplayLevels is set to 0, no menu nodes will be dynamically displayed. If the
MaximumDynamicDisplayLevels is set to a negative number, an exception is thrown.
Defining Menu Content
You can define content for the Menu control in two ways: by adding individual MenuItem objects (declaratively or
programmatically), and by data binding the control to an XML data source.
Adding Menu Items Manually
You can add individual menu items to the control by specifying them in the Items property. The Items property is a collection
of MenuItem objects. The following example shows the declarative markup for a Menu control with three items, each of
which has two child items:

<asp:Menu ID="Menu1" runat="server" StaticDisplayLevels="3">


<Items>
<asp:MenuItem Text="File" Value="File">
<asp:MenuItem Text="New" Value="New"></asp:MenuItem>
<asp:MenuItem Text="Open" Value="Open"></asp:MenuItem>
</asp:MenuItem>
<asp:MenuItem Text="Edit" Value="Edit">
<asp:MenuItem Text="Copy" Value="Copy"></asp:MenuItem>
<asp:MenuItem Text="Paste" Value="Paste"></asp:MenuItem>
</asp:MenuItem>
<asp:MenuItem Text="View" Value="View">
<asp:MenuItem Text="Normal" Value="Normal"></asp:MenuItem>
<asp:MenuItem Text="Preview" Value="Preview"></asp:MenuItem>
</asp:MenuItem>
</Items>
</asp:Menu>

Data Binding to an XML Data Source


Binding to an XML file allows you to control the menu's content through edits to the file, rather than by using the designer. This
allows you to update the navigational aspect of your site without revisiting the Menu control or editing any code. If you have a
site with changing content, an XML file can be used to organize the content, and fed to the Menu control to make sure the
content is accessible to users of the Web site.
Appearance and Behavior
You can adjust the behavior of the Menu control through its properties. Additionally, you can control the behavior of dynamic
display, including the amount of time a menu node remains visible once it is displayed. For example, to change the Menu
orientation from horizontal to vertical, you can set the Orientation property as follows:
[Visual Basic]
Menu.Orientation = Orientation.Vertical

[C#]
Menu.Orientation = Orientation.Vertical;

Setting the property to Orientation.Horizontal changes the orientation back to horizontal.


You can set individual properties of the Menu control to specify the size, color, font, and other characteristics of its appearance.
In addition, you can apply skins and themes to the Menu control.
Style
Each menu level supports style properties. If no dynamic style properties are set, the static style properties are used. If dynamic
style properties are set and no static style properties are set, the default rendering of static style properties is used. The Menu
control style hierarchy is as follows:
1. Control
2. SubMenuStyles
3. MenuItemStyles
4. SelectedItemStyles
5. HoverMenuItemStyles
These styles are merged across dynamic and static menus by using the following logic:
Each individual style is applied to the appropriate action or item type.
All styles are a merged into the style preceding them in the hierarchy, with the last style overriding.
Note
Static menus never merge and dynamic style is applied if a static style is not defined.

Dynamic Appearance Timing


One aspect of a dynamic menu is the amount of time it takes for the dynamically appearing portion of a menu to disappear.
This value is configurable in milliseconds by adjusting the DisappearAfter property as follows:
[Visual Basic]
Menu.DisappearAfter = 1000

[C#]
Menu.DisappearAfter = 1000;

The default value is 500 milliseconds. If the value of DisappearAfter is set to 0, pausing outside of the Menu control causes it
to disappear immediately. Setting the value to -1 indicates that the pause time should be infinite, and only by clicking outside
of the Menu control will the dynamic portion vanish.
See Also
Reference
Menu
Visual Web Developer

Walkthrough: Displaying a Menu on Web Pages


This walkthrough illustrates how to place and configure an ASP.NET Menu control on a Web page.
One common aspect of Web sites of any complexity is a navigational menu. You can use the Menu control in ASP.NET to easily
set up a complex navigational menu without writing code.
The Menu control allows for multiple display options, including a static display where the menu is fully exposed and a dynamic
display where portions of the menu appear as the mouse pointer moves over the parent menu item. The control also provides
a combination of static and dynamic display modes that allow a series of root items that are static, but with child menu items
that appear dynamically.
You can configure the ASP.NET Menu control in the designer with static links to your pages or you can bind it automatically to
a hierarchical data source such as an XmlDataSource or a SiteMapDataSource control.
Tasks illustrated in this walkthrough include:
Creating a basic menu and configuring it statically to link to your pages.
Creating a more complex menu that is bound to a Web.sitemap XML file.
Adjusting the orientation of a menu.
Configuring multiple levels of static display versus dynamic display.
Prerequisites
In order to complete this walkthrough, you will need:
Microsoft Visual Web Developer (Visual Studio).
The .NET Framework.
Creating the Web Site
If you have already created a Web site in Visual Web Developer (for example, by completing the steps in
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and go to the next section,
"Creating a Basic Menu." Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, enter the name of the folder where you want to keep the pages of your Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click the programming language you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Creating a Basic Menu
The first step in creating a menu for your page is the placement of a Menu control.
To add a Menu control to the page
1. Switch to or open Default.aspx, and then switch to Design view.
2. From the Navigation control group in the Toolbox, drag a Menu control onto the page.
For this example, you will orient the menu horizontally rather than vertically.
To position the Menu control horizontally
Right-click the Menu control, click Properties, and then set Orientation to Horizontal.
Configuring a Basic Menu
In this section, you will define the menu items by using the Menu Item Editor.
To edit Menu control items
1. Right-click the Menu control, and then click Edit Menu Items.
The Menu Item Editor appears.
2. Under Items, click the Add a root item icon.
3. Under Properties for the new item, set Text to Home and NavigateURL to Default.aspx.
4. Under Items, click the Add a root item icon.
5. Under Properties, set Text to Products and NavigateURL to Products.aspx.
6. Under Items, click the Add a root item icon.
7. Under Properties, set Text to Services and NavigateURL to Services.aspx.
8. Click OK.
If you look at the source for Default.aspx, you will see that the menu items and links are stated declaratively in the control.
To create the target pages
1. In Solution Explorer, right-click the root of your Web site, and then click Add New Item.
2. Click Web Form, name the file Products.aspx, and then click Add.
3. Repeat the preceding steps and create a file named Services.aspx.
Testing the Menu
With your pages and menu in place, you can try it out.
To test the Menu control
1. Click Default.aspx in Solution Explorer and then press CTRL+F5 to run the Default.aspx page.
2. Move the pointer over the items; the browser's status bar at the bottom of the page (if visible) will show what page is
linked.
3. Click a link to jump to the page.
Creating a Menu Bound to a Site Map
In the last section, you created a simple static menu configured declaratively within the page. In this section, you skip editing
the Menu control items directly, and instead bind the control to a Web.sitemap file as an XML data source. This allows the
Menu control's structure to be maintained within a separate XML file that can be easily updated without modifying the page or
using the designer.
For this example you will use a second Menu control.
To create a second Menu control
From the Navigation group of the Toolbox, drag a second Menu control onto the Default.aspx page.
Next, you will need a Web.sitemap file to bind to.
To create a site map file
1. In Solution Explorer, right-click the root of your Web site, and then click Add New Item.
2. In the Add New Item <Websitename> dialog box, click Site Map.
3. Click Add.
4. Place the following XML code in the Web.sitemap file.
The XML represents the structure of the menu. Nested nodes become child menu items of parent node menu items.

<siteMap>
<siteMapNode title="Home" description="Home" url="default.aspx" >
<siteMapNode title="Products" description="Our products"
url="Products.aspx">
<siteMapNode title="Hardware"
description="Hardware choices"
url="Hardware.aspx" />
<siteMapNode title="Software"
description="Software choices"
url="Software.aspx" />
</siteMapNode>
<siteMapNode title="Services"
description="Services we offer"
url="Services.aspx">
<siteMapNode title="Training"
description="Training classes"
url="Training.aspx" />
<siteMapNode title="Consulting"
description="Consulting services"
url="Consulting.aspx" />
<siteMapNode title="Support"
description="Support plans"
url="Support.aspx" />
</siteMapNode>
</siteMapNode>
</siteMap>

5. Save the file.


Binding to a Site Map
Now you can create a navigation data source that points to your Web.sitemap file and bind your Menu control to it.
To bind to a Menu control to a site map
1. Open the Default.aspx file, and then switch to Design view.
2. Click the smart tag to display the Menu Tasks dialog box.
3. In the Menu Tasks dialog box, in the Choose Data Source drop-down list, click New Data Source.
The Data Source Configuration Wizard dialog box appears.
4. Click Site Map.
Under Specify an ID for the data source, the default name, SiteMapDataSource1, appears.
5. Click OK.
Testing Site Map Binding
With your pages and menu in place, you can try it out.
To test the site map binding
1. Press CTRL+F5 to run the Default.aspx page.
2. Move the pointer over the Home menu item of the second, vertical menu.
Products and Services appear.
3. Move the pointer over Products.
Hardware and Software appear.
If you look at the source code for Default.aspx, you will notice that unlike the first menu item, the items are not specified
declaratively; instead, the data source is referenced by the Menu control.
Adjusting Static and Dynamic Levels
The vertical menu you created in the preceding section uses a fully dynamic display, with only the top level remaining static.
With the Menu control, you have the ability to specify behavior based on pausing the mouse pointer and whether or not the
menu should be dynamic or static. In this section, you will adjust the dynamic and static qualities of the Menu control.
To make the Menu control static for two levels
1. On the Default.aspx page in Design view, right-click the second Menu control, and then click Properties.
2. Set StaticDisplayLevels to 2.
Testing the Dynamic Menu
With your pages and menu in place, you can try it out.
To test the dynamic menu
Press CTRL+F5 to run the Default.aspx page.
The first two levels of the menu are displayed, whereas the third level is dynamic.
Next Steps
The Menu control allows you to easily create navigation menus. You can configure the control for dynamic or static display
and bind it to a site map XML file. You might also want to experiment with the following additional options:
Apply a theme or skin to the Menu control. For details, see
Walkthrough: Customizing a Web Site Using Themes in Visual Studio
Learn more about site navigation. For details, see ASP.NET Site Navigation Overview.
Use a Menu control on a master page to provide site-wide navigation defined on a single page. For details, see
Walkthrough: Creating and Using ASP.NET Master Pages in Visual Web Developer.
Walk through the steps to implement site navigation. For details, see Walkthrough: Adding Site Navigation to a Web Site.
See Also
Tasks
Walkthrough: Controlling ASP.NET Menus Programmatically
Concepts
ASP.NET Menu Control Overview
Visual Web Developer

Walkthrough: Controlling ASP.NET Menus Programmatically


This walkthrough illustrates how to work with the ASP.NET Menu control programmatically by coordinating two menus on the
same page using code.
You can create navigational menus for your Web site using the ASP.NET Menu control. In this walkthrough, you explore the
programmatic aspects of the ASP.NET Menu control and create two menus bound to the same Web.sitemap file that work
together. The first menu is a statically displayed menu of categories such as products, services, and support. It will appear
horizontally across the top of the page. The second menu is displayed horizontally below the first menu. The content of the
second menu is determined by which menu item is selected in the first. Based on the current selection of the first menu, you
programmatically adjust the site map data source of the second menu to show only that portion of the Web.sitemap file that is
relevant to the selected category.
Prerequisites
To complete this walkthrough, you will need:
Microsoft Visual Web Developer (Visual Studio).
The .NET Framework.
Creating the Web Site
If you have already created a Web site in Visual Web Developer (for example, by following the steps in
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and skip to "Making the Site
Map File" later in this walkthrough. Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, enter the name of the folder where you want to keep the pages of your Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click the programming language you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Making the Site Map File
Both menus derive their content from the site's Web.sitemap file. The SiteMapDataSource objects you create are used by both
menus to ensure that each displays the appropriate portion of the site map.
To create the Web.sitemap file
1. In Solution Explorer, right-click the name of your Web site, and then click Add New Item.
2. In the Add New Item dialog box, choose Site Map and then click Add.
3. Add the following XML code to the new file. The XML represents a hierarchy of menu choices. The <siteMapNode>
elements are nested. Each node is a menu item that contains subitems, and some subitems have subitems of their own.
There are three second-level nodes below the Home node: Hardware, Software, and Support. Beneath them are various
subcategories.

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


<siteMap>
<siteMapNode title="Home">
<siteMapNode title="Products">
<siteMapNode title="Hardware" url="Default.aspx?node=hardware">
<siteMapNode title="Mouse"/>
<siteMapNode title="Keyboard"/>
<siteMapNode title="NetCard"/>
<siteMapNode title="Monitor"/>
<siteMapNode title="PC"/>
</siteMapNode>
<siteMapNode title="Software" url="Default.aspx?node=software">
<siteMapNode title="Spreadsheet"/>
<siteMapNode title="Word Processor"/>
<siteMapNode title="Presentation"/>
<siteMapNode title="Mail"/>
<siteMapNode title="Games"/>
</siteMapNode>
<siteMapNode title="Books" url="Default.aspx?node=books">
<siteMapNode title="Programming"/>
<siteMapNode title="Debugging"/>
<siteMapNode title="Testing"/>
<siteMapNode title="Web Apps"/>
<siteMapNode title="WinForm Apps"/>
</siteMapNode>
</siteMapNode>
<siteMapNode title="Services">
<siteMapNode title="Consulting" url="Default.aspx?node=consulting">
<siteMapNode title="Processes"/>
<siteMapNode title="Management"/>
<siteMapNode title="Recruiting"/>
</siteMapNode>
<siteMapNode title="Development" url="Default.aspx?node=development">
<siteMapNode title="Web Apps"/>
<siteMapNode title="Enterprise Apps"/>
<siteMapNode title="Database"/>
</siteMapNode>
</siteMapNode>
<siteMapNode title="Support">
<siteMapNode title="Drivers" url="Default.aspx?node=drivers">
<siteMapNode title="Audio"/>
<siteMapNode title="Network"/>
<siteMapNode title="Printer"/>
<siteMapNode title="Modem"/>
</siteMapNode>
<siteMapNode title="Manuals" url="Default.aspx?node=manuals">
<siteMapNode title="Applications"/>
<siteMapNode title="Troubleshooting"/>
<siteMapNode title="Installation"/>
<siteMapNode title="Internet"/>
</siteMapNode>
<siteMapNode title="Updates" url="Default.aspx?node=updates">
<siteMapNode title="Release 1"/>
<siteMapNode title="Game Package"/>
</siteMapNode>
</siteMapNode>
</siteMapNode>
</siteMap>

4. Save the file.


Making the First Menu
The first menu displays a single level of static menu items. It is displayed horizontally at the top of the page.
To create the first menu
1. In Solution Explorer, double-click the Default.aspx page to open it.
2. Switch to Design view.
3. From the Navigation control group in the Toolbox, drag a Menu control onto the page.
4. In the Properties window, set the Orientation property to Horizontal.
5. Set MaximumDynamicDisplayLevels to 0.
This ensures that no portions of the menu will appear in a dynamic, fly-out fashion.
6. Be sure that StaticDisplayLevels is set to 1.
This allows only one level to appear in the menu.
7. Click the smart tag on the Menu control.
The Menu Tasks dialog box appears.
8. Choose New Data Source in the Choose Data Source drop-down list.
9. In the Data Source Configuration Wizard, choose Site Map.
10. Accept the default name of SiteMapDataSource1 and click OK.
Configuring the First Data Source
Because the first menu displays only a single level of static menu items, you need to configure its data source to display the
appropriate portion of the Web.sitemap file. In this case, it is the second-level elements: Products, Services, and Support.
The default bindings of the Menu control to a SiteMapDataSource control make each menu item a navigation link. Because
you want to programmatically control the behavior of another menu, you use custom bindings so these menu items do not act
as navigation links but instead cause a postback to occur so the second menu can be updated.
To configure the first data source
1. View the Default.aspx page in Design view, and then click the smart tag on the Menu control.
The Menu Tasks dialog box appears.
2. Click Edit MenuItem Databindings.
3. In the Menu DataBindings Editor, in the Available data bindings drop-down list, select SiteMapNode and click
Add.
4. Select TextField in the Data binding properties drop-down list and select Title from the drop-down menu. Click OK.
5. Select the SiteMapDataSource control.
6. In Properties, set ShowStartingNode to False.
Creating the Second Menu
The second menu is dynamic, and its data source uses only a portion of the site map file that is determined programmatically
by what has been selected on the first menu. Like before, you want the menu to display its first level statically; however, you
now want the rest of the Web.sitemap file to appear dynamically.
To create the second menu
1. View the Default.aspx page in Design view, and then drag a second Menu control onto the page below the first Menu
control.
2. In Properties, set Orientation to Horizontal.
3. Click the smart tag on the second Menu control.
The Menu Tasks dialog box appears.
4. Choose New Data Source in the Choose Data Source drop-down list.
5. In the Data Source Configuration Wizard, choose Site Map.
6. Accept the default name of SiteMapDataSource2 and click OK.
Configuring the Second Data Source
In this section, you configure the data source to select only a particular section of the Web.sitemap file. To do this, you start
with the default first category in the first menu, which is the Products section of the Web.sitemap file. You then use the
StartingNodeURL property to indicate a specific URL attribute within the file.
To configure the second data source's starting point
1. Select SiteMapDataSource2 and set its StartingNodeURL property to "Default.aspx?node=hardware".
2. Set StartingNodeOffset to -1.
3. Set ShowStartingNode to False.
Adding Code to Coordinate the Menus
To control the second menu based on the state of the first menu, catch the MenuItemClick event of the first menu, and indicate
the second menu's view of the site map file in code.
To coordinate the menus in code
1. View the Default.aspx page in Design view and select Menu1.
2. In Properties, set the MenuItemClick event to Menu1_MenuItemClick.
A method named Menu1_MenuItemClick will be created for you in the code-behind file for the Default.aspx page, or inside
the <script> tags of the .aspx page if you are using the single-file page model.
3. Add the following highlighted code to the method.
VB
Protected Sub Menu1_MenuItemClick(ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.MenuEventArgs) _
Handles Menu1.MenuItemClick
Select Case e.Item.Value
Case "Products"
SiteMapDataSource2.StartingNodeUrl = "Default.aspx?node=hardware"
Case "Services"
SiteMapDataSource2.StartingNodeUrl = "Default.aspx?node=consulting"
Case "Support"
SiteMapDataSource2.StartingNodeUrl = "Default.aspx?node=drivers"
End Select
End Sub

C#
protected void Menu1_MenuItemClick(Object sender,
System.Web.UI.WebControls.MenuEventArgs e)
{
switch(e.Item.Value)
{
case "Products":
SiteMapDataSource2.StartingNodeUrl = "Default.aspx?node=hardware";
return;
case "Services":
SiteMapDataSource2.StartingNodeUrl = "Default.aspx?node=consulting";
return;
case "Support":
SiteMapDataSource2.StartingNodeUrl = "Default.aspx?node=drivers";
return;
}
}

The preceding code catches the click event of Menu1. Instead of navigating to any location, you use the value to
determine what the second Menu control displays. You accomplish that by adjusting the StartingNodeUrl property of
the second Menu control's SiteMapDataSource control.
4. Save the file.
Testing the Menus
To test the interaction between the two menus, click items on the first menu, and watch the second menu change accordingly.
The second menu is dynamic, and features the third level of the Web.sitemap file.
To test the menu
1. Press CTRL+F5 to run the page.
The first menu appears, with the secondary menu featuring the menu items beneath Products in the Web.sitemap file.
2. Click Services in the first menu.
The second menu now displays Consulting and Development dynamic menus.
3. Click Support.
The second menu displays the Drivers, Manuals, and Updates dynamic menu items.
Next Steps
The Menu control allows you to create navigation menus easily, and offers programmatic support for more complex scenarios.
You might also want to experiment with the following options:
Apply a theme or skin to the Menu control. For more information, see
Walkthrough: Customizing a Web Site Using Themes in Visual Studio
Learn more about site navigation. For more information, see ASP.NET Site Navigation Overview
Use a Menu control on a master page to provide side-wide navigation defined on a single page. For more information,
see Walkthrough: Creating and Using ASP.NET Master Pages in Visual Web Developer.
See Also
Tasks
Walkthrough: Displaying a Menu on Web Pages
Concepts
ASP.NET Menu Control Overview
ASP.NET

Using CSS and Styles with the Menu Control


Almost every aspect of the Menu control's appearance can be managed by using the properties of the Menu control or
cascading style sheets (CSS). By understanding which properties control which aspects of the rendering, you can tailor a
menu's appearance. This topic introduces the types of styles exposed by the Menu control and suggests some best practices
for setting styles with the Menu control.
You can set attributes of the various styles directly in the markup or use a style sheet. The CssClass property can be used to
assign a CSS class to a menu style that controls some aspect of the Menu control's appearance. The following example shows
how to specify a CssClass property for a number of Menu properties that you can then reference in a style sheet.

<asp:menu id="NavigationMenu2"
staticdisplaylevels="3"
orientation="Vertical"
target="_blank"
runat="server"
CssClass="menu2">
<levelsubmenustyles>
<asp:submenustyle CssClass="level1" />
<asp:submenustyle CssClass="level2"/>
<asp:SubMenuStyle CssClass="level3" />
</levelsubmenustyles>
...

Note that it is a best practice to either specify inline styles in the markup or use the CssClass property and specify styles using
a style sheet. It is not recommended that you both specify inline styles and use a style sheet, because unexpected behavior
could result. For a general discussion of using CSS with server controls, see ASP.NET Web Server Controls and CSS Styles.
Menu Behavior and Styles
The Menu control uses two modes of display: static and dynamic. Static display means that part or all of the menu structure is
always visible. A completely static menu displays the entire menu structure, and a user can click any part of it. Dynamic display
means that portions of the menu structure appear as the mouse pointer is positioned over certain items; child menu items are
displayed only when the user holds the mouse pointer over a parent node.
The StaticDisplayLevels property dictates how many levels of menu items are displayed statically. If you have four levels of
menu items and the StaticDisplayLevels property is set to 3, the first three levels are displayed statically and the last level of
menu items is displayed dynamically.
To control the appearance of the static portion of the menu, you can use the style properties with the word "Static" in the name:
StaticMenuStyle
StaticMenuItemStyle
StaticSelectedStyle
StaticHoverStyle
To control the appearance of the dynamic portion of the menu, you can use the style properties with the word "Dynamic" in the
name:
DynamicMenuStyle
DynamicMenuItemStyle
DynamicSelectedStyle
DynamicHoverStyle
The StaticMenuStyle and DynamicMenuStyle properties affect the entire set of static or dynamic menu items, respectively.
For example, if you specified a border using the DynamicMenuStyle property, the entire dynamic region would have a
border.
Contrast this behavior with the StaticMenuItemStyle and DynamicMenuItemStyle properties. These properties affect
individual menu items. For example, if you specified a border using the DynamicMenuItemStyle property, each dynamic
menu item would have its own border.
The StaticSelectedStyle and DynamicSelectedStyle properties affect only the selected menu item, and the
StaticHoverStyle and DynamicHoverStyle properties affect the style of the menu item when the mouse pointer is
positioned over the menu item.
Menu Levels
Another approach to controlling the appearance of menu items is to style each level in the menu structure separately. The
Menu control has several properties that act as collections of styles, which means that they can contain style information for
each level of a menu structure.
The style properties that you can use to specify the appearance for each level have the word "Level" in their names:
LevelMenuItemStyles
LevelSubMenuStyles
LevelSelectedStyles
The following example creates a collection of four styles that apply to the first four levels of menu items and could be
referenced in a style sheet by using the CssClass value.

<LevelMenuItemStyles>
<asp:MenuItemStyle CssClass="Level1Style" />
<asp:MenuItemStyle CssClass="Level2Style" />
<asp:MenuItemStyle CssClass="Level3Style" />
<asp:MenuItemStyle CssClass="Level4Style" />
</LevelMenuItemStyles>

The first style in the collection applies to the first-level menu items; the second style applies to the second-level menu items,
and so on. Note that there is no inheritance between level styles so that styles applied to one level do not affect subsequent
levels.
The following example creates a collection of three styles that apply to the first three levels of menu items and could be
referenced in a style sheet.

<LevelSubMenuStyles>
<asp:SubMenuStyle CssClass="submenulevel1" />
<asp:SubMenuStyle CssClass="submenulevel2" />
<asp:SubMenuStyle CssClass="submenulevel3" />
</LevelSubMenuStyles>

Common Menu Styling Scenario


The styles you use to format a Menu control depend on how much and where you want control over the appearance of the
menu items. For example, if you want each menu item level to have a consistent look, use the LevelMenuItemStyles property
to style each menu level. If you want all static menu items to look the same and all dynamic menu items to look the same, you
can use the StaticMenuItemStyle property to control the appearance of all static menu items and the
DynamicMenuItemStyle property to control the appearance of all dynamic menu items.
The following example shows the markup and style sheet contents necessary to create a specific menu. This example
demonstrates some best practices when using the Menu control, including:
The Menu control property Font is used in the markup to set the font for the overall menu.
The width of the control is set by the Width Menu control property.
The LevelMenuItemStyles property is used to specify the style for each menu item level.
The !important declaration is used in the style sheet to override the default font for the menu.
The following example provides the declarative code for the menu control.

<asp:menu id="NavigationMenu1" CssClass="menu1"


staticdisplaylevels="3"
staticsubmenuindent="0"
orientation="Vertical"
target="_blank"
Font-names="Arial, Gill Sans"
Width="100px"
runat="server">

<LevelMenuItemStyles>
<asp:MenuItemStyle CssClass="level1"/>
<asp:MenuItemStyle CssClass="level2"/>
<asp:MenuItemStyle CssClass="level3" />
</LevelMenuItemStyles>

<StaticHoverStyle CssClass="hoverstyle"/>

<LevelSubMenuStyles>
<asp:SubMenuStyle CssClass="sublevel1" />
</LevelSubMenuStyles>

<items>
<asp:menuitem text="Home" tooltip="Home">
<asp:menuitem text="Section 1" tooltip="Section 1">
<asp:menuitem text="Item 1" tooltip="Item 1"/>
<asp:menuitem text="Item 2" tooltip="Item 2"/>
<asp:menuitem text="Item 3" tooltip="Item 3"/>
</asp:menuitem>
<asp:menuitem text="Section 2" tooltip="Section 2">
<asp:menuitem text="Item 1" tooltip="Item 1"/>
<asp:menuitem text="Item 2" tooltip="Item 2">
<asp:MenuItem Text="Subitem 1"/>
<asp:menuitem Text="Subitem 2" />
</asp:menuitem>
<asp:menuitem text="Item 3" tooltip="Item 3"/>
</asp:menuitem>
</asp:menuitem>
</items>
</asp:menu>

The following example is the CSS code for the menu control.

.level1
{
color: White;
background-color: Black;
font-variant: small-caps;
font-size: large;
font-weight: bold;
}

.level2
{
color: Blue;
font-family: Gill Sans MT !important;
font-size: medium;
background-color: Gray;
}

.level3
{
color: black;
background-color: Silver;
font-family: Gill Sans MT !important;
font-size: small;
}

.hoverstyle
{
font-weight: bold;
}

.sublevel1
{
background-color: Gray !important;
color: White !important;
font-variant: small-caps;
}

The final Menu control is shown in the following illustration.

See Also
Tasks
Walkthrough: Controlling ASP.NET Menus Programmatically
Concepts
ASP.NET Web Server Controls and CSS Styles
Using Images with the Menu Control
ASP.NET

Using Images with the Menu Control


You can use images to indicate additional child menu items available when the mouse pointer is positioned over a menu item.
You can also use images to separate static or dynamic menu items, or to serve as a background for the entire menu or for a
level of menu items.
You can specify the images to be used and how those images appear using cascading style sheets (CSS) and the properties of
the Menu control.
Using the Default Pop-Out Images
You can use either of two properties, or both, to designate the images that indicate child menu items not shown when the
Menu control is first rendered. To use the default image to indicate that a static menu item has child items, set the
StaticEnableDefaultPopOutImage property to true; to use the default image for a dynamic menu item with child items, set the
DynamicEnableDefaultPopOutImage property to true. Setting the value to false for either or both of these properties hides the
default black arrow image on each menu item with child items.
The following example sets both values to true so that any static or dynamic menu items that have child items will display the
default black arrow image.

<asp:Menu ID="Menu1" runat="server"


StaticEnableDefaultPopOutImage="true"
DynamicEnableDefaultPopOutImage="true">

Specifying Custom Indicator Icons


To use custom images that you have created for indicator icons, you assign values to the StaticPopOutImageUrl and
DynamicPopOutImageUrl properties. Each of these properties specifies a file location and name that indicate the image to be
used. The StaticPopOutImageUrl property governs the image used for static menu items, and the
DynamicPopOutImageUrl property governs the image used for dynamic menu items.
The following example sets both the static and dynamic indicator icons to the image Greenarrow.gif, located in the Images
directory.

<asp:Menu ID="Menu1" Runat="server"


StaticPopOutImageUrl="~/images/greenarrow.gif"
DynamicPopOutImageUrl="~/images/greenarrow.gif">

Specifying Separator Images


Menu items at the same level can be separated from each other by separator images. You can specify separator images that
appear above and below menu items in a given level, or for all levels of the static or dynamic menu. Four properties are used
to specify separator images, two for the top and bottom separators for static menu items and two for the top and bottom
separators for dynamic menu items:
StaticTopSeparatorImageUrl
StaticBottomSeparatorImageUrl
DynamicTopSeparatorImageUrl
DynamicBottomSeparatorImageUrl
The following example specifies that the Greenseparator.gif image appears below each static menu item.

<asp:Menu ID="Menu2" Runat="server"


StaticBottomSeparatorImageUrl="~/greenseparator.gif">

Specifying Scroll Images


If you specify a lot of menu items, the pop-up window used to display dynamic menu items might not expand enough to show
all the menu items. The Menu control automatically creates scroll bars so users can scroll through the list of menu items, and
you can use the ScrollDownImageUrl and ScrollUpImageUrl properties to assign custom arrows or other images to the up and
down icons on the scrollbar.
The following example shows how you would use these two properties to specify custom images for the scrollbar arrows.

<asp:Menu ID="Menu1" Runat="server"


ScrollUpImageUrl="~/images/greenuparrow.gif"
ScrollDownImageUrl="~/images/greenuparrow.gif"

Specifying Image Size in CSS


How you work with images can significantly impact how they are displayed with a Menu control. For example, when a page is
first displayed and the images used on the Menu control have not yet been cached by a browser, these images can appear to
flicker or "jump" until the browser determines the image size. By specifying the size of the images used in the Menu control in
a cascading style sheet (CSS), you can prevent this from occurring.
If you use an image with a menu item, first assign a class name to the System.Web.UI.WebControls.WebControl.CssClass
property of the menu item using the image in the HTML markup. Then, in the CSS, you can indicate the size of the image. The
following example assigns the class name "menuitem" to the StaticMenuItemStyle and DynamicMenuItemStyle properties.

<StaticMenuItemStyle CssClass="menuitem" />


<DynamicMenuItemStyle CssClass="menuitem" />

In a CSS file that is referenced by the page containing the menu, you would then reference the menu item's CSS class and set
the image size.
The following example references the CSS class "menuitem" and specifies that a 40-pixel-by-40-pixel image is used to indicate
when a menu item has child items.

.menuitem {} /*Style code for each menu item goes here. */


.menuitem img
{
width: 40px;
height: 40px;
}

See Also
Tasks
Walkthrough: Displaying a Menu on Web Pages
Walkthrough: Controlling ASP.NET Menus Programmatically
Reference
Menu
Concepts
ASP.NET Web Server Controls and CSS Styles
ASP.NET Menu Control Overview
ASP.NET

SiteMapPath Web Server Control Overview


The SiteMapPath displays a navigation path (which is also known as a breadcrumb or eyebrow) that shows the user the current
page location and displays links as a path back to the home page. The control provides many options for customizing the
appearance of the links.
The SiteMapPath control obtains navigation data from a site map. This data includes information about the pages in your
Web site, such as the URL, title, description, and location in the navigation hierarchy. Storing your navigation data in one place
makes it easier to add and remove items in the navigational menus of your Web site.
In earlier versions of ASP and ASP.NET, when you added a page to your Web site and then added a link to that new page from
every other page in the Web site, you had to add the links manually, include a common file, or develop custom navigation
functionality. ASP.NET version 2.0 includes navigation controls that make navigational menus easy to create, customize, and
maintain.
The following code example shows site-map data that is included in a Web.sitemap file.

<siteMap>
<siteMapNode title="Home" description="Home" url="~/default.aspx" >
<siteMapNode title="Services" description="Services we offer"
url="~/Services.aspx">
<siteMapNode title="Training" description="Training classes"
url="~/Training.aspx" />
<siteMapNode title="Consulting" description="Consulting services"
url="~/Consulting.aspx" />
</siteMapNode>
</siteMapNode>
</siteMap>

Note
Only pages that are listed in the site map can display navigation data in the SiteMapPath control. If you place a SiteMapPat
h control on a page that is not listed in the site map, the control will display nothing to the client.

You can add a SiteMapPath control to the Training.aspx page by adding the following code.

<asp:SiteMapPath ID="SiteMapPath1" Runat="server"></asp:SiteMapPath>

When the Training.aspx page is viewed by a client, the SiteMapPath control will display something like the following, with
Home and Services rendered as hyperlinks:
Home > Services > Training
You can use the SiteMapPath control to create site navigation without code and without binding data. The control can read
and render the site-map information automatically. However, if needed, you can also use the SiteMapPath control to alter
site-map data. For more information, see How to: Programmatically Modify Site-Map Nodes in Memory.
The SiteMapPath control allows users to navigate backward — from the current page to pages that are higher in the site
hierarchy. However, the SiteMapPath control does not allow you to navigate forward — from the current page to another
page that is lower in the site hierarchy. For example, you can use the SiteMapPath control in newsgroup or message board
applications to allow users to see the path to the article that they are currently browsing.
See Also
Tasks
How to: Customize the Appearance of SiteMapPath Web Server Controls
How to: Filter the Nodes Retrieved by SiteMapDataSource Web Server Controls
Reference
SiteMapPath
XmlSiteMapProvider
Concepts
ASP.NET Site Navigation Overview
Securing ASP.NET Site Navigation
Securing Data Access
Other Resources
ASP.NET Application Security in Hosted Environments
Visual Web Developer

TreeView Control (Visual Studio)


The topics in this section describe how to work with the ASP.NET TreeView Web control to display hierarchical data (such as a
table of contents) in a tree structure in a Web page. The TreeView control is made up of TreeNode objects. The TreeView
control can be bound to data.
In This Section
TreeView Web Server Control Overview
Walkthrough: Displaying Hierarchical Data in a TreeView Control
Populating Tree Nodes in the TreeView Web Server Control
How to: Add or Delete TreeView Node Elements (Visual Studio)
Binding Data to the TreeView Web Server Control
Selection, Navigation, and Check Boxes in the TreeView Web Server Control
TreeView Web Server Control Events
Customizing the Look and Feel of the TreeView Web Server Control
See Also
Other Resources
Creating Web Site Navigation
Navigation Toolbox Controls
Individual Web and HTML Controls
ASP.NET

TreeView Web Server Control Overview


The TreeView Web server control is used to display hierarchical data, such as a table of contents or file directory, in a tree
structure. It supports the following features:
Automatic data binding, which allows the nodes of the control to be bound to hierarchical data, such as an XML
document.
Site navigation support through integration with the SiteMapDataSource control.
Node text that can be displayed as either selectable text or hyperlinks.
Customizable appearance through themes, user-defined images, and styles.
Programmatic access to the TreeView object model, which allows you to dynamically create trees, populate nodes, set
properties, and so on.
Node population through client-side callbacks to the server (on supported browsers).
The ability to display a check box next to each node.
TreeView Node Types
The TreeView control is made up of one or more nodes. Each entry in the tree is called a node and is represented by a
TreeNode object. The following table describes the three different node types.
Node type Description
Root A node that has no parent node and one or more child nodes.

Parent A node that has a parent node and one or more child nodes.

Leaf A node that has no child nodes.

Although a typical tree has only one root node, the TreeView control allows you to add multiple root nodes to your tree
structure. This is useful when you want to display item listings without displaying a single main root node, as in a list of
product categories.
Each node has a Text property and a Value property. The value of the Text property is displayed in the TreeView control, while
the Value property is used to store any additional data about the node, such as data passed to the postback event that is
associated with the node.
When a node of the TreeView control is clicked, it can either raise a selection event (via postback) or navigate to another page.
When the NavigateUrl property is not set, clicking a node will raise a SelectedNodeChanged event that can be handled to
provide custom functionality. Each node also has a SelectAction property that can be used to determine specific actions that
happen when the node is clicked, such as expand or collapse the node. Instead of raising a selection event to navigate to a page
when a node is clicked, set the NavigateUrl property of the node to a value other than an empty string ("").
Displaying Data in the TreeView Control
The TreeView control can display several different types of data: static data that is specified declaratively in the control, data
that is bound to the control, or data that is added to the TreeView control programmatically, in response to user actions.
Displaying Static Data
You can display static data in the TreeView control by creating a collection of TreeNode elements that are children of the
TreeView control. These child elements are also known as child nodes.
The following example shows the markup for a TreeView control that contains three nodes, two of which have child nodes.

<asp:TreeView ID="MyTreeView" Runat="server">


<Nodes>
<asp:TreeNode Value="Child1" Expanded="True" Text="1">
<asp:TreeNode Value="Grandchild1" Text="A" />
<asp:TreeNode Value="Grandchild2" Text="B" />
</asp:TreeNode>
<asp:TreeNode Value="Child2" Text="2" />
<asp:TreeNode Value="Child3" Expanded="True" Text="3">
<asp:TreeNode Value="Grandchild1" Text="A" />
</asp:TreeNode>
</Nodes>
</asp:TreeView>

Bind Data to the TreeView Control


You can bind a TreeView control to a data source that supports the IHierarchicalDataSource interface, such as the
XmlDataSource and SiteMapDataSource controls. Additionally, when binding data, you have complete control over which
fields are populated from the data source. For more information, see Binding Data to the TreeView Web Server Control.
Displaying Data Programmatically by Using TreeNodeCollection
You can populate a TreeView control with data programmatically by accessing the Nodes property, which returns a
TreeNodeCollection class. TreeNodeCollection is a strongly typed collection of TreeNode objects. Because a TreeNode
object contains a property called ChildNodes that can contain TreeNode objects, the TreeNodeCollection class is a
hierarchal data structure that represents all of the nodes of the TreeView control.
For an example of how to traverse the Nodes collection, see Nodes.
Populating TreeNode Data on Demand
It might not be practical to define your data structure statically, or the data might depend on information that is gathered at
run time. To display data dynamically, the TreeView control supports dynamic node population. When the TreeView control
is configured to populate on demand, the control raises an event when a user expands the node. The event handler retrieves
the appropriate data and then populates the node that the user has clicked. To populate the TreeNode object with data on
demand, set the PopulateOnDemand property of a node to true, and create a TreeNodePopulate event handler to populate the
TreeNode object with data.
Client-Side TreeView Node Population
Any browser that has the SupportsCallback property set to true in the browser capabilities configuration file supports client-
side node population.
Client-side node population enables the TreeView control to populate a node by calling the server's TreeNodePopulate
event from client script instead of requiring a full postback to the server. For more information about client-side node
population, see PopulateNodesFromClient.
Enabling Client Script
By default, on up-level browsers, the expand-collapse functionality of a node on the TreeView control is performed using
client script. Using client script increases the efficiency of the rendering because the control does not have to post back to the
server to render the new configuration.
Note
If client script is disabled in the browser or the browser does not support client script, then the TreeView control will revert t
o down-level mode and post back to the server each time a user clicks the node.

TreeView Postback
By default, the TreeView control handles expand-collapse functionality on the client unless the browser does not support
client script or the EnableClientScript property is set to false. If the PopulateNodesFromClient property is set to true and the
browser supports client script, then the TreeView control retrieves the data from the server without posting the entire page
back.
When the TreeView control is in selection mode, each time a user clicks a node, a postback to the server occurs and the
SelectedNodeChanged event is raised.
Typically, you should handle postback events when the TreeView control is in selection mode or the nodes are being
dynamically populated. This is because either the PopulateOnDemand or PopulateNodesFromClient property is set to
true.
TreeNode Rendering
Each TreeNode object contains four UI elements, which are shown in the following image and described in the table below.
TreeNode UI Elements
Item Description
Expand/Coll An optional image that indicates whether the node can be expanded to show child nodes. By default, this is a plus
apse image sign [+] if the node can be expanded, or a minus sign [-] if the node can be collapsed.

Check box Check boxes can be optionally enabled, which allows users to select a particular node.

Node image You can specify a node image to display next to the node text.

Node text Node text is the actual text that displays on the TreeNode object. Node text can behave like a hyperlink in naviga
tion mode, or like a button in selection mode.

In addition to its own properties, the TreeView control supports properties of the TreeNodeStyle control for each node type.
These style properties override the NodeStyle property, which applies to all node types.
The TreeView also has a NodeIndent property that specifies the indentation level for all nodes. Nodes are indented from the
side on which the TreeView control is rendered. This is the left side for locales that render from left to right, and it is the right
side for locales that render from right to left.
A node can also have a different style applied when it is selected or when the mouse hovers over the node. When the Selected
property of a node is set to true, the SelectedNodeStyle property is applied, which overrides any unselected style properties
for the selected node. When the mouse hovers over a node, the HoverNodeStyle property is applied. The following image and
table describe the TreeNodeStyle properties.
TreeNodeStyle Properties

Node Property Description


NodeSpacing Specifies the amount of vertical spacing between the entire current node and adjacent nodes above and b
elow.

VerticalPadding Specifies the amount of space rendered on the top and bottom of the TreeNode text.

HorizontalPadding Specifies the amount space rendered on the left and right of the TreeNode text.

ChildNodesPadding Specifies the amount of space above and below the child nodes of the TreeNode.

ImageUrl Specifies the path to the image that displays next to the TreeNode.

For more information, see Customizing the Look and Feel of the TreeView Web Server Control.
Displaying a Check Box Next to a TreeView Node
Another custom rendering feature of the TreeView control is its ability to render check boxes between the node text and
image by using the ShowCheckBoxes property. Showing check boxes allows the user to select multiple nodes at once, which is
especially useful for interfaces like a newsgroup tree, where users can select and subscribe to multiple newsgroups at once. For
more information about using check boxes, see Selection, Navigation, and Check Boxes in the TreeView Web Server Control.
Using the ExpandDepth Property
By default, the TreeView control displays all of the nodes of the tree expanded. You can configure the TreeView control to
initially display to any depth. To do so, you can set the ExpandDepth property to a number reflecting the node level that you
want to display. For example, if you set the ExpandDepth property to 2, then two levels of the node, or two child nodes, will
display when the site initially renders on the client.
See Also
Concepts
Populating Tree Nodes in the TreeView Web Server Control
Customizing the Look and Feel of the TreeView Web Server Control
TreeView Web Server Control Events
Selection, Navigation, and Check Boxes in the TreeView Web Server Control
Visual Web Developer

Walkthrough: Displaying Hierarchical Data in a TreeView


Control
The ASP.NET TreeView control is designed to present users with data in a hierarchical structure. Users can open individual
nodes that can in turn contain child nodes. The TreeView control is suitable for displaying XML data, but can be used for any
data that can be represented in a hierarchy. This walkthrough shows you the basics of using the TreeView control and various
ways to display hierarchical data.
Tasks illustrated in this walkthrough include:
Using the TreeView control to display XML data.
Customizing the display of the TreeView control.
Displaying records from related database tables in the TreeView control.
Prerequisites
In order to complete this walkthrough, you will need:
Microsoft Visual Web Developer (Visual Studio).
Microsoft Data Access Components (MDAC) version 2.7 or later.
If you are using Microsoft Windows XP or Windows Server 2003, you already have MDAC 2.7. However, if you are using
Microsoft Windows 2000, you might need to upgrade the MDAC already installed on your computer. For more
information, see "Microsoft Data Access Components (MDAC) Installation" in the MSDN Library.
Access to the SQL Server Northwind database. For information about downloading and installing the SQL Server sample
Northwind database, see Installing Sample Databases on the Microsoft SQL Server Web site.
Note
If you need information about how to log on to the computer running SQL Server, contact the server administrator.

A user name and password for a SQL Server account that has access to the Northwind database, if the SQL Server
database is not on the same computer as the Web server.
Creating the Web Site
Create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New, and then click Web Site. If you are using Visual Web Developer Express, on the File menu,
click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, select File System, and enter the name of the folder where you want to keep the pages of your Web
site.
For example, type the folder name C:\WebSites\HierarchicalData.
5. In the Language list, click the programming language you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Creating an XML File for Data
Create a new XML file by following these steps.
To create the XML file
1. In Solution Explorer, right-click the Web site, and then click Add New Item.
2. In the Add New Item dialog box, under Standard Templates, click XML File.
3. In the Name box, type Bookstore.xml, and then click Add.
Visual Web Developer creates the new Bookstore.xml file and opens the code editor.
4. Copy the following XML data, and then paste it into the Bookstore.xml file, overwriting what is already in the file.

<?xml version="1.0" standalone="yes"?>


<bookstore>
<genre name="fiction">
<book ISBN="10-000000-001">
<title>The Iliad and The Odyssey</title>
<price>12.95</price>
<comments>
<userComment rating="4">
Best translation I've read.
</userComment>
<userComment rating="2">
I like other versions better.
</userComment>
</comments>
</book>
<book ISBN="10-000000-999">
<title>Anthology of World Literature</title>
<price>24.95</price>
<comments>
<userComment rating="3">
Needs more modern literature.
</userComment>
<userComment rating="4">
Excellent overview of world literature.
</userComment>
</comments>
</book>
</genre>
<genre name="nonfiction">
<book ISBN="11-000000-002">
<title>Computer Dictionary</title>
<price>24.95</price>
<comments>
<userComment rating="3">A valuable resource.</userComment>
</comments>
</book>
<book ISBN="11-000000-003">
<title>Cooking on a Budget</title>
<price>23.95</price>
<comments>
<userComment rating="4">Delicious!</userComment>
</comments>
</book>
</genre>
</bookstore>

The XML file contains information about books that might be available from an online bookstore.
5. Save the Bookstore.xml file, and then close it.
Displaying XML Data in the TreeView Control
In this section, you will use the TreeView control to display the XML data. To begin, you can display the XML information
without any special configuration.
To display the XML data
1. Open the Default.aspx page, and then switch to Design view.
2. In the Toolbox, from the Navigation group, drag a TreeView control onto the page.
3. Right-click the TreeView control, and then click Show Smart Tag.
4. On the TreeView Tasks menu, in the Choose Data Source drop-down list, select New Data Source. The Data Source
Configuration Wizard appears.
5. In the Where will the application get data from? window, select XML File. Leave the default ID for the data source.
Click OK.
6. In the Configure Data Source dialog box, in the Data file box, enter ~/Bookstore.xml, and then click OK.
You can now test the page.
To test the page
1. Press CTRL+F5 to run the page.
2. Collapse, and then expand, the nodes in the control.
By default, the nodes display only the tag names of the elements in the Bookstore.xml file.
You can customize the information displayed in the TreeView control by creating custom bindings, which allow you to specify
what information from the XML file to display for each node.
To create custom bindings
1. On the Default.aspx page, right-click the TreeView control, and then click Show Smart Tag.
2. On the TreeView Tasks menu, click Edit TreeNode Databindings.
The TreeView DataBindings Editor dialog box appears.
3. Clear the Auto generate data bindings check box, because you will define the data bindings.
4. Click Add to create a new binding, and then, under Data binding properties, set DataMember to bookstore and set
Text to Book Information.
You are configuring the binding to display a static value, because the Bookstore node is the top-most node in the .xml
file and appears only once in the TreeView control.
5. Click Add to create a second binding, and then, under Data binding properties, set DataMember to genre and
TextField to name.
This specifies that the node will read the <genre> element in the .xml file and assign its name attribute to the TextField
property.
6. Click Add to create a third binding for books, and then, under DataBinding Properties, set DataMember to book and
TextField to ISBN.
7. Click OK.
You can now test the page.
To test the page
Press CTRL+F5 to run the page.
This time, the TreeView control displays the three levels corresponding to the bindings that you have defined. The three
levels are the root node, labeled Book Information, the genre groups, and the ISBN details.
You can create a data binding for any element in an XML file, but you can bind only to the attributes of the element, the inner
text, the name of the element, or the value of the element. You cannot bind to any of the nested elements. To display values in
the nested elements, you create separate bindings to those elements. An alternative method is to transform the XML file using
XSLT, so that the inner elements are converted to attributes. For more information and an example, see the
System.Web.UI.WebControls.XmlDataSource.TransformFile property.
Displaying Relational Data in the TreeView Control
The TreeView control can display any type of hierarchical data, even if the data hierarchy is logical, as in a database, and not
physical, as in an XML file. In this section, you will use the TreeView control to display data from related tables in the
Northwind database.
To start, you will create a connection to the computer running SQL Server where you have the Northwind database.
To create a connection to SQL Server
1. In Server Explorer, right-click Data Connections, and then click Add Connection. If you are using Visual Web
Developer Express, use Database Explorer.
The Add Connection dialog box appears.
If the Data source list does not display Microsoft SQL Server (SqlClient), click Change, and in the Change Data
Source dialog box, select Microsoft SQL Server.
If the Choose Data Source page appears, in the Data source list, select the type of data source you will use. For
this walkthrough, the data source type is Microsoft SQL Server. In the Data provider list, click .NET Framework
Data Provider for SQL Server, and then click Continue.
Note
If the Server Explorer tab is not visible in Visual Web Developer, in the View menu, click Server Explorer. If the Databa
se Explorer tab is not visible, in the View menu, click Database Explorer.

2. In the Add Connection box, enter your server name in the Server Name box.
3. For the Log on to the server section, select the option that is appropriate to access the running the SQL Server database
(integrated security or specific ID and password) and, if required, enter a user name and password.
4. Select the Save my Password check box.
Note
In production applications, do not use Save my Password because this embeds the user name and password in the ap
plication files.

5. Under Select or enter a database name, enter Northwind.


6. Click Test Connection, and when you are sure that it works, click OK.
Your new connection has been created under Data Connections in Server Explorer (or Database Explorer).
Configuring a TreeView Control to Display Database Data
In this section, you will dynamically populate nodes with data. The first-level nodes will represent master data — in this case,
categories. When users click a node, the child nodes for the category will be created by making a query to the database that
retrieves the products for that category. To retrieve the data, you can use a data source control. However, in this walkthrough,
you will create and execute a query programmatically.
To begin, create a new page and a new TreeView control.
To create the new page and TreeView control
1. Add an ASP.NET Web page (Web Form page) named TreeViewDynamic.aspx to your Web site.
2. Open the TreeViewDynamic.aspx page, switch to Design view, and then in the Toolbox, from the Standard group, drag a
Label control onto the page and name it labelStatus.
The labelStatus control is used for error reporting only.
3. In the Toolbox, from the Navigation group, drag a TreeView control onto the page.
4. Right-click the TreeView control, click Properties, and then set MaxDataBindDepth to 2.
5. Right-click the TreeView control, click Show Smart Tasks, and then on the TreeView Tasks menu, click Edit Nodes.
6. In the TreeView Node Editor dialog box, click the icon labeled Add a root node, and then, under Properties, set Text
to Product List and PopulateOnDemand to true.
7. Click OK.
You are creating the topmost node of the tree, which contains only static text.
To configure the Web.config file
1. In the Toolbox, from the Data group, drag a SqlDataSource control onto the page.
2. Select the SqlDataSource control, and then click Show Smart Tag.
3. On the SqlDataSource Tasks menu, click Configure Data Source.
The Configure Data Source - SqlDataSource1 wizard displays a page in which you can choose a connection.
4. In the Which data connection should your application use to connect to the database? box, enter the connection
that you created in "To create a connection to SQL Server," and then click Next.
The wizard displays a page in which you can choose to store the connection string in a configuration file. Storing the
connection string in the configuration file has two advantages:
It is more secure than storing it in the page.
You can use the same connection string in multiple pages.
5. Select the Yes, save this connection as check box, and then click Next.
The wizard displays a page in which you can specify what data you want to retrieve from the database.
6. Under Specify columns from a table or view, in the Name box, click Categories.
7. Under Columns, select the CategoryID and CategoryName boxes.
8. Click Next.
9. Click Finish.
You will use the connection string created in the Web.config file later, in the RunQuery method defined later in this
walkthrough. You will not use the SqlDataSource control.
Now, you will add code to populate the control's child nodes when users click the node. To add nodes dynamically, you create
an event handler for the TreeNodePopulate event.
To create the event handler
1. Right-click the TreeView control, and then in Properties, click the Events icon.
2. Double-click the box for the TreeNodePopulate event.
Visual Web Developer switches to Source view.
3. Add the following highlighted code to the handler.
VB
Protected Sub TreeView1_TreeNodePopulate(ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.TreeNodeEventArgs) _
Handles TreeView1.TreeNodePopulate
If e.Node.ChildNodes.Count = 0 Then
Select Case e.Node.Depth
Case 0
PopulateCategories(e.Node)
Case 1
PopulateProducts(e.Node)
End Select
End If
End Sub

C#
protected void TreeView1_TreeNodePopulate(
object sender, TreeNodeEventArgs e)
{
if (e.Node.ChildNodes.Count == 0)
{
switch (e.Node.Depth)
{
case 0:
PopulateCategories(e.Node);
break;
case 1:
PopulateProducts(e.Node);
break;
}
}
}

This code is called when a user clicks a node to open it. Because you want to display different data at different levels of
the tree, you must determine which node depth the user has clicked, and then populate the nodes at that level
appropriately. In this walkthrough, the PopulateCategories method is called if the user clicks the root node (depth 0).
The PopulateProducts method is called if the user clicks a category name (depth 1). The methods are shown in the next
section.
The TreeNodeEventArgs object provides programmatic access to the current node. To populate the node, you add
elements to it. In the example code, the node is passed to the method that will add the child nodes.
Reading Node Data from the Database
The information to display in each node comes from the database. You must write the code that performs the database query,
reads the records, and creates a node for each record. This walkthrough assumes that you are working with the SQL Server
Northwind sample database, so you must use ADO.NET objects from the System.Data.SqlClient namespace.
For the first level of nodes (level 0), you will display a list of all available categories. The code you create calls a RunQuery
method that you will create later in the walkthrough.
To add nodes for all categories
1. Switch to Source view.
2. If you are working with a single-file page, add the following directives to the top of the code page.

<%@ Import Namespace="System.Data" %>


<%@ Import Namespace="System.Data.SqlClient" %>

Importing the namespaces will make it easier to write the code you need.
3. If you are working with a code-behind page, switch to the code-behind page (TreeViewDynamic.aspx.vb or
TreeViewDynamic.aspx.cs) and add the following lines to the top of the code file, outside the class declaration.
VB
Imports System.Data
Imports System.Data.SqlClient

C#
using System.Data;
using System.Data.SqlClient;

4. Make sure the page is still in Source view.


5. Add the following method to the page code.
VB
Sub PopulateCategories(ByVal node As TreeNode)
Dim sqlQuery As New SqlCommand( _
"Select CategoryName, CategoryID From Categories")
Dim ResultSet As DataSet
ResultSet = RunQuery(sqlQuery)
If ResultSet.Tables.Count > 0 Then
Dim row As DataRow
For Each row In ResultSet.Tables(0).Rows
Dim NewNode As TreeNode = New _
TreeNode(row("CategoryName").ToString(), _
row("CategoryID").ToString())
NewNode.PopulateOnDemand = True
NewNode.SelectAction = TreeNodeSelectAction.Expand
node.ChildNodes.Add(NewNode)
Next
End If
End Sub

C#
void PopulateCategories(TreeNode node)
{
SqlCommand sqlQuery = new SqlCommand(
"Select CategoryName, CategoryID From Categories");
DataSet resultSet;
resultSet = RunQuery(sqlQuery);
if (resultSet.Tables.Count > 0)
{
foreach (DataRow row in resultSet.Tables[0].Rows)
{
TreeNode NewNode = new
TreeNode(row["CategoryName"].ToString(),
row["CategoryID"].ToString());
NewNode.PopulateOnDemand = true;
NewNode.SelectAction = TreeNodeSelectAction.Expand;
node.ChildNodes.Add(NewNode);
}
}
}

The code creates a SqlCommand object that encapsulates the text of the query. It passes the object to a method (which
you will write) that performs the database query and returns a DataSet object. The code then loops through the records
in the DataSet object and creates a new node for each record, setting the text and value of the node with database
information. Then, the code sets the PopulateOnDemand property of each node to true so that the node will raise its
TreeNodePopulate event when clicked. The SelectAction property is set so that the nodes are expanded by default.
The second level of nodes will display the products for each category. For this reason, populating the products nodes requires a
parameterized query so that you can retrieve the products for the current category and populate the child nodes appropriately.
To add nodes for products
Add the following method to the page code.
VB
Sub PopulateProducts(ByVal node As TreeNode)
Dim sqlQuery As New SqlCommand
sqlQuery.CommandText = "Select ProductName From Products " & _
" Where CategoryID = @categoryid"
sqlQuery.Parameters.Add("@categoryid", SqlDbType.Int).Value = _
node.Value
Dim ResultSet As DataSet = RunQuery(sqlQuery)
If ResultSet.Tables.Count > 0 Then
Dim row As DataRow
For Each row In ResultSet.Tables(0).Rows
Dim NewNode As TreeNode = New _
TreeNode(row("ProductName").ToString())
NewNode.PopulateOnDemand = False
NewNode.SelectAction = TreeNodeSelectAction.None
node.ChildNodes.Add(NewNode)
Next
End If
End Sub

C#
void PopulateProducts(TreeNode node)
{
SqlCommand sqlQuery = new SqlCommand();
sqlQuery.CommandText = "Select ProductName From Products " +
" Where CategoryID = @categoryid";
sqlQuery.Parameters.Add("@categoryid", SqlDbType.Int).Value =
node.Value;
DataSet ResultSet = RunQuery(sqlQuery);
if (ResultSet.Tables.Count > 0)
{
foreach (DataRow row in ResultSet.Tables[0].Rows)
{
TreeNode NewNode = new
TreeNode(row["ProductName"].ToString());
NewNode.PopulateOnDemand = false;
NewNode.SelectAction = TreeNodeSelectAction.None;
node.ChildNodes.Add(NewNode);
}
}
}

This code is similar to the code used to populate the categories node. One difference is that the SqlCommand object is
configured with a parameter that is set at run time with the value of the node that the user clicked; that is, of the selected
category. Another difference is that the PopulateOnDemand property is set to false. This causes the products nodes to
be displayed without an expansion button, which is necessary because there are no more nodes below products.
The final step is to create the method that performs the query and returns the dataset.
To perform the query
Add the following subroutine to the page.
VB
Function RunQuery(ByVal sqlQuery As SqlCommand) As DataSet
Dim connectionString As String
connectionString = _
ConfigurationManager.ConnectionStrings _
("NorthwindConnectionString").ConnectionString
Dim dbConnection As New SqlConnection
dbConnection.ConnectionString = connectionString
Dim dbAdapter As New SqlDataAdapter
dbAdapter.SelectCommand = sqlQuery
sqlQuery.Connection = dbConnection
Dim resultsDataSet As DataSet = New DataSet
Try
dbAdapter.Fill(resultsDataSet)
Catch ex As Exception
labelStatus.Text = "Unable to connect to SQL Server."
End Try
Return resultsDataSet
End Function

C#
private DataSet RunQuery(SqlCommand sqlQuery)
{
string connectionString =
ConfigurationManager.ConnectionStrings
["NorthwindConnectionString"].ConnectionString;
SqlConnection DBConnection =
new SqlConnection(connectionString);
SqlDataAdapter dbAdapter = new SqlDataAdapter();
dbAdapter.SelectCommand = sqlQuery;
sqlQuery.Connection = DBConnection;
DataSet resultsDataSet = new DataSet();
try
{
dbAdapter.Fill(resultsDataSet);
}
catch
{
labelStatus.Text = "Unable to connect to SQL Server.";
}
return resultsDataSet;
}

This code creates a data adapter based on the SqlCommand object passed to it. Then, it creates and populates a dataset
with the adapter.
You can now test the page.
To test the page
1. Press CTRL+F5 to run the page.
The TreeView control is displayed with a list of categories and products.
2. Click a category to confirm that it collapses and expands to show a list of products for each category.
Next Steps
This walkthrough used both hierarchical XML data and a relational database to populate a TreeView control. You can use the
TreeView control to work with site navigation information and XML data as tabular (list) data.
For details on site navigation, see Walkthrough: Adding Site Navigation to a Web Site.
For details on working more with XML data, see Walkthrough: Creating a Web Page to Display XML Data.
See Also
Tasks
Walkthrough: Creating a Web Page to Display XML Data
How to: Secure Connection Strings When Using Data Source Controls
ASP.NET

Populating Tree Nodes in the TreeView Web Server Control


The TreeView Web server control can display several different types of data: static data that is specified declaratively in the
control; data that is bound to the control; or data that is added to the TreeView control dynamically, in response to user
actions.
Displaying Static Data
The simplest data scheme is declarative static data. To display static data by using declarative syntax, create a collection of
nodes that are children of the TreeView control.
The following example shows the markup for a TreeView control that contains three nodes, two of which have child nodes.

<asp:TreeView ID="TreeView1" Runat="server">


<Nodes>
<asp:TreeNode Value="Parent1" Expanded="True" Text="1">
<asp:TreeNode Value="Child1A" Text="A" />
<asp:TreeNode Value="Child1B" Text="B" />
</asp:TreeNode>
<asp:TreeNode Value="Parent2" Text="2">
</asp:TreeNode>
<asp:TreeNode Value="Parent3" Expanded="True" Text="3">
<asp:TreeNode Value="Child3A" Text="A">
</asp:TreeNode>
</asp:TreeNode>
</Nodes>
</asp:TreeView>

Binding to a Data Source


To display data that is declaratively bound to the control, first add a hierarchical data source control, such as the
XmlDataSource control, to the page and assign it an ID. Then, set the DataSourceID property of the TreeView control to the ID
of the data source control. The TreeView control can automatically bind to the data source and display its values.
Note
The TreeView control can bind to any data source control that implements the IHierarchicalDataSource interface, such as a
SiteMapDataSource object or an XmlDataSource object.

By default, when binding to a data source where each data item contains multiple properties — such as an XML element with
several attributes — a node displays the value returned by the ToString method of the data item. In the case of an XML
element, the node displays the element name. This schema shows the underlying structure of the tree, but is not very useful
otherwise. You can bind a node to a specific data item property by specifying tree-node bindings using the DataBindings
collection. The DataBindings collection contains TreeNodeBinding objects that define the relationship between a data item
and the node it is binding to. You can specify the criteria for binding and the data item property to display in the node. For
more information about tree-node bindings, see TreeNodeBinding.
Note
The TreeView control also provides a DataSource property and a DataBind method for manual data binding.

Displaying Data Dynamically


It might not be practical to define your data structure statically, or the data might depend on information that you gather at run
time. You can populate TreeNode objects in a TreeViewcontrol's Nodes collection programmatically from server-side code or
you can utilize the PopulateOnDemand feature of the TreeView control to populate nodes dynamically when the parent node
is expanded on the client. For more information, see Binding Data to the TreeView Web Server Control.
See Also
Reference
TreeView Web Server Control Overview
Concepts
TreeView Web Server Control Events
Customizing the Look and Feel of the TreeView Web Server Control
Binding Data to the TreeView Web Server Control
Selection, Navigation, and Check Boxes in the TreeView Web Server Control
Visual Web Developer

How to: Add or Delete TreeView Node Elements (Visual Studio)


You can create nodes for the TreeView control statically — that is, at design time. This is useful if you are creating a tree of fixed
items.
Note
You cannot define nodes statically and bind data to the TreeView control.

To add nodes to the TreeView control


1. In Design view, right-click the TreeView control and then click Edit Nodes.
2. In the TreeView Node Editor, under Nodes, click the Add a root node button.
3. In the Properties grid, configure the node by setting property values. Typical properties to set include the following:
Expanded Specifies whether the node is open by default.
Text Specifies the text that is displayed by the node.
SelectAction One of several values that specifies what happens when users click the node.
4. To create a child node, select the parent node in the TreeView Node Editor and then click the Add a child node button.
5. When you have finished creating nodes, click OK.
To delete a node from the TreeView control
1. In Design view, right-click the TreeView control and then click Edit Nodes.
The TreeView Node Editor appears.
2. In the TreeView Node Editor, under Nodes, select the node that you want to delete and then click the Remove a node
button.
Note When you delete a node, all of its child nodes are deleted as well.
1. When you have finished deleting nodes, click OK.

See Also
Reference
TreeView Web Server Control Overview
ASP.NET

Binding Data to the TreeView Web Server Control


The ASP.NET TreeView control makes it easy to bind to a data source that supports the IHierarchicalDataSource interface, such
as the XmlDataSource class and the SiteMapDataSource class. Additionally, you have complete control over which fields of the
data source are used for the Text, Value, and other TreeNode properties.
For more information, see TreeView Web Server Control Overview.
Binding to an XML File
The TreeView control supports declarative binding to an XML file by using XmlDataSource controls. You can bind a
TreeView control to an XML file by creating an XmlDataSource control that represents the XML file and then assigning that
XmlDataSource to your TreeView control. Furthermore, you can control how and what data is bound to the TreeView
control by using several techniques, which include the following:
If the data source is an XML file, alter the data by performing an XML transformation before the XML file is bound to the
control. For more information, see XSLT Transformations.
Create a custom DataBindings property that controls which fields in the XML file populate the TreeNode properties, such
as the Text property, the Value property, the NavigateUrl property, and others. For more information, see
Customizing the Look and Feel of the TreeView Web Server Control.
For more information about binding to an XML file, see Binding to Hierarchical Data. For a step-by-step example, see
Walkthrough: Displaying Hierarchical Data in a TreeView Control.
Binding to a Site Map
The TreeView control supports declarative binding to a site-map file by using SiteMapDataSource controls. When binding to
an instance of the SiteMapDataSource control, the Title and Url properties of each SiteMapNode are automatically associated
with the Text and NavigateUrl properties of each TreeNode object in the TreeView control, so there is no need to create
custom data bindings. For more information and an example of binding a TreeView control to a site map, see TreeView.
Populating Nodes on Demand
The populate-on-demand feature allows you to specify that a node not be populated with data when the TreeView control
initially renders. Instead, the TreeNode control will request child-node data when a user clicks the node. When the
PopulateOnDemand property of a TreeNode control is set to true, the TreeNodePopulate event occurs when a user clicks the
node to expand it. You can create an event handler to retrieve data dynamically when the TreeNodePopulate event is raised,
which allows tree data to be retrieved as needed. For more information, see Server Event Handling in ASP.NET Web Pages.
Non-Declarative Data Binding
In addition to using a class that derives from DataSourceControl to declaratively bind data to the TreeView control, the
TreeView control provides a DataSource property and a DataBind method for data binding.
See Also
Reference
TreeView Web Server Control Overview
Concepts
Selection, Navigation, and Check Boxes in the TreeView Web Server Control
ASP.NET

Selection, Navigation, and Check Boxes in the TreeView Web


Server Control
The ASP.NET TreeView control makes it easy for you to respond when a user clicks a node, or to change the behavior of a node
to make it act like a hyperlink. Additionally, you can use the TreeView control to display check boxes next to individual nodes
so that users can select multiple nodes at once.
Selection and Navigation
Each node has a Text property and a Value property. The value of the Text property is displayed in the TreeView control, while
the Value property is used to store any additional data about the node, such as data passed to the postback event that is
associated with the node.
When a node of the TreeView control is clicked, it can either raise a selection event (via postback) or go to another page.
When the NavigateUrl property is not set, clicking a node will raise a SelectedNodeChanged event that can be handled to
provide custom functionality. You can also check the Selected property of a node to determine whether it is selected. Setting
this property to true or calling the Select method on the node will cause the node to be selected programmatically.
Each node also has a SelectAction property that can be used to specify actions that will occur when the node is clicked, such as
expanding or collapsing the node. Instead of raising a SelectedNodeChanged event to go to another page when a node is
clicked, set the NavigateUrl property of the node to a value other than an empty string ("").
For more information about handling selection events, see SelectedNode. For more information about navigation mode, see
NavigateUrl. For more information about setting the NavigateUrl property when binding data, see NavigateUrlField.
Check Boxes
In cases where you want users to be able to select multiple nodes, you can use the TreeView control to display a check box
next to a node image. When the ShowCheckBoxes property is set to a TreeNodeType other than TreeNodeType.None,
check boxes are displayed next to the specified nodes. When check boxes are displayed, you can use the
TreeNodeCheckChanged event to run your custom routine whenever the state of a check box changes between posts to the
server. The next time the page is posted to the server, the CheckedNodes property is populated with the selected nodes.
The TreeView control does not expose an AutoPostBack property. Thus, to submit check box selections, you must place a
control, such as a Button Web server control, on the page to post information back to the server.
For more information about using check boxes with the ASP.NET TreeView control, see CheckBoxes.
See Also
Reference
TreeView Web Server Control Overview
Concepts
Populating Tree Nodes in the TreeView Web Server Control
ASP.NET

TreeView Web Server Control Events


The TreeView Web server control provides several events that you can program. This allows you to run your custom routines
whenever an event occurs.
Events
TreeView control events are raised only when a user interacts with the control by doing such things as selecting, expanding, or
collapsing a node. They are not raised if the select, expand, or collapse methods are called programmatically. For example, if
you call the Expand method, no event will be raised.
The following table describes the events that are supported by the TreeView control.
Event Description
TreeNodeCheckChanged Occurs when a check box of the TreeView control changes state between posts to the server. Occurs
once for every TreeNode object that changes.

SelectedNodeChanged Occurs when a node is selected in the TreeView control.

TreeNodeExpanded Occurs when a node is expanded in the TreeView control.

TreeNodeCollapsed Occurs when a node is collapsed in the TreeView control.

TreeNodePopulate Occurs when a node, with its PopulateOnDemand property set to true, is expanded in the TreeView
control.

TreeNodeDataBound Occurs when a data item is bound to a node in the TreeView control.

Example
The SelectedNodeChanged Event
The following code example demonstrates handling the SelectedNodeChanged event and accessing the SelectedNode
property that raised the event. It sets the text of MyLabel to be the ToolTip property text of the SelectedNode.
VB
Protected Sub TreeView1_SelectedNodeChanged(ByVal sender As Object, ByVal e As System.Event
Args) Handles TreeView1.SelectedNodeChanged
MyLabel.Text = TreeView1.SelectedNode.ToolTip
End Sub

C#
protected void TreeView1_SelectedNodeChanged(object sender, EventArgs e)
{
MyLabel.Text = TreeView1.SelectedNode.ToolTip;
}

The TreeNodeExpanded and TreeNodeCollapsed Events


The following code example demonstrates handling the TreeNodeCollapsed event and the TreeNodeExpanded event and
then accessing the TreeNode object that was collapsed or expanded.
VB
Protected Sub TreeView1_TreeNodeCollapsed(ByVal sender As Object, ByVal e As System.Web.UI.
WebControls.TreeNodeEventArgs) Handles TreeView1.TreeNodeCollapsed
MyLabel.Text = "You collapsed the " & e.Node.Value & " node."
End Sub
Protected Sub TreeView1_TreeNodeExpanded(ByVal sender As Object, ByVal e As System.Web.UI.W
ebControls.TreeNodeEventArgs) Handles TreeView1.TreeNodeExpanded
MyLabel.Text = "You expanded the " & e.Node.Value & " node."
End Sub

C#
protected void TreeView1_TreeNodeCollapsed(object sender, TreeNodeEventArgs e)
{
MyLabel.Text = "You collapsed the " + e.Node.Value + " node.";
}
protected void TreeView1_TreeNodeExpanded(object sender, TreeNodeEventArgs e)
{
MyLabel.Text = "You expanded the " + e.Node.Value + " node.";
}

The TreeNodePopulate Event


The following code example demonstrates handling the TreeNodePopulate event and then programmatically adding a new
TreeNode object to the ChildNodes collection of the node that raised the event.
VB
Protected Sub TreeView1_TreeNodePopulate(ByVal sender As Object, ByVal e As System.Web.UI.W
ebControls.TreeNodeEventArgs) Handles TreeView1.TreeNodePopulate
e.Node.ChildNodes.Add(New TreeNode("New Node Populated on Demand"))
End Sub

C#
protected void TreeView1_TreeNodePopulate(object sender, TreeNodeEventArgs e)
{
e.Node.ChildNodes.Add(new TreeNode("New Node Populated on Demand"));
}

See Also
Reference
TreeView Web Server Control Overview
Concepts
Populating Tree Nodes in the TreeView Web Server Control
Customizing the Look and Feel of the TreeView Web Server Control
Selection, Navigation, and Check Boxes in the TreeView Web Server Control
Binding Data to the TreeView Web Server Control
ASP.NET

Customizing the Look and Feel of the TreeView Web Server


Control
The rendering of the TreeView control is fully customizable, which allows for a wide range of display styles.
To customize the look and feel of the TreeView control, you can do the following:
Specify properties of the TreeView control that affect the control display and rendering.
Specify an ImageSet property that selects a set of built-in images to render with the control at run time.
Specify individual image and style properties that control display and rendering characteristics of specific groups of
TreeNode objects within the TreeView control.
Use the AutoFormat feature of Visual Studio to customize a set of image and style properties all at once.
Assign a predefined theme or a skin that defines the display and rendering characteristics at run time for TreeView
controls in an application.
Top-Level Layout Properties
In addition to standard server control properties, such as the BackColor property, the TreeView control exposes a set of
properties that that give precise control over the appearance of the TreeView control.
The NodeIndent Property
The NodeIndent property specifies the indentation level for all nodes. Nodes are indented from the side on which the
TreeView control is rendered. This is the left side for locales that render from left to right, and it is the right side for locales
that render from right to left.
The NodeWrap Property
The NodeWrap property specifies whether the text displayed in each node wraps to the beginning of the next line or continues
on the same line when it runs out of space.
The ShowLines Property
The ShowLines property specifies whether lines connecting child nodes to parent nodes are displayed. When this property is
set to true, the TreeView control searches the Web-accessible folder specified by the LineImagesFolder property for the line
images.
TreeNodeStyle Properties
In addition to its own properties, the TreeView control supports properties of the TreeNodeStyle control for each node type.
These style properties override the NodeStyle property, which applies to all node types.
The TreeView control also has a NodeIndent property that specifies the indentation level for all nodes. Nodes are indented
from the side on which the TreeView control is rendered. This is the left side for locales that render from left to right, and it is
the right side for locales that render from right to left.
A node can also have a different style applied when it is selected or when the mouse hovers over the node. When the Selected
property of a node is set to true, the SelectedNodeStyle property is applied, which overrides any unselected style properties
for the selected node. When the mouse hovers over a node, the HoverNodeStyle property is applied. The following image and
table describe the TreeNodeStyle properties.
TreeNodeStyle Properties

Node property Description


NodeSpacing Specifies the amount of vertical spacing between the entire current node and adjacent nodes above and b
elow.

VerticalPadding Specifies the amount of space rendered on the top and bottom of the TreeNode text.

HorizontalPadding Specifies the amount space rendered on the left and right of the TreeNode text.

ChildNodesPadding Specifies the amount of space above and below the child nodes of the TreeNode.

ImageUrl Specifies the path to the image that displays next to the TreeNode.
The Level Styles Collection
The LevelStyles collection is an alternative to setting the individual style properties, such as the NodeStyle property. The
LevelStyles collection controls the style of nodes at specific levels of the tree. The first style in the collection corresponds to
the style of nodes in the first level of the tree. The second style in the collection corresponds to the style of nodes in the second
level of the tree, and so on. This property is most often used to generate table of contents-style navigation menus where nodes
at a certain level should have the same appearance, regardless of whether they have child nodes.
Note
If a style is defined for a certain level using the LevelStyles collection, then it overrides any root-, parent-, or leaf-node style
settings for the nodes at that level.

Style Precedence
Style properties are applied in the following order of precedence:
1. NodeStyle
2. RootNodeStyle, ParentNodeStyle, or LeafNodeStyle, depending on the node type. If the LevelStyles collection is defined,
it is applied at this time, overriding the other node style properties.
3. SelectedNodeStyle
4. HoverNodeStyle
AutoFormat
If you are using a visual design tool, such as Visual Web Developer, the TreeView control exposes an AutoFormat feature. The
AutoFormat feature applies a set of display properties to the control at design time. These property settings override any
previously set property values and can be modified in the code designer.
In addition to standard style attributes, AutoFormat also sets the ImageSet property to be one of available sets of images that
are included with the TreeView control. By using AutoFormat, you can quickly change the appearance of the TreeView control
to mimic other well-known custom trees, such as the following:
Outlook Inbox folder
Microsoft Windows file system
MSN Messenger contact list
Outlook Express newsgroups list
MSDN table of contents
Windows Help table of contents
Frequently asked questions (FAQs)
Windows Event List view
In addition to the common tree styles, the AutoFormat feature includes a number of stylized bulleted lists.
While AutoFormat is useful for applying a set of properties to a single control, you can use themes and skins to apply the same
look and feel to multiple TreeView controls within your Web site. For more information, see
ASP.NET Themes and Skins Overview.
Image Properties
Unlike most controls, the TreeView control benefits from the ability to apply a set of graphic resources to the control. Images
are used to represent nodes, expand and collapse buttons, and connecting lines.
You can set images at the TreeView level by setting the ImageSet property or creating custom images and setting the
individual image properties. You can also set images at the TreeNode level to customize the appearance of the TreeView
control even further.
Image Sets
The TreeView control includes built-in sets of image resources that are the same images using in many common trees. The
following table shows some of the common image sets that you might use.
ImageSet name Description
TreeViewImageSet.Contacts MSN Messenger images

TreeViewImageSet.Faq FAQ-style images

TreeViewImageSet.Inbox Outlook Inbox images

TreeViewImageSet.News Outlook Express newsgroup images

TreeViewImageSet.Help Microsoft Windows Help system images

TreeViewImageSet.XPFileExplorer Microsoft Windows XP file explorer images


Custom Images and Lines
In addition to using built-in image resources, you can define your own custom set of image resources for the TreeView
control. To use a custom set of images, you must create two types of images. The first are node images that show an
expandable node, a collapsible node, and a node that does not expand or collapse. These images can be created in a program
such as Microsoft Paint. If you are using lines to connect the nodes, you must create a set of line images and set the
ShowLines property to true. If you are using a visual designer such as Visual Web Developer, you can use the Line Image
Creator tool to create line images. If not, you must create them manually using a program, such as Microsoft Paint.
Once you have created your node images, place them in a directory in your Web site, and then set the following properties on
your TreeView control to reference the images:
CollapseImageUrl
ExpandImageUrl
NoExpandImageUrl
Additionally, the line images must be placed in a folder and then the LineImagesFolder property must be set to point to the
folder of your line images.
For more information about the ImageSet property and a complete listing of available image sets, see ImageSet.
For more information about line images and a list of all the TreeView control images, see LineImagesFolder.
Themes and Skins
Themes and skins provide an easy way to apply a set of properties to multiple controls within a Web site. For example, if you
create a theme called MyTheme and you define a skin within that theme called MyTreeView skin, then you can define that skin
one time and apply it to many TreeView controls.
For more information, see ASP.NET Themes and Skins Overview.
See Also
Reference
TreeView Web Server Control Overview
Visual Web Developer

Login Toolbox Controls


The topics in this section describe how to work with ASP.NET Web server controls that appear on the Login tab of the Visual
Web Developer Toolbox. These include controls that enable you to build a login page, enable users to register on your Web
site, and that display different information to logged-in and anonymous users.
For complete syntax information for Web server controls, see Web Server Control Syntax.
In This Section
Getting Started — Login Controls
Learning More — Login Controls
Walkthrough Topics — Login Controls
How-to Topics — Login Controls
Reference
ChangePassword
Provides an overview of programming the ChangePassword class.
CreateUserWizard
Provides an overview of programming the CreateUserWizard class.
Login
Provides an overview of programming the Login class.
LoginName
Provides an overview of programming the LoginName class.
LoginStatus
Provides an overview of programming the LoginStatus class.
LoginView
Provides an overview of programming the LoginView class.
PasswordRecovery
Provides an overview of programming the PasswordRecovery class.
See Also
Tasks
Walkthrough: Creating a Web Site with Membership and User Login (Visual Studio)
Other Resources
ASP.NET Web Site Security (Visual Studio)
Managing Users by Using Membership
Individual Web and HTML Controls
ASP.NET Web Server Controls (Visual Studio)
ASP.NET Web Pages (Visual Studio)
Visual Web Developer

Getting Started — Login Controls


The topics in this section provide essential information for learning to work with the ASP.NET login controls. Using the login
controls, you can create login pages, enable users to register at your Web site, recover passwords, and display different
information to logged-in and anonymous users.
In This Section
ASP.NET Login Controls Overview
Walkthrough: Creating a Web Site with Membership and User Login (Visual Studio)
How to: Create an ASP.NET Login Page
How to: Add a Login Button to an ASP.NET Web Page
How to: Display the Name of the Current User
How to: Enable User Registration
How to: Enable User Password Recovery Using the ASP.NET PasswordRecovery Control
See Also
Tasks
Walkthrough: Creating a Web Site with Membership and User Login (Visual Studio)
Other Resources
Login Toolbox Controls
Managing Users by Using Membership
Individual Web and HTML Controls
ASP.NET

ASP.NET Login Controls Overview


The ASP.NET login controls work together to provide for your ASP.NET Web applications a robust login solution that requires
no programming. By default, login controls integrate with ASP.NET membership and forms authentication to help automate
user authentication for your Web site. For information about using ASP.NET membership with forms authentication, see
Introduction to Membership.
By default, the ASP.NET login controls work in plain text over HTTP. If you are concerned about security, use HTTPS with SSL
encryption. For more information on SSL, see Configuring SSL on a Web Server or a Web Site in the IIS documentation.
Note
Login controls might not function properly if the Method of the ASP.NET Web page is changed from POST (the default) to GE
T.

This topic describes each ASP.NET login control and provides links to the control's reference documentation.
The Login Control
The Login control displays a user interface for user authentication. The Login control contains text boxes for the user name and
password and a check box that allows users to indicate whether they want the server to store their identity using ASP.NET
membership and automatically be authenticated the next time they visit the site.
The Login control has properties for customized display, for customized messages, and for links to other pages where users
can change their password or recover a forgotten password. The Login control can be used as a standalone control on a main
or home page, or you can use it on a dedicated login page.
If you use the Login control with ASP.NET membership, you do not need to write code to perform authentication. However, if
you want to create your own authentication logic, you can handle the Login control's Authenticate event and add custom
authentication code.
The LoginView Control
The LoginView control allows you to display different information to anonymous and logged-in users. The control displays one
of two templates: the AnonymousTemplate or the LoggedInTemplate. In the templates, you can add markup and controls that
display information appropriate for anonymous users and authenticated users, respectively.
The LoginView control also includes events for ViewChanging and ViewChanged, which allow you to write handlers for when
the user logs in and changes status.
The LoginStatus Control
The LoginStatus control displays a login link for users who are not authenticated and a logout link for users who are
authenticated. The login link takes the user to a login page. The logout link resets the current user's identity to be an
anonymous user.
You can customize the appearance of the LoginStatus control by setting the LoginText and LoginImageUrl properties.
The LoginName Control
The LoginName control displays a user's login name if the user has logged in using ASP.NET membership. Alternatively, if your
site uses integrated Windows authentication, the control displays the user's Windows account name.
The PasswordRecovery Control
The PasswordRecovery control allows user passwords to be retrieved based on the e-mail address that was used when the
account was created. The PasswordRecovery control sends an e-mail message containing a password to the user.
You can configure ASP.NET membership to store passwords using non-reversible encryption. In that case, the
PasswordRecovery control generates a new password instead of sending the original password to the user.
You can also configure membership to include a security question that the user must answer to recover a password. If you do,
the PasswordRecovery control asks the question and checks the answer before recovering the password.
The PasswordRecovery control requires that your application can forward e-mail message to a Simple Mail Transfer Protocol
(SMTP) server. You can customize the text and format of the e-mail message sent to the user by setting the MailDefinition
property.
Note
Password information sent in an e-mail message is sent as clear text.

The following example shows a PasswordRecovery control declared in an ASP.NET page with MailDefinition property
settings to customize the e-mail message.

<asp:PasswordRecovery ID="PasswordRecovery1" Runat="server"


SubmitButtonText="Get Password" SubmitButtonType="Link">
<MailDefinition From="administrator@Contoso.com"
Subject="Your new password"
BodyFileName="PasswordMail.txt" />
</asp:PasswordRecovery>

The CreateUserWizard Control


The CreateUserWizard control collects information from potential users. By default, the CreateUserWizard control adds the
new user to the ASP.NET membership system.
The CreateUserWizard control gathers the following user information:
User name
Password
Confirmation of password
E-mail address
Security question
Security answer
This information is used to authenticate users and recover user passwords, if necessary.
Note
The CreateUserWizard control is inherited from the Wizard control.

The following example shows a typical ASP.NET declaration for the CreateUserWizard control:

<asp:CreateUserWizard ID="CreateUserWizard1" Runat="server"


ContinueDestinationPageUrl="~/Default.aspx">
<WizardSteps>
<asp:CreateUserWizardStep Runat="server"
Title="Sign Up for Your New Account">
</asp:CreateUserWizardStep>
<asp:CompleteWizardStep Runat="server"
Title="Complete">
</asp:CompleteWizardStep>
</WizardSteps>
</asp:CreateUserWizard>

The ChangePassword Control


The ChangePassword control allows users to change their password. The user must first supply the original password and then
create and confirm the new password. If the original password is correct, the user password is changed to the new password.
The control also includes support for sending an e-mail message about the new password.
The ChangePassword control includes two templated views that are displayed to the user. The first is the
ChangePasswordTemplate, which displays the user interface used to gather the data required to change the user password.
The second template is the SuccessTemplate, which defines the user interface that is displayed after a user password has been
successfully changed.
The ChangePassword control works with authenticated and non-authenticated users. If a user has not been authenticated, the
control prompts the user for a login name. If the user is authenticated, the control populates the text box with the user's login
name.
See Also
Concepts
Customizing the Appearance of ASP.NET Login Controls
Visual Web Developer

Walkthrough: Creating a Web Site with Membership and User


Login (Visual Studio)
A common requirement for Web sites is to allow only some members or other authenticated users to see certain pages. In that
case, the application must prompt the user for a name and password. The application must also include a way to hide
information from anonymous users (users who are not logged in). This walkthrough shows you how to use ASP.NET controls
and ASP.NET membership services to create an application that performs all these tasks. For more information, see
Introduction to Membership.
Tasks illustrated in this walkthrough include:
Configuring an application to include ASP.NET membership services, and how to define users.
Using login controls to get user credentials and to display information to logged-in users.
Protecting one or more pages in your application so that only logged-in users can view them.
Allowing new users to register at your site.
Allowing members to change and reset their passwords.
Prerequisites
In order to complete this walkthrough, you will need:
Microsoft Visual Web Developer.
Microsoft Internet Information Services (IIS) installed locally on your computer.
Microsoft Data Access Components (MDAC) version 2.7 or later. If you are using Microsoft Windows XP or Windows
Server 2003, you already have MDAC 2.7. However, if you are using Microsoft Windows 2000, you might to need to
upgrade the MDAC already installed on your computer. For more information, see the article "Microsoft Data Access
Components (MDAC) Installation" in the MSDN library.
Access to an e-mail server that can forward e-mail messages. (The server does not have to be able to receive messages.)
IIS includes the Default SMTP virtual server, a mail server that is suitable for this walkthrough. For more information
about configuring this server, see How to: Install and Configure SMTP Virtual Servers in IIS. If you are working on a local
area network, check with your network administrator for information about access to an e-mail server.
Creating the Web Site
If you have already created a Web site in Microsoft Visual Studio (for example, by working with the topic
Walkthrough: Creating a Basic Web Page in Visual Web Developer ), you can use that Web site and skip to "Configuring
Membership" later in this walkthrough. Otherwise, create a new Web site and page by following these steps.
To create a local IIS Web site
1. Open Visual Studio.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, select ASP.NET Web Site.
4. In the Location list box, select HTTP. Click Browse.
The Choose Location dialog box appears.
5. Select Local IIS.
6. Open Local Web Servers.
7. Select Default Web Site.
8. Click the Create New Web Application icon ( ) above the list of Web sites and then name the new Web site
membership.
9. Click Open.
The Choose Location dialog box closes.
10. In the Languages box, click the programming language you prefer to work in.
The programming language you choose will be the default for your Web site, but you can set the programming
languages for each page individually.
11. Click OK in the New Web Site dialog box.
Visual Web Developer creates the Web site and a new page named Default.aspx.
Configuring Membership
Later in this walkthrough you will put pages into a subdirectory that is protected. You must create the subdirectory now so that
you can configure security for it later in the walkthrough.
To add a new folder to the Web site
1. In Solution Explorer, right-click the name of your Web site and click New Folder.
2. Name the folder MemberPages.
Before you work with ASP.NET membership, you must configure your application to enable membership and to set up users.
You can use the Web Site Administration tool, which provides a wizard-like interface for making configuration settings.
For this walkthrough, you will define a single user.
To create a membership user
1. On the Website menu, click ASP.NET Configuration.
2. Select the Security tab, click the link to Use the security Setup Wizard to configure security step by step, and then
click Next.
3. Proceed to Step 2 of the wizard and select the From the Internet option.
The wizard displays a page where you can select the authentication method that your Web site will use. This option
specifies that your application will use Forms authentication, where users will log in to the application using a login page
that you will create later in this walkthrough.
4. Click Next.
The wizard displays a message stating that user information will be stored using Advanced provider settings. By
default, membership information is stored in a Microsoft SQL Server Express database file in the App_Data folder of
your Web site.
5. Click Next.
The wizard displays an option to create roles. You will perform this step separately later in the walkthrough. Therefore, do
not select the Enable roles for this web site check box.
6. Click Next.
The wizard displays a page where you can create new users.
7. Enter information that defines a user of your application. Use the following values as guidelines (you can use any values
that you like, but be sure to note your entries for later in the walkthrough):
User Name Your name (with no spaces), or a sample name.
Password A password. A strong password is required (one that includes uppercase and lowercase letters,
punctuation, and that is at least eight characters long).
E-mail Your personal e-mail address. Later in the walkthrough you will send yourself an e-mail message, so you
need a legitimate e-mail address.
Security Question and Security Answer Type a question and answer that can be used later if you need to
recover your password.
8. Click Create User.
The wizard displays a confirmation page.
Note
Leave the Web Site Administration tool open.

Earlier in the walkthrough you created a folder named MemberPages. In this part of the walkthrough, you will create a rule
that makes sure that only logged-in users can access pages in that folder.
To set up access rules for the MemberPages subdirectory
1. In the wizard, click Next.
The wizard displays a page that allows you to create access rules.
2. In the Add New Access Rule box, expand the node for your Web site.
3. Select MemberPages, the folder you created earlier.
4. Under Rule applies to, select Anonymous users.
5. Under Permission, select Deny.
The rule you are creating denies access to anonymous users — that is, users who have not logged in.
6. Click Add This Rule.
The new rule is displayed in the grid below. When users request a page from the MemberPages subdirectory, the rules
are checked to determine whether the user is allowed access to the page.
7. Click Finish.
You are now done with the wizard. The wizard closes and you are returned to the Security tab of the Web Site
Administration tool.
Configuring the Application for E-Mail
For part of this walkthrough, the application needs to be able to send e-mail messages. To send messages, your application
must have access to a Simple Mail Transport Protocol (SMTP) server, which forwards e-mail messages from your application to
an e-mail recipient.
IIS includes the Default SMTP virtual server as an optional component, which is suitable for this walkthrough. For more
information about configuring this server, see How to: Install and Configure SMTP Virtual Servers in IIS. If you are working on a
local area network, check with your network administrator for information about access to an e-mail server.
After you have set up or determined how to access an SMTP server, you must configure your application to route e-mail
messages to that server. You can do so by making an entry in your Web site's Web.config file, which contains a series of
settings that determine how your application runs.
To configure the application to use a specific SMTP server
1. In the Web Site Administration tool, click the Application tab.
2. Under SMTP Settings, click Configure SMTP e-mail settings.
The tool displays a page where you can configure e-mail.
3. If you are using the SMTP virtual server that is on your computer, enter localhost as the Server Name; otherwise, enter
the appropriate server name.
Include information for the port number and for authentication according to the requirements of your SMTP server. See
your administrator for more information on how to configure these settings.
4. In the From box, type a valid e-mail address.
5. Click Save, and in the confirmation page, click OK.
The Web Site Administration tool creates a Web.config file (if one did not already exist) with the settings you have made.
Note
The Web.config file will not appear in Solution Explorer until you refresh the view.

6. Close the Web Site Administration tool.


Logging the User In
As part of your application, you need to establish the user's identity so that the application can perform actions — such as
showing or hiding information — based on who the user is. To get the user's identity, you have the user log in.
In this walkthrough, you will add a link on the home page that takes users to a login page, and then you will create the login
page.
To create a home page with a login button
1. Open or switch to the Default.aspx page of your site. (If you do not have a Default.aspx page, you can add one or use a
different page.)
2. Switch to Design view.
3. Type static text such as Welcome to our site and, in the Formatting toolbar, use the Block Format drop-down list to
format the text as Heading 1.
4. From the Login group of the Toolbox, drag a LoginStatus control onto the page.
By default, the LoginStatus control is rendered as a link. When users click it, the application displays a login page. You can
now create the login page.
To create a login page
1. In Solution Explorer, right-click your Web application and select Add New Item. Add a Web Form named Login.aspx
to your site.
Note
For this walkthrough, the page must be named Login.aspx. By default, forms authentication is configured to work with
a page with this name. Although you will not do so in this walkthrough, you can change the default login page — the p
age to which users are redirected — in the Web.config file.

2. In the Login.aspx page, switch to Design view.


3. From the Login group of the Toolbox, drag a Login control onto the page.
The Login control is a single control that will prompt the user for credentials and validate them.
Displaying Login Errors
The Login control includes validation to help users enter correct information. For example, if a user skips the password, a
validator control displays an asterisk (*) next to the Password box. You can provide more complete information for login
errors by adding a ValidationSummary control to the page.
To display detailed login errors
1. From the Validation group of the Toolbox, drag a ValidationSummary control onto the page.
2. In the Properties window for the ValidationSummary control, set the ValidationGroup property to Login1, which is
the default ID of the Login control you added previously.
Displaying Information for Logged-In Users
You will now modify the home page to customize the display depending on whether the user is logged in. Anonymous users
will see a generic message inviting them to log in. Logged-in users will see a message that welcomes them by their logged-in
name.
To customize the display for logged-in users
1. Switch to or open the Default.aspx page.
2. From the Login group of the Toolbox, drag a LoginView control onto the page.
The LoginView control is displayed with its AnonymousTemplate template open. This template allows you to define
the content that users will see before they have logged in.
3. Click the edit area of the LoginView control to activate editing.
4. In the edit area of the LoginView control's AnonymousTemplate template, type You are not logged in. Click the
Login link to sign in.
5. On the LoginView Tasks panel, in the Views list, click LoggedInTemplate. If you do not see the LoginView Tasks
panel, right-click the heading of the LoginView control and select Show Smart Tag.
You are now defining the content that will be displayed to users who have already logged in.
6. Click the edit area of the LoginView control to activate editing, and then type You are logged in. Welcome,.
7. From the Login group of the Toolbox, drag a LoginName control into the template after the text.
Testing Login
You can now test the login capability of your application.
To test login
1. In Solution Explorer, right-click Default.aspx and click Set As Start Page.
This configures the Web site so that when you run the site, the Default.aspx page appears first.
2. Press CTRL+F5 to run the Web site.
The home page (Default.aspx) appears in the browser, showing the Login link and the generic message.
3. Click the Login link.
The login page you created is displayed.
4. Type the login name of the user you created earlier in the walkthrough, and then click Log In. (Do not yet enter a
password.)
An asterisk (*) is displayed next to the Password box, and an error message is displayed in the ValidationSummary
control.
5. Type both a user name and password and then click Log In.
If you entered correct credentials, you are returned to the home page. The page now displays a Logout link, your user
name, and the welcome message that you defined for the logged-in user.
6. Close the browser.
Limiting Access for Members-Only Pages
A typical task in many Web sites is to configure pages so that only logged-in users can view the pages. Earlier in the
walkthrough, you created the MemberPages subdirectory and created a rule that limits access to pages in the subdirectory. In
this section of the walkthrough, you will add a page to the protected subdirectory and test the access rule.
To create the members-only page
1. In Solution Explorer, right-click the MemberPages folder, click Add New Item, and add a new Web Form named
Members.aspx.
Note
Be sure to create the page in the MemberPages folder.

2. In Design view, add text to the page, such as Welcome, members! The exact text does not matter, as long as you will be
able to recognize this page when you see it in the browser.
You can now add a link to the members-only page from the home page. In a real application, you would probably put the
members-only page link in the logged-in template of the LoginView control. That way, visitors to your site would not see the
link until they were logged in. For this walkthrough, however, you will make the link available to all users so that you can see
the effect of trying to view a members-only page without first logging in.
To add a link to the members-only page
1. Switch to or open the Default.aspx page.
2. From the Standard group of the Toolbox, drag a HyperLink control onto the page.
3. In the Properties window for the HyperLink control, set the Text property to Members page and the NavigateUrl
property to ~/MemberPages/Members.aspx to point to the page that you created previously.
Testing the Members-Only Page
You can test the members-only page by accessing it both as an anonymous user and a logged-in user.
To test the members-only page
1. Press CTRL+F5 to run the Web site.
2. When the Default.aspx page appears in the browser, do not log in. Instead, click the Members page link.
You are redirected to the Login.aspx page because access to the members page is denied for anonymous users.
3. In the login page, type the user name and password that you used earlier in the walkthrough to log in.
You are redirected to the Members.aspx page because the user name you are logged in as has been authorized to access
the page.
4. Close the browser window.
Creating New Users
In the first part of the walkthrough, you created a user with the Web Site Administration tool. That strategy is useful if you are
working with a small, defined list of users; for example, if you are creating users for a small team. In many Web sites, however,
users are allowed to register themselves. ASP.NET includes the CreateUserWizard control that performs the same task you
performed earlier using the Web Site Administration tool.
In this part of the walkthrough, you will add a facility that allows users to register on your Web site. To start, you will create a
registration page.
To create a registration page
1. In Solution Explorer, right-click the name of your Web site, click Add New Item, and add a new Web Form named
Register.aspx.
Note
Be sure to create the page in the root of the Web site, not in the MemberPages folder.

2. In the Register.aspx page, switch to Design view and type static text such as Register into the page. In the Formatting
toolbar, use the Block Format drop-down list to format the text as Heading 1.
3. From the Login group of the Toolbox, drag a CreateUserWizard control onto the page.
4. In the Properties window for the CreateUserWizard control, set the ContinueDestinationPageUrl property to
~/Default.aspx.
This configures the control so that when users click Continue after creating a user, the control returns to the home page.
5. From the Standard group of the Toolbox, drag a HyperLink control onto the page. In the Properties window for the
HyperLink control, set the Text property to Home and the NavigateUrl property to ~/Default.aspx.
You can now add a link to the home page that displays the registration page. For this walkthrough, assume that you want to
display the registration link only to users who are not logged in.
To create a registration link on the home page
1. Switch to or open the Default.aspx page.
2. Right-click the LoginView control added previously, and select Show Smart Tag. In the LoginView Tasks panel, select
AnonymousTemplate from the Views list box to activate editing in the anonymous template.
3. From the Standard group of the Toolbox, drag a HyperLink control into the anonymous template. In the Properties
window for the HyperLink control, set the Text property to Register and the NavigateUrl property to Register.aspx.
The Register link will be displayed only to users who are not logged in.
You can now test the registration process.
To test registration
1. Press CTRL+F5 to run the Web site and display the Default.aspx page.
Because you are not logged in, the page containing the Register link is displayed.
2. Click the Register link.
The registration page is displayed.
3. In the text boxes, enter a new user name, a strong password, an e-mail address, and a security question and answer. (All
five pieces of information are required.)
4. Click Create User.
A confirmation message is displayed.
5. Click the Continue button.
You are returned to the home page as a logged-in user. Note that the Login link has changed to Logout and that the
information displayed in the Login control is from the LoggedInTemplate property, not from the AnonymousTemplate
property.
6. Click the Logout link.
The page changes to display the information for anonymous users.
7. Click the Login link.
8. Enter the credentials for the user you just created.
You are logged in as the new user.
9. Close the browser window.
Changing Passwords
Users sometimes might want to change their passwords, and it is often impractical to perform this task by hand. You can
therefore use another ASP.NET control to allow users to change passwords on their own. To change a password, users must
know their existing password.
In this walkthrough, you will add a page where logged-in users can change their password.
To create a password-change page
1. In Solution Explorer, right-click the MemberPages folder, click Add New Item, and add a new Web Form named
ChangePassword.aspx.
Note
Be sure to create the page in the MemberPages folder.

You are putting the page in the members-only folder because only logged-in users can change their passwords.
2. In the ChangePassword.aspx page, switch to Design view and type static text such as Change Password. In the
Formatting toolbar, use the Block Format drop-down list to format the text as Heading 1.
3. From the Login group of the Toolbox, drag a ChangePassword control onto the page.
4. In the Properties window for the ChangePassword control, set ContinueDestinationPageUrl property to
~/Default.aspx.
5. This configures the control so that when users click Continue after changing a password, the control returns to the
home page.
You can now add a link to the home page that displays the password-change page. You will make the link available only to
users who are logged in.
To create a password-change link on the home page
1. Switch to or open the Default.aspx page.
2. Right-click the LoginView control and then click Show Smart Tag. In the LoginView Tasks menu, in the Views list,
click LoggedInTemplate.
This switches the LoginView control to edit mode for the content that will appear to users who are logged in.
3. From the Standard group of the Toolbox, drag a HyperLink control into the editing region. In the Properties window
for the HyperLink control, set the Text property to Change password and the NavigateUrl property to
~/MemberPages/ChangePassword.aspx.
The Change password link will be displayed only to users who are logged in, which is the opposite of the Register link
you created earlier.
You can now test the password-change process.
To test password change
1. Press CTRL+F5 to run the Web site.
2. In the Default.aspx, page, click the Login link and log in as one of the users you have created.
When you are finished, you are returned to the home page as a logged-in user.
3. Click the Change password link.
4. In the password-change page, enter the old password and a new password, and then click Change Password.
5. Click Continue.
6. On the home page, click Logout.
7. Click the Login link.
8. Enter the new password.
You are logged in with the new password.
9. Close the browser window.
Recovering a Password
Users will occasionally forget their passwords. You can add a password recovery page to your Web site so that they can once
again log in to your site. Password recovery can take two forms:
You can send users the password they selected (or that you created for them when you set up the site). This option
requires that the site store the password using reversible encryption.
You can send users a new password, which they can change using the Change Password page you created earlier. This
option is useful if the Web site stores passwords using a non-reversible encryption scheme such as hashing.
Note
Returning a password in clear text using e-mail is not recommended for sites that require a high level of security. For high-se
curity sites, it is recommended that you return passwords using encryption, such as Secure Sockets Layer (SSL).
By default, the ASP.NET membership system secures passwords by hashing them, meaning that the passwords cannot be
recovered. Therefore, for this part of the walkthrough, your Web site will send users a new password.
Note
Password recovery requires that your Web site can send e-mail messages. If you are not able to configure your Web site to s
end e-mail (as explained under "Configuring the Application for E-Mail" earlier in this walkthrough), you will not be able to a
dd password recovery to your site.

To add password recovery


1. In Solution Explorer, right-click the name of your Web site, click Add New Item, and add a new Web Form named
RecoverPassword.aspx.
Note
Be sure to create the page in the root of the Web site, not in the MemberPages folder.

2. In the RecoverPassword.aspx page, switch to Design view and type static text such as Reset my password to a new
value. In the Formatting toolbar, use the Block Format drop-down list to format the text as Heading 1.
3. From the Login group of the Toolbox, drag a PasswordRecovery control onto the page.
4. From the Standard group of the Toolbox, drag a HyperLink control onto the page. In the Properties window for the
HyperLink control, set the Text property to Home and the NavigateUrl property to ~/Default.aspx.
5. Switch to the Default.aspx page.
6. Right-click the LoginView control and then click Show Smart Tag. In the LoginView Tasks menu, in the Views list,
click AnonymousTemplate.
This switches the LoginView control to edit mode for the content that will appear to users who are not logged in.
7. From the Standard group of the Toolbox, drag a HyperLink control into the template. In the Properties window for
the HyperLink control, set the Text property to Forgot your password? and the NavigateUrl property to
~/RecoverPassword.aspx.
Now you can test password recovery.
To test password recovery
1. Press CTRL+F5 to run the Web site.
2. By default, you are not logged in, so you see the anonymous template of the LoginView control.
3. Click the Forgot your password? link.
The RecoverPassword.aspx page appears.
4. Type your user name and click Submit.
The security question is displayed and you are prompted to type the security answer.
5. Type the answer and click Submit.
If you entered a correct answer, the Web site resets your password and sends you an e-mail message with the new
password.
Next Steps
This walkthrough has illustrated a simple but complete scenario for creating an application that prompts users for credentials,
displays information to logged-in users, allows users to recover a forgotten password, and limits access to pages. You can
create more sophisticated pages and applications using the techniques and controls illustrated in the walkthrough. For
example, you might want to:
Create additional users and define roles (groups) such as managers, sales, or members and assign users to different
roles. For details, see Walkthrough: Managing Web Site Users with Roles.
Change the membership provider from the default Access provider to a SQL provider. Storing membership information
in an Access database is suitable for small to medium-sized sites, but if your site will experience heavy traffic, you will
want to use Microsoft SQL Server as the membership store. For more information, see
Web Site Administration Tool Provider Tab and Creating the Application Services Database for SQL Server.
Change the appearance of login controls. The Login, PasswordRecovery, and CreateUserWizard controls all support
templates, which allows you to configure the text and buttons they contain as well as change the color, font, and other
appearance characteristics of the controls. For more information, see the topics in the Login ASP.NET Controls section.
Create rules that limit access to pages or folders not only for anonymous users, but for specific users or roles.
Combine membership with profile properties, which allows you to store user-specific settings for each user. For details,
see Walkthrough: Maintaining Web Site User Information with Profile Properties.
Combine login controls with master pages. Master pages allow you to define a page layout that you can use for all the
pages in your application. For details, see
Walkthrough: Creating and Using ASP.NET Master Pages in Visual Web Developer.
Add the ability to recover a forgotten password. For more information, see
How to: Enable User Password Recovery Using the ASP.NET PasswordRecovery Control.
See Also
Concepts
Introduction to Membership
ASP.NET

How to: Create an ASP.NET Login Page


You can create a login page using the ASP.NET Login control. This control takes a user name and password and uses ASP.NET
membership and forms authentication to verify the user's credentials and create an authentication ticket. For information
about configuring ASP.NET membership and forms authentication, see Introduction to Membership.
To create a login page
1. Create an ASP.NET Web application that uses ASP.NET membership. For details and examples, see
Configuring an ASP.NET Application to Use Membership.
2. Create an ASP.NET Web page in your application named Login.aspx.
Note
By default, ASP.NET forms authentication is configured to work with a page named Login.aspx. You can change the de
fault login page name in the Web.config file for your application using the LoginUrl property.

3. Add a Login control to the page.


4. Optionally set the control's DestinationPageUrl property to the name of the page that the user will be redirected to after
logging in. If you do not specify a value for the DestinationPageUrl property, the user will be redirected to the
originally requested URL after being authenticated.
The following example shows the markup for a Login control:

<asp:Login
ID="Login1"
runat="server"
DestinationPageUrl="~/MembersHome.aspx">
</asp:Login>

See Also
Reference
ASP.NET Login Controls Overview
ASP.NET

How to: Add a Login Button to an ASP.NET Web Page


To allow users to log in to an ASP.NET application that uses ASP.NET membership (forms authentication) for user
authentication, you can use the LoginStatus control. The LoginStatus control detects a user's authentication status. If a user is
not authenticated, the control displays a button that directs the user to the application's login page. If the user is authenticated,
the LoginStatus control displays a button that users can click to log out of the application.
Note
By default, ASP.NET membership and forms authentication is configured to work with a page named Login.aspx. You can cha
nge the default login page name in the application's configuration file by setting the loginUrl attribute of the <forms> elem
ent.

By default, the LoginStatus control renders a button. You can configure the button text by setting the LoginText property.
Alternatively, you can configure the LoginStatus control to display an image (an ImageButton control).
To add a login button to an ASP.NET Web page
1. Add a LoginStatus control to your page.
2. Customize the text displayed in the button by setting the LoginText and LogoutText properties.
To add a login or logout images
1. Add a LoginStatus control to your page.
2. Set the LoginImageUrl and LogoutImageUrl to the URL of the image to display as login and logout images, respectively.
3. Optionally customize the alt text displayed for the image by setting the LoginText and LogoutText properties.
See Also
Other Resources
Login ASP.NET Controls
ASP.NET

How to: Display the Name of the Current User


You can display the name of the current user using the LoginName control. This control displays the user ID of the current
logged-in user, whether the user's identity is established with ASP.NET login controls (and implicitly, ASP.NET membership) or
with Integrated Windows authentication.
Note
The current user's login name will appear only if the user has been authenticated. If the user has not logged in, the control is
not rendered.

To display the current user name


Place a LoginName control on your page using the following syntax:

<asp:LoginName id="LoginName1" runat="server"


FormatString ="Welcome, {0}" />

See Also
Reference
ASP.NET Login Controls Overview
ASP.NET

How to: Enable User Registration


If your application uses the ASP.NET membership system to authenticate users, you can use the CreateUserWizard control to
allow users to create a new user entry in the membership system (The CreateUserWizard control can also be used by
administrators to create new users).
Note
If your Web application uses Integrated Windows authentication, you cannot create or manage users from the application. Fo
r more information, see Limiting Access to ASP.NET Web Sites.

For information on how to configure your application to use membership, see Introduction to Membership for more details.
To enable user registration
1. Create or edit an ASP.NET Web page that does not require permissions.
2. Place a CreateUserWizard control on the page using the following syntax:

<asp:CreateUserWizard ID="CreateUserWizard1" Runat="server">


</asp:CreateUserWizard>

3. Set the ContinueDestinationPageUrl property to the URL of the page that users will visit after completing registration,
such as your home page or a member page.
Note
When users complete the registration form, by default they are logged in automatically.

See Also
Tasks
How to: Customize the ASP.NET CreateUserWizard Control
Other Resources
Login ASP.NET Controls
ASP.NET

How to: Enable User Password Recovery Using the ASP.NET


PasswordRecovery Control
If your application uses ASP.NET membership for authentication, you can enable password recovery in your application using
the PasswordRecovery control. Your application will send users either their current password or a new password, depending
on how your membership provider is configured. By default, ASP.NET hashes passwords using a non-reversible encryption
scheme, so a new password is sent to the user. If your membership provider is configured to encrypt passwords or store
passwords in clear text (which is not recommended), then the user's current password is sent.
To recover a password, your application must be able to send an e-mail message to the user. Your application must therefore
be configured with the name of an SMTP server to which it can forward e-mail messages. For more information, see the
SmtpClient class and How to: Install and Configure SMTP Virtual Servers in IIS.
To enable password recovery
1. Create or edit an ASP.NET Web page on your site that is accessible to anonymous users (for example,
RecoverPassword.aspx). In an authenticated Web site, you can use the location configuration element to specify that a
page can be accessed anonymously, as shown in the following example:

<configuration>
<location path="RecoverPassword.aspx">
<system.web>
<authorization>
<allow users="?" />
</authorization>
</system.web>
</location>

<system.web>
<authentication mode="Forms" >
<forms loginUrl="UserLogin.aspx" />
</authentication>
<authorization>
<deny users="?" />
</authorization>
</system.web>
</configuration>

2. Place a PasswordRecovery control on the page as shown in the following example:

<asp:PasswordRecovery ID="PasswordRecovery1" Runat="server">


</asp:PasswordRecovery>

3. Optionally configure the following templates to customize the appearance of that PasswordRecovery control:
UserNameTemplate, QuestionTemplate, and SuccessTemplate.
See Also
Other Resources
Login ASP.NET Controls
Visual Web Developer

Learning More — Login Controls


The topics in this section provide in-depth information about the ASP.NET login controls. Using the login controls, you can
create login pages, enable users to register at your Web site, recover passwords, and display different information to logged-in
and anonymous users.
In This Section
How to: Display Different Information to Anonymous and Logged In Users (Visual Studio)
Customizing the Appearance of ASP.NET Login Controls
Securing Login Controls
See Also
Other Resources
Login Toolbox Controls
Managing Users by Using Membership
Individual Web and HTML Controls
Visual Web Developer

How to: Display Different Information to Anonymous and


Logged In Users (Visual Studio)
You can display different information to anonymous and logged-in (authenticated) users by including a LoginView control on
the page. The LoginView control includes two templates: one for displaying information to anonymous users, and the other
for displaying information to logged-in users. (You can also include templates based on role names using the RoleGroups
property.)The control automatically determines whether a user is authenticated and renders the appropriate template.
To display different information to anonymous and logged-in users
1. In Design view on an ASP.NET page, from the Login folder in the Toolbox, drag a LoginView control onto the page.
2. If the LoginView Tasks panel is not showing, right-click the control and click Show Smart Tag to display the
LoginView Tasks panel.
By default, the control displays the AnonymousTemplate.
3. Add static text and controls that should be visible to users who have not logged in, such as a Login control that enables
users to log in, recover a password, or create a new user ID.
4. In the LoginView Tasks menu, select LoggedInTemplate from the list of Views.
5. Add static text and controls that should be visible to authenticated users, such as a LoginName control with the
FormatString property set to a welcome message.
Example
<asp:LoginView ID="LoginView1" Runat="server">
<LoggedInTemplate>
<asp:LoginName ID="LoginName1" Runat="server"
FormatString ="Welcome, {0}"/>
<br />
<asp:HyperLink ID="HyperLink1" Runat="server"
NavigateUrl="~/MemberPages/ChangePassword.aspx">
Change Password
</asp:HyperLink>
</LoggedInTemplate>
<AnonymousTemplate>
<asp:Login id="Login1" runat="server"
CreateUserText="Create a new user..."
CreateUserUrl="~/Register.aspx"
PasswordRecoveryUrl="~/Recovery.aspx"
UserNameLabelText="E-mail address:" />
</AnonymousTemplate>
</asp:LoginView>

The code example shows a LoginView control in Source view after you have defined an AnonymousTemplate and a
LoggedInTemplate.
See Also
Tasks
Walkthrough: Creating a Web Site with Membership and User Login (Visual Studio)
Reference
ASP.NET Login Controls Overview
ASP.NET

Customizing the Appearance of ASP.NET Login Controls


You can customize the contents of several ASP.NET login controls by specifying control templates and adding your own
controls to the user interface (UI) of the control, or by replacing or removing optional controls not required for the UI of the
control.
You can also use the style properties of login controls as well as themes and skins to tailor the appearance of the control. For
more information, refer to the members of the specific control and ASP.NET Themes and Skins Overview.
Customizable Login Controls
You can customize the content of any login control where the existing control UI can be replaced using a template. This
includes the Login, PasswordRecovery, CreateUserWizard, and ChangePassword controls. The following table lists the
templates that are available to customize with each control.
Login
Use the LayoutTemplate template to specify different controls to retrieve a user name and password for logging in.
PasswordRecovery
Use the UserNameTemplate template to specify different controls to retrieve the user name for which to recover the
password.
Use the QuestionTemplate template to specify different controls to retrieve the password question if the
RequiresQuestionAndAnswer property is true.
Use the SuccessTemplate template to specify different controls that appear when a user's password has been successfully
recovered.
CreateUserWizard
Use the ContentTemplate template of the CreateUserStep step to specify different controls to retrieve the user name,
password, and other information required to create a new user account.
Use the ContentTemplate template of the CompleteStep step to specify different controls that appear when the create user
operation is complete.
ChangePassword
Use the ChangePasswordTemplate template to specify different controls to retrieve the user name, current password, and
new password for the user that is changing his or her password.
Use the SuccessTemplate template to specify different controls that appear when a user's password has been successfully
changed.
Specifying Controls in Login Control Templates
You can include additional controls and command buttons in login control templates as well as replace the default controls and
command buttons with your own.
Replacing Command Buttons in a Login Control Template
You can use any control as a command button in a login control template. However, for the login control to recognize the
command, the command control must bubble up an event that includes event arguments that inherit from the
CommandEventArgs class. The command button must specify a value for the CommandName property of the
CommandEventArgs class that identifies which command is to be executed by the login control. The following table lists the
valid values for the CommandName property and their related login control templates.
System.Web.UI.WebControls.Login.LayoutTemplate
Login - Validates the user credentials and logs the user in.
System.Web.UI.WebControls.PasswordRecovery.UserNameTemplate
Submit - Retrieves the user name to recover the password for and continues the login process.
System.Web.UI.WebControls.PasswordRecovery.QuestionTemplate
Submit - Retrieves the password answer for the user and recovers the user's password.
System.Web.UI.WebControls.CreateUserWizard.CreateUserStep
CreateUser - Retrieves the user-supplied values and creates the new user account.
Cancel - Terminates the create user operation.
System.Web.UI.WebControls.CreateUserWizard.CompleteStep
Continue - Navigates the user to the ContinueDestinationPageUrl page.
System.Web.UI.WebControls.ChangePassword.ChangePasswordTemplate
ChangePassword - Retrieves the user-supplied values and changes the password.
Cancel - Terminates the change password operation.
System.Web.UI.WebControls.ChangePassword.SuccessTemplate
Continue - Navigates the user to the ContinueDestinationPageUrl page.
Replacing Controls in a Login Control Template
You can replace the input and display controls used by several ASP.NET login controls in their respective templates. Each
template has controls that must be included in the template as well as optional controls. Required and optional controls are
identified using the ID property of the control. If a template does not include a control where the ID property is set to a
required control identifier, or if that control does not implement the appropriate interface, the ASP.NET login control will throw
an exception.
The following table lists the templates and the required controls by their ID properties.
System.Web.UI.WebControls.Login.LayoutTemplate
UserName - The account name of the user to be logged in. This control is required and must implement the
IEditableTextControl interface.
Password - The password of the user to be logged in. This control is required and must implement the
IEditableTextControl interface.
RememberMe - true to store the authentication token in a persistent cookie; false to store the authentication token in a
session cookie. This control is optional and must implement the ICheckBoxControl interface.
FailureText - Displays a login failure message. This control is optional and must implement the ITextControl interface.
System.Web.UI.WebControls.PasswordRecovery.UserNameTemplate
UserName - The account name of the user to recover the password for. This control is required and must implement the
IEditableTextControl interface.
FailureText - Displays a password recovery failure message. This control is optional and must implement the ITextControl
interface.
System.Web.UI.WebControls.PasswordRecovery.QuestionTemplate
UserName - Displays the account name of the user that the password is being recovered for. This control is optional and
must implement the ITextControl interface.
Question - The password question for the user that the password is being recovered for. This control is optional and must
implement the ITextControl interface.
Answer - The password answer for the user that the password is being recovered for. This control is required and must
implement the IEditableTextControl interface.
FailureText - Displays a password recovery failure message. This control is optional and must implement the ITextControl
interface.
System.Web.UI.WebControls.CreateUserWizard.CreateUserStep
UserName - The account name of the user account to be created. This control is required and must implement the
IEditableTextControl interface.
Password - The password for the user account to be created. This control is required and must implement the
IEditableTextControl interface.
ConfirmPassword - A confirmation value that must match the password. This control is optional and must implement the
IEditableTextControl interface.
Question - The password question for the user to be created. This control is required if the RequiresQuestionAndAnswer
property is true and must implement the IEditableTextControl interface.
Answer - The password answer for the user to be created. This control is required if the RequiresQuestionAndAnswer
property is true and must implement the IEditableTextControl interface.
Email - The e-mail address for the user account to be created. This control is required if the RequiresUniqueEmail property is
true and must implement the IEditableTextControl interface.
ErrorMessage - Displays a create user account failure message. This control is optional and must implement the
ITextControl interface.
System.Web.UI.WebControls.ChangePassword.ChangePasswordTemplate
UserName - The account name of the user account to be created. This control is required if the DisplayUserName property
is true and must implement the IEditableTextControl interface.
CurrentPassword - The current password for the user account. This control is required and must implement the
IEditableTextControl interface.
NewPassword - The new password for the user account. This control is required and must implement the
IEditableTextControl interface.
ConfirmPassword - A confirmation value that must match the new password. This control is optional and must implement
the IEditableTextControl interface.
FailureText - Displays a create user account failure message. This control is optional and must implement the ITextControl
interface.
Referencing a Control in a Login Control Template
To reference a control in a login control template, you can call the FindControl method of the container for the control
template. The following table lists the templates and their associated container properties.
System.Web.UI.WebControls.Login.LayoutTemplate
LayoutTemplate
System.Web.UI.WebControls.PasswordRecovery.UserNameTemplate
UserNameTemplateContainer
System.Web.UI.WebControls.PasswordRecovery.QuestionTemplate
QuestionTemplateContainer
System.Web.UI.WebControls.PasswordRecovery.SuccessTemplate
SuccessTemplateContainer
System.Web.UI.WebControls.CreateUserWizard.CreateUserStep
ContentTemplateContainer
System.Web.UI.WebControls.ChangePassword.ChangePasswordTemplate
ChangePasswordTemplateContainer
System.Web.UI.WebControls.ChangePassword.SuccessTemplate
SuccessTemplateContainer
For example, if you were to include a DropDownList control with an ID of TimeZoneList in the ContentTemplate template of
the CreateUserStep step of a CreateUserWizard control, you can reference the DropDownList control by calling the
FindControl method of the ContentTemplateContainer container of the CreateUserStep property, as shown in the
following example.
VB
Protected Sub CreateUserWizard1_CreatedUser(sender As Object, e As EventArgs)
Dim timeZoneList As DropDownList = _
CType(CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("TimeZoneLi
st"), DropDownList)
End Sub

C#
protected void CreateUserWizard1_CreatedUser(object sender, EventArgs e)
{
DropDownList timeZoneList =
(DropDownList)CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("Ti
meZoneList");
}

See Also
Reference
ASP.NET Login Controls Overview
Concepts
Configuring an ASP.NET Application to Use Membership
ASP.NET

How to: Use Advanced Features of the ASP.NET Login Control


The Login control is a composite control that provides all the common user interface (UI) elements of a login form. The control
is modularized, and each part can be individually customized. These parts include the Username and Password text boxes, the
Submit button, the button to create a new user, the Remember Me check box, and help information for the user. You can define
your own user interface for the Login control by defining new elements and by reusing default components. You can also
customize the user interface text and the appearance (fonts and colors) of the Login control. Alternatively, you can change the
overall appearance of the Login control by applying an ASP.NET theme or skin.
Additionally, you can make use of more advanced capabilities of the Login control, such as whether the login information is
stored in a persistent cookie in the browser or whether the login control is visible (on pages other than the default login page)
when a user is logged in. Finally, you can convert the login control to a template to have complete control over the control's
appearance.
To control whether the login control is visible when a user is logged in
1. Place a Login control on a page.
Note
By default, the control is configured to work with a login page named Login.aspx. You can change the name of the login
page in the Web.config file by setting the LoginUrl property of the FormsAuthentication class.

2. If you want the Login control to appear only when a user is not logged in (the control will always be displayed on the
login page identified by the LoginUrl property), set the VisibleWhenLoggedIn property to false.
To control whether the authentication token is stored in a persistent cookie
1. If you want the control to display a Remember me next time check box, set the DisplayRememberMe property to true.
If a user selects the Remember me next time check box when he or she logs in, the authentication token will be stored
in a persistent cookie in the browser.
2. If you want the Remember me next time check box to be selected by default, set the RememberMeSet property to
true.
3. If you want the authentication token to be stored in a persistent cookie without giving the user the option to clear the
Remember me next time check box, set the RememberMeSet property to true and set the DisplayRememberMe
property to false. This is not recommended for sites that can be accessed from public computers that serve multiple
users, as a user's persistent authentication token could be used by an unwanted user.

To add help links to the Login control


1. To add a link to the Login control that takes the user to a URL where he or she can create a new user account, set the
CreateUserText property to text such as Click here to register and the CreateUserUrl property to the URL of the Help
page, such as ~/register.aspx.
2. To add a link to the Login control that takes the user to a URL for users to recover their passwords, set the
PasswordRecoveryText property to text such as Forgot your password? and the PasswordRecoveryUrl property to the
URL of the Help page, such as ~/recoverpassword.aspx.
3. To add a link to the Login control that takes the user to a Help URL, set the HelpPageText property to text such as Need
Help? and the HelpPageUrl property to the URL of the help page, such as ~/userhelp.aspx.
To add images to the Login control
To use an image instead of a Log In button, set the LoginButtonImageUrl property to the URL of your login image file,
such as ~/images/login.gif.
You can also include images with the links to the create user URL, password recovery URL, and Help URL using the
PasswordRecoveryIconUrl, CreateUserIconUrl, and HelpPageIconUrl properties, respectively.
Converting the Login Control to a Template
You can convert the Login control into a template that is defined in the markup as a table that contains ASP.NET controls such
as Label and TextBox . You can then use these elements or add your own to create a custom template for your Login control.
Notice that the same control IDs are used for the controls that make up the Login template as in the default template.
To use a template with the Login control
1. Place a Login control on a page in Design view.
2. Right-click the control and select Convert to Template from the shortcut menu.
How the Login control is converted depends on the DOCTYPE declaration. If the DOCTYPE declaration is set to XHTML 1.0
Transitional (<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">), styles are applied to the table that is created when the Login
control is converted to a template. If the DOCTYPE declaration is not set to XHTML 1.0 Transitional or is absent, no style
information is persisted to the outer table that is generated.
For example, if you set the relative font size on the Login control, and then convert the control to a template, the relative font
size is not persisted to the table. The following example shows a Login control with a font size set to X-Large.

<asp:login id="Login2" runat="server" font-size="X-Large" BackColor="#F7F6F3" BorderColor="


#E6E2D8" BorderPadding="4" BorderStyle="Solid" BorderWidth="1px" Font-Names="Verdana" ForeC
olor="#333333">
<TitleTextStyle BackColor="#5D7B9D" Font-Bold="True" Font-Size="0.9em" ForeColor="White
" />
<InstructionTextStyle Font-Italic="True" ForeColor="Black" />
<TextBoxStyle Font-Size="0.8em" />
<LoginButtonStyle BackColor="#FFFBFF" BorderColor="#CCCCCC" BorderStyle="Solid" BorderW
idth="1px"
Font-Names="Verdana" Font-Size="0.8em" ForeColor="#284775" />
</asp:login>

When the Login control in the code above is converted to a template, the table created does not have any of the styles applied.
The following example is a snippet of the code generated from the control above when it is converted to a template.

<asp:login id="Login2" runat="server" font-size="X-Large" BackColor="#F7F6F3" BorderColor="


#E6E2D8" BorderPadding="4" BorderStyle="Solid" BorderWidth="1px" Font-Names="Verdana" ForeC
olor="#333333">
<TitleTextStyle BackColor="#5D7B9D" Font-Bold="True" Font-Size="0.9em" ForeColor="White
" />
<InstructionTextStyle Font-Italic="True" ForeColor="Black" />
<TextBoxStyle Font-Size="0.8em" />
<LoginButtonStyle BackColor="#FFFBFF" BorderColor="#CCCCCC" BorderStyle="Solid" BorderW
idth="1px"
Font-Names="Verdana" Font-Size="0.8em" ForeColor="#284775" />
<LayoutTemplate>
<table border="0" cellpadding="4" cellspacing="0" style="border-collapse: collapse">
...

If you want to have the style attributes also apply to the table created when you convert the Login control to a template,
ensure that the DOCTYPE for the page is set to XHTML 1.0 Transitional before you select Convert to Template from the
control menu in Design view.
See Also
Concepts
Customizing the Appearance of ASP.NET Login Controls
ASP.NET Themes and Skins Overview
Other Resources
Login ASP.NET Controls
ASP.NET

How to: Customize the PasswordRecovery Control


You can customize the PasswordRecovery control in the following ways:
You can edit the displayed templates and change the control's user interface (UI).
You can apply an ASP.NET theme to the control. For more information, see ASP.NET Themes and Skins Overview.
You can use the control's properties (such as QuestionLabelText or InstructionTextStyle).to modify its appearance. For
details, see the properties of the PasswordRecovery control in the class library reference.
This topic describes how to customize the System.Web.UI.WebControls.PasswordRecovery control using templates.
To edit the PasswordRecovery templates
1. Add a PasswordRecovery control to the page as shown in the following code example.

<asp:PasswordRecovery ID="PasswordRecovery1" Runat="server">


</asp:PasswordRecovery>

2. You can apply styles to customize the appearance of the PasswordRecovery control. Use properties to apply any
desired styles to the template, such as the LabelStyle, HyperLinkStyle, and TitleTextStyle properties.
To customize the content of the PasswordRecovery control, continue with the following steps to modify the templates
used by the PasswordRecovery control.
3. Create a UserNameTemplate template to specify the markup and controls that appear when the control is first rendered,
as shown in the following code example.
Security Note
This example has a text box that accepts user input, which is a potential security threat. By default, ASP.NET Web pages
validate that user input does not include script or HTML elements. For more information, see Script Exploits Overview.

VB
<UserNameTemplate>
<table border="0" cellpadding="1">
<tr>
<td>
<table border="0" cellpadding="0">
<tr>
<td align="center" colspan="2">
Forgot Your Password?</td>
</tr>
<tr>
<td align="center" colspan="2">
Enter your User Name to receive your password.</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="UserNameLabel" runat="server" AssociatedControlID="UserNa
me">User Name:</asp:Label></td>
<td>
<asp:TextBox ID="UserName" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="UserNameRequired" runat="server" Control
ToValidate="UserName"
ErrorMessage="User Name is required." ToolTip="User Name is required."
ValidationGroup="PasswordRecovery1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align="center" colspan="2" style="color: red">
<asp:Literal ID="FailureText" runat="server" EnableViewState="False"></a
sp:Literal>
</td>
</tr>
<tr>
<td align="right" colspan="2">
<asp:Button ID="SubmitButton" runat="server" CommandName="Submit" Text="
Submit" ValidationGroup="PasswordRecovery1" />
</td>
</tr>
</table>
</td>
</tr>
</table>
</UserNameTemplate>

C#
<UserNameTemplate>
<table border="0" cellpadding="1">
<tr>
<td>
<table border="0" cellpadding="0">
<tr>
<td align="center" colspan="2">
Forgot Your Password?</td>
</tr>
<tr>
<td align="center" colspan="2">
Enter your User Name to receive your password.</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="UserNameLabel" runat="server" AssociatedControlID="UserNa
me">User Name:</asp:Label></td>
<td>
<asp:TextBox ID="UserName" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="UserNameRequired" runat="server" Control
ToValidate="UserName"
ErrorMessage="User Name is required." ToolTip="User Name is required."
ValidationGroup="PasswordRecovery1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align="center" colspan="2" style="color: red">
<asp:Literal ID="FailureText" runat="server" EnableViewState="False"></a
sp:Literal>
</td>
</tr>
<tr>
<td align="right" colspan="2">
<asp:Button ID="SubmitButton" runat="server" CommandName="Submit" Text="
Submit" ValidationGroup="PasswordRecovery1" />
</td>
</tr>
</table>
</td>
</tr>
</table>
</UserNameTemplate>

4. Create a QuestionTemplate template to specify the markup and controls that appear when the control prompts the user
for the security question, as shown in the following code example.
Security Note
This example has a text box that accepts user input, which is a potential security threat. By default, ASP.NET Web pages
validate that user input does not include script or HTML elements. For more information, see Script Exploits Overview.

VB
<QuestionTemplate>
<table border="0" cellpadding="1">
<tr>
<td>
<table border="0" cellpadding="0">
<tr>
<td align="center" colspan="2">
Identity Confirmation</td>
</tr>
<tr>
<td align="center" colspan="2">
Answer the following question to receive your password.</td>
</tr>
<tr>
<td align="right">
User Name:</td>
<td>
<asp:Literal ID="UserName" runat="server"></asp:Literal>
</td>
</tr>
<tr>
<td align="right">
Question:</td>
<td>
<asp:Literal ID="Question" runat="server"></asp:Literal>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="AnswerLabel" runat="server" AssociatedControlID="Answer">
Answer:</asp:Label></td>
<td>
<asp:TextBox ID="Answer" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="AnswerRequired" runat="server" ControlTo
Validate="Answer"
ErrorMessage="Answer is required." ToolTip="Answer is required." Valid
ationGroup="PasswordRecovery1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align="center" colspan="2" style="color: red">
<asp:Literal ID="FailureText" runat="server" EnableViewState="False"></a
sp:Literal>
</td>
</tr>
<tr>
<td align="right" colspan="2">
<asp:Button ID="SubmitButton" runat="server" CommandName="Submit" Text="
Submit" ValidationGroup="PasswordRecovery1" />
</td>
</tr>
</table>
</td>
</tr>
</table>
</QuestionTemplate>

C#
<QuestionTemplate>
<table border="0" cellpadding="1">
<tr>
<td>
<table border="0" cellpadding="0">
<tr>
<td align="center" colspan="2">
Identity Confirmation</td>
</tr>
<tr>
<td align="center" colspan="2">
Answer the following question to receive your password.</td>
</tr>
<tr>
<td align="right">
User Name:</td>
<td>
<asp:Literal ID="UserName" runat="server"></asp:Literal>
</td>
</tr>
<tr>
<td align="right">
Question:</td>
<td>
<asp:Literal ID="Question" runat="server"></asp:Literal>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="AnswerLabel" runat="server" AssociatedControlID="Answer">
Answer:</asp:Label></td>
<td>
<asp:TextBox ID="Answer" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="AnswerRequired" runat="server" ControlTo
Validate="Answer"
ErrorMessage="Answer is required." ToolTip="Answer is required." Valid
ationGroup="PasswordRecovery1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align="center" colspan="2" style="color: red">
<asp:Literal ID="FailureText" runat="server" EnableViewState="False"></a
sp:Literal>
</td>
</tr>
<tr>
<td align="right" colspan="2">
<asp:Button ID="SubmitButton" runat="server" CommandName="Submit" Text="
Submit" ValidationGroup="PasswordRecovery1" />
</td>
</tr>
</table>
</td>
</tr>
</table>
</QuestionTemplate>

5. Create a SuccessTemplate template to specify the markup and controls that appear when a user has successfully
retrieved a password
The following code example shows the markup for a PasswordRecovery control with a SuccessTemplate template
defined.
Security Note
This example has a text box that accepts user input, which is a potential security threat. By default, ASP.NET Web pages
validate that user input does not include script or HTML elements. For more information, see Script Exploits Overview.

VB
<%@ Page Language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/x


html1/DTD/xhtml1-transitional.dtd">

<script runat="server">

</script>

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<meta http-equiv="Content-Type" content="text/html" />
<title>PasswordRecovery All Templates Sample</title>
</head>
<body>
<form id="form1" runat="server">
<div title="All Templates Sample">
<asp:PasswordRecovery ID="PasswordRecovery1" runat="server">
<QuestionTemplate>
<table border="0" cellpadding="1">
<tr>
<td>
<table border="0" cellpadding="0">
<tr>
<td align="center" colspan="2">
Identity Confirmation</td>
</tr>
<tr>
<td align="center" colspan="2">
Answer the following question to receive your password.</td>
</tr>
<tr>
<td align="right">
User Name:</td>
<td>
<asp:Literal ID="UserName" runat="server"></asp:Literal>
</td>
</tr>
<tr>
<td align="right">
Question:</td>
<td>
<asp:Literal ID="Question" runat="server"></asp:Literal>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="AnswerLabel" runat="server" AssociatedControlID="
Answer">Answer:</asp:Label></td>
<td>
<asp:TextBox ID="Answer" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="AnswerRequired" runat="server" C
ontrolToValidate="Answer"
ErrorMessage="Answer is required." ToolTip="Answer is required
." ValidationGroup="PasswordRecovery1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align="center" colspan="2" style="color: red">
<asp:Literal ID="FailureText" runat="server" EnableViewState="Fa
lse"></asp:Literal>
</td>
</tr>
<tr>
<td align="right" colspan="2">
<asp:Button ID="SubmitButton" runat="server" CommandName="Submit
" Text="Submit" ValidationGroup="PasswordRecovery1" />
</td>
</tr>
</table>
</td>
</tr>
</table>
</QuestionTemplate>
<UserNameTemplate>
<table border="0" cellpadding="1">
<tr>
<td>
<table border="0" cellpadding="0">
<tr>
<td align="center" colspan="2">
Forgot Your Password?</td>
</tr>
<tr>
<td align="center" colspan="2">
Enter your User Name to receive your password.</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="UserNameLabel" runat="server" AssociatedControlID
="UserName">User Name:</asp:Label></td>
<td>
<asp:TextBox ID="UserName" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="UserNameRequired" runat="server"
ControlToValidate="UserName"
ErrorMessage="User Name is required." ToolTip="User Name is re
quired." ValidationGroup="PasswordRecovery1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align="center" colspan="2" style="color: red">
<asp:Literal ID="FailureText" runat="server" EnableViewState="Fa
lse"></asp:Literal>
</td>
</tr>
<tr>
<td align="right" colspan="2">
<asp:Button ID="SubmitButton" runat="server" CommandName="Submit
" Text="Submit" ValidationGroup="PasswordRecovery1" />
</td>
</tr>
</table>
</td>
</tr>
</table>
</UserNameTemplate>
<SuccessTemplate>
<table border="0" cellpadding="1">
<tr>
<td>
<table border="0" cellpadding="0">
<tr>
<td>
Your password has been sent to you.</td>
</tr>
</table>
</td>
</tr>
</table>
</SuccessTemplate>
</asp:PasswordRecovery>

</div>
</form>
</body>
</html>

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

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/x


html1/DTD/xhtml1-transitional.dtd">

<script runat="server">

</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Password Recovery All Templates Sample</title>
</head>
<body>
<form id="form1" runat="server">
<div title="All Templates Sample">
<asp:PasswordRecovery ID="PasswordRecovery1" runat="server">
<QuestionTemplate>
<table border="0" cellpadding="1">
<tr>
<td>
<table border="0" cellpadding="0">
<tr>
<td align="center" colspan="2">
Identity Confirmation</td>
</tr>
<tr>
<td align="center" colspan="2">
Answer the following question to receive your password.</td>
</tr>
<tr>
<td align="right">
User Name:</td>
<td>
<asp:Literal ID="UserName" runat="server"></asp:Literal>
</td>
</tr>
<tr>
<td align="right">
Question:</td>
<td>
<asp:Literal ID="Question" runat="server"></asp:Literal>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="AnswerLabel" runat="server" AssociatedControlID="
Answer">Answer:</asp:Label></td>
<td>
<asp:TextBox ID="Answer" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="AnswerRequired" runat="server" C
ontrolToValidate="Answer"
ErrorMessage="Answer is required." ToolTip="Answer is required
." ValidationGroup="PasswordRecovery1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align="center" colspan="2" style="color: red">
<asp:Literal ID="FailureText" runat="server" EnableViewState="Fa
lse"></asp:Literal>
</td>
</tr>
<tr>
<td align="right" colspan="2">
<asp:Button ID="SubmitButton" runat="server" CommandName="Submit
" Text="Submit" ValidationGroup="PasswordRecovery1" />
</td>
</tr>
</table>
</td>
</tr>
</table>
</QuestionTemplate>
<UserNameTemplate>
<table border="0" cellpadding="1">
<tr>
<td>
<table border="0" cellpadding="0">
<tr>
<td align="center" colspan="2">
Forgot Your Password?</td>
</tr>
<tr>
<td align="center" colspan="2">
Enter your User Name to receive your password.</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="UserNameLabel" runat="server" AssociatedControlID
="UserName">User Name:</asp:Label></td>
<td>
<asp:TextBox ID="UserName" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="UserNameRequired" runat="server"
ControlToValidate="UserName"
ErrorMessage="User Name is required." ToolTip="User Name is re
quired." ValidationGroup="PasswordRecovery1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align="center" colspan="2" style="color: red">
<asp:Literal ID="FailureText" runat="server" EnableViewState="Fa
lse"></asp:Literal>
</td>
</tr>
<tr>
<td align="right" colspan="2">
<asp:Button ID="SubmitButton" runat="server" CommandName="Submit
" Text="Submit" ValidationGroup="PasswordRecovery1" />
</td>
</tr>
</table>
</td>
</tr>
</table>
</UserNameTemplate>
<SuccessTemplate>
<table border="0" cellpadding="1">
<tr>
<td>
<table border="0" cellpadding="0">
<tr>
<td>
Your password has been sent to you.</td>
</tr>
</table>
</td>
</tr>
</table>
</SuccessTemplate>
</asp:PasswordRecovery>

</div>
</form>
</body>
</html>

See Also
Reference
ASP.NET Login Controls Overview
Concepts
Customizing the Appearance of ASP.NET Login Controls
ASP.NET

How to: Customize the ASP.NET CreateUserWizard Control


You can customize the contents of the CreateUserWizard control using the CreateUserWizardStep and CompleteWizardStep
templates. By specifying the contents of the templates, you can specify your own custom user interface (UI) that includes
controls that the CreateUserWizard control uses to gather information about the new user, as well as additional controls that
you specify (for a list of the controls that the CreateUserWizard control uses, see
Customizing the Appearance of ASP.NET Login Controls.)
Additionally, because the CreateUserWizard control inherits from the Wizard class, you can add your own custom steps to the
CreateUserWizard control. For more information on the Wizard control, see Wizard Web Server Control Overview.
Note
You can also customize the appearance of the CreateUserWizard control using themes and style properties. For details, see
ASP.NET Themes and Skins Overview and the properties of the CreateUserWizard control.

To customize the CreateUserWizard steps


1. Place a CreateUserWizard control on your page using the following syntax.

<asp:CreateUserWizard ID="CreateUserWizard1" Runat="server">


<WizardSteps>
<asp:CreateUserWizardStep runat="server">
</asp:CreateUserWizardStep>
<asp:CompleteWizardStep runat="server">
</asp:CompleteWizardStep>
</WizardSteps>
</asp:CreateUserWizard>

2. To customize the user account creation step, create a <ContentTemplate> element within the
<asp:CreateUserWizardStep> element. Inside the template, add markup and controls to define the layout and content
of the UI for gathering the user information you need.
Note
If your membership provider extends the MembershipProvider class with custom members, you must add any controls
to gather custom information required by your membership provider for creating a new user. For details, see CreateU
serWizardStep.

The following code example shows a CreateUserStep property that includes CheckBox controls that enable users to
specify additional options.
VB
<asp:CreateUserWizardStep ID="CreateUserWizardStep1" runat="server">
<ContentTemplate>
<table border="0" style="font-size: 100%; font-family: Verdana">
<tr>
<td align="center" colspan="2" style="font-weight: bold; color: white;
background-color: #5d7b9d">
Sign Up for Your New Account</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="UserNameLabel" runat="server" AssociatedControlID="
UserName">
User Name:</asp:Label></td>
<td>
<asp:TextBox ID="UserName" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="UserNameRequired" runat="server" C
ontrolToValidate="UserName"
ErrorMessage="User Name is required." ToolTip="User Name is re
quired." ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="PasswordLabel" runat="server" AssociatedControlID="
Password">
Password:</asp:Label></td>
<td>
<asp:TextBox ID="Password" runat="server" TextMode="Password"></as
p:TextBox>
<asp:RequiredFieldValidator ID="PasswordRequired" runat="server" C
ontrolToValidate="Password"
ErrorMessage="Password is required." ToolTip="Password is requ
ired." ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="ConfirmPasswordLabel" runat="server" AssociatedCont
rolID="ConfirmPassword">
Confirm Password:</asp:Label></td>
<td>
<asp:TextBox ID="ConfirmPassword" runat="server" TextMode="Passwor
d"></asp:TextBox>
<asp:RequiredFieldValidator ID="ConfirmPasswordRequired" runat="se
rver" ControlToValidate="ConfirmPassword"
ErrorMessage="Confirm Password is required." ToolTip="Confirm
Password is required."
ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValida
tor>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="EmailLabel" runat="server" AssociatedControlID="Ema
il">
E-mail:</asp:Label></td>
<td>
<asp:TextBox ID="Email" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="EmailRequired" runat="server" Cont
rolToValidate="Email"
ErrorMessage="E-mail is required." ToolTip="E-mail is required
." ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="QuestionLabel" runat="server" AssociatedControlID="
Question">
Security Question:</asp:Label></td>
<td>
<asp:TextBox ID="Question" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="QuestionRequired" runat="server" C
ontrolToValidate="Question"
ErrorMessage="Security question is required." ToolTip="Securit
y question is required."
ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValida
tor>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="AnswerLabel" runat="server" AssociatedControlID="An
swer">
Security Answer:</asp:Label></td>
<td>
<asp:TextBox ID="Answer" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="AnswerRequired" runat="server" Con
trolToValidate="Answer"
ErrorMessage="Security answer is required." ToolTip="Security
answer is required."
ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValida
tor>
</td>
</tr>
<tr>
<td align="center" colspan="2">
<asp:CompareValidator ID="PasswordCompare" runat="server" ControlT
oCompare="Password"
ControlToValidate="ConfirmPassword" Display="Dynamic" ErrorMes
sage="The Password and Confirmation Password must match."
ValidationGroup="CreateUserWizard1"></asp:CompareValidator>
</td>
</tr>
<tr>
<td align="center" colspan="2" style="color: red">
<asp:Literal ID="ErrorMessage" runat="server" EnableViewState="Fal
se"></asp:Literal>
</td>
</tr>
</table>
<asp:CheckBox ID="SubscribeCheckBox" runat="server" Checked="True" Text="Send
me a monthly newsletter." />
<br />
<asp:CheckBox ID="ShareInfoCheckBox" runat="server" Checked="True" Text="Share
my information with partner sites." />
</ContentTemplate>
</asp:CreateUserWizardStep>

C#
<asp:CreateUserWizardStep ID="CreateUserWizardStep1" runat="server">
<ContentTemplate>
<table border="0" style="font-size: 100%; font-family: Verdana">
<tr>
<td align="center" colspan="2" style="font-weight: bold; color: white;
background-color: #5d7b9d">
Sign Up for Your New Account</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="UserNameLabel" runat="server" AssociatedControlID="
UserName">
User Name:</asp:Label></td>
<td>
<asp:TextBox ID="UserName" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="UserNameRequired" runat="server" C
ontrolToValidate="UserName"
ErrorMessage="User Name is required." ToolTip="User Name is re
quired." ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="PasswordLabel" runat="server" AssociatedControlID="
Password">
Password:</asp:Label></td>
<td>
<asp:TextBox ID="Password" runat="server" TextMode="Password"></as
p:TextBox>
<asp:RequiredFieldValidator ID="PasswordRequired" runat="server" C
ontrolToValidate="Password"
ErrorMessage="Password is required." ToolTip="Password is requ
ired." ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="ConfirmPasswordLabel" runat="server" AssociatedCont
rolID="ConfirmPassword">
Confirm Password:</asp:Label></td>
<td>
<asp:TextBox ID="ConfirmPassword" runat="server" TextMode="Passwor
d"></asp:TextBox>
<asp:RequiredFieldValidator ID="ConfirmPasswordRequired" runat="se
rver" ControlToValidate="ConfirmPassword"
ErrorMessage="Confirm Password is required." ToolTip="Confirm
Password is required."
ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValida
tor>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="EmailLabel" runat="server" AssociatedControlID="Ema
il">
E-mail:</asp:Label></td>
<td>
<asp:TextBox ID="Email" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="EmailRequired" runat="server" Cont
rolToValidate="Email"
ErrorMessage="E-mail is required." ToolTip="E-mail is required
." ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="QuestionLabel" runat="server" AssociatedControlID="
Question">
Security Question:</asp:Label></td>
<td>
<asp:TextBox ID="Question" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="QuestionRequired" runat="server" C
ontrolToValidate="Question"
ErrorMessage="Security question is required." ToolTip="Securit
y question is required."
ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValida
tor>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="AnswerLabel" runat="server" AssociatedControlID="An
swer">
Security Answer:</asp:Label></td>
<td>
<asp:TextBox ID="Answer" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="AnswerRequired" runat="server" Con
trolToValidate="Answer"
ErrorMessage="Security answer is required." ToolTip="Security
answer is required."
ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValida
tor>
</td>
</tr>
<tr>
<td align="center" colspan="2">
<asp:CompareValidator ID="PasswordCompare" runat="server" ControlT
oCompare="Password"
ControlToValidate="ConfirmPassword" Display="Dynamic" ErrorMes
sage="The Password and Confirmation Password must match."
ValidationGroup="CreateUserWizard1"></asp:CompareValidator>
</td>
</tr>
<tr>
<td align="center" colspan="2" style="color: red">
<asp:Literal ID="ErrorMessage" runat="server" EnableViewState="Fal
se"></asp:Literal>
</td>
</tr>
</table>
<asp:CheckBox ID="SubscribeCheckBox" runat="server" Checked="True" Text="Send
me a monthly newsletter." />
<br />
<asp:CheckBox ID="ShareInfoCheckBox" runat="server" Checked="True" Text="Share
my information with partner sites." />
</ContentTemplate>
</asp:CreateUserWizardStep>

3. To customize the completion step, create a <ContentTemplate> element within the <asp:CompleteWizardStep>
element. Inside the template, add markup and controls to define the layout and content of the UI for displaying a
confirmation message and optionally allowing the user to navigate to continue. (You must provide the controls to gather
the information required by your membership provider for creating a new user account. For details, see
CompleteWizardStep.)
The following code example shows a CompleteStep property that references the CheckBox controls from the previous
example.
VB
<asp:CompleteWizardStep ID="CompleteWizardStep1" runat="server">
<ContentTemplate>
<table border="0" style="font-size: 100%; font-family: Verdana" id="TABLE1" >
<tr>
<td align="center" colspan="2" style="font-weight: bold; color: white;
background-color: #5d7b9d; height: 18px;">
Complete</td>
</tr>
<tr>
<td>
Your account has been successfully created.<br />
<br />
<asp:Label ID="SubscribeLabel" runat="server" Text="You have elect
ed to receive our monthly newsletter."></asp:Label><br />
<br />
<asp:Label ID="ShareInfoLabel" runat="server" Text="You have elect
ed to share your information with partner sites."></asp:Label></td>
</tr>
<tr>
<td align="right" colspan="2">
&nbsp;<asp:Button ID="ContinueButton" runat="server" BackColor="#F
FFBFF" BorderColor="#CCCCCC"
BorderStyle="Solid" BorderWidth="1px" CausesValidation="False"
CommandName="Continue"
Font-Names="Verdana" ForeColor="#284775" Text="Continue" Valid
ationGroup="CreateUserWizard1" />
</td>
</tr>
</table>
</ContentTemplate>
</asp:CompleteWizardStep>

C#
<asp:CompleteWizardStep ID="CompleteWizardStep1" runat="server">
<ContentTemplate>
<table border="0" style="font-size: 100%; font-family: Verdana" id="TABLE1" >
<tr>
<td align="center" colspan="2" style="font-weight: bold; color: white;
background-color: #5d7b9d; height: 18px;">
Complete</td>
</tr>
<tr>
<td>
Your account has been successfully created.<br />
<br />
<asp:Label ID="SubscribeLabel" runat="server" Text="You have elect
ed to receive our monthly newsletter."></asp:Label><br />
<br />
<asp:Label ID="ShareInfoLabel" runat="server" Text="You have elect
ed to share your information with partner sites."></asp:Label></td>
</tr>
<tr>
<td align="right" colspan="2">
&nbsp;<asp:Button ID="ContinueButton" runat="server" BackColor="#F
FFBFF" BorderColor="#CCCCCC"
BorderStyle="Solid" BorderWidth="1px" CausesValidation="False"
CommandName="Continue"
Font-Names="Verdana" ForeColor="#284775" Text="Continue" Valid
ationGroup="CreateUserWizard1" />
</td>
</tr>
</table>
</ContentTemplate>
</asp:CompleteWizardStep>

4. Add code to reference the additional controls. For example, handling the CreatingUser event enables you to enter code to
gather, verify, and modify information before a new user account is created.
The following code example shows a handler for the CreatedUser event that references the CheckBox controls from the
previous examples and adds them to the Comment property of the newly created user account. You will need to add an
OnCreatedUser attribute to the CreateUserWizard control on your page that references the handler for the
CreatedUser event (for example, OnCreatedUser="CreateUserWizard1_CreatedUser".)
VB
Protected Sub CreateUserWizard1_CreatedUser(ByVal sender As Object, ByVal e As EventAr
gs)
' Determine the checkbox values.
Dim subscribeCheckBox As CheckBox = _
CType(CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("Sub
scribeCheckBox"), CheckBox)
Dim shareInfoCheckBox As CheckBox = _
CType(CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("Sha
reInfoCheckBox"), CheckBox)
Dim userNameTextBox As TextBox = _
CType(CreateUserWizardStep1.ContentTemplateContainer.FindControl("UserName"), Te
xtBox)

Dim user As MembershipUser = Membership.GetUser(userNameTextBox.Text)


User.Comment = "Subscribe=" & subscribeCheckBox.Checked.ToString() & "&" & _
"ShareInfo=" & shareInfoCheckBox.Checked.ToString()
Membership.UpdateUser(user)

' Show or hide the labels based on the checkbox values.


Dim subscribeLabel As Label = _
CType(CreateUserWizard1.CompleteStep.ContentTemplateContainer.FindControl("Subsc
ribeLabel"), Label)
Dim shareInfoLabel As Label = _
CType(CreateUserWizard1.CompleteStep.ContentTemplateContainer.FindControl("Share
InfoLabel"), Label)

subscribeLabel.Visible = subscribeCheckBox.Checked
shareInfoLabel.Visible = shareInfoCheckBox.Checked
End Sub

C#
protected void CreateUserWizard1_CreatedUser(object sender, EventArgs e)
{
// Determine the checkbox values.
CheckBox subscribeCheckBox =
(CheckBox)CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("S
ubscribeCheckBox");
CheckBox shareInfoCheckBox =
(CheckBox)CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("S
hareInfoCheckBox");
TextBox userNameTextBox =
(TextBox)CreateUserWizardStep1.ContentTemplateContainer.FindControl("UserName");

MembershipUser user = Membership.GetUser(userNameTextBox.Text);


user.Comment = "Subscribe=" + subscribeCheckBox.Checked.ToString() + "&" +
"ShareInfo=" + shareInfoCheckBox.Checked.ToString();
Membership.UpdateUser(user);

// Show or hide the labels based on the checkbox values.


Label subscribeLabel =
(Label)CreateUserWizard1.CompleteStep.ContentTemplateContainer.FindControl("Subscr
ibeLabel");
Label shareInfoLabel =
(Label)CreateUserWizard1.CompleteStep.ContentTemplateContainer.FindControl("ShareI
nfoLabel");

subscribeLabel.Visible = subscribeCheckBox.Checked;
shareInfoLabel.Visible = shareInfoCheckBox.Checked;
}

To add a wizard step


1. Add an <asp:WizardStep> element to the <WizardSteps> section of the CreateUserWizard control. Include any
controls and markup in the additional wizard step that your customized CreateUserWizard control will use.
For example, the following code example shows a step to be added before the CreateUserStep of the
CreateUserWizard control that includes a textbox control for users to enter a user name. The user name will be checked
to ensure that it does not already exist in the membership database.
VB
<asp:WizardStep ID="CreateUserWizardStep0" runat="server">
<table border="0" style="font-size: 100%; font-family: Verdana" id="TABLE1" >
<tr>
<td align="center" colspan="2" style="font-weight: bold; color: white; b
ackground-color: #5d7b9d">
Select an Account Name</td>
</tr>
<tr>
<td>
<asp:Label ID="AccountNameLabel" runat="server" AssociatedControlID="S
earchAccount" >
Account Name:</asp:Label>
<asp:TextBox ID="SearchAccount" runat="server"></asp:TextBox><br />
<asp:Label ID="SearchAccountMessage" runat="server" ForeColor="red" />

</td>
</tr>
</table>
</asp:WizardStep>

C#
<asp:WizardStep ID="CreateUserWizardStep0" runat="server">
<table border="0" style="font-size: 100%; font-family: Verdana" id="TABLE1" >
<tr>
<td align="center" colspan="2" style="font-weight: bold; color: white; b
ackground-color: #5d7b9d">
Select an Account Name</td>
</tr>
<tr>
<td>
<asp:Label ID="AccountNameLabel" runat="server" AssociatedControlID="S
earchAccount" >
Account Name:</asp:Label>
<asp:TextBox ID="SearchAccount" runat="server"></asp:TextBox><br />
<asp:Label ID="SearchAccountMessage" runat="server" ForeColor="red" />

</td>
</tr>
</table>
</asp:WizardStep>

2. Add code for your wizard step. You can handle the NextButtonClick event of the Wizard control to execute your code.
The CurrentStepIndex property value indicates which additional wizard step raised the NextButtonClick event by the
step index number (starting from 0 for the first step).
The following code example shows a handler for the NextButtonClick event that takes the user name entered in the
TextBox control in the wizard step from the previous code example and verifies that the user name is not blank and does
not currently exist in the membership database. You will need to add an OnNextButtonClick attribute to the
CreateUserWizard control on your page that references the handler for the NextButtonClick event handler (for
example, OnNextButtonClick="CreateUserWizard1_NextButtonClick".)
VB
Private Function UserExists(ByVal username As String) As Boolean
If Membership.GetUser(username) IsNot Nothing Then Return True

Return False
End Function

Protected Sub CreateUserWizard1_NextButtonClick(ByVal sender As Object, ByVal e As Wiz


ardNavigationEventArgs)
If e.CurrentStepIndex = 0 Then
If SearchAccount.Text.Trim() = "" OrElse UserExists(SearchAccount.Text) Then
SearchAccountMessage.Text = "That account already exists. Please select an
different account name."
e.Cancel = True
Else
Dim userName As TextBox = _
CType(CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindCont
rol("UserName"), TextBox)
userName.Text = SearchAccount.Text
SearchAccountMessage.Text = ""
e.Cancel = False
End If
End If
End Sub

C#
private bool UserExists(string username)
{
if (Membership.GetUser(username) != null) { return true; }

return false;
}

protected void CreateUserWizard1_NextButtonClick(object sender, WizardNavigationEventA


rgs e)
{
if (e.CurrentStepIndex == 0)
{
if (SearchAccount.Text.Trim() == "" || UserExists(SearchAccount.Text))
{
SearchAccountMessage.Text = "That account already exists. Please select an
different account name.";
e.Cancel = true;
}
else
{
TextBox userName =
(TextBox)CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindC
ontrol("UserName");
userName.Text = SearchAccount.Text;
SearchAccountMessage.Text = "";
e.Cancel = false;
}
}
}

Security Note
This control has a text box that accepts user input, which is a potential security threat. By default, ASP.NET Web pages v
alidate user input to ensure that the input does not contain HTML elements or script. For more information, see
Script Exploits Overview.

Example
The following code example shows a CreateUserWizard control with templates defined for the two basic steps,
CreateUserStep and CompleteStep, and an additional wizard step added before the CreateUserStep.
Security Note
This control has a textbox that accepts user input, which is a potential security threat. User input in a Web page can potentiall
y contain malicious client script. By default, ASP.NET Web pages validate user input to ensure that the input does not contain
HTML elements or script. As long as this validation is enabled, you do not need to explicitly check for script or HTML element
s in user input. For more information, see Script Exploits Overview.

VB
<%@ Page Language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1


/DTD/xhtml1-transitional.dtd">

<script runat="server">
Protected Sub CreateUserWizard1_CreatedUser(ByVal sender As Object, ByVal e As EventArg
s)
' Determine the checkbox values.
Dim subscribeCheckBox As CheckBox = _
CType(CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("Subs
cribeCheckBox"), CheckBox)
Dim shareInfoCheckBox As CheckBox = _
CType(CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("Shar
eInfoCheckBox"), CheckBox)
Dim userNameTextBox As TextBox = _
CType(CreateUserWizardStep1.ContentTemplateContainer.FindControl("UserName"), Tex
tBox)

Dim user As MembershipUser = Membership.GetUser(userNameTextBox.Text)


User.Comment = "Subscribe=" & subscribeCheckBox.Checked.ToString() & "&" & _
"ShareInfo=" & shareInfoCheckBox.Checked.ToString()
Membership.UpdateUser(user)
' Show or hide the labels based on the checkbox values.
Dim subscribeLabel As Label = _
CType(CreateUserWizard1.CompleteStep.ContentTemplateContainer.FindControl("Subscr
ibeLabel"), Label)
Dim shareInfoLabel As Label = _
CType(CreateUserWizard1.CompleteStep.ContentTemplateContainer.FindControl("ShareI
nfoLabel"), Label)

subscribeLabel.Visible = subscribeCheckBox.Checked
shareInfoLabel.Visible = shareInfoCheckBox.Checked
End Sub

Private Function UserExists(ByVal username As String) As Boolean


If Membership.GetUser(username) IsNot Nothing Then Return True

Return False
End Function

Protected Sub CreateUserWizard1_NextButtonClick(ByVal sender As Object, ByVal e As Wiza


rdNavigationEventArgs)
If e.CurrentStepIndex = 0 Then
If SearchAccount.Text.Trim() = "" OrElse UserExists(SearchAccount.Text) Then
SearchAccountMessage.Text = "That account already exists. Please select an
different account name."
e.Cancel = True
Else
Dim userName As TextBox = _
CType(CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindContr
ol("UserName"), TextBox)
userName.Text = SearchAccount.Text
SearchAccountMessage.Text = ""
e.Cancel = False
End If
End If
End Sub
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >


<head id="Head1" runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:CreateUserWizard ID="CreateUserWizard1" runat="server" BackColor="#F7F6F3" Bor
derColor="#E6E2D8"
BorderStyle="Solid" BorderWidth="1px" Font-Names="Verdana" Font-Size="0.8em"
OnNextButtonClick="CreateUserWizard1_NextButtonClick"
OnCreatedUser="CreateUserWizard1_CreatedUser" ContinueDestinationPageUrl="~/Def
ault.aspx">
<WizardSteps>
<asp:WizardStep ID="CreateUserWizardStep0" runat="server">
<table border="0" style="font-size: 100%; font-family: Verdana" id="TAB
LE1" >
<tr>
<td align="center" colspan="2" style="font-weight: bold; color
: white; background-color: #5d7b9d">
Select an Account Name</td>
</tr>
<tr>
<td>
<asp:Label ID="AccountNameLabel" runat="server" AssociatedCo
ntrolID="SearchAccount" >
Account Name:</asp:Label>
<asp:TextBox ID="SearchAccount" runat="server"></asp:TextBox
><br />
<asp:Label ID="SearchAccountMessage" runat="server" ForeColo
r="red" />
</td>
</tr>
</table>
</asp:WizardStep>
<asp:CreateUserWizardStep ID="CreateUserWizardStep1" runat="server">
<ContentTemplate>
<table border="0" style="font-size: 100%; font-family: Verdana">
<tr>
<td align="center" colspan="2" style="font-weight: bold; co
lor: white; background-color: #5d7b9d">
Sign Up for Your New Account</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="UserNameLabel" runat="server" Associated
ControlID="UserName">
User Name:</asp:Label></td>
<td>
<asp:TextBox ID="UserName" runat="server"></asp:TextBox
>
<asp:RequiredFieldValidator ID="UserNameRequired" runat
="server" ControlToValidate="UserName"
ErrorMessage="User Name is required." ToolTip="User
Name is required." ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="PasswordLabel" runat="server" Associated
ControlID="Password">
Password:</asp:Label></td>
<td>
<asp:TextBox ID="Password" runat="server" TextMode="Pas
sword"></asp:TextBox>
<asp:RequiredFieldValidator ID="PasswordRequired" runat
="server" ControlToValidate="Password"
ErrorMessage="Password is required." ToolTip="Passw
ord is required." ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="ConfirmPasswordLabel" runat="server" Ass
ociatedControlID="ConfirmPassword">
Confirm Password:</asp:Label></td>
<td>
<asp:TextBox ID="ConfirmPassword" runat="server" TextMo
de="Password"></asp:TextBox>
<asp:RequiredFieldValidator ID="ConfirmPasswordRequired
" runat="server" ControlToValidate="ConfirmPassword"
ErrorMessage="Confirm Password is required." ToolTi
p="Confirm Password is required."
ValidationGroup="CreateUserWizard1">*</asp:Required
FieldValidator>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="EmailLabel" runat="server" AssociatedCon
trolID="Email">
E-mail:</asp:Label></td>
<td>
<asp:TextBox ID="Email" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="EmailRequired" runat="s
erver" ControlToValidate="Email"
ErrorMessage="E-mail is required." ToolTip="E-mail
is required." ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="QuestionLabel" runat="server" Associated
ControlID="Question">
Security Question:</asp:Label></td>
<td>
<asp:TextBox ID="Question" runat="server"></asp:TextBox
>
<asp:RequiredFieldValidator ID="QuestionRequired" runat
="server" ControlToValidate="Question"
ErrorMessage="Security question is required." ToolT
ip="Security question is required."
ValidationGroup="CreateUserWizard1">*</asp:Required
FieldValidator>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="AnswerLabel" runat="server" AssociatedCo
ntrolID="Answer">
Security Answer:</asp:Label></td>
<td>
<asp:TextBox ID="Answer" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="AnswerRequired" runat="
server" ControlToValidate="Answer"
ErrorMessage="Security answer is required." ToolTip
="Security answer is required."
ValidationGroup="CreateUserWizard1">*</asp:Required
FieldValidator>
</td>
</tr>
<tr>
<td align="center" colspan="2">
<asp:CompareValidator ID="PasswordCompare" runat="serve
r" ControlToCompare="Password"
ControlToValidate="ConfirmPassword" Display="Dynami
c" ErrorMessage="The Password and Confirmation Password must match."
ValidationGroup="CreateUserWizard1"></asp:CompareVa
lidator>
</td>
</tr>
<tr>
<td align="center" colspan="2" style="color: red">
<asp:Literal ID="ErrorMessage" runat="server" EnableVie
wState="False"></asp:Literal>
</td>
</tr>
</table>
<asp:CheckBox ID="SubscribeCheckBox" runat="server" Checked="True"
Text="Send me a monthly newsletter." />
<br />
<asp:CheckBox ID="ShareInfoCheckBox" runat="server" Checked="True"
Text="Share my information with partner sites." />
</ContentTemplate>
</asp:CreateUserWizardStep>
<asp:CompleteWizardStep ID="CompleteWizardStep1" runat="server">
<ContentTemplate>
<table border="0" style="font-size: 100%; font-family: Verdana" id=
"TABLE1" >
<tr>
<td align="center" colspan="2" style="font-weight: bold; co
lor: white; background-color: #5d7b9d; height: 18px;">
Complete</td>
</tr>
<tr>
<td>
Your account has been successfully created.<br />
<br />
<asp:Label ID="SubscribeLabel" runat="server" Text="You
have elected to receive our monthly newsletter."></asp:Label><br />
<br />
<asp:Label ID="ShareInfoLabel" runat="server" Text="You
have elected to share your information with partner sites."></asp:Label></td>
</tr>
<tr>
<td align="right" colspan="2">
&nbsp;<asp:Button ID="ContinueButton" runat="server" Ba
ckColor="#FFFBFF" BorderColor="#CCCCCC"
BorderStyle="Solid" BorderWidth="1px" CausesValidat
ion="False" CommandName="Continue"
Font-Names="Verdana" ForeColor="#284775" Text="Cont
inue" ValidationGroup="CreateUserWizard1" />
</td>
</tr>
</table>
</ContentTemplate>
</asp:CompleteWizardStep>
</WizardSteps>
<SideBarStyle BackColor="#5D7B9D" BorderWidth="0px" Font-Size="0.9em" VerticalA
lign="Top" />
<TitleTextStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" />
<SideBarButtonStyle BorderWidth="0px" Font-Names="Verdana" ForeColor="White" />
<NavigationButtonStyle BackColor="#FFFBFF" BorderColor="#CCCCCC" BorderStyle="S
olid"
BorderWidth="1px" Font-Names="Verdana" ForeColor="#284775" />
<HeaderStyle BackColor="#5D7B9D" BorderStyle="Solid" Font-Bold="True" Font-Size
="0.9em"
ForeColor="White" HorizontalAlign="Center" />
<CreateUserButtonStyle BackColor="#FFFBFF" BorderColor="#CCCCCC" BorderStyle="S
olid"
BorderWidth="1px" Font-Names="Verdana" ForeColor="#284775" />
<ContinueButtonStyle BackColor="#FFFBFF" BorderColor="#CCCCCC" BorderStyle="Sol
id"
BorderWidth="1px" Font-Names="Verdana" ForeColor="#284775" />
<StepStyle BorderWidth="0px" />
</asp:CreateUserWizard>
&nbsp;</div>
</form>
</body>
</html>

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

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1


/DTD/xhtml1-transitional.dtd">

<script runat="server">
protected void CreateUserWizard1_CreatedUser(object sender, EventArgs e)
{
// Determine the checkbox values.
CheckBox subscribeCheckBox =
(CheckBox)CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("Subs
cribeCheckBox");
CheckBox shareInfoCheckBox =
(CheckBox)CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("Shar
eInfoCheckBox");
TextBox userNameTextBox =
(TextBox)CreateUserWizardStep1.ContentTemplateContainer.FindControl("UserName");

MembershipUser user = Membership.GetUser(userNameTextBox.Text);


user.Comment = "Subscribe=" + subscribeCheckBox.Checked.ToString() + "&" +
"ShareInfo=" + shareInfoCheckBox.Checked.ToString();
Membership.UpdateUser(user);

// Show or hide the labels based on the checkbox values.


Label subscribeLabel =
(Label)CreateUserWizard1.CompleteStep.ContentTemplateContainer.FindControl("Subscribe
Label");
Label shareInfoLabel =
(Label)CreateUserWizard1.CompleteStep.ContentTemplateContainer.FindControl("ShareInfo
Label");

subscribeLabel.Visible = subscribeCheckBox.Checked;
shareInfoLabel.Visible = shareInfoCheckBox.Checked;
}

private bool UserExists(string username)


{
if (Membership.GetUser(username) != null) { return true; }

return false;
}

protected void CreateUserWizard1_NextButtonClick(object sender, WizardNavigationEventArgs


e)
{
if (e.CurrentStepIndex == 0)
{
if (SearchAccount.Text.Trim() == "" || UserExists(SearchAccount.Text))
{
SearchAccountMessage.Text = "That account already exists. Please select an di
fferent account name.";
e.Cancel = true;
}
else
{
TextBox userName =
(TextBox)CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindCont
rol("UserName");
userName.Text = SearchAccount.Text;
SearchAccountMessage.Text = "";
e.Cancel = false;
}
}
}
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >


<head id="Head1" runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:CreateUserWizard ID="CreateUserWizard1" runat="server" BackColor="#F7F6F3" Bor
derColor="#E6E2D8"
BorderStyle="Solid" BorderWidth="1px" Font-Names="Verdana" Font-Size="0.8em"
OnNextButtonClick="CreateUserWizard1_NextButtonClick"
OnCreatedUser="CreateUserWizard1_CreatedUser" ContinueDestinationPageUrl="~/Def
ault.aspx">
<WizardSteps>
<asp:WizardStep ID="CreateUserWizardStep0" runat="server">
<table border="0" style="font-size: 100%; font-family: Verdana" id="TAB
LE1" >
<tr>
<td align="center" colspan="2" style="font-weight: bold; color
: white; background-color: #5d7b9d">
Select an Account Name</td>
</tr>
<tr>
<td>
<asp:Label ID="AccountNameLabel" runat="server" AssociatedCo
ntrolID="SearchAccount" >
Account Name:</asp:Label>
<asp:TextBox ID="SearchAccount" runat="server"></asp:TextBox
><br />
<asp:Label ID="SearchAccountMessage" runat="server" ForeColo
r="red" />
</td>
</tr>
</table>
</asp:WizardStep>
<asp:CreateUserWizardStep ID="CreateUserWizardStep1" runat="server">
<ContentTemplate>
<table border="0" style="font-size: 100%; font-family: Verdana">
<tr>
<td align="center" colspan="2" style="font-weight: bold; co
lor: white; background-color: #5d7b9d">
Sign Up for Your New Account</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="UserNameLabel" runat="server" Associated
ControlID="UserName">
User Name:</asp:Label></td>
<td>
<asp:TextBox ID="UserName" runat="server"></asp:TextBox
>
<asp:RequiredFieldValidator ID="UserNameRequired" runat
="server" ControlToValidate="UserName"
ErrorMessage="User Name is required." ToolTip="User
Name is required." ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="PasswordLabel" runat="server" Associated
ControlID="Password">
Password:</asp:Label></td>
<td>
<asp:TextBox ID="Password" runat="server" TextMode="Pas
sword"></asp:TextBox>
<asp:RequiredFieldValidator ID="PasswordRequired" runat
="server" ControlToValidate="Password"
ErrorMessage="Password is required." ToolTip="Passw
ord is required." ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="ConfirmPasswordLabel" runat="server" Ass
ociatedControlID="ConfirmPassword">
Confirm Password:</asp:Label></td>
<td>
<asp:TextBox ID="ConfirmPassword" runat="server" TextMo
de="Password"></asp:TextBox>
<asp:RequiredFieldValidator ID="ConfirmPasswordRequired
" runat="server" ControlToValidate="ConfirmPassword"
ErrorMessage="Confirm Password is required." ToolTi
p="Confirm Password is required."
ValidationGroup="CreateUserWizard1">*</asp:Required
FieldValidator>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="EmailLabel" runat="server" AssociatedCon
trolID="Email">
E-mail:</asp:Label></td>
<td>
<asp:TextBox ID="Email" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="EmailRequired" runat="s
erver" ControlToValidate="Email"
ErrorMessage="E-mail is required." ToolTip="E-mail
is required." ValidationGroup="CreateUserWizard1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="QuestionLabel" runat="server" Associated
ControlID="Question">
Security Question:</asp:Label></td>
<td>
<asp:TextBox ID="Question" runat="server"></asp:TextBox
>
<asp:RequiredFieldValidator ID="QuestionRequired" runat
="server" ControlToValidate="Question"
ErrorMessage="Security question is required." ToolT
ip="Security question is required."
ValidationGroup="CreateUserWizard1">*</asp:Required
FieldValidator>
</td>
</tr>
<tr>
<td align="right">
<asp:Label ID="AnswerLabel" runat="server" AssociatedCo
ntrolID="Answer">
Security Answer:</asp:Label></td>
<td>
<asp:TextBox ID="Answer" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="AnswerRequired" runat="
server" ControlToValidate="Answer"
ErrorMessage="Security answer is required." ToolTip
="Security answer is required."
ValidationGroup="CreateUserWizard1">*</asp:Required
FieldValidator>
</td>
</tr>
<tr>
<td align="center" colspan="2">
<asp:CompareValidator ID="PasswordCompare" runat="serve
r" ControlToCompare="Password"
ControlToValidate="ConfirmPassword" Display="Dynami
c" ErrorMessage="The Password and Confirmation Password must match."
ValidationGroup="CreateUserWizard1"></asp:CompareVa
lidator>
</td>
</tr>
<tr>
<td align="center" colspan="2" style="color: red">
<asp:Literal ID="ErrorMessage" runat="server" EnableVie
wState="False"></asp:Literal>
</td>
</tr>
</table>
<asp:CheckBox ID="SubscribeCheckBox" runat="server" Checked="True"
Text="Send me a monthly newsletter." />
<br />
<asp:CheckBox ID="ShareInfoCheckBox" runat="server" Checked="True"
Text="Share my information with partner sites." />
</ContentTemplate>
</asp:CreateUserWizardStep>
<asp:CompleteWizardStep ID="CompleteWizardStep1" runat="server">
<ContentTemplate>
<table border="0" style="font-size: 100%; font-family: Verdana" id=
"TABLE1" >
<tr>
<td align="center" colspan="2" style="font-weight: bold; co
lor: white; background-color: #5d7b9d; height: 18px;">
Complete</td>
</tr>
<tr>
<td>
Your account has been successfully created.<br />
<br />
<asp:Label ID="SubscribeLabel" runat="server" Text="You
have elected to receive our monthly newsletter."></asp:Label><br />
<br />
<asp:Label ID="ShareInfoLabel" runat="server" Text="You
have elected to share your information with partner sites."></asp:Label></td>
</tr>
<tr>
<td align="right" colspan="2">
&nbsp;<asp:Button ID="ContinueButton" runat="server" Ba
ckColor="#FFFBFF" BorderColor="#CCCCCC"
BorderStyle="Solid" BorderWidth="1px" CausesValidat
ion="False" CommandName="Continue"
Font-Names="Verdana" ForeColor="#284775" Text="Cont
inue" ValidationGroup="CreateUserWizard1" />
</td>
</tr>
</table>
</ContentTemplate>
</asp:CompleteWizardStep>
</WizardSteps>
<SideBarStyle BackColor="#5D7B9D" BorderWidth="0px" Font-Size="0.9em" VerticalA
lign="Top" />
<TitleTextStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" />
<SideBarButtonStyle BorderWidth="0px" Font-Names="Verdana" ForeColor="White" />
<NavigationButtonStyle BackColor="#FFFBFF" BorderColor="#CCCCCC" BorderStyle="S
olid"
BorderWidth="1px" Font-Names="Verdana" ForeColor="#284775" />
<HeaderStyle BackColor="#5D7B9D" BorderStyle="Solid" Font-Bold="True" Font-Size
="0.9em"
ForeColor="White" HorizontalAlign="Center" />
<CreateUserButtonStyle BackColor="#FFFBFF" BorderColor="#CCCCCC" BorderStyle="S
olid"
BorderWidth="1px" Font-Names="Verdana" ForeColor="#284775" />
<ContinueButtonStyle BackColor="#FFFBFF" BorderColor="#CCCCCC" BorderStyle="Sol
id"
BorderWidth="1px" Font-Names="Verdana" ForeColor="#284775" />
<StepStyle BorderWidth="0px" />
</asp:CreateUserWizard>
&nbsp;</div>
</form>
</body>
</html>

See Also
Reference
TemplatedWizardStep
Concepts
Customizing the Appearance of ASP.NET Login Controls
ASP.NET Themes and Skins Overview
Other Resources
Login ASP.NET Controls
ASP.NET

Securing Login Controls


ASP.NET login controls enable you to offer a solution for controlling access to Web pages based on user authentication,
membership, and roles. Login controls include the CreateUserWizard control, Login control, LoginStatus control, LoginView
control, PasswordRecovery control and ChangePassword control. The information in this topic describes how to improve the
security of the login controls through best practices in configuration and coding.
While following coding and configuration best practices can improve the security of your application, it is also important that
you continually keep your Web server computer up to date with the latest security patches for Microsoft Windows and Internet
Information Services (IIS), as well as any patches for Microsoft SQL Server or other data sources.
You can find more detailed information about best practices for writing secure code and securing applications in the book
"Writing Secure Code" by Michael Howard and David LeBlanc and through the guidance provided by Microsoft Patterns and
Practices (http://www.microsoft.com/resources/practices/default.mspx).
Information about special security practices for other types of controls is also available in the following topics:
Securing Standard Controls
Securing Web Parts Pages
Securing Data Access
General Security Practices for Login Controls
Securing login controls involves following best practices in a number of areas which are covered briefly below with links
leading to more information.
Using Secure Sockets Layer (SSL) Protocol
ASP.NET login controls transmit information to the server in plain text over HTTP. When you are dealing with sensitive
information, it is strongly recommended that you use HTTPS protocol with secure sockets layer (SSL) encryption. SSL protects
against data being altered (data integrity), protects a user's identity (confidentiality), and assures that data originates from the
expected client (authentication). For more information, see Cryptography Overview and
Configuring SSL on a Web Server or a Web Site in the IIS documentation.
Validating User Input
Never assume that input you get from users is safe. Malicious users can send potentially dangerous information from the
client to your application. For login controls, it is especially important to take precautions with user input because the
information being entered is often sensitive. For more information about guarding against malicious input, see
Basic Security Practices for Web Applications.
Whenever practical, use validation controls to test for valid user names and for strong passwords. You can validate some user
input without validation controls. For example, the CreateUserWizard control supports required and comparison validation.
You can also specify a regular expression with the EmailRegularExpression property to validate that e-mail addresses match a
specified pattern and with the PasswordRegularExpression property to validate that passwords meet your requirements.
For the most flexibility in validating user input in login controls, you can use templates. Whenever possible, create a template
for the control, add individual controls (typically TextBox controls), and add validation controls to restrict the user's input to the
narrowest allowable input.
Note
When using validation controls, always perform validation in server code in addition to using client-side validation. This help
s prevent users from bypassing validation by disabling or changing the client script check.

For more information, see Validating User Input in ASP.NET Web Pages.
Securing View State
Login controls store information in the page's view state, so it is a best security practice to secure view state. Although view
state data is stored in an encoded format, it can be viewed and tampered with. For more information, see Securing View State.
Securing Membership
ASP.NET membership provides functionality for validating and storing user credentials. The CreateUserWizard, Login,
PasswordRecovery, and ChangePassword controls use ASP.NET membership to enable you to create a complete
authentication system that requires little or no code. Additionally, the LoginName, LoginStatus, and LoginView controls can
be used to complete your solution for handling user membership and controlling access to pages within your Web site. For
more information, see Introduction to Membership and Securing Membership.
Membership providers shipped with ASP.NET have a built-in threshold for the maximum number of invalid password or
password answer attempts, as specified in the MaxInvalidPasswordAttempts property. ASP.NET membership also enables you
to configure the number of minutes in which a maximum number of invalid password or password answer attempts are
allowed before the membership user is locked out, as specified in the PasswordAttemptWindow property. The default
password attempt threshold is 5, and the default password attempt window is 10 minutes. Thresholds in the default providers
can be overridden by thresholds set in the membership section of the application's Web.config file. It is recommended that if
you set these thresholds, you set the values as low as practical. Additionally, it is recommended that you do not set the
RequiresQuestionAndAnswer property to false, because invalid password answer attempts will not be tracked. For more
information, see Membership Providers.
Securing E-Mail
The CreateUserWizard, ChangePassword, and PasswordRecovery controls can send e-mail messages with details about
the completed user transaction. Ensure that any e-mail messages sent to users reveal only necessary information. For example,
avoid making the subject line of the e-mail messages easy for unintended parties to filter from other e-mail messages. It is
recommended that you avoid sending passwords in e-mail. Consider other methods of verifying password transactions, such
as sending a confirmation code and a return URL that requires users to use the URL to complete the transaction.
If the MailDefinition property of the CreateUserWizard, ChangePassword, and PasswordRecovery controls is not specified,
then no e-mail message is sent. When these controls are configured to send e-mail messages, it is recommended that you
handle the mail error event to catch any SMTP-related errors to avoid revealing unnecessary information to users. For the
ChangePassword control, handle the SendMailError and set the Handled property of the SendMailErrorEventArgs object to
true. For an example showing how to handle a mail error event, see SendMailError event. For more information on installing
the Simple Mail Transfer Protocol (SMTP) service, see How to: Install and Configure SMTP Virtual Servers in IIS.
Security Consideration for Individual Controls
The following sections describe security considerations for individual login controls.
CreateUserWizard
The CreateUserWizard control collects information from a user and then creates an account in the ASP.NET membership
system for that user. You can extend the CreateUserWizard control to accept additional information by adding fields or steps
before or after the CreateUserWizardStep and the CompleteWizardStep steps. A security issue could arise if a user does not
complete all the steps in a CreateUserWizard control but an account is created. To prevent users from bypassing custom
wizard steps, override the OnNextButtonClick method and perform custom authentication. Once the information is collected,
use the MembershipProvider class's CreateUser method to create the user.
If you are performing administrative tasks and are using the CreateUserWizard to automatically create user accounts, it is
recommended that you set the AutoGeneratePassword property to true and the LoginCreatedUser property to false. In this
particular scenario, setting the DisableCreatedUser property to false is recommended.
Login Control
The Login control is a composite control that incorporates user name and password text boxes, as well as a check box
indicating whether users want to be remembered the next time they visit the page. The RememberMeSet property causes an
authentication cookie to be sent to the user's browser and the DisplayRememberMe property displays a check box that enables
the user to control whether a persistent cookie is sent. Avoid setting RememberMeSet to true and DisplayRememberMe to
false, because a cookie is sent but the user does not know it. In general, there are risks involved in storing cookies on users'
computers. Cookies are another form of user input and are therefore subject to information disclosure and spoofing. For more
information, see ASP.NET Cookies Overview.
If your Login control is used with a wide range of end users, consider coding the control so that users on public computers
have an option of using a non-persistent cookie which is discarded after the session times out. For more information on
writing cookies, see How to: Write a Cookie.
LoginName Control
The LoginName control displays the user's logged-in name, or it displays the user's domain and account name if the
application is using Windows authentication. Consider adding a check box that enables users to specify whether their name or
account information is displayed. For example, users on public computers may not want sensitive information displayed.
LoginView Control
The LoginView control enables you to display different information to users who are logged on and to users who are not
The LoginView control enables you to display different information to users who are logged on and to users who are not
logged on (anonymous users). Review the contents that you display with the AnonymousTemplate LoggedInTemplate
templates, and any with templates associated with the RoleGroups property to ensure that users are not able to view templates
not intended for them. In particular, the collection in the RoleGroups property is searched in the order that templates are
defined. The first matching role group template is displayed to the user. If a user is a member of more than one role, the first
role group template that matches any of the user's roles is displayed. If more than one template is associated with a single role,
only the first defined template will be used. For more information, see Understanding Role Management.
PasswordRecovery Control
The PasswordRecovery control enables users to retrieve their passwords based on the e-mail addresses associated with their
user names. When configuring the PasswordRecovery control, follow these guidelines:
Handle the SendMailError event to take action if errors occur when sending the e-mail message.
Set a limited number of password answer attempts with the MaxInvalidPasswordAttempts property and a limited
time window with the PasswordAttemptWindow property.
Review all information sent to users e-mail and review the security of the channel used to transmit messages, especially
if the password recovery e-mail message contains user passwords. Avoid sending e-mail messages that are clearly
marked as containing sensitive information, such as messages in which the subject line contains the word "password".
ChangePassword Control
The ChangePassword control enables users to change their passwords. When configuring the ChangePassword control,
follow these guidelines:
Handle the SendMailError event to take action if errors occur when sending e-mail.
Set a limited number of password answer attempts with the MaxInvalidPasswordAttempts property and a limited
time window with the PasswordAttemptWindow property.
Review all information sent to users e-mail and review the security of the channel used to transmit messages, especially
when the ChangePassword control is configured to use e-mail to send the new password to the user.
Use SSL to ensure that the user's new password cannot be read during the postback.
Limit access to the file that the ChangePassword control uses as the body of e-mail messages sent to the user. This file
is defined by the MailDefinition class's BodyFileName property.
See Also
Tasks
How to: Install and Configure SMTP Virtual Servers in IIS
Concepts
Basic Security Practices for Web Applications
Securing Standard Controls
Securing Membership
Other Resources
Managing Users by Using Membership
ASP.NET Web Site Security (Visual Studio)
Validation Server Controls
Cryptographic Services
Visual Web Developer

Walkthrough Topics — Login Controls


This following procedure describes how to work with ASP.NET login controls to create login pages, enable user registration,
recover passwords, and display different information to logged-in and anonymous users.
Walkthrough Topics
Walkthrough: Creating a Web Site with Membership and User Login (Visual Studio)
See Also
Other Resources
Login Toolbox Controls
Visual Web Developer

How-to Topics — Login Controls


The following procedures describe how to work with ASP.NET login controls to create login pages, enable user registration,
recover passwords, and display different information to logged-in and anonymous users.
How-to Topics
How to: Create an ASP.NET Login Page
How to: Add a Login Button to an ASP.NET Web Page
How to: Display the Name of the Current User
How to: Enable User Registration
How to: Enable User Password Recovery Using the ASP.NET PasswordRecovery Control
How to: Display Different Information to Anonymous and Logged In Users (Visual Studio)
How to: Use Advanced Features of the ASP.NET Login Control
How to: Customize the PasswordRecovery Control
How to: Customize the ASP.NET CreateUserWizard Control
See Also
Other Resources
Login Toolbox Controls
Visual Web Developer

HTML Controls for ASP.NET Web Pages


The topics in this section describe how to work with ASP.NET Web server controls that appear on the HTML tab of the Visual
Web Developer Toolbox.
By default, HTML elements on an ASP.NET Web page are not available to the server; they are treated as opaque text that is
passed through to the browser. However, by converting HTML elements to HTML server controls, you expose them as
elements you can program in server-based code.
For complete syntax information for Web server controls, see Web Server Control Syntax.
In This Section
HTML Div Control
HTML Horizontal Rule Control
HTML Image Control
HTML Input Controls
HTML Select Control
HTML Table Control
HTML Text Area Control
See Also
Tasks
How to: Add HTML Server Controls to an ASP.NET Web Page Using the Designer
Other Resources
Individual Web and HTML Controls
ASP.NET Web Server Controls (Visual Studio)
ASP.NET Web Pages (Visual Studio)
Visual Web Developer

HTML Div Control


One control based on the HTML DIV element is available on the HTML tab of the Toolbox as the Div control.
HTML server controls added from the Toolbox to a page in Visual Studio are simply HTML elements with certain attributes
already set. You can also create HTML elements in Source view by typing markup.
By default, HTML elements on a Web Forms page are not available to the server; they are treated as markup that is passed
through to the browser. However, if you add an id attribute and the attribute runat="server", ASP.NET recognizes the element
as a control on the page and you can program it with server-based code. If you convert an HTML DIV element to an ASP.NET
server control, it is created as an instance of the HtmlGenericControl class. For more information, see
ASP.NET Web Server Controls Overview. For a list of these controls, see HTML Server Controls.
ASP.NET server controls that render as a DIV element are as follows:
Panel

See Also
Tasks
How to: Convert HTML Server Controls to HTML Elements (Visual Studio)
How to: Add HTML Server Controls to an ASP.NET Web Page Using the Designer
Visual Web Developer

HTML Horizontal Rule Control


One control based on the HTML HR element is available on the HTML tab of the Toolbox as the Horizontal Rule control.
HTML server controls added from the Toolbox to a page in Visual Studio are simply HTML elements with certain attributes
already set. You can also create HTML elements in Source view by typing markup.
By default, HTML elements on a Web Forms page are not available to the server; they are treated as markup that is passed
through to the browser. However, if you add an id attribute and the attribute runat="server", ASP.NET recognizes the element
as a control on the page and you can program it with server-based code. If you convert an HTML HR element to an ASP.NET
server control, it is created as an instance of the HtmlGenericControl class. For more information, see
ASP.NET Web Server Controls Overview. For a list of these controls, see HTML Server Controls.
See Also
Tasks
How to: Convert HTML Server Controls to HTML Elements (Visual Studio)
How to: Add HTML Server Controls to an ASP.NET Web Page Using the Designer
Visual Web Developer

HTML Image Control


One control based on the HTML IMG element is available on the HTML tab of the Toolbox as the Image control.
HTML server controls added from the Toolbox to a page in Visual Studio are simply HTML elements with certain attributes
already set. You can also create HTML elements in Source view by typing markup.
By default, HTML elements on a Web Forms page are not available to the server; they are treated as markup that is passed
through to the browser. However, if you add an id attribute and the attribute runat="server", ASP.NET recognizes the element
as a control on the page and you can program it with server-based code. If you convert an HTML IMG element to an ASP.NET
server control, it is created as an instance of the HtmlImage class. For more information, see
ASP.NET Web Server Controls Overview. For a list of these controls, see HTML Server Controls.
ASP.NET server controls that render as an IMG element are as follows:
Image
Security Note
The URL that is associated with an Image server control or an HTML IMG element can be tampered with by a malicious user.
For more information, see Script Exploits Overview.

See Also
Tasks
How to: Convert HTML Server Controls to HTML Elements (Visual Studio)
How to: Add HTML Server Controls to an ASP.NET Web Page Using the Designer
Visual Web Developer

HTML Input Controls


The following controls, which are based on the HTML INPUT element, are available on the HTML tab of the Toolbox:
Input (Button) control: INPUT type="button" element
Input (Checkbox) control: INPUT type="checkbox" element
Input (File) control: INPUT type="file" element
Input (Hidden) control: INPUT type="hidden" element
Input (Password) control: INPUT type="password" element
Input (Radio) control: INPUT type="radio" element
Input (Reset) control: INPUT type="reset" element
Input (Submit) control: INPUT type="submit" element
Input (Text) control: INPUT type="text" element
HTML server controls added from the Toolbox to a page in Visual Studio are simply HTML elements with certain attributes
already set. You can also create HTML elements in Source view by typing markup.
By default, HTML elements on a Web Forms page are not available to the server; they are treated as markup that is passed
through to the browser. However, if you add an id attribute and the attribute runat="server", ASP.NET recognizes the element
as a control on the page and you can program it with server-based code.
Unlike other HTML elements, if you convert an HTML INPUT element to an ASP.NET server control, it is not created as an
instance of the HtmlInputControl class. You cannot create an instance of the HtmlInputControl class directly. Instead, this
class is inherited by the classes listed in the table below.
The following table lists the type that is used to instantiate INPUT elements as ASP.NET server controls if the markup contains
the attribute runat="server" and an id attribute.
Server control Type
Button control HtmlInputButton

CheckBox control HtmlInputCheckBox

File Field control HtmlInputFile

Hidden control HtmlInputHidden

Password control HtmlInputPassword

Radio Button control HtmlInputRadioButton

Reset Button control HtmlInputReset

Submit Button control HtmlInputSubmit

Text Field control HtmlInputText

For more information, see ASP.NET Web Server Controls Overview. For a list of HTML controls, see HTML Server Controls.
Security Note
User input in a Web Forms page can include potentially malicious client script. By default, the Web Forms page validates that
user input does not include script or HTML elements. For more information, see Script Exploits Overview and
How to: Protect Against Script Exploits in a Web Application by Applying HTML Encoding to Strings.
ASP.NET server controls that render as an INPUT element are as follows:
Button
CheckBox
FileUpload
HiddenField
ImageButton
RadioButton
TextBox
See Also
Tasks
How to: Convert HTML Server Controls to HTML Elements (Visual Studio)
How to: Add HTML Server Controls to an ASP.NET Web Page Using the Designer
Visual Web Developer

HTML Select Control


One control based on the HTML SELECT element is available on the HTML tab of the Toolbox as the Select control.
HTML server controls added from the Toolbox to a page in Visual Studio are simply HTML elements with certain attributes
already set. You can also create HTML elements in Source view by typing markup.
By default, HTML elements on a Web Forms page are not available to the server; they are treated as markup that is passed
through to the browser. However, if you add an id attribute and the attribute runat="server", ASP.NET recognizes the element
as a control on the page and you can program it with server-based code. If you convert an HTML SELECT element to an
ASP.NET server control, it is created as an instance of the HtmlSelect class. For more information, see
ASP.NET Web Server Controls Overview. For a list of these controls, see HTML Server Controls.
Security Note
Controls in a Web Forms page can include potentially malicious client script. By default, the Web Forms page validates that u
ser input does not include script or HTML elements. For more information, see Script Exploits Overview and
How to: Protect Against Script Exploits in a Web Application by Applying HTML Encoding to Strings.

ASP.NET server controls that render as a SELECT element are as follows:


ListBox
DropDownList
See Also
Tasks
How to: Convert HTML Server Controls to HTML Elements (Visual Studio)
How to: Add HTML Server Controls to an ASP.NET Web Page Using the Designer
Visual Web Developer

HTML Table Control


One control based on the HTML TABLE element is available on the HTML tab of the Toolbox as the Table control.
By default, when you add a Table control to an HTML page or a Web Forms page, the table measures three columns by three
rows. You can customize the number of columns and rows by using commands on the Layout menu. For details, see
HTML Table Editing in Visual Web Developer.
HTML server controls added from the Toolbox to a page in Visual Studio are simply HTML elements with certain attributes
already set. You can also create HTML elements in Source view by typing markup.
By default, HTML elements on a Web Forms page are not available to the server; they are treated as markup that is passed
through to the browser. However, if you add an id attribute and the attribute runat="server", ASP.NET recognizes the element
as a control on the page and you can program it with server-based code. If you convert an HTML TABLE element to an
ASP.NET server control, it is created as an instance of the HtmlTable class. For more information, see
ASP.NET Web Server Controls Overview. For a list of these controls, see HTML Server Controls.
ASP.NET server controls that can render as a TABLE element are as follows:
Calendar
CheckBoxList (if the RepeatLayout property is set to Table)
DataList
GridView
RadioButtonList (if the RepeatLayout property is set to Table)
Table
See Also
Tasks
How to: Convert HTML Server Controls to HTML Elements (Visual Studio)
How to: Add HTML Server Controls to an ASP.NET Web Page Using the Designer
Visual Web Developer

HTML Text Area Control


One control based on the HTML TEXTAREA element is available on the HTML tab of the Toolbox as the Text Area control.
HTML server controls added from the Toolbox to a page in Visual Studio are simply HTML elements with certain attributes
already set. You can also create HTML elements in Source view by typing markup.
By default, HTML elements on a Web Forms page are not available to the server; they are treated as markup that is passed
through to the browser. However, if you add an id attribute and the attribute runat="server", ASP.NET recognizes the element
as a control on the page and you can program it with server-based code. If you convert an HTML TEXTAREA element to an
ASP.NET server control, it is created as an instance of the HtmlTextArea class. For more information, see
ASP.NET Web Server Controls Overview. For a list of these controls, see HTML Server Controls.
Security Note
User input in a Web Forms page can include potentially malicious client script. By default, the Web Forms page validates that
user input does not include script or HTML elements. For more information, see Script Exploits Overview and
How to: Protect Against Script Exploits in a Web Application by Applying HTML Encoding to Strings.

ASP.NET server controls that render as a TEXTAREA element are as follows:


TextBox (if the TextMode property is set to MultiLine)
See Also
Tasks
How to: Convert HTML Server Controls to HTML Elements (Visual Studio)
How to: Add HTML Server Controls to an ASP.NET Web Page Using the Designer
Visual Web Developer

ASP.NET Web User Controls (Visual Studio)


The topics in this section provide information on controls that are defined declaratively and provide a simple and
straightforward mechanism for reuse of UI and UI-related code.
In This Section
Getting Started — ASP.NET User Controls
Learning More — User Controls
Walkthrough Topics — ASP.NET User Controls
How-to Topics — ASP.NET User Controls
See Also
Concepts
Caching Portions of an ASP.NET Page
Other Resources
Individual Web and HTML Controls
ASP.NET Web Server Controls (Visual Studio)
ASP.NET Web Pages (Visual Studio)
Visual Web Developer

Getting Started — ASP.NET User Controls


In addition to using HTML and Web server controls, you can create custom, reusable controls using the same techniques you
use for ASP.NET Web pages. These controls are called user controls.
While you need to choose a single language when authoring a user control, you can include multiple user controls—each
authored in a different language—in a single ASP.NET Web page. For example, you can create one user control in Visual Basic
that imports data from an XML file, and create another user control in C# that contains an order form, and include both
controls in the same ASP.NET Web page.
You can cache output from a user control independently from the rest of its containing ASP.NET Web page. This technique,
called fragment caching, can improve performance for your site. For example, if your user control contains an ASP.NET server
control that makes a database request, but the rest of the page contains only literal text and simple code that runs on the
server, you can use fragment caching in the user control to increase your application's performance.
The topics in this section provide essential information on working with user controls.
In This Section
ASP.NET User Controls Overview
Walkthrough: Creating Reusable Elements with ASP.NET User Controls
How to: Create ASP.NET User Controls (Visual Studio)
How to: Include ASP.NET User Controls in Web Pages (Visual Studio)
Reference
System.Web.UI.UserControl
Describes the events, methods, and properties of the .NET Framework class for user controls.
Related Sections
Walkthrough: Creating a Basic Web Page in Visual Web Developer
Describes how to create forms-based Web pages that are processed on the server.
ASP.NET User Controls
Introduces ASP.NET Web page user controls.
Caching Portions of an ASP.NET Page
Discusses the techniques you can use to cache regions of your pages using the @ OutputCache directive and user controls.
This technique is useful if you do not want to cache entire pages.
See Also
Concepts
Caching Portions of an ASP.NET Page
Other Resources
Individual Web and HTML Controls
ASP.NET Web Server Controls (Visual Studio)
ASP.NET Web Pages (Visual Studio)
ASP.NET

ASP.NET User Controls Overview


At times, you might need functionality in a control that is not provided by the built-in ASP.NET Web server controls. In those
cases, you can create your own controls. You have two options. You can create:
User controls. User controls are containers into which you can put markup and Web server controls. You can then treat
the user control as a unit and define properties and methods for it.
Custom controls. A custom control is a class that you write that derives from Control or WebControl.
User controls are substantially easier to create than custom controls, because you can reuse existing controls. They make it
particularly easy to create controls with complex user interface elements.
This topic provides an overview of working with ASP.NET user controls.
User Control Structure
An ASP.NET Web user control is similar to a complete ASP.NET Web page (.aspx file), with both a user interface page and code.
You create the user control in much the same way you create an ASP.NET page and then add the markup and child controls
that you need. A user control can include code to manipulate its contents like a page can, including performing tasks such as
data binding.
A user controls differs from an ASP.NET Web page in these ways:
The file name extension for the user control is .ascx.
Instead of an @ Page directive, the user control contains an @ Control directive that defines configuration and other
properties.
User controls cannot run as stand-alone files. Instead, you must add them to ASP.NET pages, as you would any control.
The user control does not have html, body, or form elements in it. These elements must be in the hosting page.
You can use the same HTML elements (except the html, body, or form elements) and Web controls on a user control that you
do on an ASP.NET Web page. For example, if you are creating a user control to use as a toolbar, you can put a series of Button
Web server controls onto the control and create event handlers for the buttons.
The following example shows a user control that implements a spinner control where users can click up and down buttons to
rotate through a series of choices in a text box.
Security Note
This example has a text box that accepts user input, which is a potential security threat. By default, ASP.NET Web pages valida
te that user input does not include script or HTML elements. For more information, see Script Exploits Overview.

VB
<%@ Control Language="VB" ClassName="UserControl1" %>
<script runat="server">
Protected colors As String() = {"Red", "Green", "Blue", "Yellow"}
Protected currentColorIndex As Integer = 0
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs)
If IsPostBack Then
currentColorIndex = CInt(ViewState("currentColorIndex"))
Else
currentColorIndex = 0
DisplayColor()
End If
End Sub

Protected Sub DisplayColor()


textColor.Text = colors(currentColorIndex)
ViewState("currentColorIndex") = currentColorIndex.ToString()
End Sub
Protected Sub buttonUp_Click(ByVal sender As Object, _
ByVal e As System.EventArgs)
If currentColorIndex = 0 Then
currentColorIndex = colors.Length - 1
Else
currentColorIndex -= 1
End If
DisplayColor()
End Sub
Protected Sub buttonDown_Click(ByVal sender As Object, _
ByVal e As System.EventArgs)
If currentColorIndex = colors.Length - 1 Then
currentColorIndex = 0
Else
currentColorIndex += 1
End If
DisplayColor()
End Sub
</script>
<asp:TextBox ID="textColor" runat="server"
ReadOnly="True" />
<asp:Button Font-Bold="True" ID="buttonUp" runat="server"
Text="^" OnClick="buttonUp_Click" />
<asp:Button Font-Bold="True" ID="buttonDown" runat="server"
Text="v" OnClick="buttonDown_Click" />

C#
<% @ Control Language="C#" ClassName="UserControl1" %>
<script runat="server">
protected int currentColorIndex;
protected String[] colors = {"Red", "Blue", "Green", "Yellow"};
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
currentColorIndex =
Int16.Parse(ViewState["currentColorIndex"].ToString());
}
else
{
currentColorIndex = 0;
DisplayColor();
}
}

protected void DisplayColor()


{
textColor.Text = colors[currentColorIndex];
ViewState["currentColorIndex"] = currentColorIndex.ToString();
}

protected void buttonUp_Click(object sender, EventArgs e)


{
if(currentColorIndex == 0)
{
currentColorIndex = colors.Length - 1;
}
else
{
currentColorIndex -= 1;
}
DisplayColor();
}
protected void buttonDown_Click(object sender, EventArgs e)
{
if(currentColorIndex == (colors.Length - 1))
{
currentColorIndex = 0;
}
else
{
currentColorIndex += 1;
}
DisplayColor();
}
</script>
<asp:TextBox ID="textColor" runat="server"
ReadOnly="True" />
<asp:Button Font-Bold="True" ID="buttonUp" runat="server"
Text="^" OnClick="buttonUp_Click" />
<asp:Button Font-Bold="True" ID="buttonDown" runat="server"
Text="v" OnClick="buttonDown_Click" />

Notice that the user control looks much like an ASP.NET page — it contains several controls (a TextBox control and two Button
controls) and code that handles the buttons' Click events and the page’s Load event. However, the control contains no markup
except for the controls, and instead of an @ Page directive it contains an @ Control directive.
Adding a User Control to a Page
You add a user control to a page by registering it on the host page. When you register it, you specify the .ascx file that contains
the user control, a tag prefix, and a tag name that you will use to declare the user control on the page. For details, see
How to: Include a User Control in an ASP.NET Web Page.
Defining Properties and Methods for a User Control
You can define properties and methods for a user control the same way you do for a page. By defining a property for a user
control, you make it possible to set its properties declaratively and in code.
Events in User Controls
When a user control contains Web server controls, you can write code in the user control to handle the events raised by the
child controls. For example, if your user control contains a Button control, you can create a handler in the user control for the
button's Click event.
By default, events raised by child controls in a user control are not available to the host page. However, you can define events
for your user control and raise them so that the host page is notified of the event. You do this in the same way that you define
events for any class. For more information, see Raising an Event.
Referencing External Resources
When a user control runs, references to external resources such as images or anchors to other pages are resolved using the
URL of the user control as the base URL. For example, if the user control contains an Image control whose ImageUrl property is
set to Images/Button1.gif, the URL of the image is added to the URL of the user control to resolve the complete path to the
image. If the user control references a resource that is not in a subfolder of the user control itself, you must provide a path that
resolves to the correct folder at run time. For more information on specifying paths for ASP.NET server controls, see
ASP.NET Web Site Paths.
Caching and User Controls
User controls can support caching directives that are separate from the host page. You can therefore add user controls to
pages and to cache portions of a page. For details, see Caching Portions of an ASP.NET Page.
See Also
Other Resources
ASP.NET User Controls
Visual Web Developer

Walkthrough: Creating Reusable Elements with ASP.NET User


Controls
ASP.NET user controls let you encapsulate the functionality of multiple server controls in a unit. User controls are made up of
one or more ASP.NET server controls—Button controls, TextBox controls, and so on—along with any code that is required for
the controls to perform the function that you want to accomplish. The user control can also include custom properties or
methods that reveal the functionality of the user control to a container, which is typically an ASP.NET page.
In this walkthrough, you will create an ASP.NET user control that acts as a picker control. The picker control has two lists, with a
set of choices in one list (the source). Users can select items in the SourceList list, and then add the items to the TargetList list.
This walkthrough has three parts, as follows:
In the first part, you will create the basic user control, adding controls and code.
In the second part, you will create a new ASP.NET page (the host page), and then add the user control to the ASP.NET
page.
In the third part, you will add custom properties and methods to the user control so that you can interact with the control
from the host page.
Tasks illustrated in this walkthrough include the following:
Creating a user control and adding ASP.NET server controls to the user control.
Creating properties and a method in the user control.
Adding a user control to a host page.
Adding code to the host page to handle the user control.
Prerequisites
In order to complete this walkthrough, you will need the following:
The Microsoft Visual Web Developer Web development tool.
The Microsoft .NET Framework.
This walkthrough assumes that you have a general understanding of working in Visual Web Developer. For an introduction,
see Walkthrough: Creating a Basic Web Page in Visual Web Developer.
Creating the Web Site
If you have already created a Web site in Visual Web Developer (for example, by completing
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and go to the next section.
Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, point to New, and then click Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the right-most Location box, enter the name of the folder where you want to keep the pages of the Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click the programming language that you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Creating the User Control
Creating a user control is similar to creating an ASP.NET Web page. In fact, a user control is effectively a subset of an ASP.NET
page and it can include most of the types of elements that you put on an ASP.NET page.
To create a user control
1. In Solution Explorer, right-click the name of the Web site, and then click Add New Item.
2. In the Add New Item <Path> dialog box, under Visual Studio installed templates, click Web User Control.
3. In the Name box, type ListPicker.
The user control file will have an .ascx extension, which is added automatically to ListPicker.
4. In the Language list, select the programming language that you prefer to work in.
5. Click Add.
The new control is created and is opened in the designer. The markup for the control looks similar to that for a page, with
one important exception: there is no @ Page directive at the top of the page. Instead, there is an @ Control directive,
which identifies the file to ASP.NET as a user control.
Adding Server Controls to the User Control
In this part of the walkthrough, you will add the controls that make up the user interface for the user control.
To add server controls
1. Switch to Design view.
2. On the Layout menu, click Insert Table.
3. Use the Insert Table dialog box to create a table with one row and three columns, and then click OK.
You are creating the table to hold the controls; that is, a layout table.
4. In the table, in the left column, type Available, and then press ENTER to create a new line.
5. In the right column, type Selected, and then press ENTER to create a new line.
6. from the Standard group in the Toolbox, drag the following controls onto the table and set their properties as indicated.
Control Properties
Drag a ListBox to the left column and place it under Available. Height: 200px
ID: SourceList
Width: 200px

Drag a Button to the middle column. ID: AddAll


Text: >>

Drag a Button to the middle column. ID: AddOne


Text: (SPACEBAR)>( SPACEBAR)

Drag a Button to the middle column. ID: Remove


Text: (SPACEBAR)X(SPACEBAR)

Drag a ListBox to the right column and place it under Selected. Height: 200px
ID: TargetList
Width: 200px

ImageButton controls can be used instead of Button controls so that an image is displayed that responds to mouse clicks.
However, for this walkthrough, it is sufficient to use text that emulates the type of graphic that is frequently used to
indicate Add All, Add, and Remove, which are the two right angle brackets (>>), one right angle bracket (>), and the X,
respectively.
7. If you want, adjust the width and height of the table columns to your preference.
8. Click the SourceList list, and then in Properties, for the Items property, click the ellipsis (…) button.
The ListItem Collection Editor dialog box appears.
9. Click Add three times to add three items
10. For the first, second, and third item, under ListItem properties, set Text to A, B, and C, respectively.
You are creating test data for now. Later in this walkthrough, in "Adding Custom Properties and Methods to the User
Control," you will remove the test data and add code to load the SourceList list dynamically.
Adding Code to Handle User Selections
Users will select items using the buttons that are in the middle column of the table. Therefore, most of the code for the control
is in handlers for the Click events.
To add code to handle user selections
1. In Design view, double-click the >> (AddAll) button to create an event handler for the Click event, and then add the
following highlighted code.
VB
Protected Sub AddAll_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles AddAll.Click
TargetList.SelectedIndex = -1
Dim li As ListItem
For Each li In SourceList.Items
AddItem(li)
Next
End Sub

C#
protected void AddAll_Click(object sender, EventArgs e)
{
TargetList.SelectedIndex = -1;
foreach(ListItem li in SourceList.Items)
{
AddItem(li);
}
}

The code loops through all the list items in the SourceList list. For each item, it calls the AddItem method and passes it
the current item. Later in this procedure, you will write the code for the AddItem method.
2. Switch to Design view, double-click the > (AddOne) button to create an event handler for the Click event, and then add
the following highlighted code:
VB
Protected Sub AddOne_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles AddOne.Click
If SourceList.SelectedIndex >= 0 Then
AddItem(SourceList.SelectedItem)
End If
End Sub
C#
protected void AddOne_Click(object sender, EventArgs e)
{
if(SourceList.SelectedIndex >= 0)
{
AddItem(SourceList.SelectedItem);
}
}

This code first checks that there is a selection in the SourceList list. If there is, the code calls the AddItem method, which
you will write later in this procedure, passing it the item that is currently selected in the SourceList list.
3. Switch to Design view, double-click the X (Remove) button to create an event handler for the Click event, and then add
the following highlighted code:
VB
Protected Sub Remove_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles Remove.Click
If TargetList.SelectedIndex >= 0 Then
TargetList.Items.RemoveAt(TargetList.SelectedIndex)
TargetList.SelectedIndex = -1
End If
End Sub

C#
protected void Remove_Click(object sender, EventArgs e)
{
if(TargetList.SelectedIndex >= 0)
{
TargetList.Items.RemoveAt(TargetList.SelectedIndex);
TargetList.SelectedIndex = -1;
}
}

The code first checks that the TargetList list contains a selection. If there is a selection, the code removes the selected
item from the list and the selection.
4. Add the following AddItem method:
VB
Protected Sub AddItem(ByVal li As ListItem)
TargetList.SelectedIndex = -1
TargetList.Items.Add(li)
End Sub

C#
protected void AddItem(ListItem li)
{
TargetList.SelectedIndex = -1;
TargetList.Items.Add(li);
}

This code unconditionally adds an item to the TargetList list. Later in this walkthrough, in "Adding Custom Properties
and Methods to the User Control," you will improve this code by adding the option to determine whether there are
duplicates.
You cannot directly test a user control, because it must be hosted in a page. In the next section, you will create an ASP.NET Web
page where you can work with the control.
Using the User Control
Like any control, a user control must be hosted in a page. In this part of the walkthrough, you will create a host page for the
control, and then you will add a user control to the page.
To create a host page
1. In Solution Explorer, right-click the name of the Web site, and then click Add New Item.
2. Under Visual Studio installed templates, click Web Form.
3. In the Name box, type HostUserControl.
4. In the Language list, select the language that you prefer to work in, and then click Add.
The new page appears in the designer.

To add the user control to the page


1. Switch to Design view.
2. From Solution Explorer, drag the user control file (ListPicker.ascx) onto the page.
Note
Be sure that you are in Design view when you drag ListPicker.ascx onto the page.

The control appears in the designer.


3. Switch to Source view.
Placing the user control on the page creates two new elements in the page:
At the top of the page is a new @ Register directive and it looks similar to the following:

<%@ Register Src="ListPicker.ascx" TagName="ListPicker"


TagPrefix="uc1" %>

The @ Register directive is required, because the user control is an external component. The values that are in the
directive provide information that is required by ASP.NET to find the control when compiling and running the page.
Together, the TagPrefix and TagName attributes specify how the user control is declared on the page. The Src
attribute specifies the file, and if it is necessary, the path, where the source file is located.
The second new element is the element for the user control and it looks similar to the following:

<uc1:ListPicker id="ListPicker1" Runat="server" />

The element for a user control looks similar to the element for an ordinary ASP.NET server control. The difference is
that the user control has a different tag prefix (uc1) and a unique tag name (ListPicker). Although the values were
established automatically by the @ Register directive when you placed the user control on the page, you can use
any tag prefix and tag name for your user control, as long as the values are not already being used in the page.
Testing the User Control
Now, you can test the preliminary version of the user control.
To test the user control
1. Press CTRL+F5 to run the page.
The page appears in the browser and you can see the two lists and three buttons that make up your user control.
2. Click the >> (AddAll) button.
All values from the SourceList list are copied to the TargetList list.
3. Click each item in the TargetList list in turn, and then click the X (Remove) button until you have removed all items.
4. Select a single value in the SourceList list, and then click the > (AddOne) button.
The single value is copied to the TargetList list.
5. Optionally, experiment more with the control until you are sure that it works as you intend it to.
6. When you are finished, close the browser.
Adding Custom Properties and Methods to the User Control
Your user control now works, but it is not yet useful as a general-purpose control. A more practical version of the user control
would let you do the following:
Specify the list of items to display in the SourceList list dynamically.
Get the list of items that the user selected in the TargetList list.
Specify whether you want to allow duplicate values in the TargetList list, optionally.
Provide a way for users to clear all items in the TargetList list quickly.
Performing these tasks requires that the host page can communicate with the user control, both to share values (set and read
properties) and to issue commands (call methods). In this part of the walkthrough, you will change the user control and add
some members (properties and methods) to it.
You will add two properties to the user control. The first property retrieves the list of items that are in the TargetList list. The
second property lets you specify whether the TargetList list accepts duplicate values. Later in this section, you will add a
method that will let you populate the SourceList list.
To add code to define custom properties
1. For the ListPicker control, open or switch to the code file.
2. Use the following code to create the SelectedItems property:
VB
Public ReadOnly Property SelectedItems() As ListItemCollection
Get
Return TargetList.Items
End Get
End Property

C#
public ListItemCollection SelectedItems
{
get { return TargetList.Items ; }
}

The SelectedItems property retrieves the values that are in the TargetList list. It can be read-only, because you will
never have to set the values in the TargetList list programmatically.
3. Use the following code to create the AllowDuplicates property:
VB
Public Property AllowDuplicates() As Boolean
Get
Return CType(ViewState("allowDuplicates"), Boolean)
End Get
Set(ByVal value As Boolean)
ViewState("allowDuplicates") = value
End Set
End Property

C#
public Boolean AllowDuplicates
{
get
{
return (Boolean)ViewState["allowDuplicates"];
}
set
{
ViewState["allowDuplicates"] = value;
}
}

The AllowDuplicates property is a read/write property. The value of the AllowDuplicates property must be saved
explicitly in View state so that it persists between round trips. (The SelectedItems property does not have to be explicitly
saved in View state, because the TargetList list saves the values in View state.)
You now have the properties defined. However, you still must modify the existing code in the user control to take advantage of
the AllowDuplicates property setting.
To modify existing code to use the AllowDuplicates property
Find the AddItem method that you wrote in "Adding Code to Handle User Selections," earlier in this walkthrough, and
replace the contents with the following highlighted code:
VB
Protected Sub AddItem(ByVal li As ListItem)
TargetList.Selectedindex = -1
If Me.AllowDuplicates = True Then
TargetList.Items.Add(li)
Else
If TargetList.Items.FindByText(li.Text) Is Nothing Then
TargetList.Items.Add(li)
End If
End If
End Sub

C#
protected void AddItem(ListItem li)
{
TargetList.SelectedIndex = -1;
if(this.AllowDuplicates == true)
{
TargetList.Items.Add(li);
}
else
{
if(TargetList.Items.FindByText(li.Text) == null)
{
TargetList.Items.Add(li);
}
}
}

The code performs the same function as before (adding an item to the TargetList list), but now the code checks to
determine whether the AllowDuplicate property is set to true. If the AllowDuplicate property is set to true, the code
first looks for an existing item with the same value as the proposed new item, and then adds the new item, but only if no
existing item is found.
Because you will be setting the contents of the SourceList list using a property, you can remove the test data that you entered
in "Adding Server Controls to the User Control," earlier in this walkthrough.
To remove the test data for the SourceList list
1. Switch to Design view.
2. Click the SourceList control, and then, in Properties, for Items, click the ellipsis (…) button.
The ListItem Collection Editor appears.
3. Click the X (Remove) button to remove each sample item, and then click OK.
Adding a Method to the User Control
You can also add methods to perform tasks in the user control when the methods are called by code in the host page. To
illustrate this, in this walkthrough, you will add two methods. The first method can be called to add items to the SourceList list.
The second method clears the contents of the TargetList list.
To add a method to clear the TargetList list
1. Use the following code to add the AddSourceItem method:
VB
Public Sub AddSourceItem(ByVal sourceItem As String)
SourceList.Items.Add(sourceItem)
End Sub

C#
public void AddSourceItem(String sourceItem)
{
SourceList.Items.Add(sourceItem);
}

2. Use the following code to add the ClearAll method:


VB
Public Sub ClearAll()
SourceList.Items.Clear()
TargetList.Items.Clear()
End Sub

C#
public void ClearAll()
{
SourceList.Items.Clear();
TargetList.Items.Clear();
}

3. On the File menu, click Save All to save the changes that you made to the user control.
Testing the User Control Properties and Method
The final task in this walkthrough is to enhance the host page to be able to share values with the user control. You can set
some of the properties for the user control declaratively. (You cannot set the SourceList list directly using the code in this
walkthrough, but you can set it programmatically.) In this procedure, you will set the AllowDuplicates property to a default
value of true.
To set user control properties declaratively
1. Switch to or open the HostUserControl.aspx page.
2. In Source view, set AllowDuplicates declaratively by using syntax that it similar to the following:

<uc1:ListPicker id="ListPicker1" Runat="server"


AllowDuplicates="true" />

Notice that you obtain Microsoft IntelliSense functionality for AllowDuplicates.


Working with the User Control Programmatically
You can also work with the user control programmatically, setting and retrieving the properties and calling the methods. To
illustrate how to work with the user control programmatically, you will add some controls to the host page.
To work with the user control programmatically
1. Switch to Design view.
2. From the Standard group in the Toolbox, drag the following controls onto the table on the host page, and then set the
properties as indicated.
Control Properties
TextBox ID: NewItem
Text: (empty)

Button ID: AddItem


Text: Add Item

Button ID: LoadFiles


Text: File List

Button ID: ClearSelection


Text: Clear All

CheckBox AutoPostBack: True


Checked: True
ID: AllowDuplicates
Text: Allow duplicates

Button ID: ShowSelection


Text: Show Selection

Label ID: Selection


Text: (empty)

3. In Design view, double-click AllowDuplicates to create an event handler for the CheckedChanged event, and then add
the following highlighted code:
VB
Protected Sub AllowDuplicates_CheckedChanged( _
ByVal sender As Object, _
ByVal e As EventArgs) Handles AllowDuplicates.CheckedChanged
ListPicker1.AllowDuplicates = AllowDuplicates.Checked
End Sub

C#
protected void AllowDuplicates_CheckedChanged(Object sender, EventArgs e)
{
ListPicker1.AllowDuplicates = AllowDuplicates.Checked;
}

4. Switch to Design view, double-click AddItem to create an event handler for the Click event, and then add the following
highlighted code:
VB
Protected Sub AddItem_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles AddItem.Click
Dim sourceItem As String = Server.HtmlEncode(NewItem.Text)
ListPicker1.AddSourceItem(sourceItem)
End Sub

C#
protected void AddItem_Click(object sender, EventArgs e)
{
ListPicker1.AddSourceItem(Server.HtmlEncode(NewItem.Text));
}

The code creates a ListItemCollection collection in code and populates it with sample data. Then, the code sets the
SourceItems property to the collection.

5. Switch to Design view, double-click LoadFiles to create an event handler for the Click event, and then add the following
highlighted code:
VB
Protected Sub LoadFiles_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles LoadFiles.Click
Dim path As String = Server.MapPath(Request.ApplicationPath)
Dim files() As String = System.IO.Directory.GetFiles(path)
Dim filename As String
For Each filename in Files
ListPicker1.AddSourceItem(filename)
Next
End Sub

C#
protected void LoadFiles_Click(object sender, EventArgs e)
{
String path = Server.MapPath(Request.ApplicationPath);
String[] files = System.IO.Directory.GetFiles(path);
foreach(String filename in files)
{
ListPicker1.AddSourceItem(filename);
}
}
This code is similar to the code for AddItem, except that this code adds a list of files in the Web site root directory.
6. Switch to Design view, double-click ShowSelection to create an event handler for the Click event, and then add the
following highlighted code:
VB
Protected Sub ShowSelection_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles ShowSelection.Click
Dim lItem As ListItem
Dim selectedItemsString As String = ""
For Each lItem in ListPicker1.SelectedItems
selectedItemsString &= "<br>" & lItem.Text
Next
Selection.Text = selectedItemsString
End Sub

C#
protected void ShowSelection_Click(object sender, EventArgs e)
{
String selectedItemsString = "";
foreach(ListItem lItem in ListPicker1.SelectedItems)
{
selectedItemsString += "<br>" + lItem.Text;
}
Selection.Text = selectedItemsString;
}

This code retrieves an object that is typed as a ListItemCollection object, reads each item in the collection, and then
displays the results in Selection.
7. Switch to Design view, double-click ClearSelection to create an event handler for the Click event, and then add the
following highlighted code:
VB
Protected Sub ClearSelection_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles ClearSelection.Click
ListPicker1.ClearAll()
End Sub

C#
protected void ClearSelection_Click(object sender, EventArgs e)
{
ListPicker1.ClearAll();
}

This code invokes the ClearAll method for the user control to remove all items from the TargetList.
Testing the Finished User Controls
Now, you can test your finished user control.
To test the user control
1. Press CTRL+F5 to run the page.
2. In the text box, type a value, and then click Add Item.
3. Repeat step 2 several times, until you have a selection of items in the user control.
4. Use the buttons to select one or more of the source items from the SourceList list, and then add them to the TargetList
list.
5. Click Show Selection.
The TargetList list items are displayed in Selection.
6. Click Clear All.
7. Click File List.
The SourceList list now displays a list of file names.
8. In the user control, click Add to add several items to the TargetList list.
9. Try adding an item to the TargetList list that is already in the list.
The duplicate value is added.
10. Clear the Allow duplicates box, and then try adding duplicates again.
This time, the duplicates are not added to the TargetList list.
11. Click Show Selection.
The list of items in the TargetList list is displayed in the host page.
Next Steps
Although the control that you have created is not very complex, you have seen much of the basic functionality that you can
build into a user control. Refining the control is largely a matter of revealing additional properties and methods that enhance
what you can do with the control. Additional members might include the following:
Appearance properties.
You can create user control properties that let a user set the background, list size, and so on, for the control.
Note
By default, the user control uses the current theme that applies to the child controls. For example, if you have a skin defi
ned for a Button control, the buttons in your user control are displayed with that skin.

Data properties.
You can add properties that enable the user control to use a wider variety of data to display in the SourceList list. For
example, you could add properties to set a dataset, data table, and data display field.
Functionality.
You can add more buttons and code to the user control to enable users not just to copy items from the SourceList list to
the TargetList list, but also to move items—where the item is removed from the SourceList list as it is moved to the
TargetList list. The control could then have buttons that could move the data back from the TargetList list to the
SourceList list.
See Also
Tasks
How to: Convert Web Forms Pages into ASP.NET User Controls
Concepts
ASP.NET User Controls Overview
Web Application Security Threats Overview (Visual Studio)
Visual Web Developer

How to: Create ASP.NET User Controls (Visual Studio)


You create ASP.NET user controls in much the same way that you design ASP.NET Web pages. You can use the same HTML
elements and controls on a user control that you do on a standard ASP.NET page. However, the user control does not have
html, body, and form elements; and the file name extension must be .ascx.
To create an ASP.NET user control
1. Open the Web site project to which you want to add user controls. If you do not already have a Web site project, you can
create one. For more information, see How to: Create Local IIS Web Sites or How to: Create File System Web Sites.
2. On the Website menu, click Add New Item.
The Add New Item dialog box appears.
3. In the Add New Item dialog box, under Visual Studio installed templates, click Web User Control.
4. In the Name box, type a name for the control.
By default, the .ascx file name extension is appended to the control name that you type.
5. From the Language list, select the programming language that you want to use.
6. Optionally, if you want to keep any code for the user control in a separate file, select the Place code in separate file
check box.
7. Click Add.
The new ASP.NET user control is created and then opened in the designer. The markup for this new control is similar to
the markup for an ASP.NET Web page, except that it contains an @ Control directive instead of an @ Page directive, and
the user control does not have html, body, and form elements.
8. Add any markup and controls to the new user control, and add code for any tasks that the user control will perform, such
as handling control events or reading data from a data source.
For the complete syntax of an example ASP.NET user control, see How to: Create an ASP.NET User Control.

See Also
Tasks
How to: Include ASP.NET User Controls in Web Pages (Visual Studio)
Concepts
ASP.NET User Controls Overview
Visual Web Developer

How to: Include ASP.NET User Controls in Web Pages (Visual


Studio)
Adding an ASP.NET user control to a Web page is similar to adding other server controls to the page. However, you must be
sure to follow the procedure below so that all of the necessary elements are added to the page.
For information about how to create a custom user control, see How to: Create ASP.NET User Controls (Visual Studio).
To add an ASP.NET user control to a Web page
1. In Visual Web Developer, open the Web page to which you want to add the ASP.NET user control.
2. Switch to Design view.
3. Select your custom user control file in Solution Explorer, and drag it onto the page.
The ASP.NET user control is added to the page. In addition, the designer creates the @ Register directive, which is
required for the page to recognize the user control. You can now work with the control's public properties and methods.
See Also
Tasks
How to: Create ASP.NET User Controls (Visual Studio)
How to: Include a User Control in an ASP.NET Web Page
Concepts
ASP.NET User Controls Overview
Visual Web Developer

Learning More — User Controls


The topics in this section provide in-depth information on working with user controls.
In This Section
How to: Convert Web Forms Pages into ASP.NET User Controls
How to: Create Instances of ASP.NET User Controls Programmatically
How to: Create Templated ASP.NET User Controls
See Also
Concepts
Caching Portions of an ASP.NET Page
Other Resources
Individual Web and HTML Controls
ASP.NET Web Server Controls (Visual Studio)
ASP.NET Web Pages (Visual Studio)
ASP.NET

How to: Convert Web Forms Pages into ASP.NET User Controls
If you have developed an ASP.NET Web page and would like to access its functionality throughout your application, you can
make some minor alterations to the page to change it to a user control.
To convert a single-file ASP.NET Web page into a user control
1. Rename the control so the file name extension is .ascx.
2. Remove the html, body, and form elements from the page.
3. Change the @ Page directive to an @ Control directive.
4. Remove all attributes of the @ Control directive except Language, AutoEventWireup (if present), CodeFile, and
Inherits.
5. Include a className attribute in the @ Control directive. This allows the user control to be strongly typed when it is
added to a page.

To convert a code-behind ASP.NET Web page into a user control


1. Rename the .aspx file so the file name extension is .ascx.
2. Rename the code-behind file to have the file name extension .ascx.vb or .ascx.cs, depending on what programming
language the code-behind file is in.
3. Open the code-behind file and change the class from which it inherits from Page to UserControl.
4. In the .aspx file, do the following:
a. Remove the html, body, and form elements from the page.
b. Change the @ Page directive to an @ Control directive.
c. Remove all attributes of the @ Control directive except Language, AutoEventWireup (if present), CodeFile, and
Inherits.
d. In the @ Control directive, change the CodeFile attribute to point to the renamed code-behind file.
5. Include a className attribute in the @ Control directive. This allows the user control to be strongly typed when it is
added to a page.
Example
The following example shows a single-file ASP.NET Web page in its original form and the resulting user control after
converting the page.
Security Note
This example has a text box that accepts user input, which is a potential security threat. By default, ASP.NET Web pages valida
te that user input does not include script or HTML elements. For more information, see Script Exploits Overview.

VB
<%@ Page Language="VB" %>
<html>
<script runat=server>
Sub EnterBtn_Click(sender as Object, e as EventArgs)
Label1.Text = "Hi " & Name.Text & " welcome to ASP.NET!"
End Sub
</script>
<body>
<h3> <u>Web Forms Page</u> </h3>
<form>
Enter Name: <asp:textbox id="Name" runat=server/>
<asp:button Text="Enter" OnClick="EnterBtn_Click"
runat=server/>
<br>
<br>
<asp:label id="Label1" runat=server/>
</form>
</body>
</html>

C#
<%@ Page Language="C#" %>
<html>
<script runat=server>
void EnterBtn_Click(Object sender, EventArgs e)
{
Label1.Text = "Hi " + Name.Text + " welcome to ASP.NET!";
}
</script>
<body>
<h3> <u>Web Forms Page</u> </h3>
<form>
Enter Name: <asp:textbox id="Name" runat=server/>
<asp:button Text="Enter" OnClick="EnterBtn_Click"
runat=server/>
<br>
<br>
<asp:label id="Label1" runat=server/>
</form>
</body>
</html>

VB
<%@ Control Language="VB" ClassName="SampleUserControl" %>
<h3> <u>User Control</u> </h3>
<script runat=server>
Sub EnterBtn_Click(sender as Object, e as EventArgs)
Label1.Text = "Hi " & Name.Text & " welcome to ASP.NET!"
End Sub
</script>
Enter Name: <asp:textbox id="Name" runat=server/>
<asp:button Text="Enter" OnClick="EnterBtn_Click"
runat=server/>
<br>
<br>
<asp:label id="Label1" runat=server/>

C#
<%@ Control Language="C#" ClassName="SampleUserControl" %>
<h3> <u>User Control</u> </h3>
<script runat=server>
void EnterBtn_Click(Object Sender, EventArgs e)
{
Label1.Text = "Hi " + Name.Text + " welcome to ASP.NET!";
}
</script>
Enter Name: <asp:textbox id="Name" runat=server/>
<asp:button Text="Enter" OnClick="EnterBtn_Click"
runat=server/>
<br>
<br>
<asp:label id="Label1" runat=server/>

See Also
Tasks
How to: Create an ASP.NET User Control
Concepts
ASP.NET User Controls Overview
ASP.NET

How to: Create Instances of ASP.NET User Controls


Programmatically
Just as you can programmatically create an instance of any server control on an ASP.NET Web page, you can do the same with
a user control.
To create an instance of a user control programmatically
1. In the user control, be sure that the @ Control directive contains a ClassName attribute that assigns a class to the user
control.
The following example sets the ClassName attribute to strongly type a user control.

<%@ Control className="MyUserControl" %>

2. In the page where you want to work with the user control, create a reference to the user control with the @ Reference
directive.
When you create the user control programmatically, the strong type for your user control is available to the ASP.NET
Web page only after you have created a reference to it. For example, the following code creates a reference to a user
control created in the MyUserControl.ascx file.

<%@ Reference Control="MyUserControl.ascx" %>

Note
You use the @ Reference when you intend to load the control programmatically. You use the @ Register directive whe
n you add a user control to the page declaratively. For details, see
How to: Include a User Control in an ASP.NET Web Page.

3. Create an instance variable for the user control, using the control's class name. The class will be part of the ASP
namespace.
For example, if you want to create an instance of the user control declared as class Spinner, you use syntax such as the
following:
VB
Protected Spinner1 As ASP.Spinner

C#
Protected ASP.Spinner Spinner1;

4. Create an instance of the user control in code by calling the LoadControl method.
5. Assign property values as necessary, and then add the control to the ControlCollection collection of a container on the
page, such as a PlaceHolder control.
Note
When you add controls to the ControlCollection object using the Add method, they are placed in the collection in the
order they are processed. If you want to add a control to a specific position in the collection, use the AddAt method and
specify the index location where you want to store the control.

Example
The following example shows an ASP.NET Web page that loads a user control programmatically. The page includes an
@ Reference directive to specify the control's file. The LoadControl method reads the file and instantiates it as a control that
can be added to the page.
VB
<%@ Page Language="VB" %>
<%@ Reference Control="~\Controls\Spinner.ascx" %>

<script runat="server">
Private Spinner1 As ASP.Spinner
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs)
Spinner1 = CType(LoadControl("~\Controls\Spinner.ascx"), _
ASP.Spinner)
' Set MaxValue first.
Spinner1.MaxValue = 20
Spinner1.MinValue = 10
PlaceHolder1.Controls.Add(Spinner1)
End Sub

Protected Sub Button1_Click(ByVal sender As Object, _


ByVal e As System.EventArgs)
Label1.Text = Spinner1.CurrentNumber.ToString()
End Sub
</script>
<html>
<head id="Head1" runat="server">
<title>Load User Control Programmatically</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:PlaceHolder runat=server ID="PlaceHolder1" />
<br />
<asp:Button ID="Button1" runat="server"
Text="Button"
OnClick="Button1_Click" />
<br />
<br />
<asp:Label ID="Label1" runat="server" Text=""></asp:Label>
</div>
</form>
</body>
</html>

C#
<%@ Page Language="C#" %>
<%@ Reference Control="~/Controls/Spinner.ascx" %>
<script runat="server">
private ASP.Spinner Spinner1;
protected void Page_Load(object sender, EventArgs e)
{
Spinner1 = (ASP.Spinner)LoadControl("~/Controls/Spinner.ascx");
// Set MaxValue first.
Spinner1.MaxValue = 20;
Spinner1.MinValue = 10;
PlaceHolder1.Controls.Add(Spinner1);
}

protected void Button1_Click(object sender, EventArgs e)


{
Label1.Text = Spinner1.CurrentNumber.ToString();
}
</script>
<html>
<head id="Head1" runat="server">
<title>Load User Control Programmatically</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:PlaceHolder runat=server ID="PlaceHolder1" />
<br />
<asp:Button ID="Button1" runat="server"
Text="Button"
OnClick="Button1_Click" />
<br />
<br />
<asp:Label ID="Label1" runat="server" Text=""></asp:Label>
</div>
</form>
</body>
</html>

See Also
Concepts
ASP.NET User Controls Overview
ASP.NET

How to: Create Templated ASP.NET User Controls


You can create user controls that implement templates, an ASP.NET feature that allows the separation of control data from its
presentation. A templated control does not provide a user interface. Instead, it is written to implement a naming container and
to include a class whose properties and methods are accessible to the host page.
The user interface for the user control is supplied by a page developer at design time. The developer creates templates of the
type defined by the user control, and can then add controls and markup to the templates.
To create a templated user control
1. In the .ascx file, add an ASP.NET PlaceHolder control where you want the template to appear.
2. In the user control's code, implement a property of type ITemplate.
3. Define a server control class that implements the INamingContainer interface as a container in which to create an
instance of the template. This is called the template's naming container.
Note
This control essentially becomes a nested class of the user control, though this is not required.

4. Apply the TemplateContainerAttribute to the property that implements ITemplate and pass the type of the template's
naming container as the argument to the attribute's constructor.
5. In the control's Init method, repeat the following steps one or more times:
Create an instance of the naming container class.
Create an instance of the template in the naming container.
Add the naming container instance to the Controls property of the PlaceHolder server control.
Note
From the point of view of the page using the user control, the syntax for the templated user control is identical to
what it would be with a custom templated control.

Example
The following example shows a templated user control and a page that contains it. The user control creates a template that can
be declared on a host page as <MessageTemplate>. The template control also exposes two properties, Index and Message, that
the host page can access inside the template.
The first sample shows the templated user control. The second sample shows a page that contains the user control.
VB
<%@ Control language="VB" ClassName="TemplatedUC" %>
<script runat="server" >
Private m_messageTemplate As ITemplate = Nothing
<TemplateContainer(GetType(MessageContainer))> Public Property _
MessageTemplate() As ITemplate
Get
Return m_messageTemplate
End Get
Set(ByVal value As ITemplate)
m_messageTemplate = Value
End Set
End Property

Sub Page_Init()
If Not (MessageTemplate Is Nothing) Then
Dim i As Integer
Dim fruits() As String = _
{"apple", "orange", "banana", "pineapple"}
For i = 0 To 3
Dim container As New MessageContainer(i, fruits(i))
MessageTemplate.InstantiateIn(container)
PlaceHolder1.Controls.Add(container)
Next i
End If
End Sub
Public Class MessageContainer
Inherits Control
Implements INamingContainer
Private m_index As Integer
Private m_message As String
Friend Sub New(ByVal i As Integer, ByVal msg As String)
Me.Index = i
Me.Message = msg
End Sub

Public Property Index() As Integer


Get
Return m_index
End Get
Set(ByVal value As Integer)
m_index = value
End Set
End Property
Public Property Message() As String
Get
Return m_message
End Get
Set(ByVal value As String)
m_message = value
End Set
End Property
End Class
</script>
<asp:placeholder runat=server id="PlaceHolder1" />

C#
<%@ Control language="C#" ClassName="TemplatedUC" %>
<script runat=server>
private ITemplate messageTemplate = null;

[ TemplateContainer(typeof(MessageContainer)) ]
public ITemplate MessageTemplate {
get
{
return messageTemplate;
}
set
{
messageTemplate = value;
}
}

void Page_Init() {
if (messageTemplate != null) {
String[] fruits = {"apple", "orange", "banana", "pineapple" };
for (int i=0; i<4; i++)
{
MessageContainer container = new MessageContainer(i, fruits[i]);
messageTemplate.InstantiateIn(container);
PlaceHolder1.Controls.Add(container);
}
}
}

public class MessageContainer: Control, INamingContainer {


private int m_index;
private String m_message;
internal MessageContainer(int index, String message)
{
m_index = index;
m_message = message;
}
public int Index {
get
{
return m_index;
}
}
public String Message
{
get
{
return m_message;
}
}
}
</script>
<asp:placeholder runat=server id="PlaceHolder1" />

VB
<%@ Page Language="VB" %>
<%@ Register TagPrefix="uc" tagname="TemplateTest"
Src="TemplatedUC.ascx" %>
<html>
<script runat=server>
Sub Page_Load()
DataBind()
End Sub
</script>
<head>
<title>Templated User Control Test</title>
</head>
<body>
<h1>Testing Templated User Control</h1>
<form id="Form1" runat=server>
<uc:TemplateTest runat=server>
<MessageTemplate>
Index: <asp:Label runat="server" ID="Label1"
Text='<%# Container.Index %>' />
<br />
Message: <asp:Label runat="server" ID="Label2"
Text='<%# Container.Message %>' />
<hr />
</MessageTemplate>
</uc:TemplateTest>
</form>
</body>
</html>

C#
<%@ Page Language="C#" %>
<%@ Register TagPrefix="uc" tagname="TemplateTest"
Src="TemplatedUC.ascx" %>
<html>
<script runat=server>
protected void Page_Load()
{
DataBind();
}

</script>
<head>
<title>Templated User Control Test</title>
</head>
<body>
<h1>Testing Templated User Control</h1>
<form id="Form1" runat=server>
<uc:TemplateTest runat=server>
<MessageTemplate>
Index: <asp:Label runat="server" ID="Label1"
Text='<%# Container.Index %>' />
<br />
Message: <asp:Label runat="server" ID="Label2"
Text='<%# Container.Message %>' />
<hr />
</MessageTemplate>
</uc:TemplateTest>
</form>
</body>
</html>

See Also
Concepts
ASP.NET User Controls Overview
Visual Web Developer

Walkthrough Topics — ASP.NET User Controls


This following walkthrough topic describes how to create ASP.NET Web user controls, which enable you to partition and reuse
common user interface (UI) functionality across your ASP.NET Web applications.
Walkthrough Topics
Walkthrough: Creating Reusable Elements with ASP.NET User Controls
See Also
Other Resources
ASP.NET Web User Controls (Visual Studio)
Visual Web Developer

How-to Topics — ASP.NET User Controls


The following procedures describe how to create ASP.NET Web user controls, which enable you to partition and reuse common
user interface (UI) functionality across your ASP.NET Web applications.
How-to Topics
How to: Create ASP.NET User Controls (Visual Studio)
How to: Include ASP.NET User Controls in Web Pages (Visual Studio)
How to: Convert Web Forms Pages into ASP.NET User Controls
How to: Create Instances of ASP.NET User Controls Programmatically
How to: Create Templated ASP.NET User Controls
See Also
Other Resources
ASP.NET Web User Controls (Visual Studio)
ASP.NET

Web Parts ASP.NET Web Server Controls


This section contains topics that describe the ASP.NET server controls you can use to display Web Parts on a Web page.
For complete syntax information for Web server controls, see Web Server Control Syntax.
In This Section
AppearanceEditorPart Web Server Control
BehaviorEditorPart Web Server Control
CatalogZone Web Server Control
ConnectionsZone Web Server Control
DeclarativeCatalogPart Web Server Control
EditorZone Web Server Control
ImportCatalogPart Web Server Control
LayoutEditorPart Web Server Control
PageCatalogPart Web Server Control
PropertyGridEditorPart Web Server Control
ProxyWebPartManager Web Server Control
ProxyWebPartManager Web Server Control
WebPartZone Web Server Control
Related Sections
ASP.NET Web Server Controls Overview
Provides general information on working with ASP.NET Web server controls.
Individual ASP.NET Web Server Controls
Provides information on other Web server controls.
Web Server Control Syntax
Provides syntax information for most Web server controls.
Walkthrough: Creating a Web Parts Page
Provides a guided walkthrough to create a Web Parts page.
ASP.NET

AppearanceEditorPart Web Server Control


The AppearanceEditorPart Web server control provides an editor control that enables end users to edit several user interface
(UI) properties on an associated WebPart control.
In This Section
AppearanceEditorPart Web Server Control Overview
Provides a general overview of the AppearanceEditorPart Web server control.
Reference
System.Web.UI.WebControls.WebParts.AppearanceEditorPart
Provides the class definition of the AppearanceEditorPart Web server control.
AppearanceEditorPart Web Server Control Declarative Syntax
Provides the declarative syntax for the AppearanceEditorPart Web server control.
Related Sections
ASP.NET Web Server Controls Overview
Provides general information on working with ASP.NET Web server controls.
Individual ASP.NET Web Server Controls
Provides information on other Web server controls.
See Also
Reference
AppearanceEditorPart
System.Web.UI.WebControls.WebParts
BehaviorEditorPart
LayoutEditorPart
PropertyGridEditorPart
AppearanceEditorPart Web Server Control Overview
The AppearanceEditorPart control enables end users to edit several UI properties of a WebPart control.
The following table lists user customizable features and corresponding WebPart control property values that are editable
using the AppearanceEditorPart control.
User Customizable Feature WebPart Control Property
Set the text for the title. Title

Select the title and border option type. ChromeType

Select the direction that content flows on the page. Direction

Set the height and units. Height

Set the width and units. Width

Hide or show the control is hidden. Hidden

To edit other properties and the behavior of WebPart controls, you can use the other EditorPart controls supplied with the
Web Parts control set. These controls include the BehaviorEditorPart, the LayoutEditorPart, and the PropertyGridEditorPart
controls. The built-in EditorPart controls provide commonly used editing features for WebPart controls. However, you can
also create a custom editor control by inheriting from the EditorPart class. For a code example, see
System.Web.UI.WebControls.WebParts.EditorPart.
Enabling an AppearanceEditorPart Control
The AppearanceEditorPart control is displayed only when a Web Parts page is in edit mode and when the user has selected
an associated WebPart control for editing. For more information, see
Walkthrough: Changing Display Modes on a Web Parts Page.
See Also
Reference
AppearanceEditorPart
System.Web.UI.WebControls.WebParts
BehaviorEditorPart
LayoutEditorPart
PropertyGridEditorPart
ASP.NET

BehaviorEditorPart Web Server Control


The BehaviorEditorPart control provides an editor control that enables end users to edit properties that affect the behavior of
an associated WebPart or GenericWebPart control.
In This Section
BehaviorEditorPart Web Server Control Overview
Provides a general overview of the BehaviorEditorPart Web server control.
Reference
System.Web.UI.WebControls.WebParts.BehaviorEditorPart
Provides the class definition of the BehaviorEditorPart Web server control.
BehaviorEditorPart Web Server Control Declarative Syntax
Provides the declarative syntax for the BehaviorEditorPart Web server control.
Related Sections
ASP.NET Web Server Controls Overview
Provides general information on working with ASP.NET Web server controls.
Individual ASP.NET Web Server Controls
Provides information on other Web server controls.
See Also
Reference
System.Web.UI.WebControls.WebParts
AppearanceEditorPart
BehaviorEditorPart
LayoutEditorPart
PropertyGridEditorPart
BehaviorEditorPart Web Server Control Overview
The BehaviorEditorPart Web server control is an editor part control that enables end users to edit several user interface (UI)
properties on an associated WebPart control at run time.
The following table lists user customizable features and corresponding WebPart control property values that are editable
using the BehaviorEditorPart control.
User Customizable Feature WebPart Control Property
Set the description text of the Web Part. Description

Set the Title Link. TitleUrl

Setting the Title Icon Image link. TitleIconImageUrl

Setting the Catalog Icon Image link. CatalogIconImageUrl

Set the Help Link. HelpUrl

Specify whether the control is hidden. Hidden

Specify the Help Mode. HelpMode

Select the Export Mode. ExportMode

Set the Authorization Filter. AuthorizationFilter

Specify whether a Web part can be removed from the page. AllowClose

Specify whether a Web part's properties can be edited. AllowEdit

Specify whether a Web part can be hidden. AllowHide

Specify whether a Web part can be minimized. AllowMinimize

Specify whether a Web part can be moved between zones or only within its own zone. AllowZoneChange

Enabling a BehaviorEditorPart Web Server Control


The BehaviorEditorPart control is displayed at run time when a Web Parts page is in edit mode, and when the user has
selected an associated WebPart control for editing. The BehaviorEditorPart control resides in an EditorZone control.
Note
An EditorZone zone can contain only EditorPart controls. EditorPart controls cannot be placed in any other type of zone.

The BehaviorEditorPart control is not displayed on the page under the following conditions:
The IsShared property value of the WebPart control being edited is true.
The page is in user personalization scope (which is the default).
For the BehaviorEditorPart control to be displayed, you must do the following:
Add an entry to the Web.config file that gives an authorized user permission to edit Web pages in shared personalization
scope, which means that the user's changes are visible to all other users. For more information about enabling shared
personalization of Web Parts page, see How to: Enable Shared Personalization of Web Parts Pages.
Programmatically change the page from user-level to shared-level personalization scope at run time. For example, you
can scope by calling the ToggleScope method.
For an example of how to make the BehaviorEditorPart control visible in a page, see the BehaviorEditorPart. For more
information about shared controls and personalization scope, see Web Parts Personalization Overview.
See Also
Reference
AppearanceEditorPart
System.Web.UI.WebControls.WebParts
BehaviorEditorPart
LayoutEditorPart
PropertyGridEditorPart
ASP.NET

CatalogZone Web Server Control


The CatalogZone control serves as the primary control in the Web Parts control set for hosting CatalogPart controls on a Web
page.
In This Section
CatalogZone Web Server Control Overview
Provides a general overview of the CatalogZone Web server control.
Reference
CatalogZone
Provides the class definition of the CatalogZone Web server control.
CatalogZone Web Server Control Declarative Syntax
Provides the declarative syntax for the CatalogZone Web server control.
Related Sections
ASP.NET Web Server Controls Overview
Provides general information on working with ASP.NET Web server controls.
Individual ASP.NET Web Server Controls
Provides information on other Web server controls.
See Also
Reference
CatalogZone
System.Web.UI.WebControls.WebParts
Other Resources
DeclarativeCatalogPart Web Server Control
PageCatalogPart Web Server Control
ImportCatalogPart Web Server Control
CatalogZone Web Server Control Overview
A key feature of Web Parts controls such as the CatalogZone control is that they allow end users to personalize Web pages and
save their personalized settings. The CatalogZone control allows end users to add WebPart controls or other server controls
to a Web Parts page at run time. The CatalogZone control serves as the primary control in the Web Parts control set for
hosting CatalogPart controls on a Web page.
Enabling a CatalogZone Web Server Control
A CatalogZone control becomes visible only when a user switches a Web page to catalog-display mode
(CatalogDisplayMode). For code examples demonstrating how to use the CatalogZone control, see the examples in
CatalogZone Web Server Control Declarative Syntax and System.Web.UI.WebControls.WebParts.CatalogZone.
CatalogPart Controls Provided With the CatalogZone Web Server Control
A zone created by a CatalogZone control can contain several types of CatalogPart controls. Each CatalogPart control is a
type of container for server controls that users can add to the page. The CatalogPart controls differ according to where the
server controls they contain are coming from.
For a summary of CatalogPart controls, see the System.Web.UI.WebControls.WebParts.CatalogZone class overview.
See Also
Reference
Web Parts Control Set Overview
CatalogZone
System.Web.UI.WebControls.WebParts.WebZone
System.Web.UI.WebControls.WebParts
Other Resources
ASP.NET Web Parts Pages
DeclarativeCatalogPart Web Server Control
PageCatalogPart Web Server Control
ImportCatalogPart Web Server Control
ASP.NET

ConnectionsZone Web Server Control


The ConnectionsZone Web server control provides a user interface (UI) that enables users to form connections between
WebPart and other server controls that reside in WebPartZoneBase zones.
In This Section
ConnectionsZone Web Server Control Overview
Provides a general overview of the ConnectionsZone Web server control.
Reference
ConnectionsZone
Provides the class definition of the ConnectionsZone Web server control.
ConnectionsZone Web Server Control Declarative Syntax
Provides the declarative syntax for the ConnectionsZone Web server control.
Related Sections
ASP.NET Web Server Controls Overview
Provides general information on working with ASP.NET Web server controls.
Individual ASP.NET Web Server Controls
Provides information on other Web server controls.
See Also
Reference
System.Web.UI.WebControls.WebParts
AppearanceEditorPart
BehaviorEditorPart
LayoutEditorPart
PropertyGridEditorPart
ConnectionsZone Web Server Control Overview
Using Web Parts controls, you can enable users to create connections at runtime between two server controls to form a
connection and share data, with one control acting as the provider of data and the other acting as the consumer. The two
controls can be WebPart controls or any other type of server control, as long as they are designed to handle connections and
that they are in a WebPartZoneBase zone. To learn more about Web Parts connections, see the WebPartConnection and
ConnectionPoint class overviews, as well as Web Parts Connections Overview.
Once the controls and conditions exist to form a Web Parts connection, it is still necessary to connect the controls. You can
connect controls in these ways:
Declaring a connection in a Web page.
Creating a connection in code.
Adding a ConnectionsZone control to the page so that users can connect the controls on demand.
The ConnectionsZone control generates a UI that enables users to connect or disconnect any eligible controls. It is an
optional control that is not necessary to form connections, but is useful when you want to give users control over which server
controls are connected or disconnected.
Web Part Control Properties Controlled through a ConnectionsZone Control
The user interface provided by the ConnectionsZone control allows users to set the ConnectionPoint object associated with
a designated consumer control and a designated provider control. For a code example demonstrating how to use the
ConnectionsZone control, see the "Example" section of the ConnectionsZone class overview.
Enabling a ConnectionsZone Control
As a tool zone, the ConnectionsZone control is designed to be visible only when the Web page is in connect mode (when the
WebPartManager control on the page has its DisplayMode property value set to ConnectDisplayMode). After users switch a
page into connect mode, they must click a connect verb of one of the server controls to display the connection UI.
For more information on changing display modes on a Web Parts page, see
Walkthrough: Changing Display Modes on a Web Parts Page.
See Also
Reference
WebZone
WebPartConnection
ConnectionPoint
WebPartZoneBase
Concepts
Web Parts Connections Overview
Other Resources
ASP.NET Web Parts Pages
ASP.NET

DeclarativeCatalogPart Web Server Control


The DeclarativeCatalogPart control enables you to add a catalog of WebPart or other server controls to a Web page using
declarative syntax.
In This Section
DeclarativeCatalogPart
Provides a general overview of the DeclarativeCatalogPart Web server control.
Reference
DeclarativeCatalogPart
Provides the class definition of the DeclarativeCatalogPart Web server control.
DeclarativeCatalogPart Web Server Control Declarative Syntax
Provides the declarative syntax for the DeclarativeCatalogPart Web server control.
Related Sections
ASP.NET Web Server Controls Overview
Provides general information on working with ASP.NET Web server controls.
Individual ASP.NET Web Server Controls
Provides information on other Web server controls.
See Also
Reference
CatalogZone
System.Web.UI.WebControls.WebParts
Other Resources
DeclarativeCatalogPart Web Server Control
PageCatalogPart Web Server Control
ImportCatalogPart Web Server Control
DeclarativeCatalogPart Web Server Control Overview
The DeclarativeCatalogPart control enables you to add a catalog of WebPart or other server controls to a Web page, giving
users the ability to change the set of controls and the functionality available on a page at run time. A catalog is a list of
WebPart or other server controls that is visible when a page is in catalog-display mode. At design time you can add controls
to the DeclarativeCatalogPart control and at run time a user can choose which controls to view in the page by selecting
them from the catalog list. For more information, see ASP.NET Web Parts Pages.
Note
The DeclarativeCatalogPart control adds a new instance of a control to the Web page when a user selects a control from it
s catalog at run time. Users can add multiple instances of the same control in a catalog to a Web page.

Enabling a DeclarativeCatalogPart Web Server Control


You must put the DeclarativeCatalogPart in a CatalogZoneBase zone, such as the CatalogZone zone. The
DeclarativeCatalogPart control becomes visible only when a Web page is in catalog display mode.
For code examples demonstrating how to use the CatalogZone control, see the "Example" section in
CatalogZone Web Server Control Declarative Syntaxand CatalogZone.
Creating a Application-wide Catalog of Controls
The DeclarativeCatalogPart enables you to set up a catalog of controls that can be used throughout an entire site. Rather
than declare individual server controls in a DeclarativeCatalogPart control, you can set the WebPartsListUserControlPath
property to the path of a user control that contains the list of server controls in the catalog. At run time, the server controls
referenced in the user control are loaded in the catalog. This strategy enables multiple pages or sites to reference the same
user control to create a catalog. When the list of server controls in user control is updated, all catalogs based on the user
control are updated.
For a code example demonstrating how to use the WebPartsListUserControlPath property, see the "Example" section in
WebPartsListUserControlPath.
See Also
Reference
DeclarativeCatalogPart
CatalogZone
System.Web.UI.WebControls.WebParts
Other Resources
ASP.NET Web Parts Pages
DeclarativeCatalogPart Web Server Control
PageCatalogPart Web Server Control
ImportCatalogPart Web Server Control
ASP.NET

EditorZone Web Server Control


The EditorZone Web Server control serves as the primary control in the Web Parts control set for hosting EditorPart controls
on a Web page.
In This Section
EditorZone Web Server Control Overview
Provides a general overview of the EditorZone Web server control.
Reference
EditorZone
Provides the class definition of the EditorZone Web server control.
EditorZone Web Server Control Declarative Syntax
Provides the declarative syntax for the EditorZone Web server control.
Related Sections
ASP.NET Web Server Controls Overview
Provides general information on working with ASP.NET Web server controls.
Individual ASP.NET Web Server Controls
Provides information on other Web server controls.
See Also
Reference
System.Web.UI.WebControls.WebParts
AppearanceEditorPart
BehaviorEditorPart
LayoutEditorPart
PropertyGridEditorPart
EditorZone Web Server Control Overview
A key feature of Web Parts is the ability of end users to personalize Web pages and save their personalized settings. One
aspect of modifying Web Parts pages includes editing the appearance, layout, behavior, and other properties of the visible
WebPart controls.
Several controls in the Web Parts control set provide the editing features, including the EditorZone control, which is the
primary control in the Web Parts control set for hosting EditorPart controls on a Web page.
The following table provides a list of EditorPart controls the EditorZone can host and a description of each.
EditorPart Control Description
AppearanceEditorPart Provides an interface that enables users to customize the visual properties of a WebPart control at run
time, such as the width, height and title.
For more information, see AppearanceEditorPart Web Server Control.

BehaviorEditorPart Provides an interface that enables users to customize behavior properties of a WebPart control at run
time, such as the display of the minimize, close, and edit buttons.
For more information, see BehaviorEditorPart Web Server Control.

LayoutEditorPart Provides an interface that enables users to customize layout properties of a WebPart control at run ti
me, such as selecting between a minimized and normal state, or setting the index at which the control
will appear within the target zone.
For more information, see LayoutEditorPart Web Server Control.

PropertyGridEditorPart Provides an interface that enables users to edit custom properties at run time that are declared as part
of a WebPart control.
For more information, see PropertyGridEditorPart Web Server Control

An EditorZone control becomes visible when a user puts a Web Parts page into edit mode.
For more details about display modes, see Walkthrough: Changing Display Modes on a Web Parts Page.
The EditorZone Web server control is a zone control. For more information about zones and how they are used in Web Parts
applications, see, Walkthrough: Creating a Web Parts Page, the reference documentation for the base WebZone class and
Web Parts Control Set Overview.
For a code example demonstrating the EditorZone class, see the Example section of EditorZone.
See Also
Reference
Web Parts Control Set Overview
EditorPart
EditorZone
Concepts
Web Parts Personalization Overview
Other Resources
ASP.NET Web Parts Pages
ASP.NET

ImportCatalogPart Web Server Control


The ImportCatalogPart Web server control imports a description file for a WebPart control (or other ASP.NET server control
that is used as a WebPart control), so that the control can be added to a Web page with pre-assigned settings. The description
file enables users to share settings for WebPart controls.
In This Section
ImportCatalogPart Web Server Control Overview
Provides a general overview of the ImportCatalogPart Web server control.
Reference
ImportCatalogPart
Provides the class definition of the ImportCatalogPart Web server control.
ImportCatalogPart Web Server Control Declarative Syntax
Provides the declarative syntax for the ImportCatalogPart Web server control.
Related Sections
ASP.NET Web Server Controls Overview
Provides general information on working with ASP.NET Web server controls.
Individual ASP.NET Web Server Controls
Provides information on other Web server controls.
See Also
Reference
CatalogZone
System.Web.UI.WebControls.WebParts
Other Resources
DeclarativeCatalogPart Web Server Control
PageCatalogPart Web Server Control
ImportCatalogPart Web Server Control Overview
The ImportCatalogPart Web server control imports a description file for a WebPart control (or other ASP.NET server control
that is used as a WebPart control), so that the control can be added by a user during runtime with pre-assigned settings to a
Web page. The description file enables users to share settings for WebPart controls.
The description file is not the same as the control itself. It is an XML file that ends with a .WebPart extension that contains
name/value pairs that describe the state of the control. The description file uses a specific XML format, as described in the topic
Web Parts Control Description Files. In addition to describing the control' state, the description file references the control name
and the assembly (or file) that contains the control.
After a user imports a description file, the WebPart control referenced in the file appears within the ImportCatalogPart
control and a user can add the control to the page.
Associating Web Parts controls with ImportCatalogPart Web Server Control
A Web Parts control associated with a ImportCatalogPart control can be compiled into an assembly or it can be a user
control (.ascx file). In either case, the control referenced in an imported description file must exist on the Web server containing
the hosting page.
Users import a description file (and its associated server control) into a Web page using the ImportCatalogPart control, which
you must already have added to the page. When a user switches the page to catalog display mode, the ImportCatalogPart
control appears and users can browse to the control's .WebPart description file and then import the control. The control's
appearance and properties are specified in the imported description file.
Before importing a WebPart control description file, users must first create (export) the file based on an existing WebPart
control. A description file can be exported for a control if the following conditions are met:
The control has properties marked with the Personalizable attribute.
The Web.config file has the enableExport attribute value set to true in the <webParts> element.
You have set the value of the ExportMode property on the control to a value other than the default value of None, which
prohibits export.
Enabling an ImportCatalogPart Web Server Control
The ImportCatalogPart Web server control is displayed at run time when a Web Parts page is in edit mode, and when the
user has selected an associated WebPart control for editing. For more information, see
Walkthrough: Changing Display Modes on a Web Parts Page.
For a code example demonstrating the use of the ImportCatalogPart Web server control, see the "Example" section of
ImportCatalogPart.
See Also
Reference
ImportCatalogPart Web Server Control Declarative Syntax
Web Parts Control Description Files
DeclarativeCatalogPart
CatalogZone
System.Web.UI.WebControls.WebParts
Other Resources
ImportCatalogPart Web Server Control
ASP.NET Web Parts Pages
DeclarativeCatalogPart Web Server Control
PageCatalogPart Web Server Control
ASP.NET

LayoutEditorPart Web Server Control


Provides an editor control that enables users to edit several layout-oriented user interface (UI) properties on an associated
WebPart control.
In This Section
LayoutEditorPart Web Server Control Overview
Provides a general overview of the LayoutEditorPart Web server control.
Reference
LayoutEditorPart
Provides the class definition of the LayoutEditorPart Web server control.
LayoutEditorPart Web Server Control Declarative Syntax
Provides the declarative syntax for the LayoutEditorPart Web server control.
Related Sections
ASP.NET Web Server Controls Overview
Provides general information on working with ASP.NET Web server controls.
Individual ASP.NET Web Server Controls
Provides information on other Web server controls.
See Also
Reference
System.Web.UI.WebControls.WebParts
AppearanceEditorPart
BehaviorEditorPart
PropertyGridEditorPart
LayoutEditorPart Web Server Control Overview
The LayoutEditorPart control enables users to edit several layout-oriented user interface (UI) properties on an associated
WebPart control.
Editor User Interfaces Provided by the LayoutEditorPart
The following table lists user customizable features and corresponding WebPart control property values that are editable
using the AppearanceEditorPart control.
User Customizable Feature WebPart Control Property
Toggle between minimized and normal state for a WebPart control. ChromeState

Set the WebPartZoneBase zone that currently contains a WebPart control. Zone

Set the index position of a WebPart control within its zone. ZoneIndex

To edit other properties and the behavior of WebPart controls, you can use the other EditorPart controls supplied with the
Web Parts control set. These controls include the BehaviorEditorPart, the LayoutEditorPart, and the PropertyGridEditorPart.
The built-in EditorPart controls provide the most commonly used features for editing WebPart controls. However, you can
also create a custom editor control by inheriting from the EditorPart class. For a code example, see
System.Web.UI.WebControls.WebParts.EditorPart.
Enabling a LayoutEditorPart Control
The LayoutEditorPart control is displayed only when a Web Parts page is in edit mode and when the user has selected an
associated WebPart control for editing. For more information, see
Walkthrough: Changing Display Modes on a Web Parts Page.
See Also
Reference
AppearanceEditorPart
System.Web.UI.WebControls.WebParts
BehaviorEditorPart
LayoutEditorPart
PropertyGridEditorPart
ASP.NET

PageCatalogPart Web Server Control


The PageCatalogPart Web server control provides a catalog that keeps references to all WebPart controls (and other server
controls that are contained in WebPartZoneBase zones) that a user has closed on a single Web Parts page. The user interface
provided by the PageCatalogPart control enables the user to add the closed controls back to the page at run time.
In This Section
PageCatalogPart Web Server Control Overview
Provides a general overview of the ImportCatalogPart Web server control.
Reference
PageCatalogPart
Provides the class definition of the PageCatalogPart Web server control.
PageCatalogPart Web Server Control Declarative Syntax
Provides the declarative syntax for the PageCatalogPart Web server control.
Related Sections
ASP.NET Web Server Controls Overview
Provides general information on working with ASP.NET Web server controls.
Individual ASP.NET Web Server Controls
Provides information on other Web server controls.
See Also
Reference
CatalogZone
System.Web.UI.WebControls.WebParts
Other Resources
DeclarativeCatalogPart Web Server Control
PageCatalogPart Web Server Control Overview
The PageCatalogPart class acts as a page catalog to maintain any controls previously added to the page that a user has closed,
so that the user can add them back to the page. This control is visible only when a Web page is in catalog display mode, a
special view that enables users to add and remove controls on the page. Only closed controls are added to the page catalog.
Add a PageCatalogPart control to your page if you want to provide users with the flexibility of closing and reopening
controls.
Note
If your page does not allow users to close controls, there is no need to add a PageCatalogPart control to the page.

For more information, see ASP.NET Web Parts Pages.


About Closed Controls
Users can close controls on a Web Parts page. A closed control has the following characteristics:
It is not visible on the page.
It is not rendered on the page.
It does not participate in page life-cycle phases.
Closing a control is different from deleting it, which permanently removes it from the page. A user can reopen a closed control
instance from a page catalog, but after a user deletes a control, he or she can never recover that instance of the control.
See Also
Reference
DeclarativeCatalogPart
CatalogZone
System.Web.UI.WebControls.WebParts
Other Resources
ASP.NET Web Parts Pages
DeclarativeCatalogPart Web Server Control
PageCatalogPart Web Server Control
ImportCatalogPart Web Server Control
ASP.NET

PropertyGridEditorPart Web Server Control


The PropertyGridEditorPart Web Server control provides an editor control that enables end users to edit custom properties on
an associated WebPart or server control.
In This Section
PropertyGridEditorPart Web Server Control Overview
Provides a general overview of the PropertyGridEditorPart Web Server control.
Reference
PropertyGridEditorPart
Provides the class definition of the PropertyGridEditorPart Web server control.
PropertyGridEditorPart Web Server Control Declarative Syntax
Provides the declarative syntax for the PropertyGridEditorPart Web Server control.
Related Sections
ASP.NET Web Server Controls Overview
Provides general information on working with ASP.NET Web server controls.
Individual ASP.NET Web Server Controls
Provides information on other Web server controls.
See Also
Reference
System.Web.UI.WebControls.WebParts
AppearanceEditorPart
BehaviorEditorPart
LayoutEditorPart
PropertyGridEditorPart
PropertyGridEditorPart Web Server Control Overview
The PropertyGridEditorPart provides a generic user interface (UI) that enables users to edit custom properties on WebPart
controls and on server controls in WebPartZoneBase zones.
The PropertyGridEditorPart control's ability to enable users to edit custom properties sets it apart from other EditorPart
controls, such as the AppearanceEditorPart and BehaviorEditorPart controls, that edit only existing, UI-oriented properties from
the WebPart class. For more information, see ASP.NET Web Parts Pages.
Declaring Properties Customizable Through the PropertyGridEditorPart Control
The PropertyGridEditorPart enables users to edit properties marked in the source code with the WebBrowsableAttribute.
When a property is marked with the WebBrowsable attribute, the PropertyGridEditorPart control creates the editing UI
based on the type of the property, and uses a PropertyDescriptor object if needed to convert the value in each editing control
to the property's type.
For an example of marking a property with the WebBrowsable attribute, see the example section of PropertyGridEditorPart.
For an example demonstrating how to use a PropertyGridEditorPart control, see
PropertyGridEditorPart Web Server Control Declarative Syntax and
System.Web.UI.WebControls.WebParts.PropertyGridEditorPart.
Attributes That Assist the PropertyGridEditorPart Control Editing UI
When creating customizable properties, you can add attributes that help the PropertyGridEditorPart control to display the
editing UI. Set the WebDisplayNameAttribute to specify the text displayed in the editing UI for each control. Set the
WebDescriptionAttribute to a string that appears as a tooltip for each control in the editing UI.
See Also
Reference
System.Web.UI.WebControls.WebParts
AppearanceEditorPart
BehaviorEditorPart
LayoutEditorPart
PropertyGridEditorPart
ASP.NET

ProxyWebPartManager Web Server Control


Provides a way for you to declare static connections in a content page when a WebPartManager control has been declared in
the content page's associated master page.
In This Section
ProxyWebPartManager Web Server Control Overview
Provides an overview of the ProxyWebPartManager Web server control.
Reference
ProxyWebPartManager
Provides the class definition of the ProxyWebPartManager Web server control.
ProxyWebPartManager Web Server Control Declarative Syntax
Provides the declarative syntax for the ProxyWebPartManager Web server control.
Related Sections
WebPartManager
Provides the class definition of the WebPartManager Web server control.
ASP.NET Web Server Controls Overview
Provides general information on working with ASP.NET Web server controls.
Individual ASP.NET Web Server Controls
Provides information on other Web server controls.
See Also
Reference
System.Web.UI.WebControls.WebParts
AppearanceEditorPart
BehaviorEditorPart
LayoutEditorPart
PropertyGridEditorPart
Other Resources
ASP.NET Master Pages
ProxyWebPartManager Web Server Control Overview
The ProxyWebPartManager control enables you to declare static connections in a content page when a WebPartManager
control has been declared in the content page's associated master page.
A Web page that uses Web Parts controls must contain one (and only one) WebPartManager control that manages all Web
Parts controls on the page. When a Web Parts application uses master pages, it is common to place the WebPartManager
control in the master page. When content pages are merged with the master page at run time, the single WebPartManager
control can manage Web Parts controls on all the content pages.
Declaring a static connection normally requires that you add an <asp:webpartconnection> element as a child of a
<staticconnections> element, which itself must be a child of a <asp:webpartmanager> element. However, when you use
master pages and put the WebPartManager control in the master page, you cannot create a <asp:webpartmanager>
element in a content page; only one WebPartManager control is permitted. The solution is to use a ProxyWebPartManager
control on the content page, which takes the place of the WebPartManager control.
At run time, the connections in the ProxyWebPartManager control are added to the StaticConnections collection of the
WebPartManager control and treated like any other connection.
For a code example demonstrating how to use the ProxyWebPartManager class, see the "Example" section of
System.Web.UI.WebControls.WebParts.ProxyWebPartManager.
Differences to note between the ProxyWebPartManager Control and WebManagerControl
The ProxyWebPartManager control is used only when you have created a WebPartManager control in a master page and
you want to declare static connections in the content page. The ProxyWebPartManager control therefore has more limited
functionality than the WebPartManager control. Although the ProxyWebPartManager control acts as a proxy to contain
static connections for the WebPartManager control in content pages, it does not inherit from the WebPartManager control.
Instead, it inherits directly from the Control class and overrides only a few of the base members.
For more details about differences between the ProxyWebPartManager control and the WebPartManager control, see
System.Web.UI.WebControls.WebParts.ProxyWebPartManager.
See Also
Reference
Web Parts Control Set Overview
WebPartManager
EditorPart
Concepts
Web Parts Personalization Overview
Other Resources
ASP.NET Web Parts Pages
WebPartManager Web Server Control
ASP.NET

WebPartManager Web Server Control


The WebPartManager control serves as the central control of the Web Parts control set, managing all the Web Parts controls,
functionality, and events that occur on a Web page.
In This Section
WebPartManager Web Server Control Overview
Provides a general overview of the WebPartManager Web server control.
Reference
WebPartManager
Provides the class definition of the WebPartManager Web server control.
WebPartManager Web Server Control Declarative Syntax
Provides the declarative syntax for the WebPartManager Web server control.
Related Sections
ProxyWebPartManager
Provides the class definition of the ProxyWebPartManager class
ASP.NET Web Server Controls Overview
Provides general information on working with ASP.NET Web server controls.
Individual ASP.NET Web Server Controls
Provides information on other Web server controls.
See Also
Reference
System.Web.UI.WebControls.WebParts
AppearanceEditorPart
BehaviorEditorPart
LayoutEditorPart
PropertyGridEditorPart
Concepts
ProxyWebPartManager Web Server Control Overview
Other Resources
WebPartZone Web Server Control
WebPartManager Web Server Control Overview
The WebPartManager control is the central control of the Web Parts control set, managing all the Web Parts controls, Web
Parts functionality, and Web Parts events.
You must add one (but only one) WebPartManager control to every page that uses Web Parts controls. The
WebPartManager control works only with authenticated users.
WebPartManger Tasks
The following table lists tasks performed by the WebPartManager control.
Task Control Functionality
Manage Web Parts c Manages the controls on a page that provide Web Parts features, including WebPart controls, connection
ontrols s, zones, and others.

Adding and removin Provides the methods for adding, deleting, and closing WebPart controls on a page.
g Web Parts controls

Administering conne Adds and removes connections between controls. Monitors the connections for problems.
ctions

Personalizing contro Enables users to move controls on a page, and launches the views in which users can edit the appearanc
ls and pages e, properties, and behavior of controls. Maintains user-specific personalization settings on each page.

Toggling between pa Switches between page views, enabling users to carry out tasks such as changing page layout or editing
ge views controls.

Raising Web Parts lif Defines and raises life-cycle events for Web Parts controls, such as events for when controls are added,
e-cycle events moved, connected, or deleted.

Enabling import and Exports XML streams that contain the state of the properties of WebPart controls, and allows users to im
export of controls port the files in personalizing complex controls in other pages or sites.

Associating Web Parts Controls with a WebPartManager


To associate a Web Parts control with a WebPartManager, the
Web Parts control is placed within a WebPartZone control zone and a single WebPartManager control must also be placed
on the same page.
For a code example demonstrating the WebPartManager control, see
System.Web.UI.WebControls.WebParts.WebPartManager.
Note
On master pages whose content pages have static Web Parts connections, use a ProxyWebPartManager control in place of a
WebPartManager control.

See Also
Reference
System.Web.UI.WebControls.WebParts
AppearanceEditorPart
BehaviorEditorPart
LayoutEditorPart
PropertyGridEditorPart
Concepts
ProxyWebPartManager Web Server Control Overview
Other Resources
WebPartZone Web Server Control
EditorZone Web Server Control
CatalogZone Web Server Control
ASP.NET

WebPartZone Web Server Control


The WebPartZone control serves as the primary control in the Web Parts control set for hosting WebPart controls on a Web
page.
In This Section
WebPartZone Web Server Control Overview
Provides a general overview of the WebPartZone Web server control.
Reference
WebPartZone
Provides the class definition of the WebPartZone Web server control.
WebPartZone Web Server Control Declarative Syntax
Provides the declarative syntax for the WebPartZone Web server control.
Related Sections
ASP.NET Web Server Controls Overview
Provides general information on working with ASP.NET Web server controls.
Individual ASP.NET Web Server Controls
Provides information on other Web server controls.
Walkthrough: Creating a Web Parts Page
Provides a guided walkthrough to create a Web Parts page.
See Also
Reference
System.Web.UI.WebControls.WebParts
WebPart
GenericWebPart
Other Resources
EditorZone Web Server Control
CatalogZone Web Server Control
ConnectionsZone Web Server Control
WebPartZone Web Server Control Overview
The WebPartZone control serves as the primary control in the Web Parts control set for hosting WebPart controls on a Web
page, and provides a common UI for the controls it contains.
WebPartZone User Interface Elements
The WebPartZone control inherits user interface elements from the base class WebZone, and provides a common UI for the
controls it contains. These common UI elements are known collectively as chrome and consist of the peripheral UI elements on
all the controls, such as the border, title, header and footer, style characteristics, and verbs (UI actions that a user can carry out
on a control, such as close or minimize). For more information on the UI elements the WebPartZone control inherits from the
WebZone base class, see WebZone.
See Also
Tasks
Walkthrough: Creating a Web Parts Page
Reference
System.Web.UI.WebControls.WebParts
WebPart
GenericWebPart
Other Resources
EditorZone Web Server Control
CatalogZone Web Server Control
ConnectionsZone Web Server Control
Visual Web Developer

Custom Web Server Controls


This section describes how to develop ASP.NET server controls. It contains a walkthrough that gives an overview of authoring a
custom server control and it provides code examples that illustrate different control authoring tasks such as rendering,
defining properties, managing state, and creating composite controls.
In This Section
Walkthrough: Developing and Using a Custom Server Control
Web Control Rendering Example
Control State vs. View State Example
Server Control Simple Properties and Subproperties
Server Control Custom State Management
Server Control Collection Properties
Composite Web Control Example
Typed Styles for Child Controls Example
Templated Server Control Example
Metadata Attributes for Custom Server Controls
Building the Custom Server Control Examples
Related Sections
ASP.NET Control Designers Overview
Provides information about implementing custom designer classes for your controls.
See Also
Other Resources
Authoring ASP.NET Server Control Adapters—An Introduction (MSDN)
Visual Web Developer

ASP.NET Data Access (Visual Studio)


ASP.NET includes features that enable you to access data from your ASP.NET Web pages with little or no code. You can connect
to databases, XML data and files, and business objects as data sources. You can then display data using a variety of controls
that provide great flexibility in how you present data on the page.
In This Section
Getting Started — ASP.NET Data Access (Visual Studio)
Provides essential information about working with data on ASP.NET Web pages.
Learning More — ASP.NET Data Access (Visual Studio)
Provides in-depth information about working with data on ASP.NET Web pages.
Walkthrough Topics — ASP.NET Data Access (Visual Studio)
Provides links to tutorials about adding data access to ASP.NET Web pages in Visual Web Developer.
How-to Topics — ASP.NET Data Access (Visual Studio)
Provides links to how-to topics about adding data access to ASP.NET Web pages in Visual Web Developer.
Related Sections
Guided Tour of Creating Web Sites in Visual Web Developer
Provides links to tutorials on all aspects of creating ASP.NET Web sites and ASP.NET Web pages.
Visual Web Developer

Getting Started — ASP.NET Data Access (Visual Studio)


The topics in this section provide essential information about adding data access to your ASP.NET Web pages in Visual Web
Developer.
In This Section
ASP.NET Data Access Overview
Walkthrough: Basic Data Access in Web Pages
Walkthrough: Creating a Web Page to Display Access Database Data
Walkthrough: Editing and Inserting Data in Web Pages with the DetailsView Web Server Control
Walkthrough: Data Binding Web Pages with a Visual Studio Data Component
See Also
Other Resources
ASP.NET Data Access (Visual Studio)
ASP.NET Web Server Controls (Visual Studio)
ASP.NET Web Pages (Visual Studio)
ASP.NET

ASP.NET Data Access Overview


Web applications commonly access data sources for storage and retrieval of dynamic data. You can write code to access data
using classes from the System.Data namespace (commonly referred to as ADO.NET) and from the System.Xml namespace. This
approach was common in previous versions of ASP.NET.
However, ASP.NET also enables you to perform data binding declaratively. This requires no code at all for the most common
data scenarios, including:
Selecting and displaying data.
Sorting, paging, and caching data.
Updating, inserting, and deleting data.
Filtering data using run-time parameters.
Creating master-detail scenarios using parameters.
ASP.NET includes two types of server controls that participate in the declarative data binding model: data source controls and
data-bound controls. These controls manage the underlying tasks required by the stateless Web model for displaying and
updating data in ASP.NET Web pages. As a result, you are not required to understand details of the page request lifecycle just
to perform data binding.
Data Source Controls
Data source controls are ASP.NET controls that manage the tasks of connecting to a data source and reading and writing data.
Data source controls do not render any user interface, but instead act as an intermediary between a particular data store (such
as a database, business object, or XML file) and other controls on the ASP.NET Web page. Data source controls enable rich
capabilities for retrieving and modifying data, including querying, sorting, paging, filtering, updating, deleting, and inserting.
ASP.NET includes the following data source controls:
Data source contr Description
ol
ObjectDataSource Enables you to work with a business object or other class and create Web applications that rely on middle
-tier objects to manage data.
For more information, see ObjectDataSource Web Server Control.

SqlDataSource Enables you to work with ADO.NET managed data providers, which provide access to Microsoft SQL Serve
r, OLE DB, ODBC, or Oracle databases.
For more information, see SqlDataSource Web Server Control.

AccessDataSource Enables you to work with a Microsoft Access database.


For more information, see AccessDataSource Web Server Control.

XmlDataSource Enables you to work with an XML file, which is especially useful for hierarchical ASP.NET server controls s
uch as the TreeView or Menu control.
For more information, see XmlDataSource Web Server Control.

SiteMapDataSource Used with ASP.NET site navigation. For more information, see ASP.NET Site Navigation Overview.

Data-source controls can also be extended to support additional data access storage providers.
For more information on data source controls, see Data Source Controls Overview.
Data-bound Controls
Data-bound controls render data as markup to the requesting browser. A data-bound control can bind to a data source control
and automatically fetch data at the appropriate time in the page request lifecycle. Data-bound controls can take advantage of
the capabilities provided by a data source control including sorting, paging, caching, filtering, updating, deleting, and inserting.
A data-bound control connects to a data source control through its DataSourceID property.
ASP.NET includes the data-bound controls described in the following table.
List Controls
Renders data in a variety of lists format. List controls include the BulletedList, CheckBoxList, DropDownList, ListBox, and
RadioButtonList controls.
AdRotator
Renders advertisements on a page as an image that users can click to go to a URL associated with the advertisement.
For more information, see AdRotator Web Server Control.
DataList
Renders data in a table. Each item is rendered using an item template that you define.
For more information see the DataList Web Server Control.
DetailsView
Displays one record at a time in a tabular layout and enables you to edit, delete, and insert records. You can also page
through multiple records.
For more information see the DetailsView Web Server Control.
FormView
Similar to the DetailsView control, but enables you to define a free-form layout for each record. The FormView control is
like a DataList control for a single record.
For more information, see FormView Web Server Control.
GridView
Displays data in a table and includes support for editing, updating, sorting, and paging data without requiring code.
Note
The GridView control supersedes the ASP.NET DataGrid control available in previous versions of ASP.NET.

For more information, see GridView Web Server Control.


Menu
Renders data in a hierarchical dynamic menu that can include submenus.
For more information, see Menu Web Server Control.
Repeater
Renders data in a list. Each item is rendered using an item template that you define.
For more information, see Repeater Web Server Control.
TreeView
Renders data in a hierarchical tree of expandable nodes.
For more information, see TreeView Web Server Control.
Note
The DataGrid control available in previous versions of ASP.NET has been superseded by the GridView control, which includ
es expanded capabilities for sorting, paging, and modifying data. Existing pages that use the DataGrid control will continue t
o function. As with other data controls, the DataGrid control has been enhanced to interact with data source controls.

For more information, see ASP.NET Data-Bound Web Server Controls Overview.
See Also
Concepts
What's New in ASP.NET Data Access
Data Source Controls Overview
ASP.NET Data-Bound Web Server Controls Overview
ASP.NET

What's New in ASP.NET Data Access


ASP.NET version 2.0 continues to offer managed data access using ADO.NET and managed classes for XML. But ASP.NET 2.0
also includes new features to make data access in Web pages easier to implement and manage.
Highlights of the new data access model in ASP.NET 2.0 are:
A simplified data-binding model that uses the new data-source controls and requires no code.
Two-way data binding that can both read and update data.
New and enhanced data controls to display and update data.
Improved support for using middle-tier business object for data access.
Backward Compatibility
An important feature in the new data access model is that existing ASP.NET applications continue to work without changes. The
data-binding model used in ASP.NET 1.0 and ASP.NET 1.1 is still supported, and you can still use ADO.NET for data access. Data
controls such as the DataList and Repeater controls have been enhanced to work with the new data source controls and to take
advantage of automatic data binding, but still work when bound directly to a data source such as a dataset.
Data Binding Using Data Source Controls
In ASP.NET 1.0 and ASP.NET 1.1, you display data on a page using a data control (for example, a Repeater or DataList control).
Data control is bound to a data source, such as an ADO.NET dataset filled by an ADO.NET data adapter. You add these data
components to the page yourself, and then write code to populate the data source and bind the data controls to the data.
Data Source Controls
In ASP.NET version 2.0, the tasks associated with data access in a Web page are provided by data source controls. A data
source control provides a single object in which you can declaratively define the following:
Connection information.
Query information, such as a SQL statement or the names of methods to invoke on an object.
Insert, update, and delete commands to modify data.
Parameters for queries, data modification, and filtering.
Options such as paging and caching (if the data source supports these options).
When you use data source controls, you do not need to write code for data access, such as calls to the DataBind method. (You
can still call the DataBind method explicitly to refresh bound data if required in your application.)
ASP.NET provides data source controls for different types of data stores, including SQL-based databases (SQL Server, OLE DB,
and Open Database Connectivity (ODBC) databases), XML data, and business objects. All data source controls expose the same
interface to data controls on the page, so that controls such as the DataList and Repeater controls, and the new GridView
control can bind the same way to any data source control, regardless of the underlying data store it represents. The result is
that you can use the full array of ASP.NET data controls to work with a wide variety of data sources.
Types of Data Source Controls
ASP.NET includes the data source controls listed in the following table.
Data source contr Description
ol
ObjectDataSource Enables you to work with a business object or other class and create Web applications that rely on middle
-tier objects to manage data. Supports advanced sorting and paging scenarios unavailable with the other
data source controls. For more information, see ObjectDataSource Web Server Control.

SqlDataSource Enables you to work with Microsoft SQL Server, OLE DB, ODBC, or Oracle databases. When used with SQL
Server, supports advanced caching capabilities. The control also supports sorting, filtering, and paging wh
en data is returned as a DataSet object. For more information, see SqlDataSource Web Server Control.
AccessDataSource Enables you to work with a Microsoft Access database. Supports sorting, filtering, and paging when data is
returned as a DataSet object. For more information, see AccessDataSource Web Server Control.

XmlDataSource Enables you to work with XML data, especially for hierarchical ASP.NET server controls such as the
TreeView or Menu controls. Supports filtering capabilities using XPath expressions and enables you to app
ly an XSLT transformation to the data. The XmlDataSource enables you to update data by saving the enti
re XML document with changes. For more information, see XmlDataSource Web Server Control.

SiteMapDataSource Used with ASP.NET site navigation. For more information, see ASP.NET Site Navigation Overview.

Enhanced Data Controls


All data controls in ASP.NET 2.0 have been enhanced to work with data source controls. As a result, you can take advantage of
automatic data binding in any data-bound control. This includes list controls such as the DropDownList control and composite
data-bound controls such as the DataList control.
In addition, ASP.NET 2.0 introduces new data controls that provide additional functionality, as described in the following table.
GridView
The GridView control is the successor to the ASP.NET DataGrid control. The GridView control automates many of the
features of the DataGrid control, so that you do not need to write code for editing, sorting, or paging. For situations in which
you want to customize the control's behavior, you can continue to use an object model similar to that of the DataGrid
control. For more information, see GridView Web Server Control.
DetailsView
The DetailsView control displays one record at a time and enables you to edit, delete, and insert records. You can also page
through multiple records. For more information see DetailsView Web Server Control.
FormView
The FormView control is similar to the DetailsView control, but enables you to define a free-form layout for each record.
The FormView control is like a DataList control for a single record. For more information, see
FormView Web Server Control.
TreeView
The TreeView control renders data in a hierarchical tree of expandable nodes. For more information, see
TreeView Web Server Control.
Menu
The Menu control renders data in a hierarchical dynamic menu including "flyout" submenus. For more information, see
Menu Web Server Control.
DataGrid Control
You can continue to use the DataGrid control, although it is superseded by the GridView control. Existing pages that use the
DataGrid control will work as is. As with other data controls, the DataGrid control has been enhanced to interact with data
source controls.
Declarative Parameters
For situations in which you need to pass parameters to a data source control, such as for a filtered query or update command,
you can declaratively define parameters as part of the data source control. These parameter objects enable you to supply
values from server control properties, Session and Application variables, cookies, QueryString values, and user profile
properties to parameterized data operations. Using parameters enables filtering and master-details scenarios with little or no
custom code.
For more information, see Using Parameters with Data Source Controls.
Simplified Data Binding
The syntax used for data binding within templates has been simplified. In ASP.NET 1.0 and ASP.NET 1.1, you have to specify the
Eval method of the DataBinder class and identify the DataItem from the container and the field to bind, you can now specify
just the Eval method and the name of the field to bind. You can optionally include a format for the bound field based on the
System.String.Format method.
A Bind method has also been added for two-way data-binding scenarios in edit item templates and update item templates. For
more information on the Eval and Bind methods, see Data-Binding Expression Syntax.
When binding to XML data, you can make use of the XPath and XPathSelect methods to bind to the results of an XPath query
against the source XML. For more information, see Binding a Tabular Control to the XmlDataSource Control.
The App_Data Folder
To improve the security of the data used by your ASP.NET application, a new subfolder named App_Data has been added for
ASP.NET applications. Files stored in the App_Data folder are not returned in response to direct HTTP requests, which makes
the App_Data folder the recommended location for data stored with your application, including .mdf (SQL Server Express
Edition), .mdb (Microsoft Access), or XML files. Note that when using the App_Data folder to store your application data, the
identity of your application has read and write permissions to the App_Data folder.
See Also
Other Resources
Accessing Data with ASP.NET
Visual Web Developer

Walkthrough: Basic Data Access in Web Pages


This walkthrough shows you how to create a simple data-bound page by using controls that are specially designed for data
access.
During this walkthrough, you will learn how to do the following:
Connect to a Microsoft SQL Server database in the Microsoft Visual Web Developer Web development tool.
Use drag-and-drop editing to create data-access elements that can be used in the page without code.
Use the SqlDataSource control to manage data access and binding.
Display data with the GridView control.
Configure the GridView control to allow for sorting and paging.
Create a filtered query that displays only selected records.
Prerequisites
In order to complete this walkthrough, you will need the following:
Access to the SQL Server Northwind database. For information about downloading and installing the SQL Server sample
Northwind database, see Installing Sample Databases on the Microsoft SQL Server Web site.
Note
If you need information about how to log on to the computer running SQL Server, contact the server administrator.

Microsoft Data Access Components (MDAC) version 2.7 or later.


If you are using Microsoft Windows XP or Windows Server 2003, you already have MDAC 2.7. However, if you using
Microsoft Windows 2000, you might have to upgrade the MDAC version that is already installed on the computer. To
download the current MDAC version, see Data Access and Storage Developer Center.
Creating the Web Site
If you have already created a Web site in Visual Web Developer by completing
Walkthrough: Creating a Basic Web Page in Visual Web Developer, you can use that Web site and go to the next section.
Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the right-most Location box, enter the name of the folder where you want to keep the pages of the Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click the programming language that you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Adding a GridView Control to Display Data
To display data on an ASP.NET Web page, you need the following:
A connection to a data source (such as a database).
In the following procedure, you will create a connection to the SQL Server Northwind database.
A data source control on the page, which executes queries and manages the results of the queries.
A control on the page to actually display the data.
In the following procedure, you will display data in a GridView control. The GridView control will get its data from the
SqlDataSource control.
You can add these elements to the Web site separately. However, it is easiest to start by visualizing the data display using
GridView control, and then using wizards to create the connection and data source control. The following procedure explains
how to create all three of the elements that you must have to display data on the page.
To add and configure a GridView control for displaying data
1. In Visual Web Developer, switch to Design view.
2. From the Data folder in the Toolbox, drag a GridView control onto the page.
3. If the GridView Tasks shortcut menu does not appear, right-click the GridView control, and then click Show Smart Tag.
4. On the GridView Tasks menu, in the Choose Data Source list, click <New data source>.
The Data Source Configuration dialog box appears.

5. Click Database.
This specifies that you want to obtain data from a database that supports SQL statements. This includes SQL Server and
other OLE-DB–compatible databases.
In the Specify an ID for the data source box, a default data source control name appears (SqlDataSource1). You can
leave this name.
6. Click OK.
The Configure Data Source Wizard appears, displaying a page on which you can choose a connection.
7. Click New Connection.
8. In the Choose Data Source dialog box, under Data source, click Microsoft SQL Server, and then click Continue.
The Add Connection dialog box appears.
9. In the Server name box, enter the name of the SQL Server that you want to use.

10. For the logon credentials, select the option that is appropriate for accessing the SQL Server database (integrated security
or specific ID and password) and if it is required, enter a user name and password.
11. Click Select or enter a database name, and then enter Northwind.
12. Click Test connection, and when you are sure that it works, click OK.
The Configure Data Source - <DataSourceName> Wizard appears and the connection information is filled in.
13. Click Next.
The wizard appears, displaying a page on which you can choose to store the connection string in the configuration file.
Storing the connection string in the configuration file has two advantages:
a. It is more secure than storing the connection string in the page.
b. You can reuse the same connection string in multiple pages.
14. Make sure that the Yes, save this connection as check box is selected, and then click Next. (You can leave the default
connection string name of NorthwindConnectionString.)
The wizard appears, displaying a page on which you can specify the data that you want to fetch from the database.
15. Under Specify columns from a table or view, in the Name list, click Customers.
16. Under Columns, select the CustomerID, CompanyName, and City check boxes.
The wizard appears, displaying the SQL statement that you are creating in a box at the bottom of the page.

Note
The wizard lets you specify selection criteria (a WHERE clause) and other SQL query options. For this part of the walkthr
ough, you will create a simple statement without selection or sort options.

17. Click Next.


18. Click Test Query to make sure that you are fetching the data you want.
19. Click Finish.
The wizard closes and you are returned to the page. Running the wizard has accomplished two tasks:
The wizard created and configured a SqlDataSource control (named SqlDataSource1), which incorporates the
connection and query information that you specified.
The wizard bound the GridView control to the SqlDataSource. Therefore, the GridView control will display data
that is returned by the SqlDataSource control.
If you view the properties for the SqlDataSource control, you can see that the wizard has created values for the
ConnectionString and SelectQuery properties.
Note
You can easily change the look of the GridView control. In Design view, right-click the GridView control, and then clic
k Show Smart Tag. On the GridView Tasks menu, click Auto Format, and then apply a scheme.
Testing the Page
You can now run the page.
To test the page
1. Press CTRL+F5 to run the page.
The page appears in the browser. The GridView control displays all data rows from the Customers table.
2. Close the browser.
Adding Sorting and Paging
You can add sorting and paging to the GridView control without writing any code.
To add sorting and paging
1. In Design view, right-click the GridView control, and then click Show Smart Tag.
2. On the GridView Tasks shortcut menu, select the Enable Sorting check box.
The column headings in the GridView control change to links.
3. On the GridView Tasks menu, select the Enable Paging check box.
A footer is added to the GridView control with page number links.
4. Optionally, use Properties to change the value of the PageSize property from 10 to a smaller page size.
5. Press CTRL+F5 to run the page.
You will be able to click a column heading to sort by the contents of that column. If there are more records in the data
source than the page size of the GridView control, you will be able to use the page navigation links at the bottom of the
GridView control to move between pages.
6. Close the browser.
Adding Filtering
Frequently you want to display only selected data in the page. In this part of the walkthrough, you will modify the query for the
SqlDataSource control so that users can select customer records for a particular city.
First, you will use a TextBox control to create a text box in which users can type the name of a city. Then, you will change the
query to include a parameterized filter (WHERE clause). As part of that process, you will create a parameter element for the
SqlDataSource control. The parameter element establishes how the SqlDataSource control will get the value for its
parameterized query—namely, from the text box.
When you are finished with this part of the walkthrough, the page might look similar to the following in Design view.
To add the text box for specifying a city
1. From the Standard group in the Toolbox, drag a TextBox control and a Button control onto the page.
The Button control is used only to post the page to the server. You will not need to write any code for it.
2. In Properties, for the TextBox control, set ID to textCity.
3. If you want, type City or similar text before the text box to act as a caption.
4. In Properties for the Button control, set Text to Submit.
You can now modify the query to include a filter.
To modify the query with a parameterized filter
1. Right-click the SqlDataSource control, and then click Show Smart Tag.
2. On the SqlDataSource Tasks menu, click Configure Data Source.
The Configure Data Source - <Datasourcename> wizard appears.
3. Click Next.
The wizard displays the SQL command that is currently configured for the SqlDataSource control.
4. Click WHERE.
The Add WHERE Clause page appears.
5. In the Column list, click City.
6. In the Operator list, click =.
7. In the Source list, click Control.
8. Under Parameter properties, in the Control ID list, click textCity.

The previous five steps specify that the query will get the search value for City from the TextBox control that you added
in the preceding procedure.
9. Click Add.
The WHERE clause that you have created appears in a box at the bottom of the page.
10. Click OK to close the Add WHERE Clause page.
11. In the Configure Data Source - <DataSourceName> wizard, click Next.
12. On the Test Query page, click Test Query.
The wizard appears, displaying the Parameter Values Editor page, which prompts you for a value to use in the WHERE
clause.
13. In the Value box, type London, and then click OK.
The customer records for London appear.
14. Click Finish to close the wizard.
You can now test filtering.
To test filtering
1. Press CTRL+F5 to run the page.
2. In the text box, type London, and then click Submit.
A list of customers from the city of London appears in the GridView control.
3. Try other cities, such as Buenos Aires and Berlin.
Next Steps
Data access is an important part of many Web applications, and this walkthrough has provided only a glimpse of what you can
do with data in the Web pages. You might want to experiment with additional features of data access. For example, you might
want to do the following:
Work with Microsoft Access instead of SQL Server. (You cannot use SQL cache dependency with Access.)
For detailed information, see Walkthrough: Creating a Web Page to Display Access Database Data.
Edit and insert records.
For detailed information, see
Walkthrough: Editing and Inserting Data in Web Pages with the DetailsView Web Server Control.
Work with records that have a master-detail relationship.
For detailed information, see Walkthrough: Creating Master/Detail Web Pages in Visual Studio.
Create a middle-tier (business) component that performs data access, and then use that as the data source in a page.
For detailed information, see Walkthrough: Data Binding to a Custom Business Object.
See Also
Concepts
Data Source Controls Overview
Visual Web Developer

Walkthrough: Creating a Web Page to Display Access Database


Data
Using the Microsoft Visual Web Developer Web development tool, you can create Web pages that work with data from a
variety of sources, including databases, XML files, and business objects. This walkthrough shows you how to work with data in
a Microsoft Access database (.mdb file).
During this walkthrough, you will learn how to do the following:
Configure permissions for .mdb files.
Connect to the database that has an AccessDataSource control.
Display Access data.
Access databases do not have the same capacity and are not as scalable as other types of databases, such as Microsoft SQL
Server. Generally, if you are creating a Web site that will support only light traffic or a limited number of users, an Access
database is sufficient. However, if the Web site will support more throughput or a larger number of users, you should consider
using SQL Server or another database that is suited for production Web sites.
Prerequisites
In order to complete this walkthrough, you will need the following:
The Northwind.mdb file that contains the Access version of the sample Northwind database.
Alternatively, you can use another Access .mdb file and adjust the steps in the walkthrough to match the tables that you
are using.
Microsoft Data Access Components (MDAC) version 2.7 or later.
If you are using Microsoft Windows XP or Windows Server 2003, you already have MDAC 2.7. However, if you using
Microsoft Windows 2000, you might to have to upgrade the MDAC version that is already installed on the computer. To
download the current MDAC version, see the Data Access and Storage Developer Center..
Optionally, Microsoft Internet Information Services (IIS) installed locally on the computer.
This lets you test that the Web site has adequate user rights to use an Access database in a production environment.
Creating the Web Site and Page
If you have already created a Web site in Visual Web Developer by completing
Walkthrough: Creating a Basic Web Page in Visual Web Developer, you can use that Web site and go to the next section.
Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the left-most Location box, click HTTP.
5. Click Browse.
The Choose Location page appears.
6. Click Local IIS, and then click Default Web Site.
7. Click the create new Web application icon ( ), and then name the new Web application AccessSample.
8. Click Open.
The New Web Site dialog box appears with the location of your new Web application in the right-most Location box.
9. In the Language list, click the programming language that you prefer to work in.
The programming language that you choose will be the default for the Web site, but you can set the programming
language for each page individually.
10. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx. The Web site is displayed in Solution
Explorer.
Configuring Permissions for an Access Database
An important aspect of working with an Access .mdb file is to correctly configure permissions. When a Web application uses an
Access database, the application must have Read permission to the .mdb file so the application can access the data.
Additionally, the application must have Write permission to the folder that contains the .mdb file. Write permission is required
because Access creates an additional file that has the extension .ldb in which it maintains information about database locks for
concurrent users. The .ldb file is created at run time.
By default, ASP.NET Web applications run in the context of a local machine account named ASPNET (for Windows 2000 and
Windows XP) or in the context of the account NETWORK SERVICE (for Windows Server 2003). For example, for Windows 2000
or Windows XP Professional, if the Web server is named ABCServer, ASP.NET applications on the ABCServer computer run in
the context of the local account ABCServer\ASPNET. Therefore, to use an Access database in an ASP.NET Web application, you
must configure the folder that contains the Access database to have both Read and Write permissions for the local ASPNET
user account.
When you create a Web site in Visual Web Developer, Visual Web Developer creates a folder named App_Data below the
current root folder. The folder is designed to be a store for application data, including Access databases. The App_Data folder is
also used by ASP.NET to store databases that the system maintains, such as the database for membership and roles. When
Visual Web Developer creates the App_Data folder, it grants Read and Write permissions for the folder to the ASPNET or
NETWORK SERVICE user account.
Note
As a security measure, files in the App_data folder are not served by the Web server. Do not store any Web pages in the App_
Data folder, because users will see an error if they request a page from that folder.

In this part of the walkthrough, you will examine the permissions of the App_Data folder to make sure that it will work correctly
when the application runs.
To set permissions in the App_Data folder
1. In Windows Explorer, move to the root folder for the Web site.
The default location for your new Web site is c:\inetpub\wwwroot\AccessSample.
2. If the App_Data folder does not already exist, create one.
By default, Visual Web Developer creates the folder when you create a new Web site.
3. Right-click the App_Data folder, click Properties, and then click the Security tab.
4. Under Group or user names, look for either of these user accounts:
If the computer is running Windows XP Professional or Windows 2000, look for computer\ASPNET.
If the computer is running Windows Server 2003, look for NETWORK SERVICE.
5. Verify that the account has Read and Write permissions for the App_Data folder.
Using Access Data on an ASP.NET Web Page
You can now use your Access database in a Web page. You will use an AccessDataSource control.
To add an AccessDataSource control to the page
1. In Visual Web Developer, in Solution Explorer, right-click the App_Data folder, and then click Add Existing Item.
2. Locate the Northwind.mdb file (or other Access .mdb file) that you want to use for this walkthrough.
3. In the App_Data folder, click the .mdb file, and then click Add.
The .mdb file is added to your application.
4. Open the Default.aspx page and switch to Design view.
5. From the Data group in the Toolbox, drag an AccessDataSource control onto the page.
If the Access Data Source Tasks shortcut menu does not appear, right-click the AccessDataSource control, and
then click Show Smart Tag.
6. On the Access Data Source Tasks shortcut menu, click Configure Data Source.
The Configure Data Source - <DataSourceName> wizard appears.
7. On the Choose a database page, in the Microsoft Access Data file box, type ~/App_Data/Northwind.mdb.
Alternatively, click Browse, and then in the Select Microsoft Access Database dialog box, move to the
Northwind.mdb file in the App_Data folder.
8. Click Next.
The Configure Select Statement page appears.
9. Click Specify columns from a table or view.
10. In the Name list, click Categories.
11. Select the CategoryID, CategoryName, and Description check boxes.
12. Click Next.
The Test Query page appears.
Optionally, click Test Query to test your query.
13. Click Finish.
14. From the Data group in the Toolbox, drag a GridView control onto the page.
If the GridView Tasks shortcut menu does not appear, right-click the GridView control, and then click Show
Smart Tag.
15. On the GridView Tasks menu, in the Choose Data Source box, click AccessDataSource1.
Testing the Page
You can now run the page.
To test the page
Press CTRL+F5 to run the page.
The GridView control displays all data rows from the Categories table.
Next Steps
This walkthrough describes the basic steps that are required to work with Access data in an ASP.NET Web page. The ASP.NET
data binding model lets you work with data from different sources in the same way. For example, you can do the following:
Use controls to filter the data that the page displays.
For detailed information, see Walkthrough: Basic Data Access in Web Pages.
Update, insert, or delete data from an Access database.
For detailed information, see
Walkthrough: Editing and Inserting Data in Web Pages with the DetailsView Web Server Control.
Create pages to display Access data from tables that have a master-detail relationship.
For detailed information, see Walkthrough: Creating Master/Detail Web Pages in Visual Studio.
See Also
Concepts
ASP.NET Data Access Overview
Binding to Data Using a Data Source Control
Visual Web Developer

Walkthrough: Editing and Inserting Data in Web Pages with


the DetailsView Web Server Control
Microsoft Visual Web Developer allows you to create data entry forms for updating records and inserting new ones into a
database with only a few lines of code. By using a combination of a data source control that encapsulates data access and
DetailsView and GridView controls that display records in an editable format, you can create a data entry page that allows
users to edit existing records or insert new ones, all without any code.
During this walkthrough, you will learn how to:
Create a data entry page.
Configure a data source control with information required to make database updates and inserts.
Use the DetailsView control to view individual records, change them, and insert new ones.
Use a GridView control to enable database modification from the data entry page.
Prerequisites
In order to complete this walkthrough, you will need:
Visual Web Developer.
Microsoft Data Access Components (MDAC) version 2.7 or later.
If you are using the Microsoft Windows XP or Windows Server 2003 operating systems, you already have MDAC 2.7.
However, if you are using the Microsoft Windows 2000 Server operating system, you might need to upgrade the MDAC
already installed on your computer. To download the current MDAC version, see the
Data Access and Storage Developer Center.
Access to the SQL Server Northwind database. For information about downloading and installing the SQL Server sample
Northwind database, see Installing Sample Databases on the Microsoft SQL Server Web site.
Note
If you need information about how to log on to the computer running SQL Server, contact the server administrator.

Permission to modify data in the sample Northwind database.


Creating the Web Site and Page
Create a new Web site and page by following these steps.
To create a new file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New, and then click Web Site. If you are using Visual Web Developer Express, on the File menu,
click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, select File System, and enter the name of the folder where you want to keep the pages of your Web
site.
For example, type the folder name C:\WebSites\EditData.
5. In the Language list, click the programming language you prefer to work in.
The programming language you choose will be the default for your Web site, but you can set the programming
languages for each page individually.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Connecting to SQL Server
The next step is to establish a connection to the SQL Server database.
To create a connection to a SQL Server database
1. In Server Explorer, right-click Data Connections, and then click Add Connection. If you are using Visual Web
Developer Express, use Database Explorer.
The Add Connection dialog box appears.
If the Data source list does not display Microsoft SQL Server (SqlClient), click Change, and in the Change Data
Source dialog box, select Microsoft SQL Server.
If the Choose Data Source page appears, in the Data source list, select the type of data source you will use. For
this walkthrough, the data source type is Microsoft SQL Server. In the Data provider list, click .NET Framework
Data Provider for SQL Server, and the click Continue.
Note
If the Server Explorer tab is not visible in Visual Web Developer, in the View menu, click Server Explorer. If the Data
base Explorer tab is not visible in the Express edition, in the View menu, click Database Explorer.

2. In the Add Connection box, enter your server name in the Server Name box.
3. For the Log on to the server section, select the option that is appropriate to access the running the SQL Server database
(integrated security or specific ID and password) and, if required, enter a user name and password. Select the Save my
Password check box if you entered a password.
4. Under Select or enter a database name, enter Northwind.
5. Click Test Connection, and when you are sure that it works, click OK.
Your new connection has been created under Data Connections in Server Explorer.
Creating the Data Entry Page
In this section, you will create a data entry page and configure a DetailsView control so that you can view employee data that
is stored in the Employees table of the Northwind database. To handle the data access for the page, you will configure a SQL
data source control.
To create a data entry page and configure a DetailsView control
1. On the Website menu, click Add New Item.
The Add New Item dialog box appears.
2. Under Visual Studio installed templates, click Web Form, and then in the Name box, type EditEmployees.aspx.
3. Click Add.
4. Open the EditEmployees.aspx page.
5. Switch to Design view.
6. Type Edit Employees, select the text, and then format the text as a heading.
7. In the Toolbox, from the Data group, drag a DetailsView control onto the page.
8. Right-click the DetailsView control, click Properties, and then set AllowPaging to true.
This will allow you to page through individual employee entries when they are displayed.
The next step is to create and configure a data source control that can be used to query the database. There are a number of
ways to create a data source control, including dragging data elements from Server Explorer or Database Explorer onto the
page. In this walkthrough, you will start with the DetailsView control and configure the data source control from there.
To configure a data source control
1. Right-click the DetailsView control and click Show Smart Tag.
2. On the DetailsView Tasks menu, in the Choose Data Source box, click <New data source>.
The Data Source Configuration Wizard dialog box appears.
3. Under Select a data source type, click Database.
4. Leave the default name of SqlDataSource1, and then click OK.
The Configure Data Source wizard displays the Choose a connection page.
5. In the Which data connection should your application use to connect to the database? box, enter the connection
that you created in "To create a connection to SQL Server," and then click Next.
The wizard displays a page where you can choose to store the connection string in a configuration file. Storing the
connection string in the configuration file has two advantages:
It is more secure than storing it in the page.
You can use the same connection string in multiple pages.
6. Select the Yes, save this connection as check box, and then click Next.
The wizard displays a page where you can specify what data you want to retrieve from the database.
7. On the Configure the Select Statement page, select Specify columns from a table or view, and then in the Name
box, click Employees.
8. Under Columns, select the EmployeeID, LastName, FirstName, and HireDate check boxes, and then click Next.
9. Click Test Query to preview the data, and then click Finish.
You can now test the employee records display page.
To test displaying the employee records
1. Press CTRL+F5 to run the page.
The first employee record is displayed in the DetailsView control.
2. Click the page number links to see additional employee records.
3. Close the browser.
Allowing Editing in a GridView Control
At this point, you can view employee records, but you cannot edit them. In this section, you will add a GridView control and
configure it so that you can edit individual records.
Note
The GridView control presents a list of records and allows you to edit them. However, it does not allow you to insert them. L
ater in this walkthrough, you will use the DetailsView control, which allows you to add new records.

To support editing, you must configure the data source control you created earlier (SqlDataSource1) with SQL statements that
perform updates.
To add a GridView control to allow editing
1. In the Toolbox, from the Data group, drag a GridView control onto the page.
2. Right-click the GridView control, click Show Smart Tag, and then on the GridView Tasks menu, in the Choose Data
Source box, click SqlDataSource1.
3. On the GridView Tasks menu, click Configure Data Source.
4. Click Next to advance to the Configure the Select Statement page of the wizard.
5. On the Configure the Select Statement page, click Advanced, select the Generate INSERT, UPDATE, and DELETE
statements check box, and then click OK.
This generates Insert, Update, and Delete statements for the SqlDataSource1 control based on the Select statement that
you configured earlier.
Note
Alternatively, you could manually create the statements by selecting Specify a custom SQL statement or stored pro
cedure and entering SQL queries.

6. Click Next, and then click Finish.


The SqlDataSource control is now configured with additional SQL statements.
Note
You can examine the statements generated by the wizard by selecting the SqlDataSource control and viewing the
DeleteQuery, InsertQuery, and UpdateQuery properties. You can also view the updated control properties by switching
to Source view and examining the markup of the control.

7. On the GridView Tasks menu, select the Enable Paging and Enable Editing check boxes.
Security Note
User input in an ASP.NET Web page can include potentially malicious client script. By default, ASP.NET Web pages valid
ate user input to make sure input does not include script or HTML elements. As long as this validation is enabled, you d
o not need to explicitly check for script or HTML elements in user input. For more information, see
Script Exploits Overview.

You can now test the editing of employee records.


To test the editing in the GridView control
1. Press CTRL+F5 to run the page.
The GridView control is displayed with the data in text boxes.
2. Choose a row in the GridView control and click Edit.
3. Make a change to the record, and then click Update.
The updated data now appears in both the GridView control and the DetailsView control.
4. Close the browser.
Allowing Editing, Deleting, and Inserting Using a DetailsView Control
The GridView control allows you to edit records, but it does not allow you to insert data. In this section, you will modify the
DetailsView control so that you can see records individually, as well as delete, insert, and update records.
To use a DetailsView control to allow deleting, inserting, and updating
1. Right-click the DetailsView control and then click Show Smart Tag.
2. On the DetailsView Tasks menu, select the Enable Inserting, Enable Editing, and Enable Deleting check boxes.
When you used the DetailsView control earlier in the walkthrough, the options for enabling editing, inserting, and
deleting were not available. The reason is that the SqlDataSource1 control that the DetailsView control is bound to did
not have the necessary SQL statements. Now that you have configured the data source control to include update
statements, the update options are available on the DetailsView control.
You can now test deleting, inserting, and updating in the DetailsView control.
To test the updating, inserting, and deleting in the DetailsView control
1. Press CTRL+F5 to run the page.
The DetailsView control displays an employee record.
2. In the DetailsView control, click Edit.
The DetailsView control now displays the data in text boxes.
3. Make a change to the record, and then click Update.
The updated record is displayed in the control.
4. In the DetailsView control, click New.
The control now displays blank text boxes for each column.
5. Enter values for each column.
The Employees table has an auto-increment key column, so the value for EmployeeID is assigned automatically when
you save the record.
6. When you are finished, click Insert.
The new record is added as the last record.
Note
Inserting a new record in the Employees table in this walkthrough will not generate any errors. However, when you wo
rk with production data, the tables might have constraints (such as a foreign key constraint) that you must be aware of
when configuring the DetailsView control.

7. Use paging in the DetailsView control to navigate to the last record, and then click Delete.
The new record is removed.
Note
As with inserting data, you must always be aware of any constraints that apply to the data row when configuring a Det
ailsView control to allow deletion.

Next Steps
This walkthrough has illustrated the basics of creating a Web page that allows users to modify data records. You might want to
explore additional data capabilities of ASP.NET Web pages. For example, you might want to do the following:
Work with records in related tables. For details, see Walkthrough: Creating Master/Detail Web Pages in Visual Studio.
Use a middle-tier component for data access. For details, see Walkthrough: Data Binding to a Custom Business Object.
Use other ways to configure data access in a Web page. For details, see Walkthrough: Basic Data Access in Web Pages.
See Also
Tasks
Walkthrough: Creating a Web Page to Display Access Database Data
Concepts
Data Source Controls Overview
Binding to Data Using a Data Source Control
Visual Web Developer

Walkthrough: Data Binding Web Pages with a Visual Studio


Data Component
Many Web applications are built by using multiple tiers, with one or more components in the middle tier that combine data
access together with business logic. This walkthrough shows you how to build a data-access component in a Web site and bind
a Web server control (a GridView control) to the data that is managed by the component. The data component interacts with a
Microsoft SQL Server database, and can both read and write data.
Tasks illustrated in this walkthrough include the following:
Creating a component that can read and write data.
Referencing the data component as a data source on a Web page.
Binding a control to the data that is returned by the data component.
Reading and writing data using the data component.
Prerequisites
In order to complete this walkthrough, you will need the following:
Access to the SQL Server Northwind database. For information about downloading and installing the SQL Server sample
Northwind database, see Installing Sample Databases on the Microsoft SQL Server Web site.
Note
If you need information about how to log on to the computer running SQL Server, contact the server administrator.

Microsoft Data Access Components (MDAC) version 2.7 or later.


If you are using Microsoft Windows XP or Windows Server 2003, you already have MDAC 2.7. However, if you using
Microsoft Windows 2000, you might to have to upgrade the MDAC version that is already installed on the computer. To
download the current MDAC version, see the Data Access and Storage Developer Center.
Creating the Web Site
If you have already created a Web site in Visual Web Developer by completing
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and go to the next section.
Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the left-most Location list, click File System, and then in the right-most Location textbox, enter the name of the folder
where you want to keep the pages of the Web site.
For example, type the folder name C:\WebSites\ComponentSample.
5. In the Language list, click the programming language that you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Creating a Data-Access Component
In this walkthrough, you will use a wizard to generate a component that reads data from and writes data to the Northwind
database. The component includes a schema file (.xsd) describing the data that you want and the methods that will be used to
read and write data. You will not have to write any code. At run time, the .xsd file is compiled into an assembly that performs
the tasks that you specify in the wizard.
To create a data-access component
1. If the Web site does not already have an App_Code folder, do the following:
a. In Solution Explorer, right-click the name of the Web site.
b. Point to Add Folder, and then click App_Code Folder.
2. Right-click the App_Code folder, and then click Add New Item.
The Add New Item dialog box appears.
3. Under Visual Studio installed templates, click DataSet.
4. In the Name box, type EmployeesObject, and then click Add.
The TableAdapter Configuration wizard appears.
5. Click New Connection.
6. If the Choose Data Source dialog box appears, click Microsoft SQL Server and then click Continue.
7. In the Server name box, enter the name of the computer that is running SQL Server.
8. For the logon credentials, select the option that is appropriate for accessing the SQL Server database (integrated security
or specific ID and password) and if it is required, enter a user name and password.
If you specify explicit credentials, select the Save my password check box.
9. Click Select or enter a database name, and then enter Northwind.
10. Click Test connection, and when you are sure that the connection works, click OK.
The TableAdapter Configuration wizard appears with the connection information filled in.
11. Click Next.
A page where you can choose to store the connection string in the configuration file appears.
12. Select the Yes, save this connection as check box, and then click Next.
You can leave the default connection string name.
A page where you can choose to use SQL statements or stored procedures appears.
13. Click Use SQL statements, and then click Next.
Using stored procedures has some advantages, including performance and security. However, for simplicity in this
walkthrough, you will use an SQL statement.
A page where you can define the SQL statement appears.
14. Under What data should be loaded into the table, type the following SQL statement:

SELECT EmployeeID, LastName, FirstName, HireDate FROM Employees

Note
You can click Query Builder to use a builder tool, if you prefer.

15. Click Next.


A page where you can define the methods that the component will expose appears.
16. Click to clear the Fill a DataTable check box, and then select the Return a DataTable and Create methods to send
updates directly to the database check boxes.
You do not need a method to fill a data table for this walkthrough. However, you will need a method that returns the data
and you also want the component to contain methods that update the database.
17. In the Method Name box, type GetEmployees.
You are naming the method that will be used later to obtain data.
18. Click Finish.
The wizard configures the component and displays it in the component designer, displaying the data that the component
manages and the methods that the component exposes.
19. Save the data component, and then close the component designer.
20. On the Build menu, click Build Web Site to make sure that the component compiles correctly.
Using the Data Component on a Page
You can now use the data component as a data source in an ASP.NET Web page. To access the data component, you will use an
ObjectDataSource control, configuring it to call the data-access methods that are exposed by the data component. You can
then add controls to the page and bind them to the data source control.
To add a data source control to the page
1. Open the Default.aspx page and switch to Design view.
2. From the Data group in the Toolbox, drag an ObjectDataSource control onto the page.
If the ObjectDataSource Tasks shortcut menu does not appear, right-click the ObjectDataSource control, and
then click Show Smart Tag.
3. On the ObjectDataSource Tasks shortcut menu, click Configure Data Source.
The Configure Data Source wizard appears.
4. In the Choose your business object list, click EmployeesObjectTableAdapters.EmployeesTableAdapter.
This is the type name (namespace and class name) of the component that you created in the preceding section.
5. Click Next.
6. On the Select tab, in the Choose a method list, click GetEmployees(), returns EmployeesDataTable.
The GetEmployees method is a method that was defined in the component that you created in the preceding section. It
returns the results of the SQL statement, available in a DataTable object that data controls can bind to.
7. Click Finish.
You can now add data controls to the page and bind them to the ObjectDataSource control. In this walkthrough, you will
work with the GridView control.
To add a GridView control to the page and bind it to the data
1. From the Data group in the Toolbox, drag a GridView control onto the page.
If the GridView Tasks shortcut menu does not appear, right-click the GridView control, and then click Show
Smart Tag.
2. On the GridView Tasks shortcut menu, in the Choose Data Source list, click ObjectDataSource1, which is the ID of
the control that you configured in the preceding section.
The GridView control reappears with a column for each data column that is returned by the SQL statement.
3. In Properties, verify that the DataKeyNames is set to EmployeeID.
Testing the Page
Now that all controls that you need are on the page, you can test the page.
To test the page
1. Press CTRL+F5 to run the page.
2. Confirm that the EmployeeID, LastName, FirstName, and HireDate columns from the Employees table are displayed in
the grid.
3. Close the browser.
The GridView control requests data from the ObjectDataSource control. In turn, the ObjectDataSource control creates an
instance of the data component and calls GetEmployees method for the data component. The GetEmployees method
returns a DataTable object, which the ObjectDataSource control returns to the GridView control.
Adding Updates to the Page
The data component that you created includes SQL statements to update the database (update, insert, and delete records). The
update facilities of the data component are exposed by methods that were generated automatically when the wizard created
the component. The GridView control and ObjectDataSource control can interact to automatically start the update methods.
Note
The GridView control does not support Insert.

To enable updates and deletes


1. Right-click the GridView control, and then click Show Smart Tag.
2. Select the Enable Editing check box.
3. Select the Enable Deleting check box.
Note
Enabling deletion lets you permanently remove records from the database. Do not enable deletion unless you are work
ing with expendable test data.

Testing Updates
You can now test to make sure that you can use the component to update the database.
To test updates
1. Press CTRL+F5 to run the page.
This time, the GridView control displays Edit and Delete links in each row.
2. Click the Edit link that is next to a row.
3. Make a change to the row, and then click Update.
The grid is redisplayed with the updated date.
4. Click the Delete link that is in a row.
The row is permanently deleted from the database. The grid is redisplayed without that row.
5. Close the browser.
Next Steps
This walkthrough illustrates how to work with a data component. You might want to experiment with additional features of
navigation. For example, you might want to do the following:
Create a custom data component instead of using the wizard.
For an example, see Walkthrough: Data Binding to a Custom Business Object.
Restrict which users can change the data. A typical method is to add membership and roles to the Web site, and then
establish rules that the business component can check before allowing changes to data.
For detailed information, see Walkthrough: Creating a Web Site with Membership and User Login (Visual Studio) and
Walkthrough: Managing Web Site Users with Roles.
See Also
Tasks
Walkthrough: Using Shared Code in Web Sites in Visual Web Developer
Walkthrough: Creating a Basic Web Page in Visual Web Developer
Concepts
Data Source Controls Overview
Using Parameters with Data Source Controls
Visual Web Developer

Learning More — ASP.NET Data Access (Visual Studio)


The topics in this section provide essential information on adding data access to your ASP.NET Web pages in Visual Web
Developer.
In This Section
Walkthrough: Creating Master/Detail Web Pages in Visual Studio
Web Page Data Binding Techniques
Connecting to Databases in ASP.NET
Using SQL Server Express Edition with ASP.NET (Visual Studio)
Securing Data Access
See Also
Other Resources
ASP.NET Data Access (Visual Studio)
ASP.NET Web Server Controls (Visual Studio)
ASP.NET Web Pages (Visual Studio)
Visual Web Developer

Walkthrough: Creating Master/Detail Web Pages in Visual


Studio
Many Web pages display data in more than one way, often displaying data from related tables. This walkthrough shows you
various ways to work with data in multiple controls and from multiple tables, including those that have a master/detail
relationship. Tasks illustrated in this walkthrough include:
Populating a drop-down list with database data.
Creating filters — SQL statements with a WHERE clause (parameterized queries).
Displaying filtered data based on the user's selection in a drop-down list.
Displaying details about a selected record using the DetailsView control.
Selecting a record in one page and displaying a related record in a second page.
Prerequisites
In order to complete this walkthrough, you will need:
Access to the SQL Server Northwind database. For information about downloading and installing the SQL Server sample
Northwind database, see Installing Sample Databases on the Microsoft SQL Server Web site.
Note
If you need information about how to log on to the computer running SQL Server, contact the server administrator.

Microsoft Data Access Components (MDAC) version 2.7 or later.


If you are using Microsoft Windows XP or Windows Server 2003, you already have MDAC 2.7. However, if you are using
Microsoft Windows 2000, you might to need to upgrade the MDAC already installed on your computer. For more
information, see the article " Microsoft Data Access Components (MDAC) Installation" in the MSDN Library.
Creating the Web Site
If you have already created a Web site in Microsoft Visual Web Developer (for example, by following the steps in
Walkthrough: Creating a Basic Web Page in Visual Web Developer or Walkthrough: Basic Data Access in Web Pages), you can
use that Web site and skip to the next section, "Connecting to SQL Server." Otherwise, create a new Web site and page by
following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, enter the name of the folder where you want to keep the pages of your Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click the programming language you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Connecting to SQL Server
To work with data, you need to establish a connection to a database. In this walkthrough, you will create a connection
independently of working with Web pages or controls.
To create a connection to SQL Server
1. Press CTRL+ALT+S to display the Database Explorer. In Database Explorer, right-click Data Connections and choose
Add Connection.
The Change Data Source dialog box is displayed.
2. In the Change Data Source dialog box, select Microsoft SQL Server. and click OK.
3. In the Add Connection dialog box, do the following:
Enter or select the name of your SQL Server computer. For a server on your computer, enter (local).
Select Use SQL Server Authentication.
Enter a user name and password.
Select Save my password.
Select Northwind as the database.
4. Click Test Connection, and when you are sure that it works, click OK.
The connection is added to Server Explorer.
Using a Drop-Down List as the Master
In this part of the walkthrough, you will add a drop-down list to a page and populate it with a list of categories from the
Northwind table. When users select a category, the page will display the products for that category.
To create and populate a drop-down list
1. Switch to or open the Default.aspx page. If you are working with a Web site you had already created, add or open a page
that you can work with in this walkthrough.
2. Switch to Design view.
3. Type Select Products By Category in the page and format the text as a heading using the Block Format drop-down list
above the Toolbox.
4. From the Standard group in the Toolbox, drag a DropDownList control onto the page.
5. In the DropDownList Tasks, select the Enable AutoPostBack check box.
This configures the control so that it causes the page to post back to the server whenever a selection is made from the
list, rather than waiting until the user clicks a button.
6. In the DropDownList Tasks, select Choose Data Source.
The Choose Data Source wizard starts.
7. In the Select a data source list, click <New Data Source>.
The Data Source Configuration Wizard dialog box is displayed.
8. Select Database.
This specifies that you want to get data from a database that supports SQL statements. (This includes SQL Server and
other OLE-DB-compatible databases.)
In the Specify an ID for the data source box, a default data source control name is displayed (SqlDataSource1). You
can leave this name.
9. Click OK.
The wizard displays the Configure Data Source - SqlDataSource1 page in which you can select a data connection.
10. From the drop-down list, select the Northwind connection you created earlier in the walkthrough.
11. Click Next.
The wizard displays a page in which you can choose to store the connection string in the configuration file.
12. Be sure the Yes, save this connection as check box is selected, and then click Next. (You can leave the default
connection string name.)
The wizard displays a page in which you can specify what data you want to retrieve from the database.
13. From the Name list under Table or View Options, select Categories.
14. In the Columns box, select CategoryID and CategoryName.
15. Click Next.
16. Click Test Query to be sure that you are getting the data you want.
17. Click Finish.
The Data Source Configuration Wizard is displayed, with the name of the data source control you have configured
displayed.
18. From the Select a data field to display in the DropDownList list, select CategoryName.
Note
If no items appear in the list, click the Refresh Schema link.

This specifies that the value of the CategoryName field will be displayed as the text of the item in the drop-down list.
19. From the Select a data field for the value of the DropDownList list, select CategoryID.
This specifies that when an item is selected, the CategoryID field will be returned as the value of the item.
20. Click OK.
Before proceeding, test the drop-down list.
To test the drop-down list
1. Press CTRL+F5 to run the page.
2. When the page is displayed, examine the drop-down list.
3. Select a category to be sure that the list performs a postback.
You can now display products for the category selected in the drop-down list.
Using a Grid to Display Detail Information
You can now extend the page to include a grid. When users make a selection from the categories drop-down list, the grid will
display the products for that category.
To use a grid to display detail information
1. Switch to or open the Default.aspx page (or the page you have been working with), and switch to Design view.
2. From the Data group of the Toolbox, drag a GridView control onto the page.
3. From the GridView Tasks menu, select <New Data Source> from the Choose Data Source list.
The Data Source Configuration Wizard opens.
4. Select Database.
In the Specify an ID for the data source box, a default data source control name is displayed (SqlDataSource2). You
can leave this name.
5. Click OK.
The wizard displays a page where you can select a connection.
6. From the connections drop-down list, select the connection you created and stored earlier in the walkthrough
(NorthwindConnectionString).
7. Click Next.
The wizard displays the Configure Data Source - SqlDataSource2 page in which you can create a SQL statement.
8. From the Name list, select Products.
9. In the Columns box, select ProductID, ProductName, and CategoryID.
10. Click WHERE.
The Add WHERE Clause dialog box is displayed.
11. From the Column list, select CategoryID.
12. From the Operator list, select =.
13. From the Source list, select Control.
14. Under Parameter Properties, in the Control ID list, select DropDownList1.
The last two steps specify that the query will get the search value for the category ID from the DropDownList control you
added earlier.
15. Click Add.
16. Click OK to close the Add WHERE Clause dialog box.
17. Click Next.
18. In the Preview page, click Test Query.
The wizard displays a dialog box that prompts you for a value to use in the WHERE clause.
19. Type 4 in the box and click OK.
The products records for category 4 are displayed.
20. Click Finish to close the wizard.
You can now test the master/detail display.
To test the page
1. Press CTRL+F5 to run the page.
When the page appears, products from the first item in the drop-down list are displayed.
2. Select a category from the list and confirm that the corresponding products appear in the grid.
Displaying Master/Detail Data on the Same Page
In this part of the walkthrough, you will display data from related tables in one page. The master table data is displayed in a
grid where users can select individual rows. When they do, one or more detail records are displayed in a scrollable control
elsewhere on the page. For illustration purposes, you will use the Northwind Categories table as the master table and the
Products table as the details table.
To display the master records
1. Add a new page to the Web site and name it MasterDetails2.aspx.
2. Switch to Design view.
3. Type Master/Detail Page in the page and format the text as a heading.
4. From the Data group of the Toolbox, drag a GridView control onto the page.
5. In the GridView Tasks menu, in the Choose Data Source list, click <New Data Source> and then use these steps to
configure a data source for the GridView control:
a. Select Database.
b. Click OK.
c. From the connection drop-down list, select the connection you created and stored earlier in the walkthrough
(NorthwindConnectionString).
d. Click Next.
e. From the Name list, select Categories.
f. In the Columns box, select CategoryID and CategoryName.
g. Click Next and then click Finish.
6. Select the GridView control, and in the GridView Tasks menu, choose Edit Columns.
The Fields dialog box is displayed.
7. Under Available Fields, open the Command Field node, choose Select, and then click Add to add it to the Selected
Fields list.
8. In the Selected Fields list, choose Select, and then in the CommandField property grid, set its SelectText property to
Details.
9. Click OK to close the Fields dialog box.
A new column with a Details hyperlink is added to the grid.
10. Select the GridView control and in the Properties window, be sure its DataKeyNames property is set to CategoryID.
This specifies that when you select a row in the grid, ASP.NET can find the key of the currently displayed Categories
record in a known location.
The grid allows you to select an individual category. The next step is to add the DetailsView control that will display the detail
records — the products associated with the selected category. The DetailsView control will use a different SQL query to get its
data, so it requires a second data source control.
To configure a query to display related records
1. Press ENTER to make space underneath the SqlDataSource1 control on the MasterDetails2.aspx page in Details view.
2. From the Data group of the Toolbox, drag a DetailsView control onto the page.
3. Configure it to use a second data source control using the following steps:
a. From the Choose Data Source list, select <New Data Source>.
b. Select Database.
c. Click OK.
d. In the connection drop-down list, click the connection you created and stored earlier in the walkthrough.
e. Click Next.
f. From the Name list under Table or View Options, select Products.
g. In the Columns box, select ProductID, ProductName, and CategoryID.
h. Click WHERE.
The Add WHERE Clause dialog box is displayed.
i. From the Column list, select CategoryID.
j. From the Operator list, select =.
k. From the Source list, select Control.
l. Under Parameter Properties, in the Control ID list, select GridView1. The query for the second grid will get its
parameter value from the selection in the first grid.
m. Click Add and then click OK to close the Add WHERE Clause dialog box.
n. Click Next.
o. In the Preview page, click Test Query.
The wizard displays a dialog box that prompts you for a value to use in the WHERE clause.
p. Type 4 in the box and click OK.
The products records for category 4 are displayed.
q. Click Finish.
4. In the DetailsView Tasks menu, check Enable Paging.
This will allow you to scroll through individual product records.
5. Optionally, in the Properties window, open the PagerSettings node and select a different Mode value.
By default, you page through records by clicking a page number, but you can select options to use next and previous
links.
You can now test the combination of the master grid and the details view.
To test the page
1. Press CTRL+F5 to run the page.
2. In the grid, select a category.
The DetailsView control displays a product associated with that category.
3. Use the pager links in the DetailsView control to navigate to other products for the same category.
4. In the grid, select a different category.
5. Review the products for that category in the DetailsView control.
Displaying Master/Detail Data on Separate Pages
For the final part of the walkthrough, you will create another variation — displaying master and detail records on separate
pages. The master records are again displayed in a grid that contains a hyperlink for each record. When users click the
hyperlink, they navigate to a second page where they can view detail records in a DetailsView control that displays the
complete Products record.
To display the master records
1. Add a new page to the Web site and name it MasterCustomers.aspx.
2. Switch to Design view.
3. Type Customers in the page and format the text as a heading.
4. From the Data folder of the Toolbox, drag a GridView control onto the page.
5. From the GridView Tasks menu on the control, choose <New Data Source> from the Choose Data Source list and
then use the wizard to do the following:
Click Database.
Connect to the Northwind database (connection NorthwindConnectionString).
Retrieve the CustomerID, CompanyName, and City columns from the Customers table.
6. Optionally, on the GridView Tasks menu, select the Enable paging check box.
7. In the GridView Tasks menu, choose Edit Columns.
The Fields dialog box is displayed.
8. Clear the Auto-Generate Fields check box.
9. Under Available Fields, choose HyperLink Field, click Add, and then set the following properties:
Property Value
Text Details

DataNavigat CustomerID
eUrlFields
This indicates that the hyperlink should get its value from the CustomerID column

DataNavigat DetailsOrders.aspx?custid={0}
eUrlFormatSt
ring This creates a link that is hard-coded to navigate to the DetailsOrders.aspx page. The link also passes a qu
ery string variable named custid whose value will be filled using the column referenced in the DataNavi
gateUrlFields property.

10. Click OK to close the Fields dialog box.


You can now create the details page that accepts a value from the master page.
To create the details page
1. Add a new page to the Web site and name it DetailsOrders.aspx.
2. Switch to Design view.
3. Type Orders in the page and format the text as a heading.
4. From the Data folder of the Toolbox, drag a GridView control onto the page.
5. In the GridView Tasks menu on the control, select <New Data Source> from the Choose Data Source list
6. In the Select a data source type list, click Database and then click OK.
7. From the connection list, select the connection you created and stored earlier in the walkthrough
(NorthwindConnectionString).
8. Click Next.
The wizard displays a page where you can create a SQL statement.
9. From the Name list, select Orders.
10. In the Columns box, select OrderID, CustomerID, and OrderDate.
11. Click WHERE.
12. From the Columns list, select CustomerID.
13. From the Operators list, select =.
14. From the Source list, select QueryString.
This specifies that the query will select records based on the value passed into the page with the query string.
15. Under Parameter Properties, in the QueryString field box, type custid.
The query will get the customer ID value from the query string, which is created when you click a Details link in the
MasterCustomers.aspx page.
16. Click Add.
17. Click OK to close the Add WHERE Clause dialog box.
18. Click Next, and then click Finish to close the wizard.
19. From the Standard node of the Toolbox, drag a Hyperlink control onto the page. Set its Text property to Return to
Customers and its NavigateUrl property to MasterCustomers.aspx.
You can now test the related master-detail pages.
To test the pages
1. Switch to the MasterCustomers.aspx page.
2. Press CTRL+F5 to run the page.
3. Click the Details link for a customer.
The browser displays the DetailsOrders.aspx page with the order for the selected customer. Note that the URL in the
browser's Address box is:

DetailsOrder.aspx?custid=x

where x is the ID of the customer you selected.


4. Click the Return to Customers link, select a different customer, and click the Details link again to test that you can view
orders for any customer.
Next Steps
This walkthrough has illustrated various ways to display data from related tables. All the scenarios have the following in
common: they rely on a parameterized query, and the parameter values can be passed to the query automatically at run time.
You might want to experiment with additional ways to use related data. For example, you might want to:
Experiment with parameters that get their values from other sources, such as a Session variable or a cookie. For more
information, see Using Parameters with Data Source Controls.
Expand what you can do with the DetailsView control from the second part of the walkthrough. For example, you can
configure the control to allow users to edit detail records. For details, see
Walkthrough: Editing and Inserting Data in Web Pages with the DetailsView Web Server Control.
See Also
Concepts
Data Source Controls Overview
Modifying Data using Data Source Controls
Visual Web Developer

Web Page Data Binding Techniques


The topics in this section provide essential information on how you can connect controls on ASP.NET Web pages to a variety of
data.
In This Section
Binding to Databases
Binding to Hierarchical Data
Binding to Business Objects
Walkthrough: Data Binding to a Custom Business Object
Data-Binding Expression Syntax
How to: Bind to Data in a Templated Control in Visual Studio
See Also
Other Resources
ASP.NET Data Access (Visual Studio)
Data Toolbox Controls
ASP.NET Web Server Controls (Visual Studio)
ASP.NET Web Pages (Visual Studio)
ASP.NET

Binding to Databases
Web applications commonly display data that comes from a relational database such as Microsoft SQL Server, Microsoft
Access, Oracle, or an OLEDB or ODBC data store. To simplify the task of binding a control to data from a database, ASP.NET
provides the SqlDataSource control.
The SqlDataSource Control
The SqlDataSource control represents a direct connection to a database in a Web application. Data-bound controls such as
the GridView, DetailsView, and FormView controls can use the SqlDataSource control to retrieve and modify data
automatically. You specify commands to select, insert, update, and delete data as part of the SqlDataSource control, and the
control performs these operations automatically. You do not need to write code (for example, ADO.NET code that uses classes
in the System.Data namespace) to create a connection and specify commands to query and update a database.
The following code example shows a GridView control bound to a SqlDataSource control to retrieve, update, and delete data.
VB

<%@ Page language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>GridView Edit Example</title>
</head>
<body>
<form id="form1" runat="server">

<h3>GridView Edit Example</h3>

<!-- The GridView control automatically sets the columns -->


<!-- specified in the datakeynames property as read-only. -->
<!-- No input controls are rendered for these columns in -->
<!-- edit mode. -->
<asp:gridview id="CustomersGridView"
datasourceid="CustomersSqlDataSource"
autogeneratecolumns="true"
autogeneratedeletebutton="true"
autogenerateeditbutton="true"
datakeynames="CustomerID"
runat="server">
</asp:gridview>

<!-- This example uses Microsoft SQL Server and connects -->
<!-- to the Northwind sample database. Use an ASP.NET -->
<!-- expression to retrieve the connection string value -->
<!-- from the Web.config file. -->
<asp:sqldatasource id="CustomersSqlDataSource"
selectcommand="Select [CustomerID], [CompanyName], [Address], [City], [PostalCode],
[Country] From [Customers]"
updatecommand="Update Customers SET CompanyName=@CompanyName, Address=@Address, Cit
y=@City, PostalCode=@PostalCode, Country=@Country WHERE (CustomerID = @CustomerID)"
deletecommand="Delete from Customers where CustomerID = @CustomerID"
connectionstring="<%$ ConnectionStrings:NorthWindConnectionString%>"
runat="server">
</asp:sqldatasource>
</form>
</body>
</html>
C#

<%@ Page language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>GridView Edit Example</title>
</head>
<body>
<form id="form1" runat="server">
<h3>GridView Edit Example</h3>

<!-- The GridView control automatically sets the columns -->


<!-- specified in the datakeynames property as read-only. -->
<!-- No input controls are rendered for these columns in -->
<!-- edit mode. -->
<asp:gridview id="CustomersGridView"
datasourceid="CustomersSqlDataSource"
autogeneratecolumns="true"
autogeneratedeletebutton="true"
autogenerateeditbutton="true"
datakeynames="CustomerID"
runat="server">
</asp:gridview>
<!-- This example uses Microsoft SQL Server and connects -->
<!-- to the Northwind sample database. Use an ASP.NET -->
<!-- expression to retrieve the connection string value -->
<!-- from the Web.config file. -->
<asp:sqldatasource id="CustomersSqlDataSource"
selectcommand="Select [CustomerID], [CompanyName], [Address], [City], [PostalCode],
[Country] From [Customers]"
updatecommand="Update Customers SET CompanyName=@CompanyName, Address=@Address, Cit
y=@City, PostalCode=@PostalCode, Country=@Country WHERE (CustomerID = @CustomerID)"
deletecommand="Delete from Customers where CustomerID = @CustomerID"
connectionstring="<%$ ConnectionStrings:NorthWindConnectionString%>"
runat="server">
</asp:sqldatasource>

</form>
</body>
</html>

The SqlDataSource control directly connects to a database and therefore implements a two-tiered data model. If you need to
bind to a middle-tier business object which performs data retrieval and updates, you can use the ObjectDataSource control. For
details, see Binding to Business Objects.
For more information about the SqlDataSource control, see the SqlDataSource Web Server Control Overview.
Binding to a Microsoft Access Database
ASP.NET provides an AccessDataSource control that simplifies the task of connecting to a Microsoft Access database file (.mdb
file). The AccessDataSource class inherits from the SqlDataSource class and automatically connects to an .mdb file using the
System.Data.OleDb .NET Framework data provider and the Microsoft.Jet.OLEDB.4.0 OLE DB provider. To connect to an
Access database, you supply a file path as the DataFile property. Other than the difference in how the AccessDataSource
control connects to a Microsoft Access database, the control works exactly like the SqlDataSource control. For more
information, see Retrieving Data Using the AccessDataSource Web Server Control.
See Also
Concepts
ASP.NET Data Access Overview
SqlDataSource Web Server Control Overview
Retrieving Data Using the AccessDataSource Web Server Control
ASP.NET

Binding to Hierarchical Data


Data source controls can work with either tabular data (table-based or relational data) or hierarchical data, or both. The
SqlDataSource and ObjectDataSource controls are examples of data source controls that work with tabular data. ASP.NET also
includes two data source controls that make it easy to bind to hierarchical data: the XmlDataSource control, which works with
XML from a file or a string, and the SiteMapDataSource control, which works with site navigation data (which by default is
maintained as XML data). Hierarchical data source controls are used in read-only scenarios to display data.
This topic provides more information about binding data-bound controls to a hierarchical data source. For additional
information on the XmlDataSource and SiteMapDataSource controls, see XmlDataSource Control Overview and
SiteMapDataSource Web Server Control Overview.
Binding a Hierarchical Control to XML Data
XML is intrinsically hierarchical in structure, and can be displayed in ASP.NET Web pages using hierarchical data-bound
controls such as the TreeView or Menu control. You can bind to a hierarchical data source control by setting the hierarchical
control's DataSourceID property to the ID of a XmlDataSource or SiteMapDataSource control.
The following code example shows a TreeView control bound to an XmlDataSource control. The XML data is filtered using an
XPath query.
VB
<%@ Page Language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">

<script runat="server">

Sub SelectRegion(sender As Object, e As EventArgs)


If RegionDropDownList.SelectedValue = "(Show All)" Then
PeopleDataSource.XPath = "/People/Person"
Else
Dim selectedValue As String = ""

Select Case RegionDropDownList.SelectedValue


Case "CA"
selectedValue = "CA"
Case "HI"
selectedValue = "HI"
Case "WA"
selectedValue = "WA"
Case Else
' Invalid value.
End Select

PeopleDataSource.XPath = "/People/Person[Address/Region='" & selectedValue & "']"


End If

PeopleTreeView.DataBind()
End Sub
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">
<table border="0" cellpadding="3">
<tr>
<td valign="top">
<b>Select Region:</b>
<asp:DropDownList runat="server" id="RegionDropDownList" AutoPostBack="True"
OnSelectedIndexChanged="SelectRegion">
<asp:ListItem Selected="True">(Show All)</asp:ListItem>
<asp:ListItem>CA</asp:ListItem>
<asp:ListItem>HI</asp:ListItem>
<asp:ListItem>WA</asp:ListItem>
</asp:DropDownList>
</td>
<td valign="top">
<asp:XmlDataSource
id="PeopleDataSource"
runat="server"
XPath="/People/Person"
DataFile="~/App_Data/people.xml" />
<asp:TreeView
id="PeopleTreeView"
runat="server"
DataSourceID="PeopleDataSource">
<DataBindings>
<asp:TreeNodeBinding DataMember="LastName" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="FirstName" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="Street" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="City" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="Region" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="ZipCode" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="Title" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="Description" TextField="#InnerText" />
</DataBindings>
</asp:TreeView>
</td>
</tr>
</table>
</form>
</body>
</html>

C#
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1
/DTD/xhtml1-transitional.dtd">

<script runat="server">

void SelectRegion(object sender, EventArgs e)


{
if (RegionDropDownList.SelectedValue == "(Show All)")
PeopleDataSource.XPath = "/People/Person";
else
{
string selectedValue = "";

switch (RegionDropDownList.SelectedValue)
{
case "CA":
selectedValue = "CA";
break;
case "HI":
selectedValue = "HI";
break;
case "WA":
selectedValue = "WA";
break;
default:
// Invalid value.
break;
}
PeopleDataSource.XPath = "/People/Person[Address/Region='" + selectedValue + "']";
}

PeopleTreeView.DataBind();
}

</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">
<table border="0" cellpadding="3">
<tr>
<td valign="top">
<b>Select Region:</b>
<asp:DropDownList runat="server" id="RegionDropDownList" AutoPostBack="True"
OnSelectedIndexChanged="SelectRegion">

<asp:ListItem Selected="True">(Show All)</asp:ListItem>


<asp:ListItem>CA</asp:ListItem>
<asp:ListItem>HI</asp:ListItem>
<asp:ListItem>WA</asp:ListItem>
</asp:DropDownList>
</td>
<td valign="top">
<asp:XmlDataSource
id="PeopleDataSource"
runat="server"
XPath="/People/Person"
DataFile="~/App_Data/people.xml" />
<asp:TreeView
id="PeopleTreeView"
runat="server"
DataSourceID="PeopleDataSource">
<DataBindings>
<asp:TreeNodeBinding DataMember="LastName" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="FirstName" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="Street" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="City" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="Region" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="ZipCode" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="Title" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="Description" TextField="#InnerText" />
</DataBindings>
</asp:TreeView>
</td>
</tr>
</table>
</form>
</body>
</html>

Binding a Tabular Control to XML Data


While the XmlDataSource control is used primarily to expose XML data to hierarchical data-bound controls such as the
TreeView and Menu controls, you can also bind tabular data-bound controls such as a GridView or DataList control to the
XmlDataSource control.
When you bind a tabular data-bound control to the XmlDataSource control, the data-bound control renders only the first
level of the XML hierarchy. However, in a data-bound control template, you can also use the XPath and XPathSelect data-
binding methods to bind to specific elements within the XML hierarchy. The XPath data-binding method returns a value from
a node or an attribute anywhere in the hierarchy. The XPathSelect method returns a list of nodes that match an XPath
expression, which the tabular data control can work with as if they were a collection of data records.
For more information and examples, see Binding a Tabular Control to the XmlDataSource Control.
Other Forms of Hierarchical Data
In addition to binding controls to a XmlDataSource control as shown in this topic, you can also bind a hierarchical control to a
sitemap file. For more information, see ASP.NET Site Maps. The following code example shows how to bind a Menu control to
a SiteMapDataSource control.
VB

<%@ Page Language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >

<!-- For the hover styles of the Menu control to -->


<!-- work correctly, you must include this head -->
<!-- element. -->
<head runat="server">
<title>Menu DataBinding Example</title>
</head>

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

<h3>Menu DataBinding Example</h3>

<!-- Bind the Menu control to a SiteMapDataSource control. -->


<asp:menu id="NavigationMenu"
disappearafter="2000"
staticdisplaylevels="2"
staticsubmenuindent="10"
orientation="Vertical"
font-names="Arial"
target="_blank"
datasourceid="MenuSource"
runat="server">

<staticmenuitemstyle backcolor="LightSteelBlue"
forecolor="Black"/>
<statichoverstyle backcolor="LightSkyBlue"/>
<dynamicmenuitemstyle backcolor="Black"
forecolor="Silver"/>
<dynamichoverstyle backcolor="LightSkyBlue"
forecolor="Black"/>

</asp:menu>

<asp:SiteMapDataSource id="MenuSource"
runat="server"/>
</form>
</body>
</html>

C#

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

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >

<!-- For the hover styles of the Menu control to -->


<!-- work correctly, you must include this head -->
<!-- element. -->
<head runat="server">
<title>Menu DataBinding Example</title>
</head>

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

<h3>Menu DataBinding Example</h3>

<!-- Bind the Menu control to a SiteMapDataSource control. -->


<asp:menu id="NavigationMenu"
disappearafter="2000"
staticdisplaylevels="2"
staticsubmenuindent="10"
orientation="Vertical"
font-names="Arial"
target="_blank"
datasourceid="MenuSource"
runat="server">

<staticmenuitemstyle backcolor="LightSteelBlue"
forecolor="Black"/>
<statichoverstyle backcolor="LightSkyBlue"/>
<dynamicmenuitemstyle backcolor="Black"
forecolor="Silver"/>
<dynamichoverstyle backcolor="LightSkyBlue"
forecolor="Black"/>
</asp:menu>

<asp:SiteMapDataSource id="MenuSource"
runat="server"/>

</form>
</body>
</html>

To create data for the example, you can copy the following sample site map data to a file in your Web application named
Web.sitemap.
<siteMap>
<siteMapNode url="~\Home.aspx"
title="Home"
description="Home">
<siteMapNode url="~\Music.aspx"
title="Music"
description="Music">
<siteMapNode url="~\Classical.aspx"
title="Classical"
description="Classical"/>
<siteMapNode url="~\Rock.aspx"
title="Rock"
description="Rock"/>
<siteMapNode url="~\Jazz.aspx"
title="Jazz"
description="Jazz"/>
</siteMapNode>
<siteMapNode url="~\Movies.aspx"
title="Movies"
description="Movies">
<siteMapNode url="~\Action.aspx"
title="Action"
description="Action"/>
<siteMapNode url="~\Drama.aspx"
title="Drama"
description="Drama"/>
<siteMapNode url="~\Musical.aspx"
title="Musical"
description="Musical"/>
</siteMapNode>
</siteMapNode>
</siteMap>

See Also
Reference
TreeView Web Server Control Overview
Concepts
XmlDataSource Control Overview
Binding a Tabular Control to the XmlDataSource Control
SiteMapDataSource Web Server Control Overview
Other Resources
Menu Web Server Control
ASP.NET

Binding to Business Objects


Business applications commonly employ an encapsulated data model using a middle- tier data access layer or business
component. Typically, in a Web application, you must write not only the code for the business data object, but additional code
to communicate with the component, and more code to bind controls to the data managed by the component. The ASP.NET
data source control model simplifies working with a business component and greatly reduces or eliminates the code you must
write by providing the ObjectDataSource control.
The ObjectDataSource Control
The ObjectDataSource control works with any business object that encapsulates data and provides data-management
services. The ObjectDataSource control uses the standard data source control object model, so that data-bound controls,
such as the GridView control, can bind to it. The source business object can manage the data access directly or can serve as a
wrapper for an existing business component. For more information, see Creating an ObjectDataSource Control Source Object.
You associate an ObjectDataSource control with a business object by setting the ObjectDataSource control's TypeName
property to the type (class name) of the business object. You then specify one or more methods of the business object that the
ObjectDataSource will call for specific data operations. The SelectMethod property of the ObjectDataSource control
identifies the method of the source business object that will be used to retrieve data. Likewise, the InsertMethod,
UpdateMethod, and DeleteMethod properties identify the methods that will be used for insert, update, and delete operations,
respectively.
Once you have associated your ObjectDataSource control with the business object, you can bind a control to the
ObjectDataSource control using the data-bound control's DataSourceID property, as shown in the following example.
VB
<%@ Register TagPrefix="aspSample" Namespace="Samples.AspNet.VB" Assembly="Samples.AspNet.V
B" %>
<%@ Page language="vb" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>ObjectDataSource - Visual Basic Example</title>
</head>
<body>
<form id="Form1" method="post" runat="server">
<asp:gridview
id="GridView1"
runat="server"
datasourceid="ObjectDataSource1" />
<asp:objectdatasource
id="ObjectDataSource1"
runat="server"
selectmethod="GetAllEmployees"
typename="Samples.AspNet.VB.EmployeeLogic" />

</form>
</body>
</html>

C#
<%@ Register TagPrefix="aspSample" Namespace="Samples.AspNet.CS" Assembly="Samples.AspNet.C
S" %>
<%@ Page language="c#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>ObjectDataSource - C# Example</title>
</head>
<body>
<form id="Form1" method="post" runat="server">

<asp:gridview
id="GridView1"
runat="server"
datasourceid="ObjectDataSource1" />
<asp:objectdatasource
id="ObjectDataSource1"
runat="server"
selectmethod="GetAllEmployees"
typename="Samples.AspNet.CS.EmployeeLogic" />

</form>
</body>
</html>

J#
<%@ Register TagPrefix="aspSample" Namespace="Samples.AspNet.JSL" Assembly="Samples.AspNet.
JSL" %>
<%@ Page language="VJ#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>ObjectDataSource - VJ# Example</title>
</head>
<body>
<form id="Form1" method="post" runat="server">

<asp:gridview
id="GridView1"
runat="server"
datasourceid="ObjectDataSource1" />

<asp:objectdatasource
id="ObjectDataSource1"
runat="server"
selectmethod="GetAllEmployees"
typename="Samples.AspNet.JSL.EmployeeLogic" />

</form>
</body>
</html>

For more details, see the topics in the ObjectDataSource Web Server Control section.
See Also
Other Resources
ObjectDataSource Web Server Control
Visual Web Developer

Walkthrough: Data Binding to a Custom Business Object


Many Web applications are built by using multiple tiers, with one or more components in the middle tier to provide data
access. Microsoft Visual Web Developer includes a wizard that helps you create a data component you can use as a middle-tier
data object, as described in Walkthrough: Data Binding Web Pages with a Visual Studio Data Component.
However, you might also want to build a custom business object, rather than relying on the data component created by the
wizard. Creating a custom business object allows you to implement your own business logic. This walkthrough illustrates how
to create a basic business object that you can use as a data source for ASP.NET Web pages.
During this walkthrough, you will learn how to:
Create a component that can return data to a Web page. The component uses an XML file for its data.
Reference the business object as a data source on a Web page.
Bind a control to the data returned by the business object.
Read and write data by using the business object.
Prerequisites
In order to complete this walkthrough, you will need:
Visual Web Developer (Visual Studio).
The .NET Framework.
This walkthrough assumes that you have a general understanding of how to use Visual Web Developer.
Creating the Web Site
If you have already created a Web site in Visual Web Developer (for example, by following the steps in
Walkthrough: Creating a Basic Web Page in Visual Web Developer), you can use that Web site and go to the next section,
"Creating an XML File for Business Data." Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, enter the name of the folder where you want to keep the pages of your Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click the programming language you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Creating an XML File for Business Data
In the following procedure, you will create a simple XML file for the business component data.
To create the XML file
1. In Solution Explorer, right-click App_Data, and then click Add New Item.
Note
Be sure you create the XML file in the App_Data folder. The App_Data folder has permissions set on it that will allow t
he Web page to read and write data to the XML file.
2. Under Visual Studio installed templates, click XML file.
3. In the Name box, type Authors.xml.
4. Click Add.
A new XML file is created that contains only the XML directive.
5. Copy the following XML data, and then paste it into the file, overwriting what is already in the file.
The XML file includes schema information that identifies the database structure of the data, including a primary-key
constraint for the key.
Note
Business components can work with data in any way that is suitable for your application. This walkthrough uses an XM
L file.

<?xml version="1.0" standalone="yes"?>


<dsPubs xmlns="http://www.tempuri.org/dsPubs.xsd">
<xs:schema id="dsPubs" targetNamespace="http://www.tempuri.org/dsPubs.xsd" xmlns:mstns
="http://www.tempuri.org/dsPubs.xsd" xmlns="http://www.tempuri.org/dsPubs.xsd" xmlns:x
s="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdat
a" attributeFormDefault="qualified" elementFormDefault="qualified">
<xs:element name="dsPubs" msdata:IsDataSet="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="authors">
<xs:complexType>
<xs:sequence>
<xs:element name="au_id" type="xs:string" />
<xs:element name="au_lname" type="xs:string" />
<xs:element name="au_fname" type="xs:string" />
<xs:element name="au_phone" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
<xs:unique name="Constraint1" msdata:PrimaryKey="true">
<xs:selector xpath=".//mstns:authors" />
<xs:field xpath="mstns:au_id" />
</xs:unique>
</xs:element>
</xs:schema>
<authors>
<au_id>172-32-1176</au_id>
<au_lname>West</au_lname>
<au_fname>Paul</au_fname>
<au_phone>408 555-0123</au_phone>
</authors>
<authors>
<au_id>213-46-8915</au_id>
<au_lname>Gray</au_lname>
<au_fname>Chris</au_fname>
<au_phone>415 555-0120</au_phone>
</authors>
</dsPubs>

6. Save the Authors.xml file, and then close it.


Creating a Component
The next step is to create a class to act as your business component. You will keep the component in the App_Code folder of
your Web site. In a real application, you can keep the component in any convenient store, including the global assembly cache.
If your Web site does not already have a directory named App_Code, you must create one.
To create an App_Code folder
In Solution Explorer, right-click the name of your Web site, click Add ASP.NET Folder, and then click App_Code.
Note
The folder must be named App_Code.

You can now add the component to your site.


To create the business component
1. In Solution Explorer, right-click the App_Code folder, and then click Add New Item.
Note
Be sure to create the new item in the App_Code folder.

The Add New Item dialog box appears.


2. Under Visual Studio installed templates, click Class.
3. In the Language box, click the programming language you prefer.
4. In the Name box, type BusinessObject.
5. Click Add.
Visual Web Developer creates the new class file and opens the code editor.
6. Copy the following code, and then paste it into the file, overwriting what is already in the file.
VB
Imports Microsoft.VisualBasic
Imports System
Imports System.Web
Imports System.Data
Namespace PubsClasses
Public Class AuthorClass
Private dsAuthors As DataSet = _
New System.Data.DataSet("ds1")
Private filePath As String = _
HttpContext.Current.Server.MapPath _
("~/App_Data/authors.xml")
Public Sub New()
dsAuthors.ReadXml(filePath, Data.XmlReadMode.ReadSchema)
End Sub

Public Function GetAuthors() As DataSet


Return dsAuthors
End Function
End Class
End Namespace

C#
using System;
using System.Web;
using System.Data;
namespace PubsClasses
{
public class AuthorClass
{
private DataSet dsAuthors = new DataSet("ds1");
private String filePath =
HttpContext.Current.Server.MapPath
("~/App_Data/Authors.xml");
public AuthorClass()
{
dsAuthors.ReadXml (filePath, XmlReadMode.ReadSchema);
}
public DataSet GetAuthors ()
{
return dsAuthors;
}
}
}

Note
Make sure the value of the filePath variable references the name of the XML file that you created previously.

When an instance of the class is created, it reads the XML file and translates it into a dataset. The class's GetAuthors
method returns the dataset.
7. Save the file. You must save the file for the next section to work properly.
Displaying Data by Using the Business Component
You can now invoke the business component in a Web page and display its data. To reference the component, you use an
ObjectDataSource control, which is specifically designed to work with objects.
To create an ObjectDataSource control that references the component
1. Switch to or open the Default.aspx page.
Note
If you do not have a Default.aspx page, you can use another page. Alternatively, you can add a new page to the Web sit
e. In Solution Explorer, right-click the name of your Web site, click Add New Item, and then add a Web Form.

2. Switch to Design view.


3. In the Toolbox, from the Data folder, drag an ObjectDataSource control onto the page.
4. In the Properties window, set ID to AuthorsObjectDataSource.
5. Right-click the ObjectDataSource control, and then click the smart tag to display the ObjectDataSource Tasks menu.
6. On the ObjectDataSource Tasks menu, click Configure Data Source.
The Configure Data Source wizard appears.
7. In the Choose your business object list, click PubsClasses.AuthorClass.
8. Click Next.
9. In the Select tab, in the Choose a method list, click GetAuthors(), returns Dataset.
The GetAuthors method is defined in the business class you created previously. It returns a dataset containing the data
from the Authors.xml file.
10. Click Finish.
The configuration information you have entered specifies that to get data from the component, the component's
GetAuthors method should be called.

Note
The name of the method you specify for the SelectMethod property is case-sensitive, even if you are programming in V
isual Basic .NET.

You can now get data from the component by using the ObjectDataSource control. You will display the data in a GridView
control on the page.
To display data from the component
1. In the Toolbox, from the Data folder, drag a GridView control onto the page.
2. Right-click the GridView control, and then click the smart tag if the Common GridView Tasks menu is not showing.
3. On the Common GridView Tasks menu, in the Choose Data Source box, click AuthorsObjectDataSource.
4. Press CTRL+F5 to run the page.
The GridView control with the XML data in it is displayed.
Inserting Data by Using the Business Component
As with other data source controls, such as the SqlDataSource control, the ObjectDataSource control supports updating
(inserting, updating, and deleting). In this section, you will modify the business component with a method that inserts an
author record. Then you will change the page so that users can type new author information and modify the
ObjectDataSource control to perform the insertion.
Note
During this part of the walkthrough, the Authors.xml file you created previously will be updated. It is important that the appli
cation have permission to write to the file at run time or the Web page will display an error when you try to update the file. If
you created the Authors.xml file in the App_Data folder, permissions are set automatically.

To modify the business component to allow inserts


1. Switch to the BusinessObject file.
2. Add the following method as the final member of AuthorClass.
VB
Public Sub InsertAuthor(ByVal au_id As String, _
ByVal au_lname As String, _
ByVal au_fname As String, ByVal au_phone As String)
Dim workRow As DataRow = dsAuthors.Tables(0).NewRow
workRow.BeginEdit()
workRow(0) = au_id
workRow(1) = au_lname
workRow(2) = au_fname
workRow(3) = au_phone
workRow.EndEdit()
dsAuthors.Tables(0).Rows.Add(workRow)
dsAuthors.WriteXml(filePath, Data.XmlWriteMode.WriteSchema)
End Sub

C#
public void InsertAuthor (String au_id, String au_lname,
String au_fname, String au_phone)
{
DataRow workRow = dsAuthors.Tables[0].NewRow ();
workRow.BeginEdit ();
workRow[0] = au_id;
workRow[1] = au_lname;
workRow[2] = au_fname;
workRow[3] = au_phone;
workRow.EndEdit ();
dsAuthors.Tables[0].Rows.Add (workRow);
dsAuthors.WriteXml (filePath, XmlWriteMode.WriteSchema);
}

Note
Pay close attention to the names of the variables used to pass author information into the method (au_id, au_lname, au
_fname, and au_phone). They must match the column names defined in the schema of the XML file you created previous
ly.

The new method takes four values to insert, which you will provide in the page as parameters. The method creates a new
row in the dataset, and then writes the updated dataset out as an XML file.
3. Save the file.
The next step is to change the page so that users can enter new author information. For the following procedure, you will use
the DetailsView control.
To add a control for inserting data
1. Switch to or open the Default.aspx page.
2. Switch to Design view.
3. In the Toolbox, from the Data folder, drag a DetailsView control onto the page.
Note
The exact layout of the page is not important.

4. On the DetailsView Tasks menu, in the Choose Data Source box, click AuthorsObjectDataSource.
Note
If the DetailsView Tasks menu is not visible, click the smart tag.

5. In the Properties window, set AutoGenerateInsertButton to true.


This causes the DetailsView control to render a New button that users can click to put the control into data-entry mode.
Finally, you must configure the ObjectDataSource control to specify what action the control should take to insert data.
To configure the data source control for inserting data
Right-click AuthorsObjectDataSource, click Properties, and then set InsertMethod to InsertAuthor.
This is the name of the method that you added to the business component.
You can now insert new authors into the XML file.
To test insertion
1. Press CTRL+F5 to run the Default.aspx page.
2. In the DetailsView control, click the New button.
The control is redisplayed with text boxes.
3. Enter new author information, and then click Insert.
The new author information is added to the XML file. The GridView control immediately reflects the new record.
Next Steps
This walkthrough illustrates how to work with a data component. You might want to experiment with additional features of
navigation. For example, you might want to:
Add update and delete functionality. To do so, you would add methods to the component. Doing so is similar to adding
the insertion logic — you add a method to the component, configure the data source control to invoke the component
method, add appropriate parameters, and add a line of code to call the Update and Delete methods of the data source
control. For details, see Walkthrough: Editing and Inserting Data in Web Pages with the DetailsView Web Server Control.
Change the business component to work with database data instead of with an XML file. You do not need to make any
changes to the controls on the page.
Restrict which users can make changes to the data. A typical method is to add membership and roles to your Web site,
and then establish rules that the business component can check before allowing changes to data. For details, see
Walkthrough: Creating a Web Site with Membership and User Login (Visual Studio) and
Walkthrough: Managing Web Site Users with Roles.
See Also
Tasks
Walkthrough: Data Binding Web Pages with a Visual Studio Data Component
Walkthrough: Using Shared Code in Web Sites in Visual Web Developer
Walkthrough: Creating a Basic Web Page in Visual Web Developer
Concepts
Data Source Controls Overview
Using Parameters with Data Source Controls
ASP.NET

Data-Binding Expression Syntax


Data-binding syntax allows you to bind control property values to data and specify values for retrieving, updating, deleting,
and inserting data.
Data-Binding Syntax
Data-binding expressions are contained within <%# and %> delimiters and use the Eval and Bind functions. The Eval function is
used to define one-way (read-only) binding. The Bind function is used for two-way (updatable) binding. In addition to calling
Eval and Bind methods to perform data binding in a data-binding expression, you can call any publicly scoped code within the
<%# and %> delimiters to execute that code and return a value during page processing.

Data-binding expressions are resolved when the DataBind method of a control or of the Page class is called. For controls such
as the GridView, DetailsView, and FormView controls, data-binding expressions are resolved automatically during the control's
PreRender event and you are not required to call the DataBind method explicitly.
The following code example shows the use of data-binding expressions with a FormView control in an ItemTemplate.
VB
<asp:FormView ID="FormView1"
DataSourceID="SqlDataSource1"
DataKeyNames="ProductID"
RunAt="server">

<ItemTemplate>
<table>
<tr><td align="right"><b>Product ID:</b></td> <td><%# Eval("ProductID") %></td>
</tr>
<tr><td align="right"><b>Product Name:</b></td> <td><%# Eval("ProductName") %></t
d></tr>
<tr><td align="right"><b>Category ID:</b></td> <td><%# Eval("CategoryID") %></td
></tr>
<tr><td align="right"><b>Quantity Per Unit:</b></td><td><%# Eval("QuantityPerUnit") %
></td></tr>
<tr><td align="right"><b>Unit Price:</b></td> <td><%# Eval("UnitPrice") %></td>
</tr>
</table>
</ItemTemplate>
</asp:FormView>

C#
<asp:FormView ID="FormView1"
DataSourceID="SqlDataSource1"
DataKeyNames="ProductID"
RunAt="server">

<ItemTemplate>
<table>
<tr><td align="right"><b>Product ID:</b></td> <td><%# Eval("ProductID") %></td>
</tr>
<tr><td align="right"><b>Product Name:</b></td> <td><%# Eval("ProductName") %></t
d></tr>
<tr><td align="right"><b>Category ID:</b></td> <td><%# Eval("CategoryID") %></td
></tr>
<tr><td align="right"><b>Quantity Per Unit:</b></td><td><%# Eval("QuantityPerUnit") %
></td></tr>
<tr><td align="right"><b>Unit Price:</b></td> <td><%# Eval("UnitPrice") %></td>
</tr>
</table>
</ItemTemplate>
</asp:FormView>
Using the Eval Method
The Eval method evaluates late-bound data expressions in the templates of data-bound controls such as the GridView,
DetailsView, and FormView controls. At run time, the Eval method calls the Eval method of the DataBinder object,
referencing the current data item of the naming container. The naming container is generally the smallest part of the data-
bound control that contains a whole record, such as a row in a GridView control. You can therefore use the Eval method only
for binding inside templates of a data-bound control.
The Eval method takes the name of a data field and returns a string containing the value of that field from the current record
in the data source. You can supply an optional second parameter to specify a format for the returned string. The string format
parameter uses the syntax defined for the Format method of the String class.
Using the Bind Method
The Bind method has some similarities to the Eval method, but there are significant differences. Although you can retrieve the
values of data-bound fields with the Bind method, as you can with the Eval method, the Bind method is also used when data
can be modified.
In ASP.NET, data-bound controls such as the GridView, DetailsView, and FormView controls can automatically use the
update, delete, and insert operations of a data source control. For example, if you have defined SQL Select, Insert, Delete, and
Update statements for your data source control, using Bind in a GridView, DetailsView, or FormView control template
enables the control to extract values from child controls in the template and pass them to the data source control. The data
source control in turn performs the appropriate command for the database. For this reason, the Bind function is used inside
the EditItemTemplate or InsertItemTemplate of a data-bound control.
The Bind method is typically used with input controls such as the TextBox control rendered by a GridView row in edit mode.
When the data-bound control creates these input controls as part of its own rendering, it can extract the input values.
The Bind method takes the name of a data field to associate with the bound property, as shown in the following example:
Security Note
This example has a text box that accepts user input, which is a potential security threat. By default, ASP.NET Web pages valida
te that user input does not include script or HTML elements. For more information, see Script Exploits Overview.

<EditItemTemplate>
<table>
<tr>
<td align=right>
<b>Employee ID:</b>
</td>
<td>
<%# Eval("EmployeeID") %>
</td>
</tr>
<tr>
<td align=right>
<b>First Name:</b>
</td>
<td>
<asp:TextBox ID="EditFirstNameTextBox" RunAt="Server"
Text='<%# Bind("FirstName") %>' />
</td>
</tr>
<tr>
<td align=right>
<b>Last Name:</b>
</td>
<td>
<asp:TextBox ID="EditLastNameTextBox" RunAt="Server"
Text='<%# Bind("LastName") %>' />
</td>
</tr>
<tr>
<td colspan="2">
<asp:LinkButton ID="UpdateButton" RunAt="server"
Text="Update" CommandName="Update" />
&nbsp;
<asp:LinkButton ID="CancelUpdateButton" RunAt="server"
Text="Cancel" CommandName="Cancel" />
</td>
</tr>
</table>
</EditItemTemplate>

When the Update button for the row is clicked, the values of each control property bound using Bind syntax are extracted and
passed to the data source control for the update operation.
Calling the DataBind Method Explicitly
Controls such as GridView, FormView, and DetailsView controls perform binding by calling the DataBind method implicitly
when they are bound to a data source control using the DataSourceID property. However, there are situations in which you
need to call the DataBind method explicitly.
One situation is if you have bound a control to a data source control using the DataSource property instead of the
DataSourceID property. In that case, you need to call the DataBind method explicitly to perform data binding and resolve
data-binding expressions.
Another situation is if you need to manually refresh the data in a data-bound control. Consider a page where you have two
controls that display information from the same database (perhaps using different views). In that case, you might need to
explicitly re-bind the control to data to keep the data display synchronized. For example, you might have a GridView control
displaying a list of products and a DetailsView control that allows users to edit an individual product. Although the GridView
and DetailsView controls display data from the same source, they are bound to different data source controls because they
use different queries to get their data. A user might update a record using the DetailsView control, causing the update to be
performed by the associated data source control. However, because the GridView control is bound to a different data source
control, it will display old record values until the page is refreshed. Therefore, after the data is updated by the DetailsView
control, you can call the DataBind method. This causes the GridView control to update its view as well by re-executing any
data-binding expressions and publicly scoped code within the <%# and %> delimiters. As a result, the GridView control reflects
the update made by the DetailsView control.
Using Binding for a Lookup Table
A common scenario with data-bound controls is to enable users to update or insert a value by selecting it from a lookup table
using a DropDownList control or other list control. In that case, the lookup control is bound to a separate data source that
returns the list of possible values, and the lookup control's selected value is bound to a field in the parent data-bound row.
You can add this functionality as follows. First, for the lookup control, you add a list control (a DropDownList or ListBox
control) to a template in a data-bound control such as a GridView, DetailsView, or FormView control. You bind the
SelectedValue property of the lookup control to the related field in the container control's data source. Then you set the lookup
control's DataSourceID property to a data source control that retrieves the lookup values. You set the lookup control's
DataTextField property to the field from the lookup table that contains the values to display, and set its DataValueField property
to the field from the lookup table that contains the unique identifier for the lookup value, if applicable.
The following code example shows a DropDownList control that is included in the InsertItemTemplate template of a
FormView control (this could also be an InsertItemTemplate template of a TemplateField included in the Fields property of a
DetailsView control or the Columns property of a GridView control). The SelectedValue property of the DropDownList
control uses the Bind method for two-way binding to the CategoryID field of the current row for the FormView control. The
DataSourceID property of the DropDownList control is set to a separate data source control that retrieves the list of possible
category names and IDs. The DataTextField property of the DropDownList control is set to the CategoryName field from the
lookup data source so that a list of possible category names is displayed. The DataValueField property of the DropDownList
control is set to the CategoryID field from the lookup data source for the related category name. When a user selects a
category name from the list, the SelectedValue property of the DropDownList control is set to the category ID for the
selected category name.
VB
<tr>
<td align="right"><b>Category:</b></td>
<td><asp:DropDownList ID="InsertCategoryDropDownList"
SelectedValue='<%# Bind("CategoryID") %>'
DataSourceID="CategoriesDataSource"
DataTextField="CategoryName"
DataValueField="CategoryID"
RunAt="Server" />
</td>
</tr>

C#
<tr>
<td align="right"><b>Category:</b></td>
<td><asp:DropDownList ID="InsertCategoryDropDownList"
SelectedValue='<%# Bind("CategoryID") %>'
DataSourceID="CategoriesDataSource"
DataTextField="CategoryName"
DataValueField="CategoryID"
RunAt="Server" />
</td>
</tr>

The same list control could be used in an edit item template as well.
See Also
Tasks
How to: Bind to Data in a Templated Control
Concepts
Binding to Databases
Binding to Business Objects
Binding to Hierarchical Data
ASP.NET Data Access Overview
Visual Web Developer

How to: Bind to Data in a Templated Control in Visual Studio


You can associate a control, such as the GridView, DetailsView, FormView, DataList, or Repeater control with a data source
control, such as the SqlDataSource control. You can also use the templates for the control (the DataList, Repeater, and
FormView controls require the templates) to customize the data presentation with your custom user interface (UI) within the
designer.
This topic explains the process of adding UI controls, such as a TextBox control, to a template, and then binding the control to
specific data.
To bind a template control to a data source
1. Establish a valid data source, such as the SqlDataSource control, on your page and note the ID property value.
For example:

<asp:SqlDataSource ID="SqlDataSource1" Runat="server"


SelectCommand="SELECT CustomerID, CompanyName FROM Customers"
ConnectionString="<%$
ConnectionStrings:NorthwindConnectionString %>">
</asp:SqlDataSource>

For more information about how to use a SqlDataSource control with the database, see
Getting Started — SqlDataSource Web Server Control (Visual Studio).
2. From the Data group in the Toolbox, drag a DataList control onto your page.
The DataList Tasks shortcut menu appears.
If the DataList Tasks shortcut menu does not appear, right-click the DataList control, and then click Show Smart
Tag.
3. In the Choose Data Source list, click the SqlDataSource control that you created in step 1.
When the page is rendered, the control displays all columns and data from the query without customization. Depending
on your data, your DataList control will appear with default bound fields, as shown in the following code example:

<asp:DataList ID="DataList1" runat="server" DataKeyField="CustomerID" DataSourceID="Sq


lDataSource1">
<ItemTemplate>
CustomerID:
<asp:Label ID="CustomerIDLabel" runat="server" Text='<%# Eval("Custome
rID") %>'>
</asp:Label><br />
CompanyName:
<asp:Label ID="CompanyNameLabel" runat="server" Text='<%# Eval("Compan
yName") %>'>
</asp:Label><br />
<br />
</ItemTemplate>
</asp:DataList>

To edit the templates for the control


1. In Design view, right-click the DataList control, and then click Show Smart Tag.
2. On the DataList Tasks menu, click Edit Templates.
You can now edit templates in the designer. You can drag other controls onto the template to be bound later.
3. In the Display list, click AlternatingItemTemplate (different controls support different templates).
4. In the AlternatingItemTemplate design space, type CustomerID:, and then from the Standard group in the Toolbox, drag
a T:System.Web.UI.WebControls.Label control onto the DataList control.
5. On the Label Tasks menu, click Edit Data Bindings.
6. In the LabelName DataBindings dialog box, under Bindable properties, click Text.
7. Under Binding for Text, in the Bound to list, click CustomerID.
8. Repeat steps 4 through 7 for CompanyName.
9. In the AlternatingItemTemplate design space, select all content, and then press CTRL+B to change the text to bold.
10. Right-click the DataList control, and then click Show Smart Tag.
11. Click End Template Editing to exit template editing mode.
When your page is displayed in the browser, the list of companies is displayed alternating between plain text and bold
text.
See Also
Tasks
Walkthrough: Basic Data Access in Web Pages
Concepts
Data Source Controls Overview
Other Resources
Getting Started — SqlDataSource Web Server Control (Visual Studio)
ASP.NET

Connecting to Databases in ASP.NET


ASP.NET gives you flexibility in how you connect to databases. A simple way is to use data source controls, which allow you to
encapsulate data access in a control that you can configure with connection and query information. Alternatively, you can write
code to perform data access yourself using ADO.NET classes.
Using Data Source Controls in an ASP.NET Web Page
To connect to a database using a data source control, you do the following:
Determine the type of data source control you need. For example, the ObjectDataSource control works with a middle-tier
business object to retrieve and modify data, while the SqlDataSource control allows you to supply a connection to a data
source and SQL statements to retrieve and modify data.
When using the SqlDataSource control, determine what provider you need. A provider is a class that communicates
with a specific type of database. The default is the System.Data.SqlClient provider, which connects to a Microsoft SQL
Server database.
Add the data source control to the page and set its properties for data access. For example, the ObjectDataSource
control requires the type of the middle-tier business object and one or more methods to query or modify data. The
SqlDataSource control requires a connection string that includes the information that the provider needs to open a
specific database and one or more SQL commands to query or modify data.
You can specify provider and connection information as individual properties of the SqlDataSource control, or you can
define provider and connection string information centrally in the Web application's Web.config file. Storing connection
information in the Web.config file allows you to reuse the information with multiple data control instances. It also helps
you secure the connection string information using access control lists (ACLs) and encryption. For more information, see
"Connection Strings" later in this topic.

Providers
An ADO.NET provider is a class that can communicate with a specific type of database or data store. For example, one provider
might be able to communicate with a SQL Server database, and another provider might be able to communicate with an
Oracle database. The providers included with the .NET Framework are:
The .NET Framework Data Provider for SQL Server in the System.Data.SqlClient namespace. This provider is the default
for the SqlDataSource control; if you are connecting to a SQL Server database using the SqlDataSource control, you
do not need to explicitly specify a provider.
The .NET Framework Data Provider for OLE DB in the System.Data.OleDb namespace.
The .NET Framework Data Provider for ODBC in the System.Data.Odbc namespace.
The .NET Framework Data Provider for Oracle in the System.Data.OracleClient namespace.
You can specify the provider in Web.config file as part of a connection string, or as a property of an individual data source
control on a page.
Connection Strings
A connection string provides the information that a provider needs to communicate with a particular database. You can store a
connection string in the Web.config file and reference the configuration entry in a data source control.
Depending on the provider, a connection string usually supplies the server or location of the database server, the particular
database to use, and authentication information. As with the provider, you can indicate the connection string within the
Web.config file or as a property of an individual data source control on a page.
Connection String Storage
It is good practice to place connection strings in the Web.config file. Within the <configuration> Element element, you can
create a child element named <connectionStrings> and place your connection strings there, as shown in this example:

<connectionStrings>
<add name="NorthindConnectionString"
connectionString=" Server=MyDataServer;Integrated Security=SSPI;Database=Northwind;"
providerName="System.Data.SqlClient" />
</connectionStrings>

In this example, the name and provider are both supplied. Any data source control on any page in the application can reference
this connection string entry. An advantage to storing connection string information in the Web.config file is that you can easily
change the server name, database, or authentication information without editing individual Web pages. Additionally, you can
secure the connection string using encryption. For more information, see
How to: Secure Connection Strings When Using Data Source Controls.
Data Source Controls
Data source controls provide data services, including retrieving and modifying data, that can be used by other data-bound Web
server controls such as the GridView, FormView, and DetailsView controls. A data source control such as SqlDataSource
encapsulates all the elements required to connect to a database (provider, connection string, and query) to retrieve or
manipulate data. For example, the following SqlDataSource control is configured to connect to a database and read all
records from the Customers table:

<asp:SqlDataSource ID="SqlDataSource1" Runat="server"


SelectCommand="Select * from Customers"
ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>" />

In this example, the provider name and connection string are stored in the Web.config file, while the SQL query is configured
as a property of the data source control.
Performing Data Access in Code
If it is not practical in your application to use data source controls, you can code data access yourself using ADO.NET classes.
You might code data access yourself if you have complex requirements that are not met by using data source controls, or if
you want to create a separate component that performs data access outside of your Web pages.
See Also
Tasks
How to: Connect to an Access Database Using the SqlDataSource Control
How to: Connect to an ODBC Database Using the SqlDataSource Control
How to: Bind to Data in a Templated Control
Concepts
ASP.NET Data Access Overview
Visual Web Developer

How To: Secure Connection Strings when Using Data Source


Controls (Visual Studio)
When working with data source controls, you should centralize the location of your connection strings placing them within the
application's Web.config file. The benefits of this are twofold: your data source controls might reference the connection string's
name from the configuration file rather than include the connection string as a control property; and site administration is
easier because management of connection strings is centralized, which eliminates the need to revisit individual pages if your
connection string information changes.
In this topic you'll learn how to place your connection strings within the Web.config file using Visual Studio and a data source
control, and how to use the command-line utility, Aspnet_regiis.exe, to encrypt those connection strings for an added layer of
security.
How to add a connection string to Web.config with a data source control
1. Open an .aspx page in Design View in Visual Studio.
2. From the Toolbox, from the Data folder, drag a data source control, such as a SqlDataSource control, onto the design
surface.
3. Right-click the control, and click Show Smart Tag.
4. In the smart tag panel, click Configure Data Source.
5. In the Choose a Data Connection panel, click New Connection.
6. Select an appropriate data source from the list on the Choose Data Source dialog box, and then click OK.
7. Indicate the correct server name, user name, and password on the Add Connection dialog box, and then click OK.
You are returned to the Configure Data Source dialog box with a summary of your connection details.
8. Click Next, and then click Yes to save your connection string in the Web.config file.
The connection string is now stored in the Web.config file, and you can configure the query details for your control.
To encrypt connection string information stored in the Web.config file
1. At the Windows command line, run the ASP.NET IIS registration tool (Aspnet_regiis.exe) with the following options:
The -pe option, passing it the string "connectionStrings" to encrypt the connectionStrings element.
The -app option, passing it the name of your application.
The Aspnet_regiis.exe tool is located in the %systemroot%\Microsoft.NET\Framework\versionNumber folder.
The following code example shows how to encrypt the connectionStrings section of the Web.config file for an
application named SampleApplication.

aspnet_regiis -pe "connectionStrings" -app "/SampleApplication"

When the command has finished, you can view the contents of the Web.config file. The connectionStrings
configuration section will contain encrypted information instead of a clear-text connection string, as shown in the
following code example.

<configuration>
<connectionStrings configProtectionProvider="RsaProtectedConfigurationProvider">
<EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
xmlns="http://www.w3.org/2001/04/xmlenc#">
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"
/>
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"
/>
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<KeyName>RSA Key
</KeyName>
</KeyInfo>
<CipherData>
<CipherValue>WcFEbDX8VyLfAsVK8g6hZVAG1674ZFc1kWH0BoazgOwdBfinhcAmQmn
In0oHtZ5tO2EXGl+dyh10giEmO9NemH4YZk+iMIln+ItcEay9CGWMXSen9UQLpcQHQqMJErZiPK4qPZaRWwqck
LqriCl9X8x9OE7jKIsO2Ibapwj+1Jo=
</CipherValue>
</CipherData>
</EncryptedKey>
</KeyInfo>
<CipherData>
<CipherValue>OpWQgQbq2wBZEGYAeV8WF82yz6q5WNFIj3rcuQ8gT0MP97aO9SHIZWwNggSEi
2Ywi4oMaHX9p0NaJXG76aoMR9L/WasAxEwzQz3fexFgFSrGPful/5txSPTAGcqUb1PEBVlB9CA71UXIGVCPTiw
F7zYDu8sSHhWa0fNXqVHHdLQYy1DfhXS3cO61vW5e/KYmKOGA4mjqT0VZaXgb9tVeGBDhjPh5ZlrLMNfYSozeJ
+m2Lsm7hnF6VvFm3fFMXa6+h0JTHeCXBdmzg/vQb0u3oejSGzB4ly+V9O0T4Yxkwn9KVDW58PHOeRT2//3iZfJ
fWV2NZ4e6vj4Byjf81o3JVNgRjmm9hr9blVbbT3Q8/j5zJ+TElCn6zPHvnuB70iG2KPJXqAj2GBzBk6cHq+WNe
bOQNWIb7dTPumuZK0yW1XDZ5gkfBuqgn8hmosTE7mCvieP9rgATf6qgLgdA6zYyVV6WDjo1qbCV807lczxa3bF
5KzKaVUSq5FS1SpdZKAE6/kkr0Ps++CE=
</CipherValue>
</CipherData>
</EncryptedData>
</connectionStrings>
</configuration>

Leave the command prompt open for later steps.


2. Determine the user account or identity under which ASP.NET runs by retrieving the current WindowsIdentity name.
The following code example shows one way to determine the WindowsIdentity name.
VB
<%@ Page Language="VB" %>
<%
Response.Write(System.Security.Principal.WindowsIdentity.GetCurrent().Name)
%>

C#
<%@ Page Language="C#" %>
<%
Response.Write(System.Security.Principal.WindowsIdentity.GetCurrent().Name);
%>

Note
By default, on Windows Server 2003 with impersonation for an ASP.NET application disabled in the Web.config file, the
identity under which the application runs is the NETWORK SERVICE account. On other versions of Windows, ASP.NET r
uns under the local ASPNET account.

The user account or identity under which ASP.NET runs must have Read access to the encryption key used to encrypt and
decrypt sections of the Web.config file. This procedure assumes that your Web site is configured with the default
RsaProtectedConfigurationProvider specified in the Machine.config file named "RsaProtectedConfigurationProvider". The
RSA key container used by the default RsaProtectedConfigurationProvider is named
"NetFrameworkConfigurationKey".
3. At the command prompt, run the Aspnet_regiis.exe tool with the following options:
The -pa option, passing it the name of the RSA key container for the default
RsaProtectedConfigurationProvider.
The identity of your ASP.Net application, as determined in the preceding step.
The following code example shows how to grant the NETWORK SERVICE account access to the machine-level
"NetFrameworkConfigurationKey" RSA key container.

aspnet_regiis -pa "NetFrameworkConfigurationKey" "NT AUTHORITY\NETWORK SERVICE"

4. To decrypt the encrypted Web.config file contents, run the aspnet_regiis.exe tool with the -pd option. The syntax is the
same as encrypting Web.config file contents with the -pe option except that you do not specify a protected configuration
provider. The appropriate provider is identified in the configProtectionProvider attribute for the protected section.
The following code example shows how to decrypt the connectionStrings element of ASP.NET application
SampleApplication.

aspnet_regiis -pd "connectionStrings" -app "/SampleApplication"

See Also
Other Resources
Encrypting Configuration Information Using Protected Configuration
Visual Web Developer

Using SQL Server Express Edition with ASP.NET (Visual Studio)


Microsoft SQL Server 2005 Express Edition provides a simple database solution for building applications. SQL Server Express
Edition supports the complete SQL Server 2005 programming model including Transact-SQL, stored procedures, views,
triggers, SQL Server CLR Integration (SQLCLR), and the XML data type. When you develop an application using SQL Server
Express Edition as the data source, you can ensure that the application will be compatible with production servers running
SQL Server 2005.
Connecting to a SQL Server Express Edition Database
You can connect to a SQL Server Express Edition database just like you would connect to any SQL Server database by
specifying the database server as the local SQL Server Express Edition data source. For example, the following connection
string connects to a database named Customers.

Data Source=.\SQLEXPRESS;Initial Catalog=Customers;Integrated Security=True;

You can also specify a database file to attach to by using the AttachDBFilename connection-string attribute in place of the
InitialCatalog or Database connection-string attributes. Connecting to the database by using a file name simplifies deploying
your database with your application (provided the target server is running SQL Server Express Edition). For example, the
following connection string connects to a database that is stored in the Customers.mdf file.

Data Source=.\SQLEXPRESS;AttachDbFileName=e:\data\Customers.mdf;Integrated Security=True;Us


er Instance=True

ASP.NET provides a convenient option for storing data in the App_Data directory of a Web application. Contents of the
App_Data directory are not served in response to Web requests, which improves the security of the data for your application.
As an added convenience, you can supply the |DataDirectory| connection string variable in place of the file path to the
App_Data directory for your application. ASP.NET features — such as the SqlDataSource control or the providers for
membership, roles, user profiles, Web Parts personalization, and so on — will automatically substitute the file path to the
App_Data directory for the |DataDirectory| connection-string variable when opening a connection to the database. This
ensures that the path to your database remains current if your Web application is moved to a different directory. The following
code example shows a connection string that includes the |DataDirectory| connection-string variable.

Data Source=.\SQLEXPRESS;AttachDbFileName=|DataDirectory|Customers.mdf;Integrated Security=


True;User Instance=True

Note
SQL Server Express Edition allows only a single connection to an .mdf file when you connect with a connection string that ha
s User Instance set to true.

You can close the connection held by Visual Web Developer by right-clicking the database in Solution Explorer and selecting
the Detach option, or by right-clicking the database in Server Explorer and selecting Close Connection. Visual Web
Developer will automatically close any open database connections when you run or debug your Web application.
Additionally, if you need to release any open connections to a SQL Server Express Edition database, you can unload your Web
application by using Internet Information Services Manager (IIS Manager). You can also unload a Web application by adding an
HTML file named App_offline.htm to the root directory of your Web application. To allow your Web application to start
responding to Web requests again, simply remove the App_offline.htm file. You will need to release open connections to a
SQL Server Express Edition database when you want to copy or move the database to a new location.
Setting up a SQL Server Express Edition Database
Visual Web Developer provides tools to help you create a SQL Server Express Edition database; manage database elements,
such as tables, stored procedures, and so on; and manage connections to the database. You can access these capabilities
through the Server Explorer window. For instructions on creating a SQL Server Express Edition database, see
How to: Create SQL Server Express Edition Databases (Visual Studio).
You can also create a SQL Server Express Edition database by connecting to a computer running SQL Server Express Edition
and issuing a CREATE DATABASE command, or by using the SQL Server management tools provided for SQL Server Express
Edition.
The default provider for ASP.NET features that store data in a SQL Server database — such as membership, roles, the user
profiles, Web Parts personalization, and so on — is configured to connect to the Aspnetdb.mdf SQL Server Express Edition
database in the App_Data directory for your application. If you enable any of these data-storage features using the default
provider and the Aspnetdb.mdf SQL Server Express Edition database does not exist in the App_Data directory for your
application, the database will be automatically created. The App_Data directory for your application will also be created if it
does not exist.
User Instances
SQL Server Express Edition supports user instances, which means that a new process will be started for each user that connects
to a SQL Server Express Edition database. The identity of the process will be the user that opened the connection. For
information on determining the identity of an ASP.NET application, see ASP.NET Impersonation.
When you connect to a local database project, Visual Web Developer connects to the SQL Server Express Edition database with
user instances enabled, by default. For example, the following code example shows a typical connection string used by Visual
Web Developer to connect to a SQL Server Express Edition database.

Data Source=.\SQLEXPRESS;AttachDbFileName=|DataDirectory|Database.mdf;Integrated Security=T


rue;User Instance=True

Although enabling user instances is suitable for desktop development, starting worker processes is not appropriate on Web
servers hosting sites for multiple customers where applications must be separated and secured. ASP.NET applications that run
with the same process identity can connect to the same user instance. Because all ASP.NET applications run with the same
process identity on Windows 2000 and Windows XP Professional (by default, the local ASPNET account) and ASP.NET
applications in the same application pool run with the same process identity on Windows Server 2003 (by default, the
NETWORK SERVICE account), shared hosting servers that contain applications that do no trust each other should explicitly
disable user instances. This functionality can be turned off by connecting to the SQL Server Express Edition instance (for
example, by issuing the following command at a command prompt: osql –E –S .\SQLEXPRESS) and issuing the following
Transact-SQL command.
EXEC sp_configure 'show advanced option', '1'
GO
RECONFIGURE WITH OVERRIDE
GO
EXEC sp_configure 'user instances enabled', 0
GO
RECONFIGURE WITH OVERRIDE
GO

Deploying a SQL Server Express Edition Database


A SQL Express Edition database is made up of two files: the .mdf file, which contains the database schema and data; and the .ldf
file, which contains log information for the database. When you deploy a Web site by using the Copy Web Site tool, the
SQL Server Express Edition database files are copied as well. Your application will continue to run as long as SQL Server
Express Edition is installed on the target server. For more information, see
How to: Copy Web Site Files with the Copy Web Site Tool.
Here are some other options for deploying a SQL Server Express Edition database.
If you are making a file-based connection to your SQL Server Express Edition database, these files can be copied with
your application to a target server (that has SQL Server Express Edition installed) using XCopy, FTP, or another means.
Because SQL Server Express Edition uses the same file format as other versions of SQL Server 2005, you can copy the
.mdf and .ldf files to a server running SQL Server and then attach the files as a database.
If you want to copy an empty SQL Server Express Edition database that contains database schema, but no data, the
SQL Server management tools enable you to generate scripts that can be run in your target database to duplicate the
schema from your development database.
Note
If you are deploying your SQL Server Express Edition database to a Web server that hosts multiple sites that do not trust eac
h other, then you cannot use file-based connections or user instances to help ensure that your data is not exposed to other a
pplications on the server. In this case, it is recommended that you migrate the contents your SQL Server Express Edition data
base to another version of SQL Server 2005 that your deployed ASP.NET application can access.

If your SQL Server Express Edition database contains encrypted information, such as encrypted passwords stored in a
membership database, make sure that your encryption keys are copied to the target server as well.
If you want to move the entire SQL Server Express Edition database, you need to ensure that there are no open connections to
the database that would cause it to be locked.
Unlocking a Locked Database
If there is an open connection to a database, the database is locked and cannot be moved or deleted. Open connections can be
held by an ASP.NET application, Visual Studio, or some other program or database client. To unlock a database, all open
connections to the database must be closed. You can close the open connections in the following ways:
You can close the connection held by Visual Web Developer by right-clicking the database in Solution Explorer and
selecting the Detach option, or by right-clicking the database in Server Explorer and selecting Close Connection.
Visual Web Developer will automatically close any open database connections when you run or debug your Web
application.
You can close any connections held by an ASP.NET application by ending the application. This can be done by using IIS
Manager, or by placing a file named App_offline.htm in the root directory of the ASP.NET application (you must remove
this file to restart the application).
You can close any connections held by other sources, such as a Windows Forms application, by exiting the program.
See Also
Other Resources
Accessing Data with ASP.NET
Managing Users by Using Membership
Managing Authorization Using Roles
ASP.NET Profile Properties
Visual Web Developer

How to: Create SQL Server Express Edition Databases (Visual


Studio)
When you install Microsoft SQL Server 2005 Express Edition with Visual Web Developer, you can use the Visual Studio data-
management tools to create SQL Server Express Edition databases and populate them with database elements, such as tables,
data, stored procedures, views, and so on.
For information about binding the data in your database to a data-bound control, see Binding to Databases.
Creating a Database for a Web Application
To create a database
1. In Visual Web Developer, open Solution Explorer, right-click the App_Data folder of your Web application, and then
click Add New Item.
--or--
If your application does not have an App_Data folder, right-click the root folder of your Web application, click Add
ASP.NET Folder, and then click App_Data.
2. Click SQL Database, type a name for the .mdf database file, and then click Add.
Two files are created: DataBaseName.mdf and DataBaseName_log.ldf. Visual Web Developer automatically moves focus
to the Data Connections section of the Server Explorer window and selects the newly created database.
To add a table to a database
1. In the Data Connections section of the Server Explorer window, double-click (or expand) the database to which you
want to add a table.
2. Right-click the Tables folder and select Add New Table.
The focus moves to the table definition panel for a new table.
3. Add table columns, and specify the column name and data type of the new column, as well as whether the column allows
nulls.
4. Select the primary-key column (or press SHIFT+SELECT to select multiple columns for a multi-column primary key),
right-click the selection, and then click Set Primary Key.
5. Optionally, select an int (integer) column to specify as an identity column; and then, in the Column Properties panel for
the column, double-click the Identity Specification section for the column and set (Is Identity) to Yes.
6. Press CTRL+S to supply a table name and save the table. If you close the table definition panel without saving the table,
you will be prompted to supply a table name, and the table will be automatically saved.
To add data to a table in a database
1. In the Data Connections section of the Server Explorer window, double-click (or expand) the database that you want
to work with and then double-click the Tables folder for that database.
2. Right-click the table to which you want to add data and then click Show Table Data.
3. In the data grid that appears, type the data that you want to place in the table, providing values for all of the required
fields.
4. When you are finished, select the next new row of the data grid. Visual Web Developer now writes the values for the
populated row to the table.
See Also
Concepts
Using SQL Server Express Edition with ASP.NET (Visual Studio)
Other Resources
Accessing Data with ASP.NET
ASP.NET

Securing Data Access


Most ASP.NET Web applications involve data access. Many applications collect data to be stored in a database or file, and the
data to be stored is often based on information that comes from users. Because the original data can come from untrusted
sources, because the information is stored in a persistent format, and because you want to be sure that unauthorized users
cannot access your data source directly, you need to pay particular attention to security issues surrounding data access. The
information in this topic describes best practices that will help you improve the security of the data access in your ASP.NET
Web application.
While following coding and configuration best practices can improve the security of your application, it is also important that
you continually keep your Web server up to date with the latest security updates for Microsoft Windows and Internet
Information Services (IIS), as well as any security updates for Microsoft SQL Server or other data source software.
More detailed information about best practices for writing secure code and securing applications can be found in the book
"Writing Secure Code" by Michael Howard and David LeBlanc, or through the guidance provided on the
Microsoft Patterns and Practices Web site.
Securing Access to a Data Source
The following sections provide information on helping secure different aspects of data access.
Connection Strings
Connecting to a database requires a connection string. Because connection strings can contain sensitive data, you should
follow these guidelines:
Do not store connection strings in a page. For example, avoid setting connection strings as declarative properties of the
SqlDataSource control or other data source controls. Instead, store connection strings in the site's Web.config file. For an
example, see How to: Secure Connection Strings When Using Data Source Controls.
Do not store connection strings as plain text. To help keep the connection to your database server secure, it is
recommended that you encrypt connection string information in the configuration file by using protected configuration.
For more information, see Encrypting Configuration Information Using Protected Configuration.
Connecting to SQL Server using Integrated Security
If possible, connect to an instance of SQL Server using integrated security instead of using an explicit user name and password.
This helps avoid the possibility of the connection string being compromised and your user ID and password being exposed.
It is recommended that you ensure that the identity of the process (for example, the application pool) that is running ASP.NET
be the default process account or a restricted user account. For more information, see ASP.NET Impersonation.
In scenarios where different Web sites connect to different SQL Server databases, it might not be practical to use integrated
security. For example, on Web-hosting sites, each customer is typically assigned a different SQL Server database, but all users
use the Web server as anonymous users. In such cases, you need to use explicit credentials to connect to an instance of
SQL Server. Be sure that you store the credentials in a secure manner, as described in this topic under Connection Strings.
SQL Server Database Permissions
It is recommended that you assign the minimum privileges to the user ID that is used to connect to the SQL Server databases
used in your application.
Restrict SQL Operations
Data-bound controls can support a wide variety of data operations, including selecting, inserting, deleting, and updating
records in data tables. It is recommended that you configure data controls to perform the minimum functionality that is
required on a page or in your application. For example, if a control should not allow users to delete data, do not include a
delete query with a data source control and do not enable deleting in the control.
SQL Server Express Edition
When a process attaches to a SQL Server Express Edition database (.mdf file), the process must have administrative
permissions. In general, this makes SQL Server Express Edition databases impractical for production Web sites because the
ASP.NET process does not (and should not) run with administrative privileges. Therefore, use SQL Server Express Edition
databases only under the following circumstances:
Use as a test database while developing your Web application. When you are ready to deploy your application, you can
transfer the database from SQL Server Express Edition to a production instance of SQL Server.
Use if you are running a Web site that can use impersonation and you can control the privileges of the impersonated
user. In practice, this strategy is practical only if the application is running on a local area network (not a public Web site).
Store the .mdf file in your site's App_Data folder, because the contents of the folder will not be returned to direct HTTP
requests. You should also map the .mdf extension to ASP.NET in IIS and to the HttpForbiddenHandler handler in ASP.NET
using the following element in the site's Web.config file:

<httpHandlers>
<add verb="*" path="*.mdf" type="System.Web.HttpForbiddenHandler" />
</httpHandlers>

For information on how to map a file name extension to ASP.NET in IIS, see How to: Register HTTP Handlers.
Microsoft Access Databases
Microsoft Access databases (.mdb files) include fewer security features than SQL Server databases. Access databases are not
recommended for production Web sites. However, if you have reason to use an .mdb file as part of your Web application,
follow these guidelines:
Store the .mdb file in your site's App_Data folder because the contents of the folder will not be returned to direct HTTP
requests. You should also map the .mdb extension to ASP.NET in IIS and to the HttpForbiddenHandler handler in ASP.NET
using the following element in the site's Web.config file:

<httpHandlers>
<add verb="*" path="*.mdb" type="System.Web.HttpForbiddenHandler" />
</httpHandlers>

For information on how to map a file name extension to ASP.NET in IIS, see How to: Register HTTP Handlers.
Add appropriate permissions for the user account or accounts that will be reading and writing in the .mdb file. If the Web
site supports anonymous access, this is generally the local ASPNET user account or the NETWORK SERVICE account.
Because Access must create an .ldb file to support locking, the user account must have write permissions for the folder
that contains the .mdb file.
If the database is protected with a password, do not use the AccessDataSource control to establish a connection to it,
because the AccessDataSource control does not support passing credentials. Instead, use the SqlDataSource control
with the ODBC provider, and pass the credentials in the connection string. Be sure to secure the connection string as
described in this topic under Connection Strings.
XML Files
If you are storing data in an XML file, place the XML file in your Web site's App_Data folder, because the contents of the folder
will not be returned in response to direct HTTP requests.
Guarding Against Malicious User Input
If your application accepts input from users, you need to make sure that the input does not contain malicious content that can
compromise your application. Malicious user input can be used to launch the following attacks:
Script injection A script injection attack attempts to send executable script to your application with the intent of having
other users run it. A typical script injection attack sends script to a page that stores the script in a database, so that
another user who views the data inadvertently runs the code.
SQL injection A SQL injection attack attempts to compromise your database (and potentially the computer on which
the database is running) by creating SQL commands that are executed instead of, or in addition to, the commands that
you have built into your application.
General Guidelines
For all user input, follow these guidelines:
Use validation controls whenever possible to limit user input to acceptable values.
Always be sure that the value of the IsValid property is true before running your server code. A value of false means that
one or more validation controls have failed a validation check.
Always perform server-side validation even if the browser is also performing client-side validation, to guard against
users bypassing client-side validation. This is especially true for CustomValidator controls; do not use only client-side
validation logic.
Always re-validate user input in the business layer of your application. Do not rely on the calling process to provide safe
data. For example, if you are using the ObjectDataSource control, add redundant validation and encoding into the object
that performs the data updates.
Script Injection
To avoid script injection attacks, follow these guidelines:
Encode user input with the HtmlEncode method, which turns HTML into its text representation (for example, <b> becomes
&ltb&gt;), and helps prevent the markup from being executed in a browser.

When using parameter objects to pass user input to a query, add handlers for the data source control's pre-query events
and perform the encoding in those events. For example, handle the SqlDataSource control's Inserting event, and in the
event, encode the parameter value before the query is executed.
If you are using the GridView control with bound fields, set the BoundField object's HtmlEncode property to true. This
causes the GridView control to encode user input when the row is in edit mode.
For controls that can be put into edit mode, it is recommended that you use templates. For example, the GridView,
DetailsView, FormView, DataList, and Login controls can display editable text boxes. However, except for the GridView
control (see the previous point), the controls do not automatically validate or HTML-encode the user input. Therefore, it is
recommended that you create templates for these controls, and in the template, include an input control such as a
TextBox control and add a validation control. In addition, when extracting the value of the control, you should encode it.
SQL Injection
To avoid SQL injection attacks, follow these guidelines:
Do not create SQL commands by concatenating strings together, especially strings that include input from users. Instead,
use parameterized queries or stored procedures.
If you are creating a parameterized query, use parameter objects to establish the values for the parameters. For details,
see Using Parameters with the SqlDataSource Control and Using Parameters with Data Source Controls.
Encrypting View-State Data
Data-bound controls, such as the GridView control, sometimes need to persist information that is considered sensitive. For
example, the GridView control can maintain a list of keys in the DataKeys property, even if this information is not displayed.
Between round trips, the control stores the information in view state.
View state information is encoded and stored with the contents of the page and could be decoded and exposed to an
unwanted source. If you must store sensitive information in view state, you can request that the page encrypt view state data.
To encrypt the data, set the page's ViewStateEncryptionMode property to true. For more information, see Securing View State.
Caching
It is recommended that you avoid storing sensitive information in the Cache object when client impersonation is enabled and
the results from the data source are retrieved based on the client identity. If caching is enabled, cached data for a single user
can be viewed by all users and sensitive information could be exposed to an unwanted source. Client impersonation is enabled
when the impersonate attribute of the identity configuration element is set to true and anonymous identification is disabled
for the application at the Web server.
See Also
Concepts
Securing View State
Securing Standard Controls
Other Resources
ASP.NET Web Site Security
Visual Web Developer

Walkthrough Topics — ASP.NET Data Access (Visual Studio)


This topic provides a directory of walkthroughs related to building data-driven Web pages and using controls such as
FormView, DataList, and GridView.
General Data Access
The topics in this category provide information that is not control specific or that applies to multiple ASP.NET data controls.
Walkthrough: Basic Data Access in Web Pages
Walkthrough: Editing and Inserting Data in Web Pages with the DetailsView Web Server Control
Walkthrough: Data Binding Web Pages with a Visual Studio Data Component
Walkthrough: Creating Master/Detail Web Pages in Visual Studio
Data Controls
The topics in this category provide information about individual Web controls.
Data Source Controls
Access Data Source Control
Walkthrough: Creating a Web Page to Display Access Database Data
Object Data Source Control
Walkthrough: Data Binding Web Pages with a Visual Studio Data Component
Walkthrough: Data Binding to a Custom Business Object
SqlDataSource Control
How to: Connect to an Oracle Database Using the SqlDataSource Control (Visual Studio)
XmlDataSource Control
Walkthrough: Creating a Web Page to Display XML Data
Data-Bound Controls
DataList Control
Walkthrough: Displaying and Formatting Data with the DataList Web Server Control
DetailsView Control
Walkthrough: Creating Master/Detail Web Pages in Visual Studio
FormView Control
Walkthrough: Displaying Formatted Data in Web Pages with the FormView Web Server Control
GridView Control
Walkthrough: Simple Sorting for the GridView Web Server Control
Walkthrough: Displaying a Drop-Down List While Editing in the GridView Web Server Control
Walkthrough: Displaying Data Using a Stored Procedure in the GridView Web Server Control
Walkthrough: Data Binding Web Pages with a Visual Studio Data Component
Walkthrough: Creating Master/Detail Web Pages in Visual Studio
See Also
Other Resources
ASP.NET Data Access (Visual Studio)
Data Toolbox Controls
Visual Web Developer

How-to Topics — ASP.NET Data Access (Visual Studio)


The following procedure describes how you can learn more about building data-driven ASP.NET Web pages.
How-to Topics
How to: Bind to Data in a Templated Control in Visual Studio
See Also
Other Resources
ASP.NET Data Access (Visual Studio)
Visual Web Developer

ASP.NET Web Site Security (Visual Studio)


Security is a vital aspect of your ASP.NET Web applications. The topics in this section provide background information on
security issues that arise in Web applications, on mitigating common security threats, protecting resources in your application,
and on authenticating and authorizing individual users.
Note
There are numerous threats and countermeasures to apply when securing an ASP.NET application. It is strongly recommend
ed that you review and apply the guidance and checklists provided in the articles
Improving Web Application Security: Threats and Countermeasures and
Building Secure ASP.NET Applications: Authentication, Authorization, and Secure Communication on the Microsoft Patterns a
nd Practices Web site.

In This Section
Getting Started — ASP.NET Web Site Security (Visual Studio)
Provides essential information about security issues and security measures you can take to protect ASP.NET Web sites and
pages.
Learning More — ASP.NET Web Site Security (Visual Studio)
Provides more in-depth information about securing ASP.NET Web sites and pages.
Walkthrough Topics — ASP.NET Web Site Security (Visual Studio)
Provides links to tutorials on adding security features to ASP.NET Web sites in Visual Web Developer.
How-to Topics — ASP.NET Web Site Security (Visual Studio)
Provides links to how-to topics on adding security features to ASP.NET Web sites in Visual Web Developer.
Related Sections
Guided Tour of Creating Web Sites in Visual Web Developer
Provides links to tutorials on all aspects of creating ASP.NET Web sites and ASP.NET Web pages.
Security in the .NET Framework
Describes .NET Framework code access security, role-based security, security policy, and security tools.
Configuring Security Policy
Describes how to configure security policy using the .NET Framework Configuration tool and the Code Access Security Policy
tool, and how to import security components using XML files.
Securing ADO.NET Applications
Describes coding guidelines for helping secure data in your database.
Visual Web Developer

Getting Started — ASP.NET Web Site Security (Visual Studio)


Security involves several disciplines and will often determine whether a Web application is successful. A secure Web
application will accurately identify users through authentication, help ensure that those users can access only what they require
through authorization, help protect confidential and sensitive data through encrypted communication and storage, and follow
security best practices for writing code to guard against creating security risks in the application logic itself.
The topics in this section provide essential information on ASP.NET features and best practices to help you create secure Web
applications.
Note
There are numerous threats and countermeasures to apply when securing an ASP.NET application. It is strongly recommend
ed that you review and apply the guidance and checklists in the "Improving Web Application Security: Threats and Counterm
easures" module published on MSDN at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secmod/html/sec
mod75.asp.

In This Section
Web Application Security Threats Overview (Visual Studio)
Basic Security Practices for Web Applications (Visual Studio)
Walkthrough: Creating a Web Site with Membership and User Login (Visual Studio)
Storing Sensitive Information Using ASP.NET
Limiting Access to ASP.NET Web Sites
Script Exploits
How to: Display Safe Error Messages
Web Application Security at Run Time
See Also
Other Resources
ASP.NET Web Site Security (Visual Studio)
Visual Web Developer

Web Application Security Threats Overview (Visual Studio)


If unknown users can access your Web application, the odds are almost certain that malicious users will try to gain
unauthorized access to your application. Servers that are accessible to the public on the Internet are commonly probed for
vulnerabilities daily. Therefore, it is recommended that you take precautions and build security into all of your Web
applications.
For more detailed information about best practices for writing secure code and securing applications, see the book "Writing
Secure Code" by Michael Howard and David LeBlanc and the guidance provided by Microsoft Patterns and Practices.
Security Technology Is Only Part of the Solution
Implementing security is only part of the solution. Another important part is vigilance. Even if your system has many security
safeguards, you need to watch it closely in these ways:
Monitor your system's event logs. Watch for repeated attempts to log into your system or for excessive requests being
made against your Web server.
Continually keep your application server up to date with the latest security updates for Microsoft Windows and Internet
Information Services (IIS), as well as any updates for Microsoft SQL Server or other data sources that your application
might use.
Threat Modeling
An important part of developing a more secure application is to understand the threats to it. Microsoft has developed a way to
categorize threats: Spoofing, Tampering, Repudiation, Information disclosure, Denial of service, Elevation of privilege (STRIDE).
The sections below briefly describe these threats and how they apply to Web applications.
Spoofing
To spoof is to impersonate a user or process in an unauthorized way. At its simplest, spoofing can mean typing in a different
user's credentials. A malicious user might also change the contents of a cookie to pretend that he is a different user or that the
cookie comes from a different server.
In general, you can help prevent spoofing by using stringent authentication. Any time someone requests access to non-public
information, make sure they are who they say they are. You can also help defend against spoofing by keeping credential
information safe. For example, do not keep a password or other sensitive information in a cookie, where a malicious user can
easily find or modify it.
Tampering
Tampering means changing or deleting a resource without authorization. One example is defacing a Web page, where the
malicious user gets into your site and changes files. An indirect way to tamper is by using a script exploit. A malicious user
manages to get code (script) to execute by masking it as user input from a form or as a link.
A primary defense against tampering is to use Windows security to lock down files, directories, and other Windows resources.
The application should also run with minimum privileges. You can help guard against script exploits by not trusting any
information that comes from a user or even from a database. Whenever you get information from an untrusted source,
process it by making sure it does not contain any executable code.
Repudiation
A repudiation threat involves carrying out a transaction in such a way that there is no proof after the fact of the principals
involved in the transaction. In a Web application, this can mean impersonating an innocent user's credentials. You can help
guard against repudiation by using stringent authentication. In addition, use the logging features of Windows to keep an audit
trail of any activity on the server. For details, see Logging Application, Server, and Security Events.
Information Disclosure
Information disclosure simply means stealing or revealing information that is supposed to be private. A classic example is
stealing passwords, but it can involve access to any file or resource on the server.
The best defense against information disclosure is to have no information to disclose. For example, if you avoid storing
passwords, malicious users cannot steal them. (An alternative to storing passwords is to store only a hash of the password.
When a user presents credentials, you can hash the user's password and compare only the hashes of the two.)
If you do store sensitive information, use Windows security to help secure it. As always, you should use authentication to help
ensure that only authorized users can access restricted information. If you must expose sensitive information, it is
recommended that you encrypt the information when it is stored, and use Secure Sockets Layer (SSL) to encrypt the
information when it is sent to and from the browser.
Denial of Service
A denial of service attack is to deliberately cause an application to be less available than it should be. A typical example is to
overload a Web application so that it cannot serve ordinary users. Alternatively, malicious users might try to simply crash your
server.
IIS allows you to throttle applications, which means that it limits the number of requests it will serve. You might be able to deny
access to users or IP addresses that are known to be malicious. Keeping your applications online is a matter of running robust
code. You should test your application thoroughly and respond appropriately to error conditions wherever possible.
Elevation of Privilege
An elevation of privilege attack is to use malicious means to get more permissions than normally assigned. For example, in a
successful elevation of privilege attack, a malicious user manages to get administrative privileges to your Web server, giving
themselves access to any data on the server as well as control over server capabilities.
To help protect against elevation of privilege, run the application in a least-privilege context, if practical. For example, it is
recommended that you do not run ASP.NET applications as the SYSTEM (administrative) user.
See Also
Concepts
Basic Security Practices for Web Applications (Visual Studio)
Security Bibliography
Other Resources
Security in Native and .NET Framework Code
ASP.NET Web Application Security
Visual Web Developer

Basic Security Practices for Web Applications (Visual Studio)


Even if you have limited experience with and knowledge of application security, there are basic measures that you should take
to help protect your Web applications. The following sections in this topic provide minimum-security guidelines that apply to
all Web applications. For more detailed information about best practices for writing secure code and securing applications, see
the book "Writing Secure Code" by Michael Howard and David LeBlanc and the guidance provided by
Microsoft Patterns and Practices.
General Web Application Security Recommendations
Run Applications with Minimum Privileges
Know Your Users
Guard Against Malicious User Input
Access Databases Securely
Create Safe Error Messages
Keep Sensitive Information Safely
Use Cookies Securely
Guard Against Denial-of-Service Threats
General Web Application Security Recommendations
Even the most elaborate application security can fail if a malicious user can use simple ways to gain access to your computers.
General Web application security recommendations include the following:
Back up data often and keep your backups physically secure.
Keep your Web server physically secure so that unauthorized users cannot gain access to it, turn it off, physically steal it,
and so on.
Use the Windows NTFS file system, not FAT32. NTFS offers substantially more security than FAT32. For details, see the
Windows Help documentation.
Protect the Web server and all of the computers on the same network with strong passwords.
Follow best practices for securing Internet Information Services (IIS). For details, see the
Windows Server TechCenter for IIS.
Close any unused ports and turn off unused services.
Run a virus checker that monitors site traffic.
Use a firewall. For recommendations, see Microsoft Firewall Guidelines on the Microsoft security Web site.
Learn about and install the latest security updates from Microsoft and other vendors.
Use Windows event logging and examine the logs frequently for suspicious activity. This includes repeated attempts to
log on to your system and excessive requests against your Web server.
Run Applications with Minimum Privileges
When your application runs, it runs within a context that has specific privileges on the local computer and potentially on
remote computers. For information about configuring application identity, see Configuring ASP.NET Process Identity.
To run with the minimum number of privileges needed, follow these guidelines:
Do not run your application with the identity of a system user (administrator).
Run the application in the context of a user with the minimum practical privileges.
Set permissions (ACLs, or Access Control Lists) on all the resources required for your application. Use the most restrictive
setting. For example, if practical in your application, set files to be read-only. For a list of the minimum ACL permissions
required for the identity of your ASP.NET application, see ASP.NET Required Access Control Lists (ACLs).
Keep files for your Web application in a folder below the application root. Do not allow users the option of specifying a
path for any file access in your application. This helps prevent users from getting access to the root of your server.
Know Your Users
In many applications, it is possible for users to access the site without having to provide credentials. If so, your application
accesses resources by running in the context of a predefined user. By default, this context is the local ASPNET user (Windows
2000 or Windows XP) or NETWORK SERVICE user (Windows Server 2003) on the Web server.
To restrict access to users who are authenticated, follow these guidelines:
If your application is an intranet application, configure it to use Windows Integrated security. This way, the user's login
credentials can be used to access resources.
If you need to gather credentials from the user, use one of the ASP.NET authentication strategies. For an example, see the
ASP.NET Forms Authentication Overview.
Guard Against Malicious User Input
As a general rule, never assume that input you get from users is safe. It is easy for malicious users to send potentially
dangerous information from the client to your application. To help guard against malicious input, follow these guidelines:
In forms, filter user input to check for HTML tags, which might contain script. For details, see
How to: Protect Against Script Exploits in a Web Application by Applying HTML Encoding to Strings.
Never echo (display) unfiltered user input. Before displaying untrusted information, encode HTML to turn potentially
harmful script into display strings.
Similarly, never store unfiltered user input in a database.
If you want to accept some HTML from a user, filter it manually. In your filter, explicitly define what you will accept. Do
not create a filter that tries to filter out malicious input; it is very difficult to anticipate all possible malicious input.
Do not assume that information you get from the header (usually via the Request object) is safe. Use safeguards for
query strings, cookies, and so on. Be aware that information that the browser reports to the server (user agent
information) can be spoofed, in case that is important in your application.
If possible, do not store sensitive information in a place that is accessible from the browser, such as hidden fields or
cookies. For example, do not store a password in a cookie.
Note
View state is stored in a hidden field in an encoded format. By default, it includes a message authentication code (MAC)
so that the page can determine whether view state has been tampered with.

Access Databases Securely


Databases typically have their own security. An important aspect Web application security is designing a way for the
application to access the database securely. Follow these guidelines:
Use the inherent security of your database to limit who can access database resources. The exact strategy depends on
your database and your application:
If practical in your application, use Windows Integrated security so that only Windows-authenticated users can
access the database. Integrated security is more secure than using SQL Server standard security.
If your application uses anonymous access, create a single user with very limited permissions, and perform
queries by connecting as this user.
Do not create SQL statements by concatenating strings that involve user input. Instead, create a parameterized query and
use user input to set parameter values.
If you must store a user name and password somewhere to use as the database login credential, store them securely. If
practical, encrypt or hash them. For details, see Encrypting and Decrypting Data.
For more information about accessing data securely, see Securing ADO.NET Applications.
Create Safe Error Messages
If you are not careful, a malicious user can deduce important information about your application from the error messages it
displays. Follow these guidelines:
Do not write error messages that echo information that might be useful to malicious users, such as a user name.
Configure the application not to show detailed errors to users. If you want to display detailed error messages for
debugging, check first that the user is local to the Web server. For details, see How to: Display Safe Error Messages.
Use the customErrorsconfiguration element to control who can view exceptions from the server.
Create custom error handling for situations that are prone to error, such as database access.
Keep Sensitive Information Safely
Sensitive information is any information that you need to keep private. A typical piece of sensitive information is a password or
an encryption key. If a malicious user can get to the sensitive information, then the data protected by the secret is
compromised. Follow these guidelines:
If your application transmits sensitive information between the browser and the server, consider using Secure Sockets
Layer (SSL). For details about how to encrypt a site with SSL, see article Q307267, "How to: Secure XML Web Services
with Secure Sockets Layer in Windows 2000" in the Microsoft Knowledge Base.
Use Protected Configuration to secure sensitive information in configuration files such as the Web.config or
Machine.config files. For more information, see Encrypting Configuration Information Using Protected Configuration.
If you must store sensitive information, do not keep it in a Web page, even in a form that you think people will not be
able to view (such as in server code).
Use the strong encryption algorithms supplied in the System.Security.Cryptography namespace.

Use Cookies Securely


Cookies are an easy and useful way to keep user-specific information available. However, because cookies are sent to the
browser's computer, they are vulnerable to spoofing or other malicious use. Follow these guidelines:
Do not store any critical information in cookies. For example, do not store a user's password in a cookie, even
temporarily. As a rule, do not store any sensitive information in a cookie that. Instead, keep a reference in the cookie to a
location on the server where the information is located.
Set expiration dates on cookies to the shortest practical time you can. Avoid permanent cookies if possible.
Consider encrypting information in cookies.
Consider setting the Secure and HttpOnly properties on your cookies to true.

Guard Against Denial-of-Service Threats


An indirect way that a malicious user can compromise your application is by making it unavailable. The malicious user can
keep the application too busy to service other users, or if nothing else can simply crash the application. Follow these guidelines:
Close or release any resource you use. For example, always close data connections and data readers, and always close
files when you are done using them.
Use error handling (for example, try/catch blocks). Include a finally block in which you release resources in case of
failure.
Configure IIS to use throttling, which prevents an application from using a disproportionate amount of CPU.
Test size limits of user input before using or storing it.
Put size safeguards on database queries to help guard against large queries using up system resources.
Put a size limit on file uploads, if those are part of your application. You can set a limit in the Web.config file using syntax
such as the following code example, where the maxRequestLength value is in kilobytes:

<configuration>
<system.web>
<httpRuntime maxRequestLength="4096" />
</system.web>
</configuration>

You can also use the RequestLengthDiskThreshold property in to reduce the memory overhead of large uploads and form
posts.
See Also
Concepts
Web Application Security Threats Overview (Visual Studio)
Security Bibliography
Other Resources
ASP.NET Web Application Security
Visual Web Developer

Walkthrough: Creating a Web Site with Membership and User


Login (Visual Studio)
A common requirement for Web sites is to allow only some members or other authenticated users to see certain pages. In that
case, the application must prompt the user for a name and password. The application must also include a way to hide
information from anonymous users (users who are not logged in). This walkthrough shows you how to use ASP.NET controls
and ASP.NET membership services to create an application that performs all these tasks. For more information, see
Introduction to Membership.
Tasks illustrated in this walkthrough include:
Configuring an application to include ASP.NET membership services, and how to define users.
Using login controls to get user credentials and to display information to logged-in users.
Protecting one or more pages in your application so that only logged-in users can view them.
Allowing new users to register at your site.
Allowing members to change and reset their passwords.
Prerequisites
In order to complete this walkthrough, you will need:
Microsoft Visual Web Developer.
Microsoft Internet Information Services (IIS) installed locally on your computer.
Microsoft Data Access Components (MDAC) version 2.7 or later. If you are using Microsoft Windows XP or Windows
Server 2003, you already have MDAC 2.7. However, if you are using Microsoft Windows 2000, you might to need to
upgrade the MDAC already installed on your computer. For more information, see the article "Microsoft Data Access
Components (MDAC) Installation" in the MSDN library.
Access to an e-mail server that can forward e-mail messages. (The server does not have to be able to receive messages.)
IIS includes the Default SMTP virtual server, a mail server that is suitable for this walkthrough. For more information
about configuring this server, see How to: Install and Configure SMTP Virtual Servers in IIS. If you are working on a local
area network, check with your network administrator for information about access to an e-mail server.
Creating the Web Site
If you have already created a Web site in Microsoft Visual Studio (for example, by working with the topic
Walkthrough: Creating a Basic Web Page in Visual Web Developer ), you can use that Web site and skip to "Configuring
Membership" later in this walkthrough. Otherwise, create a new Web site and page by following these steps.
To create a local IIS Web site
1. Open Visual Studio.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, select ASP.NET Web Site.
4. In the Location list box, select HTTP. Click Browse.
The Choose Location dialog box appears.
5. Select Local IIS.
6. Open Local Web Servers.
7. Select Default Web Site.
8. Click the Create New Web Application icon ( ) above the list of Web sites and then name the new Web site
membership.
9. Click Open.
The Choose Location dialog box closes.
10. In the Languages box, click the programming language you prefer to work in.
The programming language you choose will be the default for your Web site, but you can set the programming
languages for each page individually.
11. Click OK in the New Web Site dialog box.
Visual Web Developer creates the Web site and a new page named Default.aspx.
Configuring Membership
Later in this walkthrough you will put pages into a subdirectory that is protected. You must create the subdirectory now so that
you can configure security for it later in the walkthrough.
To add a new folder to the Web site
1. In Solution Explorer, right-click the name of your Web site and click New Folder.
2. Name the folder MemberPages.
Before you work with ASP.NET membership, you must configure your application to enable membership and to set up users.
You can use the Web Site Administration tool, which provides a wizard-like interface for making configuration settings.
For this walkthrough, you will define a single user.
To create a membership user
1. On the Website menu, click ASP.NET Configuration.
2. Select the Security tab, click the link to Use the security Setup Wizard to configure security step by step, and then
click Next.
3. Proceed to Step 2 of the wizard and select the From the Internet option.
The wizard displays a page where you can select the authentication method that your Web site will use. This option
specifies that your application will use Forms authentication, where users will log in to the application using a login page
that you will create later in this walkthrough.
4. Click Next.
The wizard displays a message stating that user information will be stored using Advanced provider settings. By
default, membership information is stored in a Microsoft SQL Server Express database file in the App_Data folder of
your Web site.
5. Click Next.
The wizard displays an option to create roles. You will perform this step separately later in the walkthrough. Therefore, do
not select the Enable roles for this web site check box.
6. Click Next.
The wizard displays a page where you can create new users.
7. Enter information that defines a user of your application. Use the following values as guidelines (you can use any values
that you like, but be sure to note your entries for later in the walkthrough):
User Name Your name (with no spaces), or a sample name.
Password A password. A strong password is required (one that includes uppercase and lowercase letters,
punctuation, and that is at least eight characters long).
E-mail Your personal e-mail address. Later in the walkthrough you will send yourself an e-mail message, so you
need a legitimate e-mail address.
Security Question and Security Answer Type a question and answer that can be used later if you need to
recover your password.
8. Click Create User.
The wizard displays a confirmation page.
Note
Leave the Web Site Administration tool open.

Earlier in the walkthrough you created a folder named MemberPages. In this part of the walkthrough, you will create a rule
that makes sure that only logged-in users can access pages in that folder.
To set up access rules for the MemberPages subdirectory
1. In the wizard, click Next.
The wizard displays a page that allows you to create access rules.
2. In the Add New Access Rule box, expand the node for your Web site.
3. Select MemberPages, the folder you created earlier.
4. Under Rule applies to, select Anonymous users.
5. Under Permission, select Deny.
The rule you are creating denies access to anonymous users — that is, users who have not logged in.
6. Click Add This Rule.
The new rule is displayed in the grid below. When users request a page from the MemberPages subdirectory, the rules
are checked to determine whether the user is allowed access to the page.
7. Click Finish.
You are now done with the wizard. The wizard closes and you are returned to the Security tab of the Web Site
Administration tool.
Configuring the Application for E-Mail
For part of this walkthrough, the application needs to be able to send e-mail messages. To send messages, your application
must have access to a Simple Mail Transport Protocol (SMTP) server, which forwards e-mail messages from your application to
an e-mail recipient.
IIS includes the Default SMTP virtual server as an optional component, which is suitable for this walkthrough. For more
information about configuring this server, see How to: Install and Configure SMTP Virtual Servers in IIS. If you are working on a
local area network, check with your network administrator for information about access to an e-mail server.
After you have set up or determined how to access an SMTP server, you must configure your application to route e-mail
messages to that server. You can do so by making an entry in your Web site's Web.config file, which contains a series of
settings that determine how your application runs.
To configure the application to use a specific SMTP server
1. In the Web Site Administration tool, click the Application tab.
2. Under SMTP Settings, click Configure SMTP e-mail settings.
The tool displays a page where you can configure e-mail.
3. If you are using the SMTP virtual server that is on your computer, enter localhost as the Server Name; otherwise, enter
the appropriate server name.
Include information for the port number and for authentication according to the requirements of your SMTP server. See
your administrator for more information on how to configure these settings.
4. In the From box, type a valid e-mail address.
5. Click Save, and in the confirmation page, click OK.
The Web Site Administration tool creates a Web.config file (if one did not already exist) with the settings you have made.
Note
The Web.config file will not appear in Solution Explorer until you refresh the view.

6. Close the Web Site Administration tool.


Logging the User In
As part of your application, you need to establish the user's identity so that the application can perform actions — such as
showing or hiding information — based on who the user is. To get the user's identity, you have the user log in.
In this walkthrough, you will add a link on the home page that takes users to a login page, and then you will create the login
page.
To create a home page with a login button
1. Open or switch to the Default.aspx page of your site. (If you do not have a Default.aspx page, you can add one or use a
different page.)
2. Switch to Design view.
3. Type static text such as Welcome to our site and, in the Formatting toolbar, use the Block Format drop-down list to
format the text as Heading 1.
4. From the Login group of the Toolbox, drag a LoginStatus control onto the page.
By default, the LoginStatus control is rendered as a link. When users click it, the application displays a login page. You can
now create the login page.
To create a login page
1. In Solution Explorer, right-click your Web application and select Add New Item. Add a Web Form named Login.aspx
to your site.
Note
For this walkthrough, the page must be named Login.aspx. By default, forms authentication is configured to work with
a page with this name. Although you will not do so in this walkthrough, you can change the default login page — the p
age to which users are redirected — in the Web.config file.

2. In the Login.aspx page, switch to Design view.


3. From the Login group of the Toolbox, drag a Login control onto the page.
The Login control is a single control that will prompt the user for credentials and validate them.
Displaying Login Errors
The Login control includes validation to help users enter correct information. For example, if a user skips the password, a
validator control displays an asterisk (*) next to the Password box. You can provide more complete information for login
errors by adding a ValidationSummary control to the page.
To display detailed login errors
1. From the Validation group of the Toolbox, drag a ValidationSummary control onto the page.
2. In the Properties window for the ValidationSummary control, set the ValidationGroup property to Login1, which is
the default ID of the Login control you added previously.
Displaying Information for Logged-In Users
You will now modify the home page to customize the display depending on whether the user is logged in. Anonymous users
will see a generic message inviting them to log in. Logged-in users will see a message that welcomes them by their logged-in
name.
To customize the display for logged-in users
1. Switch to or open the Default.aspx page.
2. From the Login group of the Toolbox, drag a LoginView control onto the page.
The LoginView control is displayed with its AnonymousTemplate template open. This template allows you to define
the content that users will see before they have logged in.
3. Click the edit area of the LoginView control to activate editing.
4. In the edit area of the LoginView control's AnonymousTemplate template, type You are not logged in. Click the
Login link to sign in.
5. On the LoginView Tasks panel, in the Views list, click LoggedInTemplate. If you do not see the LoginView Tasks
panel, right-click the heading of the LoginView control and select Show Smart Tag.
You are now defining the content that will be displayed to users who have already logged in.
6. Click the edit area of the LoginView control to activate editing, and then type You are logged in. Welcome,.
7. From the Login group of the Toolbox, drag a LoginName control into the template after the text.
Testing Login
You can now test the login capability of your application.
To test login
1. In Solution Explorer, right-click Default.aspx and click Set As Start Page.
This configures the Web site so that when you run the site, the Default.aspx page appears first.
2. Press CTRL+F5 to run the Web site.
The home page (Default.aspx) appears in the browser, showing the Login link and the generic message.
3. Click the Login link.
The login page you created is displayed.
4. Type the login name of the user you created earlier in the walkthrough, and then click Log In. (Do not yet enter a
password.)
An asterisk (*) is displayed next to the Password box, and an error message is displayed in the ValidationSummary
control.
5. Type both a user name and password and then click Log In.
If you entered correct credentials, you are returned to the home page. The page now displays a Logout link, your user
name, and the welcome message that you defined for the logged-in user.
6. Close the browser.
Limiting Access for Members-Only Pages
A typical task in many Web sites is to configure pages so that only logged-in users can view the pages. Earlier in the
walkthrough, you created the MemberPages subdirectory and created a rule that limits access to pages in the subdirectory. In
this section of the walkthrough, you will add a page to the protected subdirectory and test the access rule.
To create the members-only page
1. In Solution Explorer, right-click the MemberPages folder, click Add New Item, and add a new Web Form named
Members.aspx.
Note
Be sure to create the page in the MemberPages folder.

2. In Design view, add text to the page, such as Welcome, members! The exact text does not matter, as long as you will be
able to recognize this page when you see it in the browser.
You can now add a link to the members-only page from the home page. In a real application, you would probably put the
members-only page link in the logged-in template of the LoginView control. That way, visitors to your site would not see the
link until they were logged in. For this walkthrough, however, you will make the link available to all users so that you can see
the effect of trying to view a members-only page without first logging in.
To add a link to the members-only page
1. Switch to or open the Default.aspx page.
2. From the Standard group of the Toolbox, drag a HyperLink control onto the page.
3. In the Properties window for the HyperLink control, set the Text property to Members page and the NavigateUrl
property to ~/MemberPages/Members.aspx to point to the page that you created previously.
Testing the Members-Only Page
You can test the members-only page by accessing it both as an anonymous user and a logged-in user.
To test the members-only page
1. Press CTRL+F5 to run the Web site.
2. When the Default.aspx page appears in the browser, do not log in. Instead, click the Members page link.
You are redirected to the Login.aspx page because access to the members page is denied for anonymous users.
3. In the login page, type the user name and password that you used earlier in the walkthrough to log in.
You are redirected to the Members.aspx page because the user name you are logged in as has been authorized to access
the page.
4. Close the browser window.
Creating New Users
In the first part of the walkthrough, you created a user with the Web Site Administration tool. That strategy is useful if you are
working with a small, defined list of users; for example, if you are creating users for a small team. In many Web sites, however,
users are allowed to register themselves. ASP.NET includes the CreateUserWizard control that performs the same task you
performed earlier using the Web Site Administration tool.
In this part of the walkthrough, you will add a facility that allows users to register on your Web site. To start, you will create a
registration page.
To create a registration page
1. In Solution Explorer, right-click the name of your Web site, click Add New Item, and add a new Web Form named
Register.aspx.
Note
Be sure to create the page in the root of the Web site, not in the MemberPages folder.

2. In the Register.aspx page, switch to Design view and type static text such as Register into the page. In the Formatting
toolbar, use the Block Format drop-down list to format the text as Heading 1.
3. From the Login group of the Toolbox, drag a CreateUserWizard control onto the page.
4. In the Properties window for the CreateUserWizard control, set the ContinueDestinationPageUrl property to
~/Default.aspx.
This configures the control so that when users click Continue after creating a user, the control returns to the home page.
5. From the Standard group of the Toolbox, drag a HyperLink control onto the page. In the Properties window for the
HyperLink control, set the Text property to Home and the NavigateUrl property to ~/Default.aspx.
You can now add a link to the home page that displays the registration page. For this walkthrough, assume that you want to
display the registration link only to users who are not logged in.
To create a registration link on the home page
1. Switch to or open the Default.aspx page.
2. Right-click the LoginView control added previously, and select Show Smart Tag. In the LoginView Tasks panel, select
AnonymousTemplate from the Views list box to activate editing in the anonymous template.
3. From the Standard group of the Toolbox, drag a HyperLink control into the anonymous template. In the Properties
window for the HyperLink control, set the Text property to Register and the NavigateUrl property to Register.aspx.
The Register link will be displayed only to users who are not logged in.
You can now test the registration process.
To test registration
1. Press CTRL+F5 to run the Web site and display the Default.aspx page.
Because you are not logged in, the page containing the Register link is displayed.
2. Click the Register link.
The registration page is displayed.
3. In the text boxes, enter a new user name, a strong password, an e-mail address, and a security question and answer. (All
five pieces of information are required.)
4. Click Create User.
A confirmation message is displayed.
5. Click the Continue button.
You are returned to the home page as a logged-in user. Note that the Login link has changed to Logout and that the
information displayed in the Login control is from the LoggedInTemplate property, not from the AnonymousTemplate
property.
6. Click the Logout link.
The page changes to display the information for anonymous users.
7. Click the Login link.
8. Enter the credentials for the user you just created.
You are logged in as the new user.
9. Close the browser window.
Changing Passwords
Users sometimes might want to change their passwords, and it is often impractical to perform this task by hand. You can
therefore use another ASP.NET control to allow users to change passwords on their own. To change a password, users must
know their existing password.
In this walkthrough, you will add a page where logged-in users can change their password.
To create a password-change page
1. In Solution Explorer, right-click the MemberPages folder, click Add New Item, and add a new Web Form named
ChangePassword.aspx.
Note
Be sure to create the page in the MemberPages folder.

You are putting the page in the members-only folder because only logged-in users can change their passwords.
2. In the ChangePassword.aspx page, switch to Design view and type static text such as Change Password. In the
Formatting toolbar, use the Block Format drop-down list to format the text as Heading 1.
3. From the Login group of the Toolbox, drag a ChangePassword control onto the page.
4. In the Properties window for the ChangePassword control, set ContinueDestinationPageUrl property to
~/Default.aspx.
5. This configures the control so that when users click Continue after changing a password, the control returns to the
home page.
You can now add a link to the home page that displays the password-change page. You will make the link available only to
users who are logged in.
To create a password-change link on the home page
1. Switch to or open the Default.aspx page.
2. Right-click the LoginView control and then click Show Smart Tag. In the LoginView Tasks menu, in the Views list,
click LoggedInTemplate.
This switches the LoginView control to edit mode for the content that will appear to users who are logged in.
3. From the Standard group of the Toolbox, drag a HyperLink control into the editing region. In the Properties window
for the HyperLink control, set the Text property to Change password and the NavigateUrl property to
~/MemberPages/ChangePassword.aspx.
The Change password link will be displayed only to users who are logged in, which is the opposite of the Register link
you created earlier.
You can now test the password-change process.
To test password change
1. Press CTRL+F5 to run the Web site.
2. In the Default.aspx, page, click the Login link and log in as one of the users you have created.
When you are finished, you are returned to the home page as a logged-in user.
3. Click the Change password link.
4. In the password-change page, enter the old password and a new password, and then click Change Password.
5. Click Continue.
6. On the home page, click Logout.
7. Click the Login link.
8. Enter the new password.
You are logged in with the new password.
9. Close the browser window.
Recovering a Password
Users will occasionally forget their passwords. You can add a password recovery page to your Web site so that they can once
again log in to your site. Password recovery can take two forms:
You can send users the password they selected (or that you created for them when you set up the site). This option
requires that the site store the password using reversible encryption.
You can send users a new password, which they can change using the Change Password page you created earlier. This
option is useful if the Web site stores passwords using a non-reversible encryption scheme such as hashing.
Note
Returning a password in clear text using e-mail is not recommended for sites that require a high level of security. For high-se
curity sites, it is recommended that you return passwords using encryption, such as Secure Sockets Layer (SSL).
By default, the ASP.NET membership system secures passwords by hashing them, meaning that the passwords cannot be
recovered. Therefore, for this part of the walkthrough, your Web site will send users a new password.
Note
Password recovery requires that your Web site can send e-mail messages. If you are not able to configure your Web site to s
end e-mail (as explained under "Configuring the Application for E-Mail" earlier in this walkthrough), you will not be able to a
dd password recovery to your site.

To add password recovery


1. In Solution Explorer, right-click the name of your Web site, click Add New Item, and add a new Web Form named
RecoverPassword.aspx.
Note
Be sure to create the page in the root of the Web site, not in the MemberPages folder.

2. In the RecoverPassword.aspx page, switch to Design view and type static text such as Reset my password to a new
value. In the Formatting toolbar, use the Block Format drop-down list to format the text as Heading 1.
3. From the Login group of the Toolbox, drag a PasswordRecovery control onto the page.
4. From the Standard group of the Toolbox, drag a HyperLink control onto the page. In the Properties window for the
HyperLink control, set the Text property to Home and the NavigateUrl property to ~/Default.aspx.
5. Switch to the Default.aspx page.
6. Right-click the LoginView control and then click Show Smart Tag. In the LoginView Tasks menu, in the Views list,
click AnonymousTemplate.
This switches the LoginView control to edit mode for the content that will appear to users who are not logged in.
7. From the Standard group of the Toolbox, drag a HyperLink control into the template. In the Properties window for
the HyperLink control, set the Text property to Forgot your password? and the NavigateUrl property to
~/RecoverPassword.aspx.
Now you can test password recovery.
To test password recovery
1. Press CTRL+F5 to run the Web site.
2. By default, you are not logged in, so you see the anonymous template of the LoginView control.
3. Click the Forgot your password? link.
The RecoverPassword.aspx page appears.
4. Type your user name and click Submit.
The security question is displayed and you are prompted to type the security answer.
5. Type the answer and click Submit.
If you entered a correct answer, the Web site resets your password and sends you an e-mail message with the new
password.
Next Steps
This walkthrough has illustrated a simple but complete scenario for creating an application that prompts users for credentials,
displays information to logged-in users, allows users to recover a forgotten password, and limits access to pages. You can
create more sophisticated pages and applications using the techniques and controls illustrated in the walkthrough. For
example, you might want to:
Create additional users and define roles (groups) such as managers, sales, or members and assign users to different
roles. For details, see Walkthrough: Managing Web Site Users with Roles.
Change the membership provider from the default Access provider to a SQL provider. Storing membership information
in an Access database is suitable for small to medium-sized sites, but if your site will experience heavy traffic, you will
want to use Microsoft SQL Server as the membership store. For more information, see
Web Site Administration Tool Provider Tab and Creating the Application Services Database for SQL Server.
Change the appearance of login controls. The Login, PasswordRecovery, and CreateUserWizard controls all support
templates, which allows you to configure the text and buttons they contain as well as change the color, font, and other
appearance characteristics of the controls. For more information, see the topics in the Login ASP.NET Controls section.
Create rules that limit access to pages or folders not only for anonymous users, but for specific users or roles.
Combine membership with profile properties, which allows you to store user-specific settings for each user. For details,
see Walkthrough: Maintaining Web Site User Information with Profile Properties.
Combine login controls with master pages. Master pages allow you to define a page layout that you can use for all the
pages in your application. For details, see
Walkthrough: Creating and Using ASP.NET Master Pages in Visual Web Developer.
Add the ability to recover a forgotten password. For more information, see
How to: Enable User Password Recovery Using the ASP.NET PasswordRecovery Control.
See Also
Concepts
Introduction to Membership
ASP.NET

Storing Sensitive Information Using ASP.NET


Often in an ASP.NET application you are required to make use of highly sensitive information. For example, you may need to
use a user ID and password to connect to a database or you may be storing user IDs and passwords that customers use to
access your application. While you can use secure sockets layer (SSL) to encrypt information as it is passed over the network,
that information must also be protected when it is stored both on the server and on the client. This topic covers some general
guidelines for storing sensitive information.
Note
For more information about storing sensitive information, see Improving Web Application Security: Threats on the MSDN W
eb site.

Avoid Storing Sensitive Information When Possible


The best way to avoid exposing sensitive information in an application is not to store it. Minimize the places where sensitive
information is stored. Avoid storing sensitive information for your application in a cookie or a control that is persisted in the
browser, which would expose the sensitive information to clients of your application. Avoid storing sensitive information in
your application logic. Instead, retrieve the sensitive information from a secure configuration location or from the client.
Encrypt Sensitive Information
When you do store sensitive information, avoid storing it in human-readable text or in an easily decoded format, such as
Base64 encoding. Instead, encrypt the information so that, if it is exposed to an attacker somehow, the attacker cannot easily
determine what the sensitive information contains.
If the sensitive information needs only to be verified and not decrypted to a human-readable format, encrypt the sensitive
information using a one-way hash. Then, when comparing the sensitive information received from a source that is being
validated, hash the value received and compare the hashes for verification. For example, if you are using ASP.NET Membership
and Forms Authentication to provide user authentication for your application, set the password format to Hashed so that
passwords are encrypted using a one-way hash when they are stored in the data source or compared for validation.
When storing sensitive information such as connection strings, user credentials, or encryption keys in the Web.config file for an
application, encrypt the sensitive sections of the Web.config file using a protected configuration provider. For more
information about protected configuration, see Encrypting Configuration Information Using Protected Configuration.
For more information about using encryption to protect sensitive information, see .NET Framework Cryptography Model.
Protect Sensitive Information using Permissions
When storing sensitive information in files, databases, the registry, or other locations, use NTFS Access Control Lists and
database permissions to restrict access to the information to only the required sources and only the require access. For more
information, see your database documentation or ASP.NET Required Access Control Lists (ACLs).
See Also
Other Resources
Getting Started — ASP.NET Web Site Security (Visual Studio)
ASP.NET Web Site Security (Visual Studio)
ASP.NET

Limiting Access to ASP.NET Web Sites


Limiting access to an application is generally divided into two topics: authentication, which is how an application identifies who
you are, and authorization, which is how an application identifies what you are permission to do. This topic provides an
overview of authentication and authorization in ASP.NET Web applications. For more detailed information, see
ASP.NET Web Application Security.
Authenticating Users
ASP.NET applications offer several different options for authenticating users. For read-only applications that can be viewed by
anyone, use anonymous authentication. For more restricted access to an application, you need to use some form of
authentication to identify users. There are two identities that you should to consider when authenticating users for your
ASP.NET application: the application identity that is used to access Windows resources and the ASP.NET user identity that is
used to identify a user to ASP.NET.
Your application can run without an ASP.NET user identity, but you will always have a Windows application identity. To help
secure your application, you should restrict the Windows identity for the application to the required resources, such as file and
database access.
ASP.NET Application Identity
When an ASP.NET page is executing, the server must have a security context, or identity, for the process that is executing the
ASP.NET code. This identity is used when securing resources using Windows Integrated security, such as files protected using
the NTFS file system or network resources.
For example, the files that contain the application code stored in the App_Code subdirectory of an application only need to be
read by the ASP.NET application identity. Therefore, the security settings for the files in the App_Code directory can be
restricted so that the ASP.NET application identity has Read access only. Another common use of the Windows identity of the
ASP.NET application is as the identity of a connection to a SQL Server using Integrated Security. For more information, see
ASP.NET Required Access Control Lists (ACLs) and How to: Access SQL Server Using Windows Integrated Security.
The identity of an ASP.NET application is determined by several factors. By default, ASP.NET pages run with the Windows
identity of the service that processes ASP.NET pages on the Web server. On a computer running Windows Server 2003, that
identity is the identity of the application pool that the ASP.NET application is a part of (by default, the NETWORK SERVICE
account). On computers running Windows 2000 and Windows XP Professional, the identity is the local ASPNET account is
created when the .NET Framework is installed. This identity can be configured to a different identity if desired. For more
information, see Configuring ASP.NET Process Identity.
You can modify the Windows identity that your ASP.NET page runs as by using the identity element of the system.web
configuration section. The identity element can be used to instruct ASP.NET to impersonate a Windows user ID. Impersonating
a Windows identity means that the ASP.NET pages for the application will run as that Windows identity. You can specify a user
name and password to impersonate. Alternatively, you can enable impersonation and ASP.NET will run in one of two ways: an
anonymous identity specified by IIS, or the authenticated browser identity as determined by IIS (for example, Anonymous
authentication, Windows Integrated (NTLM) authentication, and so on). For more information, see ASP.NET Impersonation.
If you are impersonating a Windows identity, you can execute code that reverts to the original identity of the process instead of
the impersonated user ID. For this reason, in environments where you need to keep one application separate from another,
you should isolate the applications in separate application pools on computers running Windows Server 2003. Each
application pool should be configured with a unique Windows identity.
You can easily determine the Windows identity of the operating system thread that your ASP.NET page is running by using the
Name property of the WindowsIdentity returned by the GetCurrent method as shown in the following code example.

<%=System.Security.Principal.WindowsIdentity.GetCurrent().Name%>

ASP.NET User
The ASP.NET user identity is used to access ASP.NET-specific resources. For example, you can identify a portion of your
application that is only available to certain users, while other portions of your application are available to all users.
The ASP.NET user is determined by the authentication element of the system.web section of the Web.config file for your
application. You have several options for authenticating the ASP.NET identity for your application. You can use the Windows
user name that is determined by IIS, ASP.NET Forms authentication, Passport authentication, or a custom authentication
scheme. The ASP.NET identity can be accessed using the User property of the current HttpContext. For details, see
ASP.NET Authentication.
If you are using ASP.NET Forms authentication or a custom authentication solution to provide the ASP.NET identity, you can
use ASP.NET membership to provide a user data store and user management functionality. For more information, see
Managing Users by Using Membership.
Authorizing Users
Authorization involves restricting user access to only those resources that are required. This includes restricting access to only
the required files, databases, and portions of your application. In addition, this includes using Code Access Security to restrict
access to code.
You can restrict file access by using NTFS access control lists and the FileAuthorizationModule. For more information, see
ASP.NET Authorization and ASP.NET Required Access Control Lists (ACLs).
You can restrict access to portions of your application by using the UrlAuthorizationModule and ASP.NET Role Management.
For more information, see ASP.NET Authorization and Managing Authorization Using Roles.
See Also
Other Resources
Getting Started — ASP.NET Web Site Security (Visual Studio)
ASP.NET Web Site Security (Visual Studio)
Visual Web Developer

Script Exploits
The topics in this section provide information about what script exploits are, how they can compromise the security of your
ASP.NET Web applications, and about which steps you can take to mitigate the threat of script exploits.
In This Section
Script Exploits Overview
How to: Protect Against Script Exploits in a Web Application by Applying HTML Encoding to Strings
See Also
Other Resources
ASP.NET Web Site Security (Visual Studio)
ASP.NET

Script Exploits Overview


From the perspective of a browser, a Web page is simply a long string of characters. The browser processes the string
sequentially, displaying some characters while interpreting other characters, such as <b> and <script> according to special
rules. If a malicious user can insert some of those special characters into a page, the browser will not know that the characters
are not supposed to be there, and it will process them as part of the page.
A simplistic script exploit might work as follows. If an application allows users to post comments about the latest movies for
other users to read, the exploit steps might be:
1. The application displays a form where users enter comments. The malicious user writes a comment that includes a
<script> block in it.

2. The form is posted and the malicious user's comment is stored in a database.
3. Another user visits the site. When the page is constructed, it reads comments out of the database and puts them into the
page. The malicious user's <script> block is written into the page as if it were a text comment.
4. When the second user's browser displays the page, it gets to the <script> block and executes it.
There are other ways that malicious users can exploit script. Most script exploits require the application to accept the malicious
input and inject it (or echo it) into a page where it will be executed by the browser. The potential damage from such an exploit
depends on the script that is executed. It can be trivial, such as an annoying message that pops up in the browser. But it can
also do serious damage by stealing cookies, stealing user input (such as a password), and, if Internet security is lax, running
native code on the user's computer.
For information about preventing script exploits, see
How to: Protect Against Script Exploits in a Web Application by Applying HTML Encoding to Strings.
SQL Statement Exploits
A variation on a script exploit is one that causes malicious SQL statements to be executed. This can occur if an application
prompts users for information and then concatenates the user's input into a string representing the SQL statement. For
example, an application might prompt for a customer name with the intention of executing a statement, such as the following:

"Select * From Customers where CustomerName = " & txtCustomerName.Value

But a malicious user who knows something about the database could use the text box to enter an embedded SQL statement
with the customer name, resulting in a statement like the following:

Select * From Customers Where CustomerName = 'a' Delete From


Customers Where CustomerName > ''

When the query is executed, the database is compromised.


Guarding Against Scripting Exploits
The primary defense against scripting exploits is to never trust information coming from a user. Assume that any data posted
to your application from a browser can contain malicious script.
Similarly, any time that you write a string into a page, you should assume that the string could contain malicious script (unless
you programmatically created the string yourself). For example, when you read strings out of a database, you should assume
that they can contain malicious script. The most security-conscious developers distrust even their own databases, on the theory
that a malicious user might have found a way to tamper with the database.
ASP.NET provides you with several ways to help protect against scripting exploits:
ASP.NET performs request validation against query-string and form variables as well as cookie values. By default, if the
current Request contains HTML-encoded elements or certain HTML characters (such as &#151; for an em dash), the
ASP.NET page framework raises an error.
If you want to display strings in your application but do not trust them, apply HTML encoding to them when the strings
are written back in a response. For example, with encoding, the tag <b> becomes &lt;b&gt;. You might do this if the
strings that you are displaying are from a database whose contents you are not sure that you can trust.
If you want your application to accept some HTML (for example, some formatting instructions from users), you should
encode the HTML at the client before it is submitted to the server.
To help protect against SQL statement exploits, never create SQL queries using string concatenation. Instead, use a
parameterized query and assign user input to parameter objects. For details, see Parameters in Data-Adapter Commands.
Always validate form input against a set of expected values and string formatting/type validation. For example, if a
specific form variable is expected to be an integer, use both the System.Int32.TryParse method to verify that the value
really is an integer and use range checking to help ensure that the value is within an acceptable range.
See Also
Tasks
How to: Protect Against Script Exploits in a Web Application by Applying HTML Encoding to Strings
Concepts
Overview of Web Application Security Threats
Basic Security Practices for Web Applications (Visual Studio)
ASP.NET

How to: Protect Against Script Exploits in a Web Application by


Applying HTML Encoding to Strings
Most scripting exploits occur when users can get executable code (or script) into your application. By default, ASP.NET provides
request validation, which raises an error if a form post contains any HTML.
You can help protect against script exploits in the following ways:
Perform parameter validation on form variables, query-string variables, and cookie values. This validation should include
two types of verification: verification that the variables can be converted to the expected type (for example, convert to an
integer, convert to date-time, and so on), and verification of expected ranges or formatting. For example, a form post
variable that is intended to be an integer should be checked with the System.Int32.TryParse method to verify the variable
really is an integer. Furthermore, the resulting integer should be checked to verify the value falls within an expected
range of values.
Apply HTML encoding to string output when writing values back out to the response. This helps ensure that any user-
supplied string input will be rendered as static text in the browsers instead of executable script code or interpreted HTML
elements.
HTML encoding converts HTML elements using HTML–reserved characters so that they are displayed rather than executed.
To apply HTML encoding to a string
Before displaying strings, call the HtmlEncode method. HTML elements are converted into string representations that the
browser will display rather than interpret as HTML.
The following example illustrates HTML encoding. In the first instance, the user input is encoded before being displayed.
In the second instance, data from a database is encoded before being displayed.
Note
This example will only work if you disable request validation in the page by adding the @ Page attribute ValidateRequ
est="false". It is not recommended that you disable request validation in a production application, so make sure that
you enable request validation again after viewing this example.

VB
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e _
As System.EventArgs) Handles Button1.Click
Label1.Text = Server.HtmlEncode(TextBox1.Text)
Label2.Text = _
Server.HtmlEncode(dsCustomers.Customers(0).CompanyName)
End Sub

C#
private void Button1_Click(object sender, System.EventArgs e)
{
Label1.Text = Server.HtmlEncode(TextBox1.Text);
Label2.Text =
Server.HtmlEncode(dsCustomers1.Customers[0].CompanyName);
}

See Also
Concepts
Script Exploits Overview
Overview of Web Application Security Threats
Basic Security Practices for Web Applications
ASP.NET

How to: Display Safe Error Messages


When your application displays error messages, it should not give away information that a malicious user might find helpful in
attacking your system. For example, if your application unsuccessfully tries to log in to a database, it should not display an
error message that includes the user name it is using.
There are a number of ways to control error messages, including the following:
Configure the application not to show verbose error messages to remote users. (Remote users are those who are not
requesting pages while working on the Web server computer.) You can optionally redirect errors to an application page.
Include error handling whenever practical and construct your own error messages. In your error handler, you can test to
see whether the user is local and react accordingly.
Create a global error handler at the page or application level that catches all unhandled exceptions and routes them to a
generic error page. That way, even if you did not anticipate a problem, at least users will not see an exception page.

To configure the application to turn off errors for remote users


In the Web.config file for your application, make the following changes to the customErrors element:
Set the mode attribute to RemoteOnly (case-sensitive). This configures the application to show detailed errors only
to local users (that is, to you, the developer).
Optionally include a defaultRedirect attribute that points to an application error page.
Optionally include <error> elements that redirect specific errors to specific pages. For example, you can redirect
standard 404 errors (page not found) to your own application page.
The following code example shows a typical customErrors block in the Web.config file.

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


<error statusCode="404" redirect="NoSuchPage.aspx"/>
<error statusCode="403" redirect="NoAccessAllowed.aspx"/>
</customErrors>

To include error handling


1. Use a try-catch block around any statements that might generate errors.
2. Optionally, test for a local user with the IsLocal property and modify error handling accordingly. The value 127.0.0.1 is
equivalent to localhost and indicates that the browser is on the same computer as the Web server.
The following code example shows an error-handling block. If an error occurs, a session state variable is loaded with
details about the message, and the application then displays a page that can read the Session variable and display the
error. (The error is deliberately written to provide no exploitable details to the user.) If the user is local, different error
details are provided. In the finally block, an open resource is released.
VB
Try
SqlConnection1.Open()
SqlDataAdapter1.Fill(Me.DsPubs1)
Catch ex As Exception
If Request.IsLocal Then
Session("CurrentError") = ex.Message
Else
Session("CurrentError") = "Error processing page."
End If
Server.Transfer("ApplicationError.aspx")
Finally
SqlConnection1.Close()
End Try

C#
try
{
sqlConnection1.Open();
sqlDataAdapter1.Fill(dsCustomers1);
}
catch (Exception ex)
{
if(Request.IsLocal)
{ Session["CurrentError"] = ex.Message; }
else
{ Session["CurrentError"] = "Error processing page."; }
Server.Transfer("ApplicationError.aspx");
}
finally
{
this.sqlConnection1.Close();
}

Creating a Global Error Handler


You can also create an error handler that catches all unhandled exceptions at the page level or for the application as a whole.
To create a global error handler
To create a global handler in a page, create a handler for the System.Web.UI.TemplateControl.Error event. To create an
application-wide error handler, in the Global.asax file, add code to the System.Web.HttpApplication.Error event. These
methods are called if an unhandled exception occurs anywhere in your page or application, respectively. You can get
information about the most recent error from the GetLastError method.
Note
If you have a global error handler, it takes precedence over error handling specified in the defaultRedirect attribute of
the customErrors configuration element.

The following code example shows a handler that gets information about the current error, puts it into a Session
variable, and then calls a generic error-handling page that can extract and display the error information.
VB
Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
Session("CurrentError") = "Global: " & _
Server.GetLastError.Message
Server.Transfer("lasterr.aspx")
End Sub

C#
protected void Application_Error(Object sender, EventArgs e)
{
Session["CurrentError"] = "Global: " +
Server.GetLastError().Message;
Server.Transfer("lasterr.aspx");
}
See Also
Other Resources
ASP.NET Web Site Security
ASP.NET

Web Application Security at Run Time


Developing your application requires that you work with one set of security issues. The other set of issues — and the ones that
are generally more prominent in any discussion of Web security — address the security of your application when it is deployed
and running.
Web applications by definition allow users access to a central resource — the Web server — and through it, to others such as
database servers. By understanding and implementing proper security measures, you:
Guard your own resources against unauthorized access.
Restrict access levels by user or role.
Establish data integrity and confidentiality, providing a relatively secure environment in which your users are
comfortable working with your application.
Establish control over how your application can get access to restricted resources.
Ensure that your application's code runs as intended.
This topic provides a general discussion of how you can accomplish these goals, and it includes links to additional topics where
you can get more details on the technologies involved.
You can help protect your application from unauthorized access by taking advantage of these types of security features:
Security features offered by Internet Information Services (IIS) as part of its general Web server function. These include
Windows file, computer, and user-level security.
Security you can build into your ASP.NET application to provide application-specific access.
Security Process in ASP.NET
IIS provides many security options for Web sites. However, IIS security mechanisms are very generic, in that the same
mechanisms are used for all applications. Moreover, IIS security options — for example, using Windows Integrated security —
might not always be convenient for your application. (For intranet applications, on the other hand, you might want to use
Windows Integrated security for simplicity.)
Therefore, in order to provide access to specific portions of your application, you can use ASP.NET security. ASP.NET security
works in conjunction with IIS security but extends it so that you can customize features, such as how to get user credentials.
IIS receives requests first from clients and performs any security checks that have been established for your application using
IIS management tools. For example, if the application has been configured in IIS to allow anonymous access, IIS performs no
credentials check. After performing this initial check of authentication, IIS sends the request to ASP.NET, which can perform a
second level of checking. ASP.NET allows you to specify access restrictions in your application using a variety of criteria: you
can restrict access to specific pages, or to specific users, and so on.
Authentication
The following table describes the authentication methods that are supported by ASP.NET. Several of these overlap with IIS
authentication. For details, see ASP.NET Authentication.
Authentic Description
ation Typ
e
Anonymou For applications where unknown users will be making requests (typically, public Web applications). Overlaps with I
s access IS.

Basic and (IIS Security Option) In this scenario, users without credentials are prompted to supply a user name and password.
Digest auth
entication
Windows I (IIS Security Option) If the user making the request has already been authenticated in a Windows-based network, II
ntegrated S can pass the user's credentials through when requesting access to a resource.
Security (al
so known a
s NTLM sec
urity)

Certificate (IIS Security Option) In this scenario, the client has a certificate — a digital identification — that has been obtained
authenticat from a third-party source. The identity mapped to the client certificate is passed to ASP.NET.
ion

Kerberos (IIS Security Option) The Kerberos authentication protocol defines the interactions between a client and a network
Authentication Service known as a Key Distribution Center (KDC). Windows 2000 and 2003 implement a KDC as th
e authentication service on each domain controller.

Windows a (ASP.NET Security Option) Integrates with the previously listed IIS security options. ASP.NET takes the security toke
uthenticati n created by IIS and makes it available as a WindowsPrincipal object set as the value of the User property of the cu
on rrent HttpContext.

Forms auth (ASP.NET Security Option) If a user needs to be authenticated, ASP.NET redirects the request to a page that you sp
entication ecify. This page usually contains a form in which you get user name information. (For extra security, the form can b
e exchanged using HTTPS protocol.) When your application gets the form information, it can perform an applicatio
n-specific check of the user's credentials. An important point is that the process of authentication is under your co
ntrol (unlike that for IIS), which allows you to specify what the form looks like and how you choose to store user in
formation.
If a user is successfully authenticated, ASP.NET issues an encrypted cookie containing a token identifying the user f
or subsequent access.

Passport a (ASP.NET Security Option) Using ASP.NET, you can check for users who have credentials they get from a Microsoft
uthenticati Passport-compliant application.
on
If a user is successfully authenticated, ASP.NET issues an encrypted cookie containing a token identifying the user f
or subsequent access.

Forms authentication is the easiest choice for ASP.NET applications on the public internet because it gives you substantial
control over how users are authenticated and it allows you to store authentication in a token on the browser.
For details about IIS security, see the access-control topics in the Windows Server TechCenter for IIS on the Microsoft TechNet
Web site. For details about ASP.NET authentication, see ASP.NET Authentication.
For details about using Forms authentication with protocol transition and constrained delegation in a Windows Server 2003
domain environment, see Kerberos Protocol Transition and Constrained Delegation.
Authorization
When your Web application runs, it requests resources from the Web server and, often, from other processes as well, such as a
database. The ASP.NET process runs in a user context that determines how your application will request those resources. The
ASP.NET process runs as a special local user named ASPNET (by default) on Windows 2000 and Windows XP Professional
Edition, or it runs as the identity of the application pool for the ASP.NET application on Windows 2003 (by default, the local
NETWORK SERVICE account). These accounts run with limited permissions. You can specify a different user context for the
ASP.NET process, including the local SYSTEM account (which runs your application in administrator context) or a user whose
credentials you explicitly provide, though this is not recommended.
In your ASP.NET application, you can specify that different users have authorized access to different resources. If your
application is using Windows authentication, you can use Windows permissions to determine authorization to access specific
files or folders on the server.
Alternatively, you can use URL-based authorization, in which authorization can be granted or denied according to different
criteria:
Specific users, or identities, which are based on the credentials provided by the user.
Roles, which are entities defined to allow multiple users to share privileges based on a common role or function.
Verbs, which are the HTTP processes (such as GET and POST) for accessing portions of your application.
For example, you can specify that all users can get pages (perform the GET verb) from your application, but that only specific
users can post pages to it. Similarly, you might specify that all users are allowed to GET pages but specific roles are denied the
right to post.
You can grant URL authorization for the application as a whole or on a directory-by-directory basis. A typical use is to allow all
users to view pages in a public directory, but to keep restricted pages in a different directory that is authorized only for specific
users or roles.
Note
By default, static files, such as images and style sheets, are not subject to ASP.NET authorization when they are served throug
h IIS. You can use IIS security features to restrict access to static files if you do not want all users to be able to access the files.
If you use the ASP.NET Development Server to test your ASP.NET application, you will see different behavior because static fil
es are subject to ASP.NET authorization and will not be served to an anonymous user when anonymous access to those files i
s disabled. Alternatively, you can map static file name extensions in IIS to the ASP.NET ISAPI extension, in which case the ASP.
NET authorization rules will apply.

For more information, see ASP.NET Authorization and Basic Security Practices for Web Applications.
ASP.NET Configuration Files
You establish ASP.NET security choices using settings in a Web.config file. The file allows you to include predefined elements
for various security options, including sections for authentication and authorization. The relevant sections of the Web.config file
might look like the following.

<configuration>
<system.web>
<authentication mode="Forms">
<forms loginUrl="login.aspx" />
</authentication>
<authorization>
<deny user="?" />
</authorization>
</system.web>
</configuration>

Your application can contain more than one configuration file. By default, there is a configuration file at the application root
that specifies security for the application as a whole — that is, security settings are inherited by subfolders. However, you can
also create configuration files in individual folders to create security settings for that folder.
For more information, see ASP.NET Architecture.
XML Web Service Security
XML Web services using .asmx files run as Web applications using ASP.NET and therefore participate in the same security
model as any ASP.NET application. For example, an XML Web service might be configured to use Basic authentication or
Windows integrated security.
At design time, when you attempt to add a reference to an XML Web service — that is, when you request the XML Web
service's discovery documents — the XML Web service will perform standard Web application authentication according to how
it was configured. For example, if the XML Web service is configured to use Basic authentication, it will expect to get a user
name and password from the requesting client. If the XML Web service is using Basic authentication, for example, the Add Web
Reference dialog box will prompt you for credentials.
If you are building an application that includes calls to an XML Web service, you need to be sure that you have appropriate
credentials before making the call, or the call will fail. At run time, you can pass credentials to the XML Web service by setting
the Credentials property of the client-side object representing the XML Web service before you call its methods.
Because other ASP.NET security options might not be sufficiently flexible, XML Web services can implement a custom
authentication solution in which credential information is passed in SOAP headers. In this solution, credentials are passed in an
optional part of the message exchanged between client and server. You can then write a custom HTTP module (implementing
the IHttpModule interface) that can listen for the information in the header and call your authentication code.
As with other ASP.NET applications, the XML Web service might implement specific role-based authorizations to limit access to
specific parts of the application.
For details, see XML Web Services Infrastructure and Securing XML Web Services Created Using ASP.NET.
Establishing Data Integrity and Confidentiality
Authentication and authorization establish who your users are and what resources they can access. These security features are
designed primarily to help protect your Web application from unauthorized use.
However, there is a separate aspect to security as well, which is to help protect your users' information and provide them with
the confidence that they can exchange sensitive information with you. For example, if your application asks users for credit
card or other account numbers, personal information, or any data that users might not want others to know, you must provide
a way for them to submit this information to you securely.
You can use Secure Sockets Layer (SSL) in IIS to exchange encrypted information using the HTTPS protocol. SSL provides
encryption in both directions: your information is transmitted to the user using encryption, and information the user posts to
your application is likewise encrypted.
Establishing SSL and Encryption
To use SSL and encryption, you must obtain a server certificate for your company or identity. The certificate is a digital
signature that identifies your site in a way that cannot be impersonated. For Internet (public) applications, you obtain a server
certificate from a recognized third-party certification authority. For private (intranet) applications, you can issue a server
certificate yourself. You might do this to help secure an internal application, such as a personnel site.
Your server certificate also enables to setup SSL-encrypted connections with your browser users. SSL uses an encryption
method called public key encryption. In this form of encryption, there are two keys: a public key used to encrypt data and a
private key that you keep secret and use to decrypt information encrypted with the public key. The server certificate you obtain
includes a public key. When users want to use SSL, your application sends the certificate and the public key to the browser. The
browser and server then use the public key to establish a way to encrypt their information exchange.
Note
Using SSL requires that the browser support an encryption key that is at least 40 bits long. This level is available in most bro
wsers. However this key length is not considered secure. You can optionally configure your application in IIS to only allow SS
L connections with a 128-bit key.

Once you have obtained a server certificate, you can instruct users to use SSL by having them use https:// as the prefix for
getting and posting Web pages. Your Web site can also be configured in IIS to only accept HTTPS connections. IIS and the
browser will automatically use an encrypted channel to exchange information.
For details about how to use SSL, see article Q307267, "How to: Secure XML Web Services with Secure Sockets Layer in
Windows 2000" in the Microsoft Knowledge Base. For information about encryption, see Cryptography Overview. For
information about certificates and about configuring SSL, see the Windows Server TechCenter for IIS on the Microsoft TechNet
Web site.
Using .NET Code Security
As a final aspect of security, you should take measures to help ensure that the code in your application is protected from
misuse, whether by being inadvertently run in an improper context or by being used in a malicious way. Because ASP.NET is
part of the .NET Framework, you can also take advantage of code access security to establish permissions for what code is
allowed to do. For information, see Code Access Security.
See Also
Concepts
Basic Security Practices for Web Applications
Visual Web Developer

Learning More — ASP.NET Web Site Security (Visual Studio)


Security should be taken into consideration with any Web site. ASP.NET provides many features to assist with securing your
Web site. The topics in this section provide in-depth information on ASP.NET features and best practices to help you create
secure Web applications.
In This Section
Accessing SQL Server from a Web Application
How ASP.NET Security Works
ASP.NET Application Security in Hosted Environments
Managing Users by Using Membership
Managing Authorization Using ASP.NET Roles (Visual Studio)
Encrypting Configuration Information Using Protected Configuration
See Also
Other Resources
ASP.NET Web Site Security (Visual Studio)
ASP.NET

Accessing SQL Server from a Web Application


When a Web application involves database access, it must provide credentials to SQL Server (that is, it must log in to SQL
Server) just as any other user or process would. In a Web application, this can introduce complications. For example, if the Web
application runs anonymously, there might not be credentials to pass to SQL Server.
There are a number of ways to design SQL Server access for your Web application. The strategy you choose depends on how
your computers are configured and whether you are on an intranet. The simplest options are:
Use Windows integrated security. This option passes the user's credentials to SQL Server. Because of delegation issues,
this frequently only works by default if SQL Server is on the same computer as IIS.
Map the identity of your ASP.NET application to a Windows domain user and then log into the database as that user. This
works well for anonymous access if SQL Server and the Web server are on separate computers.
Access the SQL Server as the local identity of your ASP.NET application (for example, the local ASPNET account on a
Windows 2000 server or the local NETWORK SERVICE account on a Windows Server 2003). This option works well for
anonymous access.
Pass an explicit user name and password in a connection string. This option can be less secure than other options so you
should always use protected configuration to secure the connection strings. You can pass a predetermined user name
and password.
In This Section
Term Definition
How to: Access SQL Server Using Windows Integrated Security Provides an example of how to use Windows integrated s
ecurity for database access.

How to: Access SQL Server Using a Mapped Windows Domain User Provides an example of how to use a mapped Windows d
omain user for database access.

How to: Access SQL Server as a Local User Provides an example of how to use a local user account fo
r database access.

How to: Access SQL Server Using Predetermined Credentials Provides an example of how to use predetermined login i
nformation for database access.

See Also
Concepts
Working with Secured Data Sources and Components
Overview of Web Application Security Threats
Basic Security Practices for Web Applications
Other Resources
ASP.NET Web Site Security
ASP.NET

How to: Access SQL Server Using Windows Integrated Security


If your application runs on a Windows-based intranet, you might be able to use Windows integrated authentication for
database access. Integrated security uses the current Windows identity established on the operating system thread to access
the SQL Server database. You can then map the Windows identity to a SQL Server database and permissions.
To connect to SQL Server using Windows integrated authentication, you must identify the Windows identity under which your
ASP.NET application is running. You must also be sure that the identity has been granted access to the SQL Server database.
This topic includes a code example that displays the current Windows identity of the ASP.NET application.
Connecting to SQL Server
If SQL Server is on a different computer than the Web server, the Windows identity must be able to flow across the network to
the remote instance of SQL Server. (Windows networks that have been configured appropriately with Kerberos authentication
are able to do this.) However, depending on the settings in the identity configuration element, the Windows identity
established on the operating system thread for ASP.NET applications may not be able to flow properly to the remote SQL
Server.
You can supply a specific user name and password for the Web site's worker process identity as shown in
How to: Access SQL Server Using a Mapped Windows Domain User, or you can impersonate the authenticated identity
supplied by Internet Information Services (IIS). To impersonate the Windows identity supplied by IIS, set the impersonate
attribute of the identity configuration element to true as shown in the following example:

<system.web>
<identity impersonate="true" />
</system.web>

In IIS, only Basic Authentication logs users on with a security token that flows across the network to a remote SQL server. By
default, other IIS security modes used in conjunction with the identity configuration element settings will not result in a token
that can authenticate to a remote SQL Server.
If the Web site is configured to support only anonymous access in IIS, then the security token passed from IIS will be that of the
Windows user account for anonymous access as configured in IIS. The anonymous user account can be used to authenticate
against a remote SQL Server. However, the default anonymous user account is a local machine account and thus will not exist
as an account on the remote SQL Server. You can change the IIS anonymous account to use a domain account, or you can
mirror the local machine account on the remote SQL Server by creating a local account on the remote SQL Server with the
same user name and password. Additionally the LogonMethod metabase property for IIS6 must be set to an option that
allows credentials to flow across the network. For example, the metabase setting MD_LOGON_NETWORK_CLEARTEXT allows
logon credentials to flow across the network.
If you are unsure of the Windows identity for your application and whether that identity is logged on with a token that can flow
across the network, you can run the following ASP.NET page as part of your application to display the name of the Windows
identity and a value indicating whether the identity can flow across the network. Note that the following sample does not take
into account whether or not Kerberos delegation has been successfully set up for your domain.
VB
<%@ Page Language="VB" %>
<%@ Import namespace="System.Security.Principal" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>ASP.NET Example</title>
<script runat="server">

Public Function WillFlowAcrossNetwork(w As WindowsIdentity) As Boolean


For Each s As SecurityIdentifier In w.Groups
If s.IsWellKnown(WellKnownSidType.InteractiveSid) Then Return True
If s.IsWellKnown(WellKnownSidType.BatchSid) Then Return True
If s.IsWellKnown(WellKnownSidType.ServiceSid) Then Return True
Next

Return False
End Function
</script>
</head>
<body>
<%
Dim current As WindowsIdentity = WindowsIdentity.GetCurrent()
Response.Write(current.Name & ", " & WillFlowAcrossNetwork(current) & "<br />")
%>
</body>
</html>

C#
<%@ Page Language="C#" %>
<%@ Import namespace="System.Security.Principal" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>ASP.NET Example</title>
<script runat="server">
public bool WillFlowAcrossNetwork(WindowsIdentity w)
{
foreach (SecurityIdentifier s in w.Groups)
{
if (s.IsWellKnown(WellKnownSidType.InteractiveSid)) { return true; }
if (s.IsWellKnown(WellKnownSidType.BatchSid)) { return true; }
if (s.IsWellKnown(WellKnownSidType.ServiceSid)) { return true; }
}
return false;
}

</script>
</head>
<body>
<%
WindowsIdentity current = WindowsIdentity.GetCurrent();
Response.Write(current.Name + ", " + WillFlowAcrossNetwork(current) + "<br />");
%>
</body>
</html>

The following procedure shows how to access a SQL Server database using Windows integrated authentication in an intranet
scenario, where each user has been granted access to the SQL Server individually.
To begin, you need to configure your application in IIS to turn off anonymous access and turn on Windows authentication.
To configure IIS for Windows integrated authentication
1. In Windows, open the Internet Information Services administration tool.
In the Microsoft Windows 2000 Server or Windows Server 2003 operating systems: In the Windows Start menu,
point to Programs, then Administrative Tools, and then Internet Services Manager.
In the Microsoft Windows XP Professional operating system: open Administrative Tools in the Control Panel.
2. Open the node for your server, and then open nodes until you find the node for your application, which is typically
located under Default Web Site.
3. Right-click your application and then click Properties.
4. On the Directory Security tab, click Edit.
5. In the Authentication Methods dialog box, clear the Anonymous Access check box, and then do one of the following:
If SQL Server is on the same computer as IIS, select the Integrated Windows authentication check box.
If SQL Server is a remote server, select the Basic Authentication check box and clear the Integrated Windows
authentication check box.
6. Click all the dialog boxes.
In the application configuration file (Web.config), specify that the application will impersonate the user's credentials supplied
by IIS.
To configure Web.config to impersonate the identity supplied by IIS
Open the Web.config file for your application and add the following to the system.web element:

<identity impersonate="true"/>

Note
Elements in Web.config are case sensitive.

When you create a connection string to access SQL Server, you must include attributes that tell SQL Server that you are using
integrated security.
To configure connection strings for Windows integrated security
In any connection string for SQL Server, include the attribute Trusted_Connection=Yes and remove the username and
password attributes.
The following shows a typical connection string configured for Windows integrated security:

"workstation id=WebServer1;packet size=4096;


Trusted_Connection=Yes;data source=SQLServer01";
persist security info=False;initial catalog=northwind"

Set up SQL Server to recognize the users who will be accessing it.
To configure SQL Server for Windows integrated security
1. From the Windows Start menu, select Microsoft SQL Server, and then select Enterprise Manager.
2. Open the node for the server and expand the node for the database you want to give users permissions for.
3. Right-click the Users node and select New Database User.
4. In the Database User Properties dialog box, enter domain\username in the Login name box, and then click OK.
Additionally, configure the SQL Server to allow all domain users to access the database.

See Also
Concepts
ASP.NET Impersonation
Accessing SQL Server from a Web Application
Other Resources
ASP.NET Web Site Security
ASP.NET

How to: Access SQL Server Using a Mapped Windows Domain


User
By default, in Microsoft Windows 2000 and Microsoft Windows XP, ASP.NET applications run in the context of the local user
account named ASPNET and in Windows Server 2003 in the context of the local user account named NETWORK SERVICE.
These user accounts have limited access rights. However, the ASPNET account is local to the Web server. Because the ASPNET
account is local to the Web server, it is not recognized as a user on remote computers. To work around this limitation, you can
have your application run in the context of a Windows domain user who is recognized on both the Web server and the
computer that is running Microsoft SQL Server.
Mapping your application process to a Windows domain user account requires that you configure the following:
The Web server.
You must make sure that the Windows domain user account that you specify has sufficient user rights (but no more) to
run a Web application.
Your application.
You must configure the Web.config file for ASP.NET to recognize the domain user account name.
Note
For information about the Machine.config and Web.config files, see ASP.NET Configuration Overview.

A connection string.
When you create connection strings for connection objects in your application, you have to specify that the connection
strings will use Windows integrated security.
SQL Server.
You must add the specified domain user account as a SQL Server login user.
Configuring a User Account on the Web Server
To set user rights for the Windows domain user account
1. On the Web server, use Windows administrative tools to make sure that the mapped Windows domain user account has
the required user rights.
For detailed information, see ASP.NET Required Access Control Lists (ACLs).
2. Run aspnet_regiis.exe with the -ga switch to grant the common user rights that are required by the identity that you will
use for application impersonation.
Mapping to the Windows User Account and Enabling Impersonation
After establishing the correct user rights for the domain user account, configure the application identity impersonation.
To configure the Web application for impersonation
Open the Web.config file for your application, and then add the following identity impersonation code:

<identity impersonate="true" userName="domain\username" password="password"/>

Note
Elements in the Web.config file are case sensitive.

Using Windows Security in the Connection String


Finally, when you create connection strings for database access, configure the connection strings to use Windows integrated
Finally, when you create connection strings for database access, configure the connection strings to use Windows integrated
security.
To use Windows integrated security in a connection string
When you create a connection string for your application, do not include a user name and password. Instead, for the
connection string, set the Integrated Security attribute to SSPI.
The following code example shows a connection string that includes the appropriate attributes:

data source=myserver;initial catalog=northwind;Integrated Security=SSPI

To configure SQL Server for integrated security


1. In Windows, click Start, point to Microsoft SQL Server, and then click Enterprise Manager.
2. Open the node for the server, and then expand the node for the database to which you want to grant user rights.
3. Right-click Users, and then click New Database User.
4. In the Database User Properties dialog box, in the Login name box, enter domain\username, and then click OK.
See Also
Concepts
ASP.NET Impersonation
ASP.NET

How to: Access SQL Server as a Local User


By default, when an ASP.NET application runs, the application runs in the context of a special local user account named ASPNET
(in Microsoft Windows 2000 and Microsoft Windows XP) or NETWORK SERVICE (in Microsoft Windows Server 2003). This
user account has sufficient user rights on the Web server to allow the application to run.
If Microsoft SQL Server and the Web server are on the same computer, you can define the ASPNET or NETWORK SERVICE user
account as a local user account on the computer running SQL Server.
The advantage of this method is that it is secure, because the Web application runs within a limited security context. Using a
single user name with SQL Server is also efficient because it enables SQL Server to take advantage of connection pooling,
which further enhances the scalability of the application.
To grant SQL Server user rights to the ASPNET or NETWORK SERVICE user account
1. In Windows, click Start, point to Programs, point to Microsoft SQL Server, and then click Enterprise Manager.
2. Expand the node for the server, and then expand the node for the database for which you want to grant user rights.
3. Right-click Users, and then click New Database User.
4. In the Database User Properties dialog box, in the Login name box, enter computername\ASPNET or NT
AUTHORITY\NETWORK SERVICE, and then click OK.
ASP.NET

How to: Access SQL Server Using Predetermined Credentials


A reliable way to connect to SQL Server is to pass a user name and password in the connection string. You can use a
predetermined user name and password. The recommended method is to store the predetermined user name and password
on the server as part of the connectionStrings configuration section and then use protected configuration to encrypt the
connection string contents. For details, see to Overview of Protected Configuration. It is also recommended that you restrict
access to the Web.config file using NTFS file system permissions.
Security Note
Never hard-code credentials as strings into programs in your application. Anyone who can get access to the code file, even th
e compiled code, will be able to get at the credentials.

Security Note
Always give a predetermined user name the minimal access privileges to a resource. Never use "sa" or any other administrati
ve-level user name. Always use strong passwords.

To store credentials in the Web.config file


1. In the Web.config file, create a new add key in the connectionStrings element. The connectionStrings element must
appear as a child of the configuration element. For details, see Configuration Sections Schema.
The following example illustrates an add key that contains a user name and password:

<configuration>
<connectionStrings>
<add name="NorthwindConnection"
connectionString="Data Source=localhost;
Initial Catalog=Northwind;
User Id=ApplicationUserID;
Password=#P%19!ef2" />
</connectionStrings>
</configuration>

2. Encrypt the connection string value using protected configuration as shown in


Walkthrough: Encrypting Configuration Information Using Protected Configuration.
3. In your application, read the credentials from the ConnectionStrings property of the ConfigurationManager class.
The following example shows how you can read credentials at run time and concatenate them into a connection string:
VB
Dim settings As ConnectionStringSettings
settings = System.Configuration.ConfigurationManager.ConnectionStrings("NorthwindConne
ction")
Dim connectionString As String = settings.ConnectionString

C#
ConnectionStringSettings settings;
settings = System.Configuration.ConfigurationManager.ConnectionStrings["NorthwindConne
ction"];
string connectionString = settings.ConnectionString;

See Also
Concepts
Accessing SQL Server from a Web Application
Working with Secured Data Sources and Components
Other Resources
ASP.NET Configuration Settings
ASP.NET Authentication
ASP.NET

How ASP.NET Security Works


Securing Web sites is a critical, complex issue for Web developers. Protecting a site requires careful planning, and Web site
administrators and programmers must have a clear understanding of the options for securing their site.
ASP.NET works in concert with the Microsoft .NET Framework and Microsoft Internet Information Services (IIS) to help provide
Web application security. To help protect your ASP.NET application, you should perform the two fundamental functions
described in the following table.
Security func Description
tion
Authentication Helps to verify that the user is, in fact, who the user claims to be. The application obtains credentials (various fo
rms of identification, such as name and password) from a user and validates those credentials against some aut
hority. If the credentials are valid, the entity that submitted the credentials is considered an authenticated identi
ty.

Authorization Limits access rights by granting or denying specific permissions to an authenticated identity.

IIS can also grant or deny access based on a user's host name or IP address. Any further access authorization is performed by
NTFS file access permission's URL authorization.
It is helpful to understand how all the various security subsystems interact. Since ASP.NET is built on the Microsoft .NET
Framework, the ASP.NET application developer also has access to all the built-in security features of the .NET Framework, such
as code access security and role-based user-access security. For details about the security capabilities of ASP.NET, see
ASP.NET Code Access Security.
In This Section
ASP.NET Security Architecture
ASP.NET Security Data Flow
ASP.NET Authentication
ASP.NET Authorization
ASP.NET Impersonation
Related Sections
Security in the .NET Framework
Provides general information about security features of the .NET Framework.
Securing Data Access
Provides information on ways to help secure connections to data sources such as databases.
Code Access Security
Provides information on code access security in the .NET Framework.
ASP.NET Application Security in Hosted Environments
Provides information about how to configure ASP.NET and the ASP.NET environment to improve the security of your
ASP.NET application Web server.
ASP.NET

ASP.NET Security Architecture


This section provides an overview of the ASP.NET security infrastructure. The following illustration shows the relationships
among the security systems in ASP.NET.
ASP.NET architecture

As the illustration shows, all Web clients communicate with ASP.NET applications through Microsoft Internet Information
Services (IIS). IIS authenticates the request if required and then locates the requested resource (such as an ASP.NET
application). If the client is authorized, the resource is made available.
When an ASP.NET application is running, it can use built-in ASP.NET security features. In addition, an ASP.NET application can
use the security features of the .NET Framework. For more information, see Key Security Concepts.
Integrating ASP.NET Authentication with IIS
In addition to relying on the authentication capabilities of IIS, you can perform authentication in ASP.NET. When considering
ASP.NET authentication, you should understand the interaction with IIS authentication services.
IIS assumes that a set of credentials maps to a Microsoft Windows NT account and that it should use those credentials to
authenticate a user. There are three different kinds of authentication available in IIS 5.0 and IIS 6.0: basic, digest, and Windows
Integrated Security (NTLM or Kerberos). You can select the type of authentication to use in IIS administrative services. For more
information on IIS authentication, see the IIS documentation.
If users request a URL that maps to an ASP.NET application, the request and authentication information are handed off to the
application. ASP.NET provides the additional types of authentication described in the following table.
Forms authentication
A system by which unauthenticated requests are redirected to an ASP.NET Web page that you create. The user provides
credentials and submits the page. If your application authenticates the request, the system issues an authentication ticket in a
cookie that contains the credentials or a key for reacquiring the identity. Subsequent requests include an authentication ticket
with the request.
Note
ASP.NET membership and ASP.NET login controls implicitly work with forms authentication.

Passport authentication
A centralized authentication service provided by Microsoft that offers a single logon and core profile services for member
sites.
ASP.NET Configuration File Security Settings
ASP.NET security settings are configured in the Machine.config and Web.config files. As with other configuration information,
base settings and default settings are established in the Machine.config file in the Config subdirectory of the current .NET
Framework installation. You can establish site-specific and application-specific settings (including overriding settings from the
Machine.config file) in Web.config files in the Web site root and application root directories. Subdirectories inherit a directory's
settings unless overridden by a Web.config file in the subdirectory. To see an example of the way in which the hierarchical
configuration system works for security, see configSections Element (General Settings Schema).
There are three major subsections to a Web.config file: the authentication, authorization, and identity sections. The values for
each security element are usually set in the Machine.config file and overridden as required in the application-level Web.config
file. All subdirectories automatically inherit those settings. However, subdirectories can have their own configuration files that
override inherited settings.
Note
ASP.NET configuration applies only to ASP.NET resources, namely those registered to be handled in IIS by the Aspnet_isapi.dl
l extension. ASP.NET configuration cannot provide authorization for resources not processed by ASP.NET. Therefore, .txt, .htm
, .html, .gif, .jpg, .jpeg, .asp, and other types of files are accessible by all users (subject to IIS permissions). For example, even th
ough the ASP.NET resources in a directory might be restricted by a Web.config file, all users can still view the files located in t
hat directory if directory browsing is turned on and no other restrictions are in place. You can put these types of files under A
SP.NET security by explicitly mapping such file name extensions to the Aspnet_isapi.dll extension using the IIS administration
tool. However, processing these types of files through ASP.NET can affect the performance of the Web site.

You can use the location configuration element to specify a particular file or directory to which settings should apply. For more
information, see configSections Element (General Settings Schema) and Configuring Specific Files and Subdirectories. For
more details about ASP.NET configuration in general, see ASP.NET Configuration Overview.
The following example shows the syntax of the security sections of a configuration file:

<authentication mode="[Windows|Forms|Passport|None]">
<forms name="name"
loginUrl="url"
protection="[All|None|Encryption|Validation]"
path="path" timeout="minutes"
requireSSL="[true|false]"
slidingExpiration="[true|false]">
<credentials passwordFormat="[Clear|MD5|SHA1]">
<user name="username"
password="password"/>
</credentials>
</forms>
<passport redirectUrl="internal" />
</authentication>

<authorization>
<allow users="comma-separated list of users"
roles="comma-separated list of roles" />
<deny users="comma-separated list of users"
roles="comma-separated list of roles" />
</authorization>

<identity impersonate ="[true|false]"


userName="domain\username"
password="password" />

<trust level="[Full|High|Medium|Low|Minimal]"
originUrl=""/>

<securityPolicy>
<trustLevel name="Full" policyFile="internal"/>
<trustLevel name="High" policyFile="web_hightrust.config"/>
<trustLevel name="Medium" policyFile="web_mediumtrust.config"/>
<trustLevel name="Low" policyFile="web_lowtrust.config"/>
<trustLevel name="Minimal" policyFile="web_minimaltrust.config"/>
</securityPolicy>

The default settings for these elements are shown in the following table.
Default value Description
<allow roles="" /> An empty string indicating that all roles are allowed by default.

<allow users="*" /> An empty string indicating that all users are allowed access (no authentication is required).
<authentication mode="Windo The authentication type that determines the source of the current User value. The default is Wi
ws" />
ndows.

<credentials passwordFormat The hashing algorithm used on passwords. The default is SHA1.
="SHA1" />

<deny roles="" /> An empty string indicating that no roles are denied by default.

<deny users="" /> An empty string indicating that no users are denied by default.

<forms loginUrl="logon.aspx The URL to which the request is directed if you set the authentication mode to Forms and if t
" />
he request does not have a valid authentication ticket.

<forms name=".ASPXAUTH" /> The name under which the forms authentication cookie is stored on the user's computer.

<forms path="/" /> The path to which forms authentication applies. The default is all paths from the application ro
ot down.

<forms protection="All" /> The security applied to the forms authentication ticket. Values include: All, None, Encryption,
and Validation.

<forms timeout="30" /> The timeout in minutes before the forms authentication ticket expires and users must re-authe
nticate.

<forms requireSSL="false" / A Boolean value indicating whether an SSL connection is required to transmit the authenticati
>
on cookie.

<forms slidingExpiration="t A Boolean value indicating whether sliding expiration is enabled. For more information, see th
rue" />
e SlidingExpiration property.

<identity impersonate="fals A Boolean value indicating whether impersonation is disabled. For more information, see
e" />
ASP.NET Impersonation.

<identity userName="" /> An empty string indicating that no user identity is specified by default.

<identity password="" /> An empty string indicating that no password for the user identity is specified by default.

<passport redirectUrl="inte The URL to which the request is directed if you set the authentication mode to Passport and i
rnal" />
f the requested page requires authentication (anonymous users are denied access) but the use
r has not logged on with Passport.

<trust level="Full" originU The security policy that will be applied to the application.
rl="" />

<trustLevel name="Full" pol The default policy file for Full trust level.
icyFile="internal"/>

<trustLevel name="High" pol The default policy file for High trust level.
icyFile="web_hightrust.conf
ig"/>

<trustLevel name="Medium" p The default policy file for Medium trust level.
olicyFile="web_mediumtrust.
config"/>

<trustLevel name="Low" poli The default policy file for Low trust level.
cyFile="web_lowtrust.config
"/>
<trustLevel name="Minimal" The default policy file for Minimal trust level.
policyFile="web_minimaltrus
t.config"/>

See Also
Concepts
Passport Authentication Provider
ASP.NET Configuration Overview
Other Resources
ASP.NET Web Site Security
Key Security Concepts
Forms Authentication Provider
ASP.NET

ASP.NET Security Data Flow


You can design security into ASP.NET applications in a number of ways. This topic describes the security data flow for two
common scenarios: impersonation and forms authentication using cookies.
Scenario 1: Impersonation
The impersonation scenario relies on Microsoft Internet Information Services (IIS) authentication and Microsoft Windows file
access security to minimize security programming in the ASP.NET application itself. The data flow is shown in the following
illustration.
Impersonation

The illustration shows the following sequence of events:


1. A request from a network client comes to IIS.
2. IIS authenticates the client using basic, digest, or Windows integrated security (NTLM or Kerberos).
3. If the client is authenticated, IIS passes the authenticated request to ASP.NET.
4. The ASP.NET application impersonates the requesting client using the access token passed from IIS, and it relies on NTFS
file permissions for granting access to resources. The ASP.NET application needs only to verify that impersonation is set
to true in the ASP.NET configuration file; no ASP.NET security code is required.
If impersonation is not enabled, the application runs with the ASP.NET process identity. For Microsoft Windows 2000
Server and Windows XP Professional, the default identity is a local account named ASPNET that is created automatically
when ASP.NET is installed. For Microsoft Windows Server 2003, the default identity is the identity of the application pool
for the IIS application (by default, the NETWORK SERVICE account.)
Note
If impersonation is not enabled and you want to restrict access for a particular user or set of users, such as users authe
nticated using forms authentication, then you must use some other means of authorization, such as URL authorization.
For more information on URL authorization, see ASP.NET Authorization.

For more details about using impersonation in ASP.NET applications, see ASP.NET Impersonation and
Using IIS Authentication with ASP.NET Impersonation.
5. If access is granted, the ASP.NET application returns the requested resource through IIS.
Scenario 2 - Forms Authentication
In the forms authentication scenario, an application collects credentials such as name and password directly from the user and
makes its own determination about their authenticity. IIS authentication is not used by the application, but IIS authentication
settings can affect forms authentication. As a rule, when you use forms authentication, you enable anonymous access in IIS.
Otherwise, if users do not pass IIS authentication, they do not reach your application in order to provide a user name and
password to forms authentication.
The data flow in this scenario is shown in the following illustration.
Forms authentication

This illustration shows the following sequence of events:


1. A user generates a request for a protected resource.
2. IIS receives the request, and because IIS anonymous access is enabled, IIS does not perform any user authentication and
the request is passed to the ASP.NET application.
3. Because the ASP.NET authentication mode is set to forms, the ASP.NET application examines the request for a forms
authentication ticket (a specific cookie). If there is no authentication ticket attached to the request, ASP.NET redirects the
request to the logon page specified in the application's configuration file.
4. On the logon page, the user enters the required credentials, usually a name and password. The application code checks
the credentials to confirm their authenticity. If the credentials are authenticated, the application code attaches an
authentication ticket to the response that represents the user credentials. (The password is not included). If authentication
fails, the response is returned with an access denied message or the logon form is presented again.
The authentication ticket that is issued is included with subsequent requests to the ASP.NET application. ASP.NET checks
the ticket for validity using a message authentication check (MAC).
5. If the user is authenticated, ASP.NET checks authorization and can either allow access to the originally requested
resource, redirect the request to some other page, or redirect the request to a custom authorization module where the
credentials are tested for authorization to access the protected resource. If authorization fails, ASP.NET redirects the user
to the logon page.
If the user is authorized, access is granted to the protected resource; or the application might require an additional test of
the credentials before authorizing access to the protected resource, depending on the design of the application.
Note
Forms authentication and authorization checking apply only to resources protected by the authentication and
authorization configuration elements. Access to Windows resources protected using Access Control Lists (ACLs) is chec
ked against the current Windows identity of the ASP.NET application. For more information, see
ASP.NET Impersonation.

See Also
Tasks
How to: Implement Simple Forms Authentication
Concepts
ASP.NET Impersonation
Using IIS Authentication with ASP.NET Impersonation
Other Resources
Managing Users by Using Membership
Managing Authorization Using Roles
ASP.NET Web Application Security
Forms Authentication Provider
Visual Web Developer

ASP.NET Authentication (Visual Web Developer)


Authentication is the process of obtaining identification credentials such as name and password from a user and validating
those credentials against some authority. If the credentials are valid, the entity that submitted the credentials is considered an
authenticated identity. Once an identity has been authenticated, the authorization process determines whether that identity has
access to a given resource.
ASP.NET implements authentication through authentication providers, the code modules that contain the code necessary to
check the requestor's credentials. The topics in this section describe the authentication providers built into ASP.NET.
In This Section
Windows Authentication Provider
Forms Authentication Provider
Related Sections
ASP.NET Web Application Security
Provides links to additional topics that describe how to secure ASP.NET Web applications.
ASP.NET Configuration Overview
Provides links to topics on how to use configuration files and the configuration API to manage the run-time behavior of
ASP.NET.
ASP.NET

Windows Authentication Provider


Windows Authentication treats the user identity supplied by Microsoft Internet Information Services (IIS) as the authenticated
user in an ASP.NET application. IIS provides a number of authentication mechanisms to verify user identity, including
anonymous authentication, Windows integrated (NTLM) authentication, Windows integrated (Kerberos) authentication, Basic
(base64 encoded) authentication, Digest authentication, and authentication based on client certificates.
Windows Authentication is implemented in ASP.NET using the WindowsAuthenticationModule module. The module constructs
a WindowsIdentity based on the credentials supplied by IIS and sets the identity as the current User property value for the
application.
Windows Authentication is the default authentication mechanism for ASP.NET applications and is identified as the
authentication mode for an application using the authentication configuration element, as shown in the following code
example.

<system.web>
<authentication mode="Windows"/>
</system.web>

Impersonating the Windows Identity


Although the Windows Authentication mode sets the value of the current User property to a WindowsIdentity based on the
credentials supplied by IIS, it does not modify the Windows identity that is supplied to the operating system. The Windows
identity supplied to the operating system is used for permission checking, such as NTFS file permissions, or for connecting to a
database using integrated security. By default, this Windows identity is the identity of the ASP.NET process. On Microsoft
Windows 2000 and Windows XP Professional, this is the identity of the ASP.NET worker process, which is the local ASPNET
account. On Windows Server 2003, this is the identity of the IIS Application Pool that the ASP.NET application is part of. By
default, this is the NETWORK SERVICE account.
You can configure the Windows identity of your ASP.NET application as the Windows identity supplied by IIS by enabling
impersonation. That is, you instruct your ASP.NET application to impersonate the identity supplied by IIS for all tasks that the
Windows operating system authenticates, including file and network access.
To enable impersonation for your Web application, in the application's Web.config file set the impersonate attribute of the
identity element to true, as shown in the following code example.

<system.web>
<authentication mode="Windows"/>
<identity impersonate="true"/>
</system.web>

For more information on the ASP.NET process identity, see Configuring ASP.NET Process Identity. For more information on
impersonation, see the Impersonate method.
Enabling Authorization using NTFS ACLs
You can improve the security of your ASP.NET application by securing the application's files using the NTFS file system and
Access Control Lists (ACLs). ACLs enable you to specify which users and groups of users have access to your application's files.
For a list of the minimum required NTFS file permissions that a Windows identity needs to run as the identity of an ASP.NET
page, see ASP.NET Required Access Control Lists (ACLs).
Note
You can also use ASP.NET roles to manage user authorization for pages and sections of your Web application. For more infor
mation, see Managing Authorization Using Roles.

See Also
Tasks
How to: Create a WindowsPrincipal Object
How to: Create GenericPrincipal and GenericIdentity Objects
Other Resources
ASP.NET Web Application Security
ASP.NET Authentication
ASP.NET

Using IIS Authentication with ASP.NET Impersonation


Internet Information Services (IIS) provides several authentication schemes that can be employed when securing a Web
application. Common scenarios include using Integrated Windows authentication (NTLM) within a corporate intranet to
determine application users' identity based on their Windows login, or specifying a single anonymous identity for a particular
application. The Windows identity supplied by IIS can then be used to determine whether the Web application has access to a
protected Windows resource, such as a file protected using an Access Control List (ACL), or a network resource such as a file or
database server. You can configure ASP.NET to use the Windows identity supplied by IIS using impersonation.
By default, ASP.NET is configured to use Windows authentication mode, which applies the Windows identity supplied by IIS to
the User property of the current HttpContext object. This enables you to determine the identity supplied by IIS through the
User property (the user Name is blank when anonymous identification is used), but does not use the supplied identity as the
WindowsIdentity for the current page. The WindowsIdentity for an application is used when determining if the application
has access to a particular file or network resource.
To configure ASP.NET to impersonate the Windows identity supplied by IIS as the WindowsIdentity for the ASP.NET
application, edit the Web.config file for the application and set the impersonate attribute of the identity configuration
element to true, as shown in the following example.

<configuration>
<system.web>
<identity impersonate="true" />
</system.web>
</configuration>

Impersonation is independent of the authentication mode configured using the authentication configuration element. The
authentication element is used to determine the User property of the current HttpContext. Impersonation is used to
determine the WindowsIdentity of the ASP.NET application.
The following describes how you would enable impersonation using an intranet scenario as an example. In this scenario, you
are setting up an internal corporate Web site for posting employee information. However, some of the information is for
managers only. The manager information can be posted to a subdirectory of the employee information site, so that access to
the information can be limited. IIS determines the user's identity using Windows Integrated (NTLM) security. The scenario
assumes that:
The Web server has the Microsoft Windows NT Server, Windows 2000 Server, or Windows Server 2003 operating
system installed.
IIS 6.0 is installed the Web server.
The Web server hard disk is formatted using NTFS.
All employees that need access to restricted resources are using Windows.
As the administrator of the application in the scenario, you would need to do the following:
1. Create the files and directories shown in the following illustration:

2. Create a Windows group named Managers that contains all users who should have access to the ManagerInfo.aspx file.
3. Use Internet Information Services (IIS) Manager to disable anonymous authentication for the application and enable
integrated windows authentication.
4. In the application's Web.config file, set the impersonate attribute in the identity element to true.
5. Set the NTFS access control list (ACL) for the ManagerInformation directory to allow access to only those identities that
are in the Windows Manager group and any required system accounts. You would need to be sure to include the identity
of the ASP.NET process. The identity of the ASP.NET process for Windows 2000 Server or Windows NT is the local
ASPNET account. The identity of the ASP.NET process for Windows Server 2003 and later is the identity of the IIS
application pool, which by default is the NETWORK SERVICE account.
Note
The ASP.NET role-management feature provides an alternative method of restricting access to areas of your Web appli
cation. For more information, see Managing Authorization Using Roles.

See Also
Concepts
Basic Security Practices for Web Applications
Other Resources
ASP.NET Web Application Security
ASP.NET

Forms Authentication Provider


Forms authentication enables you to authenticate the user name and password of your users using a login form that you
create. Unauthenticated requests are redirected to a login page, where the user provides credentials and submits the form. If
the application authenticates the request, the system issues a ticket that contains a key for reestablishing the identity for
subsequent requests.
The topics in this section describe how to use forms authentication to create a custom login system.
Note
A convenient way to use forms authentication is to use ASP.NET membership (which stores user credentials) and the ASP.NE
T login controls (which you can use to create a login page).

In This Section
ASP.NET Forms Authentication Overview
How to: Implement Simple Forms Authentication
Forms Authentication Control Flow
Forms Authentication Credentials
Forms Authentication Utilities
Handling FormsAuthentication Events
Forms Authentication Across Applications
Related Sections
ASP.NET Web Site Security
Provides links to all topics on security in ASP.NET security.
Managing Users by Using Membership
Provides information about managing user names and passwords with built-in ASP.NET classes.
ASP.NET Login Controls Overview.
Provides information about controls you can use to create pages for logging in, managing passwords, and creating new
users.
ASP.NET

ASP.NET Forms Authentication Overview


Forms authentication provides you with a way to authenticate users using your own code and then maintain an authentication
token in a cookie or in the page URL. Forms authentication participates in the ASP.NET page life cycle through the
FormsAuthenticationModule. You can access forms authentication information and capabilities through the
FormsAuthentication class.
To use forms authentication, you create a logon page that collects credentials from the user and that includes code to
authenticate the credentials. If the credentials are valid, you can call methods of the FormsAuthentication class to redirect the
request to the originally requested resource with an appropriate authentication ticket (cookie). If you do not want the
redirection, you can simply get the forms authentication cookie or set it.
You configure forms authentication using the authentication configuration element. In the simplest case, you can specify a URL
to redirect unauthenticated requests to a logon page, supply a minimal implementation of a logon page, and supply valid
credentials, either in the Web.config file or in a separate file. The following example shows a section from a configuration file
that specifies a logon page and authentication credentials for the Authenticate method. The passwords have been encrypted
using the HashPasswordForStoringInConfigFile method.

<authentication mode="Forms">
<forms name="SavingsPlan" loginUrl="/Logon.aspx">
<credentials passwordFormat="SHA1">
<user name="Kim"
password="07B7F3EE06F278DB966BE960E7CBBD103DF30CA6"/>
<user name="John"
password="BA56E5E0366D003E98EA1C7F04ABF8FCB3753889"/>
</credentials>
</forms>
</authentication>

After successful authentication, the FormsAuthenticationModule module populates the current User property with the
information for the authenticated user. The following code example shows how to programmatically read the identity of the
forms-authenticated user.
VB
Dim authUser2 As String = User.Identity.Name

C#
String authUser2 = User.Identity.Name;

Forms Authentication, ASP.NET Membership, and Login Controls


A convenient way to work with forms authentication is to use ASP.NET membership and ASP.NET login controls. ASP.NET
membership provides a way to store and manage user information and includes methods to authenticate users. ASP.NET login
controls work with ASP.NET membership and encapsulate the logic required to prompt users for credentials, validate users,
recover or replace passwords, and so on. In effect, ASP.NET membership and ASP.NET login controls provide a layer of
abstraction over forms authentication and replace most or all of the work you would normally have to do to use forms
authentication. For more information, see Managing Users by Using Membership and the ASP.NET Login Controls Overview.
See Also
Concepts
ASP.NET Configuration Overview
Other Resources
ASP.NET Web Application Security
Forms Authentication Provider
ASP.NET

How to: Implement Simple Forms Authentication


This example in this topic presents a simple implementation of ASP.NET forms authentication. It is intended to illustrate the
fundamentals of how to use forms authentication to log users into an ASP.NET application.
Note
A convenient way to work with forms authentication is to use ASP.NET membership and ASP.NET login controls. ASP.NET me
mbership provides a way to store and manage user information and includes methods to authenticate users. ASP.NET login c
ontrols work with ASP.NET membership and encapsulate the logic required to prompt users for credentials, validate users, re
cover or replace passwords, and so on. In effect, ASP.NET membership and ASP.NET login controls provide a layer of abstract
ion over forms authentication and replace most or all of the work you would normally have to do to use forms authenticatio
n. For more information, see Managing Users by Using Membership and ASP.NET Login Controls Overview.

In the scenario for the example, users request a protected resource, namely a page named Default.aspx. Only one user has
access to the protected resource: jchen@contoso.com, with a password of "37Yj*99P". The user name and password are hard-
coded into the Logon.aspx file. The example requires three files: the Web.config file, a page named Logon.aspx, and a page
named Default.aspx. The files reside in the application root directory.
To configure the application for forms authentication
1. If the application has a Web.config file in the application root, open it.
2. If the application does not already have a Web.config file in the application root folder, create a text file named
Web.config and add the following elements to it:

<?xml version="1.0"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<system.web>

</system.web>
</configuration>

3. Within the system.web element, create an authentication element and set its mode attribute to Forms, as shown in the
following example:

<system.web>
<authentication mode="Forms">
</authentication>
</system.web>

4. Within the authentication element, create a forms element and set the following attributes:
loginUrl Set to "Logon.aspx." Logon.aspx is the URL to use for redirection if ASP.NET does not find an
authentication cookie with the request.
name Set to ".ASPXFORMSAUTH". This sets the suffix for the name of the cookie that contains the authentication
ticket.

<system.web>
<authentication mode="Forms">
<forms loginUrl="Logon.aspx" name=".ASPXFORMSAUTH">
</forms>
</authentication>
</system.web>

5. Within the system.web element, create an authorization element.


<system.web>
<authentication mode="Forms">
<forms loginUrl="Logon.aspx" name=".ASPXFORMSAUTH">
</forms>
</authentication>
<authorization>
</authorization>
</system.web>

6. Within the authorization element, create a deny element and set its users attribute to "?". This specifies that
unauthenticated users (represented by "?") are denied access to resources in this application.

<system.web>
<authentication mode="Forms">
<forms loginUrl="logon.aspx" name=".ASPXFORMSAUTH">
</forms>
</authentication>
<authorization>
<deny users="?" />
</authorization>
</system.web>

7. Save the Web.config file and close it.

Creating the Logon Page


When users request any page from the Web site and if they have not previously been authenticated, they are redirected to a
page named Logon.aspx. You specified this file name earlier in the Web.config file.
The Logon.aspx page collects user credentials (e-mail address and password) and authenticates them. If the user is successfully
authenticated, the logon page redirects the user to the page they originally requested. In the example, the valid credentials are
hard-coded into the page code.
Security Note
This example contains a text box that accepts user input, which is a potential security threat. By default, ASP.NET Web pages v
alidate that user input does not include script or HTML elements. For more information, see Script Exploits Overview.

To create the logon page


1. Create an ASP.NET page named Logon.aspx in the application root folder.
2. Copy the following markup and code into it:
VB
<%@ Page Language="VB" %>
<%@ Import Namespace="System.Web.Security" %>

<script runat="server">
Sub Logon_Click(ByVal sender As Object, ByVal e As EventArgs)
If ((UserEmail.Text = "jchen@contoso.com") And _
(UserPass.Text = "37Yj*99Ps")) Then
FormsAuthentication.RedirectFromLoginPage _
(UserEmail.Text, Persist.Checked)
Else
Msg.Text = "Invalid credentials. Please try again."
End If
End Sub
</script>
<html>
<head id="Head1" runat="server">
<title>Forms Authentication - Login</title>
</head>
<body>
<form id="form1" runat="server">
<h3>
Logon Page</h3>
<table>
<tr>
<td>
E-mail address:</td>
<td>
<asp:TextBox ID="UserEmail" runat="server" /></td>
<td>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1"
ControlToValidate="UserEmail"
Display="Dynamic"
ErrorMessage="Cannot be empty."
runat="server" />
</td>
</tr>
<tr>
<td>
Password:</td>
<td>
<asp:TextBox ID="UserPass" TextMode="Password"
runat="server" />
</td>
<td>
<asp:RequiredFieldValidator ID="RequiredFieldValidator2"
ControlToValidate="UserPass"
ErrorMessage="Cannot be empty."
runat="server" />
</td>
</tr>
<tr>
<td>
Remember me?</td>
<td>
<asp:CheckBox ID="Persist" runat="server" /></td>
</tr>
</table>
<asp:Button ID="Submit1" OnClick="Logon_Click" Text="Log On"
runat="server" />
<p>
<asp:Label ID="Msg" ForeColor="red" runat="server" />
</p>
</form>
</body>
</html>

C#
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Web.Security" %>

<script runat="server">
void Logon_Click(object sender, EventArgs e)
{
if ((UserEmail.Text == "jchen@contoso.com") &&
(UserPass.Text == "37Yj*99Ps"))
{
FormsAuthentication.RedirectFromLoginPage
(UserEmail.Text, Persist.Checked);
}
else
{
Msg.Text = "Invalid credentials. Please try again.";
}
}
</script>
<html>
<head id="Head1" runat="server">
<title>Forms Authentication - Login</title>
</head>
<body>
<form id="form1" runat="server">
<h3>
Logon Page</h3>
<table>
<tr>
<td>
E-mail address:</td>
<td>
<asp:TextBox ID="UserEmail" runat="server" /></td>
<td>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1"
ControlToValidate="UserEmail"
Display="Dynamic"
ErrorMessage="Cannot be empty."
runat="server" />
</td>
</tr>
<tr>
<td>
Password:</td>
<td>
<asp:TextBox ID="UserPass" TextMode="Password"
runat="server" />
</td>
<td>
<asp:RequiredFieldValidator ID="RequiredFieldValidator2"
ControlToValidate="UserPass"
ErrorMessage="Cannot be empty."
runat="server" />
</td>
</tr>
<tr>
<td>
Remember me?</td>
<td>
<asp:CheckBox ID="Persist" runat="server" /></td>
</tr>
</table>
<asp:Button ID="Submit1" OnClick="Logon_Click" Text="Log On"
runat="server" />
<p>
<asp:Label ID="Msg" ForeColor="red" runat="server" />
</p>
</form>
</body>
</html>

The page contains ASP.NET server controls that collect user information and a check box that users can click to make
their login credentials persistent. The Log On button's Click handler contains code that checks the user's e-mail address
and password against hard-coded values. (The password is a strong password that contains various non-alphabetic
characters and is at least eight characters long.) If the user's credentials are correct, the code calls the
FormsAuthentication class's RedirectFromLoginPage method, passing the user's name and a Boolean value (derived
from the check box) indicating whether to persist an authentication ticket as a cookie. The method redirects the user to
the page originally requested. If the user's credentials do not match, an error message is displayed. Note that the page
imports the System.Web.Security namespace, which contains the FormsAuthentication class.

Creating the Default Page


For the example, you will create an ASP.NET page in the application root folder. Because you specified in the configuration file
that all unauthenticated users are denied access to the application's ASP.NET resources (which includes .aspx files; but does not
include static files such as HTML files or multi-media files including images, music, and so on), when a user requests the page,
forms authentication will check the user's credentials and redirect the user to the logon page if necessary. The page you create
will also allow users to log out, which clears their persisted authentication ticket (cookie).
To create a default page
1. Create an ASP.NET page named Default.aspx in the application root folder.
2. Copy the following markup and code into it:
VB
<%@ Page Language="VB" %>
<html>
<head>
<title>Forms Authentication - Default Page</title>
</head>

<script runat="server">
Sub Page_Load(ByVal Src As Object, ByVal e As EventArgs)
Welcome.Text = "Hello, " & Context.User.Identity.Name
End Sub

Sub Signout_Click(ByVal sender As Object, ByVal e As EventArgs)


FormsAuthentication.SignOut()
Response.Redirect("Logon.aspx")
End Sub
</script>

<body>
<h3>
Using Forms Authentication</h3>
<asp:Label ID="Welcome" runat="server" />
<form id="Form1" runat="server">
<asp:Button ID="Submit1" OnClick="Signout_Click"
Text="Sign Out" runat="server" /><p>
</form>
</body>
</html>

C#
<%@ Page Language="C#" %>
<html>
<head>
<title>Forms Authentication - Default Page</title>
</head>

<script runat="server">
void Page_Load(object sender, EventArgs e)
{
Welcome.Text = "Hello, " + Context.User.Identity.Name;
}

void Signout_Click(object sender, EventArgs e)


{
FormsAuthentication.SignOut();
Response.Redirect("Logon.aspx");
}
</script>

<body>
<h3>
Using Forms Authentication</h3>
<asp:Label ID="Welcome" runat="server" />
<form id="Form1" runat="server">
<asp:Button ID="Submit1" OnClick="Signout_Click"
Text="Sign Out" runat="server" /><p>
</form>
</body>
</html>

The page displays the user's authenticated identity, which was set by the FormsAuthentication class and is available in
an ASP.NET page as the Context.User.Identity.Name property. The Sign Out button's Click handler contains code that
calls the SignOut method to clear the user identity and remove the authentication ticket (cookie). It then redirects the
user to the logon page.

See Also
Reference
ASP.NET Login Controls Overview
Concepts
Basic Security Practices for Web Applications
Other Resources
ASP.NET Web Application Security
Managing Users by Using Membership
ASP.NET

Forms Authentication Control Flow


The flow of control for ASP.NET forms authentication is shown in the following table.
Browser and HTTP op Server reply
eration
Requests a protected re If there is no authentication cookie, redirects the request to a logon page to collect credentials. Inform
source from a server. Th ation about the originating page is placed in the query string using RETURNURL as the key. The server
e HTTP operation is: HTTP reply is:

GET /default 302 Found


.aspx Location: http://samples.microsoft.com/logon.aspx?RETURNURL=/default.as
px

Follows the redirection t Returns the logon page. For security, we recommend that you use Secure Sockets Layer (SSL) for the
o the logon page. The H logon page to keep the user's credentials from being sent in clear text. The server HTTP reply is:
TTP operation is:
200 OK
GET /logon.a
spx?RETURNUR
L=/default.a
spx

After user enters creden Validates user credentials and, if the credentials are authenticated, redirects the browser to the origin
tials into the logon page al URL specified in the QueryString as the RETURNURL variable. By default, the authentication ticket is is
, submits the page. The sued as a cookie.
HTTP operation is:
Note
You can specify that the authentication ticket be included in the URL instead of a cookie using the
POST /logon. CookieMode property.
aspx?RETURNU
RL=/default.
aspx The server HTTP reply is:

302 Found
Location: /default.aspx

Follows the redirection If the user is authenticated, grants access and grants the authentication cookie, which contains an aut
and requests the origina hentication ticket. Future requests by the same browser session will be authenticated when the modul
l resource again. The HT e inspects the cookie. It is possible to create a persistent cookie that can be used for future sessions, b
TP operation is: ut only until the cookie's expiration date. The server HTTP reply is:

GET /default 200 OK


.aspx Set-Cookie: ASPXTICKET=ABCDEFG12345;Path=/

Note that the cookie path is set to /. Because cookie names are case-sensitive, this prevents inconsiste
nt case in URLs on the site. For example, if the path were set to /SavingsPlan and a link contained /sav
ingsplan, the user would be forced to re-authenticate because the browser would not send the cookie.

See Also
Other Resources
ASP.NET Web Application Security
Forms Authentication Provider
ASP.NET

Forms Authentication Credentials


Forms authentication credentials that are used to validate users at logon can be stored in an external data source or in the
application configuration file.
Note
ASP.NET membership is the preferred method for storing and managing user credentials in forms-authenticated applications
. For more information, see Managing Users by Using Membership.

Storing Users in the Application Configuration File


When using forms authentication, you can validate users from user/password pairs in the credentials section of the Web site's
configuration file. You can use the Authenticate method to compare the credentials collected from the user to the list of
user/password pairs in the credentials section to determine whether access should be granted. In the following example, users
Kim and John can log on if they provide the correct password.

<credentials passwordFormat="SHA1" >


<user name="Kim"
password="07B7F3EE06F278DB966BE960E7CBBD103DF30CA6"/>
<user name="John"
password="BA56E5E0366D003E98EA1C7F04ABF8FCB3753889"/>
</credentials>

The credential pairs in the example are encrypted using the Secure Hash Algorithm-1 (SHA1) password-hashing format. The
PasswordFormat attribute is required. Values for this property are listed in the following table.
Valu Description
e
Clear Passwords are stored in clear text. The user password is compared directly to this value without further transformation.

MD5 Passwords are stored using a Message Digest 5 (MD5) hash digest. To validate credentials, the user password is hashed
using the MD5 algorithm and compared to the stored value. The clear-text password is never stored or compared when
using this value. This algorithm produces better performance than SHA1.

SHA1 Passwords are stored using the SHA1 hash digest. To validate credentials, the user password is hashed using the SHA1 a
lgorithm and compared to the stored value. The clear-text password is never stored. Use this algorithm for improved sec
urity over the MD5 algorithm.

The .NET Framework includes classes and methods that make it easy for you to create hashed values programmatically for
persistent storage. One class that can be helpful for programming this task is the FormsAuthentication class. Its
HashPasswordForStoringInConfigFile method can do the hashing. For more precise control, you can use the
System.Security.Cryptography classes as well.
Hashed passwords stored in a text file cannot be used to regenerate the original password, but they are potentially vulnerable
to a dictionary attack. In this type of attack, the attacker, after gaining access to the password file, attempts to guess passwords
by using software to iteratively hash all words in a large dictionary and compare the generated hashes to the stored hash. If
you store hashed passwords in any way, you should require your users to choose passwords that are not common words and
that contain some numbers and non-alphanumeric characters to help prevent dictionary attacks. Additionally, you can make
credentials management easier by storing them using ASP.NET membership. For more information, see
Managing Users by Using Membership.
See Also
Reference
FormsAuthenticationModule
Other Resources
ASP.NET Web Application Security
Forms Authentication Provider
ASP.NET

Forms Authentication Utilities


To manage forms authentication, you can use static methods of the FormsAuthentication class. The following table lists the
methods.
Method Description
Authenticate Attempts to validate the credentials from the configured credential store, given the supp
lied credentials.

Decrypt Returns an instance of the FormsAuthenticationTicket class, given an encrypted authenti


cation ticket obtained from an HTTP cookie.

Encrypt Given a FormsAuthenticationTicket, produces a string containing an encrypted authe


ntication ticket suitable for use in an HTTP cookie.

GetAuthCookie Retrieves an encrypted authentication cookie as an HttpCookie instance. The cookie is n


ot added to the Cookies collection.

GetRedirectUrl Returns the redirection URL for the request that caused the redirect to the logon page.

HashPasswordForStoringInConfigFile Given a password and a string identifying the hash type, produces a hash password suit
able for storing in a configuration file.

Initialize Initializes the FormsAuthentication class by reading configuration settings and getting
the cookie values and encryption values for the current application.

RedirectFromLoginPage Redirects an authenticated user to the originally requested URL.

RenewTicketIfOld Updates the sliding expiration on a FormsAuthenticationTicket.

SetAuthCookie Creates an authentication ticket and attaches it to the cookie collection of the outgoing r
esponse.

SignOut Removes the authentication ticket by setting the authentication cookie or URL text to an
empty value. This removes both durable and session cookies.
Important
Although the SignOut method clears the ticket from the authenticated browser session
, your application can still be susceptible to a replay attack from an unwanted source th
at has "sniffed" an authentication ticket. For information on mitigating against a replay
attack with forms authentication, see SignOut.

The following table lists helpful properties for managing forms authentication tickets.
Property Description
FormsCookieName Gets the cookie name for the current application.

FormsCookiePath Gets the cookie path for the current application.

CookiesSupported Gets a value that indicates whether the application is configured to support cookieless forms authen
tication.

CookieMode Gets a value that indicates whether the application is configured for cookieless forms authentication.
CookieDomain Gets the value of the domain of the forms authentication cookie.

DefaultUrl Gets the URL that forms authentication will redirect to if no redirect URL is specified.

LoginUrl Gets the URL for the logon page that forms authentication will redirect to.

RequireSSL Gets a value indicating whether cookies must be transmitted using Secure Sockets Layer (SSL).

SlidingExpiration Gets a value indicating whether sliding expiration is enabled.

EnableCrossAppRedirects Gets a value indicating whether authenticated users can be redirected to URLs in other Web applicat
ions when the forms authentication ticket is not stored in a cookie.

You can use the methods of the FormsAuthentication class to customize the way forms authentication works. You can also
use them in the logon page handler to avoid having to explicitly code the redirection. The following code example shows an
ASP.NET Web page that authenticates the user and redirects to the requested page.
VB
<html>
<head>
<script language="VB" runat=server>
Sub SubmitBtn_Click(Source As Object, e As EventArgs)
' Try to authenticate credentials supplied by user.
If FormsAuthentication.Authenticate _
(UserName.Value, UserPassword.Value) Then
Dim ticket As New FormsAuthenticationTicket _
(UserName.Value, False, 5000)
FormsAuthentication.RedirectFromLoginPage _
(UserName.Value, Persist.Checked)
End If
End Sub
</script>
</head>
<body>
<form method=post runat=server>
<table>
<tr>
<td>Name:</td>
<td><input type="text" id="UserName" runat=server/>
</tr>
<tr>
<td>Password:</td>
<td><input type="password" id="UserPassword" runat=server/>
</td>
</tr>
</table>
<input type="checkbox" id="Persist" runat=server/>
<!-- Use persistent cookie -->
<br>
<input type="submit" OnServerClick="SubmitBtn_Click" runat=server/>
</form>
</body>
</html>

C#
<html>
<head>
<script language="C#" runat=server>
void SubmitBtn_Click(Object Source, EventArgs e)
{
// Try to authenticate credentials supplied by user.
if (FormsAuthentication.Authenticate(UserName.Value,
UserPassword.Value))
{
FormsAuthenticationTicket ticket = new
FormsAuthenticationTicket(UserName.Value, false, 5000);

FormsAuthentication.RedirectFromLoginPage(UserName.Value,
Persist.Checked);
}
}
</script>
</head>

<body>

<form method=post runat=server>


<table>
<tr>
<td>Name:</td>
<td><input type="text" id="UserName" runat=server/></td>
</tr>
<tr>
<td>Password:</td>
<td><input type="password" id="UserPassword" runat=server/>
</td>
</tr>
</table>
<input type="checkbox" id="Persist" runat=server/>
<!-- Use persistent cookie. -->
<br>
<input type="submit" OnServerClick="SubmitBtn_Click" runat=server/>
</form>
</body>
</html>

Applications that need detailed control over the HTTP cookie properties can construct the ticket and perform the redirection in
custom code. In those cases, you should use encryption methods of the FormsAuthentication class to encrypt the
authentication ticket.
See Also
Reference
FormsAuthentication
FormsAuthenticationTicket
HttpCookie
Other Resources
ASP.NET Web Application Security
Forms Authentication Provider
ASP.NET

Handling FormsAuthentication Events


To customize how the forms authentication ticket is handled and how the User property is set, you can handle the
FormsAuthentication_OnAuthenticate event in your application's Global.asax file. Although it is common to allow forms
authentication manage these tasks for you, your applications might have specific requirements, such as setting the User
property to a custom class that implements the IPrincipal interface. In those cases, your application should handle the
FormsAuthentication_OnAuthenticate event and perform cookie management. For more information, see
FormsAuthenticationEventHandler.
See Also
Other Resources
ASP.NET Web Application Security
Forms Authentication Provider
ASP.NET

Forms Authentication Across Applications


ASP.NET supports forms authentication in a distributed environment, either across applications on a single server or in a Web
farm. When forms authentication is enabled across multiple ASP.NET applications, users are not required to re-authenticate
when switching between the applications.
Configuring Forms Authentication Across Applications
To configure forms authentication across applications, you set several attributes in the forms and machineKey configuration
sections so that the values are the same for all applications participating in shared forms authentication.
The following example shows the Authentication section of a Web.config file. Unless otherwise noted, the name, protection,
path, validationKey, validation, decryptionKey, and decryption attributes must be identical across all applications.
Similarly, the encryption and validation keys and the encryption scheme and validation scheme used for cookie data must be
exactly the same. If the settings do not match, cookies cannot be shared.
Note
Applications running ASP.NET version 2.0 can share forms authentication ticket information with earlier versions of ASP.NET
provided you include decryption="3DES" in your machineKey element configuration for each ASP.NET version 2.0 applicatio
n.

<configuration>
<system.web>
<authentication mode="Forms" >
<!-- The name, protection, and path attributes must match
exactly in each Web.config file. -->
<forms loginUrl="login.aspx"
name=".ASPXFORMSAUTH"
protection="All"
path="/"
timeout="30" />
</authentication>

<!-- Validation and decryption keys must exactly match and cannot
be set to "AutoGenerate". The validation and decryption
algorithms must also be the same. -->
<machineKey
validationKey="[your key here]"
decryptionKey="[your key here]"
validation="SHA1" />
</system.web>
</configuration>

After a cookie has been issued, expiration of the cookie is tracked based on the Expires value in the cookie itself. This means
that if two applications have different Timeout attributes, the expiration date and time that was set when each cookie was
originally issued are retained throughout the lifetime of the cookie. When a cookie is updated, the cookie's original expiration
is used to compute the new expiration. The only time the configuration Timeout value is used is when the cookie is initially
created.
See Also
Tasks
How to: Implement Simple Forms Authentication
Other Resources
ASP.NET Web Application Security
ASP.NET

ASP.NET Authorization
Authorization determines whether an identity should be granted access to a specific resource. In ASP.NET, there are two ways
to authorize access to a given resource:
File authorization File authorization is performed by the FileAuthorizationModule. It checks the access control list
(ACL) of the .aspx or .asmx handler file to determine whether a user should have access to the file. ACL permissions are
verified for the user's Windows identity (if Windows authentication is enabled) or for the Windows identity of the
ASP.NET process. For more information, see ASP.NET Impersonation.
URL authorization URL authorization is performed by the UrlAuthorizationModule, which maps users and roles to
URLs in ASP.NET applications. This module can be used to selectively allow or deny access to arbitrary parts of an
application (typically directories) for specific users or roles.
Using URL Authorization
With URL authorization, you explicitly allow or deny access to a particular directory by user name or role. To do so, you create
an authorization section in the configuration file for that directory. To enable URL authorization, you specify a list of users or
roles in the allow or deny elements of the authorization section of a configuration file. The permissions established for a
directory also apply to its subdirectories, unless configuration files in a subdirectory override them.
The following shows the syntax for the authorization section:

<authorization>
<[allow|deny] users roles verbs />
</authorization>

The allow or deny element is required. You must specify either the users or the roles attribute. Both can be included, but both
are not required. The verbs attribute is optional.
The allow and deny elements grant and revoke access, respectively. Each element supports the attributes shown in the
following table:
Attrib Description
ute
users Identifies the targeted identities (user accounts) for this element.
Anonymous users are identified using a question mark (?). You can specify all authenticated users using an asterisk (*).

roles Identifies a role (a RolePrincipal object) for the current request that is allowed or denied access to the resource. For mor
e information, see Managing Authorization Using Roles.

verbs Defines the HTTP verbs to which the action applies, such as GET, HEAD, and POST. The default is "*", which specifies all
verbs.

The following example grants access to the Kim identity and members of the Admins role, and denies access to the John identity
(unless the John identity is included in the Admins role) and to all anonymous users:

<authorization>
<allow users="Kim"/>
<allow roles="Admins"/>
<deny users="John"/>
<deny users="?"/>
</authorization>

The following authorization section shows how to allow access to the John identity and deny access to all other users:

<authorization>
<allow users="John"/>
<deny users="*"/>
</authorization>

You can specify multiple entities for both the users and roles attributes by using a comma-separated list, as shown in the
following example:

<allow users="John, Kim, contoso\Jane"/>

Note that if you specify a domain account name, the name must include both the domain and user name (contoso\Jane).
The following example allows all users to perform an HTTP GET for a resource, but allows only the Kim identity to perform a
POST operation:

<authorization>
<allow verbs="GET" users="*"/>
<allow verbs="POST" users="Kim"/>
<deny verbs="POST" users="*"/>
</authorization>

Rules are applied as follows:


Rules contained in application-level configuration files take precedence over inherited rules. The system determines
which rule takes precedence by constructing a merged list of all rules for a URL, with the most recent rules (those nearest
in the hierarchy) at the head of the list.
Given a set of merged rules for an application, ASP.NET starts at the head of the list and checks rules until the first match
is found. The default configuration for ASP.NET contains an <allow users="*"> element, which authorizes all users. (By
default, this rule is applied last.) If no other authorization rules match, the request is allowed. If a match is found and the
match is a deny element, the request is returned with the 401 HTTP status code. If an allow element matches, the
module allows the request to be processed further.
In a configuration file, you can also create a location element to specify a particular file or directory to which settings in that the
location element should apply.
See Also
Reference
FileAuthorizationModule
UrlAuthorizationModule
IPrincipal
Concepts
Configuring Specific Files and Subdirectories
ASP.NET Impersonation
Other Resources
ASP.NET Web Application Security
ASP.NET

ASP.NET Impersonation
When using impersonation, ASP.NET applications can execute with the Windows identity (user account) of the user making the
request. Impersonation is commonly used in applications that rely on Microsoft Internet Information Services (IIS) to
authenticate the user.
ASP.NET impersonation is disabled by default. If impersonation is enabled for an ASP.NET application, that application runs in
the context of the identity whose access token IIS passes to ASP.NET. That token can be either an authenticated user token, such
as a token for a logged-in Windows user, or the token that IIS provides for anonymous users (typically, the
IUSR_MACHINENAME identity).
When impersonation is enabled, only your application code runs under the context of the impersonated user. Applications are
compiled and configuration information is loaded using the identity of the ASP.NET process. For more information, see
Configuring ASP.NET Process Identity. The compiled application is put in the Temporary ASP.NET files directory. The
application identity that is being impersonated needs to have read/write access to this directory. The impersonated application
identity also requires at least read access to the files in your application directory and subdirectories. For more information, see
ASP.NET Required Access Control Lists (ACLs).
Note
Because ASP.NET uses the Windows identity of the ASP.NET process when compiling applications and loading configuration i
nformation, you must keep application code and configuration information private between applications on a server that hos
ts multiple applications. On Windows Server 2003 you can create multiple application pools and specify a unique identity for
each application pool. You can then restrict access to application files using access control lists (ACLs) (if file system is format
ted using NTFS) and these identities. For example, consider two applications, App1 and App2, where the information in each
application must be kept private. You can put App1 in the ApplicationPool1 application pool which has an identity of ID_Appli
cationPool1. You can put App2 in the ApplicationPool2 application pool which has an identity of ID_ApplicationPool2. The ID_
ApplicationPool1 account is given access to the files in App1, but denied access to the files in App2. ID_ApplicationPool2 is gi
ven access to the files in App2, but denied access to the files in App1. Note that you cannot make this separation on Windows
2000 or Windows XP Professional, because on those operating systems, the process identity for all ASP.NET applications is a
single identity.

You control impersonation using the identity configuration element. As with other configuration directives, this directive
applies hierarchically. A minimal configuration file to enable impersonation for an application might look like the following
example:

<configuration>
<system.web>
<identity impersonate="true"/>
</system.web>
</configuration>

You can also add support for specific names to run an application as a configurable identity, as shown in the following
example:

<identity impersonate="true"
userName="contoso\Jane"
password="E@1bp4!T2" />

Note
In the preceding example, the user name and password are stored in clear text in the configuration file. To improve the securi
ty of your application, it is recommended that you restrict the access to your Web.config file using an Access Control List (AC
L) and that you encrypt the identityconfiguration element in your Web.config file using protected configuration. For more inf
ormation, see Encrypting Configuration Information Using Protected Configuration.

The configuration illustrated in the example enables the entire application to run using the contoso\Jane identity, regardless of
the identity of the request. This type of impersonation can be delegated to another computer. That is, if you specify the user
name and password for the impersonated user, you can connect to another computer on the network and request resources,
such as files or access to SQL Server, using integrated security. If you enable impersonation and do not specify a domain
account as the identity, you will not be able to connect to another computer on the network unless your IIS application is
configured to use Basic authentication.
Note
On Windows 2000, you cannot impersonate using specific user credentials for the identity of the ASP.NET worker process. B
ut you can enable impersonation without specific user credentials so that your application impersonates the identity determi
ned by IIS. For more information, see article 810204, "PRB: Per Request Impersonation Does Not Work on Windows 2000 wit
h ASP.NET," in the Microsoft Knowledge Base at http://support.microsoft.com.

Reading the Impersonated Identity


The following code example shows how to programmatically read the identity of the impersonated user:
VB
Dim username As String = _
System.Security.Principal.WindowsIdentity.GetCurrent().Name

C#
String username =
System.Security.Principal.WindowsIdentity.GetCurrent().Name;

See Also
Other Resources
ASP.NET Web Application Security
ASP.NET

ASP.NET Application Security in Hosted Environments


The topics in this section provide information about how to configure ASP.NET and the ASP.NET environment to improve the
security of your ASP.NET application Web server.
In This Section
Configuring ASP.NET Process Identity
ASP.NET Required Access Control Lists (ACLs)
ASP.NET Code Access Security
ASP.NET Trust Levels and Policy Files
Related Sections
ASP.NET Web Application Security
Provides links to general topics on securing ASP.NET Web applications.
Configuring ASP.NET Applications
Provides links to topics on how to use configuration files and the configuration API to manage the run-time behavior of
ASP.NET.
ASP.NET

Configuring ASP.NET Process Identity


ASP.NET pages are executed within a process, or Windows program. All Windows programs run with a specific security
identity. By default, the ASP.NET process runs under a predefined Windows identity. Alternatively, by configuring your
application to use impersonation, you can set ASP.NET to run under a different identity or under the Windows identity of the
user making the request.
To help improve the security of your ASP.NET applications, you should make sure that the ASP.NET process runs with an
identity that has only the minimal permissions required to run your applications. This reduces the vulnerability of any
resources that are exposed by ASP.NET, should a security breach occur.
On a Web server running Microsoft Windows Server 2003 and Internet Information Services (IIS) 6.0, the ASP.NET process
runs in the application pool for the Web application. The application pool defines the identity that ASP.NET runs under (by
default, the NETWORK SERVICE account). On earlier versions of IIS, (in Microsoft Windows 2000 and Windows XP Professional
operating systems), ASP.NET runs in the ASP.NET worker process (Aspnet_wp.exe). The identity that ASP.NET runs under is
defined by the identity of the Aspnet_wp.exe process (by default, the ASPNET account).
To specify the identity for your ASP.NET application on a server running Windows Server 2003, use IIS Manager to configure
the identity of the application pool for your ASP.NET application. The application-pool identity must also be added to the
IIS_WPG group on the server computer.
To run the ASP.NET worker process with its own account under Windows 2000 or Windows XP Professional, you can apply the
following two attributes to the <processModel> configuration element of the Web server computer's Machine.config file:
userName The name of the Windows account under which the process will run.
password The clear-text password for the account. There are security risks associated with storing clear-text passwords
in a configuration file. If you store credentials in the configuration file, you should encrypt the contents of the
<processModel> configuration element using protected configuration. For more information, see
Encrypting Configuration Information Using Protected Configuration. For applications published on the Internet, you
should use an alternative means of running the application with a specific identity, such as impersonating the
anonymous identity supplied by IIS. For more information, see Using IIS Authentication with ASP.NET Impersonation.
The following example shows how to set these attributes, in the <processModel> element of a configuration file, to run the
worker process under a local user account.

<system.web>
<processModel enable="true"
userName="LOCALMACHINE\IUSR_ProcessUser"
password="%Hco94*#QW12"/>
</system.web>

In addition to setting the userName attribute to the name of an existing Windows identity, you can set it to the predefined
names System or Machine. The System account runs the worker process under the same identity as IIS itself (typically
SYSTEM).
Security Note
It is not recommended that you run your applications under the System account, because the account has elevated privilege
s and can therefore represent a security risk if the ASP.NET process is compromised.

The Machine account runs the worker process with a special account named ASPNET that has limited permissions. With either
identity, the process does not have to supply credentials to the operating system.
Note
In order for your ASP.NET applications to function properly, you must ensure that the process identity has access to the Acce
ss Control Lists (ACLs) that are listed in ASP.NET Required Access Control Lists (ACLs). Additionally, on servers running IIS 5.
0, the process identity must be granted read access to the IIS metabase, which can be accomplished using the Aspnet_regiis.e
xe tool and specifying the -ga option (for example, aspnet_regiis -ga "UserDomain\ApplicationUser").
See Also
Other Resources
ASP.NET Web Application Security
ASP.NET

ASP.NET Required Access Control Lists (ACLs)


The following table shows which type of file and folder permissions the identity of an ASP.NET Web application must have in
order to function properly. Some permissions are required only by the account that the ASP.NET process is running as, while
others are required by any impersonated account also. For more information, see ASP.NET Impersonation.
Location Acce Account Comments
ss ty
pe
%SystemRoot%\Microsoft Read Process or This is the location for dynamically compiled files. Beneath this location, applicatio
.NET\Framework\version /writ configured n code generation takes place in a discrete directory for each application. You can
Number\Temporary ASP. e impersonat configure the root location using the tempDir attribute of the <compilation> con
NET Files ion. figuration section.

%SystemRoot%\assembly Read Process or This is the location of the global assembly cache (GAC).
configured
impersonat
ion.

%SystemRoot%\System3 Read Process Contains system DLLs loaded by the .NET Framework.
2

%SystemRoot%\Temp Read Process Used for Web services support.


/writ
e/del
ete

User profile directory Read Process Used by the GAC cache lock files and the security configuration caching mechanis
/writ m of the common language runtime. If the user profile directory for the account d
e oes not exist, ASP.NET uses the default user profile directory.

Web application directory Read Process or This is the location for application files.
configured
impersonat
ion.

Web application directory Read Process or This is the default location for data files in an ASP.NET Web application. If your ap
\App_Data /writ configured plication uses the App_Data subdirectory, the ASP.NET process must be able to wr
e impersonat ite to the directory and for some databases, to be able to create temporary files in
ion. the subdirectory.

%SystemRoot%\Microsoft Read Process or ASP.NET must be able to access the system assemblies referenced in the Machine.
.NET\Framework\version configured config file in the CONFIG subdirectory under %SystemRoot%\Microsoft.NET\Fra
and subdirectories impersonat mework\version\.
ion

See Also
Other Resources
ASP.NET Web Application Security
ASP.NET

ASP.NET Code Access Security


One of the benefits of using ASP.NET to host multiple Web sites is support in the common language runtime (CLR) for code
access security to help protect server applications. Code is assigned to a security zone classification based on evidence about
the code's origin, such as a strong name for an assembly or the code's URL of origin.
Applications that run with full trust can still be constrained by NTFS file permissions, database permissions, and so on using
the Windows account (the ASP.NET process identity) under which they are executing. For more information, see
Configuring ASP.NET Process Identity.
In general, you can configure code access security for an individual assembly by making it a strong-named assembly and by
adding security policy for that assembly. However, many ASP.NET assemblies are dynamically generated during page
compilation and therefore are not strongly named, so you must configure security policy for those assemblies indirectly.
Additionally, because ASP.NET supports no-compile applications, assembly-based evidence is not supported. Because ASP.NET
applications include the concept of directory structures, it is much easier to configure code access security based on categories
of ASP.NET applications as opposed to manually configuring the .NET Framework to work separately with each ASP.NET
application on a computer separately.
For each application, ASP.NET lets you assign a configurable trust level that corresponds to a predefined set of permissions. By
default, applications are assigned a trust level according to the evidence they present. If you want to run a Web application with
less than the Full permission set, you must use one of the predefined trust levels defined in
ASP.NET Trust Levels and Policy Files to enforce a partial trust policy.
You can use the following configuration settings in the application's Web.config file to override the default behavior and
associate an application with a given security policy:

<location path="SampleApp" allowOverride="false">


<trust level="High"
originUrl="http://www.contoso.com"/>
</location>

The trust configuration element can apply to the machine level (in which case every ASP.NET application runs at that trust
level) or to any application root directory in the hierarchy (in which case the trust level applies to the specific ASP.NET
application). If you want to set policy for an entire site, you can do so by editing the Web.config file for the root application of
the site and specifying the root of the site as the path location, as in the following example:

<location path="ContosoSite" allowOverride="false">


<trust level="High"
originUrl="http://www.contoso.com"/>
</location>

It is recommended that you set the level attribute of the trust configuration element to High for sites that are trusted. For
sites that are not trusted, such as a Web server that hosts sites that run code from an external customer, it is recommended
that you set the level attribute of the trust configuration element to Medium. For a detailed description of running ASP.NET
applications in Medium trust, see "How To: Use Medium Trust in ASP.NET 2.0" at
Patterns and Practices (PAG): Security Guidance for Applications.
If you are configuring trust settings at the machine or site level, you typically set the allowOverride attribute to false in the
location element, so that individual applications are not able to specify their own trust level. This is typical in shared server
installations.
The following table lists the default supported attributes for the trust configuration element.
A Description Supported values
tt
ri
b
u
t
e
l Specifies the security zone under which the application will run. Full, High, Medium,
e Low, and Minimal.
v
e
l

o Specifies a URL or URL pattern that is allowed for connect access using classes in the System.Net nam Well-formed HTTP U
ri espace. If present, this attribute can be used to check permissions for some objects, such as a RLs, or the regex-bas
g WebRequest instance, that allow connectivity to various network locations. For example, you could co ed syntax that is supp
i nfigure this attribute with the host name of servers in a Web farm so that ASP.NET pages could call W orted by WebPermis
n eb services deployed in the same Web farm as the Web application. sionAttribute.
U
rl

The following table lists permission types supported by the CLR and the default policy for each permission under different
trust levels.
Permission Ful High Medium Low Min
l imal
AspNetHostingPermission Full High Medium Low Mini
mal

ConfigurationPermission Unr Unrestricted No permission No permission No p


estr ermi
icte ssio
d n

DnsPermission Unr Unrestricted Unrestricted No permission No p


estr ermi
icte ssio
d n

EnvironmentPermission Unr Unrestricted Read: TEMP, TMP, OS, USERN No permission No p


estr AME, COMPUTERNAME ermi
icte ssio
d n

FileIOPermission Unr Unrestricted Read, Write, Append, Read, PathDiscovery:Appli No p


estr PathDiscovery:Application Di cation Directory ermi
icte rectory ssio
d n

IsolatedStorageFilePermission Unr Unrestricted AssemblyIsolationByUser, Un 1 MB UserQuota (can be ch No p


estr restricted UserQuota anged for individual sites), A ermi
icte ssemblyIsolationByUser ssio
d n

PrintingPermission Unr DefaultPrinting DefaultPrinting No permission No p


estr ermi
icte ssio
d n

ReflectionPermission Unr ReflectionEmit No permission No permission No p


estr ermi
icte ssio
d n
RegistryPermission Unr Unrestricted No permission No permission No p
estr ermi
icte ssio
d n

SecurityPermission Unr Execution, Assertion, Execution, Assertion, Contr Execution Exe


estr ControlPrincipal, olPrincipal, ControlThread, cuti
icte ControlThread, RemotingConfiguration on
d RemotingConfiguration

SmtpPermission Unr Connect Connect No permission No p


estr ermi
icte ssio
d n

SocketPermission Unr Unrestricted No permission No permission No p


estr ermi
icte ssio
d n

WebPermission Unr Unrestricted Connect to origin host (if con No permission No p


estr figured) ermi
icte ssio
d n

SqlClientPermission Unr Unrestricted Unrestricted No permission No p


estr ermi
icte ssio
d n

Event Log Unr No permission No permission No permission No p


estr ermi
icte ssio
d n

Message Queue Unr No permission No permission No permission No p


estr ermi
icte ssio
d n

Service Controller Unr No permission No permission No permission No p


estr ermi
icte ssio
d n

Performance Counters Unr No permission No permission No permission No p


estr ermi
icte ssio
d n

Directory Service Unr No permission No permission No permission No p


estr ermi
icte ssio
d n

When a permission level is available but is not explicitly mentioned in security policy, applications running with Full
permissions can always use it. Applications running with lower trust levels will not be able to use resources unless you grant
them explicit permissions by altering the security policy.
As the table shows, application with High permission sets have read/write permission for files in their application directories,
and Low trust applications have read-only permission for files in their application directories. Because the FileIOPermission
type relies on a physical path (for example, c:\SampleAppPath), ASP.NET uses a tokenized statement in the policy files that is
replaced at run time with relevant path information for the application.
The WebPermission type allows the application to connect to the network location defined by the original host attribute,
using classes like System.Net.WebRequest. In ASP.NET, you can configure this permission by providing an optional
originUrl attribute on the trust section for a given application. The originUrl attribute replaces the $OriginHost$ variable in
policy files, as shown in the following section from the Web_hightrust.config file:

<IPermission class="WebPermission" version="1">


<ConnectAccess>
<URI uri="$OriginHost$"/>
</ConnectAccess>
</IPermission>

See Also
Other Resources
ASP.NET Web Application Security
ASP.NET

ASP.NET Trust Levels and Policy Files


Trust levels are associated with policy files using the <securityPolicy> configuration element, which is valid only in a site-level
configuration (Web.config) file. You can add or remove trust levels by adding entries to the configuration section that specify
the trust level name and the policy file to be used. The default trust files are installed in the Config directory under the folder
containing the Aspnet_isapi.dll file. This is the same location used for the Machine.config configuration file and the run-time
security policy file.
The Full trust Level is a special case. Because it is exactly equivalent to having full trust in the local machine zone, the ASP.NET
host does not apply any additional policy to these applications. Therefore, the Full trust level is mapped to an internal handler
and ASP.NET does not add additional policy to the application domain for full-trust applications.
The following example shows the securityPolicy section of a configuration file that maps trust levels to different policy files.

<system.web>
<securityPolicy>
<trustLevel name="Full" policyFile="internal"/>
<trustLevel name="High" policyFile="web_hightrust.config"/>
<trustLevel name="Medium" policyFile="web_mediumtrust.config"/>
<trustLevel name="Low" policyFile="web_lowtrust.config"/>
<trustLevel name="Minimal" policyFile="web_minimaltrust.config"/>
</securityPolicy>
</system.web>

If you do not want applications to be able to specify their own trust level, you can specify a <location> directive and set the
allowOverride attribute to false. You might do this on a server that hosts multiple applications and that needs to limit the
trust level of the hosted applications.
Modifying Trust-Level Files
You can alter the policy files or create new ones with custom permission sets. For example, you can copy the contents of the
Web_hightrust.config file and assign permission to make OLEDB connections by first adding the OleDbPermission class to the
SecurityClasses section of the policy file, as shown in the following code example.

<SecurityClass Name="OleDbPermission"
Description="System.Data.OleDb.OleDbPermission, System.Data, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089"/>

You can then specify the parameters for the specified OleDbPermission, including restrictions for OLEDB connection strings.
Next, you can specify which permission sets include the OleDbPermission security class by adding an IPermission element
to the PermissionSet element with a name of ASP.NET in the trust-policy file. For example, the following code example
specifies that the only allowed OLEDB connection will grant unrestricted access to the Catalog.mdb Access database.

<PermissionSet
class="NamedPermissionSet"
version="1"
Name="ASP.Net">
<IPermission
class="OleDbPermission"
version="1"
Unrestricted="true" />
</PermissionSet>

Some permissions, such as the OleDbPermission permission, allow you specify additional restrictions that narrow the access
that is granted or denied. For example, the OleDbPermission permission allows you to grant access to make connections
using the OLE DB .NET Framework Data Provider, but with restrictions on which OLEDB connection strings are allowed. The
following code example specifies that the only allowed OLEDB connections to Access databases are allowed.

<IPermission class="OleDbPermission" version="1">


<add ConnectionString=
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=E:\access_data\catalog.mdb""
KeyRestrictions=""data source=;user id=;password=;"
KeyRestrictionBehavior="AllowOnly"/>
</IPermission>

You can save your updated trust-policy file and put it in place of the current Web_hightrust.config file, or you can create a new
trust-policy file and either specify that as the policy file for the High trust level, or create a new trust level as shown in the
following code example.

<trustLevel name="HighCustom"
policyFile="web_highcustom.config"/>

In order to preserve the default settings, ASP.NET includes two copies of each file that contains trust-level settings. One copy is
named with the file name extension .config, as shown in the configuration section earlier. The .config file contains the settings
for each trust level used by the system. The second copy is named with the file name extension .config.default and contains the
default settings for the related trust level. If the current trust-level settings have been modified and you want to restore the
default settings, you can replace the contents of the .config file with the contents of the .config.default file.
For a more detailed description of managing a trust policy file, see "How To: Use Medium Trust in ASP.NET 2.0" at
Patterns and Practices (PAG): Security Guidance for Applications.
See Also
Concepts
ASP.NET Policy Mechanics
Other Resources
ASP.NET Web Application Security
ASP.NET

ASP.NET Policy Mechanics


The application domain policy for trust levels consists of a policy level (for example, an instance of the
System.Security.Policy.PolicyLevel class) that is loaded and applied to the application domain as the application domain policy.
The policy tree itself is the same for High, Medium, Low, and Minimal trust levels (no policy is applied for Full), except for
the set of granted permissions in the ASP.NET permission set.
After computing the application domain policy for a given application (full-trust applications are exempt from this step), the
policy is applied to the application domain. Application domain policy intersects with the various other policy levels (Enterprise,
Machine, and User) so that it can only further restrict, not expand, the existing policy.
To see how application domain policy is used to restrict granted permissions, consider the fictitious permission sets and policy
levels shown in the following table.
Level Name Permissions
Enterprise P1 {A, B, C, D}

Machine P2 {A, B, C}

User P3 {A, B, C}

Application Domain P4 {A, B}

The simplified application permission (ignoring permission requests) of these policy sets would be the intersection of the
permissions granted at the various levels. Thus, the intersection of P1, P2, P3, and P4 is {A, B}.
Managing Policy Files
You can edit policy files by hand. You can use the .NET Framework Configuration Tool or the Code Access Security Policy Tool
to administer security policy for the enterprise, machine, or user levels. For more information about using these tools, see
Administering Security Policy.
See Also
Other Resources
ASP.NET Web Application Security
ASP.NET

Managing Users by Using Membership


ASP.NET membership enables you to validate and manage user information for your Web application. It provides functionality
for validating user credentials, creating and modifying membership users, and managing user settings such as passwords and
e-mail addresses. ASP.NET membership is primarily intended for use with ASP.NET forms authentication, but can be used
anywhere within an ASP.NET application.
ASP.NET membership enables you to manage user authentication for your application while keeping the user information in
the data source of your choice. Because ASP.NET membership users providers to the membership data source, it does not
require extensive code to read and write membership information.
ASP.NET membership consists primarily of built-in membership providers, which communicate with the data source, and the
static membership class that exposes the functionality of the membership providers. You call the membership class from your
ASP.NET code to perform user validation and management.
Note
Most of the functionality that the membership class and the membership providers provide is encapsulated in several user
management web controls. For more information, see the Login control.

In This Section
Introduction to Membership
Comparison of Membership with Windows or Passport Authentication
Membership Classes
Membership Providers
Configuring an ASP.NET Application to Use Membership
Securing Membership
Implementing a Membership Provider
How to: Implement a Custom Membership User
Reference
System.Web.Security
Related Sections
Basic Security Practices for Web Applications
Describes common types of Web site security attacks and how to help prevent them.
Security in the .NET Framework
Describes general .NET Framework security concepts, services, and best practices.
ASP.NET Web Site Security
Provides links to all topics on security in ASP.NET security.
ASP.NET Login Controls Overview.
Provides information about controls you can use to create pages for logging in, managing passwords, and creating new
users.
ASP.NET

Introduction to Membership
ASP.NET membership gives you a built-in way to validate and store user credentials. ASP.NET membership therefore helps you
manage user authentication in your Web sites. You can use ASP.NET membership with ASP.NET Forms authentication or with
the ASP.NET login controls to create a complete system for authenticating users.
ASP.NET membership supports facilities for:
Creating new users and passwords.
Storing membership information (user names, passwords, and supporting data) in Microsoft SQL Server, Active
Directory, or an alternative data store.
Authenticating users who visit your site. You can authenticate users programmatically, or you can use the ASP.NET login
controls to create a complete authentication system that requires little or no code.
Managing passwords, which includes creating, changing, and resetting them . Depending on membership options you
choose, the membership system can also provide an automated password-reset system that takes a user-supplied
question and response.
Exposing a unique identification for authenticated users that you can use in your own applications and that also
integrates with the ASP.NET personalization and role-management (authorization) systems.
Specifying a custom membership provider, which allows you to substitute your own code to manage membership and
maintain membership data in a custom data store
Membership, Roles and the User Profile
Although membership is a self-standing feature in ASP.NET for authentication, it can be integrated with ASP.NET role
management to provide authorization services for your site. Membership can also be integrated with the user profile to
provide application-specific customization that can be tailored to individual users. For details, see
Managing Authorization Using Roles and ASP.NET Profile Properties.
How Membership Works
To use membership, you must first configure it for your site. In outline, you follow these steps:
1. Specify membership options as part of your Web site configuration. By default, membership is enabled. You can also
specify what membership provider you want to use. (In practical terms, this means that you are specifying what type of
database you want to keep membership information in.) The default provider uses a Microsoft SQL Server database. You
can also choose to use Active Directory to store membership information, or you can specify a custom provider. For
information on membership configuration options that can be specified in the Web.config file for your ASP.NET
application, see Configuring an ASP.NET Application to Use Membership.
2. Configure your application to use Forms authentication (as distinct from Windows or Passport authentication). You
typically specify that some pages or folders in your application are protected and are accessible only to authenticated
users.
3. Define user accounts for membership. You can do this in a variety of ways. You can use the Web Site Administration Tool,
which provides a wizard-like interface for creating new users. Alternatively, you can create a "new user" ASP.NET Web
page where you collect a user name and password (and optionally an e-mail address), and then use a membership
function named CreateUser to create a new user in the membership system.
You can now use membership to authenticate users in your application. Most often, you will provide a login form, which might
be a separate page or a special area on your home page. You can create the login form by hand using ASP.NET TextBox
controls, or you can use ASP.NET login controls. Because you have configured the application to use Forms authentication,
ASP.NET will automatically display the login page if an unauthenticated user requests a protected page.
Note
The ASP.NET login controls (Login, LoginView, LoginStatus, LoginName, and PasswordRecovery) encapsulate virtually all of t
he logic required to prompt users for credentials and validate the credentials in the membership system.

If you use login controls, they will automatically use the membership system to validate a user. If you have created a login form
by hand, you can prompt the user for a user name and password and then call the ValidateUser method to perform the
validation. After the user is validated, information about the user can be persisted (for example, with an encrypted cookie if the
user's browser accepts cookies) using Forms Authentication. The login controls perform this task automatically. If you have
created a login form by hand, you can call methods of the FormsAuthentication class to create the cookie and write it to the
user's computer. If a user has forgotten his or her password, the login page can call membership functions that help the user
remember the password or create a new one.
Each time the user requests another protected page, ASP.NET Forms authentication checks whether the user is authenticated
and then either allows the user to view the page or redirects the user to the login page. By default, the authentication cookie
remains valid for the user's session.
After a user has been authenticated, the membership system makes available an object that contains information about the
current user. For example, you can get properties of the membership user object to determine the user's name and e-mail
address, when the user last logged into your application, and so on.
An important aspect of the membership system is that you never need to explicitly perform any low-level database functions
to get or set user information. For example, you create a new user by calling the membership CreateUser method. The
membership system handles the details of creating the necessary database records to store the user information. When you
call the ValidateUser method to check a user's credentials, the membership system does all the database lookup for you.
Membership Configuration and Management
You configure the membership system in your application's Web.config file. The easiest way to configure and manage
membership is with the Web Site Administration Tool, which provides a wizard-based interface. As part of membership
configuration, you specify:
What membership provider to use. (This typically also specifies what database to store membership information in.)
Password options such as encryption and whether to support password recovery based on a user-specific question.
Users and passwords. If you are using the Web Site Administration Tool, you can create and manage users directly.
Otherwise, you must call membership functions to create and manage users programmatically.
See Also
Concepts
Securing Membership
Other Resources
Managing Users by Using Membership
Visual Web Developer

Walkthrough: Creating a Web Site with Membership and User


Login (Visual Studio)
A common requirement for Web sites is to allow only some members or other authenticated users to see certain pages. In that
case, the application must prompt the user for a name and password. The application must also include a way to hide
information from anonymous users (users who are not logged in). This walkthrough shows you how to use ASP.NET controls
and ASP.NET membership services to create an application that performs all these tasks. For more information, see
Introduction to Membership.
Tasks illustrated in this walkthrough include:
Configuring an application to include ASP.NET membership services, and how to define users.
Using login controls to get user credentials and to display information to logged-in users.
Protecting one or more pages in your application so that only logged-in users can view them.
Allowing new users to register at your site.
Allowing members to change and reset their passwords.
Prerequisites
In order to complete this walkthrough, you will need:
Microsoft Visual Web Developer.
Microsoft Internet Information Services (IIS) installed locally on your computer.
Microsoft Data Access Components (MDAC) version 2.7 or later. If you are using Microsoft Windows XP or Windows
Server 2003, you already have MDAC 2.7. However, if you are using Microsoft Windows 2000, you might to need to
upgrade the MDAC already installed on your computer. For more information, see the article "Microsoft Data Access
Components (MDAC) Installation" in the MSDN library.
Access to an e-mail server that can forward e-mail messages. (The server does not have to be able to receive messages.)
IIS includes the Default SMTP virtual server, a mail server that is suitable for this walkthrough. For more information
about configuring this server, see How to: Install and Configure SMTP Virtual Servers in IIS. If you are working on a local
area network, check with your network administrator for information about access to an e-mail server.
Creating the Web Site
If you have already created a Web site in Microsoft Visual Studio (for example, by working with the topic
Walkthrough: Creating a Basic Web Page in Visual Web Developer ), you can use that Web site and skip to "Configuring
Membership" later in this walkthrough. Otherwise, create a new Web site and page by following these steps.
To create a local IIS Web site
1. Open Visual Studio.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, select ASP.NET Web Site.
4. In the Location list box, select HTTP. Click Browse.
The Choose Location dialog box appears.
5. Select Local IIS.
6. Open Local Web Servers.
7. Select Default Web Site.
8. Click the Create New Web Application icon ( ) above the list of Web sites and then name the new Web site
membership.
9. Click Open.
The Choose Location dialog box closes.
10. In the Languages box, click the programming language you prefer to work in.
The programming language you choose will be the default for your Web site, but you can set the programming
languages for each page individually.
11. Click OK in the New Web Site dialog box.
Visual Web Developer creates the Web site and a new page named Default.aspx.
Configuring Membership
Later in this walkthrough you will put pages into a subdirectory that is protected. You must create the subdirectory now so that
you can configure security for it later in the walkthrough.
To add a new folder to the Web site
1. In Solution Explorer, right-click the name of your Web site and click New Folder.
2. Name the folder MemberPages.
Before you work with ASP.NET membership, you must configure your application to enable membership and to set up users.
You can use the Web Site Administration tool, which provides a wizard-like interface for making configuration settings.
For this walkthrough, you will define a single user.
To create a membership user
1. On the Website menu, click ASP.NET Configuration.
2. Select the Security tab, click the link to Use the security Setup Wizard to configure security step by step, and then
click Next.
3. Proceed to Step 2 of the wizard and select the From the Internet option.
The wizard displays a page where you can select the authentication method that your Web site will use. This option
specifies that your application will use Forms authentication, where users will log in to the application using a login page
that you will create later in this walkthrough.
4. Click Next.
The wizard displays a message stating that user information will be stored using Advanced provider settings. By
default, membership information is stored in a Microsoft SQL Server Express database file in the App_Data folder of
your Web site.
5. Click Next.
The wizard displays an option to create roles. You will perform this step separately later in the walkthrough. Therefore, do
not select the Enable roles for this web site check box.
6. Click Next.
The wizard displays a page where you can create new users.
7. Enter information that defines a user of your application. Use the following values as guidelines (you can use any values
that you like, but be sure to note your entries for later in the walkthrough):
User Name Your name (with no spaces), or a sample name.
Password A password. A strong password is required (one that includes uppercase and lowercase letters,
punctuation, and that is at least eight characters long).
E-mail Your personal e-mail address. Later in the walkthrough you will send yourself an e-mail message, so you
need a legitimate e-mail address.
Security Question and Security Answer Type a question and answer that can be used later if you need to
recover your password.
8. Click Create User.
The wizard displays a confirmation page.
Note
Leave the Web Site Administration tool open.

Earlier in the walkthrough you created a folder named MemberPages. In this part of the walkthrough, you will create a rule
that makes sure that only logged-in users can access pages in that folder.
To set up access rules for the MemberPages subdirectory
1. In the wizard, click Next.
The wizard displays a page that allows you to create access rules.
2. In the Add New Access Rule box, expand the node for your Web site.
3. Select MemberPages, the folder you created earlier.
4. Under Rule applies to, select Anonymous users.
5. Under Permission, select Deny.
The rule you are creating denies access to anonymous users — that is, users who have not logged in.
6. Click Add This Rule.
The new rule is displayed in the grid below. When users request a page from the MemberPages subdirectory, the rules
are checked to determine whether the user is allowed access to the page.
7. Click Finish.
You are now done with the wizard. The wizard closes and you are returned to the Security tab of the Web Site
Administration tool.
Configuring the Application for E-Mail
For part of this walkthrough, the application needs to be able to send e-mail messages. To send messages, your application
must have access to a Simple Mail Transport Protocol (SMTP) server, which forwards e-mail messages from your application to
an e-mail recipient.
IIS includes the Default SMTP virtual server as an optional component, which is suitable for this walkthrough. For more
information about configuring this server, see How to: Install and Configure SMTP Virtual Servers in IIS. If you are working on a
local area network, check with your network administrator for information about access to an e-mail server.
After you have set up or determined how to access an SMTP server, you must configure your application to route e-mail
messages to that server. You can do so by making an entry in your Web site's Web.config file, which contains a series of
settings that determine how your application runs.
To configure the application to use a specific SMTP server
1. In the Web Site Administration tool, click the Application tab.
2. Under SMTP Settings, click Configure SMTP e-mail settings.
The tool displays a page where you can configure e-mail.
3. If you are using the SMTP virtual server that is on your computer, enter localhost as the Server Name; otherwise, enter
the appropriate server name.
Include information for the port number and for authentication according to the requirements of your SMTP server. See
your administrator for more information on how to configure these settings.
4. In the From box, type a valid e-mail address.
5. Click Save, and in the confirmation page, click OK.
The Web Site Administration tool creates a Web.config file (if one did not already exist) with the settings you have made.
Note
The Web.config file will not appear in Solution Explorer until you refresh the view.

6. Close the Web Site Administration tool.


Logging the User In
As part of your application, you need to establish the user's identity so that the application can perform actions — such as
showing or hiding information — based on who the user is. To get the user's identity, you have the user log in.
In this walkthrough, you will add a link on the home page that takes users to a login page, and then you will create the login
page.
To create a home page with a login button
1. Open or switch to the Default.aspx page of your site. (If you do not have a Default.aspx page, you can add one or use a
different page.)
2. Switch to Design view.
3. Type static text such as Welcome to our site and, in the Formatting toolbar, use the Block Format drop-down list to
format the text as Heading 1.
4. From the Login group of the Toolbox, drag a LoginStatus control onto the page.
By default, the LoginStatus control is rendered as a link. When users click it, the application displays a login page. You can
now create the login page.
To create a login page
1. In Solution Explorer, right-click your Web application and select Add New Item. Add a Web Form named Login.aspx
to your site.
Note
For this walkthrough, the page must be named Login.aspx. By default, forms authentication is configured to work with
a page with this name. Although you will not do so in this walkthrough, you can change the default login page — the p
age to which users are redirected — in the Web.config file.

2. In the Login.aspx page, switch to Design view.


3. From the Login group of the Toolbox, drag a Login control onto the page.
The Login control is a single control that will prompt the user for credentials and validate them.
Displaying Login Errors
The Login control includes validation to help users enter correct information. For example, if a user skips the password, a
validator control displays an asterisk (*) next to the Password box. You can provide more complete information for login
errors by adding a ValidationSummary control to the page.
To display detailed login errors
1. From the Validation group of the Toolbox, drag a ValidationSummary control onto the page.
2. In the Properties window for the ValidationSummary control, set the ValidationGroup property to Login1, which is
the default ID of the Login control you added previously.
Displaying Information for Logged-In Users
You will now modify the home page to customize the display depending on whether the user is logged in. Anonymous users
will see a generic message inviting them to log in. Logged-in users will see a message that welcomes them by their logged-in
name.
To customize the display for logged-in users
1. Switch to or open the Default.aspx page.
2. From the Login group of the Toolbox, drag a LoginView control onto the page.
The LoginView control is displayed with its AnonymousTemplate template open. This template allows you to define
the content that users will see before they have logged in.
3. Click the edit area of the LoginView control to activate editing.
4. In the edit area of the LoginView control's AnonymousTemplate template, type You are not logged in. Click the
Login link to sign in.
5. On the LoginView Tasks panel, in the Views list, click LoggedInTemplate. If you do not see the LoginView Tasks
panel, right-click the heading of the LoginView control and select Show Smart Tag.
You are now defining the content that will be displayed to users who have already logged in.
6. Click the edit area of the LoginView control to activate editing, and then type You are logged in. Welcome,.
7. From the Login group of the Toolbox, drag a LoginName control into the template after the text.
Testing Login
You can now test the login capability of your application.
To test login
1. In Solution Explorer, right-click Default.aspx and click Set As Start Page.
This configures the Web site so that when you run the site, the Default.aspx page appears first.
2. Press CTRL+F5 to run the Web site.
The home page (Default.aspx) appears in the browser, showing the Login link and the generic message.
3. Click the Login link.
The login page you created is displayed.
4. Type the login name of the user you created earlier in the walkthrough, and then click Log In. (Do not yet enter a
password.)
An asterisk (*) is displayed next to the Password box, and an error message is displayed in the ValidationSummary
control.
5. Type both a user name and password and then click Log In.
If you entered correct credentials, you are returned to the home page. The page now displays a Logout link, your user
name, and the welcome message that you defined for the logged-in user.
6. Close the browser.
Limiting Access for Members-Only Pages
A typical task in many Web sites is to configure pages so that only logged-in users can view the pages. Earlier in the
walkthrough, you created the MemberPages subdirectory and created a rule that limits access to pages in the subdirectory. In
this section of the walkthrough, you will add a page to the protected subdirectory and test the access rule.
To create the members-only page
1. In Solution Explorer, right-click the MemberPages folder, click Add New Item, and add a new Web Form named
Members.aspx.
Note
Be sure to create the page in the MemberPages folder.

2. In Design view, add text to the page, such as Welcome, members! The exact text does not matter, as long as you will be
able to recognize this page when you see it in the browser.
You can now add a link to the members-only page from the home page. In a real application, you would probably put the
members-only page link in the logged-in template of the LoginView control. That way, visitors to your site would not see the
link until they were logged in. For this walkthrough, however, you will make the link available to all users so that you can see
the effect of trying to view a members-only page without first logging in.
To add a link to the members-only page
1. Switch to or open the Default.aspx page.
2. From the Standard group of the Toolbox, drag a HyperLink control onto the page.
3. In the Properties window for the HyperLink control, set the Text property to Members page and the NavigateUrl
property to ~/MemberPages/Members.aspx to point to the page that you created previously.
Testing the Members-Only Page
You can test the members-only page by accessing it both as an anonymous user and a logged-in user.
To test the members-only page
1. Press CTRL+F5 to run the Web site.
2. When the Default.aspx page appears in the browser, do not log in. Instead, click the Members page link.
You are redirected to the Login.aspx page because access to the members page is denied for anonymous users.
3. In the login page, type the user name and password that you used earlier in the walkthrough to log in.
You are redirected to the Members.aspx page because the user name you are logged in as has been authorized to access
the page.
4. Close the browser window.
Creating New Users
In the first part of the walkthrough, you created a user with the Web Site Administration tool. That strategy is useful if you are
working with a small, defined list of users; for example, if you are creating users for a small team. In many Web sites, however,
users are allowed to register themselves. ASP.NET includes the CreateUserWizard control that performs the same task you
performed earlier using the Web Site Administration tool.
In this part of the walkthrough, you will add a facility that allows users to register on your Web site. To start, you will create a
registration page.
To create a registration page
1. In Solution Explorer, right-click the name of your Web site, click Add New Item, and add a new Web Form named
Register.aspx.
Note
Be sure to create the page in the root of the Web site, not in the MemberPages folder.

2. In the Register.aspx page, switch to Design view and type static text such as Register into the page. In the Formatting
toolbar, use the Block Format drop-down list to format the text as Heading 1.
3. From the Login group of the Toolbox, drag a CreateUserWizard control onto the page.
4. In the Properties window for the CreateUserWizard control, set the ContinueDestinationPageUrl property to
~/Default.aspx.
This configures the control so that when users click Continue after creating a user, the control returns to the home page.
5. From the Standard group of the Toolbox, drag a HyperLink control onto the page. In the Properties window for the
HyperLink control, set the Text property to Home and the NavigateUrl property to ~/Default.aspx.
You can now add a link to the home page that displays the registration page. For this walkthrough, assume that you want to
display the registration link only to users who are not logged in.
To create a registration link on the home page
1. Switch to or open the Default.aspx page.
2. Right-click the LoginView control added previously, and select Show Smart Tag. In the LoginView Tasks panel, select
AnonymousTemplate from the Views list box to activate editing in the anonymous template.
3. From the Standard group of the Toolbox, drag a HyperLink control into the anonymous template. In the Properties
window for the HyperLink control, set the Text property to Register and the NavigateUrl property to Register.aspx.
The Register link will be displayed only to users who are not logged in.
You can now test the registration process.
To test registration
1. Press CTRL+F5 to run the Web site and display the Default.aspx page.
Because you are not logged in, the page containing the Register link is displayed.
2. Click the Register link.
The registration page is displayed.
3. In the text boxes, enter a new user name, a strong password, an e-mail address, and a security question and answer. (All
five pieces of information are required.)
4. Click Create User.
A confirmation message is displayed.
5. Click the Continue button.
You are returned to the home page as a logged-in user. Note that the Login link has changed to Logout and that the
information displayed in the Login control is from the LoggedInTemplate property, not from the AnonymousTemplate
property.
6. Click the Logout link.
The page changes to display the information for anonymous users.
7. Click the Login link.
8. Enter the credentials for the user you just created.
You are logged in as the new user.
9. Close the browser window.
Changing Passwords
Users sometimes might want to change their passwords, and it is often impractical to perform this task by hand. You can
therefore use another ASP.NET control to allow users to change passwords on their own. To change a password, users must
know their existing password.
In this walkthrough, you will add a page where logged-in users can change their password.
To create a password-change page
1. In Solution Explorer, right-click the MemberPages folder, click Add New Item, and add a new Web Form named
ChangePassword.aspx.
Note
Be sure to create the page in the MemberPages folder.

You are putting the page in the members-only folder because only logged-in users can change their passwords.
2. In the ChangePassword.aspx page, switch to Design view and type static text such as Change Password. In the
Formatting toolbar, use the Block Format drop-down list to format the text as Heading 1.
3. From the Login group of the Toolbox, drag a ChangePassword control onto the page.
4. In the Properties window for the ChangePassword control, set ContinueDestinationPageUrl property to
~/Default.aspx.
5. This configures the control so that when users click Continue after changing a password, the control returns to the
home page.
You can now add a link to the home page that displays the password-change page. You will make the link available only to
users who are logged in.
To create a password-change link on the home page
1. Switch to or open the Default.aspx page.
2. Right-click the LoginView control and then click Show Smart Tag. In the LoginView Tasks menu, in the Views list,
click LoggedInTemplate.
This switches the LoginView control to edit mode for the content that will appear to users who are logged in.
3. From the Standard group of the Toolbox, drag a HyperLink control into the editing region. In the Properties window
for the HyperLink control, set the Text property to Change password and the NavigateUrl property to
~/MemberPages/ChangePassword.aspx.
The Change password link will be displayed only to users who are logged in, which is the opposite of the Register link
you created earlier.
You can now test the password-change process.
To test password change
1. Press CTRL+F5 to run the Web site.
2. In the Default.aspx, page, click the Login link and log in as one of the users you have created.
When you are finished, you are returned to the home page as a logged-in user.
3. Click the Change password link.
4. In the password-change page, enter the old password and a new password, and then click Change Password.
5. Click Continue.
6. On the home page, click Logout.
7. Click the Login link.
8. Enter the new password.
You are logged in with the new password.
9. Close the browser window.
Recovering a Password
Users will occasionally forget their passwords. You can add a password recovery page to your Web site so that they can once
again log in to your site. Password recovery can take two forms:
You can send users the password they selected (or that you created for them when you set up the site). This option
requires that the site store the password using reversible encryption.
You can send users a new password, which they can change using the Change Password page you created earlier. This
option is useful if the Web site stores passwords using a non-reversible encryption scheme such as hashing.
Note
Returning a password in clear text using e-mail is not recommended for sites that require a high level of security. For high-se
curity sites, it is recommended that you return passwords using encryption, such as Secure Sockets Layer (SSL).
By default, the ASP.NET membership system secures passwords by hashing them, meaning that the passwords cannot be
recovered. Therefore, for this part of the walkthrough, your Web site will send users a new password.
Note
Password recovery requires that your Web site can send e-mail messages. If you are not able to configure your Web site to s
end e-mail (as explained under "Configuring the Application for E-Mail" earlier in this walkthrough), you will not be able to a
dd password recovery to your site.

To add password recovery


1. In Solution Explorer, right-click the name of your Web site, click Add New Item, and add a new Web Form named
RecoverPassword.aspx.
Note
Be sure to create the page in the root of the Web site, not in the MemberPages folder.

2. In the RecoverPassword.aspx page, switch to Design view and type static text such as Reset my password to a new
value. In the Formatting toolbar, use the Block Format drop-down list to format the text as Heading 1.
3. From the Login group of the Toolbox, drag a PasswordRecovery control onto the page.
4. From the Standard group of the Toolbox, drag a HyperLink control onto the page. In the Properties window for the
HyperLink control, set the Text property to Home and the NavigateUrl property to ~/Default.aspx.
5. Switch to the Default.aspx page.
6. Right-click the LoginView control and then click Show Smart Tag. In the LoginView Tasks menu, in the Views list,
click AnonymousTemplate.
This switches the LoginView control to edit mode for the content that will appear to users who are not logged in.
7. From the Standard group of the Toolbox, drag a HyperLink control into the template. In the Properties window for
the HyperLink control, set the Text property to Forgot your password? and the NavigateUrl property to
~/RecoverPassword.aspx.
Now you can test password recovery.
To test password recovery
1. Press CTRL+F5 to run the Web site.
2. By default, you are not logged in, so you see the anonymous template of the LoginView control.
3. Click the Forgot your password? link.
The RecoverPassword.aspx page appears.
4. Type your user name and click Submit.
The security question is displayed and you are prompted to type the security answer.
5. Type the answer and click Submit.
If you entered a correct answer, the Web site resets your password and sends you an e-mail message with the new
password.
Next Steps
This walkthrough has illustrated a simple but complete scenario for creating an application that prompts users for credentials,
displays information to logged-in users, allows users to recover a forgotten password, and limits access to pages. You can
create more sophisticated pages and applications using the techniques and controls illustrated in the walkthrough. For
example, you might want to:
Create additional users and define roles (groups) such as managers, sales, or members and assign users to different
roles. For details, see Walkthrough: Managing Web Site Users with Roles.
Change the membership provider from the default Access provider to a SQL provider. Storing membership information
in an Access database is suitable for small to medium-sized sites, but if your site will experience heavy traffic, you will
want to use Microsoft SQL Server as the membership store. For more information, see
Web Site Administration Tool Provider Tab and Creating the Application Services Database for SQL Server.
Change the appearance of login controls. The Login, PasswordRecovery, and CreateUserWizard controls all support
templates, which allows you to configure the text and buttons they contain as well as change the color, font, and other
appearance characteristics of the controls. For more information, see the topics in the Login ASP.NET Controls section.
Create rules that limit access to pages or folders not only for anonymous users, but for specific users or roles.
Combine membership with profile properties, which allows you to store user-specific settings for each user. For details,
see Walkthrough: Maintaining Web Site User Information with Profile Properties.
Combine login controls with master pages. Master pages allow you to define a page layout that you can use for all the
pages in your application. For details, see
Walkthrough: Creating and Using ASP.NET Master Pages in Visual Web Developer.
Add the ability to recover a forgotten password. For more information, see
How to: Enable User Password Recovery Using the ASP.NET PasswordRecovery Control.
See Also
Concepts
Introduction to Membership
ASP.NET

Comparison of Membership with Windows or Passport


Authentication
The ASP.NET membership system is primarily designed to be used with ASP.NET login controls and with
Forms Authentication Provider. That is, the membership system is most useful in applications where you get user credentials in
your application and need to validate them. However, you can use ASP.NET membership with any custom authentication
system.
Windows and Passport Authentication
In ASP.NET Web applications, you can also use Windows authentication or Passport authentication. In Windows authentication,
your application does not need to perform authentication; Windows validates user credentials when the user accesses a Web
application that is configured to use Windows authentication. You can access the user-identification and authentication status
with the WindowsIdentity class. In Passport authentication, user credentials are validated against a centralized store available
to any Passport-enabled Web site. You can get the user's name and authentication status using the PassportIdentity class.
For more information about selecting an authentication strategy, see ASP.NET Authentication.
See Also
Concepts
Introduction to Membership
Other Resources
Managing Users by Using Membership
ASP.NET Web Application Security
ASP.NET

Membership Classes
ASP.NET Membership consists of a set of classes and interfaces that create and manage users and authenticate users based on
credentials that they supply. The following table shows the membership classes and the interfaces and functions that they
provide.
ASP.NET Membership Classes and Descriptions
The following table lists the classes that are used by ASP.NET Membership and their functions.
Class/Interface Functions
Membership Creates a new user.
Provides general membership facilitie Deletes a user.
s.
Updates a user with new information.
Returns a list of users.
Finds a user by name or e-mail.
Validates (authenticates) a user.
Gets the number of users online.
Searches for users by username or e-mail address.

MembershipUser Gets the password and password question.


Provides information about a specific Changes the password.
user.
Determines whether the user is online.
Determines whether the user is validated.
Returns the date for last activity, login, and password change.
Unlocks a user.

MembershipProvider Defines the methods and properties that a provider used by membership is required to
implement.
Defines functionality for data provider
s that can be used by the membership
system.

MembershipProviderCollection Returns a collection of all the available providers.

MembershipUserCollection Stores references to MembershipUser objects.

MembershipCreateStatus Provides descriptive values for success or failure when creating a new membership use
r.

MembershipCreateUserException Defines the exception thrown if a user cannot be created. A MembershipCreateStatus


enumeration value describing the reason for the exception is available through the
StatusCode property.

MembershipPasswordFormat Specifies the possible password storage formats used by the membership providers inc
luded with ASP.NET (Clear, Hashed, Encrypted).

See Also
Concepts
Securing Membership
Other Resources
Managing Users by Using Membership
ASP.NET

Membership Providers
By using a provider model, you can easily adapt the membership system to use different data stores or data stores with
different schemas. In addition, you can extend the membership system by creating a custom provider, which you might do to
create an interface between the membership system and an existing user database.
An important feature of the tiered membership model is that applications that use the membership system are not bound to a
specific data store. If necessary, you can switch the underlying membership data store in your application without changing
any application code by simply configuring the application to use a different membership provider. (And of course by
migrating any existing user information, if applicable.) For example, if you already have a database containing user
information, a provider can be written to take advantage of that data and the Membership APIs can then invoke that provider
to perform membership tasks.
ASP.NET ships with two membership providers: one that uses Microsoft SQL Server as a data source and another that uses
Windows Active Directory. Third parties might make membership providers available for other databases, such as Oracle, or
for SQL Server databases that have a different schema than that used by ASP.NET providers.
You can also configure multiple membership providers, which allows you to select a membership provider at run time based
on application requirements. For example, for business reasons your membership information might be in separate regional
databases. By configuring multiple membership providers that each interact with a different regional database, you can direct
membership calls to the appropriate provider for different users.
Custom Membership Providers
It is also possible to create a custom membership provider, which you might do to link the membership system to a user
database that already exists, connect to a database not supported by the providers that are included with ASP.NET, or extend
membership to expose more features.
Once you have a custom membership provider, you can configure your application to use that provider in the same way that
you configure the application to use an ASP.NET provider. The Membership class will automatically invoke your custom
provider to communicate with your authentication data source.
For details on creating a custom membership provider, see Implementing a Membership Provider. Also see the
Sample Membership Provider Implementation.
See Also
Other Resources
Managing Users by Using Membership
ASP.NET Web Site Security (Visual Studio)
ASP.NET

Configuring an ASP.NET Application to Use Membership


ASP.NET Membership is configured using the membership element in the Web.config file for your application. The
membership element is a sub-element of the system.web section. You can enable ASP.NET Membership for an application
by directly editing the Web.config file for that application, or you can use the Web Site Administration Tool, which provides a
wizard-based interface. As part of membership configuration, you specify:
Which membership provider (or providers) to use. (This typically also specifies what database to store membership
information in.)
Password options such as encryption and whether to support password recovery based on a user-specific question.
Users and passwords. If you are using the Web Site Administration Tool, you can create and manage users directly.
Otherwise, you must call membership functions to create and manage users programmatically.
For an example of configuring ASP.NET Membership using the Web Site Administration Tool, see
Walkthrough: Creating a Web Site with Membership and User Login (Visual Studio).
Specifying the Default Provider
You specify the default membership provider using the defaultProvider attribute of the membership element. The machine
configuration specifies a SqlMembershipProvider instance named "AspNetSqlMembershipProvider" that is identified as the
default provider if you do not specify a default provider explicitly. The "AspNetSqlMembershipProvider" connects to the
aspnetdb database in the local SQL Server.
Note
You need to set up the database used by the SqlMembershipProvider before using it in an application. For details, see
Creating and Configuring the Application Services Database for SQL Server.

You can also specify the default provider instance and options for that provider by configuring a provider in the membership
section. You use the providers element to identify a provider to add to the collection of providers available for the application.
You can identify your provider instance as the default provider by using the value of the name attribute as the
defaultProvider value. When you specify a provider instance, you must also specify a valid connection string for that instance
by using the connectionStrings section of the configuration. For example, the following Web.config file identifies a
SqlMembershipProvider instance that connects to a SQL Server other than the local server.

<configuration>
<connectionStrings>
<add name="MySqlConnection" connectionString="Data
Source=MySqlServer;Initial Catalog=aspnetdb;Integrated
Security=SSPI;" />
</connectionStrings>
<system.web>
<authentication mode="Forms" >
<forms loginUrl="login.aspx"
name=".ASPXFORMSAUTH" />
</authentication>
<authorization>
<deny users="?" />
</authorization>
<membership defaultProvider="SqlProvider" userIsOnlineTimeWindow="15">
<providers>
<clear />
<add
name="SqlProvider"
type="System.Web.Security.SqlMembershipProvider"
connectionStringName="MySqlConnection"
applicationName="MyApplication"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="true"
requiresUniqueEmail="true"
passwordFormat="Hashed" />
</providers>
</membership>
</system.web>
</configuration>

See Also
Other Resources
Managing Users by Using Membership
ASP.NET Web Site Security (Visual Studio)
ASP.NET

Securing Membership
ASP.NET membership provides functionality for managing and authenticating users and is most commonly used with Forms
authentication and authentication controls such as the Login, LoginView, LoginStatus, LoginName, PasswordRecovery, and
CreateUserWizard controls. This topic describes how to optimize the security of the membership feature through best practices
in configuring a Web site and coding with the membership classes.
While following these best practices can improve the security of your application, it is also important that you continually keep
your application server up to date with the latest security patches for Microsoft Windows and Internet Information Services
(IIS), as well as any patches for Microsoft SQL Server or other membership data sources.
For more detailed information about best practices for writing secure code and securing applications, see the book "Writing
Secure Code" by Michael Howard and David LeBlanc and the guidance provided by Microsoft Patterns and Practices
(http://www.microsoft.com/resources/practices/default.mspx).
Secure Membership Configuration
The membership feature is enabled by default for ASP.NET applications and cannot be disabled. The default configuration
settings are set to the most secure values. For information about membership configuration settings and their default values,
see membership Element (ASP.NET Settings Schema). You should set the requiresQuestionAndAnswer attribute to true,
especially where enablePasswordReset or enablePasswordRetrieval is likewise true.
Securing Configuration Values
When storing sensitive information in a configuration file for an application, you should encrypt the sensitive values using
Protected Configuration. Information that is especially sensitive includes the encryption keys stored in the machineKey
configuration element and connection strings to a data source stored in the connectionStrings configuration element. For more
information, see Encrypting Configuration Information Using Protected Configuration.
Secure Encryption Keys and Hashing
It is highly recommended that you encrypt user passwords in the membership data source using a passwordFormat attribute
set to Hashed or Encrypted, where Hashed is the most secure format. The encryption key values for the specified encryption
algorithm are stored in the machineKey configuration element. For strong encryption, specify an encryption key that is a
randomly generated value of the appropriate length for the selected encryption algorithm.
On a server that hosts multiple applications, it is recommended that you define unique encryption keys for each application. A
less secure alternative is to define a single encryption key and specify the IsolateApps option with the key.
You can set the machine configuration on a host server to deny applications from overriding configuration settings. This
includes denying the ability for encryption keys to be redefined in the Web.config file for an application.
Securing Connections to a Membership Data Source
Connection Strings
To keep the connection to your database server secure, you should encrypt connection-string information in the configuration
using Protected Configuration. For more information, see Encrypting Configuration Information Using Protected Configuration.
Connecting to SQL Server using Integrated Security
You should connect to computers running SQL Server using Integrated Security to avoid the possibility of your connection
string being compromised and your user ID and password being exposed. When you specify a connection that uses Integrated
Security to connect to a computer running SQL Server, the membership feature reverts to the identity of the process. You
should ensure that the identity of the process running ASP.NET (for example, the application pool) is the default process
account or a restricted user account. For more information, see ASP.NET Impersonation.
SQL Server Database Permissions
The SQL Server database that is used to store the user information for membership includes database roles and views that
enable you to restrict user access to only the required capabilities and visibility. You should assign the minimum necessary
privileges to a user ID that connects to the SQL Server membership database. For more information, see
Roles and Views in the Application Services Database for SQL Server.
SQL Server Express Worker Process Identity
SQL Server Express 2005 includes a new mode of operation where it can start a worker process running as the identity of the
connecting user. This capability is referred to as "run as user" mode. Although this mode of operation is suitable for desktop
development when using IIS, starting worker processes is not appropriate on Web servers hosting multiple, untrusted
customer codebases. Shared hosting servers that contain applications that do no trust each other should explicitly disable the
"run as user" functionality. This functionality can be turned off by connecting to the SQL Express instance (for example, osql –E
–S .\sqlexpress) and issuing the following Transact-SQL command.
EXEC sp_configure 'show advanced option', '1'
GO
RECONFIGURE WITH OVERRIDE
GO
EXEC sp_configure 'user instances enabled', 0
GO
RECONFIGURE WITH OVERRIDE
GO

Secure Web Pages that Use Membership


Application pages that work with sensitive data, such as logon pages, should be secured using standard Web-security
mechanisms. These include measures such as using Secure Sockets Layer (SSL) and requiring that users be logged on to carry
out sensitive operations like updating user information or deleting users.
Additionally, pages should not expose sensitive feature data such as passwords, and in some cases user names, in clear text.
Ensure that pages that display such information make use of SSL and are available only to authenticated users. Also, avoid
storing sensitive feature data in cookies or sending it across insecure connections.
Securing Against Denial of Service Attacks
Methods that perform updates or large search operations can reduce the responsiveness of your membership data source if
called concurrently by a number of clients. To reduce exposure to a denial of service attack, restrict access to ASP.NET pages
that use methods that perform database updates or searches to administrative users, and expose only ASP.NET pages that
provide validation and password management for general use.
Error Messages and Events
Exceptions
To prevent sensitive information from being exposed to unwanted sources, configure your application either to not display
detailed error messages or to display detailed error messages only when the client is the Web server itself. For more
information, see customErrors Element (ASP.NET Settings Schema).
Event Log
If your server is running Windows Server 2003, you can improve the security of your application by securing the event log, and
by setting parameters regarding the size, retention, and so on of the event log to prevent an indirect denial of service attack
against it.
Health Monitoring
Successful and failed logon attempts are logged using the ASP.NET health-monitoring feature. In the default configuration, this
means failed login attempts will record user-name and other diagnostic information in the Application event log. Ensure that
access to the event log is restricted to keep this information private.
Custom Membership Providers
When creating a custom membership provider, ensure that you follow security best practices to avoid attacks such as SQL-
injection attacks when working with a database. When making use of a custom membership provider, ensure that the provider
has been reviewed for security best practices.
Working with Culture-Sensitive Characters
When using the SQL Server membership provider or a custom membership provider, your data source might be configured to
store membership data in a culture sensitive format. However, ASP.NET evaluates user names from the authorization
configuration element and user names from the membership data store as culture invariant. As a result, an unauthorized user
could be granted authorization because when the user name is treated as culture invariant, it is the same as the name of an
authorized user.
To avoid users gaining unauthorized access, ensure that user names are unique when evaluated as culture invariant.
Alternatively, you can specify only role names for authorization using the authorization configuration element and then ensure
that role names are unique when evaluated as culture invariant. Specifying authorization using role names is often preferred,
because creating and managing roles can be restricted as an administrative function.
See Also
Other Resources
Managing Users by Using Membership
ASP.NET Web Site Security (Visual Studio)
ASP.NET

Implementing a Membership Provider


ASP.NET membership is designed to enable you to easily use a number of different membership providers for your ASP.NET
applications. You can use the supplied membership providers that are included with the .NET Framework, or you can
implement your own providers.
There are two primary reasons for creating a custom membership provider.
You need to store membership information in a data source that is not supported by the membership providers included
with the .NET Framework, such as a FoxPro database, an Oracle database, or other data sources.
You need to manage membership information using a database schema that is different from the database schema used
by the providers that ship with the .NET Framework. A common example of this would be membership data that already
exists in a SQL Server database for a company or Web site.
Required Classes
To implement a membership provider, you create a class that inherits the MembershipProvider abstract class from the
System.Web.Security namespace. The MembershipProvider abstract class inherits the ProviderBase abstract class from the
System.Configuration.Provider namespace, so you must implement the required members of the ProviderBase class as well.
The following tables list the required properties and methods that you must implement from the ProviderBase and
MembershipProvider abstract classes and a description of each. To review an implementation of each member, see the code
supplied for the Sample Membership Provider Implementation.
Required ProviderBase Members
Memb Description
er
Initialize Takes, as input, the name of the provider and a NameValueCollection of configuration settings. Used to set property v
method alues for the provider instance including implementation-specific values and options specified in the configuration fil
e (Machine.config or Web.config) supplied in the configuration.
Required MembershipProvider Members
Member Description
EnablePasswordReset proper A Boolean value specified in the configuration file (Web.config).
ty
The EnablePasswordReset property indicates whether users can use the ResetPassword meth
od to overwrite their current password with a new, randomly generated password.
This property is read-only.

EnablePasswordRetrieval pro A Boolean value specified in the configuration file (Web.config).


perty
The EnablePasswordRetrieval property indicates whether users can retrieve their password us
ing the GetPassword method.
This property is read-only.

RequiresQuestionAndAnswer A Boolean value specified in the configuration file (Web.config).


property
The RequiresQuestionAndAnswer property indicates whether users must supply a password
answer in order to retrieve their password using the GetPassword method, or reset their passw
ord using the ResetPassword method.
This property is read-only.
RequiresUniqueEmail propert A Boolean value specified in the configuration file (Web.config).
y
The RequiresUniqueEmail property indicates whether users must supply a unique e-mail addr
ess value when creating a user. If a user already exists in the data source for the current
ApplicationName, then the CreateUser method returns null (Nothing in Visual Basic) and a stat
us value of DuplicateEmail.
This property is read-only.

PasswordFormat property A MembershipPasswordFormat value specified in the configuration file (Web.config).


The PasswordFormat property indicates the format that passwords are stored in. Passwords ca
n be stored in Clear, Encrypted, and Hashed password formats. Clear passwords are stored in
plain text, which improves the performance of password storage and retrieval but is less secure,
as passwords are easily read if your data source is compromised. Encrypted passwords are enc
rypted when stored and can be decrypted for password comparison or password retrieval. This r
equires additional processing for password storage and retrieval but is more secure, as passwor
ds are not easily determined if the data source is compromised. Hashed passwords are hashed
using a one-way hash algorithm and a randomly generated salt value when stored in the databa
se. When a password is validated, it is hashed with the salt value in the database for verification.
Hashed passwords cannot be retrieved.
You can use the EncryptPassword and DecryptPassword virtual methods of the MembershipPr
ovider class to encrypt and decrypt password values, or you can supply your own encryption co
de. If you use the EncryptPassword and DecryptPassword virtual methods of the Membershi
pProvider class, Encrypted passwords are encrypted using the key information supplied in the
machineKey Element (ASP.NET Settings Schema) in your configuration.
This property is read-only.

MaxInvalidPasswordAttempts An Integer value specified in the configuration file (Web.config).


property
The MaxInvalidPasswordAttempts works in conjunction with the PasswordAttemptWindow to g
uard against an unwanted source guessing the password or password answer of a membership
user through repeated attempts. If the number of invalid passwords or password questions sup
plied for a membership user exceeds the MaxInvalidPasswordAttempts within the number of
minutes identified by the PasswordAttemptWindow, then the membership user is locked out
by setting the IsLockedOut property to true until the user is unlocked using the UnlockUser met
hod. If a valid password or password answer is supplied before the MaxInvalidPasswordAtte
mpts is reached, the counter that tracks the number of invalid attempts is reset to zero.
If the RequiresQuestionAndAnswer property is set to false, invalid password answer attempts a
re not tracked.
Invalid password and password answer attempts are tracked in the ValidateUser,
ChangePassword, ChangePasswordQuestionAndAnswer, GetPassword, and ResetPassword m
ethods.
This property is read-only.

PasswordAttemptWindow pr An Integer value specified in the configuration file (Web.config).


operty
For a description, see the description of the MaxInvalidPasswordAttempts property.
This property is read-only.

ApplicationName property The name of the application using the membership information specified in the configuration fil
e (Web.config). The ApplicationName is stored in the data source with related user informatio
n and used when querying for that information. See the section on the ApplicationName later
in this topic for more information.
This property is read/write and defaults to the ApplicationPath if not specified explicitly.
CreateUser method Takes, as input, the name of a new user, a password, and an e-mail address and inserts a new us
er for the application into the data source. The CreateUser method returns a MembershipUser
object populated with the information for the newly created user. The CreateUser method also
defines an out parameter (in Visual Basic, you can use ByRef) that returns a
MembershipCreateStatus value that indicates whether the user was successfully created, or a re
ason that the user was not successfully created.
The CreateUser method raises the ValidatingPassword event, if a
MembershipValidatePasswordEventHandler has been specified, and continues or cancels the cre
ate-user action based on the results of the event. You can use the OnValidatingPassword virtual
method to execute the specified MembershipValidatePasswordEventHandler.

UpdateUser method Takes, as input, a MembershipUser object populated with user information and updates the da
ta source with the supplied values.

DeleteUser method Takes, as input, the name of a user and deletes that user's information from the data source. The
DeleteUser method returns true if the user was successfully deleted; otherwise, false. An additi
onal Boolean parameter is included to indicate whether related information for the user, such a
s role or profile information is also deleted.

ValidateUser method Takes, as input, a user name and a password and verifies that the values match those in the data
source. The ValidateUser method returns true for a successful user name and password match
; otherwise, false.

GetUser method Takes, as input, a unique user identifier and a Boolean value indicating whether to update the
LastActivityDate value for the user to show that the user is currently online. The GetUser metho
d returns a MembershipUser object populated with current values from the data source for the
specified user. If the user name is not found in the data source, the GetUser method returns nul
l (Nothing in Visual Basic).

GetUser method Takes, as input, a user name and a Boolean value indicating whether to update the LastActivit
yDate value for the user to show that the user is currently online. The GetUser method returns
a MembershipUser object populated with current values from the data source for the specified
user. If the user name is not found in the data source, the GetUser method returns null (Nothi
ng in Visual Basic).

GetAllUsers method Returns a MembershipUserCollection populated with MembershipUser objects for all of the us
ers in the data source.
The results returned by GetAllUsers are constrained by the pageIndex and pageSize parameter
s. The pageSize parameter identifies the maximum number of MembershipUser objects to retu
rn in the MembershipUserCollection. The pageIndex parameter identifies which page of resul
ts to return, where 1 identifies the first page. The totalRecords parameter is an out parameter th
at is set to the total number of membership users. For example, if 13 users were in the database
for the application, and the pageIndex value was 2 with a pageSize of 5, the MembershipUserC
ollection returned would contain the sixth through the tenth users returned. totalRecords woul
d be set to 13.

GetNumberOfUsersOnline m Returns an integer value that is the count of all the users in the data source where the LastActiv
ethod ityDate is greater than the current date and time minus the UserIsOnlineTimeWindow property.
The UserIsOnlineTimeWindow property is an integer value specifying the number of minutes
to use when determining whether a user is online.
ResetPassword method Takes, as input, a user name and a password answer and generates a new, random password for
the specified user. The ResetPassword method updates the user information in the data source
with the new password value and returns the new password as a string. A convenient mechanis
m for generating a random password is the GeneratePassword method of the Membership clas
s.
The ResetPassword method ensures that the EnablePasswordReset property is set to true be
fore performing any action. If the EnablePasswordReset property is false, a
NotSupportedException is thrown. The ResetPassword method also checks the value of the Re
quiresQuestionAndAnswer property. If the RequiresQuestionAndAnswer property is true, t
he ResetPassword method checks the value of the supplied answer parameter against the stor
ed password answer in the data source. If they do not match, a MembershipPasswordException i
s thrown.
The ResetPassword method raises the ValidatingPassword event, if a MembershipValidate
PasswordEventHandler has been specified, to validate the newly generated password and con
tinues or cancels the reset-password action based on the results of the event. You can use the O
nValidatingPassword virtual method to execute the specified MembershipValidatePasswor
dEventHandler.

GetPassword method Takes, as input, a user name and a password answer and retrieves the password for that user fro
m the data source and returns the password as a string.
GetPassword ensures that the EnablePasswordRetrieval property is set to true before perfor
ming any action. If the EnablePasswordRetrieval property is false, an ProviderException is thr
own.
The GetPassword method also checks the value of the RequiresQuestionAndAnswer propert
y. If the RequiresQuestionAndAnswer property is true, the GetPassword method checks the
value of the supplied answer parameter against the stored password answer in the data source.
If they do not match, a MembershipPasswordException is thrown.

GetUserNameByEmail metho Takes, as input, an e-mail address and returns the first user name from the data source where th
d e e-mail address matches the supplied email parameter value.
If no user name is found with a matching e-mail address, an empty string is returned.
If multiple user names are found that match a particular e-mail address, only the first user name
found is returned.

ChangePassword method Takes, as input, a user name, a current password, and a new password, and updates the passwor
d in the data source if the supplied user name and current password are valid. The ChangePass
word method returns true if the password was updated successfully; otherwise, false.
The ChangePassword method raises the ValidatingPassword event, if a MembershipValida
tePasswordEventHandler has been specified, and continues or cancels the change-password a
ction based on the results of the event. You can use the OnValidatingPassword virtual method
to execute the specified MembershipValidatePasswordEventHandler.

ChangePasswordQuestion Takes, as input, a user name, a password, a password question, and a password answer, and upd
AndAnswer method ates the password question and answer in the data source if the supplied user name and passw
ord are valid. The ChangePasswordQuestionAndAnswer method returns true if the passwor
d question and answer are updated successfully; otherwise, false.
If the supplied user name and password are not valid, false is returned.
FindUsersByName method Returns a list of membership users where the user name contains a match of the supplied usern
ameToMatch for the configured ApplicationName. For example, if the usernameToMatch para
meter is set to "user," then the users "user1," "user2," "user3," and so on are returned. Wildcard
support is included based on the data source. Users are returned in alphabetical order by user n
ame.
The results returned by FindUsersByName are constrained by the pageIndex and pageSize par
ameters. The pageSize parameter identifies the number of MembershipUser objects to return i
n the MembershipUserCollection. The pageIndex parameter identifies which page of results t
o return, where 1 identifies the first page. The totalRecords parameter is an out parameter that i
s set to the total number of membership users that matched the usernameToMatch value. For ex
ample, if 13 users were found where usernameToMatch matched part of or the entire user nam
e, and the pageIndex value was 2 with a pageSize of 5, then the MembershipUserCollection w
ould contain the sixth through the tenth users returned. totalRecords would be set to 13.

FindUsersByEmail method Returns a list of membership users where the user name contains a match of the supplied email
ToMatch for the configured ApplicationName. For example, if the emailToMatch parameter is
set to "address@example.com," then users with the e-mail addresses "address1@example.com,"
"address2@example.com," and so on are returned. Wildcard support is included based on the d
ata source. Users are returned in alphabetical order by user name.
The results returned by FindUsersByEmail are constrained by the pageIndex and pageSize par
ameters. The pageSize parameter identifies the number of MembershipUser objects to return i
n the MembershipUserCollection collection. The pageIndex parameter identifies which page o
f results to return, where 1 identifies the first page. The totalRecords parameter is an out parame
ter that is set to the total number of membership users that matched the emailToMatch value. F
or example, if 13 users were found where emailToMatch matched part of or the entire user nam
e, and the pageIndex value was 2 with a pageSize of 5, then the MembershipUserCollection w
ould contain the sixth through the tenth users returned. totalRecords would be set to 13.

UnlockUser method Takes, as input, a user name, and updates the field in the data source that stores the IsLockedO
ut property to false. The UnlockUser method returns true if the record for the membership us
er is updated successfully; otherwise false.

ApplicationName
Membership providers store user information uniquely for each application. This enables multiple ASP.NET applications to use
the same data source without running into a conflict if duplicate user names are created. Alternatively, multiple ASP.NET
applications can use the same user data source by specifying the same ApplicationName.
Because membership providers store user information uniquely for each application, you will need to ensure that your data
schema includes the application name and that queries and updates also include the application name. For example, the
following command is used to retrieve a user name from a database, based on the e-mail address, and ensures that the
ApplicationName is included in the query.

SELECT Username FROM MyUserTable


WHERE Email = 'someone@example.com' AND ApplicationName = 'MyApplication'

Custom Members
You may need to extend the membership provider interfaces with additional functionality not provided by the ProviderBase
and MembershipProvider abstract classes. Any public members that you add to your membership provider will be accessible
using the Provider or Providers property of the Membership class.
An example of this could be a LockUser method that sets the IsLockedOut property to true. The following example shows
how to cast the Provider property, which exposes the default membership provider for an application, as a custom-provider
type in order to call the custom LockUser method.
VB
Dim p As MyCustomProvider = CType(Membership.Provider, MyCustomProvider)
p.LockUser(username)
C#
MyCustomProvider p = (MyCustomProvider)Membership.Provider;
p.LockUser(username);

Thread Safety
For each membership provider specified in the configuration for an application, ASP.NET instantiates a single membership
provider instance that is used for all of the requests served by an HttpApplication object. As a result, you can have multiple
requests executing concurrently. ASP.NET does not ensure the thread safety of calls to your provider. You will need to write
your provider code to be thread safe. For example, creating a connection to a database or opening a file for editing should be
done within the member that is called, such as CreateUser, rather than opening a file or database connection when the
Initialize method is called.
See Also
Reference
ValidatePasswordEventArgs
OnValidatingPassword
Concepts
Sample Membership Provider Implementation
Securing ASP.NET Site Navigation
Other Resources
Managing Users by Using Membership
ASP.NET Web Site Security
ASP.NET

Sample Membership Provider Implementation


Describes the sample membership providers and their supported data source schema.
The following topics include the code for a sample membership provider implementation. The sample provider uses the .NET
Framework Data Provider for ODBC to connect to an ODBC data source. The sample uses an Access database as its data
source.
This topic describes implementation details about the sample membership provider and describes how to build the sample
and configure an ASP.NET application to use the sample provider.
Note
Because data sources contain differing SQL syntax, some commands will work with one data source and not with another. Th
erefore, you should create a membership provider specific to your data source even if you are using the .NET Framework Dat
a Provider for ODBC or the .NET Framework Data Provider for OLEDB to access your data source, for example, SybaseMemb
ershipProvider, OracleMembershipProvider, and so on.

There are two versions of the sample provider included: one in Visual Basic and another in C#. Sample code can be found in
How to: Sample Membership Provider Implementation.
Database Schema
To create the Access table used by the sample provider, issue the following data-definition query in a new or existing Access
database.

CREATE TABLE Users


(
PKID Guid NOT NULL PRIMARY KEY,
Username Text (255) NOT NULL,
ApplicationName Text (255) NOT NULL,
Email Text (128) NOT NULL,
Comment Text (255),
Password Text (128) NOT NULL,
PasswordQuestion Text (255),
PasswordAnswer Text (255),
IsApproved YesNo,
LastActivityDate DateTime,
LastLoginDate DateTime,
LastPasswordChangedDate DateTime,
CreationDate DateTime,
IsOnLine YesNo,
IsLockedOut YesNo,
LastLockedOutDate DateTime,
FailedPasswordAttemptCount Integer,
FailedPasswordAttemptWindowStart DateTime,
FailedPasswordAnswerAttemptCount Integer,
FailedPasswordAnswerAttemptWindowStart DateTime
)

Event Log Access


If the sample provider encounters an exception when working with the data source, it writes the details of the exception to the
application event log instead of returning the exception to the ASP.NET application. This is done as a security measure to
prevent private information about the data source from being exposed in the ASP.NET application.
The sample provider specifies an event Source of "OdbcMembershipProvider." Before your ASP.NET application will be able to
write to the Application Event Log successfully, you will need to create the following registry key.
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application\OdbcMembershipProvider
If you do not want the sample provider to write exceptions to the event log, then you can set the
writeExceptionsToEventLog attribute to false in the Web.config file.
Building the Sample Provider
In order to use the sample provider, you can place your source code in the App_Code directory of your application. Note that if
you already have source code in the App_Code directory of your application, you must add the version of the sample provider
that is written in the same language as the existing code in the directory. The provider will be compiled by ASP.NET when your
application is requested.
You can also compile the sample provider as a library and place it in the Bin directory of your Web application, or strongly
name it and place it in the GAC. The following command shows how to compile the sample provider using the command-line
compiler.
VB
vbc /out:OdbcMembershipProvider.dll /t:library OdbcMembershipProvider.vb /r:System.Web.dll
/r:System.Configuration.dll

C#
csc /out:OdbcMembershipProvider.dll /t:library OdbcMembershipProvider.cs /r:System.Web.dll
/r:System.Configuration.dll

Using the Sample Provider in an ASP.NET Application


The following example shows the Web.config file for an ASP.NET application configured to use the sample provider. The
configuration file assumes the existence of two files, CreateUser.aspx and RetrievePassword.aspx. The two files are accessible to
all users, even those who are logged in.
The example uses an ODBC DSN named "MembershipUsers" to obtain connection information for the Access database. To use
the sample provider, you will need to either create the "MembershipUsers" System DSN or supply a valid ODBC connection
string to your database.

<configuration>

<location path="CreateUser.aspx">
<system.web>
<authorization>
<allow users="?" />
</authorization>
</system.web>
</location>
<location path="RetrievePassword.aspx">
<system.web>
<authorization>
<allow users="?" />
</authorization>
</system.web>
</location>
<connectionStrings>
<add name="OdbcServices" connectionString="DSN=MembershipUsers;" />
</connectionStrings>

<system.web>

<authentication mode="Forms" >


<forms loginUrl="login.aspx"
name=".ASPXFORMSAUTH" />
</authentication>

<authorization>
<deny users="?" />
</authorization>
<machineKey
validationKey="C50B3C89CB21F4F1422FF158A5B42D0E8DB8CB5CDA1742572A487D9401E3400267682B
202B746511891C1BAF47F8D25C07F6C39A104696DB51F17C529AD3CABE"
decryptionKey="8A9BE8FD67AF6979E7D20198CFEA50DD3D3799C77AF2B72F"
validation="SHA1" />
<membership defaultProvider="OdbcProvider" userIsOnlineTimeWindow="15">

<providers>

<add
name="OdbcProvider"
type="Samples.AspNet.Membership.OdbcMembershipProvider"
connectionStringName="OdbcServices"
enablePasswordRetrieval="true"
enablePasswordReset="true"
requiresQuestionAndAnswer="true"
writeExceptionsToEventLog="true" />

</providers>
</membership>
</system.web>
</configuration>

See Also
Concepts
Implementing a Membership Provider
Other Resources
Managing Users by Using Membership
ASP.NET

How to: Sample Membership Provider Implementation


Illustrates a complete ODBC-based membership provider.
The following code illustrates a complete ODBC-based membership provider.
Example
VB
Imports System.Web.Security
Imports System.Configuration.Provider
Imports System.Collections.Specialized
Imports System
Imports System.Data
Imports System.Data.Odbc
Imports System.Configuration
Imports System.Diagnostics
Imports System.Web
Imports System.Globalization
Imports System.Security.Cryptography
Imports System.Text
Imports System.Web.Configuration

'
' This provider works with the following schema for the table of user data.
'
' CREATE TABLE Users
' (
' PKID Guid NOT NULL PRIMARY KEY,
' Username Text (255) NOT NULL,
' ApplicationName Text (255) NOT NULL,
' Email Text (128) NOT NULL,
' Comment Text (255),
' Password Text (128) NOT NULL,
' PasswordQuestion Text (255),
' PasswordAnswer Text (255),
' IsApproved YesNo,
' LastActivityDate DateTime,
' LastLoginDate DateTime,
' LastPasswordChangedDate DateTime,
' CreationDate DateTime,
' IsOnLine YesNo,
' IsLockedOut YesNo,
' LastLockedOutDate DateTime,
' FailedPasswordAttemptCount Integer,
' FailedPasswordAttemptWindowStart DateTime,
' FailedPasswordAnswerAttemptCount Integer,
' FailedPasswordAnswerAttemptWindowStart DateTime
' )
'
Namespace Samples.AspNet.Membership

Public NotInheritable Class OdbcMembershipProvider


Inherits MembershipProvider

'
' Global generated password length, generic exception message, event log info.
'

Private newPasswordLength As Integer = 8


Private eventSource As String = "OdbcMembershipProvider"
Private eventLog As String = "Application"
Private exceptionMessage As String = "An exception occurred. Please check the Event Log
."
Private connectionString As String
'
' Used when determining encryption key values.
'
Private machineKey As MachineKeySection

'
' If False, exceptions are thrown to the caller. If True,
' exceptions are written to the event log.
'
Private pWriteExceptionsToEventLog As Boolean

Public Property WriteExceptionsToEventLog As Boolean


Get
Return pWriteExceptionsToEventLog
End Get
Set
pWriteExceptionsToEventLog = value
End Set
End Property

'
' System.Configuration.Provider.ProviderBase.Initialize Method
'

Public Overrides Sub Initialize(name As String, config As NameValueCollection)

'
' Initialize values from web.config.
'

If config Is Nothing Then _


Throw New ArgumentNullException("config")

If name Is Nothing OrElse name.Length = 0 Then _


name = "OdbcMembershipProvider"
If String.IsNullOrEmpty(config("description")) Then
config.Remove("description")
config.Add("description", "Sample ODBC Membership provider")
End If

' Initialize the abstract base class.


MyBase.Initialize(name, config)

pApplicationName = GetConfigValue(config("applicationName"), _
System.Web.Hosting.HostingEnvironment.ApplicationVirt
ualPath)
pMaxInvalidPasswordAttempts = Convert.ToInt32(GetConfigValue(config("maxInvalidPasswo
rdAttempts"), "5"))
pPasswordAttemptWindow = Convert.ToInt32(GetConfigValue(config("passwordAttemptWindow
"), "10"))
pMinRequiredNonAlphanumericCharacters = Convert.ToInt32(GetConfigValue(config("minReq
uiredAlphaNumericCharacters"), "1"))
pMinRequiredPasswordLength = Convert.ToInt32(GetConfigValue(config("minRequiredPasswo
rdLength"), "7"))
pPasswordStrengthRegularExpression = Convert.ToString(GetConfigValue(config("password
StrengthRegularExpression"), ""))
pEnablePasswordReset = Convert.ToBoolean(GetConfigValue(config("enablePasswordReset")
, "True"))
pEnablePasswordRetrieval = Convert.ToBoolean(GetConfigValue(config("enablePasswordRet
rieval"), "True"))
pRequiresQuestionAndAnswer = Convert.ToBoolean(GetConfigValue(config("requiresQuestio
nAndAnswer"), "False"))
pRequiresUniqueEmail = Convert.ToBoolean(GetConfigValue(config("requiresUniqueEmail")
, "True"))
pWriteExceptionsToEventLog = Convert.ToBoolean(GetConfigValue(config("writeExceptions
ToEventLog"), "True"))
Dim temp_format As String = config("passwordFormat")
If temp_format Is Nothing Then
temp_format = "Hashed"
End If

Select Case temp_format


Case "Hashed"
pPasswordFormat = MembershipPasswordFormat.Hashed
Case "Encrypted"
pPasswordFormat = MembershipPasswordFormat.Encrypted
Case "Clear"
pPasswordFormat = MembershipPasswordFormat.Clear
Case Else
Throw New ProviderException("Password format not supported.")
End Select
'
' Initialize OdbcConnection.
'

Dim ConnectionStringSettings As ConnectionStringSettings = _


ConfigurationManager.ConnectionStrings(config("connectionStringName"))

If ConnectionStringSettings Is Nothing OrElse ConnectionStringSettings.ConnectionStri


ng.Trim() = "" Then
Throw New ProviderException("Connection string cannot be blank.")
End If

connectionString = COnnectionStringSettings.ConnectionString

' Get encryption and decryption key information from the configuration.
Dim cfg As System.Configuration.Configuration = _
WebConfigurationManager.OpenWebConfiguration(System.Web.Hosting.HostingEnvironment.
ApplicationVirtualPath)
machineKey = CType(cfg.GetSection("system.web/machineKey"), MachineKeySection)

If machineKey.ValidationKey.Contains("AutoGenerate") Then _
If PasswordFormat <> MembershipPasswordFormat.Clear Then _
Throw New ProviderException("Hashed or Encrypted passwords " & _
"are not supported with auto-generated keys.")
End Sub

'
' A helper function to retrieve config values from the configuration file.
'

Private Function GetConfigValue(configValue As String, defaultValue As String) As Strin


g
If String.IsNullOrEmpty(configValue) Then _
Return defaultValue

Return configValue
End Function

'
' System.Web.Security.MembershipProvider properties.
'

Private pApplicationName As String


Private pEnablePasswordReset As Boolean
Private pEnablePasswordRetrieval As Boolean
Private pRequiresQuestionAndAnswer As Boolean
Private pRequiresUniqueEmail As Boolean
Private pMaxInvalidPasswordAttempts As Integer
Private pPasswordAttemptWindow As Integer
Private pPasswordFormat As MembershipPasswordFormat
Public Overrides Property ApplicationName As String
Get
Return pApplicationName
End Get
Set
pApplicationName = value
End Set
End Property

Public Overrides ReadOnly Property EnablePasswordReset As Boolean


Get
Return pEnablePasswordReset
End Get
End Property

Public Overrides ReadOnly Property EnablePasswordRetrieval As Boolean


Get
Return pEnablePasswordRetrieval
End Get
End Property

Public Overrides ReadOnly Property RequiresQuestionAndAnswer As Boolean


Get
Return pRequiresQuestionAndAnswer
End Get
End Property

Public Overrides ReadOnly Property RequiresUniqueEmail As Boolean


Get
Return pRequiresUniqueEmail
End Get
End Property

Public Overrides ReadOnly Property MaxInvalidPasswordAttempts As Integer


Get
Return pMaxInvalidPasswordAttempts
End Get
End Property

Public Overrides ReadOnly Property PasswordAttemptWindow As Integer


Get
Return pPasswordAttemptWindow
End Get
End Property

Public Overrides ReadOnly Property PasswordFormat As MembershipPasswordFormat


Get
Return pPasswordFormat
End Get
End Property
Private pMinRequiredNonAlphanumericCharacters As Integer

Public Overrides ReadOnly Property MinRequiredNonAlphanumericCharacters() As Integer


Get
Return pMinRequiredNonAlphanumericCharacters
End Get
End Property

Private pMinRequiredPasswordLength As Integer

Public Overrides ReadOnly Property MinRequiredPasswordLength() As Integer


Get
Return pMinRequiredPasswordLength
End Get
End Property
Private pPasswordStrengthRegularExpression As String

Public Overrides ReadOnly Property PasswordStrengthRegularExpression() As String


Get
Return pPasswordStrengthRegularExpression
End Get
End Property

'
' System.Web.Security.MembershipProvider methods.
'

'
' MembershipProvider.ChangePassword
'
Public Overrides Function ChangePassword(username As String, _
oldPwd As String, _
newPwd As String) As Boolean
If Not ValidateUser(username, oldPwd) Then _
Return False

Dim args As ValidatePasswordEventArgs = _


New ValidatePasswordEventArgs(username, newPwd, True)

OnValidatingPassword(args)

If args.Cancel Then
If Not args.FailureInformation Is Nothing Then
Throw args.FailureInformation
Else
Throw New ProviderException("Change password canceled due to New password validat
ion failure.")
End If
End If

Dim conn As OdbcConnection = New OdbcConnection(connectionString)


Dim cmd As OdbcCommand = New OdbcCommand("UPDATE Users " & _
" SET Password = ?, LastPasswordChangedDate = ? " & _
" WHERE Username = ? AND ApplicationName = ?", conn)

cmd.Parameters.Add("@Password", OdbcType.VarChar, 255).Value = EncodePassword(newPwd)


cmd.Parameters.Add("@LastPasswordChangedDate", OdbcType.DateTime).Value = DateTime.No
w
cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicationNam
e
Dim rowsAffected As Integer = 0

Try
conn.Open()

rowsAffected = cmd.ExecuteNonQuery()
Catch e As OdbcException
If WriteExceptionsToEventLog Then

WriteToEventLog(e, "ChangePassword")

Throw New ProviderException(exceptionMessage)


Else
Throw e
End If
Finally
conn.Close()
End Try

If rowsAffected > 0 Then


Return True
End If

Return False
End Function

'
' MembershipProvider.ChangePasswordQuestionAndAnswer
'
Public Overrides Function ChangePasswordQuestionAndAnswer(username As String, _
password As String, _
newPwdQuestion As String, _
newPwdAnswer As String) As Boolean

If Not ValidateUser(username, password) Then _


Return False

Dim conn As OdbcConnection = New OdbcConnection(connectionString)


Dim cmd As OdbcCommand = New OdbcCommand("UPDATE Users " & _
" SET PasswordQuestion = ?, PasswordAnswer = ?" & _
" WHERE Username = ? AND ApplicationName = ?", conn)

cmd.Parameters.Add("@Question", OdbcType.VarChar, 255).Value = newPwdQuestion


cmd.Parameters.Add("@Answer", OdbcType.VarChar, 255).Value = EncodePassword(new
PwdAnswer)
cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicat
ionName

Dim rowsAffected As Integer = 0

Try
conn.Open()

rowsAffected = cmd.ExecuteNonQuery()
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "ChangePasswordQuestionAndAnswer")
Throw New ProviderException(exceptionMessage)
Else
Throw e
End If
Finally
conn.Close()
End Try

If rowsAffected > 0 Then


Return True
End If

Return False
End Function

'
' MembershipProvider.CreateUser
'

Public Overrides Function CreateUser(ByVal username As String, _


ByVal password As String, _
ByVal email As String, _
ByVal passwordQuestion As String, _
ByVal passwordAnswer As String, _
ByVal isApproved As Boolean, _
ByVal providerUserKey As Object, _
ByRef status As MembershipCreateStatus) As MembershipUser

Dim Args As ValidatePasswordEventArgs = _


New ValidatePasswordEventArgs(username, password, True)

OnValidatingPassword(args)

If args.Cancel Then
status = MembershipCreateStatus.InvalidPassword
Return Nothing
End If

If RequiresUniqueEmail AndAlso GetUserNameByEmail(email) <> "" Then


status = MembershipCreateStatus.DuplicateEmail
Return Nothing
End If

Dim u As MembershipUser = GetUser(username, False)

If u Is Nothing Then
Dim createDate As DateTime = DateTime.Now

If providerUserKey Is Nothing Then


providerUserKey = Guid.NewGuid()
Else
If Not TypeOf providerUserKey Is Guid Then
status = MembershipCreateStatus.InvalidProviderUserKey
Return Nothing
End If
End If

Dim conn As OdbcConnection = New OdbcConnection(connectionString)


Dim cmd As OdbcCommand = New OdbcCommand("INSERT INTO Users " & _
" (PKID, Username, Password, Email, PasswordQuestion, " & _
" PasswordAnswer, IsApproved," & _
" Comment, CreationDate, LastPasswordChangedDate, LastActivityDate,"
& _
" ApplicationName, IsLockedOut, LastLockedOutDate," & _
" FailedPasswordAttemptCount, FailedPasswordAttemptWindowStart, " &
_
" FailedPasswordAnswerAttemptCount, FailedPasswordAnswerAttemptWindo
wStart)" & _
" Values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", con
n)
cmd.Parameters.Add("@PKID", OdbcType.UniqueIdentifier).Value = providerUser
Key
cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username
cmd.Parameters.Add("@Password", OdbcType.VarChar, 255).Value = EncodePasswo
rd(password)
cmd.Parameters.Add("@Email", OdbcType.VarChar, 128).Value = email
cmd.Parameters.Add("@PasswordQuestion", OdbcType.VarChar, 255).Value = pass
wordQuestion
cmd.Parameters.Add("@PasswordAnswer", OdbcType.VarChar, 255).Value = Encode
Password(passwordAnswer)
cmd.Parameters.Add("@IsApproved", OdbcType.Bit).Value = isApproved
cmd.Parameters.Add("@Comment", OdbcType.VarChar, 255).Value = ""
cmd.Parameters.Add("@CreationDate", OdbcType.DateTime).Value = createDate
cmd.Parameters.Add("@LastPasswordChangedDate", OdbcType.DateTime).Value = c
reateDate
cmd.Parameters.Add("@LastActivityDate", OdbcType.DateTime).Value = createDa
te
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pAppl
icationName
cmd.Parameters.Add("@IsLockedOut", OdbcType.Bit).Value = False
cmd.Parameters.Add("@LastLockedOutDate", OdbcType.DateTime).Value = createD
ate
cmd.Parameters.Add("@FailedPasswordAttemptCount", OdbcType.Int).Value = 0
cmd.Parameters.Add("@FailedPasswordAttemptWindowStart", OdbcType.DateTime).
Value = createDate
cmd.Parameters.Add("@FailedPasswordAnswerAttemptCount", OdbcType.Int).Value
= 0
cmd.Parameters.Add("@FailedPasswordAnswerAttemptWindowStart", OdbcType.Date
Time).Value = createDate

Try
conn.Open()

Dim recAdded As Integer = cmd.ExecuteNonQuery()

If recAdded > 0 Then


status = MembershipCreateStatus.Success
Else
status = MembershipCreateStatus.UserRejected
End If
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "CreateUser")
End If

status = MembershipCreateStatus.ProviderError
Finally
conn.Close()
End Try

Return GetUser(username, False)


Else
status = MembershipCreateStatus.DuplicateUserName
End If

Return Nothing
End Function

'
' MembershipProvider.DeleteUser
'

Public Overrides Function DeleteUser(username As String, _


deleteAllRelatedData As Boolean) As Boolean
Dim conn As OdbcConnection = New OdbcConnection(connectionString)
Dim cmd As OdbcCommand = New OdbcCommand("DELETE FROM Users " & _
" WHERE Username = ? AND Applicationname = ?", conn)

cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username


cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicat
ionName

Dim rowsAffected As Integer = 0

Try
conn.Open()

rowsAffected = cmd.ExecuteNonQuery()

If deleteAllRelatedData Then
' Process commands to delete all data for the user in the database.
End If
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "DeleteUser")

Throw New ProviderException(exceptionMessage)


Else
Throw e
End If
Finally
conn.Close()
End Try

If rowsAffected > 0 Then _


Return True

Return False
End Function

'
' MembershipProvider.GetAllUsers
'

Public Overrides Function GetAllUsers(ByVal pageIndex As Integer, _


ByVal pageSize As Integer, _
ByRef totalRecords As Integer) _
As MembershipUserCollection

Dim conn As OdbcConnection = New OdbcConnection(connectionString)


Dim cmd As OdbcCommand = New OdbcCommand("SELECT Count(*) FROM Users " & _
"WHERE ApplicationName = ?", conn)
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = Applicati
onName

Dim users As MembershipUserCollection = New MembershipUserCollection()

Dim reader As OdbcDataReader = Nothing


totalRecords = 0

Try
conn.Open()
totalRecords = CInt(cmd.ExecuteScalar())

If totalRecords <= 0 Then Return users


cmd.CommandText = "SELECT PKID, Username, Email, PasswordQuestion," & _
" Comment, IsApproved, IsLockedOut, CreationDate, LastLoginDate,"
& _
" LastActivityDate, LastPasswordChangedDate, LastLockedOutDate " &
_
" FROM Users " & _
" WHERE ApplicationName = ? " & _
" ORDER BY Username Asc"

reader = cmd.ExecuteReader()

Dim counter As Integer = 0


Dim startIndex As Integer = pageSize * pageIndex
Dim endIndex As Integer = startIndex + pageSize - 1

Do While reader.Read()
If counter >= startIndex Then
Dim u As MembershipUser = GetUserFromReader(reader)
users.Add(u)
End If

If counter >= endIndex Then cmd.Cancel()

counter += 1
Loop
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "GetAllUsers")

Throw New ProviderException(exceptionMessage)


Else
Throw e
End If
Finally
If Not reader Is Nothing Then reader.Close()
conn.Close()
End Try

Return users
End Function

'
' MembershipProvider.GetNumberOfUsersOnline
'

Public Overrides Function GetNumberOfUsersOnline() As Integer

Dim onlineSpan As TimeSpan = New TimeSpan(0, System.Web.Security.Membership.Use


rIsOnlineTimeWindow, 0)
Dim compareTime As DateTime = DateTime.Now.Subtract(onlineSpan)

Dim conn As OdbcConnection = New OdbcConnection(connectionString)


Dim cmd As OdbcCommand = New OdbcCommand("SELECT Count(*) FROM Users " & _
" WHERE LastActivityDate > ? AND ApplicationName = ?", conn)

cmd.Parameters.Add("@CompareDate", OdbcType.DateTime).Value = compareTime


cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicat
ionName

Dim numOnline As Integer = 0

Try
conn.Open()

numOnline = CInt(cmd.ExecuteScalar())
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "GetNumberOfUsersOnline")

Throw New ProviderException(exceptionMessage)


Else
Throw e
End If
Finally
conn.Close()
End Try

Return numOnline
End Function

'
' MembershipProvider.GetPassword
'

Public Overrides Function GetPassword(username As String, answer As String) As String

If Not EnablePasswordRetrieval Then


Throw New ProviderException("Password Retrieval Not Enabled.")
End If

If PasswordFormat = MembershipPasswordFormat.Hashed Then


Throw New ProviderException("Cannot retrieve Hashed passwords.")
End If

Dim conn As OdbcConnection = New OdbcConnection(connectionString)


Dim cmd As OdbcCommand = New OdbcCommand("SELECT Password, PasswordAnswer, IsLo
ckedOut FROM Users " & _
" WHERE Username = ? AND ApplicationName = ?", conn)
cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicat
ionName

Dim password As String = ""


Dim passwordAnswer As String = ""
Dim reader As OdbcDataReader = Nothing

Try
conn.Open()

reader = cmd.ExecuteReader(CommandBehavior.SingleRow)

If reader.HasRows Then
reader.Read()

If reader.GetBoolean(2) Then _
Throw New MembershipPasswordException("The supplied user is locked ou
t.")

password = reader.GetString(0)
passwordAnswer = reader.GetString(1)
Else
Throw New MembershipPasswordException("The supplied user name is not fo
und.")
End If
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "GetPassword")

Throw New ProviderException(exceptionMessage)


Else
Throw e
End If
Finally
If Not reader Is Nothing Then reader.Close()
conn.Close()
End Try

If RequiresQuestionAndAnswer AndAlso Not CheckPassword(answer, passwordAnswer)


Then
UpdateFailureCount(username, "passwordAnswer")

Throw New MembershipPasswordException("Incorrect password answer.")


End If

If PasswordFormat = MembershipPasswordFormat.Encrypted Then


password = UnEncodePassword(password)
End If

Return password
End Function

'
' MembershipProvider.GetUser(String, Boolean)
'

Public Overrides Function GetUser(ByVal username As String, _


ByVal userIsOnline As Boolean) As MembershipUser

Dim conn As OdbcConnection = New OdbcConnection(connectionString)


Dim cmd As OdbcCommand = New OdbcCommand("SELECT PKID, Username, Email, Passwor
dQuestion," & _
" Comment, IsApproved, IsLockedOut, CreationDate, LastLoginDate," & _
" LastActivityDate, LastPasswordChangedDate, LastLockedOutDate" & _
" FROM Users WHERE Username = ? AND ApplicationName = ?", conn)

cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username


cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicat
ionName

Dim u As MembershipUser = Nothing


Dim reader As OdbcDataReader = Nothing

Try
conn.Open()

reader = cmd.ExecuteReader()

If reader.HasRows Then
reader.Read()
u = GetUserFromReader(reader)
If userIsOnline Then
Dim updateCmd As OdbcCommand = New OdbcCommand("UPDATE Users " & _
"SET LastActivityDate = ? " & _
"WHERE Username = ? AND Applicationname = ?", conn)

updateCmd.Parameters.Add("@LastActivityDate", OdbcType.DateTime).Va
lue = DateTime.Now
updateCmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value
= username
updateCmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255)
.Value = pApplicationName

updateCmd.ExecuteNonQuery()
End If
End If
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "GetUser(String, Boolean)")
Throw New ProviderException(exceptionMessage)
Else
Throw e
End If
Finally
If Not reader Is Nothing Then reader.Close()

conn.Close()
End Try

Return u
End Function

'
' MembershipProvider.GetUser(Object, Boolean)
'

Public Overrides Function GetUser(ByVal providerUserKey As Object, _


ByVal userIsOnline As Boolean) As MembershipUser

Dim conn As OdbcConnection = New OdbcConnection(connectionString)


Dim cmd As OdbcCommand = New OdbcCommand("SELECT PKID, Username, Email, Passwor
dQuestion," & _
" Comment, IsApproved, IsLockedOut, CreationDate, LastLoginDate," & _
" LastActivityDate, LastPasswordChangedDate, LastLockedOutDate" & _
" FROM Users WHERE PKID = ?", conn)

cmd.Parameters.Add("@PKID", OdbcType.UniqueIdentifier).Value = providerUserKey

Dim u As MembershipUser = Nothing


Dim reader As OdbcDataReader = Nothing

Try
conn.Open()

reader = cmd.ExecuteReader()

If reader.HasRows Then
reader.Read()
u = GetUserFromReader(reader)

If userIsOnline Then
Dim updateCmd As OdbcCommand = New OdbcCommand("UPDATE Users " & _
"SET LastActivityDate = ? " & _
"WHERE PKID = ?", conn)

updateCmd.Parameters.Add("@LastActivityDate", OdbcType.DateTime).Va
lue = DateTime.Now
updateCmd.Parameters.Add("@PKID", OdbcType.UniqueIdentifier).Value
= providerUserKey

updateCmd.ExecuteNonQuery()
End If
End If
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "GetUser(Object, Boolean)")

Throw New ProviderException(exceptionMessage)


Else
Throw e
End If
Finally
If Not reader Is Nothing Then reader.Close()

conn.Close()
End Try

Return u
End Function

'
' GetUserFromReader
' A helper function that takes the current row from the OdbcDataReader
' and hydrates a MembershiUser from the values. Called by the
' MembershipUser.GetUser implementation.
'

Private Function GetUserFromReader(ByVal reader As OdbcDataReader) As MembershipUse


r
Dim providerUserKey As Object = reader.GetValue(0)
Dim username As String = reader.GetString(1)
Dim email As String = reader.GetString(2)

Dim passwordQuestion As String = ""


If Not reader.GetValue(3) Is DBNull.Value Then _
passwordQuestion = reader.GetString(3)

Dim comment As String = ""


If Not reader.GetValue(4) Is DBNull.Value Then _
comment = reader.GetString(4)

Dim isApproved As Boolean = reader.GetBoolean(5)


Dim isLockedOut As Boolean = reader.GetBoolean(6)
Dim creationDate As DateTime = reader.GetDateTime(7)

Dim lastLoginDate As DateTime = New DateTime()


If Not reader.GetValue(8) Is DBNull.Value Then _
lastLoginDate = reader.GetDateTime(8)

Dim lastActivityDate As DateTime = reader.GetDateTime(9)


Dim lastPasswordChangedDate As DateTime = reader.GetDateTime(10)

Dim lastLockedOutDate As DateTime = New DateTime()


If Not reader.GetValue(11) Is DBNull.Value Then _
lastLockedOutDate = reader.GetDateTime(11)

Dim u As MembershipUser = New MembershipUser(Me.Name, _


username, _
providerUserKey, _
email, _
passwordQuestion, _
comment, _
isApproved, _
isLockedOut, _
creationDate, _
lastLoginDate, _
lastActivityDate, _
lastPasswordChangedDate, _
lastLockedOutDate)

Return u
End Function

'
' MembershipProvider.UnlockUser
'

Public Overrides Function UnlockUser(ByVal username As String) As Boolean


Dim conn As OdbcConnection = New OdbcConnection(connectionString)
Dim cmd As OdbcCommand = New OdbcCommand("UPDATE Users " & _
" SET IsLockedOut = False, LastLockedOutDate
= ? " & _
" WHERE Username = ? AND ApplicationName = ?"
, conn)

cmd.Parameters.Add("@LastLockedOutDate", OdbcType.DateTime).Value = DateTime.No


w
cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicat
ionName

Dim rowsAffected As Integer = 0

Try
conn.Open()

rowsAffected = cmd.ExecuteNonQuery()
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "UnlockUser")

Throw New ProviderException(exceptionMessage)


Else
Throw e
End If
Finally
conn.Close()
End Try

If rowsAffected > 0 Then _


Return True

Return False
End Function

'
' MembershipProvider.GetUserNameByEmail
'

Public Overrides Function GetUserNameByEmail(email As String) As String


Dim conn As OdbcConnection = New OdbcConnection(connectionString)
Dim cmd As OdbcCommand = New OdbcCommand("SELECT Username" & _
" FROM Users WHERE Email = ? AND ApplicationName = ?", conn)

cmd.Parameters.Add("@Email", OdbcType.VarChar, 128).Value = email


cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicat
ionName

Dim username As String = ""

Try
conn.Open()

username = cmd.ExecuteScalar().ToString()
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "GetUserNameByEmail")

Throw New ProviderException(exceptionMessage)


Else
Throw e
End If
Finally
conn.Close()
End Try

If username Is Nothing Then _


username = ""
Return username
End Function

'
' MembershipProvider.ResetPassword
'

Public Overrides Function ResetPassword(ByVal username As String, ByVal answer As S


tring) As String

If Not EnablePasswordReset Then


Throw New NotSupportedException("Password Reset is not enabled.")
End If

If answer Is Nothing AndAlso RequiresQuestionAndAnswer Then


UpdateFailureCount(username, "passwordAnswer")

Throw New ProviderException("Password answer required for password Reset.")


End If

Dim newPassword As String = _


System.Web.Security.Membership.GeneratePassword(newPasswordLength, MinRequire
dNonAlphanumericCharacters)

Dim Args As ValidatePasswordEventArgs = _


New ValidatePasswordEventArgs(username, newPassword, True)

OnValidatingPassword(args)

If args.Cancel Then
If Not args.FailureInformation Is Nothing Then
Throw args.FailureInformation
Else
Throw New MembershipPasswordException("Reset password canceled due to p
assword validation failure.")
End If
End If

Dim conn As OdbcConnection = New OdbcConnection(connectionString)


Dim cmd As OdbcCommand = New OdbcCommand("SELECT PasswordAnswer, IsLockedOut FR
OM Users " & _
" WHERE Username = ? AND ApplicationName = ?", conn)

cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username


cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicat
ionName

Dim rowsAffected As Integer = 0


Dim passwordAnswer As String = ""
Dim reader As OdbcDataReader = Nothing

Try
conn.Open()

reader = cmd.ExecuteReader(CommandBehavior.SingleRow)

If reader.HasRows Then
reader.Read()

If reader.GetBoolean(1) Then _
Throw New MembershipPasswordException("The supplied user is locked ou
t.")
passwordAnswer = reader.GetString(0)
Else
Throw New MembershipPasswordException("The supplied user name is not fo
und.")
End If

If RequiresQuestionAndAnswer AndAlso Not CheckPassword(answer, passwordAnsw


er) Then
UpdateFailureCount(username, "passwordAnswer")

Throw New MembershipPasswordException("Incorrect password answer.")


End If

Dim updateCmd As OdbcCommand = New OdbcCommand("UPDATE Users " & _


" SET Password = ?, LastPasswordChangedDate = ?" & _
" WHERE Username = ? AND ApplicationName = ? AND IsLockedOut = False",
conn)

updateCmd.Parameters.Add("@Password", OdbcType.VarChar, 255).Value = Encode


Password(newPassword)
updateCmd.Parameters.Add("@LastPasswordChangedDate", OdbcType.DateTime).Val
ue = DateTime.Now
updateCmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = userna
me
updateCmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value =
pApplicationName

rowsAffected = updateCmd.ExecuteNonQuery()
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "ResetPassword")

Throw New ProviderException(exceptionMessage)


Else
Throw e
End If
Finally
If Not reader Is Nothing Then reader.Close()
conn.Close()
End Try

If rowsAffected > 0 Then


Return newPassword
Else
Throw New MembershipPasswordException("User not found, or user is locked ou
t. Password not Reset.")
End If
End Function

'
' MembershipProvider.UpdateUser
'

Public Overrides Sub UpdateUser(ByVal user As MembershipUser)

Dim conn As OdbcConnection = New OdbcConnection(connectionString)


Dim cmd As OdbcCommand = New OdbcCommand("UPDATE Users " & _
" SET Email = ?, Comment = ?," & _
" IsApproved = ?" & _
" WHERE Username = ? AND ApplicationName = ?", conn)

cmd.Parameters.Add("@Email", OdbcType.VarChar, 128).Value = user.Email


cmd.Parameters.Add("@Comment", OdbcType.VarChar, 255).Value = user.Comment
cmd.Parameters.Add("@IsApproved", OdbcType.Bit).Value = user.IsApproved
cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = user.UserName
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicat
ionName

Try
conn.Open()

cmd.ExecuteNonQuery()
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "UpdateUser")

Throw New ProviderException(exceptionMessage)


Else
Throw e
End If
Finally
conn.Close()
End Try
End Sub

'
' MembershipProvider.ValidateUser
'

Public Overrides Function ValidateUser(username As String, password As String) As Boole


an
Dim isValid As Boolean = False

Dim conn As OdbcConnection = New OdbcConnection(connectionString)


Dim cmd As OdbcCommand = New OdbcCommand("SELECT Password, IsApproved FROM User
s " & _
" WHERE Username = ? AND ApplicationName = ? AND IsLockedOut = False",
conn)

cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username


cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicat
ionName

Dim reader As OdbcDataReader = Nothing


Dim isApproved As Boolean = False
Dim pwd As String = ""

Try
conn.Open()

reader = cmd.ExecuteReader(CommandBehavior.SingleRow)

If reader.HasRows Then
reader.Read()
pwd = reader.GetString(0)
isApproved = reader.GetBoolean(1)
Else
Return False
End If

reader.Close()

If CheckPassword(password, pwd) Then


If isApproved Then
isValid = True

Dim updateCmd As OdbcCommand = New OdbcCommand("UPDATE Users SET L


astLoginDate = ?" & _
" WHERE Username = ? AND Ap
plicationName = ?", conn)

updateCmd.Parameters.Add("@LastLoginDate", OdbcType.DateTime).Value
= DateTime.Now
updateCmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value
= username
updateCmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255)
.Value = pApplicationName

updateCmd.ExecuteNonQuery()
End If
Else
conn.Close()

UpdateFailureCount(username, "password")
End If
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "ValidateUser")

Throw New ProviderException(exceptionMessage)


Else
Throw e
End If
Finally
If Not reader Is Nothing Then reader.Close()
conn.Close()
End Try

Return isValid
End Function

'
' UpdateFailureCount
' A helper method that performs the checks and updates associated with
' password failure tracking.
'

Private Sub UpdateFailureCount(username As String, failureType As String)

Dim conn As OdbcConnection = New OdbcConnection(connectionString)


Dim cmd As OdbcCommand = New OdbcCommand("SELECT FailedPasswordAttemptCount, "
& _
" FailedPasswordAttemptWindowStart, " & _
" FailedPasswordAnswerAttemptCount, " & _
" FailedPasswordAnswerAttemptWindowStart " &
_
" FROM Users " & _
" WHERE Username = ? AND ApplicationName = ?
", conn)

cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username


cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicat
ionName

Dim reader As OdbcDataReader = Nothing


Dim windowStart As DateTime = New DateTime()
Dim failureCount As Integer = 0

Try
conn.Open()

reader = cmd.ExecuteReader(CommandBehavior.SingleRow)

If reader.HasRows Then
reader.Read()

If failureType = "password" Then


failureCount = reader.GetInt32(0)
windowStart = reader.GetDateTime(1)
End If

If failureType = "passwordAnswer" Then


failureCount = reader.GetInt32(2)
windowStart = reader.GetDateTime(3)
End If
End If

reader.Close()

Dim windowEnd As DateTime = windowStart.AddMinutes(PasswordAttemptWindow)

If failureCount = 0 OrElse DateTime.Now > windowEnd Then


' First password failure or outside of PasswordAttemptWindow.
' Start a New password failure count from 1 and a New window starting n
ow.

If failureType = "password" Then _


cmd.CommandText = "UPDATE Users " & _
" SET FailedPasswordAttemptCount = ?, " & _
" FailedPasswordAttemptWindowStart = ? " & _
" WHERE Username = ? AND ApplicationName = ?"

If failureType = "passwordAnswer" Then _


cmd.CommandText = "UPDATE Users " & _
" SET FailedPasswordAnswerAttemptCount = ?, " & _
" FailedPasswordAnswerAttemptWindowStart = ? "
& _
" WHERE Username = ? AND ApplicationName = ?"

cmd.Parameters.Clear()
cmd.Parameters.Add("@Count", OdbcType.Int).Value = 1
cmd.Parameters.Add("@WindowStart", OdbcType.DateTime).Value = DateTime.
Now
cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = p
ApplicationName

If cmd.ExecuteNonQuery() < 0 Then _


Throw New ProviderException("Unable to update failure count and windo
w start.")
Else
failureCount += 1

If failureCount >= MaxInvalidPasswordAttempts Then


' Password attempts have exceeded the failure threshold. Lock out
' the user.

cmd.CommandText = "UPDATE Users " & _


" SET IsLockedOut = ?, LastLockedOutDate = ? " &
_
" WHERE Username = ? AND ApplicationName = ?"

cmd.Parameters.Clear()

cmd.Parameters.Add("@IsLockedOut", OdbcType.Bit).Value = True


cmd.Parameters.Add("@LastLockedOutDate", OdbcType.DateTime).Value =
DateTime.Now
cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = user
name
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value
= pApplicationName

If cmd.ExecuteNonQuery() < 0 Then _


Throw New ProviderException("Unable to lock out user.")
Else
' Password attempts have not exceeded the failure threshold. Update
' the failure counts. Leave the window the same.

If failureType = "password" Then _


cmd.CommandText = "UPDATE Users " & _
" SET FailedPasswordAttemptCount = ?" & _
" WHERE Username = ? AND ApplicationName = ?"

If failureType = "passwordAnswer" Then _


cmd.CommandText = "UPDATE Users " & _
" SET FailedPasswordAnswerAttemptCount = ?" &
_
" WHERE Username = ? AND ApplicationName = ?"

cmd.Parameters.Clear()

cmd.Parameters.Add("@Count", OdbcType.Int).Value = failureCount


cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = user
name
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value
= pApplicationName

If cmd.ExecuteNonQuery() < 0 Then _


Throw New ProviderException("Unable to update failure count.")
End If
End If
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "UpdateFailureCount")

Throw New ProviderException(exceptionMessage)


Else
Throw e
End If
Finally
If Not reader Is Nothing Then reader.Close()
conn.Close()
End Try
End Sub

'
' CheckPassword
' Compares password values based on the MembershipPasswordFormat.
'

Private Function CheckPassword(password As String, dbpassword As String) As Boolean


Dim pass1 As String = password
Dim pass2 As String = dbpassword

Select Case PasswordFormat


Case MembershipPasswordFormat.Encrypted
pass2 = UnEncodePassword(dbpassword)
Case MembershipPasswordFormat.Hashed
pass1 = EncodePassword(password)
Case Else
End Select

If pass1 = pass2 Then


Return True
End If

Return False
End Function

'
' EncodePassword
' Encrypts, Hashes, or leaves the password clear based on the PasswordFormat.
'
Private Function EncodePassword(password As String) As String
Dim encodedPassword As String = password

Select Case PasswordFormat


Case MembershipPasswordFormat.Clear

Case MembershipPasswordFormat.Encrypted
encodedPassword = _
Convert.ToBase64String(EncryptPassword(Encoding.Unicode.GetBytes(password)))
Case MembershipPasswordFormat.Hashed
Dim hash As HMACSHA1 = New HMACSHA1()
hash.Key = HexToByte(machineKey.ValidationKey)
encodedPassword = _
Convert.ToBase64String(hash.ComputeHash(Encoding.Unicode.GetBytes(password)))
Case Else
Throw New ProviderException("Unsupported password format.")
End Select

Return encodedPassword
End Function

'
' UnEncodePassword
' Decrypts or leaves the password clear based on the PasswordFormat.
'
Private Function UnEncodePassword(encodedPassword As String) As String
Dim password As String = encodedPassword

Select Case PasswordFormat


Case MembershipPasswordFormat.Clear

Case MembershipPasswordFormat.Encrypted
password = _
Encoding.Unicode.GetString(DecryptPassword(Convert.FromBase64String(password)))
Case MembershipPasswordFormat.Hashed
Throw New ProviderException("Cannot unencode a hashed password.")
Case Else
throw new ProviderException("Unsupported password format.")
End Select
Return password
End Function

'
' HexToByte
' Converts a hexadecimal string to a byte array. Used to convert encryption
' key values from the configuration.
'
Private Function HexToByte(hexString As String) As Byte()
Dim ReturnBytes((hexString.Length \ 2) - 1) As Byte
For i As Integer = 0 To ReturnBytes.Length - 1
ReturnBytes(i) = Convert.ToByte(hexString.Substring(i*2, 2), 16)
Next
Return ReturnBytes
End Function

'
' MembershipProvider.FindUsersByName
'

Public Overrides Function FindUsersByName(usernameToMatch As String, _


pageIndex As Integer, _
pageSize As Integer, _
ByRef totalRecords As Integer) _
As MembershipUserCollection
Dim conn As OdbcConnection = New OdbcConnection(connectionString)
Dim cmd As OdbcCommand = New OdbcCommand("SELECT Count(*) FROM Users " & _
"WHERE Username LIKE ? AND ApplicationName = ?", conn)
cmd.Parameters.Add("@UsernameSearch", OdbcType.VarChar, 255).Value = usernameTo
Match
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicat
ionName
Dim users As MembershipUserCollection = New MembershipUserCollection()

Dim reader As OdbcDataReader = Nothing


Try
conn.Open()
totalRecords = CInt(cmd.ExecuteScalar())
If totalRecords <= 0 Then Return users

cmd.CommandText = "SELECT PKID, Username, Email, PasswordQuestion," & _


" Comment, IsApproved, IsLockedOut, CreationDate, LastLoginDate," & _
" LastActivityDate, LastPasswordChangedDate, LastLockedOutDate " & _
" FROM Users " & _
" WHERE Username LIKE ? AND ApplicationName = ? " & _
" ORDER BY Username Asc"

reader = cmd.ExecuteReader()
Dim counter As Integer = 0
Dim startIndex As Integer = pageSize * pageIndex
Dim endIndex As Integer = startIndex + pageSize - 1
Do While reader.Read()
If counter >= startIndex Then
Dim u As MembershipUser = GetUserFromReader(reader)
users.Add(u)
End If

If counter >= endIndex Then cmd.Cancel()


counter += 1
Loop
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "FindUsersByName")

Throw New ProviderException(exceptionMessage)


Else
Throw e
End If
Finally
If Not reader Is Nothing Then reader.Close()

conn.Close()
End Try
Return users
End Function
'
' MembershipProvider.FindUsersByEmail
'
Public Overrides Function FindUsersByEmail(emailToMatch As String, _
pageIndex As Integer, _
pageSize As Integer, _
ByRef totalRecords As Integer) _
As MembershipUserCollection

Dim conn As OdbcConnection = New OdbcConnection(connectionString)


Dim cmd As OdbcCommand = New OdbcCommand("SELECT Count(*) FROM Users " & _
"WHERE Email LIKE ? AND ApplicationName = ?",
conn)
cmd.Parameters.Add("@EmailSearch", OdbcType.VarChar, 255).Value = emailToMatch
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = Applicati
onName

Dim users As MembershipUserCollection = New MembershipUserCollection()


Dim reader As OdbcDataReader = Nothing
totalRecords = 0
Try
conn.Open()
totalRecords = CInt(cmd.ExecuteScalar())
If totalRecords <= 0 Then Return users

cmd.CommandText = "SELECT PKID, Username, Email, PasswordQuestion," & _


" Comment, IsApproved, IsLockedOut, CreationDate, LastLoginDate,"
& _
" LastActivityDate, LastPasswordChangedDate, LastLockedOutDate " &
_
" FROM Users " & _
" WHERE Email LIKE ? AND ApplicationName = ? " & _
" ORDER BY Username Asc"
reader = cmd.ExecuteReader()

Dim counter As Integer = 0


Dim startIndex As Integer = pageSize * pageIndex
Dim endIndex As Integer = startIndex + pageSize - 1

Do While reader.Read()
If counter >= startIndex Then
Dim u As MembershipUser = GetUserFromReader(reader)
users.Add(u)
End If
If counter >= endIndex Then cmd.Cancel()

counter += 1
Loop
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "FindUsersByEmail")
Throw New ProviderException(exceptionMessage)
Else
Throw e
End If
Finally
If Not reader Is Nothing Then reader.Close()
conn.Close()
End Try

Return users
End Function

'
' WriteToEventLog
' A helper function that writes exception detail to the event log. Exceptions
' are written to the event log as a security measure to aSub Private database
' details from being Returned to the browser. If a method does not Return a status
' or boolean indicating the action succeeded or failed, a generic exception is also
' Thrown by the caller.
'
Private Sub WriteToEventLog(e As Exception, action As String)
Dim log As EventLog = New EventLog()
log.Source = eventSource
log.Log = eventLog
Dim message As String = "An exception occurred communicating with the data source." &
vbCrLf & vbCrLf
message &= "Action: " & action & vbCrLf & vbCrLf
message &= "Exception: " & e.ToString()

log.WriteEnTry(message)
End Sub

End Class
End Namespace

C#
using System.Web.Security;
using System.Configuration.Provider;
using System.Collections.Specialized;
using System;
using System.Data;
using System.Data.Odbc;
using System.Configuration;
using System.Diagnostics;
using System.Web;
using System.Globalization;
using System.Security.Cryptography;
using System.Text;
using System.Web.Configuration;
/*

This provider works with the following schema for the table of user data.
CREATE TABLE Users
(
PKID Guid NOT NULL PRIMARY KEY,
Username Text (255) NOT NULL,
ApplicationName Text (255) NOT NULL,
Email Text (128) NOT NULL,
Comment Text (255),
Password Text (128) NOT NULL,
PasswordQuestion Text (255),
PasswordAnswer Text (255),
IsApproved YesNo,
LastActivityDate DateTime,
LastLoginDate DateTime,
LastPasswordChangedDate DateTime,
CreationDate DateTime,
IsOnLine YesNo,
IsLockedOut YesNo,
LastLockedOutDate DateTime,
FailedPasswordAttemptCount Integer,
FailedPasswordAttemptWindowStart DateTime,
FailedPasswordAnswerAttemptCount Integer,
FailedPasswordAnswerAttemptWindowStart DateTime
)
*/

namespace Samples.AspNet.Membership
{

public sealed class OdbcMembershipProvider: MembershipProvider


{
//
// Global connection string, generated password length, generic exception message, even
t log info.
//

private int newPasswordLength = 8;


private string eventSource = "OdbcMembershipProvider";
private string eventLog = "Application";
private string exceptionMessage = "An exception occurred. Please check the Event Log.";
private string connectionString;
//
// Used when determining encryption key values.
//
private MachineKeySection machineKey;

//
// If false, exceptions are thrown to the caller. If true,
// exceptions are written to the event log.
//

private bool pWriteExceptionsToEventLog;


public bool WriteExceptionsToEventLog
{
get { return pWriteExceptionsToEventLog; }
set { pWriteExceptionsToEventLog = value; }
}

//
// System.Configuration.Provider.ProviderBase.Initialize Method
//
public override void Initialize(string name, NameValueCollection config)
{
//
// Initialize values from web.config.
//

if (config == null)
throw new ArgumentNullException("config");

if (name == null || name.Length == 0)


name = "OdbcMembershipProvider";
if (String.IsNullOrEmpty(config["description"]))
{
config.Remove("description");
config.Add("description", "Sample ODBC Membership provider");
}

// Initialize the abstract base class.


base.Initialize(name, config);

pApplicationName = GetConfigValue(config["applicationName"],
System.Web.Hosting.HostingEnvironment.ApplicationVirt
ualPath);
pMaxInvalidPasswordAttempts = Convert.ToInt32(GetConfigValue(config["maxInvalidPasswo
rdAttempts"], "5"));
pPasswordAttemptWindow = Convert.ToInt32(GetConfigValue(config["passwordAttemptWindow
"], "10"));
pMinRequiredNonAlphanumericCharacters = Convert.ToInt32(GetConfigValue(config["minReq
uiredNonAlphanumericCharacters"], "1"));
pMinRequiredPasswordLength = Convert.ToInt32(GetConfigValue(config["minRequiredPasswo
rdLength"], "7"));
pPasswordStrengthRegularExpression = Convert.ToString(GetConfigValue(config["password
StrengthRegularExpression"], ""));
pEnablePasswordReset = Convert.ToBoolean(GetConfigValue(config["enablePasswordReset"]
, "true"));
pEnablePasswordRetrieval = Convert.ToBoolean(GetConfigValue(config["enablePasswordRet
rieval"], "true"));
pRequiresQuestionAndAnswer = Convert.ToBoolean(GetConfigValue(config["requiresQuestio
nAndAnswer"], "false"));
pRequiresUniqueEmail = Convert.ToBoolean(GetConfigValue(config["requiresUniqueEmail"]
, "true"));
pWriteExceptionsToEventLog = Convert.ToBoolean(GetConfigValue(config["writeExceptions
ToEventLog"], "true"));

string temp_format = config["passwordFormat"];


if (temp_format == null)
{
temp_format = "Hashed";
}

switch (temp_format)
{
case "Hashed":
pPasswordFormat = MembershipPasswordFormat.Hashed;
break;
case "Encrypted":
pPasswordFormat = MembershipPasswordFormat.Encrypted;
break;
case "Clear":
pPasswordFormat = MembershipPasswordFormat.Clear;
break;
default:
throw new ProviderException("Password format not supported.");
}
//
// Initialize OdbcConnection.
//
ConnectionStringSettings ConnectionStringSettings =
ConfigurationManager.ConnectionStrings[config["connectionStringName"]];
if (ConnectionStringSettings == null || ConnectionStringSettings.ConnectionString.Tri
m() == "")
{
throw new ProviderException("Connection string cannot be blank.");
}

connectionString = ConnectionStringSettings.ConnectionString;

// Get encryption and decryption key information from the configuration.


Configuration cfg =
WebConfigurationManager.OpenWebConfiguration(System.Web.Hosting.HostingEnvironment.
ApplicationVirtualPath);
machineKey = (MachineKeySection)cfg.GetSection("system.web/machineKey");
if (machineKey.ValidationKey.Contains("AutoGenerate"))
if (PasswordFormat != MembershipPasswordFormat.Clear)
throw new ProviderException("Hashed or Encrypted passwords " +
"are not supported with auto-generated keys.");
}

//
// A helper function to retrieve config values from the configuration file.
//

private string GetConfigValue(string configValue, string defaultValue)


{
if (String.IsNullOrEmpty(configValue))
return defaultValue;
return configValue;
}

//
// System.Web.Security.MembershipProvider properties.
//

private string pApplicationName;


private bool pEnablePasswordReset;
private bool pEnablePasswordRetrieval;
private bool pRequiresQuestionAndAnswer;
private bool pRequiresUniqueEmail;
private int pMaxInvalidPasswordAttempts;
private int pPasswordAttemptWindow;
private MembershipPasswordFormat pPasswordFormat;

public override string ApplicationName


{
get { return pApplicationName; }
set { pApplicationName = value; }
}
public override bool EnablePasswordReset
{
get { return pEnablePasswordReset; }
}

public override bool EnablePasswordRetrieval


{
get { return pEnablePasswordRetrieval; }
}

public override bool RequiresQuestionAndAnswer


{
get { return pRequiresQuestionAndAnswer; }
}

public override bool RequiresUniqueEmail


{
get { return pRequiresUniqueEmail; }
}

public override int MaxInvalidPasswordAttempts


{
get { return pMaxInvalidPasswordAttempts; }
}

public override int PasswordAttemptWindow


{
get { return pPasswordAttemptWindow; }
}

public override MembershipPasswordFormat PasswordFormat


{
get { return pPasswordFormat; }
}
private int pMinRequiredNonAlphanumericCharacters;

public override int MinRequiredNonAlphanumericCharacters


{
get { return pMinRequiredNonAlphanumericCharacters; }
}

private int pMinRequiredPasswordLength;


public override int MinRequiredPasswordLength
{
get { return pMinRequiredPasswordLength; }
}

private string pPasswordStrengthRegularExpression;


public override string PasswordStrengthRegularExpression
{
get { return pPasswordStrengthRegularExpression; }
}
//
// System.Web.Security.MembershipProvider methods.
//
//
// MembershipProvider.ChangePassword
//

public override bool ChangePassword(string username, string oldPwd, string newPwd)


{
if (!ValidateUser(username, oldPwd))
return false;

ValidatePasswordEventArgs args =
new ValidatePasswordEventArgs(username, newPwd, true);

OnValidatingPassword(args);
if (args.Cancel)
if (args.FailureInformation != null)
throw args.FailureInformation;
else
throw new MembershipPasswordException("Change password canceled due to new passwo
rd validation failure.");

OdbcConnection conn = new OdbcConnection(connectionString);


OdbcCommand cmd = new OdbcCommand("UPDATE Users " +
" SET Password = ?, LastPasswordChangedDate = ? " +
" WHERE Username = ? AND ApplicationName = ?", conn);

cmd.Parameters.Add("@Password", OdbcType.VarChar, 255).Value = EncodePassword(newPwd)


;
cmd.Parameters.Add("@LastPasswordChangedDate", OdbcType.DateTime).Value = DateTime.No
w;
cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicationNam
e;

int rowsAffected = 0;

try
{
conn.Open();

rowsAffected = cmd.ExecuteNonQuery();
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "ChangePassword");

throw new ProviderException(exceptionMessage);


}
else
{
throw e;
}
}
finally
{
conn.Close();
}

if (rowsAffected > 0)
{
return true;
}
return false;
}

//
// MembershipProvider.ChangePasswordQuestionAndAnswer
//
public override bool ChangePasswordQuestionAndAnswer(string username,
string password,
string newPwdQuestion,
string newPwdAnswer)
{
if (!ValidateUser(username, password))
return false;
OdbcConnection conn = new OdbcConnection(connectionString);
OdbcCommand cmd = new OdbcCommand("UPDATE Users " +
" SET PasswordQuestion = ?, PasswordAnswer = ?" +
" WHERE Username = ? AND ApplicationName = ?", conn);

cmd.Parameters.Add("@Question", OdbcType.VarChar, 255).Value = newPwdQuestion;


cmd.Parameters.Add("@Answer", OdbcType.VarChar, 255).Value = EncodePassword(newPwdAns
wer);
cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicationNam
e;

int rowsAffected = 0;
try
{
conn.Open();
rowsAffected = cmd.ExecuteNonQuery();
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "ChangePasswordQuestionAndAnswer");
throw new ProviderException(exceptionMessage);
}
else
{
throw e;
}
}
finally
{
conn.Close();
}

if (rowsAffected > 0)
{
return true;
}

return false;
}

//
// MembershipProvider.CreateUser
//
public override MembershipUser CreateUser(string username,
string password,
string email,
string passwordQuestion,
string passwordAnswer,
bool isApproved,
object providerUserKey,
out MembershipCreateStatus status)
{
ValidatePasswordEventArgs args =
new ValidatePasswordEventArgs(username, password, true);
OnValidatingPassword(args);

if (args.Cancel)
{
status = MembershipCreateStatus.InvalidPassword;
return null;
}

if (RequiresUniqueEmail && GetUserNameByEmail(email) != "")


{
status = MembershipCreateStatus.DuplicateEmail;
return null;
}
MembershipUser u = GetUser(username, false);

if (u == null)
{
DateTime createDate = DateTime.Now;

if (providerUserKey == null)
{
providerUserKey = Guid.NewGuid();
}
else
{
if ( !(providerUserKey is Guid) )
{
status = MembershipCreateStatus.InvalidProviderUserKey;
return null;
}
}
OdbcConnection conn = new OdbcConnection(connectionString);
OdbcCommand cmd = new OdbcCommand("INSERT INTO Users " +
" (PKID, Username, Password, Email, PasswordQuestion, " +
" PasswordAnswer, IsApproved," +
" Comment, CreationDate, LastPasswordChangedDate, LastActivityDate," +
" ApplicationName, IsLockedOut, LastLockedOutDate," +
" FailedPasswordAttemptCount, FailedPasswordAttemptWindowStart, " +
" FailedPasswordAnswerAttemptCount, FailedPasswordAnswerAttemptWindowStart)"
+
" Values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", conn);
cmd.Parameters.Add("@PKID", OdbcType.UniqueIdentifier).Value = providerUserKey;
cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username;
cmd.Parameters.Add("@Password", OdbcType.VarChar, 255).Value = EncodePassword(passw
ord);
cmd.Parameters.Add("@Email", OdbcType.VarChar, 128).Value = email;
cmd.Parameters.Add("@PasswordQuestion", OdbcType.VarChar, 255).Value = passwordQues
tion;
cmd.Parameters.Add("@PasswordAnswer", OdbcType.VarChar, 255).Value = EncodePassword
(passwordAnswer);
cmd.Parameters.Add("@IsApproved", OdbcType.Bit).Value = isApproved;
cmd.Parameters.Add("@Comment", OdbcType.VarChar, 255).Value = "";
cmd.Parameters.Add("@CreationDate", OdbcType.DateTime).Value = createDate;
cmd.Parameters.Add("@LastPasswordChangedDate", OdbcType.DateTime).Value = createDat
e;
cmd.Parameters.Add("@LastActivityDate", OdbcType.DateTime).Value = createDate;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicationN
ame;
cmd.Parameters.Add("@IsLockedOut", OdbcType.Bit).Value = false;
cmd.Parameters.Add("@LastLockedOutDate", OdbcType.DateTime).Value = createDate;
cmd.Parameters.Add("@FailedPasswordAttemptCount", OdbcType.Int).Value = 0;
cmd.Parameters.Add("@FailedPasswordAttemptWindowStart", OdbcType.DateTime).Value =
createDate;
cmd.Parameters.Add("@FailedPasswordAnswerAttemptCount", OdbcType.Int).Value = 0;
cmd.Parameters.Add("@FailedPasswordAnswerAttemptWindowStart", OdbcType.DateTime).Va
lue = createDate;

try
{
conn.Open();

int recAdded = cmd.ExecuteNonQuery();


if (recAdded > 0)
{
status = MembershipCreateStatus.Success;
}
else
{
status = MembershipCreateStatus.UserRejected;
}
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "CreateUser");
}

status = MembershipCreateStatus.ProviderError;
}
finally
{
conn.Close();
}

return GetUser(username, false);


}
else
{
status = MembershipCreateStatus.DuplicateUserName;
}

return null;
}

//
// MembershipProvider.DeleteUser
//
public override bool DeleteUser(string username, bool deleteAllRelatedData)
{
OdbcConnection conn = new OdbcConnection(connectionString);
OdbcCommand cmd = new OdbcCommand("DELETE FROM Users " +
" WHERE Username = ? AND Applicationname = ?", conn);

cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username;


cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicationNam
e;

int rowsAffected = 0;
try
{
conn.Open();
rowsAffected = cmd.ExecuteNonQuery();

if (deleteAllRelatedData)
{
// Process commands to delete all data for the user in the database.
}
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "DeleteUser");
throw new ProviderException(exceptionMessage);
}
else
{
throw e;
}
}
finally
{
conn.Close();
}

if (rowsAffected > 0)
return true;
return false;
}

//
// MembershipProvider.GetAllUsers
//

public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out i


nt totalRecords)
{
OdbcConnection conn = new OdbcConnection(connectionString);
OdbcCommand cmd = new OdbcCommand("SELECT Count(*) FROM Users " +
"WHERE ApplicationName = ?", conn);
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = ApplicationName
;
MembershipUserCollection users = new MembershipUserCollection();

OdbcDataReader reader = null;


totalRecords = 0;
try
{
conn.Open();
totalRecords = (int)cmd.ExecuteScalar();

if (totalRecords <= 0) { return users; }


cmd.CommandText = "SELECT PKID, Username, Email, PasswordQuestion," +
" Comment, IsApproved, IsLockedOut, CreationDate, LastLoginDate," +
" LastActivityDate, LastPasswordChangedDate, LastLockedOutDate " +
" FROM Users " +
" WHERE ApplicationName = ? " +
" ORDER BY Username Asc";

reader = cmd.ExecuteReader();
int counter = 0;
int startIndex = pageSize * pageIndex;
int endIndex = startIndex + pageSize - 1;
while (reader.Read())
{
if (counter >= startIndex)
{
MembershipUser u = GetUserFromReader(reader);
users.Add(u);
}

if (counter >= endIndex) { cmd.Cancel(); }


counter++;
}
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "GetAllUsers ");
throw new ProviderException(exceptionMessage);
}
else
{
throw e;
}
}
finally
{
if (reader != null) { reader.Close(); }
conn.Close();
}

return users;
}

//
// MembershipProvider.GetNumberOfUsersOnline
//

public override int GetNumberOfUsersOnline()


{

TimeSpan onlineSpan = new TimeSpan(0, System.Web.Security.Membership.UserIsOnlineTime


Window, 0);
DateTime compareTime = DateTime.Now.Subtract(onlineSpan);

OdbcConnection conn = new OdbcConnection(connectionString);


OdbcCommand cmd = new OdbcCommand("SELECT Count(*) FROM Users " +
" WHERE LastActivityDate > ? AND ApplicationName = ?", conn);

cmd.Parameters.Add("@CompareDate", OdbcType.DateTime).Value = compareTime;


cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicationNam
e;

int numOnline = 0;
try
{
conn.Open();
numOnline = (int)cmd.ExecuteScalar();
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "GetNumberOfUsersOnline");
throw new ProviderException(exceptionMessage);
}
else
{
throw e;
}
}
finally
{
conn.Close();
}
return numOnline;
}
//
// MembershipProvider.GetPassword
//

public override string GetPassword(string username, string answer)


{
if (!EnablePasswordRetrieval)
{
throw new ProviderException("Password Retrieval Not Enabled.");
}

if (PasswordFormat == MembershipPasswordFormat.Hashed)
{
throw new ProviderException("Cannot retrieve Hashed passwords.");
}

OdbcConnection conn = new OdbcConnection(connectionString);


OdbcCommand cmd = new OdbcCommand("SELECT Password, PasswordAnswer, IsLockedOut FROM
Users " +
" WHERE Username = ? AND ApplicationName = ?", conn);
cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicationNam
e;
string password = "";
string passwordAnswer = "";
OdbcDataReader reader = null;
try
{
conn.Open();
reader = cmd.ExecuteReader(CommandBehavior.SingleRow);

if (reader.HasRows)
{
reader.Read();

if (reader.GetBoolean(2))
throw new MembershipPasswordException("The supplied user is locked out.");

password = reader.GetString(0);
passwordAnswer = reader.GetString(1);
}
else
{
throw new MembershipPasswordException("The supplied user name is not found.");
}
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "GetPassword");
throw new ProviderException(exceptionMessage);
}
else
{
throw e;
}
}
finally
{
if (reader != null) { reader.Close(); }
conn.Close();
}
if (RequiresQuestionAndAnswer && !CheckPassword(answer, passwordAnswer))
{
UpdateFailureCount(username, "passwordAnswer");

throw new MembershipPasswordException("Incorrect password answer.");


}

if (PasswordFormat == MembershipPasswordFormat.Encrypted)
{
password = UnEncodePassword(password);
}
return password;
}

//
// MembershipProvider.GetUser(string, bool)
//

public override MembershipUser GetUser(string username, bool userIsOnline)


{
OdbcConnection conn = new OdbcConnection(connectionString);
OdbcCommand cmd = new OdbcCommand("SELECT PKID, Username, Email, PasswordQuestion,"
+
" Comment, IsApproved, IsLockedOut, CreationDate, LastLoginDate," +
" LastActivityDate, LastPasswordChangedDate, LastLockedOutDate" +
" FROM Users WHERE Username = ? AND ApplicationName = ?", conn);

cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username;


cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicationNam
e;

MembershipUser u = null;
OdbcDataReader reader = null;

try
{
conn.Open();

reader = cmd.ExecuteReader();
if (reader.HasRows)
{
reader.Read();
u = GetUserFromReader(reader);
if (userIsOnline)
{
OdbcCommand updateCmd = new OdbcCommand("UPDATE Users " +
"SET LastActivityDate = ? " +
"WHERE Username = ? AND Applicationname = ?", conn);
updateCmd.Parameters.Add("@LastActivityDate", OdbcType.DateTime).Value = DateTi
me.Now;
updateCmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username;
updateCmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pAp
plicationName;

updateCmd.ExecuteNonQuery();
}
}

}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "GetUser(String, Boolean)");
throw new ProviderException(exceptionMessage);
}
else
{
throw e;
}
}
finally
{
if (reader != null) { reader.Close(); }
conn.Close();
}
return u;
}

//
// MembershipProvider.GetUser(object, bool)
//
public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
{
OdbcConnection conn = new OdbcConnection(connectionString);
OdbcCommand cmd = new OdbcCommand("SELECT PKID, Username, Email, PasswordQuestion," +
" Comment, IsApproved, IsLockedOut, CreationDate, LastLoginDate," +
" LastActivityDate, LastPasswordChangedDate, LastLockedOutDate" +
" FROM Users WHERE PKID = ?", conn);
cmd.Parameters.Add("@PKID", OdbcType.UniqueIdentifier).Value = providerUserKey;

MembershipUser u = null;
OdbcDataReader reader = null;

try
{
conn.Open();

reader = cmd.ExecuteReader();
if (reader.HasRows)
{
reader.Read();
u = GetUserFromReader(reader);
if (userIsOnline)
{
OdbcCommand updateCmd = new OdbcCommand("UPDATE Users " +
"SET LastActivityDate = ? " +
"WHERE PKID = ?", conn);

updateCmd.Parameters.Add("@LastActivityDate", OdbcType.DateTime).Value = DateTi


me.Now;
updateCmd.Parameters.Add("@PKID", OdbcType.UniqueIdentifier).Value = providerUs
erKey;
updateCmd.ExecuteNonQuery();
}
}
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "GetUser(Object, Boolean)");
throw new ProviderException(exceptionMessage);
}
else
{
throw e;
}
}
finally
{
if (reader != null) { reader.Close(); }

conn.Close();
}

return u;
}

//
// GetUserFromReader
// A helper function that takes the current row from the OdbcDataReader
// and hydrates a MembershiUser from the values. Called by the
// MembershipUser.GetUser implementation.
//

private MembershipUser GetUserFromReader(OdbcDataReader reader)


{
object providerUserKey = reader.GetValue(0);
string username = reader.GetString(1);
string email = reader.GetString(2);
string passwordQuestion = "";
if (reader.GetValue(3) != DBNull.Value)
passwordQuestion = reader.GetString(3);
string comment = "";
if (reader.GetValue(4) != DBNull.Value)
comment = reader.GetString(4);
bool isApproved = reader.GetBoolean(5);
bool isLockedOut = reader.GetBoolean(6);
DateTime creationDate = reader.GetDateTime(7);
DateTime lastLoginDate = new DateTime();
if (reader.GetValue(8) != DBNull.Value)
lastLoginDate = reader.GetDateTime(8);
DateTime lastActivityDate = reader.GetDateTime(9);
DateTime lastPasswordChangedDate = reader.GetDateTime(10);

DateTime lastLockedOutDate = new DateTime();


if (reader.GetValue(11) != DBNull.Value)
lastLockedOutDate = reader.GetDateTime(11);

MembershipUser u = new MembershipUser(this.Name,


username,
providerUserKey,
email,
passwordQuestion,
comment,
isApproved,
isLockedOut,
creationDate,
lastLoginDate,
lastActivityDate,
lastPasswordChangedDate,
lastLockedOutDate);

return u;
}

//
// MembershipProvider.UnlockUser
//

public override bool UnlockUser(string username)


{
OdbcConnection conn = new OdbcConnection(connectionString);
OdbcCommand cmd = new OdbcCommand("UPDATE Users " +
" SET IsLockedOut = False, LastLockedOutDate = ? "
+
" WHERE Username = ? AND ApplicationName = ?", conn
);
cmd.Parameters.Add("@LastLockedOutDate", OdbcType.DateTime).Value = DateTime.Now;
cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicationNam
e;
int rowsAffected = 0;

try
{
conn.Open();

rowsAffected = cmd.ExecuteNonQuery();
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "UnlockUser");

throw new ProviderException(exceptionMessage);


}
else
{
throw e;
}
}
finally
{
conn.Close();
}
if (rowsAffected > 0)
return true;

return false;
}

//
// MembershipProvider.GetUserNameByEmail
//

public override string GetUserNameByEmail(string email)


{
OdbcConnection conn = new OdbcConnection(connectionString);
OdbcCommand cmd = new OdbcCommand("SELECT Username" +
" FROM Users WHERE Email = ? AND ApplicationName = ?", conn);
cmd.Parameters.Add("@Email", OdbcType.VarChar, 128).Value = email;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicationNam
e;
string username = "";
try
{
conn.Open();
username = (string)cmd.ExecuteScalar();
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "GetUserNameByEmail");
throw new ProviderException(exceptionMessage);
}
else
{
throw e;
}
}
finally
{
conn.Close();
}
if (username == null)
username = "";

return username;
}

//
// MembershipProvider.ResetPassword
//

public override string ResetPassword(string username, string answer)


{
if (!EnablePasswordReset)
{
throw new NotSupportedException("Password reset is not enabled.");
}
if (answer == null && RequiresQuestionAndAnswer)
{
UpdateFailureCount(username, "passwordAnswer");
throw new ProviderException("Password answer required for password reset.");
}
string newPassword =
System.Web.Security.Membership.GeneratePassword(newPasswordLength,MinRequiredNonAlp
hanumericCharacters);

ValidatePasswordEventArgs args =
new ValidatePasswordEventArgs(username, newPassword, true);
OnValidatingPassword(args);

if (args.Cancel)
if (args.FailureInformation != null)
throw args.FailureInformation;
else
throw new MembershipPasswordException("Reset password canceled due to password va
lidation failure.");

OdbcConnection conn = new OdbcConnection(connectionString);


OdbcCommand cmd = new OdbcCommand("SELECT PasswordAnswer, IsLockedOut FROM Users " +
" WHERE Username = ? AND ApplicationName = ?", conn);

cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username;


cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicationNam
e;

int rowsAffected = 0;
string passwordAnswer = "";
OdbcDataReader reader = null;

try
{
conn.Open();

reader = cmd.ExecuteReader(CommandBehavior.SingleRow);
if (reader.HasRows)
{
reader.Read();

if (reader.GetBoolean(1))
throw new MembershipPasswordException("The supplied user is locked out.");
passwordAnswer = reader.GetString(0);
}
else
{
throw new MembershipPasswordException("The supplied user name is not found.");
}
if (RequiresQuestionAndAnswer && !CheckPassword(answer, passwordAnswer))
{
UpdateFailureCount(username, "passwordAnswer");
throw new MembershipPasswordException("Incorrect password answer.");
}

OdbcCommand updateCmd = new OdbcCommand("UPDATE Users " +


" SET Password = ?, LastPasswordChangedDate = ?" +
" WHERE Username = ? AND ApplicationName = ? AND IsLockedOut = False", conn);
updateCmd.Parameters.Add("@Password", OdbcType.VarChar, 255).Value = EncodePassword
(newPassword);
updateCmd.Parameters.Add("@LastPasswordChangedDate", OdbcType.DateTime).Value = Dat
eTime.Now;
updateCmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username;
updateCmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplic
ationName;
rowsAffected = updateCmd.ExecuteNonQuery();
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "ResetPassword");
throw new ProviderException(exceptionMessage);
}
else
{
throw e;
}
}
finally
{
if (reader != null) { reader.Close(); }
conn.Close();
}

if (rowsAffected > 0)
{
return newPassword;
}
else
{
throw new MembershipPasswordException("User not found, or user is locked out. Passw
ord not Reset.");
}
}

//
// MembershipProvider.UpdateUser
//

public override void UpdateUser(MembershipUser user)


{
OdbcConnection conn = new OdbcConnection(connectionString);
OdbcCommand cmd = new OdbcCommand("UPDATE Users " +
" SET Email = ?, Comment = ?," +
" IsApproved = ?" +
" WHERE Username = ? AND ApplicationName = ?", conn);

cmd.Parameters.Add("@Email", OdbcType.VarChar, 128).Value = user.Email;


cmd.Parameters.Add("@Comment", OdbcType.VarChar, 255).Value = user.Comment;
cmd.Parameters.Add("@IsApproved", OdbcType.Bit).Value = user.IsApproved;
cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = user.UserName;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicationNam
e;

try
{
conn.Open();
cmd.ExecuteNonQuery();
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "UpdateUser");
throw new ProviderException(exceptionMessage);
}
else
{
throw e;
}
}
finally
{
conn.Close();
}
}

//
// MembershipProvider.ValidateUser
//

public override bool ValidateUser(string username, string password)


{
bool isValid = false;

OdbcConnection conn = new OdbcConnection(connectionString);


OdbcCommand cmd = new OdbcCommand("SELECT Password, IsApproved FROM Users " +
" WHERE Username = ? AND ApplicationName = ? AND IsLockedOut = False", conn);
cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicationNam
e;

OdbcDataReader reader = null;


bool isApproved = false;
string pwd = "";
try
{
conn.Open();

reader = cmd.ExecuteReader(CommandBehavior.SingleRow);

if (reader.HasRows)
{
reader.Read();
pwd = reader.GetString(0);
isApproved = reader.GetBoolean(1);
}
else
{
return false;
}
reader.Close();

if (CheckPassword(password, pwd))
{
if (isApproved)
{
isValid = true;

OdbcCommand updateCmd = new OdbcCommand("UPDATE Users SET LastLoginDate = ?" +


" WHERE Username = ? AND ApplicationNam
e = ?", conn);

updateCmd.Parameters.Add("@LastLoginDate", OdbcType.DateTime).Value = DateTime.


Now;
updateCmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username;
updateCmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pAp
plicationName;

updateCmd.ExecuteNonQuery();
}
}
else
{
conn.Close();

UpdateFailureCount(username, "password");
}
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "ValidateUser");
throw new ProviderException(exceptionMessage);
}
else
{
throw e;
}
}
finally
{
if (reader != null) { reader.Close(); }
conn.Close();
}

return isValid;
}

//
// UpdateFailureCount
// A helper method that performs the checks and updates associated with
// password failure tracking.
//
private void UpdateFailureCount(string username, string failureType)
{
OdbcConnection conn = new OdbcConnection(connectionString);
OdbcCommand cmd = new OdbcCommand("SELECT FailedPasswordAttemptCount, " +
" FailedPasswordAttemptWindowStart, " +
" FailedPasswordAnswerAttemptCount, " +
" FailedPasswordAnswerAttemptWindowStart " +
" FROM Users " +
" WHERE Username = ? AND ApplicationName = ?", con
n);

cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username;


cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicationNam
e;
OdbcDataReader reader = null;
DateTime windowStart = new DateTime();
int failureCount = 0;

try
{
conn.Open();
reader = cmd.ExecuteReader(CommandBehavior.SingleRow);

if (reader.HasRows)
{
reader.Read();

if (failureType == "password")
{
failureCount = reader.GetInt32(0);
windowStart = reader.GetDateTime(1);
}

if (failureType == "passwordAnswer")
{
failureCount = reader.GetInt32(2);
windowStart = reader.GetDateTime(3);
}
}
reader.Close();

DateTime windowEnd = windowStart.AddMinutes(PasswordAttemptWindow);

if (failureCount == 0 || DateTime.Now > windowEnd)


{
// First password failure or outside of PasswordAttemptWindow.
// Start a new password failure count from 1 and a new window starting now.
if (failureType == "password")
cmd.CommandText = "UPDATE Users " +
" SET FailedPasswordAttemptCount = ?, " +
" FailedPasswordAttemptWindowStart = ? " +
" WHERE Username = ? AND ApplicationName = ?";

if (failureType == "passwordAnswer")
cmd.CommandText = "UPDATE Users " +
" SET FailedPasswordAnswerAttemptCount = ?, " +
" FailedPasswordAnswerAttemptWindowStart = ? " +
" WHERE Username = ? AND ApplicationName = ?";

cmd.Parameters.Clear();
cmd.Parameters.Add("@Count", OdbcType.Int).Value = 1;
cmd.Parameters.Add("@WindowStart", OdbcType.DateTime).Value = DateTime.Now;
cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicatio
nName;

if (cmd.ExecuteNonQuery() < 0)
throw new ProviderException("Unable to update failure count and window start.")
;
}
else
{
if (failureCount++ >= MaxInvalidPasswordAttempts)
{
// Password attempts have exceeded the failure threshold. Lock out
// the user.
cmd.CommandText = "UPDATE Users " +
" SET IsLockedOut = ?, LastLockedOutDate = ? " +
" WHERE Username = ? AND ApplicationName = ?";

cmd.Parameters.Clear();

cmd.Parameters.Add("@IsLockedOut", OdbcType.Bit).Value = true;


cmd.Parameters.Add("@LastLockedOutDate", OdbcType.DateTime).Value = DateTime.No
w;
cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicat
ionName;

if (cmd.ExecuteNonQuery() < 0)
throw new ProviderException("Unable to lock out user.");
}
else
{
// Password attempts have not exceeded the failure threshold. Update
// the failure counts. Leave the window the same.

if (failureType == "password")
cmd.CommandText = "UPDATE Users " +
" SET FailedPasswordAttemptCount = ?" +
" WHERE Username = ? AND ApplicationName = ?";
if (failureType == "passwordAnswer")
cmd.CommandText = "UPDATE Users " +
" SET FailedPasswordAnswerAttemptCount = ?" +
" WHERE Username = ? AND ApplicationName = ?";

cmd.Parameters.Clear();

cmd.Parameters.Add("@Count", OdbcType.Int).Value = failureCount;


cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplica
tionName;

if (cmd.ExecuteNonQuery() < 0)
throw new ProviderException("Unable to update failure count.");
}
}
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "UpdateFailureCount");
throw new ProviderException(exceptionMessage);
}
else
{
throw e;
}
}
finally
{
if (reader != null) { reader.Close(); }
conn.Close();
}
}

//
// CheckPassword
// Compares password values based on the MembershipPasswordFormat.
//

private bool CheckPassword(string password, string dbpassword)


{
string pass1 = password;
string pass2 = dbpassword;

switch (PasswordFormat)
{
case MembershipPasswordFormat.Encrypted:
pass2 = UnEncodePassword(dbpassword);
break;
case MembershipPasswordFormat.Hashed:
pass1 = EncodePassword(password);
break;
default:
break;
}

if (pass1 == pass2)
{
return true;
}

return false;
}

//
// EncodePassword
// Encrypts, Hashes, or leaves the password clear based on the PasswordFormat.
//
private string EncodePassword(string password)
{
string encodedPassword = password;

switch (PasswordFormat)
{
case MembershipPasswordFormat.Clear:
break;
case MembershipPasswordFormat.Encrypted:
encodedPassword =
Convert.ToBase64String(EncryptPassword(Encoding.Unicode.GetBytes(password)));
break;
case MembershipPasswordFormat.Hashed:
HMACSHA1 hash = new HMACSHA1();
hash.Key = HexToByte(machineKey.ValidationKey);
encodedPassword =
Convert.ToBase64String(hash.ComputeHash(Encoding.Unicode.GetBytes(password)));
break;
default:
throw new ProviderException("Unsupported password format.");
}

return encodedPassword;
}

//
// UnEncodePassword
// Decrypts or leaves the password clear based on the PasswordFormat.
//
private string UnEncodePassword(string encodedPassword)
{
string password = encodedPassword;

switch (PasswordFormat)
{
case MembershipPasswordFormat.Clear:
break;
case MembershipPasswordFormat.Encrypted:
password =
Encoding.Unicode.GetString(DecryptPassword(Convert.FromBase64String(password)))
;
break;
case MembershipPasswordFormat.Hashed:
throw new ProviderException("Cannot unencode a hashed password.");
default:
throw new ProviderException("Unsupported password format.");
}

return password;
}

//
// HexToByte
// Converts a hexadecimal string to a byte array. Used to convert encryption
// key values from the configuration.
//

private byte[] HexToByte(string hexString)


{
byte[] returnBytes = new byte[hexString.Length / 2];
for (int i = 0; i < returnBytes.Length; i++)
returnBytes[i] = Convert.ToByte(hexString.Substring(i*2, 2), 16);
return returnBytes;
}

//
// MembershipProvider.FindUsersByName
//

public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pa


geIndex, int pageSize, out int totalRecords)
{

OdbcConnection conn = new OdbcConnection(connectionString);


OdbcCommand cmd = new OdbcCommand("SELECT Count(*) FROM Users " +
"WHERE Username LIKE ? AND ApplicationName = ?", conn);
cmd.Parameters.Add("@UsernameSearch", OdbcType.VarChar, 255).Value = usernameToMatch;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicationNam
e;

MembershipUserCollection users = new MembershipUserCollection();

OdbcDataReader reader = null;

try
{
conn.Open();
totalRecords = (int)cmd.ExecuteScalar();

if (totalRecords <= 0) { return users; }

cmd.CommandText = "SELECT PKID, Username, Email, PasswordQuestion," +


" Comment, IsApproved, IsLockedOut, CreationDate, LastLoginDate," +
" LastActivityDate, LastPasswordChangedDate, LastLockedOutDate " +
" FROM Users " +
" WHERE Username LIKE ? AND ApplicationName = ? " +
" ORDER BY Username Asc";

reader = cmd.ExecuteReader();

int counter = 0;
int startIndex = pageSize * pageIndex;
int endIndex = startIndex + pageSize - 1;

while (reader.Read())
{
if (counter >= startIndex)
{
MembershipUser u = GetUserFromReader(reader);
users.Add(u);
}

if (counter >= endIndex) { cmd.Cancel(); }

counter++;
}
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "FindUsersByName");

throw new ProviderException(exceptionMessage);


}
else
{
throw e;
}
}
finally
{
if (reader != null) { reader.Close(); }

conn.Close();
}
return users;
}

//
// MembershipProvider.FindUsersByEmail
//
public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int page
Index, int pageSize, out int totalRecords)
{
OdbcConnection conn = new OdbcConnection(connectionString);
OdbcCommand cmd = new OdbcCommand("SELECT Count(*) FROM Users " +
"WHERE Email LIKE ? AND ApplicationName = ?", conn)
;
cmd.Parameters.Add("@EmailSearch", OdbcType.VarChar, 255).Value = emailToMatch;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = ApplicationName
;

MembershipUserCollection users = new MembershipUserCollection();

OdbcDataReader reader = null;


totalRecords = 0;
try
{
conn.Open();
totalRecords = (int)cmd.ExecuteScalar();

if (totalRecords <= 0) { return users; }


cmd.CommandText = "SELECT PKID, Username, Email, PasswordQuestion," +
" Comment, IsApproved, IsLockedOut, CreationDate, LastLoginDate," +
" LastActivityDate, LastPasswordChangedDate, LastLockedOutDate " +
" FROM Users " +
" WHERE Email LIKE ? AND ApplicationName = ? " +
" ORDER BY Username Asc";
reader = cmd.ExecuteReader();

int counter = 0;
int startIndex = pageSize * pageIndex;
int endIndex = startIndex + pageSize - 1;

while (reader.Read())
{
if (counter >= startIndex)
{
MembershipUser u = GetUserFromReader(reader);
users.Add(u);
}

if (counter >= endIndex) { cmd.Cancel(); }


counter++;
}
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "FindUsersByEmail");

throw new ProviderException(exceptionMessage);


}
else
{
throw e;
}
}
finally
{
if (reader != null) { reader.Close(); }
conn.Close();
}

return users;
}

//
// WriteToEventLog
// A helper function that writes exception detail to the event log. Exceptions
// are written to the event log as a security measure to avoid private database
// details from being returned to the browser. If a method does not return a status
// or boolean indicating the action succeeded or failed, a generic exception is also
// thrown by the caller.
//
private void WriteToEventLog(Exception e, string action)
{
EventLog log = new EventLog();
log.Source = eventSource;
log.Log = eventLog;
string message = "An exception occurred communicating with the data source.\n\n";
message += "Action: " + action + "\n\n";
message += "Exception: " + e.ToString();

log.WriteEntry(message);
}

}
}

See Also
Concepts
Sample Membership Provider Implementation
Other Resources
Managing Users by Using Membership
ASP.NET

How to: Implement a Custom Membership User


Provides an example that illustrates how to extend the MembershipUser class with a custom membership provider.
While the user System.Web.Profile provides a convenient mechanism for storing information per user in a Web application, the
design of your application might require that additional user information be stored with the user authentication information in
the Membership data store. In this case, you would need to build a custom membership provider to store and retrieve the user
authentication information and the additional user values in your data store (for an example of a custom membership
provider, see Implementing a Membership Provider). Additionally, you can extend the MembershipUser class to make the
added user values available to application code.
Creating a custom membership user involves the following tasks:
Create a class that inherits the MembershipUser class.
Create a data source to store authentication information and additional user settings.
Create a custom membership provider for the data store. The custom membership provider will contain additional code
that can receive objects of the custom membership user type as input, as well as return objects of the custom
membership user type.
The examples in this topic show how you can modify the custom membership provider example in
How to: Sample Membership Provider Implementation to support a custom membership user implementation.
Create a Custom Membership User
You can create a custom membership user by creating a class that inherits the MembershipUser class, and then including
properties that expose the additional user values. Optionally, you can add methods and events to the MembershipUser class
as well.
When the Membership class is called to create an instance of your custom MembershipUser, only the constructors defined
by the MembershipUser class will be called. If your MembershipUser implementation includes additional constructor
overloads, those constructors will only be called by application code that is written specifically to call a custom constructor.
The following code example shows a simple custom membership user that inherits the MembershipUser class and provides
two additional properties: IsSubscriber, which is a Boolean property that identifies whether the user subscribes to a service or
newsletter for a Web application; and CustomerID, which contains a unique identifier for a separate customer database.
VB
Imports System
Imports System.Web.Security

Namespace Samples.AspNet.Membership.VB
Public Class OdbcMembershipUser
Inherits MembershipUser

Private _IsSubscriber As Boolean


Private _CustomerID As String

Public Property IsSubscriber() As Boolean


Get
Return _IsSubscriber
End Get
Set(ByVal value As Boolean)
_IsSubscriber = value
End Set
End Property

Public Property CustomerID() As String


Get
Return _CustomerID
End Get
Set(ByVal value As String)
_CustomerID = value
End Set
End Property

Public Sub New(ByVal providername As String, _


ByVal username As String, _
ByVal providerUserKey As Object, _
ByVal email As String, _
ByVal passwordQuestion As String, _
ByVal comment As String, _
ByVal isApproved As Boolean, _
ByVal isLockedOut As Boolean, _
ByVal creationDate As DateTime, _
ByVal lastLoginDate As DateTime, _
ByVal lastActivityDate As DateTime, _
ByVal lastPasswordChangedDate As DateTime, _
ByVal lastLockedOutDate As DateTime, _
ByVal isSubscriber As Boolean, _
ByVal customerID As String)

MyBase.New(providername, _
username, _
providerUserKey, _
email, _
passwordQuestion, _
comment, _
isApproved, _
isLockedOut, _
creationDate, _
lastLoginDate, _
lastActivityDate, _
lastPasswordChangedDate, _
lastLockedOutDate)

Me.IsSubscriber = isSubscriber
Me.CustomerID = customerID
End Sub

End Class
End Namespace

C#
using System;
using System.Web.Security;
namespace Samples.AspNet.Membership.CS
{
public class OdbcMembershipUser : MembershipUser
{
private bool _IsSubscriber;
private string _CustomerID;

public bool IsSubscriber


{
get { return _IsSubscriber; }
set { _IsSubscriber = value; }
}

public string CustomerID


{
get { return _CustomerID; }
set { _CustomerID = value; }
}

public OdbcMembershipUser(string providername,


string username,
object providerUserKey,
string email,
string passwordQuestion,
string comment,
bool isApproved,
bool isLockedOut,
DateTime creationDate,
DateTime lastLoginDate,
DateTime lastActivityDate,
DateTime lastPasswordChangedDate,
DateTime lastLockedOutDate,
bool isSubscriber,
string customerID) :
base(providername,
username,
providerUserKey,
email,
passwordQuestion,
comment,
isApproved,
isLockedOut,
creationDate,
lastLoginDate,
lastActivityDate,
lastPasswordChangedDate,
lastLockedOutDate)
{
this.IsSubscriber = isSubscriber;
this.CustomerID = customerID;
}

}
}

For an example of modifying the CreateUserWizard control to include additional user information for a membership user, see
How to: Customize the ASP.NET CreateUserWizard Control.
Create a Data Store for the Membership User Data
You will need to provide a data store for the user authentication information for the membership feature, as well as the
additional user information for your custom membership user.
The following code example shows a query that you can run in a Microsoft Access database to create a table to store
authentication information and property values for your custom membership user.

CREATE TABLE Users


(
PKID Guid NOT NULL PRIMARY KEY,
Username Text (255) NOT NULL,
ApplicationName Text (255) NOT NULL,
Email Text (128) NOT NULL,
Comment Text (255),
Password Text (128) NOT NULL,
PasswordQuestion Text (255),
PasswordAnswer Text (255),
IsApproved YesNo,
LastActivityDate DateTime,
LastLoginDate DateTime,
LastPasswordChangedDate DateTime,
CreationDate DateTime,
IsOnLine YesNo,
IsLockedOut YesNo,
LastLockedOutDate DateTime,
FailedPasswordAttemptCount Integer,
FailedPasswordAttemptWindowStart DateTime,
FailedPasswordAnswerAttemptCount Integer,
FailedPasswordAnswerAttemptWindowStart DateTime,
IsSubscriber YesNo,
CustomerID Text (64)
)

Create a Custom Membership Provider


You will need to create a custom membership provider that supports both your custom membership user type, and your
custom membership data store. The GetUser and CreateUser methods of the custom membership provider can be written to
return objects of the custom membership user type. The UpdateUser method of the custom membership provider can be
written to receive an object of the custom membership user type as input.
The following sections provide guidance on creating a custom membership provider that uses a custom membership user
type. The examples build on the code provided in How to: Sample Membership Provider Implementation and use the database
schema from the Create a Data Source for the Membership User Data section earlier in this topic.
Modify the GetUser Methods
When working with a custom membership user type, the
System.Web.Security.MembershipProvider.GetUser(System.String,System.Boolean) and
System.Web.Security.MembershipProvider.GetUser(System.Object,System.Boolean) methods of your membership provider
must still return an object of type MembershipUser. Provided your custom membership user class inherits the
MembershipUser class, return an object of your custom membership user type as the return value for your implementation
of the GetUser methods. Application code can then cast the returned MembershipUser as your custom membership user
type to access the additional members of your custom membership user as shown in the following code example.
The following code example shows the modified GetUser methods (and their supporting private method) of the sample
membership provider from How to: Sample Membership Provider Implementation, which have been updated to return the
custom membership user type from the Create a Custom Membership User section earlier in this topic.
VB
'
' MembershipProvider.GetUser(String, Boolean)
'

Public Overrides Function GetUser(ByVal username As String, _


ByVal userIsOnline As Boolean) As MembershipUser

Dim conn As OdbcConnection = New OdbcConnection(connectionString)


Dim cmd As OdbcCommand = New OdbcCommand("SELECT PKID, Username, Email, PasswordQuestio
n," & _
" Comment, IsApproved, IsLockedOut, CreationDate, LastLoginDate," & _
" LastActivityDate, LastPasswordChangedDate, LastLockedOutDate" & _
" FROM Users WHERE Username = ? AND ApplicationName = ?", conn)

cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username


cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicationName

Dim u As OdbcMembershipUser = Nothing


Dim reader As OdbcDataReader = Nothing

Try
conn.Open()

reader = cmd.ExecuteReader()

If reader.HasRows Then
reader.Read()
u = GetUserFromReader(reader)
If userIsOnline Then
Dim updateCmd As OdbcCommand = New OdbcCommand("UPDATE Users " & _
"SET LastActivityDate = ? " & _
"WHERE Username = ? AND Applicationname = ?", conn)
updateCmd.Parameters.Add("@LastActivityDate", OdbcType.DateTime).Value = Da
teTime.Now
updateCmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = userna
me
updateCmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value =
pApplicationName

updateCmd.ExecuteNonQuery()
End If
End If
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "GetUser(String, Boolean)")

Throw New ProviderException(exceptionMessage)


Else
Throw e
End If
Finally
If Not reader Is Nothing Then reader.Close()

conn.Close()
End Try

Return u
End Function

'
' MembershipProvider.GetUser(Object, Boolean)
'
Public Overrides Function GetUser(ByVal providerUserKey As Object, _
ByVal userIsOnline As Boolean) As MembershipUser

Dim conn As OdbcConnection = New OdbcConnection(connectionString)


Dim cmd As OdbcCommand = New OdbcCommand("SELECT PKID, Username, Email, PasswordQuestio
n," & _
" Comment, IsApproved, IsLockedOut, CreationDate, LastLoginDate," & _
" LastActivityDate, LastPasswordChangedDate, LastLockedOutDate" & _
" FROM Users WHERE PKID = ?", conn)

cmd.Parameters.Add("@PKID", OdbcType.UniqueIdentifier).Value = providerUserKey

Dim u As OdbcMembershipUser = Nothing


Dim reader As OdbcDataReader = Nothing

Try
conn.Open()

reader = cmd.ExecuteReader()

If reader.HasRows Then
reader.Read()
u = GetUserFromReader(reader)

If userIsOnline Then
Dim updateCmd As OdbcCommand = New OdbcCommand("UPDATE Users " & _
"SET LastActivityDate = ? " & _
"WHERE PKID = ?", conn)

updateCmd.Parameters.Add("@LastActivityDate", OdbcType.DateTime).Value = Da
teTime.Now
updateCmd.Parameters.Add("@PKID", OdbcType.UniqueIdentifier).Value = provid
erUserKey
updateCmd.ExecuteNonQuery()
End If
End If
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "GetUser(Object, Boolean)")
Throw New ProviderException(exceptionMessage)
Else
Throw e
End If
Finally
If Not reader Is Nothing Then reader.Close()

conn.Close()
End Try

Return u
End Function

'
' GetUserFromReader
' A helper function that takes the current row from the OdbcDataReader
' and hydrates a MembershiUser from the values. Called by the
' MembershipUser.GetUser implementation.
'

Private Function GetUserFromReader(ByVal reader As OdbcDataReader) As OdbcMembershipUser


Dim providerUserKey As Object = reader.GetValue(0)
Dim username As String = reader.GetString(1)
Dim email As String = reader.GetString(2)
Dim passwordQuestion As String = ""
If Not reader.GetValue(3) Is DBNull.Value Then _
passwordQuestion = reader.GetString(3)

Dim comment As String = ""


If Not reader.GetValue(4) Is DBNull.Value Then _
comment = reader.GetString(4)

Dim isApproved As Boolean = reader.GetBoolean(5)


Dim isLockedOut As Boolean = reader.GetBoolean(6)
Dim creationDate As DateTime = reader.GetDateTime(7)

Dim lastLoginDate As DateTime = New DateTime()


If Not reader.GetValue(8) Is DBNull.Value Then _
lastLoginDate = reader.GetDateTime(8)

Dim lastActivityDate As DateTime = reader.GetDateTime(9)


Dim lastPasswordChangedDate As DateTime = reader.GetDateTime(10)

Dim lastLockedOutDate As DateTime = New DateTime()


If Not reader.GetValue(11) Is DBNull.Value Then _
lastLockedOutDate = reader.GetDateTime(11)

Dim isSubscriber As Boolean = False


If reader.GetValue(12) IsNot DBNull.Value Then _
isSubscriber = reader.GetBoolean(12)

Dim customerID As String = String.Empty


If reader.GetValue(13) IsNot DBNull.Value Then _
customerID = reader.GetString(13)
Dim u As OdbcMembershipUser = New OdbcMembershipUser(Me.Name, _
username, _
providerUserKey, _
email, _
passwordQuestion, _
comment, _
isApproved, _
isLockedOut, _
creationDate, _
lastLoginDate, _
lastActivityDate, _
lastPasswordChangedDate, _
lastLockedOutDate, _
isSubscriber, _
customerID)

Return u
End Function

C#
//
// MembershipProvider.GetUser(string, bool)
//

public override MembershipUser GetUser(string username, bool userIsOnline)


{
OdbcConnection conn = new OdbcConnection(connectionString);
OdbcCommand cmd = new OdbcCommand("SELECT PKID, Username, Email, PasswordQuestion," +
" Comment, IsApproved, IsLockedOut, CreationDate, LastLoginDate," +
" LastActivityDate, LastPasswordChangedDate, LastLockedOutDate," +
" IsSubscriber, CustomerID" +
" FROM Users WHERE Username = ? AND ApplicationName = ?", conn);

cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username;


cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicationName;

OdbcMembershipUser u = null;
OdbcDataReader reader = null;

try
{
conn.Open();

reader = cmd.ExecuteReader();

if (reader.HasRows)
{
reader.Read();
u = GetUserFromReader(reader);

if (userIsOnline)
{
OdbcCommand updateCmd = new OdbcCommand("UPDATE Users " +
"SET LastActivityDate = ? " +
"WHERE Username = ? AND Applicationname = ?", conn);

updateCmd.Parameters.Add("@LastActivityDate", OdbcType.DateTime).Value = DateTime.N


ow;
updateCmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username;
updateCmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplic
ationName;

updateCmd.ExecuteNonQuery();
}
}

}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "GetUser(String, Boolean)");

throw new ProviderException(exceptionMessage);


}
else
{
throw e;
}
}
finally
{
if (reader != null) { reader.Close(); }

conn.Close();
}

return u;
}

//
// MembershipProvider.GetUser(object, bool)
//

public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)


{
OdbcConnection conn = new OdbcConnection(connectionString);
OdbcCommand cmd = new OdbcCommand("SELECT PKID, Username, Email, PasswordQuestion," +
" Comment, IsApproved, IsLockedOut, CreationDate, LastLoginDate," +
" LastActivityDate, LastPasswordChangedDate, LastLockedOutDate," +
" IsSubscriber" +
" FROM Users WHERE PKID = ?", conn);

cmd.Parameters.Add("@PKID", OdbcType.UniqueIdentifier).Value = providerUserKey;

OdbcMembershipUser u = null;
OdbcDataReader reader = null;

try
{
conn.Open();

reader = cmd.ExecuteReader();
if (reader.HasRows)
{
reader.Read();
u = GetUserFromReader(reader);

if (userIsOnline)
{
OdbcCommand updateCmd = new OdbcCommand("UPDATE Users " +
"SET LastActivityDate = ? " +
"WHERE PKID = ?", conn);

updateCmd.Parameters.Add("@LastActivityDate", OdbcType.DateTime).Value = DateTime.N


ow;
updateCmd.Parameters.Add("@PKID", OdbcType.UniqueIdentifier).Value = providerUserKe
y;

updateCmd.ExecuteNonQuery();
}
}

}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "GetUser(Object, Boolean)");

throw new ProviderException(exceptionMessage);


}
else
{
throw e;
}
}
finally
{
if (reader != null) { reader.Close(); }

conn.Close();
}

return u;
}

//
// GetUserFromReader
// A helper function that takes the current row from the OdbcDataReader
// and hydrates a MembershipUser from the values. Called by the
// MembershipUser.GetUser implementation.
//

private OdbcMembershipUser GetUserFromReader(OdbcDataReader reader)


{
object providerUserKey = reader.GetValue(0);
string username = reader.GetString(1);
string email = reader.GetString(2);

string passwordQuestion = "";


if (reader.GetValue(3) != DBNull.Value)
passwordQuestion = reader.GetString(3);

string comment = "";


if (reader.GetValue(4) != DBNull.Value)
comment = reader.GetString(4);

bool isApproved = reader.GetBoolean(5);


bool isLockedOut = reader.GetBoolean(6);
DateTime creationDate = reader.GetDateTime(7);

DateTime lastLoginDate = new DateTime();


if (reader.GetValue(8) != DBNull.Value)
lastLoginDate = reader.GetDateTime(8);

DateTime lastActivityDate = reader.GetDateTime(9);


DateTime lastPasswordChangedDate = reader.GetDateTime(10);

DateTime lastLockedOutDate = new DateTime();


if (reader.GetValue(11) != DBNull.Value)
lastLockedOutDate = reader.GetDateTime(11);

bool isSubscriber = false;


if (reader.GetValue(12) != DBNull.Value)
isSubscriber = reader.GetBoolean(12);

string customerID = String.Empty;


if (reader.GetValue(13) != DBNull.Value)
customerID = reader.GetString(13);
OdbcMembershipUser u = new OdbcMembershipUser(this.Name,
username,
providerUserKey,
email,
passwordQuestion,
comment,
isApproved,
isLockedOut,
creationDate,
lastLoginDate,
lastActivityDate,
lastPasswordChangedDate,
lastLockedOutDate,
isSubscriber,
customerID);

return u;
}

Modify the UpdateUser Method


When working with a custom membership user type and a custom membership provider, implement an UpdateUser method
that takes an object of type MembershipUser as input. In your implementation of the UpdateUser method, cast the supplied
MembershipUser object as your custom membership user type to access the values of the additional properties and update
them in the data store.
The following code example shows the modified UpdateUser method of the sample membership provider from
How to: Sample Membership Provider Implementation, which has been updated to cast the supplied user as the custom
membership user type from the Create a Custom Membership User section earlier in this topic.
VB
Public Overrides Sub UpdateUser(ByVal user As MembershipUser)

Dim conn As OdbcConnection = New OdbcConnection(connectionString)


Dim cmd As OdbcCommand = New OdbcCommand("UPDATE Users " & _
" SET Email = ?, Comment = ?," & _
" IsApproved = ?, IsSubscriber= ?, CustomerID = ?" & _
" WHERE Username = ? AND ApplicationName = ?", conn)

Dim u As OdbcMembershipUser = CType(user, OdbcMembershipUser)

cmd.Parameters.Add("@Email", OdbcType.VarChar, 128).Value = user.Email


cmd.Parameters.Add("@Comment", OdbcType.VarChar, 255).Value = user.Comment
cmd.Parameters.Add("@IsApproved", OdbcType.Bit).Value = user.IsApproved
cmd.Parameters.Add("@IsSubscriber", OdbcType.Bit).Value = u.IsSubscriber
cmd.Parameters.Add("@CustomerID", OdbcType.VarChar, 128).Value = u.CustomerID
cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = user.UserName
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicationName

Try
conn.Open()

cmd.ExecuteNonQuery()
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "UpdateUser")

Throw New ProviderException(exceptionMessage)


Else
Throw e
End If
Finally
conn.Close()
End Try
End Sub

C#
public override void UpdateUser(MembershipUser user)
{
OdbcConnection conn = new OdbcConnection(connectionString);
OdbcCommand cmd = new OdbcCommand("UPDATE Users " +
" SET Email = ?, Comment = ?," +
" IsApproved = ?, IsSubscriber = ?, CustomerID = ?" +
" WHERE Username = ? AND ApplicationName = ?", conn);

OdbcMembershipUser u = (OdbcMembershipUser)user;

cmd.Parameters.Add("@Email", OdbcType.VarChar, 128).Value = user.Email;


cmd.Parameters.Add("@Comment", OdbcType.VarChar, 255).Value = user.Comment;
cmd.Parameters.Add("@IsApproved", OdbcType.Bit).Value = user.IsApproved;
cmd.Parameters.Add("@IsSubscriber", OdbcType.Bit).Value = u.IsSubscriber;
cmd.Parameters.Add("@CustomerID", OdbcType.VarChar, 128).Value = u.CustomerID;
cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = user.UserName;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicationName;

try
{
conn.Open();

cmd.ExecuteNonQuery();
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "UpdateUser");

throw new ProviderException(exceptionMessage);


}
else
{
throw e;
}
}
finally
{
conn.Close();
}
}

Modify the CreateUser Method


When working with a custom membership user type and a custom membership provider, the custom membership provider
must implement a CreateUser method that takes only the properties supported by the MembershipUser class as input. You
can create an overload of the CreateUser method that takes additional property values as shown in the following code
example.
However, this overload will not be called by the Membership class or controls that rely on the Membership class, such as the
CreateUserWizard control. To call this method from an application, cast the MembershipProvider instance referenced by the
Membership class as your custom membership provider type, and then call your CreateUseroverload directly.
If your application is using the CreateUserWizard control to add new users to your membership data source, you can
customize the wizard steps of the CreateUserWizard control to include controls that retrieve the additional property values of
your custom membership user. You can then handle the CreatedUser event of the CreateUserWizard control and add event
code that does the following:
Retrieves the property values of the additional membership user.
Casts the membership user created by the CreateUserWizard control as your custom membership user type.
Sets the additional properties on the membership user.
Passes the updated user to the UpdateUser method of the Membership class. This will call the UpdateUser method of
your custom provider (which is described in the Modify the UpdateUser Method section earlier in this topic) to add the
additional property values to your data source.
Note
For an example of modifying the steps of the CreateUserWizard, see
How to: Customize the ASP.NET CreateUserWizard Control.

The following code example shows the modified CreateUser method of the sample membership provider from
How to: Sample Membership Provider Implementation, which has been updated to return the custom membership user type
from the Create a Custom Membership User section earlier in this topic. An overload has been created to take values for the
additional properties of the custom membership provider as input.
VB
'
' MembershipProvider.CreateUser
'

Public Overrides Function CreateUser(ByVal username As String, _


ByVal password As String, _
ByVal email As String, _
ByVal passwordQuestion As String, _
ByVal passwordAnswer As String, _
ByVal isApproved As Boolean, _
ByVal providerUserKey As Object, _
ByRef status As MembershipCreateStatus) _
As MembershipUser
Return Me.CreateUser(username, password, email, _
passwordQuestion, passwordAnswer, _
isApproved, providerUserKey, False, "", status)
End Function

'
' OdbcMembershipProvider.CreateUser -- returns OdbcMembershipUser
'

Public Overloads Function CreateUser(ByVal username As String, _


ByVal password As String, _
ByVal email As String, _
ByVal passwordQuestion As String, _
ByVal passwordAnswer As String, _
ByVal isApproved As Boolean, _
ByVal providerUserKey As Object, _
ByVal isSubscriber As Boolean, _
ByVal customerID As String, _
ByRef status As MembershipCreateStatus) _
As OdbcMembershipUser

Dim Args As ValidatePasswordEventArgs = _


New ValidatePasswordEventArgs(username, password, True)

OnValidatingPassword(Args)

If Args.Cancel Then
status = MembershipCreateStatus.InvalidPassword
Return Nothing
End If

If RequiresUniqueEmail AndAlso GetUserNameByEmail(email) <> "" Then


status = MembershipCreateStatus.DuplicateEmail
Return Nothing
End If

Dim u As MembershipUser = GetUser(username, False)


If u Is Nothing Then
Dim createDate As DateTime = DateTime.Now

If providerUserKey Is Nothing Then


providerUserKey = Guid.NewGuid()
Else
If Not TypeOf providerUserKey Is Guid Then
status = MembershipCreateStatus.InvalidProviderUserKey
Return Nothing
End If
End If

Dim conn As OdbcConnection = New OdbcConnection(connectionString)


Dim cmd As OdbcCommand = New OdbcCommand("INSERT INTO Users " & _
" (PKID, Username, Password, Email, PasswordQuestion, " & _
" PasswordAnswer, IsApproved," & _
" Comment, CreationDate, LastPasswordChangedDate, LastActivityDate," & _
" ApplicationName, IsLockedOut, LastLockedOutDate," & _
" FailedPasswordAttemptCount, FailedPasswordAttemptWindowStart, " & _
" FailedPasswordAnswerAttemptCount, FailedPasswordAnswerAttemptWindowStart,
" & _
" IsSubscriber, CustomerID)" & _
" Values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", conn)

cmd.Parameters.Add("@PKID", OdbcType.UniqueIdentifier).Value = providerUserKey


cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username
cmd.Parameters.Add("@Password", OdbcType.VarChar, 255).Value = EncodePassword(passw
ord)
cmd.Parameters.Add("@Email", OdbcType.VarChar, 128).Value = email
cmd.Parameters.Add("@PasswordQuestion", OdbcType.VarChar, 255).Value = passwordQues
tion
cmd.Parameters.Add("@PasswordAnswer", OdbcType.VarChar, 255).Value = EncodePassword
(passwordAnswer)
cmd.Parameters.Add("@IsApproved", OdbcType.Bit).Value = isApproved
cmd.Parameters.Add("@Comment", OdbcType.VarChar, 255).Value = ""
cmd.Parameters.Add("@CreationDate", OdbcType.DateTime).Value = createDate
cmd.Parameters.Add("@LastPasswordChangedDate", OdbcType.DateTime).Value = createDat
e
cmd.Parameters.Add("@LastActivityDate", OdbcType.DateTime).Value = createDate
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicationN
ame
cmd.Parameters.Add("@IsLockedOut", OdbcType.Bit).Value = False
cmd.Parameters.Add("@LastLockedOutDate", OdbcType.DateTime).Value = createDate
cmd.Parameters.Add("@FailedPasswordAttemptCount", OdbcType.Int).Value = 0
cmd.Parameters.Add("@FailedPasswordAttemptWindowStart", OdbcType.DateTime).Value =
createDate
cmd.Parameters.Add("@FailedPasswordAnswerAttemptCount", OdbcType.Int).Value = 0
cmd.Parameters.Add("@FailedPasswordAnswerAttemptWindowStart", OdbcType.DateTime).Va
lue = createDate
cmd.Parameters.Add("@IsSubscriber", OdbcType.Bit).Value = isSubscriber
cmd.Parameters.Add("@CustomerID", OdbcType.VarChar, 128).Value = customerID

Try
conn.Open()

Dim recAdded As Integer = cmd.ExecuteNonQuery()

If recAdded > 0 Then


status = MembershipCreateStatus.Success
Else
status = MembershipCreateStatus.UserRejected
End If
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "CreateUser")
End If
status = MembershipCreateStatus.ProviderError
Finally
conn.Close()
End Try

Return GetUser(username, False)


Else
status = MembershipCreateStatus.DuplicateUserName
End If

Return Nothing
End Function

C#
//
// MembershipProvider.CreateUser
//

public override MembershipUser CreateUser(string username,


string password,
string email,
string passwordQuestion,
string passwordAnswer,
bool isApproved,
object providerUserKey,
out MembershipCreateStatus status)
{
return this.CreateUser(username, password, email,
passwordQuestion, passwordAnswer,
isApproved, providerUserKey, false, "",
out status);
}

//
// OdbcMembershipProvider.CreateUser -- returns OdbcMembershipUser
//

public OdbcMembershipUser CreateUser(


string username,
string password,
string email,
string passwordQuestion,
string passwordAnswer,
bool isApproved,
object providerUserKey,
bool isSubscriber,
string customerID,
out MembershipCreateStatus status)
{
ValidatePasswordEventArgs args =
new ValidatePasswordEventArgs(username, password, true);

OnValidatingPassword(args);

if (args.Cancel)
{
status = MembershipCreateStatus.InvalidPassword;
return null;
}

if (RequiresUniqueEmail && GetUserNameByEmail(email) != "")


{
status = MembershipCreateStatus.DuplicateEmail;
return null;
}

MembershipUser u = GetUser(username, false);

if (u == null)
{
DateTime createDate = DateTime.Now;

if (providerUserKey == null)
{
providerUserKey = Guid.NewGuid();
}
else
{
if ( !(providerUserKey is Guid) )
{
status = MembershipCreateStatus.InvalidProviderUserKey;
return null;
}
}

OdbcConnection conn = new OdbcConnection(connectionString);


OdbcCommand cmd = new OdbcCommand("INSERT INTO Users " +
" (PKID, Username, Password, Email, PasswordQuestion, " +
" PasswordAnswer, IsApproved," +
" Comment, CreationDate, LastPasswordChangedDate, LastActivityDate," +
" ApplicationName, IsLockedOut, LastLockedOutDate," +
" FailedPasswordAttemptCount, FailedPasswordAttemptWindowStart, " +
" FailedPasswordAnswerAttemptCount, FailedPasswordAnswerAttemptWindowStart, " +
" IsSubscriber, CustomerID)" +
" Values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", conn);

cmd.Parameters.Add("@PKID", OdbcType.UniqueIdentifier).Value = providerUserKey;


cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username;
cmd.Parameters.Add("@Password", OdbcType.VarChar, 255).Value = EncodePassword(password)
;
cmd.Parameters.Add("@Email", OdbcType.VarChar, 128).Value = email;
cmd.Parameters.Add("@PasswordQuestion", OdbcType.VarChar, 255).Value = passwordQuestion
;
cmd.Parameters.Add("@PasswordAnswer", OdbcType.VarChar, 255).Value = EncodePassword(pas
swordAnswer);
cmd.Parameters.Add("@IsApproved", OdbcType.Bit).Value = isApproved;
cmd.Parameters.Add("@Comment", OdbcType.VarChar, 255).Value = "";
cmd.Parameters.Add("@CreationDate", OdbcType.DateTime).Value = createDate;
cmd.Parameters.Add("@LastPasswordChangedDate", OdbcType.DateTime).Value = createDate;
cmd.Parameters.Add("@LastActivityDate", OdbcType.DateTime).Value = createDate;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicationName;
cmd.Parameters.Add("@IsLockedOut", OdbcType.Bit).Value = false;
cmd.Parameters.Add("@LastLockedOutDate", OdbcType.DateTime).Value = createDate;
cmd.Parameters.Add("@FailedPasswordAttemptCount", OdbcType.Int).Value = 0;
cmd.Parameters.Add("@FailedPasswordAttemptWindowStart", OdbcType.DateTime).Value = crea
teDate;
cmd.Parameters.Add("@FailedPasswordAnswerAttemptCount", OdbcType.Int).Value = 0;
cmd.Parameters.Add("@FailedPasswordAnswerAttemptWindowStart", OdbcType.DateTime).Value
= createDate;
cmd.Parameters.Add("@IsSubscriber", OdbcType.Bit).Value = isSubscriber;
cmd.Parameters.Add("@CustomerID", OdbcType.VarChar, 128).Value = customerID;

try
{
conn.Open();

int recAdded = cmd.ExecuteNonQuery();

if (recAdded > 0)
{
status = MembershipCreateStatus.Success;
}
else
{
status = MembershipCreateStatus.UserRejected;
}
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "CreateUser");
}

status = MembershipCreateStatus.ProviderError;
}
finally
{
conn.Close();
}

return (OdbcMembershipUser)GetUser(username, false);


}
else
{
status = MembershipCreateStatus.DuplicateUserName;
}

return null;
}

See Also
Concepts
Implementing a Membership Provider
Other Resources
Managing Users by Using Membership
Visual Web Developer

Managing Authorization Using ASP.NET Roles (Visual Studio)


ASP.NET role management helps you to manage authorization, allowing you to specify which resources users in your
application are allowed to access. Role management lets you treat groups of users as a unit by assigning users to roles.
In This Section
Understanding Role Management
Walkthrough: Managing Web Site Users with Roles
Role Management Classes
Role Management Providers
Securing Roles
Implementing a Role Provider
Reference
System.Web.Security
Describes the classes you need for ASP.NET security features.
See Also
Other Resources
Managing Users by Using Membership
ASP.NET Web Site Security (Visual Studio)
ASP.NET

Understanding Role Management


Role management helps you to manage authorization, allowing you to specify the resources users in your application are
allowed to access. Role management 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 independent from individual application users.
For example, you do not have to grant individual members of your site access to member-only pages; instead, you can grant
access to the role of member and then simply add and remove users from that role as people sign up or allow their
memberships to lapse.
Users can belong to more than one role. For example, if your site is a discussion forum, some users might be in the roles of
both member and moderator. You might define each role to have different privileges on the site, and a user who is in both
roles would then have both sets of privileges.
Even if your application has only a few users, you might still find it convenient to create roles. Roles give you flexibility to
change permissions and add and remove users without having to make changes throughout the site. As you define more
access rules for your application, roles become a more convenient way to apply the changes to groups of users.
Roles and Access Rules
The primary purpose of establishing roles is to provide you with an easy way to manage access rules for groups of users. You
create users and then assign the users to roles (in Windows, to groups). A typical use is to then create a set of pages that you
want to restrict to certain users. Often you isolate these restricted pages in a folder by themselves. Then you can use the Web
Site Administration Tool to define rules that grant and deny access to restricted folders. For example, you can configure the site
so that members or managers have access to the pages in the restricted folder and all other users are denied access. If an
unauthorized user tries to view a restricted page, the user either sees an error or is redirected to a page that you specify.
Role Management, User Identity, and Membership
To work with roles, you must be able to identify users in your application so that you can determine whether the user is in a
specific role. You can configure your application to establish user identity in two ways: Windows authentication and Forms
authentication. If your application runs in a local area network (that is, in a domain-based intranet application), you can identify
users using their Windows domain account name. In that case, a user's roles are the Windows groups that the user belongs to.
In Internet applications or other scenarios where it is impractical to use Windows accounts, you can use Forms authentication
to establish user identity. For this task, you typically create a page where users can enter a user name and password and then
you validate the user's credentials. The ASP.NET Login controls can perform much of this work for you, or you can create a
login page and use the FormsAuthentication class to establish a user identity.
Note
Roles do not work with users who have not established an identity in your application (anonymous users).

If you use Login controls or Forms authentication to establish user identity, you can also use role management in conjunction
with membership. In this scenario, you use membership to define users and passwords. You can then use role management to
define roles and assign membership user IDs to those roles. However, role management does not depend on membership. As
long as you have a way in your application to set user identity, you can still use role management for authorization.
Role Management API
Role management is not limited to restricting rights to pages or folders. Role management provides an API that you can use to
determine programmatically whether a user is in a role. This allows you to write code to take advantage of roles and perform
any application tasks based not only on who the user is but also on what roles the user is in.
If you establish user identity in your application, you can use the role-management API methods for creating roles, adding
users to roles, and getting information about which users are in which roles. These methods enable you to create your own
interface for managing roles.
If your application uses Windows authentication, the role management API offers fewer facilities for role management. For
example, you cannot use role management to create new roles. Instead, you use Windows user and group management to
create user accounts and groups and assign users to groups. Role management can then read Windows user and group
information so that you can use the information for authentication.
How ASP.NET Role Management Works
To work with role management, you first enable it and optionally configure access rules that can take advantage of roles. You
can then use role management functions at run time to work with the roles.
Note
The easiest way to configure role management, define roles, add users to roles, and create access rules is to use the Web Site
Administration Tool.

Role Management Configuration


To use ASP.NET role management, you enable it in your application's Web.config file using a setting such as the following:

<roleManager
enabled="true"
cacheRolesInCookie="true" >
</roleManager>

A typical use for roles is to establish rules that allow or deny access to pages or folders. You can set up such access rules in the
authorization Element (ASP.NET Settings Schema) section of the Web.config file. The following example allows users in the role
of members to view pages in the folder called memberPages and denies access to anyone else:

<configuration>
<location path="memberPages">
<system.web>
<authorization>
<allow roles="members" />
<deny users="*" />
</authorization>
</system.web>
</location>
<!-- other configuration settings here -->
<configuration>

For more information about setting up access rules, see ASP.NET Authorization.
You must also create roles such as manager or member and assign user IDs to the roles. If your application uses Windows
authentication, you use the Windows Computer Management tool to create users and groups.
If you are using Forms authentication, the easiest way to set up users and roles is with the ASP.NET Web Site Administration
Tool. If you prefer, you can perform this task programmatically by calling various role-manager methods. The following code
example demonstrates how you can create the role members:
VB
Roles.CreateRole("members")

C#
Roles.CreateRole("members");

The following code example demonstrates how you can add the user JoeWorden individually to the role manager, and how you
can add the users JillShrader and ShaiBassli to the role members all at once:
VB
Roles.AddUsersToRole("JoeWorden", "manager")
Dim userGroup(2) As String
userGroup(0) = "JillShrader"
userGroup(1) = "ShaiBassli"
Roles.AddUsersToRole(userGroup, "members")
C#
Roles.AddUsersToRole("JoeWorden", "manager");
string[] userGroup = new string[2];
userGroup[0] = "JillShrader";
userGroup[1] = "ShaiBassli";
Roles.AddUsersToRole(userGroup, "members");

Working with Roles at Run Time


At run time, when users visit your site, they establish an identity, either as a Windows account name or by logging into your
application. (In an Internet site, if users visit your site without logging in — that is, anonymously — they will have no user
identity and therefore will not be in any role.) Information about the logged-in user is available to your application from the
User property. When roles are enabled, ASP.NET looks up the roles for the current user and adds them to the User object so
that you can check them. The following code example demonstrates how you can determine whether the current user is in the
role of member, and if so, it displays a button for members:
VB
If User.IsInRole("members") Then
buttonMembersArea.Visible = True
End If

C#
if (User.IsInRole("members"))
{
buttonMembersArea.Visible = True;
;

ASP.NET also creates an instance of the RolePrincipal class and adds it to the current request context so that you can perform
role management tasks programmatically, such as determining what users are in a specific role. . The following code example
demonstrates how you can get a list of the roles for the current logged-in user.
VB
Dim userRoles() as String = CType(User, RolePrincipal).GetRoles()

C#
string[] userRoles = ((RolePrincipal)User).GetRoles();

If you are using the LoginView control in your application, the control will check the user's roles and can dynamically create a
user interface based on the user's roles.
Caching Role Information
If a user's browser allows cookies, ASP.NET can optionally store role information in an encrypted cookie on the user's
computer. On each page request, ASP.NET reads the cookie and populates the role information for that user from the cookie.
This strategy minimizes the need to read role information from the database. If the user's browser does not support cookies or
if cookies are disabled, role information is instead cached only for the duration of each page request.
See Also
Concepts
Role Management Providers
Role Management Classes
Other Resources
ASP.NET Web Site Security
Visual Web Developer

Walkthrough: Managing Web Site Users with Roles


Many ASP.NET applications involve membership — authenticating users so that they have access to restricted resources, such
as members-only pages. If the application will support many users, or if the list of users is likely to change over time, consider
establishing roles to manage user access. A role is the name of a group, such as managers, sales, or members. After
establishing roles, you can assign individual users to a role. Then, you can grant permissions to a role, and every user in that
role inherits the permissions you have assigned. Roles are therefore an efficient way to manage permissions for groups of
users.
During this walkthrough, you will learn how to:
Establish roles for an application.
Assign users to roles.
Create rules (permissions) that selectively grant or deny access to pages for different rules.
Programmatically determine whether a user is in a particular role and which roles the current user is in.
Prerequisites
In order to complete this walkthrough, you will need:
Visual Studio.
The .NET Framework.
IIS installed locally on your computer.
SQL Server Express Edition installed locally on your computer.
A way to identify individual users.
Note
In working applications, you can identify users in various ways, including by their Windows user account. However, in t
his walkthrough, users will identify themselves by logging in to your site. Therefore, this walkthrough requires that you
have a site configured to use ASP.NET membership. If you have a site already configured with membership, you can us
e that site as a starting point for this walkthrough.

Configuring a Web Site, Membership, and Roles


Before you work with ASP.NET roles, you must have a Web site available, and configure the site to enable membership and set
up user roles. If you have completed the topic
Walkthrough: Creating a Web Site with Membership and User Login (Visual Studio), you can use the Web site that you
configured in that walkthrough.
If you do not already have a Web site available, use the following procedure to create one. Otherwise, go to the next section
"Creating Folders for Member-Only Pages."
To create a local IIS Web site
1. Open Visual Studio.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, select ASP.NET Web Site.
4. In the Location list box, select File System.
5. Click Browse, and then select a directory for your application, such as C:\RolesWebSite.
6. In the Languages box, click the programming language that you prefer to work in.
The programming language you choose will be the default for your Web site, but you can set the programming
languages for each page individually.
7. Click OK in the New Web Site dialog box.
Visual Web Developer creates the Web site and a new page named Default.aspx.
Creating Folders for Member-Only Pages
In order to work with roles, you will need to create two folders, MemberPages and GuestPages, where you can keep pages
that have restricted access.
Note
If you are re-using the Web site from the membership walkthrough, you probably already have this folder and can skip step
1 of the following procedure.

To create folders for restricted access


1. In Solution Explorer, right-click the root of your Web site, click New Folder, and then name the folder
MemberPages.
This folder will contain a page that is accessible to only some of your users.
2. Right-click the root of your Web site, click New Folder, and then name the folder GuestPages.
This folder will contain a page accessible to any logged-in user (but not to anonymous users).
Configuring the Web Site for Membership and Roles
After creating the basic Web site, you can configure it to use membership and roles.
To configure the Web site for membership and roles
1. On the Web site menu, click ASP.NET Configuration.
2. Select the Security tab, click the link to Use the security Setup Wizard to configure security step by step, and then
click Next.
3. Proceed to Step 2 of the wizard and select the From the Internet option.
The wizard displays a page where you can select the authentication method that your Web site will use.
This option specifies that your application will use Forms authentication, where users will log into the application using a
login page that you will create later in this walkthrough.
4. Click Next.
The wizard displays a message stating that user information will be stored using Advanced provider settings. Your
application will use the default provider, which stores membership information in a SQL Server Express Edition database
file in the App_Data folder of your Web site.
5. Click Next again.
6. In Step 4: Define Roles, select the Enable roles for this Web site check box, and then click Next.
7. When prompted, create two roles, members and guests, and then click Next.
8. In Step 5: Add New Users, create three users named member1, guest1, and memberGuest.
You can assign any strong passwords you like, but be sure to remember them. Passwords must be at least 7 characters
long, and at least one of the characters must be non-alphanumeric. For the e-mail address, use your own. (You will not be
sending e-mail messages in this walkthrough.)
Note
Do not close the Web Site Administration Tool yet.

The Web site that you are creating will allow users to gain access to different pages according to their roles. Therefore, you
need to create some access rules that determine which roles have access to which folders.
To set up access rules for the site folders
1. In the security wizard of the Web Site Administration Tool, click Next.
Step 6: Add New Access Rules displays a page where you can create rules that determine which roles (or users) can
gain access to the pages in your Web site.
2. Under Select a directory for this rule, expand the root node, and then click GuestPages.
3. Under Rule applies to, select Anonymous Users.
4. Under Permission, select Deny.
The rule you are creating denies access to anonymous users — that is, users who have not logged in.
5. Click Add This Rule.
The new rule is displayed in the grid at the bottom of the page. When users request a page from the GuestPages
directory, the rules are checked in order, from top to bottom, to determine whether the user is allowed access to the
page. If the user is not logged in, the pages in this folder will not be displayed.
6. Under Select a directory for this rule, click MemberPages.
7. Under Rule applies to, select Role, and then in the drop-down list, click members.
8. Under Permission, select Allow.
The rule you are creating grants access permissions for the MemberPages folder to anyone in the members role.
9. Click Add This Rule.
10. Under Select a directory for this rule, click MemberPages.
11. Under Rule applies to, select All Users.
12. Under Permission, select Deny.
13. Click Add This Rule.
The second rule for the MemberPages folder makes sure that no one except users in the members role can gain access
to the folder. The rules are processed in order, from top to bottom, as you see them in the grid.
The first rule (Allow) grants access to users in the role named members. The second rule (Deny) denies access to all other
users. You can create as many Allow or Deny rules as you need for your application. When users request a page from the
MemberPages directory, the rules are applied in order, from top to bottom, to determine whether the user is allowed
access to the page.
14. Click Finish to return to the Security tab.
Note
Do not close the Web Site Administration Tool yet.

Assigning Users to Roles


You must perform one last configuration step: assigning the users you have created to roles.
To assign users to roles
1. On the Security tab of the Web Site Administration Tool, under Users, click Manage users.
2. In the row for guest1, click Edit Roles.
The Roles box is filled in with a list of available roles.
3. Select the guests check box to assign the user guest1 to the role guests.
4. In the row for member1, click Edit Roles and assign the user member1 to the role members.
5. Using the same technique, assign the user memberGuest to both the guests and members roles.
6. Close the Web Site Administration tool, and then do the following:
a. In Solution Explorer, click the refresh icon.
b. On the Web site menu, click ASP.NET Configuration to restart the Web Site Administration tool.
This ensures that the connection to the Membership database that was used by the Web Site Administration tool is
closed.
c. Close the Web Site Administration tool again.
Adding Pages with Restricted Access
To test your membership and role settings, you need to create a way for users to log in so that you can identify them. You must
also create some Web pages that will allow you to test the access rules you have created.
To create a default page for all users
1. Switch to Visual Studio.
2. Open or switch to the Default.aspx page, and then switch to Design view.
If you do not have a Default.aspx page, add one to the root of your Web site.
Note
Be sure to name the page Default.aspx; this name is used later in the walkthrough.

3. Add a heading with text, such as Welcome!


4. In the Toolbox, from the Login group, drag a LoginStatus control onto the page.
When clicked, the LoginStatus control takes users to the Login.aspx page if they have not already logged in.
5. From the Login group in the Toolbox, drag a LoginName control onto the page. Set the FormatString property to
"Hello {0}."
The LoginName control will display the user's name if the user is logged in.
6. In the Toolbox, from the Standard group, drag a HyperLink control onto the page. In the Properties panel for the
HyperLink control, set the Text property to Guests and Members and the NavigateUrl property to
~/GuestPages/Guests.aspx.
Note
You will create the Guests.aspx page later in this walkthrough.

7. In the Toolbox, from the Standard group, drag another HyperLink control onto the page. In the Properties panel for
the HyperLink control, set the Text property to Members and the NavigateUrl property to
~/MemberPages/Members.aspx.
Note
You will create the Members.aspx page later in this walkthrough.

You now have a home page that is available to all users. From here, users can link to additional pages, some of which will be
restricted. The next step is to create a simple login page.
To create a login page
1. In Solution Explorer, right-click the root folder of your Web site and select Add New Item. Add a Web Form named
Login.aspx to your Web site.
2. In the Login.aspx page, switch to Design view.
3. In the Toolbox, from the Login group, drag a Login control onto the page.
4. In the Properties panel for the Login control, set the DestinationPageUrl property to ~/Default.aspx.
Finally, you need to create some pages that represent the restricted content of your site.
To create restricted pages
1. In Solution Explorer, right-click the GuestPages folder, click Add New Item, and add a Web Form named
Guests.aspx in this folder.
2. Switch to Design view and add a heading to the Guests.aspx page, such as Welcome to the Guests page!
3. In the Toolbox, from the Standard group, drag a HyperLink control onto the page. In the Properties panel for the
HyperLink control, set the Text property to Home and the NavigateUrl property to ~/Default.aspx.
4. In Solution Explorer, right-click the MemberPages folder, select Add New Item, and add a Web Form named
Members.aspx.
5. Switch to Design view and add a heading to the Members.aspx page, such as Welcome to the Members page!
6. In the Toolbox, from the Standard group, drag a HyperLink control onto the page.
7. In the Properties panel for the HyperLink control, set the Text property to Home and the NavigateUrl property to
~/Default.aspx.
You do not have to add any code to the pages to restrict access to them. They are restricted because they reside in folders
that are protected with access rules.
Testing Roles
Your site is now ready for testing.
To test roles
1. Switch to the Default.aspx page, and then press CTRL+F5 to run it.
2. Click Guests and Members.
You are redirected to the Login.aspx page because you are attempting to access a page that does not allow anonymous
users.
3. Log in as guest1, who is in the role of guests.
After you log in successfully, you are redirected to the Guests.aspx page.
Click Home to return to the Default.aspx page.
The Default.aspx page displays the text Hello, guest1 where you put the LoginName control. In addition, the
LoginStatus control has changed text from Login to Logout, because you are now logged in as guest1.
4. Click Guests and Members.
This time, you go straight to the Guests.aspx page because you are already logged in as a user in the role of guests.
5. Click Home to return to the Default.aspx page.
6. Click Members.
You are redirected to the Login.aspx page because guest1 does not have permissions for the Members.aspx page.
7. Log in either as member1 or as memberGuest.
You are redirected to the Members.aspx page because you are now logged in as a user in the role of members.
8. Click Home to return to the Default.aspx page.
The page now reflects your new login name.
Next Steps
This walkthrough illustrates the basic functionality of ASP.NET role management. You might want to experiment with
additional features of role management. For example, you might want to:
Work with Windows roles instead of custom roles that you create in the membership system.
Work programmatically with roles. For details, see Managing Authorization Using Roles.
Alternatively, you can create a custom provider that allows you to use an existing or custom data store for membership
and role information. For more information, see Implementing a Role Provider.
Apply access rules to links that are displayed in the navigational structure of your Web site. For more information, see
Walkthrough: Filtering Site-Map Nodes Based on Security Roles.
See Also
Tasks
Walkthrough: Creating a Web Site with Membership and User Login (Visual Studio)
Walkthrough: Filtering Site-Map Nodes Based on Security Roles
Reference
AuthorizationSection
Concepts
Understanding Role Management
ASP.NET

Role Management Classes


Role management consists of a set of classes and interfaces that establish roles for the current user and manage role
information. The following table shows the role management classes and functions that they provide.
Class/Interface Functions
Roles Creates roles.
Provides general management facilities f Adds users to roles.
or roles.
Determines whether specific user is in role.
Gets roles for users.
Removes users from role.
Manages the cookie containing role information.
Note
The functions for creating roles and assigning users to them do not work if you are
using the WindowsTokenRoleProvider. In that case, you manage role information us
ing Windows.

RoleProvider Defines the functionality a provider must implement to be used by the Roles class.
Defines functionality for data providers t
hat can be used by role-management se
rvices.

RoleManagerModule Automatically creates a RolePrincipal and attaches it to the current context.


Adds role information to the current Us Raises a GetRoles event that allows you to customize the process of adding roles to t
er property. he current user context.

RoleManagerEventArgs Provides access to the current user context during the GetRoles event.
Defines arguments passed to the RoleM
anager_GetRoles event.

RolePrincipal Stores role information for the current user.


Acts as a IPrincipal object and caches the Manages retrieval of role information from either the cookie or the database (or both
roles for a user. , if necessary).

See Also
Concepts
Understanding Role Management
Role Management Providers
Other Resources
ASP.NET Web Site Security
ASP.NET

Role Management Providers


Role management services use the provider model to separate the functionality of role management — the API — from the
data store that contains role information. The .NET Framework includes the following providers that maintain role information
in different data stores:
SQL Server. Role information is stored in a SQL Server database. The SQL provider is suitable for medium to large
Internet applications. This is the default provider.
Windows (WindowsToken). Role information is based on Windows accounts (users and groups). The Windows provider
is useful only if your application runs on a network where all users have domain accounts.
Authorization Manager (AzMan). Role information is managed using an Authorization Manager XML file or a
directory-based policy store.
You specify a provider by setting the defaultProvider attribute when you configure role management in your application's
Web.config file. For example, to specify the role provider instance with the name "SQL," make the following entry in the
roleManager Element (ASP.NET Settings Schema) of the configuration file:

<roleManager
defaultProvider="SQL"
enabled="true"
cacheRolesInCookie="true" >
</roleManager>

Roles can use the same database that you use for membership services and the user profile. However, you still have the option
of specifying a different provider for each of these services. For information on configuring the role-management database,
see Creating and Configuring the Application Services Database for SQL Server.
If you specify the WindowsTokenRoleProvider provider, you must also configure the application to use Windows
authentication with an entry in the Web.config file like the following:

<authentication mode="Windows" />

The WindowsTokenRoleProvider provider does not support most of the management functions of the role management
API. For example, if you use the WindowsTokenRoleProvider provider, you cannot create groups or add users to groups
using role management. Instead, you must perform those functions in Windows.
Custom Role Management Providers
You can also create a custom role-management provider, which allows you to define your own storage for role information or
use an existing role-information store. The general strategy is to create a class that inherits the RoleProvider abstract class. The
RoleProvider class identifies the methods that your provider defines (which are essentially the same as those in the Roles
class).
After you have a custom role provider, you can configure your application to use that provider in the same way that you
configure the application to use one of the providers supplied with the .NET Framework. The role management system will
then automatically invoke your custom provider and call its methods.
For more information, see Implementing a Role Provider.
See Also
Concepts
Understanding Role Management
Role Management Classes
Other Resources
ASP.NET Web Site Security
ASP.NET

Securing Roles
Role management enables you to manage authorization for your application with categories you create, referred to as "roles."
By assigning users to roles, you can control access to different parts or features of your Web application based on a role
instead of, or in addition to, a user name. For example, an employee application might have roles such as Managers,
Employees, Directors, and so on, where different privileges are specified for each role.
Users can belong to more than one role. For example, if your site is a discussion forum, some users might be in the roles of
both Members and Moderators. You might define each role to have different privileges on the site, and a user who is in both
roles would then have both sets of privileges.
While following coding and configuration best practices can improve the security of your application, it is also important that
you continually keep your application server up to date with the latest security patches for Microsoft Windows and Internet
Information Services (IIS), as well as any patches for Microsoft SQL Server, Active Directory, or other role data sources.
For more detailed information about best practices for writing secure code and securing applications, see the book "Writing
Secure Code" by Michael Howard and David LeBlanc and the guidance provided by Microsoft Patterns and Practices
(http://www.microsoft.com/resources/practices/default.mspx).
Secure Role Manager Configuration
The role-manager feature is disabled by default for ASP.NET applications to improve the security of applications that do not
use the role manager. When the role-manager feature is enabled, the default configuration settings are set to the most secure
values. For information about role-manager configuration settings and their default values, see
roleManager Element (ASP.NET Settings Schema).
Securing Configuration Values
When storing sensitive information in a configuration file for an application, you should encrypt the sensitive values using
Protected Configuration. Information that is especially sensitive includes the encryption keys stored in the machineKey
configuration element and connection strings to a data source stored in the connectionStrings configuration element. For more
information, see Encrypting Configuration Information Using Protected Configuration.
Secure Encryption Keys and Hashing
It is highly recommended that you protect role names cached in a cookie by setting the cookieProtection attribute of the
roleManager element to All. The encryption key values for the specified encryption algorithm are stored in the machineKey
configuration element. For strong encryption, specify an encryption key that is a randomly generated value of the appropriate
length for the selected encryption algorithm.
On a server that hosts multiple applications, you should define unique encryption keys for each application. A less secure
alternative is to define a single encryption key and specify the IsolateApps option with the key.
Host servers can also restrict the ability to override configuration settings from the machine configuration by denying override
rights. This includes denying the ability for encryption keys to be redefined in the Web.config file for an application.
Securing Connections to a Role Data Source
Connection Strings
As mentioned earlier, it is important to protect the connection string that is used to access SQL Server, Active Directory, or
another data-source application. To keep the connection to your database server secure, you should encrypt connection-string
information in the configuration by using Protected Configuration. For more information, see
Encrypting Configuration Information Using Protected Configuration.
Connecting to SQL Server Using Integrated Security
To connect to computers running SQL Server, you should use Integrated Security to avoid the possibility of your connection
string being compromised and your user ID and password being exposed. When you specify a connection that uses Integrated
Security to connect to a computer running SQL Server, the role-manager feature reverts to the identity of the process. You
should ensure that the identity of the process (for example, the application pool) that is running ASP.NET be the default process
account or a restricted user account. For more information, see ASP.NET Impersonation.
SQL Server Database Permissions
The SQL Server database that is used to store the user information for roles includes database roles and views that enable you
to restrict user access to only the required capabilities and visibility. You should assign minimum privileges to the user ID that
is used to connect to the SQL Server role database. For more information, see
Roles and Views in the Application Services Database for SQL Server.
SQL Server Express Worker Process Identity
SQL Server Express 2005 includes a new mode of operation that allows SQL Server to start a worker process running as the
identity of the connecting user. This capability is referred to as "run as user" mode. Although this mode of operation is suitable
for desktop development when using IIS, starting worker processes is not appropriate on Web servers hosting multiple,
untrusted customer code bases. Shared hosting servers that contain applications that do not trust each other should explicitly
disable the "run as user" functionality. This functionality can be turned off by connecting to the SQL Express instance (for
example, osql –E –S .\sqlexpress) and issuing the following Transact-SQL command.
EXEC sp_configure 'show advanced option', '1'
GO
RECONFIGURE WITH OVERRIDE
GO
EXEC sp_configure 'user instances enabled', 0
GO
RECONFIGURE WITH OVERRIDE
GO
Securing the Authorization Store
To improve the security of your data source when using the AuthorizationStoreRoleProvider, you should store your role
information in an Active Directory server, as opposed to a file-based authorization store. This can keep the policy-store file
from being exposed should the Web server be compromised.
The role-manager feature reverts to the identity of the process when connecting to an Active Directory server. You should
ensure that the identity of the process (for example, the application pool) that is running ASP.NET is the default process
account or a restricted user account. For more information, see ASP.NET Impersonation. Additionally, you should assign
permissions to the account in the Active Directory authorization store that allow access to only the specific Authorization
Manager application or scope required by your ASP.NET application.
You should use a network encryption tool such as Internet Protocol Security (IPSec) to protect the connection to the Active
Directory server.
Securing the Role Cookie
You can specify that role names for a user be cached in a session cookie to improve performance by setting the
cacheRolesInCookie attribute of the roleManager to element true. By default, the role names are stored in an encrypted
format, but you should provide additional security for the roles cookie by setting the cookieRequireSSL attribute to true and
only cache roles in a session cookie when SSL is enabled. This keeps the role cookie from being exposed over the network and
being used in a replay attack against your application.
Preventing Cookies Being Shared Across Applications
If the cacheRolesInCookie attribute of the roleManager element is set to true, and if the cookiePath attribute is set to a path
that includes multiple applications, the same role cookie will be sent to multiple applications. You can share the role cookie
across multiple applications by specifying the same encryption information in the machineKey configuration element for each
application.
To avoid sharing the role names cookie across multiple applications, specify separate encryption keys in the machineKey
configuration element for each application, set the cookiePath attribute for each application to the specific application path,
and set the ApplicationName property to a unique value for each application.
Secure Web Pages that Use Roles
Application pages that work with sensitive data, such as logon pages, should be secured using standard Web security
mechanisms. These include using Secure Sockets Layer (SSL) and requiring that users be logged on to carry out sensitive
operations like updating user information or deleting users.
Additionally, pages should not expose sensitive feature data such as passwords, and in some cases user names, in clear text.
Ensure that pages that display such information make use of SSL and are available only to authenticated users. Also, avoid
storing sensitive feature data in cookies or sending it across insecure connections.
Securing Against Denial of Service Attacks
Methods that perform updates or large search operations can reduce the responsiveness of your role data source if called
Methods that perform updates or large search operations can reduce the responsiveness of your role data source if called
concurrently by a number of clients. To reduce your exposure to a denial of service attack, restrict access to ASP.NET pages that
make use of methods that perform database updates or searches to administrative users, and expose only ASP.NET pages that
provide validation of role membership for general use.
Error Messages and Events
Exceptions
To prevent sensitive information from being exposed to unwanted sources, configure your application either to not display
detailed error messages or to display detailed error messages only when the client is the Web server itself. For more
information, see customErrors Element (ASP.NET Settings Schema).
Event Log
If your server is running Windows Server 2003, you can improve the security of you application by securing the event log, and
by setting parameters regarding the size, retention, and so on of the event log to prevent an indirect denial of service attack
against it.
Trace Information
Your Web server can be configured to trace when certain actions occur regarding the role-manager feature and store the trace
information in a log file. Because sensitive information such as user names and role names can be stored in the trace log file,
you should restrict access to the ability to enable tracing to administrators only as well as the ability to configure the location
of the trace log file and access to the trace log file.
Custom Role Providers
When creating a custom role provider, ensure that you follow security best practices to avoid attacks such as SQL injection
attacks when working with a database. When making use of a custom role provider, ensure that the provider has been
reviewed for security best practices.
Working with Culture-Sensitive Characters
When using the SQL Server role provider or a custom role provider, your data source might be configured to store role data in
a culture-sensitive format. However, ASP.NET always evaluates role names specified in the authorization configuration element
and role names in the data source as culture invariant. As a result, unauthorized users could be granted unwanted permissions
because when their unauthorized role name is treated as culture invariant, it is the same as the name of an authorized role. To
avoid users gaining unauthorized access, ensure that role names are unique when evaluated as culture invariant.
See Also
Other Resources
Managing Authorization Using Roles
ASP.NET Web Site Security (Visual Studio)
ASP.NET

Implementing a Role Provider


ASP.NET role management enables you to easily use a number of different providers for your ASP.NET applications. You can
use the supplied profile providers that are included with the .NET Framework, or you can implement your own provider.
There are two primary reasons for creating a custom role provider.
You need to store role information in a data source that is not supported by the role providers included with the .NET
Framework, such as a FoxPro database, an Oracle database, or other data source.
You need to manage role information using a database schema that is different from the database schema used by the
providers that ship with the .NET Framework. A common example of this would be authorization data that already exists
in a SQL Server database for a company or Web site.
Required Classes
To implement a role provider, you create a class that inherits the RoleProvider abstract class from the System.Web.Security
namespace. The RoleProvider abstract class inherits the ProviderBase abstract class from the System.Configuration.Provider
namespace. As a result, you must implement the required members of the ProviderBase class as well. The following tables list
the required properties and methods that you must implement from the ProviderBase and RoleProvider abstract classes and
a description of each. To review an implementation of each member, see the code supplied for the
Sample Role-Provider Implementation.
ProviderBase Members
Memb Description
er
Initialize Takes as input the name of the provider and a NameValueCollection of configuration settings. Used to set property va
method lues for the provider instance including implementation-specific values and options specified in the configuration file
(Machine.config or Web.config).
RoleProvider Members
Member Description
ApplicationName proper The name of the application using the role information specified in the configuration file (Web.config
ty ). The ApplicationName is stored in the data source with related user information and used when q
uerying for user information. See the section on the ApplicationName later in this topic for more in
formation.
This property is read-write and defaults to the ApplicationPath if not specified explicitly.

AddUsersToRoles metho Takes as input a list of user names and a list of role names, and associates the specified users with th
d e specified roles at the data source for the configured ApplicationName.
You should throw a ProviderException if any of the role names or user names specified do not exist f
or the configured ApplicationName.
You should throw an ArgumentException if any of the specified user names or role names is an empt
y string and an ArgumentNullException if any of the specified user names or role names is null (Not
hing in Visual Basic).
If your data source supports transactions, you should include each add operation in a transaction and
roll back the transaction and throw an exception if any add operation fails.

CreateRole method Takes as input the name of a role and adds the specified role to the data source for the configured A
pplicationName.
You should throw a ProviderException if the specified role name already exists for the configured
ApplicationName.
You should throw an ArgumentException if the specified role name is an empty string, contains a c
omma, or exceeds the maximum length allowed by the data source, and an ArgumentNullExceptio
n if the specified role name is null (Nothing in Visual Basic).
DeleteRole method Takes as input the name of a role and a Boolean value that indicates whether to throw an exception if
there are still users associated with the role. The DeleteRole deletes the specified role from the data
source for the configured ApplicationName.
If the throwOnPopulatedRole parameter is true, and the role identified by the role name parameter h
as one or more members, throw a ProviderException and do not delete the role. If the throwOnPop
ulatedRole parameter is false, then delete the role whether it is empty or not.
When you delete a role from the data source, ensure that you also delete any associations between a
user name and the deleted role for the configured ApplicationName.
You should throw an ArgumentException if the specified role name does not exist, or is an empty s
tring. You should throw an ArgumentNullException if the specified role name is null (Nothing in
Visual Basic).

FindUsersInRole method Takes as input a role name and a user name to search for and returns a list of users in a role where th
e user name contains a match of the supplied usernameToMatch for the configured ApplicationNa
me. Wildcard support is included based on the data source. Users are returned in alphabetical order
by user name.
It is recommended that you throw a ProviderException if the role name specified does not exist in t
he data source.

GetAllRoles method Returns a list of role names from the data source. Only the roles for the specified ApplicationName
are retrieved.
If no roles exist for the configured ApplicationName, you should return a string array with no elem
ents.

GetRolesForUser metho Takes as input a user name and returns the role names that the specified user is associated with, fro
d m the data source. Only the roles for the configured ApplicationName are retrieved.
If no roles exist for the specified user for the configured ApplicationName, you should return a stri
ng array with no elements.
You should throw an ArgumentException if the specified user name is an empty string. You should
throw an ArgumentNullException if the specified user name is null (Nothing in Visual Basic).

GetUsersInRole method Takes as input a role name and returns the user names associated with a role from the data source. O
nly the roles for the configured ApplicationName are retrieved.
If the specified role name does not exist for the configured ApplicationName, you should throw a P
roviderException.
If no users are associated with the specified role for the configured ApplicationName, you should r
eturn a string array with no elements.
You should throw an ArgumentException if the specified role name is an empty string, contains a c
omma, or exceeds the maximum length for a role name allowed by your data source. You should thr
ow an ArgumentNullException if the specified role name is null (Nothing in Visual Basic).

IsUserInRole method Takes as input a user name and a role name and determines whether the current logged-on user is a
ssociated with a role from the data source for the configured ApplicationName.
You should throw a ProviderException if the role name or user name specified does not exist for th
e configured ApplicationName.
You should throw an ArgumentException if the specified user name or role name is an empty strin
g and an ArgumentNullException if the specified user name or role name is null (Nothing in Visu
al Basic).
RemoveUsersFromRoles Takes as input a list of user names and a list of role names and removes the association for the specif
method ied users from the specified roles at the data source for the configured ApplicationName.
You should throw a ProviderException if any of the role names or user names specified does not ex
ist for the configured ApplicationName.
You should throw an ArgumentException if any of the specified user names or role names is an em
pty string and an ArgumentNullException if any of the specified user names or role names is null
(Nothing in Visual Basic).
If your data source supports transactions, you should include each remove operation in a transaction
and roll back the transaction and throw an exception if any remove operation fails.

RoleExists method Takes as input a role name and determines whether the role name exists in the data source for the co
nfigured ApplicationName.
You should throw an ArgumentException if the specified role name does not exist, or is an empty s
tring. It is recommended that you throw an ArgumentNullException if the specified role name is n
ull (Nothing in Visual Basic).

ApplicationName
Role providers store role information uniquely for each application. This enables multiple ASP.NET applications to use the
same data source without running into a conflict if duplicate user names are used. Alternatively, multiple ASP.NET applications
can use the same role data source by specifying the same ApplicationName.
Because role providers store role information uniquely for each application, you will need to ensure that your data schema
includes the application name and that queries and updates also include the application name. For example, the following
command is used to retrieve a role name from a database and ensures that the ApplicationName is included in the query.

SELECT Rolename FROM Roles


WHERE Rolename = 'Administrators' AND ApplicationName = 'MyApplication'

Thread Safety
For each role provider specified in the configuration for an application, ASP.NET instantiates a single role-provider instance
that is used for all of the requests served by an HttpApplication object. As a result, you can have multiple requests executing
concurrently. ASP.NET does not ensure the thread safety of calls to your provider. You will need to write your provider code to
be thread safe. For example, creating a connection to a database or opening a file for editing should be done within the
member that is called, such as AddUsersToRoles , rather than opening a file or database connection when the Initialize
method is called.
See Also
Concepts
Sample Role-Provider Implementation
Securing Roles
Other Resources
Managing Authorization Using Roles
ASP.NET

Sample Role-Provider Implementation


Describes the sample role provider and the supported data-source schema.
The following topics include the code for a sample role-provider implementation. The sample provider uses the .NET
Framework Data Provider for ODBC to connect to an ODBC data source. The sample uses an Access database as its data
source.
This topic describes how to implement the sample profile provider and configure an ASP.NET application to use the sample
provider.
Note
Because data sources contain differing SQL syntax, some commands will work with one data source and not with another. Th
erefore, you should create a role provider specific to your data source even if you are using the .NET Framework Data Provid
er for ODBC or the .NET Framework Data Provider for OLEDB to access your data source,for example, SybaseProfileProvider
or OracleProfileProvider.

To view the code for the sample provider, see How to: Sample Role-Provider Implementation.
Database Schema
The sample role provider uses two database tables to manage role information: a Roles table that contains role names and
application names, and a UsersInRoles table that is used to associate a user name with a role name for an application.
To create the Access tables used by the sample provider, issue the following data-definition query in a new or existing Access
database.

CREATE TABLE Roles


(
Rolename Text (255) NOT NULL,
ApplicationName Text (255) NOT NULL,
CONSTRAINT PKRoles PRIMARY KEY (Rolename, ApplicationName)
)

CREATE TABLE UsersInRoles


(
Username Text (255) NOT NULL,
Rolename Text (255) NOT NULL,
ApplicationName Text (255) NOT NULL,
CONSTRAINT PKUsersInRoles PRIMARY KEY (Username, Rolename, ApplicationName)
)

Event Log Access


If the sample provider encounters an exception when working with the data source, it writes the details of the exception to the
Application Event Log instead of returning the exception to the ASP.NET application. This is done as a security measure to avoid
exposing private information about the data source in the ASP.NET application.
The sample provider specifies an event Source of "OdbcRoleProvider". Before your ASP.NET application will be able to write to
the Application Event Log successfully, you will need to create the following registry key.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application\OdbcRoleProvider

If you do not want the sample provider to write exceptions to the event log, then you can set the
writeExceptionsToEventLog attribute to false in the Web.config file.
Building the Sample Provider
In order to use the sample provider, you can place your source code in the App_Code directory of your application. Note that if
you already have source code in the App_Code directory of your application, you must add the version of the sample provider
that is written in the same language as the existing code in the directory. The provider will be compiled by ASP.NET when your
application is requested.
You can also compile the sample provider as a library and place it in the Bin directory of your Web application, or strongly
name it and place it in the GAC. The following command shows how to compile the sample provider using the command-line
compiler.
VB
vbc /out:OdbcRoleProvider.dll /t:library OdbcRoleProvider.vb /r:System.Web.dll /r:System.Co
nfiguration.dll

C#
csc /out:OdbcRoleProvider.dll /t:library OdbcRoleProvider.cs /r:System.Web.dll /r:System.Co
nfiguration.dll

Using the Sample Provider in an ASP.NET Application


The following example shows the Web.config file for an ASP.NET application configured to use the sample provider. The
example uses an ODBC DSN named "RolesDSN" to obtain connection information for the Access database. To use the sample
provider, you will need to either create the "RolesDSN" System DSN or supply a valid ODBC connection string to your
database.
The example configuration assumes that your Web site is set up to use forms authentication and includes an ASP.NET page
called login.aspx that allows users to log in.

<configuration>
<connectionStrings>
<add name="OdbcServices" connectionString="DSN=RolesDSN;" />
</connectionStrings>

<system.web>
<authentication mode="Forms" />
<forms loginUrl="loginvb.aspx"
name=".ASPXFORMSAUTH" />
</authentication>

<authorization>
<deny users="?" />
</authorization>
<roleManager defaultProvider="OdbcRoleProvider"
enabled="true"
cacheRolesInCookie="true"
cookieName=".ASPROLES"
cookieTimeout="30"
cookiePath="/"
cookieRequireSSL="false"
cookieSlidingExpiration="true"
cookieProtection="All" >
<providers>
<clear />
<add
name="OdbcRoleProvider"
type="Samples.AspNet.Roles.OdbcRoleProvider"
connectionStringName="OdbcServices"
applicationName="SampleApplication"
writeExceptionsToEventLog="false" />
</providers>
</roleManager>

</system.web>
</configuration>

See Also
Concepts
Implementing a Role Provider
Other Resources
Managing Authorization Using Roles
ASP.NET Web Site Security (Visual Studio)
ASP.NET

How to: Sample Role-Provider Implementation


Illustrates a role-provider implementation.
The following code illustrates a role-provider implementation. For more information, see
Sample Role-Provider Implementation.
Example
VB
Imports System.Web.Security
Imports System.Configuration.Provider
Imports System.Collections.Specialized
Imports System
Imports System.Data
Imports System.Data.Odbc
Imports System.Configuration
Imports System.Diagnostics
Imports System.Web
Imports System.Globalization
Imports Microsoft.VisualBasic

'
'
' This provider works with the following schema for the tables of role data.
'
' CREATE TABLE Roles
' (
' Rolename Text (255) NOT NULL,
' ApplicationName Text (255) NOT NULL,
' CONSTRAINT PKRoles PRIMARY KEY (Rolename, ApplicationName)
' )
'
' CREATE TABLE UsersInRoles
' (
' Username Text (255) NOT NULL,
' Rolename Text (255) NOT NULL,
' ApplicationName Text (255) NOT NULL,
' CONSTRAINT PKUsersInRoles PRIMARY KEY (Username, Rolename, ApplicationName)
' )
'
'

Namespace Samples.AspNet.Roles
Public NotInheritable Class OdbcRoleProvider
Inherits RoleProvider

'
' Global OdbcConnection, generated password length, generic exception message, event lo
g info.
'
Private conn As OdbcConnection

Private eventSource As String = "OdbcRoleProvider"


Private eventLog As String = "Application"
Private exceptionMessage As String = "An exception occurred. Please check the Event Log
."
Private pConnectionStringSettings As ConnectionStringSettings
Private connectionString As String
'
' If false, exceptions are Thrown to the caller. If true,
' exceptions are written to the event log.
'
Private pWriteExceptionsToEventLog As Boolean = False

Public Property WriteExceptionsToEventLog As Boolean


Get
Return pWriteExceptionsToEventLog
End Get
Set
pWriteExceptionsToEventLog = value
End Set
End Property

'
' System.Configuration.Provider.ProviderBase.Initialize Method
'
Public Overrides Sub Initialize(name As String, config As NameValueCollection)

'
' Initialize values from web.config.
'
If config Is Nothing Then _
Throw New ArgumentNullException("config")

If name Is Nothing OrElse name.Length = 0 Then _


name = "OdbcRoleProvider"

If String.IsNullOrEmpty(config("description")) Then
config.Remove("description")
config.Add("description", "Sample ODBC Role provider")
End If

' Initialize the abstract base class.


MyBase.Initialize(name, config)

If config("applicationName") Is Nothing OrElse config("applicationName").Trim() = ""


Then
pApplicationName = System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath
Else
pApplicationName = config("applicationName")
End If

If Not config("writeExceptionsToEventLog") Is Nothing Then


If config("writeExceptionsToEventLog").ToUpper() = "TRUE" Then
pWriteExceptionsToEventLog = true
End If
End If

'
' Initialize OdbcConnection.
'

pConnectionStringSettings = _
ConfigurationManager.ConnectionStrings(config("connectionStringName"))

If pConnectionStringSettings Is Nothing OrElse pConnectionStringSettings.ConnectionSt


ring.Trim() = "" Then
Throw New ProviderException("Connection string cannot be blank.")
End If

connectionString = pConnectionStringSettings.ConnectionString
End Sub

'
' System.Web.Security.RoleProvider properties.
'

Private pApplicationName As String

Public Overrides Property ApplicationName As String


Get
Return pApplicationName
End Get
Set
pApplicationName = value
End Set
End Property

'
' System.Web.Security.RoleProvider methods.
'

'
' RoleProvider.AddUsersToRoles
'

Public Overrides Sub AddUsersToRoles(usernames As String(), rolenames As String())


For Each rolename As String In rolenames
If Not RoleExists(rolename) Then
Throw New ProviderException("Role name not found.")
End If
Next

For Each username As String In usernames


If username.Contains(",") Then
Throw New ArgumentException("User names cannot contain commas.")
End If

For Each rolename As String In rolenames


If IsUserInRole(username, rolename) Then
Throw New ProviderException("User is already in role.")
End If
Next
Next

Dim conn As OdbcConnection = New OdbcConnection(connectionString)


Dim cmd As OdbcCommand = New OdbcCommand("INSERT INTO UsersInRoles " & _
" (Username, Rolename, ApplicationName) " & _
" Values(?, ?, ?)", conn)

Dim userParm As OdbcParameter = cmd.Parameters.Add("@Username", OdbcType.VarChar, 255


)
Dim roleParm As OdbcParameter = cmd.Parameters.Add("@Rolename", OdbcType.VarChar, 255
)
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = ApplicationName

Dim tran As OdbcTransaction = Nothing

Try
conn.Open()
tran = conn.BeginTransaction()
cmd.Transaction = tran

For Each username As String In usernames


For Each rolename As String In rolenames
userParm.Value = username
roleParm.Value = rolename
cmd.ExecuteNonQuery()
Next
Next
tran.Commit()
Catch e As OdbcException
Try
tran.Rollback()
Catch
End Try

If WriteExceptionsToEventLog Then
WriteToEventLog(e, "AddUsersToRoles")
Else
Throw e
End If
Finally
conn.Close()
End Try
End Sub

'
' RoleProvider.CreateRole
'

Public Overrides Sub CreateRole(rolename As String)

If rolename.Contains(",") Then
Throw New ArgumentException("Role names cannot contain commas.")
End If

If RoleExists(rolename) Then
Throw New ProviderException("Role name already exists.")
End If
Dim conn As OdbcConnection = New OdbcConnection(connectionString)
Dim cmd As OdbcCommand = New OdbcCommand("INSERT INTO Roles " & _
" (Rolename, ApplicationName) " & _
" Values(?, ?)", conn)

cmd.Parameters.Add("@Rolename", OdbcType.VarChar, 255).Value = rolename


cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = Applicati
onName

Try
conn.Open()

cmd.ExecuteNonQuery()
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "CreateRole")
Else
Throw e
End If
Finally
conn.Close()
End Try
End Sub
'
' RoleProvider.DeleteRole
'

Public Overrides Function DeleteRole(ByVal rolename As String, ByVal throwOnPopulat


edRole As Boolean) As Boolean

If Not RoleExists(rolename) Then


Throw New ProviderException("Role does not exist.")
End If

If throwOnPopulatedRole AndAlso GetUsersInRole(rolename).Length > 0 Then


Throw New ProviderException("Cannot delete a populated role.")
End If

Dim conn As OdbcConnection = New OdbcConnection(connectionString)


Dim cmd As OdbcCommand = New OdbcCommand("DELETE FROM Roles " & _
" WHERE Rolename = ? AND ApplicationName = ?", conn)

cmd.Parameters.Add("@Rolename", OdbcType.VarChar, 255).Value = rolename


cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = Applicati
onName

Dim cmd2 As OdbcCommand = New OdbcCommand("DELETE FROM UsersInRoles " & _


" WHERE Rolename = ? AND ApplicationName = ?", conn)

cmd2.Parameters.Add("@Rolename", OdbcType.VarChar, 255).Value = rolename


cmd2.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = Applicat
ionName

Dim tran As OdbcTransaction = Nothing


Try
conn.Open()
tran = conn.BeginTransaction()
cmd.Transaction = tran
cmd2.Transaction = tran

cmd2.ExecuteNonQuery()
cmd.ExecuteNonQuery()

tran.Commit()
Catch e As OdbcException
Try
tran.Rollback()
Catch
End Try

If WriteExceptionsToEventLog Then
WriteToEventLog(e, "DeleteRole")

Return False
Else
Throw e
End If
Finally
conn.Close()
End Try

Return True
End Function

'
' RoleProvider.GetAllRoles
'

Public Overrides Function GetAllRoles() As String()


Dim tmpRoleNames As String = ""

Dim conn As OdbcConnection = New OdbcConnection(connectionString)


Dim cmd As OdbcCommand = New OdbcCommand("SELECT Rolename FROM Roles " & _
" WHERE ApplicationName = ?", conn)

cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = Applicati


onName

Dim reader As OdbcDataReader = Nothing

Try
conn.Open()

reader = cmd.ExecuteReader()

Do While reader.Read()
tmpRoleNames &= reader.GetString(0) & ","
Loop
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "GetAllRoles")
Else
Throw e
End If
Finally
If Not reader Is Nothing Then reader.Close()
conn.Close()
End Try

If tmpRoleNames.Length > 0 Then


' Remove trailing comma.
tmpRoleNames = tmpRoleNames.Substring(0, tmpRoleNames.Length - 1)
Return tmpRoleNames.Split(CChar(","))
End If

Return New String() {}


End Function

'
' RoleProvider.GetRolesForUser
'

Public Overrides Function GetRolesForUser(ByVal username As String) As String()


Dim tmpRoleNames As String = ""

Dim conn As OdbcConnection = New OdbcConnection(connectionString)


Dim cmd As OdbcCommand = New OdbcCommand("SELECT Rolename FROM UsersInRoles " &
_
" WHERE Username = ? AND ApplicationName = ?", conn)

cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username


cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = Applicati
onName

Dim reader As OdbcDataReader = Nothing

Try
conn.Open()
reader = cmd.ExecuteReader()

Do While reader.Read()
tmpRoleNames &= reader.GetString(0) & ","
Loop
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "GetRolesForUser")
Else
Throw e
End If
Finally
If Not reader Is Nothing Then reader.Close()
conn.Close()
End Try

If tmpRoleNames.Length > 0 Then


' Remove trailing comma.
tmpRoleNames = tmpRoleNames.Substring(0, tmpRoleNames.Length - 1)
Return tmpRoleNames.Split(CChar(","))
End If

Return New String() {}


End Function

'
' RoleProvider.GetUsersInRole
'

Public Overrides Function GetUsersInRole(ByVal rolename As String) As String()


Dim tmpUserNames As String = ""

Dim conn As OdbcConnection = New OdbcConnection(connectionString)


Dim cmd As OdbcCommand = New OdbcCommand("SELECT Username FROM UsersInRoles " &
_
" WHERE Rolename = ? AND ApplicationName = ?", conn)

cmd.Parameters.Add("@Rolename", OdbcType.VarChar, 255).Value = rolename


cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = Applicati
onName

Dim reader As OdbcDataReader = Nothing

Try
conn.Open()

reader = cmd.ExecuteReader()

Do While reader.Read()
tmpUserNames &= reader.GetString(0) & ","
Loop
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "GetUsersInRole")
Else
Throw e
End If
Finally
If Not reader Is Nothing Then reader.Close()
conn.Close()
End Try

If tmpUserNames.Length > 0 Then


' Remove trailing comma.
tmpUserNames = tmpUserNames.Substring(0, tmpUserNames.Length - 1)
Return tmpUserNames.Split(CChar(","))
End If

Return New String() {}


End Function
'
' RoleProvider.IsUserInRole
'

Public Overrides Function IsUserInRole(ByVal username As String, ByVal rolename As


String) As Boolean

Dim userIsInRole As Boolean = False


Dim conn As OdbcConnection = New OdbcConnection(connectionString)
Dim cmd As OdbcCommand = New OdbcCommand("SELECT COUNT(*) FROM UsersInRoles " &
_
" WHERE Username = ? AND Rolename = ? AND ApplicationName = ?", conn)

cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username


cmd.Parameters.Add("@Rolename", OdbcType.VarChar, 255).Value = rolename
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = Applicati
onName

Try
conn.Open()

Dim numRecs As Integer = CType(cmd.ExecuteScalar(), Integer)

If numRecs > 0 Then


userIsInRole = True
End If
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "IsUserInRole")
Else
Throw e
End If
Finally
conn.Close()
End Try

Return userIsInRole
End Function

'
' RoleProvider.RemoveUsersFromRoles
'

Public Overrides Sub RemoveUsersFromRoles(ByVal usernames As String(), ByVal rolena


mes As String())

For Each rolename As String In rolenames


If Not RoleExists(rolename) Then
Throw New ProviderException("Role name not found.")
End If
Next

For Each username As String In usernames


For Each rolename As String In rolenames
If Not IsUserInRole(username, rolename) Then
Throw New ProviderException("User is not in role.")
End If
Next
Next

Dim conn As OdbcConnection = New OdbcConnection(connectionString)


Dim cmd As OdbcCommand = New OdbcCommand("DELETE FROM UsersInRoles " & _
" WHERE Username = ? AND Rolename = ? AND ApplicationName = ?", conn)

Dim userParm As OdbcParameter = cmd.Parameters.Add("@Username", OdbcType.VarCha


r, 255)
Dim roleParm As OdbcParameter = cmd.Parameters.Add("@Rolename", OdbcType.VarCha
r, 255)
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = Applicati
onName

Dim tran As OdbcTransaction = Nothing

Try
conn.Open()
tran = conn.BeginTransaction
cmd.Transaction = tran

For Each username As String In usernames


For Each rolename As String In rolenames
userParm.Value = username
roleParm.Value = rolename
cmd.ExecuteNonQuery()
Next
Next

tran.Commit()
Catch e As OdbcException
Try
tran.Rollback()
Catch
End Try

If WriteExceptionsToEventLog Then
WriteToEventLog(e, "RemoveUsersFromRoles")
Else
Throw e
End If
Finally
conn.Close()
End Try
End Sub

'
' RoleProvider.RoleExists
'

Public Overrides Function RoleExists(ByVal rolename As String) As Boolean


Dim exists As Boolean = False

Dim conn As OdbcConnection = New OdbcConnection(connectionString)


Dim cmd As OdbcCommand = New OdbcCommand("SELECT COUNT(*) FROM Roles " & _
" WHERE Rolename = ? AND ApplicationName = ?", conn)

cmd.Parameters.Add("@Rolename", OdbcType.VarChar, 255).Value = rolename


cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = Applicati
onName

Try
conn.Open()

Dim numRecs As Integer = CType(cmd.ExecuteScalar(), Integer)

If numRecs > 0 Then


exists = True
End If
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "RoleExists")
Else
Throw e
End If
Finally
conn.Close()
End Try

Return exists
End Function

'
' RoleProvider.FindUsersInRole
'

Public Overrides Function FindUsersInRole(ByVal rolename As String, ByVal usernameT


oMatch As String) As String()

Dim conn As OdbcConnection = New OdbcConnection(connectionString)


Dim cmd As OdbcCommand = New OdbcCommand("SELECT Username FROM UsersInRoles "
& _
"WHERE Username LIKE ? AND RoleName = ? AND ApplicationName = ?", con
n)
cmd.Parameters.Add("@UsernameSearch", OdbcType.VarChar, 255).Value = usernameTo
Match
cmd.Parameters.Add("@RoleName", OdbcType.VarChar, 255).Value = rolename
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicat
ionName

Dim tmpUserNames As String = ""


Dim reader As OdbcDataReader = Nothing

Try
conn.Open()

reader = cmd.ExecuteReader()

Do While reader.Read()
tmpUserNames &= reader.GetString(0) & ","
Loop
Catch e As OdbcException
If WriteExceptionsToEventLog Then
WriteToEventLog(e, "FindUsersInRole")
Else
Throw e
End If
Finally
If Not reader Is Nothing Then reader.Close()

conn.Close()
End Try

If tmpUserNames.Length > 0 Then


' Remove trailing comma.
tmpUserNames = tmpUserNames.Substring(0, tmpUserNames.Length - 1)
Return tmpUserNames.Split(CChar(","))
End If
Return New String() {}
End Function

'
' WriteToEventLog
' A helper function that writes exception detail to the event log. Exceptions
' are written to the event log as a security measure to aSub Private database
' details from being returned to the browser. If a method does not Return a status
' or boolean indicating the action succeeded or failed, a generic exception is also
' Thrown by the caller.
'

Private Sub WriteToEventLog(e As OdbcException, action As String)


Dim log As EventLog = New EventLog()
log.Source = eventSource
log.Log = eventLog

Dim message As String = exceptionMessage & vbCrLf & vbCrLf


message &= "Action: " & action & vbCrLf & vbCrLf
message &= "Exception: " & e.ToString()

log.WriteEnTry(message)
End Sub
End Class
End Namespace

C#
using System.Web.Security;
using System.Configuration.Provider;
using System.Collections.Specialized;
using System;
using System.Data;
using System.Data.Odbc;
using System.Configuration;
using System.Diagnostics;
using System.Web;
using System.Globalization;

/*

This provider works with the following schema for the tables of role data.

CREATE TABLE Roles


(
Rolename Text (255) NOT NULL,
ApplicationName Text (255) NOT NULL,
CONSTRAINT PKRoles PRIMARY KEY (Rolename, ApplicationName)
)

CREATE TABLE UsersInRoles


(
Username Text (255) NOT NULL,
Rolename Text (255) NOT NULL,
ApplicationName Text (255) NOT NULL,
CONSTRAINT PKUsersInRoles PRIMARY KEY (Username, Rolename, ApplicationName)
)

*/

namespace Samples.AspNet.Roles
{

public sealed class OdbcRoleProvider: RoleProvider


{
//
// Global connection string, generic exception message, event log info.
//

private string eventSource = "OdbcRoleProvider";


private string eventLog = "Application";
private string exceptionMessage = "An exception occurred. Please check the Event Log.";

private ConnectionStringSettings pConnectionStringSettings;


private string connectionString;
//
// If false, exceptions are thrown to the caller. If true,
// exceptions are written to the event log.
//

private bool pWriteExceptionsToEventLog = false;

public bool WriteExceptionsToEventLog


{
get { return pWriteExceptionsToEventLog; }
set { pWriteExceptionsToEventLog = value; }
}

//
// System.Configuration.Provider.ProviderBase.Initialize Method
//

public override void Initialize(string name, NameValueCollection config)


{

//
// Initialize values from web.config.
//

if (config == null)
throw new ArgumentNullException("config");

if (name == null || name.Length == 0)


name = "OdbcRoleProvider";

if (String.IsNullOrEmpty(config["description"]))
{
config.Remove("description");
config.Add("description", "Sample ODBC Role provider");
}

// Initialize the abstract base class.


base.Initialize(name, config);

if (config["applicationName"] == null || config["applicationName"].Trim() == "")


{
pApplicationName = System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath;
}
else
{
pApplicationName = config["applicationName"];
}

if (config["writeExceptionsToEventLog"] != null)
{
if (config["writeExceptionsToEventLog"].ToUpper() == "TRUE")
{
pWriteExceptionsToEventLog = true;
}
}

//
// Initialize OdbcConnection.
//

pConnectionStringSettings = ConfigurationManager.
ConnectionStrings[config["connectionStringName"]];
if (pConnectionStringSettings == null || pConnectionStringSettings.ConnectionString.T
rim() == "")
{
throw new ProviderException("Connection string cannot be blank.");
}

connectionString = pConnectionStringSettings.ConnectionString;
}

//
// System.Web.Security.RoleProvider properties.
//

private string pApplicationName;

public override string ApplicationName


{
get { return pApplicationName; }
set { pApplicationName = value; }
}

//
// System.Web.Security.RoleProvider methods.
//

//
// RoleProvider.AddUsersToRoles
//

public override void AddUsersToRoles(string[] usernames, string[] rolenames)


{
foreach (string rolename in rolenames)
{
if (!RoleExists(rolename))
{
throw new ProviderException("Role name not found.");
}
}

foreach (string username in usernames)


{
if (username.Contains(","))
{
throw new ArgumentException("User names cannot contain commas.");
}

foreach (string rolename in rolenames)


{
if (IsUserInRole(username, rolename))
{
throw new ProviderException("User is already in role.");
}
}
}

OdbcConnection conn = new OdbcConnection(connectionString);


OdbcCommand cmd = new OdbcCommand("INSERT INTO UsersInRoles " +
" (Username, Rolename, ApplicationName) " +
" Values(?, ?, ?)", conn);

OdbcParameter userParm = cmd.Parameters.Add("@Username", OdbcType.VarChar, 255);


OdbcParameter roleParm = cmd.Parameters.Add("@Rolename", OdbcType.VarChar, 255);
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = ApplicationName
;

OdbcTransaction tran = null;

try
{
conn.Open();
tran = conn.BeginTransaction();
cmd.Transaction = tran;

foreach (string username in usernames)


{
foreach (string rolename in rolenames)
{
userParm.Value = username;
roleParm.Value = rolename;
cmd.ExecuteNonQuery();
}
}

tran.Commit();
}
catch (OdbcException e)
{
try
{
tran.Rollback();
}
catch { }

if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "AddUsersToRoles");
}
else
{
throw e;
}
}
finally
{
conn.Close();
}
}

//
// RoleProvider.CreateRole
//

public override void CreateRole(string rolename)


{
if (rolename.Contains(","))
{
throw new ArgumentException("Role names cannot contain commas.");
}

if (RoleExists(rolename))
{
throw new ProviderException("Role name already exists.");
}
OdbcConnection conn = new OdbcConnection(connectionString);
OdbcCommand cmd = new OdbcCommand("INSERT INTO Roles " +
" (Rolename, ApplicationName) " +
" Values(?, ?)", conn);
cmd.Parameters.Add("@Rolename", OdbcType.VarChar, 255).Value = rolename;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = ApplicationName
;

try
{
conn.Open();

cmd.ExecuteNonQuery();
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "CreateRole");
}
else
{
throw e;
}
}
finally
{
conn.Close();
}
}

//
// RoleProvider.DeleteRole
//

public override bool DeleteRole(string rolename, bool throwOnPopulatedRole)


{
if (!RoleExists(rolename))
{
throw new ProviderException("Role does not exist.");
}

if (throwOnPopulatedRole && GetUsersInRole(rolename).Length > 0)


{
throw new ProviderException("Cannot delete a populated role.");
}

OdbcConnection conn = new OdbcConnection(connectionString);


OdbcCommand cmd = new OdbcCommand("DELETE FROM Roles " +
" WHERE Rolename = ? AND ApplicationName = ?", conn);

cmd.Parameters.Add("@Rolename", OdbcType.VarChar, 255).Value = rolename;


cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = ApplicationName
;

OdbcCommand cmd2 = new OdbcCommand("DELETE FROM UsersInRoles " +


" WHERE Rolename = ? AND ApplicationName = ?", conn);

cmd2.Parameters.Add("@Rolename", OdbcType.VarChar, 255).Value = rolename;


cmd2.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = ApplicationNam
e;

OdbcTransaction tran = null;

try
{
conn.Open();
tran = conn.BeginTransaction();
cmd.Transaction = tran;
cmd2.Transaction = tran;
cmd2.ExecuteNonQuery();
cmd.ExecuteNonQuery();

tran.Commit();
}
catch (OdbcException e)
{
try
{
tran.Rollback();
}
catch { }

if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "DeleteRole");

return false;
}
else
{
throw e;
}
}
finally
{
conn.Close();
}

return true;
}

//
// RoleProvider.GetAllRoles
//

public override string[] GetAllRoles()


{
string tmpRoleNames = "";

OdbcConnection conn = new OdbcConnection(connectionString);


OdbcCommand cmd = new OdbcCommand("SELECT Rolename FROM Roles " +
" WHERE ApplicationName = ?", conn);

cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = ApplicationName


;

OdbcDataReader reader = null;

try
{
conn.Open();

reader = cmd.ExecuteReader();

while (reader.Read())
{
tmpRoleNames += reader.GetString(0) + ",";
}
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "GetAllRoles");
}
else
{
throw e;
}
}
finally
{
if (reader != null) { reader.Close(); }
conn.Close();
}

if (tmpRoleNames.Length > 0)
{
// Remove trailing comma.
tmpRoleNames = tmpRoleNames.Substring(0, tmpRoleNames.Length - 1);
return tmpRoleNames.Split(',');
}

return new string[0];


}

//
// RoleProvider.GetRolesForUser
//

public override string[] GetRolesForUser(string username)


{
string tmpRoleNames = "";
OdbcConnection conn = new OdbcConnection(connectionString);
OdbcCommand cmd = new OdbcCommand("SELECT Rolename FROM UsersInRoles " +
" WHERE Username = ? AND ApplicationName = ?", conn);

cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username;


cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = ApplicationName
;

OdbcDataReader reader = null;

try
{
conn.Open();

reader = cmd.ExecuteReader();

while (reader.Read())
{
tmpRoleNames += reader.GetString(0) + ",";
}
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "GetRolesForUser");
}
else
{
throw e;
}
}
finally
{
if (reader != null) { reader.Close(); }
conn.Close();
}
if (tmpRoleNames.Length > 0)
{
// Remove trailing comma.
tmpRoleNames = tmpRoleNames.Substring(0, tmpRoleNames.Length - 1);
return tmpRoleNames.Split(',');
}

return new string[0];


}

//
// RoleProvider.GetUsersInRole
//

public override string[] GetUsersInRole(string rolename)


{
string tmpUserNames = "";

OdbcConnection conn = new OdbcConnection(connectionString);


OdbcCommand cmd = new OdbcCommand("SELECT Username FROM UsersInRoles " +
" WHERE Rolename = ? AND ApplicationName = ?", conn);

cmd.Parameters.Add("@Rolename", OdbcType.VarChar, 255).Value = rolename;


cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = ApplicationName
;

OdbcDataReader reader = null;

try
{
conn.Open();

reader = cmd.ExecuteReader();

while (reader.Read())
{
tmpUserNames += reader.GetString(0) + ",";
}
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "GetUsersInRole");
}
else
{
throw e;
}
}
finally
{
if (reader != null) { reader.Close(); }
conn.Close();
}

if (tmpUserNames.Length > 0)
{
// Remove trailing comma.
tmpUserNames = tmpUserNames.Substring(0, tmpUserNames.Length - 1);
return tmpUserNames.Split(',');
}

return new string[0];


}
//
// RoleProvider.IsUserInRole
//

public override bool IsUserInRole(string username, string rolename)


{
bool userIsInRole = false;
OdbcConnection conn = new OdbcConnection(connectionString);
OdbcCommand cmd = new OdbcCommand("SELECT COUNT(*) FROM UsersInRoles " +
" WHERE Username = ? AND Rolename = ? AND ApplicationName = ?", conn);

cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username;


cmd.Parameters.Add("@Rolename", OdbcType.VarChar, 255).Value = rolename;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = ApplicationName
;

try
{
conn.Open();

int numRecs = (int)cmd.ExecuteScalar();

if (numRecs > 0)
{
userIsInRole = true;
}
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "IsUserInRole");
}
else
{
throw e;
}
}
finally
{
conn.Close();
}

return userIsInRole;
}

//
// RoleProvider.RemoveUsersFromRoles
//

public override void RemoveUsersFromRoles(string[] usernames, string[] rolenames)


{
foreach (string rolename in rolenames)
{
if (!RoleExists(rolename))
{
throw new ProviderException("Role name not found.");
}
}

foreach (string username in usernames)


{
foreach (string rolename in rolenames)
{
if (!IsUserInRole(username, rolename))
{
throw new ProviderException("User is not in role.");
}
}
}

OdbcConnection conn = new OdbcConnection(connectionString);


OdbcCommand cmd = new OdbcCommand("DELETE FROM UsersInRoles " +
" WHERE Username = ? AND Rolename = ? AND ApplicationName = ?", conn);

OdbcParameter userParm = cmd.Parameters.Add("@Username", OdbcType.VarChar, 255);


OdbcParameter roleParm = cmd.Parameters.Add("@Rolename", OdbcType.VarChar, 255);
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = ApplicationName
;

OdbcTransaction tran = null;

try
{
conn.Open();
tran = conn.BeginTransaction();
cmd.Transaction = tran;

foreach (string username in usernames)


{
foreach (string rolename in rolenames)
{
userParm.Value = username;
roleParm.Value = rolename;
cmd.ExecuteNonQuery();
}
}

tran.Commit();
}
catch (OdbcException e)
{
try
{
tran.Rollback();
}
catch { }

if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "RemoveUsersFromRoles");
}
else
{
throw e;
}
}
finally
{
conn.Close();
}
}

//
// RoleProvider.RoleExists
//
public override bool RoleExists(string rolename)
{
bool exists = false;
OdbcConnection conn = new OdbcConnection(connectionString);
OdbcCommand cmd = new OdbcCommand("SELECT COUNT(*) FROM Roles " +
" WHERE Rolename = ? AND ApplicationName = ?", conn);

cmd.Parameters.Add("@Rolename", OdbcType.VarChar, 255).Value = rolename;


cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = ApplicationName
;

try
{
conn.Open();

int numRecs = (int)cmd.ExecuteScalar();

if (numRecs > 0)
{
exists = true;
}
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "RoleExists");
}
else
{
throw e;
}
}
finally
{
conn.Close();
}

return exists;
}

//
// RoleProvider.FindUsersInRole
//

public override string[] FindUsersInRole(string rolename, string usernameToMatch)


{
OdbcConnection conn = new OdbcConnection(connectionString);
OdbcCommand cmd = new OdbcCommand("SELECT Username FROM UsersInRoles " +
"WHERE Username LIKE ? AND RoleName = ? AND ApplicationName = ?", conn);
cmd.Parameters.Add("@UsernameSearch", OdbcType.VarChar, 255).Value = usernameToMatch;
cmd.Parameters.Add("@RoleName", OdbcType.VarChar, 255).Value = rolename;
cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicationNam
e;

string tmpUserNames = "";


OdbcDataReader reader = null;

try
{
conn.Open();

reader = cmd.ExecuteReader();
while (reader.Read())
{
tmpUserNames += reader.GetString(0) + ",";
}
}
catch (OdbcException e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "FindUsersInRole");
}
else
{
throw e;
}
}
finally
{
if (reader != null) { reader.Close(); }
conn.Close();
}
if (tmpUserNames.Length > 0)
{
// Remove trailing comma.
tmpUserNames = tmpUserNames.Substring(0, tmpUserNames.Length - 1);
return tmpUserNames.Split(',');
}

return new string[0];


}

//
// WriteToEventLog
// A helper function that writes exception detail to the event log. Exceptions
// are written to the event log as a security measure to avoid private database
// details from being returned to the browser. If a method does not return a status
// or boolean indicating the action succeeded or failed, a generic exception is also
// thrown by the caller.
//

private void WriteToEventLog(OdbcException e, string action)


{
EventLog log = new EventLog();
log.Source = eventSource;
log.Log = eventLog;
string message = exceptionMessage + "\n\n";
message += "Action: " + action + "\n\n";
message += "Exception: " + e.ToString();

log.WriteEntry(message);
}
}
}

See Also
Concepts
Sample Role-Provider Implementation
Other Resources
Managing Authorization Using Roles
ASP.NET

Encrypting Configuration Information Using Protected


Configuration
Part of securing an application involves ensuring that highly sensitive information is not stored in a readable or easily
decodable format. Examples of sensitive information include user names, passwords, connection strings, and encryption keys.
Storing sensitive information in a non-readable format improves the security of your application by making it difficult for an
attacker to gain access to the sensitive information, even if an attacker gains access to the file, database, or other storage
location.
One of the primary places that sensitive information is stored in an ASP.NET application is the Web.config file. To help secure
information in configuration files, ASP.NET provides a feature called protected configuration, which enables you to encrypt
sensitive information in a configuration file.
In This Section
Overview of Protected Configuration
Specifying a Protected Configuration Provider
Encrypting and Decrypting Configuration Sections
Importing and Exporting Protected Configuration RSA Key Containers
Understanding Machine-Level and User-Level RSA Key Containers
Walkthrough: Encrypting Configuration Information Using Protected Configuration
Walkthrough: Creating and Exporting an RSA Key Container
Implementing a Protected Configuration Provider
Reference
ProtectedConfiguration
Related Sections
ASP.NET Web Site Security (Visual Studio)
ASP.NET

Overview of Protected Configuration


You can use protected configuration to encrypt sensitive information, including user names and passwords, database
connection strings, and encryption keys, in a Web application configuration file such as the Web.config file. Encrypting
configuration information can improve the security of your application by making it difficult for an attacker to gain access to
the sensitive information even if the attacker gains access to your configuration file.
For example, an unencrypted configuration file might contain a section specifying connection strings used to connect to a
database, as shown in the following example:

<configuration>
<connectionStrings>
<add name="SampleSqlServer" connectionString="Data Source=localhost;Integrated Security
=SSPI;Initial Catalog=Northwind;" />
</connectionStrings>
</configuration>

A configuration file that encrypts the connection string values using protected configuration does not show the connection
strings in clear text, but instead stores them in encrypted form, as shown in the following example:

<configuration>

<connectionStrings configProtectionProvider="RsaProtectedConfigurationProvider">
<EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
xmlns="http://www.w3.org/2001/04/xmlenc#">
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<KeyName>RSA Key</KeyName>
</KeyInfo>
<CipherData>
<CipherValue>RXO/zmmy3sR0iOJoF4ooxkFxwelVYpT0riwP2mYpR3FU+r6BPfvsqb384pohivkyNY
7Dm4lPgR2bE9F7k6TblLVJFvnQu7p7d/yjnhzgHwWKMqb0M0t0Y8DOwogkDDXFxs1UxIhtknc+2a7UGtGh6Di3N572q
xdfmGfQc7ZbwNE=
</CipherValue>
</CipherData>
</EncryptedKey>
</KeyInfo>
<CipherData>
<CipherValue>KMNKBuV9nOid8pUvdNLY5I8R7BaEGncjkwYgshW8ClKjrXSM7zeIRmAy/cTaniu8Rfk92K
VkEK83+UlQd+GQ6pycO3eM8DTM5kCyLcEiJa5XUAQv4KITBNBN6fBXsWrGuEyUDWZYm6Eijl8DqRDb11i+StkBLlHPy
yhbnCAsXdz5CaqVuG0obEy2xmnGQ6G3Mzr74j4ifxnyvRq7levA2sBR4lhE5M80Cd5yKEJktcPWZYM99TmyO3KYjtmR
W/Ws/XO3z9z1b1KohE5Ok/YX1YV0+Uk4/yuZo0Bjk+rErG505YMfRVtxSJ4ee418ZMfp4vOaqzKrSkHPie3zIR7SuVU
eYPFZbcV65BKCUlT4EtPLgi8CHu8bMBQkdWxOnQEIBeY+TerAee/SiBCrA8M/n9bpLlRJkUb+URiGLoaj+XHym//fmC
clAcveKlba6vKrcbqhEjsnY2F522yaTHcc1+wXUWqif7rSIPhc0+MT1hB1SZjd8dmPgtZUyzcL51DoChy+hZ4vLzE=
</CipherValue>
</CipherData>
</EncryptedData>
</connectionStrings>

When the page is requested, the .NET Framework decrypts the connection string information and makes it available to your
application.
Note
You cannot use protected configuration to encrypt the configProtectedData section of a configuration file. You also cannot
use protected configuration to encrypt the configuration sections that do not employ a section handler or sections that are p
art of the managed cryptography configuration. The following is a list of configuration sections that cannot be encrypted usin
g protected configuration: processModel, runtime, mscorlib, startup, system.runtime.remoting, configProtectedData,
satelliteassemblies, cryptographySettings, cryptoNameMapping, and cryptoClasses. It is recommended that you use
other means of encrypting sensitive information, such as the ASP.NET Set Registry console application (Aspnet_setreg.exe)
tool, to protect sensitive information in these configuration sections. For information on the ASP.NET Set Registry console ap
plication (Aspnet_setreg.exe), see article Q329290, "How to use the ASP.NET utility to encrypt credentials and session state
connection strings," in the Microsoft Knowledge Base at the Microsoft support Web site.

Security Note
Encrypted configuration information is decrypted when loaded into the memory that is used by your application. If the mem
ory for your application is compromised, the sensitive information from your protected configuration section might be comp
romised as well.

Working with Protected Configuration


You manage protected configuration using the ASP.NET IIS Registration tool (Aspnet_regiis.exe) or the protected
configuration classes in the System.Configuration namespace.
The Aspnet_regiis.exe tool (located in the %SystemRoot%\Microsoft.NET\Framework\versionNumber folder) includes
options for encrypting and decrypting sections of a Web.config file, creating or deleting key containers, exporting and
importing key container information, and managing access to a key container.
Encryption and decryption of the contents of a Web.config file is performed using a ProtectedConfigurationProvider class. The
following list describes the protected configuration providers included in the .NET Framework:
DPAPIProtectedConfigurationProvider. Uses the Windows Data Protection API (DPAPI) to encrypt and decrypt data.
RsaProtectedConfigurationProvider. Uses the RSA encryption algorithm to encrypt and decrypt data.
Both providers offer strong encryption of data; however, if you are planning to use the same encrypted configuration file on
multiple servers, such as a Web farm, only the RsaProtectedConfigurationProvider enables you to export the encryption
keys used to encrypt the data and import them on another server.
You can specify which ProtectedConfigurationProvider you want to use by configuring it in your application's Web.config
file, or you can use one of the ProtectedConfigurationProvider instances configured in the Machine.config file. For more
information, see Specifying a Protected Configuration Provider.
Once you have specified which provider to use, you can encrypt or decrypt the contents of the Web.config file for your
application. For more information, see Encrypting and Decrypting Configuration Sections.
Note
As a best practice when securing your Web applications, it is important that you always keep your application server up to da
te with the latest security patches for Microsoft Windows and Internet Information Services (IIS), as well as any security patch
es for Microsoft SQL Server or other membership data sources. For detailed information about best practices for writing sec
ure code and securing applications, see the book "Writing Secure Code" by Michael Howard and David LeBlanc, and see the g
uidance provided on the Microsoft Patterns and Practices Web site.

See Also
Tasks
Walkthrough: Encrypting Configuration Information Using Protected Configuration
Other Resources
Encrypting Configuration Information Using Protected Configuration
ASP.NET

Specifying a Protected Configuration Provider


You can encrypt and decrypt sections of a Web.config file using a ProtectedConfigurationProvider class. The following list
describes the protected configuration providers included in the .NET Framework:
DPAPIProtectedConfigurationProvider. Uses the Windows Data Protection API (DPAPI) to encrypt and decrypt data.
RsaProtectedConfigurationProvider. Uses the RSA encryption algorithm to encrypt and decrypt data.
Both providers offer strong encryption of data. However, if you are planning on using the same encrypted configuration file on
multiple servers, such as a Web farm, only the RSAProtectedConfigurationProvider enables you to export the encryption keys
and import them on another server.
The .NET Framework also enables you to define your own protected configuration providers. For details, see
Implementing a Protected Configuration Provider.
Configuring a Protected Configuration Provider
You can specify your own protected configuration provider or you can use one of the providers built into ASP.NET. By default,
the Machine.config file specifies the following protected configuration providers:
An RsaProtectedConfigurationProvider instance named RsaProtectedConfigurationProvider. This is the configured
as the default provider.
An DPAPIProtectedConfigurationProvider instance named DataProtectionConfigurationProvider.
You specify a protected configuration provider in the configProtectedData section of a configuration file. If you want to
specify your own provider with custom settings, you can declare a new provider instance using the add element of the
providers element. You can identify your provider instance as the default provider using the defaultProvider attribute of the
configProtectedData element.
The following example configures an RsaProtectedConfigurationProvider instance with the name SampleProvider and sets
it as the default provider.

<configuration>
<configProtectedData defaultProvider="SampleProvider">
<providers>
<add name="SampleProvider"
type="System.Configuration.RsaProtectedConfigurationProvider,
System.Configuration, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a,
processorArchitecture=MSIL"
keyContainerName="SampleKeys"
useMachineContainer="true" />
</providers>
</configProtectedData>
</configuration>

You use the name of the protected configuration provider instance when encrypting configuration sections. For more
information, see Encrypting and Decrypting Configuration Sections.
Protected Configuration Provider Options
Each protected configuration provider exposes options that you can set using attributes of the provider's declaration in the
configuration file. All providers require the type and description attribute as well as the keyName for the provider instance.
Beyond that, the options are unique to each provider type.
The following table describes the configuration options for the RSAProtectedConfigurationProvider.
Attribut Description
e
type The type of protected configuration provider. The following example shows a type definition for the RsaProtectedC
onfigurationProvider:

type="System.Configuration.RsaProtectedConfigurationProvider,
System.Configuration, Version=2.0. 0.0,
Culture=neutral,
PublicKeyToken=b03f5f7f11d0a3a,
processorArchitecture=MSIL"

descripti A description of the provider instance.


on

keyCont The name of the RSA key container used to encrypt or decrypt the contents of the Web.config file.
ainerNa
me Note
The ASP.NET process must have read access to the specified RSA key container. You can grant access to an RSA ke
y container with the Aspnet_regiis.exe tool using the -pa switch. For more information, see
Importing and Exporting Protected Configuration RSA Key Containers.

useMach true if the RSA key container is a machine-level key container; false if the RSA key container is a user-level key cont
ineCont ainer. For more information, see Encrypting Configuration Information Using Protected Configuration.
ainer

useOAEP true to use Optimal Asymmetric Encryption Padding (OAEP) when encrypting and decrypting; otherwise, false. For
more information, see the RSAOAEPKeyExchangeFormatter class.

cspProvi The name of the Windows cryptography API (crypto API) cryptographic service provider (CSP). For more informatio
derNam n, see ProviderName.
e

The following table describes the configuration options for the DPAPIProtectedConfigurationProvider.
Attrib Description
ute
type The type of protected configuration provider. The following example shows a type definition for the DPAPIProtectedC
onfigurationProvider:

type="System.Configuration.DPAPIProtectedConfigurationProvider,
System.Configuration, Version=2.0.0.0,
Culture=neutral,
PublicKeyToken=b03f5f7f11d0a3a,
processorArchitecture=MSIL"

descri A description of the provider instance.


ption

keyE An application-specific value to include with the encryption key to protect against other applications being able to decry
ntrop pt encrypted information. For more information, refer to the OptionalEntropy parameter of the CryptProtectData m
y ethod of the Windows data protection API (DPAPI).

useM true to use machine-specific protection; false to use user-account-specific protection. When true, any process running
achin on the computer can unprotect data, and it is recommended that you restrict access to encrypted data using an Access
eProt Control List (ACL). For more information, see the CRYPTPROTECT_LOCAL_MACHINE value for the dwFlags parameter
ectio of the CryptProtectData method of the Windows data protection API (DPAPI).
n

See Also
Tasks
Walkthrough: Encrypting Configuration Information Using Protected Configuration
Other Resources
Encrypting Configuration Information Using Protected Configuration
ASP.NET

Encrypting and Decrypting Configuration Sections


You can use the ASP.NET IIS Registration Tool (Aspnet_regiis.exe) to encrypt or decrypt sections of a Web configuration file.
ASP.NET will automatically decrypt encrypted configuration elements when the Web.config file is processed.
Note
The Aspnet_regiis.exe tool is located in the %windows%\Microsoft.NET\Framework\versionNumber folder.

You can also use the protected configuration classes in the System.Configuration namespace to encrypt and decrypt sections
of a Web configuration file, sections of a configuration file for an executable (.exe), or sections in the machine-level and
application-level configuration files. For more information, see the ProtectSection method of the SectionInformation class. For
information on referencing a section of a Web.config file, see the WebConfigurationManager class. For information on
referencing configuration sections of files other than the Web.config file, see the ConfigurationManager class.
Encrypting a Web Configuration Section
To encrypt configuration file contents, use the Aspnet_regiis.exe tool with the –pe option and the name of the configuration
element to be encrypted.
Use the –app option to identify the application for which the Web.config file will be encrypted and the -site option to identify
which Web site the application is a part of. The Web site is identified using the site number from the Internet Information
Services (IIS) metabase. You can retrieve the site number from the INSTANCE_META_PATH server variable in the
ServerVariables collection. For example, when IIS is installed, a Web site named "Default Web Site" is created as site 1. In pages
served from that site, the INSTANCE_META_PATH server variable returns "/LM/W3SVC/1". If you do not specify a -site option,
site 1 is used.
Use the –prov option to identify the name of the ProtectedConfigurationProvider that will perform the encryption and
decryption. If you do not specify a provider using the -prov option, the provider configured as the defaultProvider is used.
Note
If you are using an RsaProtectedConfigurationProvider instance that specifies a custom key container, you must create the ke
y container before running the Aspnet_regiis.exe tool. For more information, see
Importing and Exporting Protected Configuration RSA Key Containers.

The following command encrypts the connectionStrings element in the Web.config file for the application
SampleApplication. Because no -site option is included, the application is assumed to be from Web site 1 (most commonly
Default Web Site in IIS). The encryption is performed using the RsaProtectedConfigurationProvider specified in the
machine configuration.

aspnet_regiis -pe "connectionStrings" -app "/SampleApplication" -prov "RsaProtectedConfigur


ationProvider"

When a page or other ASP.NET resource in the application is requested, ASP.NET calls the provider for the protected
configuration section to decrypt the information for use by ASP.NET and your application code.
Note
To decrypt and encrypt a section of the Web.config file, the ASP.NET process must have permission to read the appropriate e
ncryption key information. For more information, see Importing and Exporting Protected Configuration RSA Key Containers.

Decrypting a Web Configuration Section


To decrypt encrypted configuration file contents, you use the Aspnet_regiis.exe tool with the -pd switch and the name of the
configuration element to be decrypted. Use the –app and -site switches to identify the application for which the Web.config
file will be decrypted. You do not need to specify the –prov switch to identify the name of the
ProtectedConfigurationProvider, because that information is read from the configProtectionProvider attribute of the
protected configuration section.
The following command decrypts the connectionStrings element in the Web.config file for the ASP.NET application
SampleApplication:

aspnet_regiis -pd "connectionStrings" -app "/SampleApplication"

See Also
Tasks
Walkthrough: Encrypting Configuration Information Using Protected Configuration
Concepts
Specifying a Protected Configuration Provider
Other Resources
Encrypting Configuration Information Using Protected Configuration
ASP.NET

Importing and Exporting Protected Configuration RSA Key


Containers
Protected configuration provides the capability to create, delete, export, and import RSA key containers when using the
RsaProtectedConfigurationProvider. One scenario where this is useful is in a Web farm where the same encrypted Web.config
file will be deployed to several servers. In that case, the same RSA key container must also be deployed to those servers. To
accomplish this, you would create an RSA key container for the application, export it to an XML file, and import it on each
server that needs to decrypt the encrypted Web.config file.
Creating RSA key containers can also be useful on a single Web server that hosts multiple ASP.NET applications. By creating an
RSA key container for each application or for each set of applications for a single customer, you can improve the security of an
application's sensitive configuration information by ensuring that the Web.config file for one application cannot be decrypted
using the RSA key container from another application.
Creating an RSA Key Container
To create an RSA key container, you use the ASP.NET IIS registration tool (Aspnet_regiis.exe) with the –pc switch. You must
give the key container a name, which identifies the key container used by the RsaProtectedConfigurationProvider specified
in the configProtectedData section of your application's Web.config file. To ensure that your newly created RSA key
container can be exported, you must include the -exp option.
For example, the following command creates an RSA key container named SampleKeys that is a machine-level key container
and is exportable.
aspnet_regiis -pc "SampleKeys"–exp
The following example shows the configProtectedData section of a Web.config file. The section specifies an
RsaProtectedConfigurationProvider that uses a machine-level RSA key container named SampleKeys.

<configProtectedData>
<providers>
<add name="SampleProvider"
type="System.Configuration.RsaProtectedConfigurationProvider, System.Configurati
on, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
processorArchitecture=MSIL"
keyContainerName="SampleKeys"
useMachineContainer="true" />
</providers>
</configProtectedData>

Note
To guard against encryption and decryption keys for protected configuration sections being unintentionally deleted, RSA key
containers are not deleted if the .NET Framework is uninstalled.

Granting Authority to Access an RSA Key Container


By default, RSA key containers are tightly protected by NTFS access control lists (ACLs) on the server where they are installed.
This improves the security of the encrypted information by restricting who can access the encryption key.
Before ASP.NET can use an RSA key container, the process identity of your ASP.NET application must be authorized to have
read access to that RSA key container. For information on setting and determining the identity of your ASP.NET application, see
ASP.NET Impersonation.
You can use the Aspnet_regiis.exe tool with the -pa switch to give the identity of your ASP.NET application permission to read
an RSA key container. For example, the following command grants the Windows Server 2003 NETWORK SERVICE account
access to read the machine-level RSA key container named SampleKeys:

aspnet_regiis -pa "SampleKeys" "NT AUTHORITY\NETWORK SERVICE"


Note
If the RSA key container is a user-level container, you must be logged on as the user in whose Windows profile the key is sto
red, and you must include the -pku option to grant access to the user-level RSA key container. For more information, see
Understanding Machine-Level and User-Level RSA Key Containers.

To use the default RsaProtectedConfigurationProvider specified in the machine configuration, you must first grant the
application's Windows identity access to the machine key container named NetFrameworkConfigurationKey, which is the key
container specified for the default provider. For example, the following command grants the NETWORK SERVICE account
access to the RSA key container used by the default RsaProtectedConfigurationProvider:

aspnet_regiis -pa "NetFrameworkConfigurationKey" "NT AUTHORITY\NETWORK SERVICE"

The NetFrameworkConfigurationKey RSA key container is the default key container for commands issued by the
Aspnet_regiis.exe tool. The preceding command could therefore also be issued as the following:

aspnet_regiis -pa "NT AUTHORITY\NETWORK SERVICE"

Exporting an RSA Key Container


To export an RSA key container to an XML file, you can use the Aspnet_regiis.exe tool with the –px switch. You can use the XML
file as backup for the RSA key container or to import the RSA key container on a different server. The private key portion of the
RSA key container is required in order to decrypt encrypted information. To make use of your exported key container on
another server, you will need to import the private key as well. You can include the private key in your XML file by specifying
the –pri option when exporting the key. You must also specify whether the exported key container is machine-level or user-
level. To export a user-level key container, you must be logged on as the user in whose Windows profile the key is stored. To
specify a user-level key, include the -pku option when exporting the encryption key information; otherwise the exported key
will be from the machine key store. For more information on machine-level and user-level encryption keys, see
Understanding Machine-Level and User-Level RSA Key Containers.
For example, the following command exports the machine-level RSA key container named SampleKeys to the file named
keys.xml and includes the private key information.

aspnet_regiis -px "SampleKeys" keys.xml -pri

Note
For security, after you export an RSA key container to an XML file, copy the XML file to a location external to the server and d
elete the XML file from the server. This reduces the chance of an attacker gaining access to your RSA key container and there
by the ability to decrypt Web.config files encrypted using that RSA key container.

Importing an RSA Key Container


You can use the Aspnet_regiis.exe tool with the –pi switch to import an RSA key container from an XML file. You must also
specify whether the imported key container is a machine-level or user-level key container. To import a user-level key container,
you must be logged on as the user in whose Windows profile the key will be stored. To specify a user-level key, include the -
pku option when importing the encryption key information; otherwise the exported key will be imported to the machine key
store.
For example, the following command imports a machine-level RSA key container named SampleKeys from the file named
keys.xml:

aspnet_regiis -pi "SampleKeys" keys.xml

The identity of the ASP.NET application that will use the imported RSA key container must be granted authority to read the
contents of the RSA key container. For more information, see Granting Authority to Access an RSA Key Container earlier in this
topic.
Deleting an RSA Key Container
To delete an RSA key container, you can use the Aspnet_regiis.exe tool with the –pz switch. Before you delete an RSA key
container, ensure that you have either exported the key to an XML file so that it can be imported later, or that there is no
information encrypted with the RSA key container that will ever need to be decrypted.
When deleting an RSA key container, you must specify the name of the key container and identify the container as machine-
level or user-level. To delete a user-level key container, you must be logged on as the user in whose Windows profile the key is
stored.
For example, the following command deletes the machine-level RSA key container named SampleKeys.

aspnet_regiis -pz "SampleKeys"

See Also
Tasks
Walkthrough: Creating and Exporting an RSA Key Container
Other Resources
Encrypting Configuration Information Using Protected Configuration
ASP.NET

Understanding Machine-Level and User-Level RSA Key


Containers
The RsaProtectedConfigurationProvider class can use either machine-level or user-level RSA key containers. Microsoft
Windows makes machine-level key containers available to all users, whereas a user-level key container is available only to the
user that created (or imported) the key container.
Comparing Machine-Level and User-Level RSA Key Containers
User-level RSA key containers are stored with the Windows user profile for a particular user and can be used to encrypt and
decrypt information for applications that run under that specific user identity. User-level RSA key containers can be useful if
you want to ensure that the RSA key information is removed when the Windows user profile is removed. However, because
you must be logged in with the specific user account that will make use of the user-level RSA key container in order to encrypt
or decrypt protected configuration sections, they are inconvenient to use.
Machine-level RSA key containers are available to all users that can log in to a computer, by default, and are the most useful as
you can use them to encrypt or decrypt protected configuration sections while logged in with an administrator account. A
machine-level RSA key container can be used to protect information for a single application, all the applications on a server, or
a group of applications on a server that run under the same user identity. Although machine-level RSA key containers are
available to all users, they can be secured with NTFS Access Control Lists (ACLs) so that only required users can access them.
Note
It is recommended that you only secure sensitive information using protected configuration on file systems formatted using
NTFS, so that you can restrict access to encryption key information using ACLs.

As there is little benefit from using user-level RSA key containers, it is recommended that you use machine-level RSA key
containers when protecting configuration sections using the RSAProtectedConfigurationProvider provider. When you create an
RSA key container to protect configuration information for one or more applications, it is recommended that you restrict the
access to the machine-level RSA key container using the Aspnet_regiis.exe tool, with the -pa option to add access to the key for
a particular identity and the -pr option to remove access to the key. For more information on how to set or determine the
identity of an ASP.NET application, see ASP.NET Impersonation. For more information on granting read access to an RSA key
container, see Importing and Exporting Protected Configuration RSA Key Containers.
Identifying Machine-Level and User-Level RSA Key Containers for the Aspnet_regiis.exe Tool
When creating, exporting, importing, or deleting an RSA key container using the Aspnet_regiis.exe tool, you must specify
whether the RSA key container is a machine-level key container or a user-level key container. You identify an RSA key
container as a user-level key container with the -pku option; otherwise, the RSA key container is considered a machine-level
container.
See Also
Tasks
Walkthrough: Creating and Exporting an RSA Key Container
Other Resources
Encrypting Configuration Information Using Protected Configuration
ASP.NET

Walkthrough: Encrypting Configuration Information Using


Protected Configuration
Provides a step-by-step example for encrypting sections of a configuration file for an ASP.NET application.
Protected Configuration helps improve the security of an application by letting you encrypt sensitive information that is stored
in a Web.config file. You can use aspnet_regiis.exe to encrypt sections of the Web.config file and manage encryption keys.
ASP.NET decrypts the configuration file when it processes the file. Therefore, decryption does not require any additional code.
For more information about Protected Configuration, see Encrypting Configuration Information Using Protected Configuration.
During this walkthrough, you will learn how to do the following:
Encrypt sections of a Web.config file by using the default Protected Configuration provider.
Access decrypted configuration information in an ASP.NET page.
Prerequisites
In order to complete this walkthrough, you will need the following:
Microsoft Internet Information Services (IIS) installed and configured on the computer that will host the site.
For detailed information about how to install and configure IIS, see the online Help that is included with the IIS
installation or go to Internet Information Services (IIS) 6.0 Technical Resources.
An ASP.NET Web site.
If you already have a Web site, you can use that site. Otherwise, for detailed information about how to create a virtual
directory or Web site, see How to: Create and Configure Virtual Directories in IIS.
Granting Read Access to an RSA Encryption Key
Before ASP.NET can decrypt encrypted information in the Web.config file, the identity of your ASP.NET application must have
read access to the encryption key that is used to encrypt and decrypt the encrypted sections. This walkthrough uses the default
RsaProtectedConfigurationProvider provider that is specified in the Machine.config file and named
"RsaProtectedConfigurationProvider". The RSA key container that is used by the default
RsaProtectedConfigurationProvider provider is named "NetFrameworkConfigurationKey".
To grant the ASP.NET identity read access to the default RSA key container
1. Open a text editor, and then copy the following code into a new file.
VB
<%@ Page Language="VB" %>
<%
Response.Write(System.Security.Principal.WindowsIdentity.GetCurrent().Name)
%>

C#
<%@ Page Language="C#" %>
<%
Response.Write(System.Security.Principal.WindowsIdentity.GetCurrent().Name);
%>

2. Save the file in your application directory as identity.aspx.


3. To determine the identity of your ASP.NET application, open identity.aspx in a browser.
The impersonated identity of your ASP.NET application is displayed in the browser.
Note
Because you are using IIS for this walkthrough, do not use impersonation for the authentication for your site. That is, fo
r this walkthrough, use only anonymous authentication as the identity of your ASP.NET application. If the identity of yo
ur application is the user ID that you are currently logged on as, such as DOMAIN\myuserid, in the Web.config file for t
he application, disable impersonation. To disable impersonation in the Web.config file, open the Web.config file, and th
en remove the <identity> element. After you remove the <identity> element, update identity.aspx in your browser to
display the modified identity for the application.

4. At the command prompt, run aspnet_regiis.exe with the following options:


The -pa option, followed by the name of the RSA key container for the default
RsaProtectedConfigurationProvider.
The identity of your ASP.Net application, as determined in the preceding step.
For example, the following command grants the NETWORK SERVICE account access to the machine-level
"NetFrameworkConfigurationKey" RSA key container.

aspnet_regiis -pa "NetFrameworkConfigurationKey" "NT AUTHORITY\NETWORK SERVICE"


Do not close the Command Prompt window.
Encrypting Sections of the Web.config File
Now that the identity of your ASP.NET application has read access to the RSA key container for the default
RsaProtectedConfigurationProvider object, you will encrypt sections of the Web.config file for your ASP.NET application by
using that key container. Then, ASP.NET decrypts the sections when it processes the Web.config file.
To encrypt the <connectionStrings> and <machineKey> sections of the Web.config file
1. In a text editor, open the Web.config file for your application.
If you do not have a Web.config file for your ASP.NET application, open a text editor, copy the example
configuration into a new file, and then save the file in your ASP.NET application directory as web.config.
2. Make sure that there is both a <connectionStrings> child element and a <machineKey> child element for the
<system.web> element, as shown in the following example.

<configuration>
<connectionStrings>
<add name="SqlServices" connectionString="Data Source=localhost;Integrated Secur
ity=SSPI;Initial Catalog=Northwind;" />
</connectionStrings>

<system.web>

<machineKey validationKey="D61B3C89CB33A2F1422FF158AFF7320E8DB8CB5CDA1742572A487D
94018787EF42682B202B746511891C1BAF47F8D25C07F6C39A104696DB51F17C529AD3CABE"
decryptionKey="FBF50941F22D6A3B229EA593F24C41203DA6837F1122EF17" />

</system.web>
</configuration>

3. Close the Web.config file.


4. At the command prompt, change the directory to the .NET Framework version 2.0 directory by typing the following
command:
cd \WINDOWS\Microsoft.Net\Framework\v2.0.*
5. At the command prompt, run aspnet_regiis.exe with the following options:
The -pe option and the string "connectionStrings" to encrypt the connectionStrings element of the Web.config
file for your application.
The -app option and the name of your application.
For example, the following command encrypts the <connectionStrings> section of the Web.config file for an application
named MyApplication.
aspnet_regiis -pe "connectionStrings" -app "/MyApplication"
6. Repeat the preceding step for the <machineKey> child element of the <system.web> element, as shown in the following
example:
aspnet_regiis -pe "system.web/machineKey" -app "/MyApplication"
Do not close the Command Prompt window.
7. Open Web.config, and then view the encrypted contents.
The contents will look similar to the following example Web.config file.

<configuration>

<connectionStrings configProtectionProvider="RsaProtectedConfigurationProvider">
<EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
xmlns="http://www.w3.org/2001/04/xmlenc#">
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"
/>
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"
/>
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<KeyName>RSA Key
</KeyName>
</KeyInfo>
<CipherData>
<CipherValue>WcFEbDX8VyLfAsVK8g6hZVAG1674ZFc1kWH0BoazgOwdBfinhcAmQmn
In0oHtZ5tO2EXGl+dyh10giEmO9NemH4YZk+iMIln+ItcEay9CGWMXSen9UQLpcQHQqMJErZiPK4qPZaRWwqck
LqriCl9X8x9OE7jKIsO2Ibapwj+1Jo=
</CipherValue>
</CipherData>
</EncryptedKey>
</KeyInfo>
<CipherData>
<CipherValue>OpWQgQbq2wBZEGYAeV8WF82yz6q5WNFIj3rcuQ8gT0MP97aO9SHIZWwNggSEi
2Ywi4oMaHX9p0NaJXG76aoMR9L/WasAxEwzQz3fexFgFSrGPful/5txSPTAGcqUb1PEBVlB9CA71UXIGVCPTiw
F7zYDu8sSHhWa0fNXqVHHdLQYy1DfhXS3cO61vW5e/KYmKOGA4mjqT0VZaXgb9tVeGBDhjPh5ZlrLMNfYSozeJ
+m2Lsm7hnF6VvFm3fFMXa6+h0JTHeCXBdmzg/vQb0u3oejSGzB4ly+V9O0T4Yxkwn9KVDW58PHOeRT2//3iZfJ
fWV2NZ4e6vj4Byjf81o3JVNgRjmm9hr9blVbbT3Q8/j5zJ+TElCn6zPHvnuB70iG2KPJXqAj2GBzBk6cHq+WNe
bOQNWIb7dTPumuZK0yW1XDZ5gkfBuqgn8hmosTE7mCvieP9rgATf6qgLgdA6zYyVV6WDjo1qbCV807lczxa3bF
5KzKaVUSq5FS1SpdZKAE6/kkr0Ps++CE=
</CipherValue>
</CipherData>
</EncryptedData>
</connectionStrings>

<system.web>
<machineKey configProtectionProvider="RsaProtectedConfigurationProvider">
<EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
xmlns="http://www.w3.org/2001/04/xmlenc#">
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"
/>
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<KeyName>RSA Key
</KeyName>
</KeyInfo>
<CipherData>
<CipherValue>IwUopItbWX0mJdGWtAqE1LlsG3u5RBRlAXs9/GZj3HEfeUXduHVF76q6Ip
88YqlfLthH+DMBYdOZAF+hCOmS2agfTo1tKUvELRGIljS/BqEYxUO+/IOz9tllAw8ZlGF7AVCzptgIejI+iLXE
ZfMKW7f6EMGeb5vaaKXHIkYZwcM=
</CipherValue>
</CipherData>
</EncryptedKey>
</KeyInfo>
<CipherData>
<CipherValue>ivVyERVPNUzIb/i7/NUbRkxsxh8IG959vycwrzJO0vYWxHZ5i03SfrLbsGUV17
+FxZ6lbcrVaF5FY3zVm7dRMRvQpVFwaVcL
</CipherValue>
</CipherData>
</EncryptedData>
</machineKey>

</system.web>
</configuration>

8. Close the Web.config file.


Accessing Decrypted Configuration Settings
ASP.NET automatically decrypts the contents of the Web.config file when it processes the file. Therefore, no additional steps are
required to decrypt the encrypted configuration settings for use by other ASP.NET features or to access the values in your code.
However, you can follow these steps, if you want to view the decrypted settings.
To view the decrypted configuration values
1. Open a text editor, and then copy the following ASP.NET code into a new file.
VB
<%@ Page Language="VB" %>
<%@ Import Namespace="System.Configuration" %>
<%@ Import Namespace="System.Web.Configuration" %>
<script runat="server">

Public Sub Page_Load()

ConnectionStringsGrid.DataSource = ConfigurationManager.ConnectionStrings
ConnectionStringsGrid.DataBind()

Dim config As System.Configuration.Configuration = _


WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath)
Dim key As MachineKeySection = _
CType(config.GetSection("system.web/machineKey"), MachineKeySection)
DecryptionKey.Text = key.DecryptionKey
ValidationKey.Text = key.ValidationKey

End Sub

</script>
<html>
<body>

<form runat="server">

<asp:GridView runat="server" CellPadding="4" id="ConnectionStringsGrid" />


<P>
MachineKey.DecryptionKey = <asp:Label runat="Server" id="DecryptionKey" /><BR>
MachineKey.ValidationKey = <asp:Label runat="Server" id="ValidationKey" />

</form>

</body>
</html>

C#
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Configuration" %>
<%@ Import Namespace="System.Web.Configuration" %>
<script runat="server">

public void Page_Load()


{
ConnectionStringsGrid.DataSource = ConfigurationManager.ConnectionStrings;
ConnectionStringsGrid.DataBind();

Configuration config = WebConfigurationManager.OpenWebConfiguration(Request.Applicat


ionPath);
MachineKeySection key =
(MachineKeySection)config.GetSection("system.web/machineKey");
DecryptionKey.Text = key.DecryptionKey;
ValidationKey.Text = key.ValidationKey;
}

</script>
<html>

<body>

<form runat="server">

<asp:GridView runat="server" CellPadding="4" id="ConnectionStringsGrid" />


<P>
MachineKey.DecryptionKey = <asp:Label runat="Server" id="DecryptionKey" /><BR>
MachineKey.ValidationKey = <asp:Label runat="Server" id="ValidationKey" />

</form>

</body>
</html>

2. Save the file as walkthrough.aspx, and then view the file in the browser.
You will see the decrypted values from your encrypted Web.config file.
3. To keep the sensitive information from the Web site private, delete the walkthrough.aspx file when you are finished with
this walkthrough.
Next Steps
You can decrypt the encrypted Web.config file contents, if you want to, by running aspnet_regiis.exe with the -pd option. The
syntax is the same as the syntax for encrypting Web.config file contents with the -pe option, except that you do not specify a
Protected Configuration provider. The appropriate provider is identified using the configProtectionProvider element for the
protected section. For example, the following commands decrypt the <connectionStrings> element and the <machineKey>
child element of the <system.web> element in the Web.config file for the ASP.NET application named MyApplication.
aspnet_regiis -pd "connectionStrings" -app "/MyApplication"
aspnet_regiis -pd "system.web/machineKey" -app "/MyApplication"
See Also
Tasks
Walkthrough: Creating and Exporting an RSA Key Container
Other Resources
Encrypting Configuration Information Using Protected Configuration
ASP.NET

Walkthrough: Creating and Exporting an RSA Key Container


Provides a step-by-step example for creating, exporting, and importing an encryption key to decrypt encrypted Web.config
sections from a single encrypted file on multiple servers.
Protected Configuration helps improve the security of an application by enabling you to encrypt sensitive information that is
stored in a configuration file. The .NET Framework automatically decrypts the configuration file when the configuration file is
processed, and decryption does not require any additional code. You can use aspnet_regiis.exe to encrypt sections of the
configuration file and to manage encryption keys. For more information about Protected Configuration, see
Encrypting Configuration Information Using Protected Configuration.
Protected Configuration lets you create, delete, export, and import custom encryption keys for use with the
RsaProtectedConfigurationProvider provider. This lets you create backup copies of encryption keys or copy an encryption key
to multiple Web servers, such as a Web farm, so that an application that has an encrypted Web.config file can be copied to
multiple locations.
During this walkthrough, you will learn how to do the following:
Create a custom RSA key container.
Specify a Protected Configuration provider that uses a custom RSA key container.
Encrypt sections of a Web.config file by using a custom RSA key container.
Export a custom RSA key container to an XML file.
Import a custom RSA key container from an XML file.
Prerequisites
In order to complete this walkthrough, you will need the following:
Microsoft Internet Information Services (IIS) installed and configured on the computer that will host the site.
For detailed information about how to install and configure IIS, see the online Help that is included with the IIS
installation or go to Internet Information Services (IIS) 6.0 Technical Resources.
An ASP.NET Web site.
If you already have a Web site, you can use it for this walkthrough. Otherwise, for detailed information about how to
create a virtual directory or Web site, see How to: Create and Configure Virtual Directories in IIS.
Creating a Custom RSA Key Container
In this part of the walkthrough, you will create an RSA key container by using aspnet_regiis.exe with the -pc option. This
identifies the RSA key container as a user-level key container. RSA key containers must be identified as either user-level (by
using the -pku option) or machine-level (by not using the -pku option). For more information about machine-level and user-
level RSA key containers, see Understanding Machine-Level and User-Level RSA Key Containers.
To create a machine-level RSA key container
1. Open a command prompt.
To do this, in Microsoft Windows, click Start, click Run, in the Open box, type cmd, and then click OK.
2. At the command prompt, enter the following command to change the directory to the .NET Framework version 2.0
directory:
cd \WINDOWS\Microsoft.Net\Framework\v2.0.*
3. Create a new, machine-level RSA key container by running aspnet_regiis.exe with the following options:
The -pc option followed by the name of the RSA key container, to create the RSA key pair.
The -exp option, to make sure that the key is exportable.
The following command will create the "MyKeys" key container.
aspnet_regiis -pc "MyKeys" -exp
Do not close the Command Prompt window.
Granting Read Access to an RSA Encryption Key
Before ASP.NET can decrypt encrypted information that is in the Web.config file, the identity of your ASP.NET application must
have read access to the encryption key that is used to encrypt and decrypt the encrypted sections.
To grant the ASP.NET identity access to the RSA key container
1. Open a text editor, and then copy the following code into a new file.
VB
<%@ Page Language="VB" %>
<%
Response.Write(System.Security.Principal.WindowsIdentity.GetCurrent().Name)
%>

C#
<%@ Page Language="C#" %>
<%
Response.Write(System.Security.Principal.WindowsIdentity.GetCurrent().Name);
%>

2. Save the file in your application directory as identity.aspx.


3. To determine the identity of your ASP.NET application, open identity.aspx in a browser.
The impersonated identity of your ASP.NET application appears in the browser.
Note
For this walkthrough, do not use impersonation authentication for your site. That is, use only anonymous authenticatio
n as the identity of your ASP.NET application. For this walkthrough, if the identity of your application is the user ID that
you are currently logged on as, such as DOMAIN\userid, in the Web.config file for the application, disable impersonatio
n. To disable impersonation, edit the Web.config file and remove the <identity> element. After you make this change,
update identity.aspx in your browser to display the modified identity for the application.

4. At the command prompt, use the following options to grant the identity access to the RSA key container by running
aspnet_regiis.exe:
The -pa option followed by the RSA key container name "MyKeys".
The identity of your ASP.NET application, as determined in the preceding step.
For example, the following command grants the NETWORK SERVICE account access to the machine-level RSA key
container "MyKeys".
aspnet_regiis -pa "MyKeys" "NT AUTHORITY\NETWORK SERVICE"
Specifying a Protected Configuration Provider
In this part of the walkthrough, you will specify an instance of a Protected Configuration provider in the Web.config file for
your ASP.NET application. The instance of a Protected Configuration provider that uses the machine-level RSA key container
named "MyKeys" is the one that you created in the preceding procedure.
To specify an instance of the Protected Configuration provider
1. Open a text editor, and then open the Web.config file for your ASP.NET application.
If you do not have a Web.config file for your ASP.NET application, open a text editor, and then copy the example
configuration into a new file. Save the file in your ASP.NET application directory as web.config.
2. Make sure that the configuration includes a <connectionStrings> element, as shown in the following example.

<configuration>
<connectionStrings>
<add name="SqlServices" connectionString="Data Source=localhost;Integrated Secur
ity=SSPI;Initial Catalog=Northwind;" />
</connectionStrings>
</configuration>

3. Add a <configProtectedData> section that includes an instance of the RsaProtectedConfigurationProvider class


named "MyProvider" that uses the machine-level RSA key container named "MyKeys", as shown in the following
example.

<configuration>
<configProtectedData>
<providers>
<add name="MyProvider"
type="System.Configuration.RsaProtectedConfigurationProvider, System.Con
figuration, Version=2.0. 0.0,
Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a,
processorArchitecture=MSIL"
keyContainerName="MyKeys"
useMachineContainer="true" />
</providers>
</configProtectedData>

<connectionStrings>
<add name="SqlServices" connectionString="Data Source=localhost;Integrated Secur
ity=SSPI;Initial Catalog=Northwind;" />
</connectionStrings>
</configuration>

4. Save, and then close the Web.config file.


Encrypting Sections of the Web.config File
Now that you have specified an instance of the RsaProtectedConfigurationProvider class that uses the "MyKeys" RSA key
container and the identity of your ASP.NET application has read access to "MyKeys", you will encrypt sections of the Web.config
file for your ASP.NET application by using "MyKeys", and then ASP.NET will decrypt the sections when it processes the
Web.config file.
To encrypt the <connectionStrings> section of the Web.config file
1. At the command prompt, run aspnet_regiis.exe with the following options:
The -pe option, followed by "connectionStrings", to encrypt the <connectionStrings> element of the Web.config
file for your application.
The -app option, to identify the name of your application.
The -prov option, followed by "MyProvider", to identify the RsaProtectedConfigurationProvider provider that
was specified in the Web.config file in the preceding section.
For example, the following command encrypts the <connectionStrings> section of the Web.config file for an application
named MyApplication.
aspnet_regiis -pe "connectionStrings" -app "/MyApplication" -prov "MyProvider"
2. Open the Web.config file, and then view the encrypted contents.
The contents will be similar to the following example Web.config file.
<configuration>
<configProtectedData>
<providers>
<add name="MyProvider"
type="System.Configuration.RsaProtectedConfigurationProvider, System.Con
figuration, Version=2.0. 0.0,
Culture=neutral, PublicKeyToken= b03f5f7f11d50a3a,
processorArchitecture=MSIL"
keyContainerName="MyKeys"
useMachineContainer="true" />
</providers>
</configProtectedData>

<connectionStrings configProtectionProvider="MyProvider">
<EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
xmlns="http://www.w3.org/2001/04/xmlenc#">
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"
/>
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"
/>
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<KeyName>RSA Key
</KeyName>
</KeyInfo>
<CipherData>
<CipherValue>WcFEbDX8VyLfAsVK8g6hZVAG1674ZFc1kWH0BoazgOwdBfinhcAmQmn
In0oHtZ5tO2EXGl+dyh10giEmO9NemH4YZk+iMIln+ItcEay9CGWMXSen9UQLpcQHQqMJErZiPK4qPZaRWwqck
LqriCl9X8x9OE7jKIsO2Ibapwj+1Jo=
</CipherValue>
</CipherData>
</EncryptedKey>
</KeyInfo>
<CipherData>
<CipherValue>OpWQgQbq2wBZEGYAeV8WF82yz6q5WNFIj3rcuQ8gT0MP97aO9SHIZWwNggSEi
2Ywi4oMaHX9p0NaJXG76aoMR9L/WasAxEwzQz3fexFgFSrGPful/5txSPTAGcqUb1PEBVlB9CA71UXIGVCPTiw
F7zYDu8sSHhWa0fNXqVHHdLQYy1DfhXS3cO61vW5e/KYmKOGA4mjqT0VZaXgb9tVeGBDhjPh5ZlrLMNfYSozeJ
+m2Lsm7hnF6VvFm3fFMXa6+h0JTHeCXBdmzg/vQb0u3oejSGzB4ly+V9O0T4Yxkwn9KVDW58PHOeRT2//3iZfJ
fWV2NZ4e6vj4Byjf81o3JVNgRjmm9hr9blVbbT3Q8/j5zJ+TElCn6zPHvnuB70iG2KPJXqAj2GBzBk6cHq+WNe
bOQNWIb7dTPumuZK0yW1XDZ5gkfBuqgn8hmosTE7mCvieP9rgATf6qgLgdA6zYyVV6WDjo1qbCV807lczxa3bF
5KzKaVUSq5FS1SpdZKAE6/kkr0Ps++CE=
</CipherValue>
</CipherData>
</EncryptedData>
</connectionStrings>
</configuration>

3. Close the Web.config file.


Accessing Decrypted Configuration Settings
ASP.NET automatically decrypts the contents of the Web.config when it processes the file. Therefore, no steps are required to
decrypt the encrypted configuration settings for use by other ASP.NET features or to access the values in your code. However,
you can follow these steps, if you want to view the decrypted settings.
To view the decrypted configuration values
1. Open a text editor, and then copy the following ASP.NET code into a new file.
VB
<%@ Page Language="VB" %>
<%@ Import Namespace="System.Configuration" %>
<script runat="server">

Public Sub Page_Load()

ConnectionStringsGrid.DataSource = ConfigurationManager.ConnectionStrings
ConnectionStringsGrid.DataBind()
End Sub

</script>
<html>

<body>

<form runat="server">
<asp:GridView runat="server" CellPadding="4" id="ConnectionStringsGrid" />
</form>

</body>
</html>

C#
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Configuration" %>
<script runat="server">

public void Page_Load()


{
ConnectionStringsGrid.DataSource = ConfigurationManager.ConnectionStrings;
ConnectionStringsGrid.DataBind();
}

</script>
<html>

<body>

<form runat="server">
<asp:GridView runat="server" CellPadding="4" id="ConnectionStringsGrid" />
</form>

</body>
</html>

2. Save the file as walkthrough.aspx, and then view the file in the browser.
You will see the decrypted values from your encrypted Web.config file.
Exporting and Importing an RSA Key Container
You can export an RSA key container to an XML file as a backup copy of the key values or copy the key container to additional
Web servers that will host a copy of the application that includes the encrypted Web.config file. Without the specific RSA key
container that was used to encrypt the Web.config file, ASP.NET will not be able to decrypt the encrypted configuration values.
To view the decrypted configuration values
1. At the command prompt, run aspnet_regiis.exe with the following options:
The -px option, followed by "MyKeys", which is the name of the RSA key container that you created in "Creating a
Custom RSA Key Container," earlier in this walkthrough.
The path of an .xml file to export the key container to.
The -pri option, to make sure that private key information is exported. Otherwise, the exported key information will
only encrypt information, not decrypt it.
For example, the following command exports the machine-level RSA key container named "MyKeys" to an .xml file
named keys.xml in the root directory of drive C.
aspnet_regiis -px "MyKeys" "c:\keys.xml" -pri
Note
To make sure that no one can decrypt the Web.config files that are encrypted by RSA key container, after you export th
e RSA key container to an .xml file, copy the .xml file to a location that is external to the Web server, and then delete the
file from the Web server.

You now have all information that is required to copy the application by using the encrypted Web.config file to a separate
Web server.
2. If you want to copy the application by using the encrypted Web.config file to a separate Web server, go to step 4.
3. If you do not have a second Web server to copy the Web application to, and you want to continue with this walkthrough,
complete the following steps to delete the RSA key container from the Web server. Then, treat the Web server as if it
were the second Web server.
a. To delete the RSA key container, at the command prompt, run aspnet_regiis.exe with the -pz switch, followed by
"MyKeys".
For example, the following command deletes "MyKeys":
aspnet_regiis -pz "MyKeys"
b. Go to step 5.
4. Copy the Web application, including the encrypted Web.config file, to a second Web server.
If you are not sure about how to copy the Web application to a second server, copy the whole folder and contents
from your existing application to the second Web server, and then to identify your application as a Web application,
follow the steps in How to: Create and Configure Virtual Directories in IIS.
5. On the second server, open a Command Prompt window. and then enter the following command to change the directory
to the .NET Framework version 2.0 directory:
cd \WINDOWS\Microsoft.Net\Framework\v2.0.*
6. Copy the .xml file that contains the exported RSA key container to the .NET Framework version 2.0 directory on the
second Web server.
In this walkthrough, you will copy the keys.xml file to the root directory of drive C.
7. On the second Web server, at the command prompt, run aspnet_regiis.exe with the following options:
The -pi option, followed by "MyKeys", which is the name of the exported key container, to import the RSA key
container.
The path of the .xml file that contains the exported key container
For example, the following command imports the RSA key container named "MyKeys".
aspnet_regiis -pi "MyKeys" "c:\keys.xml"
8. On the second Web server, delete the copy of the .xml file that contains the exported RSA key container.
9. On the second Web server, determine the identity of the ASP.NET application, and then grant that identity access to the
imported RSA key container by following the steps in "Granting Read Access to an RSA Encryption Key," earlier in this
walkthrough.
10. On the second Web server, view the decrypted configuration settings from the encrypted Web.config file by following the
steps in the preceding section.
See Also
Tasks
Walkthrough: Encrypting Configuration Information Using Protected Configuration
Other Resources
Encrypting Configuration Information Using Protected Configuration
ASP.NET

Implementing a Protected Configuration Provider


Protected configuration enables you to encrypt sections of an ASP.NET application's Web.config file in order to protect
sensitive information used by the application. This can improve the security of your application by making it difficult for an
attacker to gain access to the sensitive information even if an attacker gains access to your Web.config file. ASP.NET includes
two protected configuration providers that can be used to encrypt sections of a Web.config file:
RSAProtectedConfigurationProvider, which uses the RSACryptoServiceProvider to encrypt configuration sections, and
DPAPIProtectedConfigurationProvider, which uses the Windows Data Protection API (DPAPI) to encrypt configuration sections.
In some cases, you might need to encrypt information using an algorithm other than those available with the RSA or DPAPI
providers. In that case, you can build a custom protected configuration provider to be used by ASP.NET.
Required Classes for Protected Configuration Providers
To implement a protected configuration provider, you create a class that inherits the ProtectedConfigurationProvider abstract
class from the System.Configuration namespace. The ProtectedConfigurationProvider abstract class inherits the
ProviderBase abstract class from the System.Configuration.Provider namespace, so you must implement the required
members of the ProviderBase class as well. The following tables list the properties and methods that you must implement
from the ProviderBase and ProtectedConfigurationProvider abstract classes. To see an implementation of each member,
see How to: Build and Run the Protected Configuration Provider Example.
Required ProviderBase Members
Member Description
Initialize met Sets property values for the provider instance, including implementation-specific values and options supplied in
hod the application configuration.
Takes as input the name of the provider and a NameValueCollection of configuration settings.
Required ProtectedConfigurationProvider Members
Memb Description
er
Encrypt Performs the encryption. Takes as input an XmlNode object containing the configuration section to be encrypted. For e
metho xample, if the configuration section to be encrypted is the connectionStrings section, the XmlNode object represent
d s XML data similar to the following example.

<connectionStrings>
<add name="SampleConnectionString"
connectionString="Data Source=localhost;Initial Catalog=Northwind;Integrated Sec
urity=SSPI;" />
</connectionStrings>

The Encrypt method encrypts the OuterXml value of the XmlNode object and returns an XmlNode object in which a
n EncryptedData element is the root element, as shown in the following example:

<EncryptedData>
<!-- encrypted contents -->
</EncryptedData>

The format of the contents of the EncryptedData element is determined by your implementation. When the element i
s decrypted, ASP.NET will pass an XmlNode object to the Decrypt method, where the EncryptedData element is the r
oot element.
Decry Performs the decryption. Takes as input an XmlNode object containing the EncryptedData element of an encrypted
pt met configuration section. For example, if the connectionStrings section is the configuration section that was encrypted, t
hod he XmlNode object represents XML data similar to highlighted XML in the following example.

<connectionStrings configProtectionProvider="CustomProvider">
<EncryptedData>
<!-- encrypted contents -->
</EncryptedData>
</connectionStrings>

The Decrypt method decrypts the contents of the XmlNode object and returns an XmlNode object that represents t
he decrypted contents of the EncryptedData XmlNode object. For example, if the connectionStrings section was e
ncrypted, the Decrypt method returns an XmlNode object with XML data similar to the following example.

<connectionStrings>
<add name="SampleConnectionString"
connectionString="Data Source=localhost;Initial Catalog=Northwind;Integrated Sec
urity=SSPI;" />
</connectionStrings>

Sample Provider
For an example custom protected configuration provider that uses the TripleDESCryptoServiceProvider class to encrypt and
decrypt sections of a Web.config file, see How to: Build and Run the Protected Configuration Provider Example.
See Also
Tasks
How to: Build and Run the Protected Configuration Provider Example
Other Resources
Encrypting Configuration Information Using Protected Configuration
ASP.NET

How to: Build and Run the Protected Configuration Provider


Example
The topics in this section include the code for an example protected configuration provider. The example provider uses the
TripleDESCryptoServiceProvider class to encrypt and decrypt configuration sections in the Web.config file.
This topic describes how to build the example and configure an ASP.NET application to use the example provider. The example
protected configuration provider has been provided in Visual Basic and in C# and can be found in
Protected Configuration Provider Implementation Example.
Building the Example Provider
You must encrypt Web.config file sections using the Aspnet_regiis.exe tool. Decryption can be performed either explicitly using
the Aspnet_regiis.exe tool or automatically by ASP.NET at run time. Therefore, you must make the example provider type
available to both the Aspnet_regiis.exe tool and to ASP.NET. This is most easily accomplished by compiling the provider with a
strong name and placing it in the global assembly cache (GAC).
Note
The Strong Name tool (Sn.exe) and the Global Assembly Cache tool (Gacutil.exe) are available as part of the .NET Framework
SDK installation. For more information, see Strong Name Tool (Sn.exe) and Global Assembly Cache Tool (Gacutil.exe).

To build the example provider


1. At the Windows command line, run the following command:

Sn.exe -k keys.snk

This generates a strong-name key pair.


Note
If you cannot execute the command, you must add the .NET Framework path to the PATH variable before running the c
ommand. In Windows, right-click My Computer, click Properties, click the Advanced tab, and then click the Environ
ment Variables button. In the System variables list, double-click the Path variable. In the Variable value text box, a
dd a semicolon (;) to the end of the existing values in the text box, and then type the path of your .NET Framework instal
lation. The .NET Framework is usually installed in the Windows installation folder at \Microsoft.NET\Framework\version
Number.

2. Create a program file named TripleDESProtectedConfigurationProvider (with the file name extension .vb or .cs,
depending on what programming language you are using), and copy into it the example provider code from
Protected Configuration Provider Implementation Example.
3. Compile the provider example code and assign to the resulting assembly the strong-name key using the following
command:
VB
vbc /out:TripleDESProtectedConfigurationProvider.dll /t:library TripleDESProtectedConf
igurationProvider.vb /r:System.Configuration.dll /keyfile:keys.snk

C#
csc /out:TripleDESProtectedConfigurationProvider.dll /t:library TripleDESProtectedConf
igurationProvider.cs /r:System.Configuration.dll /keyfile:keys.snk

4. Install the assembly in the global assembly cache using the following command-line command:
gacutil.exe -i TripleDESProtectedConfigurationProvider.dll

Note
If you need to remove the assembly from the GAC, you can use the Gacutil.exe tool with the following command:

Creating and Storing an Encryption Key


The example TripleDES protected configuration provider encrypts and decrypts configuration sections using an encryption key
stored in a text file as a hexadecimal string. You create the key file using code included in the example provider. In the key file,
the key is stored on the first line of the file and the vector (IV) on the second, as shown in the following example:

EBBCB17E444EBB9EA2EA7EE3E0FD9E108C6E75A90101D017
8C979426981FD2A6

After creating the key file, you should store it in a secure location on the server, and then restrict file access to the key file to the
ASP.NET application identity, to the SYSTEM account, and to administrators. This protects the key from being accessed by an
attacker and rendering your encryption useless.
To create an encryption key
1. Create a console application named CreateKey.
2. Copy the following code as the application's main module.
VB
Imports System
Imports Samples.AspNet.ProtectedConfiguration

Public Class CreateKey


Public Shared Sub Main(args() As String)
Dim filePath As String = args(0)
Dim provider As TripleDESProtectedConfigurationProvider = _
New TripleDESProtectedConfigurationProvider()
provider.CreateKey(filePath)
Console.WriteLine("New TripleDES key written to '{0}'", filePath)
End Sub
End Class

C#
using System;
using Samples.AspNet.ProtectedConfiguration;
public class CreateKey
{
public static void Main(string[] args)
{
string filePath = args[0];
TripleDESProtectedConfigurationProvider provider =
new TripleDESProtectedConfigurationProvider();
provider.CreateKey(filePath);
Console.WriteLine("New TripleDES Key written to '{0}'", filePath);
}
}

The example protected configuration provider includes a public CreateKey method that takes a file path as input,
generates a new key, and writes the new key to the specified file. The code in the console application creates an instance
of the protected configuration provider and calls its CreateKey method. The code takes a file path as a command line
argument and creates a new key file in the specified location.
3. At the Windows command line, run the console application using syntax such as the following:

CreateKey "c:\WebSites\SampleApplication\App_Data\Keys.txt"

Using the Example Provider in an ASP.NET Application


After compiling the provider and creating an encryption key, you can configure an ASP.NET application to use the provider.
To use the example provider in an ASP.NET application
1. Open your Web site's Web.config file. If the application does not have a Web.config file, create a text file named
Web.config in the Web site's root folder and add the following elements:

<?xml version="1.0"?>
<configuration>
<system.web>

</system.web>
</configuration>

2. Within the configuration section (as a peer of the system.web element), add the following highlighted elements :

<configuration>
<configProtectedData>
<providers>
<add name="TripleDESProvider"
type="Samples.AspNet.ProtectedConfiguration.TripleDESProtectedConfigurationProvi
der,
TripleDESProtectedConfigurationProvider,
Version=0.0.0.0, CultureInfo=neutral,
PublicKeyToken=a5a9eb4fc5306403,
processorArchitecture=MSIL"
keyFilePath="c:\WebSites\SampleApplication\App_Data\Keys.txt" />
</providers>
</configProtectedData>
</configuration>

Note
Change the value of the keyFilePath attribute to match the location where you stored the key file you created earlier.

3. Within the configuration section, add a <connectionStrings> section and one or more connection strings.
The following example shows a connectionStrings section containing a connection string for the sample SQL Server
Northwind database. The SQL Server instance name is assumed to be SampleSQLServer.

<connectionStrings>
<add name="NorthwindConnectionString"
connectionString="Data Source=SampleSQLServer;Initial Catalog=Northwind;Persist Se
curity Info=True;" Integrated Security=SSPI;"
providerName="System.Data.SqlClient" />
</connectionStrings>

Note
Change the connectionString value to include connection information for the SQL Server database you want to use.

4. Save the file and close it.


5. At the Windows command line, run the following command to encrypt the connectionStrings section of the Web.config
file:

aspnet_regiis.exe -pe "connectionStrings" -app "/SampleApplication" -prov "TripleDESPr


ovider"

Note
For SampleApplication, substitute the name of the Web application where you want to test the encryption.

6. Open the Web.config file and note that the connection string has been encrypted.
7. In the Web application, use the encrypted connection string.
For example, add a SqlDataSource control and set its ConnectionString property to "NorthwindConnectionString," as
shown in the following example:

<asp:SqlDataSource ID="SqlDataSource1"
runat="server"
ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
SelectCommand="SELECT ProductName FROM Products">
</asp:SqlDataSource>

8. Bind a control such as a GridView control to the SqlDataSource control.


9. Run the page.
Note that the data is displayed as you expect. ASP.NET has decrypted the connection string at run time before using it to
connect to the Northwind database.

See Also
Concepts
Implementing a Protected Configuration Provider
Other Resources
Encrypting Configuration Information Using Protected Configuration
ASP.NET

Protected Configuration Provider Implementation Example


The following code example shows how to implement a protected configuration provider. For details about how to build this
provider and use it in an ASP.NET application, see How to: Build and Run the Protected Configuration Provider Example.
Example
VB
Imports System
Imports System.Xml
Imports System.Security.Cryptography
Imports System.IO
Imports System.Text
Imports System.Configuration.Provider
Imports System.Collections.Specialized
Imports System.Configuration

Namespace Samples.AspNet.ProtectedConfiguration
Public Class TripleDESProtectedConfigurationProvider
Inherits ProtectedConfigurationProvider

Private des As TripleDESCryptoServiceProvider = New TripleDESCryptoServiceProvider()

Private pKeyFilePath As String


Private pName As String

Public ReadOnly Property KeyFilePath As String


Get
Return pKeyFilePath
End Get
End Property

'
' ProviderBase.Name
'

Public Overrides ReadOnly Property Name As String


Get
Return pName
End Get
End Property

'
' ProviderBase.Initialize
'
Public Overrides Sub Initialize(name As String, config As NameValueCollection)
pName = name
pKeyFilePath = config("keyFilePath")
ReadKey(KeyFilePath)
End Sub

'
' ProtectedConfigurationProvider.Encrypt
'
Public Overrides Function Encrypt(node As XmlNode ) As XmlNode
Dim encryptedData As String = EncryptString(node.OuterXml)

Dim xmlDoc As XmlDocument = New XmlDocument()


xmlDoc.PreserveWhitespace = True
xmlDoc.LoadXml("<EncryptedData>" & encryptedData & "</EncryptedData>")
Return xmlDoc.DocumentElement
End Function

'
' ProtectedConfigurationProvider.Decrypt
'
Public Overrides Function Decrypt(encryptedNode As XmlNode) As XmlNode
Dim decryptedData As String = DecryptString(encryptedNode.InnerText)

Dim xmlDoc As XmlDocument = New XmlDocument()


xmlDoc.PreserveWhitespace = True
xmlDoc.LoadXml(decryptedData)

Return xmlDoc.DocumentElement
End Function

'
' EncryptString
' Encrypts a configuration section and returns the encrypted
' XML as a string.
'

Private Function EncryptString(encryptValue As String) As String


Dim valBytes() As Byte = Encoding.Unicode.GetBytes(encryptValue)

Dim transform As ICryptoTransform = des.CreateEncryptor()

Dim ms As MemoryStream = New MemoryStream()


Dim cs As CryptoStream = New CryptoStream(ms, transform, CryptoStreamMode.Write)
cs.Write(valBytes, 0, valBytes.Length)
cs.FlushFinalBlock()
Dim returnBytes() As Byte = ms.ToArray()
cs.Close()

Return Convert.ToBase64String(returnBytes)
End Function

'
' DecryptString
' Decrypts an encrypted configuration section and returns the
' unencrypted XML as a string.
'

Private Function DecryptString(encryptedValue As String) As String


Dim valBytes() As Byte = Convert.FromBase64String(encryptedValue)
Dim transform As ICryptoTransform = des.CreateDecryptor()

Dim ms As MemoryStream = New MemoryStream()


Dim cs As CryptoStream = New CryptoStream(ms, transform, CryptoStreamMode.Write)
cs.Write(valBytes, 0, valBytes.Length)
cs.FlushFinalBlock()
Dim returnBytes() As Byte = ms.ToArray()
cs.Close()
Return Encoding.Unicode.GetString(returnBytes)
End Function

'
' CreateKey
' Generates a New TripleDES key and vector and writes them
' to the supplied file path.
'

Public Sub CreateKey(filePath As String)


des.GenerateKey()
des.GenerateIV()

Dim sw As StreamWriter = New StreamWriter(filePath, false)


sw.WriteLine(ByteToHex(des.Key))
sw.WriteLine(ByteToHex(des.IV))
sw.Close()
End Sub

'
' ReadKey
' Reads in the TripleDES key and vector from the supplied
' file path and sets the Key and IV properties of the
' TripleDESCryptoServiceProvider.
'

Private Sub ReadKey(filePath As String)


Dim sr As StreamReader = New StreamReader(filePath)
Dim keyValue As String = sr.ReadLine()
Dim ivValue As String = sr.ReadLine()
des.Key = HexToByte(keyValue)
des.IV = HexToByte(ivValue)
End Sub

'
' ByteToHex
' Converts a byte array to a hexadecimal string.
'

Private Function ByteToHex(byteArray As Byte()) As String


Dim outString As String = ""

For Each b As Byte In byteArray


outString &= b.ToString("X2")
Next
Return outString
End Function

'
' HexToByte
' Converts a hexadecimal string to a byte array.
'

Private Function HexToByte(hexString As String) As Byte()


Dim returnBytes() As Byte = New Byte(CInt((hexString.Length / 2) - 1)) {}
For i As Integer= 0 To returnBytes.Length - 1
returnBytes(i) = Convert.ToByte(hexString.Substring(i*2, 2), 16)
Next

Return returnBytes
End Function

End Class
End Namespace

C#
using System;
using System.Xml;
using System.Security.Cryptography;
using System.IO;
using System.Text;
using System.Configuration.Provider;
using System.Collections.Specialized;
using System.Configuration;

namespace Samples.AspNet.ProtectedConfiguration
{

public class TripleDESProtectedConfigurationProvider : ProtectedConfigurationProvider


{

private TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();

private string pKeyFilePath;


private string pName;
public string KeyFilePath
{
get { return pKeyFilePath; }
}

//
// ProviderBase.Name
//

public override string Name


{
get { return pName; }
}

//
// ProviderBase.Initialize
//

public override void Initialize(string name, NameValueCollection config)


{
pName = name;
pKeyFilePath = config["keyFilePath"];
ReadKey(KeyFilePath);
}

//
// ProtectedConfigurationProvider.Encrypt
//
public override XmlNode Encrypt(XmlNode node)
{
string encryptedData = EncryptString(node.OuterXml);

XmlDocument xmlDoc = new XmlDocument();


xmlDoc.PreserveWhitespace = true;
xmlDoc.LoadXml("<EncryptedData>" + encryptedData + "</EncryptedData>");

return xmlDoc.DocumentElement;
}

//
// ProtectedConfigurationProvider.Decrypt
//
public override XmlNode Decrypt(XmlNode encryptedNode)
{
string decryptedData = DecryptString(encryptedNode.InnerText);

XmlDocument xmlDoc = new XmlDocument();


xmlDoc.PreserveWhitespace = true;
xmlDoc.LoadXml(decryptedData);

return xmlDoc.DocumentElement;
}

//
// EncryptString
// Encrypts a configuration section and returns the encrypted
// XML as a string.
//

private string EncryptString(string encryptValue)


{
byte[] valBytes = Encoding.Unicode.GetBytes(encryptValue);

ICryptoTransform transform = des.CreateEncryptor();

MemoryStream ms = new MemoryStream();


CryptoStream cs = new CryptoStream(ms, transform, CryptoStreamMode.Write);
cs.Write(valBytes, 0, valBytes.Length);
cs.FlushFinalBlock();
byte[] returnBytes = ms.ToArray();
cs.Close();

return Convert.ToBase64String(returnBytes);
}

//
// DecryptString
// Decrypts an encrypted configuration section and returns the
// unencrypted XML as a string.
//

private string DecryptString(string encryptedValue)


{
byte[] valBytes = Convert.FromBase64String(encryptedValue);

ICryptoTransform transform = des.CreateDecryptor();

MemoryStream ms = new MemoryStream();


CryptoStream cs = new CryptoStream(ms, transform, CryptoStreamMode.Write);
cs.Write(valBytes, 0, valBytes.Length);
cs.FlushFinalBlock();
byte[] returnBytes = ms.ToArray();
cs.Close();

return Encoding.Unicode.GetString(returnBytes);
}

//
// CreateKey
// Generates a new TripleDES key and vector and writes them
// to the supplied file path.
//

public void CreateKey(string filePath)


{
des.GenerateKey();
des.GenerateIV();
StreamWriter sw = new StreamWriter(filePath, false);
sw.WriteLine(ByteToHex(des.Key));
sw.WriteLine(ByteToHex(des.IV));
sw.Close();
}

//
// ReadKey
// Reads in the TripleDES key and vector from the supplied
// file path and sets the Key and IV properties of the
// TripleDESCryptoServiceProvider.
//

private void ReadKey(string filePath)


{
StreamReader sr = new StreamReader(filePath);
string keyValue = sr.ReadLine();
string ivValue = sr.ReadLine();
des.Key = HexToByte(keyValue);
des.IV = HexToByte(ivValue);
}

//
// ByteToHex
// Converts a byte array to a hexadecimal string.
//

private string ByteToHex(byte[] byteArray)


{
string outString = "";

foreach (Byte b in byteArray)


outString += b.ToString("X2");

return outString;
}

//
// HexToByte
// Converts a hexadecimal string to a byte array.
//

private byte[] HexToByte(string hexString)


{
byte[] returnBytes = new byte[hexString.Length / 2];
for (int i = 0; i < returnBytes.Length; i++)
returnBytes[i] = Convert.ToByte(hexString.Substring(i*2, 2), 16);
return returnBytes;
}

}
}

See Also
Tasks
How to: Build and Run the Protected Configuration Provider Example
Concepts
Implementing a Protected Configuration Provider
Other Resources
Encrypting Configuration Information Using Protected Configuration
Visual Web Developer

Walkthrough Topics — ASP.NET Web Site Security (Visual


Studio)
The following walkthrough topics demonstrate how to help protect your ASP.NET Web sites against malicious users.
Walkthrough Topics
Walkthrough: Creating a Web Site with Membership and User Login (Visual Studio)
Walkthrough: Creating a Web Site with Membership and User Login (Visual Studio)
Walkthrough: Managing Web Site Users with Roles
Walkthrough: Encrypting Configuration Information Using Protected Configuration
Walkthrough: Creating and Exporting an RSA Key Container

See Also
Other Resources
ASP.NET Web Site Security (Visual Studio)
Visual Web Developer

How-to Topics — ASP.NET Web Site Security (Visual Studio)


The following procedures describe how to help protect your ASP.NET Web sites against malicious users.
How-to Topics
How to: Protect Against Script Exploits in a Web Application by Applying HTML Encoding to Strings
How to: Display Safe Error Messages
How to: Access SQL Server Using Windows Integrated Security
How to: Access SQL Server Using a Mapped Windows Domain User
How to: Access SQL Server as a Local User
How to: Access SQL Server Using Predetermined Credentials
How to: Implement Simple Forms Authentication
How to: Sample Membership Provider Implementation
How to: Sample Role-Provider Implementation
How to: Build and Run the Protected Configuration Provider Example
See Also
Other Resources
ASP.NET Web Site Security (Visual Studio)
Visual Web Developer

ASP.NET Debugging and Troubleshooting (Visual Studio)


ASP.NET includes features to help you diagnose problems that might arise in your Web application. These include:
A debugger that you can use to step through a page or component as it is running.
Techniques for avoiding errors and capturing information when they do occur.
Ways to trace page requests and gather information about each step of page processing.
Ways to raise and respond to health monitoring events, which can log information about performance and error
conditions.
The topics in this section describe each of these troubleshooting features.
In This Section
Debugging ASP.NET Web Pages
Provides information about using the Visual Studio debugger to step through ASP.NET code.
Tracing in ASP.NET Web Pages (Visual Studio)
Provides information about displaying diagnostic information about page processing.
Error Handling in ASP.NET Pages and Applications
Provides information and guidelines about ways to capture and handle error conditions.
ASP.NET Health Monitoring
Provides links to topics on how to monitor your application's health and be notified of problems.
Related Sections
Guided Tour of Creating Web Sites in Visual Web Developer
Provides links to tutorials on all aspects of creating ASP.NET Web sites and ASP.NET Web pages.
Visual Web Developer

Debugging ASP.NET Web Pages


The topics in this section provide information about using the debugger with Web pages and code in your Web site.
In This Section
ASP.NET Debugging Overview
Debugging Web Pages Overview
Walkthrough: Debugging Web Pages in Visual Web Developer
See Also
Other Resources
ASP.NET Debugging and Troubleshooting (Visual Studio)
Debugging in Visual Studio
Debugging ASP.NET Web Applications
ASP.NET

ASP.NET Debugging Overview


Application code can contain various types of errors, or bugs. Most syntax errors are caught during compilation. However,
other types of errors require that you debug your code — that is, that you examine the code while it is running to validate that
the execution path and data is as it should be. For more information, see Debugging and Profiling Applications.
The .NET Framework SDK includes a tool called Visual Debugger that allows you to examine an application while it is running.
This tool is located in %ProgramFiles%\Microsoft Visual Studio 8\SDK\v2.0\GuiDebug\DbgCLR.exe. Using the debugger, you
can see exactly how your application is working by stepping through each statement as it executes and by viewing the data in
each variable. To use Visual Debugger, open it and then attach it to the process that is running the pages of your ASP.NET
application. In Internet Information Services (IIS) versions 5.0 and 5.1, and in IIS 6.0 running in IIS 5.0 application mode, the
process to which you attach the debugger is the ASP.NET worker process (Aspnet_wp.exe). In IIS 6.0 running in worker process
isolation mode, the process that you attach to is the thread pool process (W3wp.exe). When the debugger is attached to a
process, you can view everything going on during that process, and the debugger maps the instructions being executed in the
process back to your original code so that you can see each line of code being executed.
Visual Debugger
Visual Debugger allows you to examine code while it is running and includes features that help you debug applications,
including the following:
Breakpoints Breakpoints are places in the code where the debugger will stop the application, allow you to view the
current data state of the application, and then step through each line of code. For information, see
Debugging Basics: Breakpoints.
Stepping Once you have stopped at a breakpoint, you can run the code line by line (known as stepping through the
code). Visual Debugger includes a number of features to help you step through your code, such as iterators that allow
you to specify how many times to step through a loop before stopping again. For more information, see
Code Stepping Overview.
Data Viewing Visual Debugger gives you many different options for viewing and tracking data while the application is
running. The debugger allows you to modify the data while the application is stopped in break mode and then continue
to run the application with the modified data. For more information, see Viewing Data in the Debugger.
Note
The Edit and Continue feature of Visual Studio 2005 is not available for Web applications.

For more information, see Using the Debugger with Web Pages.
Configuring ASP.NET Web Applications for Debugging
To enable debugging for an ASP.NET Web application, you must configure the application to compile into a debug build. A
debug build includes information that the debugger needs so that it can step through your code and display the contents of
variables. You configure your Web application for debug builds in the Compilation section of your application's Web.config file.
For more information, see compilation Element (ASP.NET Settings Schema). Alternatively, if you want to debug only single
pages, you can add debug=true to the @ Page directive on the pages that you wish to debug. For more information, see
How to: Enable Debugging for ASP.NET Applications.
Note
An application compiled into a debug build will perform considerably more slowly than if it is compiled into a retail build. Be
sure you have debug mode turned off before you deploy your application. Additionally, in debug mode, more information is
exposed in the stack when an error occurs and can be a potential security issue.

Local and Remote Debugging


If you are running a Web server locally, such as IIS, you can debug applications running locally on your computer so that you
can view your pages in a browser.
If you cannot run a page locally, because you cannot run a Web server or because the application is not available to you locally,
you can debug an application running on another server. In order to debug remotely, you must install the Visual Studio remote
debugging components on the remote server. For more information, see How to: Set Up Remote Debugging.
Permissions for Debugging
Debugging a process requires more privileges than running it. Therefore, in addition to configuring your application for
debugging, you must also ensure that you have adequate permissions to attach to a process in order to debug it. Users have
the permission to debug processes running under their own user local identity, but they cannot debug other user's processes.
Administrators can debug any process.
To debug on a remote server, you need administrator privileges on the computer where the process to be debugged runs. For
more information, see How to: Debug Web Applications on a Remote Server.
Client-Side Script Debugging
In addition to server-side application debugging, Visual Debugger allows you to debug client script written in ECMAScript
(JavaScript) or VBScript. Client-script debugging can be especially useful when you have Web server controls that use client-
side script. For more information, see Client-Side Script Debugging Roadmap and
How to: Enable Client-Side Script Debugging.
See Also
Tasks
How to: Debug Web Applications on a Remote Server
How to: Enable Debugging for ASP.NET Applications
Debugging ASP.NET Web Applications During Development
Reference
What's New in the Visual Studio 2005 Debugger
Concepts
Debugging Basics: Breakpoints
Other Resources
Debugging ASP.NET Web Applications
The Microsoft .NET Framework SDK Debugger
Visual Web Developer

Debugging Web Pages Overview


The ASP.NET page framework provides extensive support for debugging Web applications. However, because Web
applications are distributed, there are some special issues associated with debugging them.
In general, you debug Web applications the same way you do other types of Visual Studio applications. You can set
breakpoints, start the debugger, break into code, examine variables, and perform all the functions associated with the Visual
Studio debugger. For details, see Debugger Roadmap. In addition, the ASP.NET page framework provides a trace mode that
enables you to insert instrumentation messages into your forms. For details, see
Walkthrough: Using Tracing in Visual Web Developer to Help Find Web Page Errors and
Walkthrough: Integrating ASP.NET Tracing with System.Diagnostics Tracing.
Debugger Configuration
Web application debugging requires certain components on the computer where debugging is to happen and requires that
you have adequate permissions.
Local Computer Configuration
If you are running Web applications locally on your computer—that is, the Web server is on your computer—then the
computer has the correct components automatically.
You must still make sure that you have adequate permissions to debug. Users have the permission to debug processes
running under their user identity, but cannot debug other user's processes. Administrators can debug any process.
Remote Computer Configuration
If the Web server is on another computer (a remote server), you must ensure that the computer is configured properly. This
involves:
Making sure that DCOM is installed on both your computer and on the server. Windows 2000 and Windows Server 2003
normally have DCOM installed already, so there is usually no action required on your part.
Installing Visual Studio server-side components on the remote computer. You can do this by running the Visual Studio
installation process on the remote computer and selecting the option for server components.
Ensuring that any debugger users have permissions to attach to a Web server process. This means that server processes
must either run as the user (impersonation) or that users who want to debug must have administrative privileges on the
Web server. (Giving users administrative privileges on the server might not be in keeping with your security policies.)
You can control ASP.NET impersonation using the identity element of the Web.config file for your application. For
details, see <identity> Element.
For details about configuring for remote debugging, see Debugging Web Applications on a Remote Server.
Whether you are running locally or on a remote computer, you must be sure that debugging is enabled for your Web
application specifically. This is done in the compilation Element (ASP.NET Settings Schema) element of the Web.config file that
is part of your Web application project. This setting instructs the compiler to insert debugging symbols into the application's
compiled code so that you can use the debugger with it. You can enable debugging using the Web Site Administration Tool.
For details, see Walkthrough: Debugging Web Pages in Visual Web Developer.
Debugging Client Script
Client script runs within the browser, separately from the code in your Web application, which runs on the server. You can use
the Visual Studio debugger to debug client script. The debugger does not enable you to follow execution from server code to
client script; however, it does support most other debugging functionality for client script.
You can debug client script in various ways. From within Visual Studio, you can use debugger commands to attach to the
browser process (Iexplore.exe) and break into the script. From there, you can use the debugger as you would for any other
code.
For more information see Client-Side Script Debugging Roadmap and How to: Enable Client-Side Script Debugging.
See Also
Other Resources
Debugging Web Applications
Debugging in Visual Studio
Visual Web Developer

Walkthrough: Debugging Web Pages in Visual Web Developer


Visual Web Developer provides you with tools to help track down errors in your ASP.NET Web pages. In this walkthrough, you
will work with the debugger, which allows you to step through the page's code line by line and examine the values of variables.
In the walkthrough, you will create a Web page that contains a simple calculator that squares a number. After creating the page
(which will include a deliberate error), you will use the debugger to examine the page as it is running.
Tasks illustrated in this walkthrough include:
Setting breakpoints.
Invoking debugger from a Web Forms page in a file system Web site.
Prerequisites
In order to complete this walkthrough, you will need:
Visual Web Developer and the .NET Framework.
You should also have a general understanding of working in Visual Web Developer. For an introduction to Visual Web
Developer, see Walkthrough: Creating a Basic Web Page in Visual Web Developer.
Creating the Web Site and Page
In the first part of the walkthrough, you will create a page that you can debug.
If you have already created a Web site in Visual Web Developer (for example, by working with the topic
Walkthrough: Creating a Basic Web Page in Visual Web Developer ), you can use that Web site and skip to "Adding Controls to
Debug" later in this walkthrough. Otherwise, create a new Web site and page by following these steps.
To create a file system Web site
1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the Location box, click File System and then type the name of the folder where you want to keep the pages of your
Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click the programming language that you prefer to work in.
The programming language you choose will be the default for your Web site. However, you can use multiple languages
in the same Web application by creating pages and components in different programming languages. For information on
creating components using different languages, see Shared Code Folders in ASP.NET Web Sites.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Creating a Page to Debug
You will begin by creating a new page. For this walkthrough, it is important that you create a new page as specified in the
following procedure.
To add a page to the Web site
1. Close the Default.aspx page.
2. In Solution Explorer, right-click the name of your Web site (for example, C:\WebSite) and choose Add New Item.
3. Under Visual Studio installed templates, choose Web Form.
4. In the Name box, type DebugPage.aspx.
5. From the Language list, choose the programming language you prefer to use.
6. Be sure that the Place code in separate file check box is cleared.
In this walkthrough, you are creating a single-file page with the code and HTML in the same page. The code for ASP.NET
pages can be located either in the page or in a separate class file. To learn more about keeping the code in a separate file,
see Walkthrough: Creating a Basic Web Page with Code Separation in Visual Web Developer .
7. Click Add.
Visual Web Developer creates the new page and opens it in Source view.
You can now add some controls to the page and then add code. The code will be simple, but enough to allow you to add
breakpoints later.
To add controls and code for debugging
1. Switch to Design view, and then from the Standard folder of the Toolbox, drag the following controls onto the page
and set their properties as indicated:
Control Properties
Label ID: CaptionLabel
Text: (empty)

TextBox ID: NumberTextBox


Text: (empty)

Button ID: SquareButton


Text: Square

Label ID: ResultLabel


Text: (empty)
Note
For this walkthrough, the layout of the page is not important.

2. Double-click the Button control to create a Click handler for it.


3. Add logic to the Click handler to call a function called Square to square the number entered by the user. The handler
might look like the following example.
Note
The code example deliberately does not include error checking.

VB
Sub SquareButton_Click(ByVal sender As Object, _
ByVal e As System.EventArgs)
Dim number As Integer
Dim result As Integer
number = CInt(NumberTextBox.Text)
result = Square(number)
ResultLabel.Text = CStr(number) & " squared is " & CStr(result)
End Sub

C#
protected void SquareButton_Click(object sender, System.EventArgs e)
{
int number, result;
number = System.Convert.ToInt32(NumberTextBox.Text);
result = Square(number);
ResultLabel.Text = NumberTextBox.Text +
" squared is " + result.ToString();
}

4. Create the function that squares the number. Include a bug in the code to add the number to itself instead of multiplying
it. The code might look like the following example.
VB
Function Square(number As Integer) As Integer
Square = number + number
End Function

C#
int Square(int number )
{
int Square;
Square = number + number;
return Square;
}

You can also add code to the page that will change the text of the label depending on whether this is the first time the page is
running.
To change the caption Label control
1. In Design view, double-click the design surface (not a control) to create a Page_Load event handler.
2. Set the text of the Caption Label control to Enter a number: if this is the first time the page is running, or Enter
another number: otherwise. The handler will look like the following code example.
VB
Sub Page_Load(ByVal sender As Object, ByVal e as System.EventArgs)
If Page.IsPostBack = False Then
CaptionLabel.Text = "Enter a number: "
Else
CaptionLabel.Text = "Enter another number: "
End If
End Sub

C#
if(Page.IsPostBack == false)
{
CaptionLabel.Text = "Enter a number: ";
}
else {
CaptionLabel.Text = "Enter another number: " ;
}

Testing the Page


To make sure the page is working, run it in its current state.
To run the page
1. Save the page.
2. Press CTRL+F5 to run the page.
3. Enter a number (other than 2) and press the Square button.
Note that the result is incorrect, because there is a bug in the program.
4. Close the browser.
Debugging the Page
In this part of the walkthrough, you will use the debugger to examine the page code line by line as it is running, add
breakpoints to the code, and then run the page in Debug mode.
You will start by setting breakpoints in your code. A breakpoint is a line in your code where execution stops and the debugger
is invoked.
To set breakpoints
1. Switch to Source view.
2. Right-click the following line, choose Breakpoint, and then choose Insert Breakpoint.
Note
You can toggle breakpoints by pressing F9.

VB
If Page.IsPostBack = False Then

C#
if(Page.IsPostBack == false)

3. Set another breakpoint on the following line of the SquareButton_Click handler:


VB
result = Square(number)

C#
result = Square(number);

Note
You cannot set a breakpoint on a statement that declares a variable.

With at least one breakpoint set, you are ready to run the debugger.
To run the debugger
1. From the Debug menu, choose Start Debugging (or press F5) to run the page in debug mode.
If you have never run the debugger before, your application probably is not configured to support debugging. By default,
debugging is turned off in applications both for performance (pages run more slowly in the debugger) and for security
reasons. Visual Web Developer displays a message telling you what it must do to enabled debugging.
The switch to enable debugging is stored as a setting in the Web.config file, which maintains various site-specific
configuration options. If the Web.config file does not exist, Visual Web Developer will both create the file and make the
appropriate debugger setting.
If the Web.config file already exists but debugging is not enabled, you will see a slightly different message telling you that
Visual Web Developer will modify the Web.config file.
2. If you see the message telling you that debugging has not been enabled, click OK to enable debugging.
In Visual Web Developer, the designer changes to debug mode displaying the code for your page and some debugger
windows.
The debugger runs your page line by line. When the debugger gets to the line with the breakpoint, it stops and highlights
the line.
Because the breakpoint is in the Page_Load handler, the page has not finished processing yet. The browser is open, but
the page is not yet displayed.
3. In the Debug menu, click Windows, click Watch, and then click Watch 1.
Note
If you are using Visual Web Developer Express Edition, the debugger offers only a single Watch window.

This opens a Watch window, where you can specify the values you want to track.
4. In the editor, right-click the IsPostBack portion of the Page.IsPostBack expression, and then click Add Watch.
This adds the expression to the Watch window and displays the current value of the property (false) is displayed in the
Value column. If you prefer, you can type the name of a variable or property in the Name column of the Watch window.
5. From the Debug menu, choose Continue to continue execution, or press F5.
The Continue command tells the debugger to proceed until it gets to the next breakpoint. The Page_Load event handler
finishes processing and the page is displayed in the browser.
6. Enter the value 2 into the text box and click the Square button.
The debugger is displayed again, with the breakpoint on the line in the Page_Load handler. This time, the Watch
window shows you that the value of Page.IsPostBack is true.
7. Press F5 again to continue.
The debugger processes the Page_Load handler and enters the SquareButton_Click handler, where it stops on the
second breakpoint you set.
8. In the Debug menu, click Windows and then click Locals.
This opens the Locals window, which displays the values of all variables and objects that are in scope at the current line
being executed. The Locals window provides an alternative way for you to view these values, with the advantage that
you do not have to explicitly set a watch on the elements, but with the disadvantage that the window might contain more
information than you want to see at once.
In the Locals window, you see that the value of number is 2 and the value of result is 0.
Note
You can also see the value of any variable in the program by holding the mouse pointer over it.

9. In the Value column of the Locals window, right-click the line for the number variable and select Edit value. Edit the
value of the number variable and change it to 5.
The value 2 for the variable number is not a good test of the program, because adding and squaring 2 both result in 4.
Therefore, while the program is running, you can change the value of this variable.
10. From the Debug menu, choose Step Into to step into the Square function, or press F11.
The Step Into command causes the debugger to execute a line and then stop again.
11. Continue stepping by pressing F11 until you reach the following line of code.
VB
ResultLabel.Text = CStr(number) & " squared is " & CStr(result)

C#
ResultLabel.Text = NumberTextBox.Text +
" squared is " + result.ToString();

The debugger walks through your code line by line. When the debugger executes the Square function, you can use the
Locals window to check the data passed to the function (number) and the return value of the function (Square).
12. In the Debug menu, click Windows and then Immediate.
The Immediate window allows you to execute commands. You can use the window to evaluate expressions (for
example, to get the value of a property).
13. In the Immediate window, type the following expression and press Enter.

? NumberTextBox.Text

The question mark (?) is an operator in the Immediate window that evaluates the expression following it. In this
example, you are evaluating the Text property of the NumberTextBox control on the page. You can evaluate any variable,
object property, or expression that combine these, using the same syntax that you would use in code.
14. In the Immediate window, type the following and press Enter:

NumberTextBox.Text = "5"

In addition to evaluating expressions, the Immediate window allows you to change variables or properties
15. Press F5 to continue running the program.
When the page appears, it displays the result of passing 5 to the Square function. In addition, the text in the text box has
been changed to 5.
The result you see — 10 — is not correct, since 10 is not the square of 5. You can now fix the bug.
To fix the bug and test again
1. Switch from the browser to Visual Web Developer.
Note
Do not close the browser window.

2. In the Square function, change the "+" operator to the "*" operator.
Because the code is not currently running (the page has finished processing), you are in edit mode and can make
permanent changes.
3. Press CTRL+S to save the page.
4. From the Debug menu, choose Delete All Breakpoints so that the page will not stop each time you run it.
Note
You can also clear breakpoints by pressing CTRL+SHIFT+F9.

5. Switch to the browser window.


6. Enter 5 in the text box and click the button.
This time, when you run the page and enter a value, it is squared correctly. The temporary changes you made earlier,
such as changing the Text property of the NumberTextBox control, have not been persisted, because they applied only
when the page was running the last time.
7. Close the browser to stop the debugger.
Next Steps
The debugger includes additional features to help you work with your code. In addition, you might want to learn about
techniques for handling error conditions and ways in which you can monitor page processing at run time. For example, you
might want to explore tracing. For details, see
Walkthrough: Using Tracing in Visual Web Developer to Help Find Web Page Errors.
See Also
Other Resources
Debugging in Visual Studio
Visual Web Developer

Tracing in ASP.NET Web Pages (Visual Studio)


ASP.NET allows you to view diagnostic information about a request for an ASP.NET page. Tracing also allows you to write
debug statements directly in your code without having to remove them from your application when it is deployed to
production servers. You can write variables or structures in a page, assert whether a condition is met, or simply trace through
the execution path of your page or application. You can view tracing information appended to the end of a page, in a separate
trace viewer, or both ways.
The topics in this section describe how tracing works, how to manage tracing, and how to integrate ASP.NET tracing with .NET
system diagnostics.
In This Section
ASP.NET Tracing Overview
Walkthrough: Using Tracing in Visual Web Developer to Help Find Web Page Errors
How to: Enable Tracing for an ASP.NET Page
Reading ASP.NET Trace Information
Writing Custom ASP.NET Trace Messages
Application-Level ASP.NET Tracing Overview
Walkthrough Topics — Tracing in Web Pages
How-to Topics — Tracing in Web Pages
See Also
Other Resources
ASP.NET Debugging and Troubleshooting (Visual Studio)
ASP.NET

ASP.NET Tracing Overview


ASP.NET tracing enables you to view diagnostic information about a single request for an ASP.NET page. Tracing also enables
you to write debug statements directly in your code without having to remove them from your application when it is deployed
to production servers. You can write variables or structures in a page or simply trace through the execution path of your page
or application.
Enabling Tracing
In order for tracing information to be gathered and displayed, you must enable tracing for the page or application. When you
enable tracing, diagnostic information and custom tracing messages are appended to the output of the page and sent to the
requesting browser. Optionally, you can view this information from a separate trace viewer (Trace.axd) that displays trace
information for every page in a given application. Tracing information can help you to clarify errors or undesired results as
ASP.NET processes a page request.
Trace statements are processed and displayed only when tracing is enabled. You can control whether tracing is displayed to a
page, to the trace viewer, or both.
ASP.NET Tracing and Diagnostics Tracing
ASP.NET tracing writes messages that are displayed on ASP.NET Web pages and the ASP.NET Trace viewer (Trace.axd). In
contrast, the Trace class is used to trace write messages to the standard .NET Framework trace output (typically a console
window). To make it easier to track how your Web forms interact with business objects and other components, you can
integrate ASP.NET tracing output with System.Diagnostics tracing to route all tracing messages to one of these outputs.
Common scenarios that use both ASP.NET tracing and Trace include Web pages that use middle tier business objects to
interact with data and business rules, and pages that use enterprise services such as transactions and queues. In these
situations the business and enterprise components play key parts in the successful execution of the page, and monitoring their
execution flow across the multiple tiers of your application using a single tracing output is desirable.
See Also
Tasks
How to: Enable Tracing for an ASP.NET Page
How to: Enable Tracing for an ASP.NET Application
How to: View ASP.NET Trace Information with the Trace Viewer
Walkthrough: Integrating ASP.NET Tracing with System.Diagnostics Tracing
ASP.NET

What's New in ASP.NET Tracing


ASP.NET tracing enables you to follow a page's execution path, display diagnostic information at run time, and debug your
application. ASP.NET tracing can be integrated with system-level tracing to provide multiple levels of tracing output in
distributed and multi-tier applications.
In ASP.NET 2.0, the major improvements to tracing features are:
Integrated tracing functionality You can now route messages emitted by the System.Diagnostics.Trace class to
ASP.NET tracing output, and route messages emitted by ASP.NET tracing to System.Diagnostics.Trace. You can also
forward ASP.NET instrumentation events to System.Diagnostics.Trace. For more information, see
Walkthrough: Integrating ASP.NET Tracing with System.Diagnostics Tracing.
Programmatic access to trace messages You can access and manipulate trace messages from your code for finer
control over the format of trace messages or for additional processing you require. For more information, see
Reading ASP.NET Trace Information and Writing Custom ASP.NET Trace Messages.
Improved application-level tracing A new application-level tracing option lets you view the most recent tracing data
available without restarting a tracing session or increasing the amount of tracing data the server must store. The most
recent tracing data is displayed, while older tracing data is discarded. For more information, see
Application-Level ASP.NET Tracing Overview.
See Also
Tasks
Walkthrough: Integrating ASP.NET Tracing with System.Diagnostics Tracing
Concepts
Application-Level ASP.NET Tracing Overview
Reading ASP.NET Trace Information
Writing Custom ASP.NET Trace Messages
Visual Web Developer

Walkthrough: Using Tracing in Visual Web Developer to Help


Find Web Page Errors
There are several ways to find errors in an ASP.NET Web page. This includes using the debugger and tracing. Tracing displays
messages about the actions that occur during page processing, and can include information that you choose to display. Tracing
also gives you information about the data that is being exchanged by the server and browser. The data exchange includes
control details, server variables, user name, cookies, and so on. This walkthrough illustrates how to use tracing.
Tracing is useful when it is impractical or not good to use the debugger. For example, the debugger might not be available
because your pages are on a remote server. Tracing also makes it easier for you to view information, such as the HTTP header,
that is not explicitly available in the debugger. For information about debugging, see
Walkthrough: Debugging Web Pages in Visual Web Developer.
In this walkthrough, you will work with tracing. You will create a Web page that prompts the user for a name, and then displays
the name. The page also stores the name in a cookie so that the user does not have to re-enter the name.
Note
In a production application, a better technique for storing personal information is to use ASP.NET profile properties. For detai
led information, see ASP.NET Profile Properties Overview. However, using a cookie in this walkthrough simplifies the code, w
hich lets you focus on tracing.

In this walkthrough, you will deliberately introduce some errors. Then, you will use tracing to see the status of page processing,
which will help you diagnose the errors.
Tasks illustrated in this walkthrough include the following:
Enabling tracing for a single page.
Reading trace output.
Displaying custom trace information.
Viewing tracing information in a separate trace window.
Creating custom trace output.
Prerequisites
In order to complete this walkthrough, you will need the following:
Microsoft Visual Web Developer Web development tool.
The .NET Framework.
This walkthrough assumes that you have a general understanding of working in Visual Web Developer. For an introduction to
Visual Web Developer, see Walkthrough: Creating a Basic Web Page in Visual Web Developer.
Creating the Web Site
If you have already created a Web site in Visual Web Developer by completing
Walkthrough: Creating a Basic Web Page in Visual Web Developer, you can use that Web site and go to "Adding Controls,"
later in this walkthrough. Otherwise, create a new Web site and page by following these steps.
Note
This walkthrough assumes that you are working with an ASP.NET page that uses a code-behind file for its code.

To create a file system Web site


1. Open Visual Web Developer.
2. On the File menu, click New Web Site.
The New Web Site dialog box appears.
3. Under Visual Studio installed templates, click ASP.NET Web Site.
4. In the right-most Location box, enter the name of the folder where you want to keep the pages of the Web site.
For example, type the folder name C:\WebSites.
5. In the Language list, click the programming language that you prefer to work in.
6. Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Adding a Page
If you are using an existing Web site, you can create a new page. If you already have a page you can use for this walkthrough,
go to the next section.
To create a new page
1. In Solution Explorer, right-click the Web site name, and then click Add New Item.
2. In the Add New Item <Path> dialog box, under Visual Studio installed templates, click Web Form.
3. In the Name box, type FirstWebPage.aspx.
4. In the Language list, click the programming language that you prefer to work in.
5. If you are creating a page in Visual Basic or C#, select the Place code in separate file check box.
6. Click Add.
Adding Controls
After you create a Web site and open a page, the next step is to add some controls to the page.
To add controls and code for debugging
Switch to Design view, and then from the Standard group in the Toolbox, drag the following controls onto the page and
set their properties as indicated in the table.

Control Properties

TextBox ID: textName


Text: (empty)

Button ID: buttonDisplayName


Text: Submit

Label ID: labelName


Text: (empty)
Note
For this walkthrough, the layout of the page is not important.

Adding Code
The next step is to add code to the page. When the page is running correctly, the user can enter a name, and then click Submit,
which displays the name in the Label control. If the user closes the browser, and then returns to the page, the page will already
have the user's name, because it is stored in a cookie.
The following steps guide you through adding the code. Neither the procedure here for adding the code nor the code itself is
completely correct. This is deliberate, so that you will be able to use tracing to find the errors on the page.
To add code
1. In Solution Explorer, right-click FirstWebPage.aspx, and then click View Code.
Note
Do not double-click the button in Design view.

2. Inside the class definition, enter the following code.


Note
If you are working with a single-file page, paste the code into the <script> block.

VB
Protected Sub buttonDisplayName_Click(ByVal sender As Object, _
ByVal e As EventArgs)
labelName.Text = Server.HtmlEncode(textName.Text)
Response.Cookies("username").Value = labelName.Text
End Sub

C#
protected void buttonDisplayName_Click(Object sender, EventArgs e)
{
labelName.Text = Server.HtmlEncode(textName.Text);
Response.Cookies["username"].Value = labelName.Text;
}

The code performs the following tasks:


It reads the value of the TextBox control, and then displays the value in the Label control. As part of this logic, the
code calls the HtmlEncode method, which turns potentially executable HTML characters, such as right angle bracket
(<), into their display equivalents. This is a security measure to prevent scripting exploits. For detailed information,
see Script Exploits.
It creates a cookie named username that stores the value that the user has entered.
3. Add the following method, either above or under the Click handler that you created in the preceding step.
VB
Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) _
Handles Me.Load
If Not Request.Cookies("username") Is Nothing Then
labelName.Text = Request.Cookies("username").Value
End If
End Sub

C#
void Page_Load(Object sender, EventArgs e)
{
if(Request.Cookies["username"] != null)
{
labelName.Text = Request.Cookies["username"].Value;
}
}

Testing the Page


You can now test the page. If you have followed the deliberately incomplete steps from the procedure in the preceding section,
the page will not yet work as designed.
To test the page
1. Press CTRL+F5 to run the page.
2. When the page appears, in the text box, type your name, and then click Submit.
Notice that even though clicking Submit caused the page to be posted back to the server, your name is not displayed.
3. Close the browser.
You can now use tracing to help you find the errors in the page.
Using Tracing to Find Errors
In this section, you will enable tracing for the page. You will examine tracing output, and then include custom tracing messages
that will help you pinpoint page errors.
To enable tracing for the page
1. Open the FirstWebPage.aspx page and switch to Design view.
2. In Properties, in the list, click DOCUMENT.
This displays properties for the page.
3. Set Trace to true.
The trace setting is actually made as part of the @ Page directive. You can see this by switching to Source view and
looking at the first line in the page. The @ Page directive will look similar to the following:
VB
<%@ Page language="VB" Trace="true" %>

C#
<%@ Page language="C#" Trace="true" %>

4. Press CTRL+F5 to run the page.


The page is displayed in the browser. At the top, you see the text and controls that you put on the page. Under the text
and controls, you see the tracing output, which displays many details about page processing and includes the following
information:
The sequence of page events that occurred while the page ran.
The types, names, and sizes of the controls on the page.
The cookies and their contents.
The server variables, which is a collection of all information that the browser sends to the server.
Notice that under Request Details (the first block of tracing information), the Request Type is GET. This indicates that it
is the first time the page has run; that is, it is not a postback.
5. In the box, type a name, and then click Submit.
Request Type is now POST. This indicates that this is a postback for the page. Clicking Submit does not cause the name
to be displayed.
6. Close the browser.
You can use custom tracing output to help you follow the logic of the page.
To add custom trace output
1. Add the following highlighted lines to the buttonDisplayName_Click handler that you created in "Adding Code," earlier
in this walkthrough:
VB
Protected Sub buttonDisplayName_Click(ByVal sender As Object, _
ByVal e As EventArgs)
Trace.Warn("debugging", "Start buttonDisplayName Click handler")
labelName.Text = Server.HtmlEncode(textName.Text)
Response.Cookies("username").Value = labelName.Text
Trace.Warn("debugging", "End buttonDisplayName Click handler")
End Sub

C#
protected void buttonDisplayName_Click(Object sender, EventArgs e)
{
Trace.Warn("debugging", "Start buttonDisplayName Click handler");
labelName.Text = Server.HtmlEncode(textName.Text);
Response.Cookies["username"].Value = labelName.Text;
Trace.Warn("debugging", "End buttonDisplayName Click handler");
}

The Warn method adds your custom messages to the trace output. Although the TraceContext class also provides a Write
method, the Warn method is more useful because the output is displayed in color.
2. Press CTRL+F5 to run the page.
3. Click Submit.
When you examine the trace output, you will notice that the output contains no red text. You can conclude from this that
the Click handler for Submit is not being called.
The most common reason that a handler is not called is that the control has not been correctly bound to the event
handler. That is true in this case — although you added the event-handling code, you did not bind the Click event for
Submit to the handler. Typically, Visual Web Developer binds the event to the control when you double-click the control
in Design view.
4. Close the browser.
5. In Source view, add the following highlighted attribute to the <asp:button> element:

<asp:button id="buttonDisplayName" runat="server" text="Submit"


onclick="buttonDisplayName_Click" />

6. Press CTRL+F5 to run the page.


7. In the box, enter a name, and then click Submit.
Your custom trace output appears in red in the Trace Information section, which lists the processing steps that the page
goes through.
The output in this section shows the messages in the order that the messages occurred during page processing. You
added your messages in the Click event handler, which is processed between the Begin Raise PostBackEvent and End
Raise PostBackEvent lines. Including custom messages lets you know not only that your handler was called but also
where in the page processing cycle the code is executed.
The category next to your custom messages is debugging, which is the category that you specified when you called the
Warn method. You can specify any category you want, and if it is useful, you can set the TraceMode property for the
page to the SortByCategory value to make it easier to find the category in the trace output.
Additionally, notice that the name that you entered is displayed in the label.
Now that the Click handler for Submit is working correctly, you can test the rest of the code in the page, including the cookie.
To test the cookie
1. Close the browser.
2. Press CTRL+F5 to run the page.
The behavior that you expect is for the name that you have entered to appear automatically in the label, because the
Click handler for Submit sets a cookie and the Page_Load handler reads it during the next postback. However, the label
is never set from the cookie.
If you are writing a cookie but it is not being persisted, the error is frequently that you are not setting an explicit
expiration date for the cookie. A cookie without an expiration date is a session cookie. A session cookie is maintained in
server memory only until the browser is closed. In other words, the cookie is not written to the browser. In the following
steps you will correct this problem.
3. Close the browser.
4. In Source view, add the following highlighted line to the buttonDisplayName_Click handler:
VB
Protected Sub buttonDisplayName_Click(ByVal sender As Object, _
ByVal e As EventArgs)
Trace.Warn("debugging", "Start buttonDisplayName Click handler")
labelName.Text = Server.HtmlEncode(textName.Text)
Response.Cookies("username").Value = labelName.Text
Response.Cookies("username").Expires= _
DateTime.Now.AddMinutes(30)
Trace.Warn("debugging", "End buttonDisplayName Click handler")
End Sub

C#
protected void buttonDisplayName_Click(Object sender, EventArgs e)
{
Trace.Warn("debugging",
"Start buttonDisplayName Click handler");
labelName.Text = Server.HtmlEncode(textName.Text);
Response.Cookies["username"].Value = labelName.Text;
Response.Cookies["username"].Expires=
DateTime.Now.AddMinutes(30);
Trace.Warn("debugging", "End buttonDisplayName Click handler");
}

The new line explicitly sets the cookie to expire in 30 minutes.


5. Press CTRL+F5 to run the page.
6. In the box, enter a name, and then click Submit.
The name is displayed in the browser. In the Response Cookies Collection trace output, you can see that the cookie is
being set.
7. Close the browser.
8. Press CTRL+F5 to run the page.
This time, the name is automatically filled in. In the Request Cookies Collection trace output, now you can see that the
browser is passing the cookie to your page.
Displaying Trace Information in a Trace Viewer Window
Setting the page to display tracing output is useful when you are working with only a single page. However, if you are working
with many pages in your application, it can be inconvenient to set tracing on and off for each page. Moreover, displaying
tracing output information in the page as the page is running can be distracting. Regardless, you would not want the page to
show tracing output to users of your application.
You can configure tracing not just at the page level but also at the application level. Setting application-level tracing has two
advantages:
You can enable and disable tracing for all pages at the same time.
You can display tracing output in a separate browser window — the trace viewer — instead of displaying it as part of the
output for the page.
When application-level tracing is enabled, ASP.NET maintains trace output from all pages in a cache. You can set options to
specify how many pages of trace output to cache and whether you want to keep the most recent or the oldest entries. You can
then invoke the trace viewer in the browser and select the trace output to examine.
In this section of the walkthrough, you will enable application-level tracing and use the trace viewer to examine the trace
output.
To enable application-level tracing
1. Switch to Source view, and then in the @ Page directive at the top of the page, delete Trace="true".
Note
Remove the attribute; do not just set it to false. Otherwise, the subsequent steps in this walkthrough will not work corr
ectly.

2. On the Website menu, click ASP.NET Configuration.


The ASP.NET Web Site Administration tool appears.
3. Click Application Configuration.
4. Under Debugging and Tracing, click Configure debugging and tracing, and then select the Capture tracing
information check box.
This setting enables application-level tracing.
For this walkthrough, you can leave the remaining settings at their default values. ASP.NET will cache up to 10 entries of
trace output (either 10 postbacks of a single page or fewer postbacks each for multiple pages), and cache the most recent
entries.
5. Close the ASP.NET Web Site Administration Tool.
Now you can run the original page and work with it in the way that a user will see it. However, at the same time, you can view
the tracing output when you have to in a separate browser window.
To view tracing output in a separate browser window
1. Press CTRL+F5 to run the page.
Notice that the page no longer displays trace output. The page looks the way a user would see it.
2. In the box, enter a name, and then click Submit to confirm that the page works correctly.
3. Open a new browser window.
4. In the browser, in the Address box, type the URL of your site, substituting trace.axd for the name of the page that you
are working with.
For example, if the URL for the page is the following:

http://localhost:8081/WebSite/Default.aspx

Type the following:

http://localhost:8081/WebSite/trace.axd
Note
A quick way to perform this task it to copy the URL from the original page, and then change just the page name.

The browser displays the current cache of trace entries.


5. Click View Details for the last (most recent) trace entry.
The browser displays trace output that is similar to what you saw earlier in the walkthrough, except that it is not
appended to the end of the page.
6. Switch to the browser instance that contains the original page.
7. In the box, type a new name, and then click Submit.
This action generates a new trace log entry.
8. Switch to the browser instance that contains the information.
9. In the browser, click Back to return to the list trace entries, and then click Refresh to update the list of entries.
A new entry appears to represent the trace output that you created in step 7.
10. Close both browser windows.
Creating Custom Trace Output
As you have seen, trace output contains lots of information, sometimes more than you need. For example, you might want to
limit trace output to only the trace output that you create yourself. Tracing lets you read the contents of the trace buffer and
selectively display the information that you need.
To create custom trace output, handle the TraceFinished event for the Trace object. In the event handler, you can read the trace
buffer.
To create custom trace output
1. In the page that you have been working with, add the following highlighted code to the Page_Load handler:
VB
Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles Me.Load
If Not Request.Cookies("username") Is Nothing Then
labelName.Text = Request.Cookies("username").Value
End If
AddHandler Trace.TraceFinished, AddressOf Me.TraceFinished
If IsPostBack Then
Trace.Write("debugging", "Page_Load (Postback)")
Else
Trace.Write("debugging", "Page_Load (First Time)")
End If
End Sub

C#
void Page_Load(object sender, EventArgs e)
{
if(Request.Cookies["username"].Value != null)
{
labelName.Text = Request.Cookies["username"].Value;
}
Trace.TraceFinished += new
TraceContextEventHandler(this.TraceFinished);
if (Page.IsPostBack)
{
Trace.Write("debugging", "Page load (postback)");
}
else
{
Trace.Write("debugging", "Page load (first time)");
}
}

The code performs the following two functions:


It binds a method in the page to the TraceFinished event for the Trace object, which is raised when the trace
output is complete for the page. You will write the method in the next step.
It writes some trace information.
2. Create the following method to handle the TraceFinished event:
VB
Sub TraceFinished(ByVal sender As Object, _
ByVal e As TraceContextEventArgs)
Dim traceRecord As TraceContextRecord
For Each traceRecord In e.TraceRecords
If traceRecord.Category = "debugging" Then
Response.Write("<BR>" & traceRecord.Message)
End If
Next
End Sub

C#
void TraceFinished(object sender, TraceContextEventArgs e)
{
foreach(TraceContextRecord traceRecord in e.TraceRecords)
{
if(traceRecord.Category == "debugging")
{
Response.Write("<br>" + traceRecord.Message);
}
}
}

This code is executed when the trace output is finished. The trace buffer is available as a collection in the TraceRecords
property of the e event argument. The code loops through the collection and displays the value of any trace record that
has debugging as its category; in this walkthrough, you have set the category of all custom trace output to debugging.
At this point in the walkthrough, the Web site is configured to enable tracing for all pages, but trace output is directed to a trace
viewer instead of to the page. If the Web site is configured differently — for example, if trace output is displayed in the page —
follow the steps in the procedure named To enable application-level tracing, in "Displaying Trace Information in a Trace Viewer
Window," earlier in the walkthrough.
You can now test the custom trace output.
To test custom trace output
1. Press CTRL+F5 to run the page.
When the page is displayed in the browser, the message Page load (first time) appear, but no other trace output
appears.
2. Click Submit.
The messages Page load (postback), Start buttonDisplayName Click handler, and End buttonDisplayName Click
handler appear.
Note
If you exceed the number of cached request that is specified in the requestLimit attribute of the
trace Element (ASP.NET Settings Schema), the TraceFinished event will not be raised and you will not see the messages on t
he Web page.

Next Steps
This walkthrough has illustrated the basic functionality of tracing in ASP.NET. Besides using tracing to display information
within the Web application, you can integrate ASP.NET tracing with other instrumentation. For example, you might want to do
the following:
Display system diagnostics messages as part of your ASP.NET tracing.
For more information, see Walkthrough: Integrating ASP.NET Tracing with System.Diagnostics Tracing.
Send ASP.NET trace information to the .NET Framework tracing mechanism, which uses classes in the System.Diagnostics
namespace.
Forward information to registered instrumentation listeners as part of the health monitoring for the Web site.
For more information about registering listeners, see <listeners> Element for <trace>.
See Also
Other Resources
Tracing in ASP.NET Web Pages (Visual Studio)
ASP.NET

How to: Enable Tracing for an ASP.NET Page


You can control whether tracing is enabled or disabled for individual pages. If tracing is enabled, when the page is requested,
ASP.NET appends to the page a series of tables containing execution details about the page request. Tracing is disabled by
default.
To enable tracing for a page
1. Include an @ Page directive at the top of your .aspx file.
2. Add a Trace attribute and set its value to true, as shown in the following example:

<%@ Page Trace="true" %>

Security Note
When tracing is enabled for a page, trace information is displayed in any browser requests that page. Tracing displays s
ensitive information, such as the values of server variables, and can therefore represent a security threat. Be sure to dis
able page tracing before porting your application to a production server. You can do this by setting the Trace attribute
to false or by removing it. You can also configure tracing in the Web.config file by setting the enabled, localOnly, and
pageOutput attributes of the trace Element (ASP.NET Settings Schema). The Trace attribute in the @ Page directive ta
kes precedence over attributes set in the trace element in the Web.config file. Therefore, even if you disable tracing in t
he Web.config file by setting the enabled attribute to false, the page might still show tracing information if the Trace
attribute in its @ Page directive is set to true.

3. Optionally, include the TraceMode attribute to specify the order in which you want your trace messages to appear:
Set TraceMode to SortByTime to sort trace messages in the order in which they are processed.
Set TraceMode to SortByCategory to sort trace messages by the categories that you specified in the
System.Web.TraceContext.Warn and System.Web.TraceContext.Write method calls in your page or server control
code.
The following example shows how to enable tracing in a page and to sort trace messages by category.

<%@ Page Language="VB" Trace="True" TraceMode="SortByCategory" %>

See Also
Tasks
How to: Enable Tracing for an ASP.NET Application
Reference
@ Page
TraceContext
Concepts
Writing Custom ASP.NET Trace Messages
Reading ASP.NET Trace Information
Other Resources
ASP.NET Tracing
ASP.NET

Reading ASP.NET Trace Information


You can view trace information appended at the end of an ASP.NET page or in the trace viewer. In both cases, the information
displayed is the same. ASP.NET organizes the trace information in a series of tables that provide diagnostic information about
the request that you are viewing. For information on viewing trace information in a page, see
How to: Enable Tracing for an ASP.NET Page. For information on viewing trace information in the trace viewer, see
How to: View Trace Information with the Trace Viewer.
Trace Output Sections
Trace information appears in the following order.
Request Details
The Request Details section displays general information about the current request and response.
Value Description
Session ID The session identification for the specified request.

Time of Reque The time the request was made.


st

Request Encod The character encoding for the request.


ing

Request Type The HTTP method used (GET or POST).

Status Code The status-code value associated with the response. For more information, see RFC 2616 at the
World Wide Web Consortium (W3C) Web site.

Response Enco The character encoding for the response.


ding
Trace Information
The Trace Information section displays the flow of page-level events. If you have created custom trace messages, the
messages are displayed in the Trace Information section also.
Value Description
Category The custom trace category specified in a Warn or Write method call, if any.

Message The custom trace message specified in a Warn or Write method, if any.

From First ( The elapsed time in seconds since the first trace message was processed. The first trace message appears at the t
s) op of the list.

From Last ( The elapsed time in seconds between the processing of the current trace message and the preceding trace messa
s) ge.
Control Tree
The Control Tree section displays information about ASP.NET server controls created in the page.
Value Description
Control ID The identification for the control. If you have not specified an ID property for the control, ASP.NET generates
an ID using the UniqueID property.

Type The fully qualified type of the control.


Render Size byt The size in bytes of the rendered control (including child controls). This is the size of the actual HTML, XML,
es or other format that is sent to the browser.

ViewState Size b The size in bytes of the control's view state (excluding child controls). For more information, see
ytes ASP.NET State Management.

ControlState Siz The size in bytes of the control's control state (excluding child controls). For more information, see
e bytes ASP.NET State Management.
Session State
The Session State section displays information about values stored in Session state, if any. For more information, see
ASP.NET Session State.
Value Description
Session Key The key for data stored in session state, if any.

Type The fully qualified type of the object that stores the data.

Value A string representation of the data stored in session state, if any.


Application State
The Application State section displays information about values stored in Application state, if any. For more information, see
ASP.NET Application State.
Value Description
Application Key The key for data stored in application state, if any.

Type The fully qualified type of the object that stores the data.

Value A string representation of the data stored in application state, if any.


Cookies Collection
The Request Cookies and Response Cookies sections display information about the cookies passed between the browser
and the server on each request and response. The section displays both persistent and session cookies. ASP.NET creates some
cookies automatically, such as those for cookie-based Session state and forms authentication. For more information, see
ASP.NET Cookies.
Value Description
Name The name of the cookie.

Value The value of the cookie, or subkeys and values if the cookie is multivalued.

Size The size in bytes of the cookie.


Headers Collection
The Headers Collection section displays information about request and response message header name/value pairs, which
provide information about the message body or requested resource. Header information is used to control how request
messages are processed and response messages are created. For more information on HTTP headers, see RFC 2616 at the
World Wide Web Consortium (W3C) Web site.
Value Description
Name The name of the header.

Value The value of the header.


Form Collection
The Form Collection section displays name/value pairs that show the form element values (control values) submitted in a
The Form Collection section displays name/value pairs that show the form element values (control values) submitted in a
request during a POST (postback).
Value Description
Name The name of the form variable.

Value The value of the form variable.


Querystring Collection
The Querystring Collection section shows the values passed in the URL. In a URL, query string information is separated from
the path information by a question mark (?); multiple query string elements are separated by an ampersand (&). Query string
name/value pairs are separated by an equals sign (=). The QueryString property of the HttpRequest object returns a
NameValueCollection of query string variables.
Value Description
Name The name of the query string variable.

Value The value of the query string variable.


Server Variables
The Server Variables section displays a collection of server-related environment variables and request header information.
The ServerVariables property of the HttpRequest object returns a NameValueCollection of server variables.
Value Description
Name The name of the server variable.

Value The value of the server variable.

See Also
Tasks
How to: Enable Tracing for an ASP.NET Application
How to: View ASP.NET Trace Information with the Trace Viewer
Other Resources
ASP.NET Tracing
ASP.NET

Writing Custom ASP.NET Trace Messages


ASP.NET tracing enables you to append custom trace information to the end of an ASP.NET page or to the trace log. The trace
information written to the trace log is viewable with the trace viewer. For more information, see
How to: View ASP.NET Trace Information with the Trace Viewer.
You can write trace information using the TraceContext class's Warn or Write methods. The difference between the two
methods is that a message written with the Warn method appears in red text.
For information on enabling tracing for a page, see How to: Enable Tracing for an ASP.NET Page. For information on enabling
tracing for an application, see How to: Enable Tracing for an ASP.NET Application.
The following code example demonstrates using the TraceContext class to display trace information at the end of an ASP.NET
page. A different exception is thrown for each LinkButton control that caused the postback. The error message used to initialize
the ArgumentException or InvalidOperationException is displayed in the trace log.
VB
<%@ Page Language="VB" Trace="true" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11


.dtd">

<script runat="server">

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)

Try
If (IsPostBack) Then

Select Case Request.Form("__EVENTTARGET")


Case "WarnLink"
Throw New ArgumentException("Trace warn.")
Case "WriteLink"
Throw New InvalidOperationException("Trace write.")
Case Else
Throw New ArgumentException("General exception.")
End Select
End If
Catch ae As ArgumentException
Trace.Warn("Exception Handling", "Warning: Page_Load.", ae)
Catch ioe As InvalidOperationException
Trace.Write("Exception Handling", "Exception: Page_Load.", ioe)
End Try
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Trace Example</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:LinkButton id="WriteLink"
runat="server"
text="Generate Trace Write" />
<asp:LinkButton id="WarnLink"
runat="server"
text="Generate Trace Warn" />
</div>
</form>
</body>
</html>
C#
<%@ Page Language="C#" Trace="true" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11


.dtd">
<script runat="server">
void Page_Load(object sender, EventArgs e)
{
try {
if (IsPostBack)
{
switch (Request.Form["__EVENTTARGET"])
{
case "WarnLink":
throw new ArgumentException("Trace warn.");
break;
case "WriteLink":
throw new InvalidOperationException("Trace write.");
break;
default:
throw new ArgumentException("General exception.");
break;
}
}
}
catch (ArgumentException ae) {
Trace.Warn("Exception Handling", "Warning: Page_Load.", ae);
}
catch (InvalidOperationException ioe) {
Trace.Write("Exception Handling", "Exception: Page_Load.", ioe);
}
}

</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Trace Example</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:LinkButton id="WriteLink"
runat="server"
text="Generate Trace Write" />
<asp:LinkButton id="WarnLink"
runat="server"
text="Generate Trace Warn" />
</div>
</form>
</body>
</html>

See Also
Tasks
How to: Enable Tracing for an ASP.NET Application
How to: View ASP.NET Trace Information with the Trace Viewer
Other Resources
ASP.NET Tracing
ASP.NET

Application-Level ASP.NET Tracing Overview


You can configure individual pages to display trace information. Alternatively, you can configure the application's Web.config
file so that all pages display trace information unless the page explicitly disables tracing. Setting application-level tracing is
useful because you do not need to make changes to individual pages to enable and disable it.
You enable application-level tracing using the trace element in the Web.config file. When you enable application-level tracing,
ASP.NET collects trace information for each request to the application, up to the maximum number of requests you specify. The
default number of requests is 10. By default, when the trace viewer reaches its request limit, the application stops storing trace
requests. You can configure tracing to store either oldest tracing data (discarding newer items) or the most recent trace
information (discarding older items).
Note
When you enable tracing for an entire application in the Web.config file, trace information is gathered and processed for eac
h page in that application. To override the application-wide settings, set the Trace attribute in that page's @ Page directive to
false. Any Write or Warn statements that you include in a page's code are stored and returned to the trace viewer only.

Viewing Trace Information


As with page tracing generally, you can view trace information at the bottom of individual pages. Alternatively, you can use the
trace viewer (Trace.axd) to view trace information collected and cached by ASP.NET when tracing is enabled.
If you want trace information to appear at the end of the page that it is associated with, you can set the trace element's
PageOutput attribute to true. If you enable application-level tracing, but you do not want trace information displayed for some
pages, you can set the Trace attribute in those pages' @ Page directive to false. For more information about configuring your
ASP.NET application, see ASP.NET Configuration Overview.
By default, application-level tracing can be viewed only on the local Web server computer. To make application-level trace
information visible from remote computers, you can set the trace element's LocalOnly attribute to false.
Note
To help keep your Web application secure, use the remote tracing capability only when you are developing or deploying you
r application. Be sure to disable it before you transfer your application to production Web servers by setting LocalOnly attrib
ute to true in the Web.config file.

The following example shows an application trace configuration that collects trace information for up to 40 requests and
allows browsers on computers other than the server to display the trace viewer.

<configuration>
<system.web>
<trace enabled="true" requestLimit="40" localOnly="false" />
</system.web>
</configuration>

Trace Configuration Attributes


The following table shows the attributes you can use to modify the behavior of application-level tracing in the trace element of
the Web.config file.
Attribute Description
enabled true to enable tracing for the application; otherwise, false. The default is false. You can override this setting for i
ndividual pages by setting the Trace attribute in those pages' @ Page directive to true or false.

pageOutput true to display trace both in pages and in the trace viewer (Trace.axd); otherwise, false. The default is false.
Note
Individual pages that have tracing enabled are not affected by this setting.
RequestLimit The number of trace requests to store on the server. The default is 10.

traceMode The order in which trace information is displayed. Set to SortByTime to sort by the order in which information w
as processed. Set to SortByCategory to sort alphabetically by user-defined category. The default is SortByTime.

localOnly true to make the trace viewer (Trace.axd) available only on the host Web server; otherwise, false. The default is t
rue.

mostRecent true to display the most recent trace information as tracing output; otherwise, false, which indicates that once th
e requestLimit value is exceeded, new requests are not stored. The default is false.
Note
Tracing data that exceeds the limit defined by the requestLimit attribute is discarded in favor of the most recen
t data only when mostRecent is true.

See Also
Tasks
How to: Enable Tracing for an ASP.NET Application
ASP.NET

How to: Enable Tracing for an ASP.NET Application


Instead of enabling tracing for individual pages, you can enable it for your entire application. In that case, every page in your
application displays trace information. Application tracing is useful when you are developing an application because you can
easily enable it and disable it without editing individual pages. When your application is complete, you can turn off tracing for
all pages at once.
When you enable tracing for an application, ASP.NET collects trace information for each request to the application, up to the
maximum number of requests you specify. The default number of requests is 10. You can view trace information with the trace
viewer.
By default, when the trace viewer reaches its request limit, the application stops storing trace requests. However, you can
configure application-level tracing to always store the most recent tracing data, discarding the oldest data when the maximum
number of requests is reached. For more information, see Application-Level ASP.NET Tracing Overview.
Note
To disable tracing for an individual page in the application, set the Trace attribute in that page's @ Page directive to false. An
y Write or Warn statements that you include in a page's code are stored and returned to the trace viewer only.

To enable tracing for an application


1. Open your Web site's Web.config file. If no Web.config file exists, create a new file in the root folder and copy the
following into it:

<?xml version="1.0"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<system.web>

</system.web>
</configuration>

2. Add a trace element as a child of the system.web element.


3. In the trace element, set the enabled attribute to true.
4. If you want trace information to appear at the end of the page that it is associated with, set the trace element's
pageOutput attribute to true. If you want tracing information to be displayed only in the trace viewer, set the
pageOutput attribute to false.
For example, the following application trace configuration collects trace information for up to 40 requests and allows
browsers on computers other than the server of origin to display the trace viewer. Trace information is not displayed in
individual pages.

<configuration>
<system.web>
<trace enabled="true" pageOutput="false" requestLimit="40" localOnly="false"/>
</system.web>
</configuration>

Note
The ASP.NET configuration system is case-sensitive.

See Also
Tasks
How to: Enable Tracing for an ASP.NET Page
How to: View ASP.NET Trace Information with the Trace Viewer
Concepts
Application-Level ASP.NET Tracing Overview
ASP.NET Configuration Overview
Other Resources
ASP.NET Tracing
ASP.NET

How to: View ASP.NET Trace Information with the Trace Viewer
If you have enabled tracing for your application, when any page is requested, the page gathers trace information and executes
any trace statements that it contains. You can view the trace output in the trace viewer. The trace viewer enables you to choose
a specific request from the pages that have been requested from your application.
Note
When you enable tracing for an application, you can display trace output in any page in the application by setting the pageO
utput attribute of the trace element to true in the Web.config file.

If multiple requests have arrived for an application that has tracing enabled, the trace viewer lists the requests in the order in
which they were processed. The information on the opening page of the trace viewer includes the time of the request, the file
requested, the status code of the request, the HTTP verb associated with the request, and a View Details link that enables you
to see more information about the request. The number of requests available will not exceed the requestLimit setting that you
specified in the Web.config file.
The following screen shot shows a trace viewer that has had seven requests to its application since tracing was enabled.
Trace viewer

To view trace details for a specific request


1. Navigate to Trace.axd in the root of your application.
For example, if the URL for your application is http://localhost/SampleApplication, navigate to
http://localhost/SampleApplication/trace.axd to view the trace information for that application.
2. Select the View Details link for the request that you want to investigate.
To clear requests from the trace viewer
1. Navigate to Trace.axd in the root of your application.
2. Select the clear current trace link to remove all the requests stored in the trace viewer.
Note
If the mostRecent attribute of the trace element is false, then the trace viewer tracks requests only up to the number o
f requests defined by the requestLimit attribute. In that case, you cannot view requests made after the request limit is
reached. Alternatively, you can set the mostRecent attribute to true so that the most recent tracing data is shown and
older tracing data that exceeds the limit defined by the requestLimit attribute is discarded.

See Also
Tasks
How to: Enable Tracing for an ASP.NET Page
How to: Enable Tracing for an ASP.NET Application
Other Resources
ASP.NET Tracing
Visual Web Developer

Walkthrough Topics — Tracing in Web Pages


The following walkthrough topic demonstrates how to use ASP.NET tracing to display diagnostic information about page
processing.
Walkthrough Topics
Walkthrough: Using Tracing in Visual Web Developer to Help Find Web Page Errors
See Also
Other Resources
Tracing in ASP.NET Web Pages (Visual Studio)
Visual Web Developer

How-to Topics — Tracing in Web Pages


The following procedures describe how to use ASP.NET tracing to display diagnostic information about page processing.
How-to Topics
How to: Enable Tracing for an ASP.NET Page
How to: Enable Tracing for an ASP.NET Application
How to: View ASP.NET Trace Information with the Trace Viewer
See Also
Other Resources
Tracing in ASP.NET Web Pages (Visual Studio)
ASP.NET

Error Handling in ASP.NET Pages and Applications


This section describes how to check for errors in your pages and create global error handlers.
In This Section
How to: Handle Page-Level Errors
How to: Handle Application-Level Errors
Related Sections
ASP.NET Troubleshooting and Debugging
Provides information about techniques for finding errors in your ASP.NET Web applications.
How to: Display Safe Error Messages
Provides information about security implications of displaying error messages.
ASP.NET

How to: Handle Page-Level Errors


If possible, you should handle errors in Try/Catch blocks within your code, because a problem is more easily corrected where
it occurs. If the user can help correct a problem, the page needs to return to the same place so the user has a context for
understanding what to do.
A page-level handler returns you to the page, but there is no longer anything on the page because instances of controls are not
created. To provide the user any information, you must specifically write it to the page.
You would probably use a page-level error handler to log unhandled errors or to take the user to a page that can display
helpful information.
This code example shows a handler for the Error event in an ASP.NET Web page. This handler catches all exceptions that are
not already handled within Try/Catch blocks in the page.
After you handle an error, you must clear it by calling the ClearError method of the Server object (HttpServerUtility class).
Example
This handler filters for specific kinds of exceptions. For an ArgumentOutOfRangeException exception, the handler writes some
text on the page, provides a link back to the page, logs the error, and notifies system administrators. For an
InvalidOperationException exception, the handler simply transfers the exception to the Generic Error Page. For any other kind
of exception, the handler does nothing, which allows your site to automatically redirect to the generic page specified in the
Web.config file. Your own code would filter for exceptions that are important to your application.
The following example is part of a complete code sample in Complete Example for Error Handlers
Security
Use the <customErrors> Element to restrict display of detailed error messages to local users only.
Be sure that you do not display error information that might help malicious users compromise your application. For details, see
How to: Display Safe Error Messages.
See Also
Tasks
How to: Handle Application-Level Errors
Concepts
Complete Example for Error Handlers
ASP.NET

How to: Handle Application-Level Errors


This code example shows how to create an error handler in the Global.asax file that will catch all unhandled ASP.NET errors
while processing a request — in other words, all the errors that are not caught with a Try/Catch block or in a page-level error
handler. In the example, the handler transfers control to a generic error page named GenericErrorPage.aspx, which interprets
the error and displays an appropriate message.
Example
The following example is from a complete code sample in Complete Example for Error Handlers.
To enable the error event handler in the Global.asax file, the Web.config file cannot specify a file for defaultRedirect. The
configuration file takes precedence. Therefore, you can either set customErrors to Off or remove the defaultRedirect setting.
If your Web.config configuration file has customErrors set to Off, the Application_Error event handler in Global.asax will
process all unhandled errors.
Security Note
Never set customErrors to Off in your Web.config file if you do not have an Application_Error handler in your Global.asax
file. Potentially compromising information about your Web site can be exposed to anyone who can cause an error to occur o
n your site.

Robust Programming
It is better to use Try/Catch blocks around any code that is subject to errors instead of relying on a global error handler.
An error handler that is defined in the Global.asax file will only catch errors that occur during processing of requests by the
ASP.NET runtime. For example, it will catch the error if a user requests an .aspx file that does not occur in your application.
However, it does not catch the error if a user requests a nonexistent .htm file. For non-ASP.NET errors, you can create a custom
handler in Internet Information Services (IIS). The custom handler will also not be called for server-level errors.
You cannot directly output error information for requests from the Global.asax file; you must transfer control to another page,
typically a Web Forms page. When transferring control to another page, use Transfer method. This preserves the current
context so that you can get error information from the GetLastError method.
After handling an error, you must clear it by calling the ClearError method of the Server object (HttpServerUtility class).
Security
Be sure that you do not display error information that might help malicious users compromise your application. For details, see
How to: Display Safe Error Messages.
See Also
Tasks
How to: Handle Page-Level Errors
Concepts
Complete Example for Error Handlers
ASP.NET

ASP.NET Health Monitoring


ASP.NET health monitoring allows system administrators to monitor the status of deployed Web applications. It supports the
following general scenarios:
Monitoring the performance of an application to ensure that it is healthy.
Rapidly diagnosing failing applications or systems.
Appraising significant events during the lifecycle of a given application.
The health monitoring system includes the event types responsible for packaging application health status information, the
provider types responsible for processing this information, and the supporting types that help during the management of
health events.
Note
Medium trust or higher is required to raise a health-monitoring event.

The topics in this section will help you understand how to program, configure, and use the health monitoring system.
In This Section
ASP.NET Health Monitoring Overview
Configuring ASP.NET Health Monitoring
Buffering ASP.NET Health Monitoring Events
Using WMI to Deliver ASP.NET Health Monitoring Events
Walkthrough: Listening for WMI Events in ASP.NET Health Monitoring
Extending ASP.NET Health Monitoring
Implementing Custom ASP.NET Health Monitoring Events and Providers
Securing ASP.NET Health Monitoring
Reference
System.Web.Management
The namespace containing types for managing and monitoring the health status of Web applications.
System.Management
The namespace containing types for connecting to the Windows Management Instrumentation (WMI) infrastructure.
System.Management.Instrumentation
The namespace containing types to instrument applications for WMI potential consumers.
HealthMonitoringSection
The type that programmatically gets or sets the healthMonitoring configuration attributes.
Related Sections
healthMonitoring Element (ASP.NET Settings Schema)
Describes the health monitoring configuration section.
ASP.NET Trust Levels and Policy Files
Describes trust levels and associated policy files.
ASP.NET

ASP.NET Health Monitoring Overview


ASP.NET provides an easy way to monitor the health of deployed ASP.NET applications, providing you with detailed run-time
information about ASP.NET resources. ASP.NET health-monitoring features can be used to perform the following tasks:
Monitor live ASP.NET applications, individually or across a Web farm, to ensure that they are working properly.
Diagnose ASP.NET applications that appear to be failing.
Log events that do not necessarily relate to errors in an ASP.NET application but can be useful for you to examine.
In the past, Web site administrators had to rely on HTTP errors, debugging output, or a limited set of event log messages to
monitor or diagnose their applications in a reactive manner. ASP.NET health monitoring provides a proactive approach by
raising Web events and delivering health-monitoring data through various mechanisms.
Note
You can also use ASP.NET tracing or debugging to diagnose errors in ASP.NET pages or applications. For more information, s
ee ASP.NET Tracing and ASP.NET Debugging. You can also monitor the performance of your ASP.NET application. For more i
nformation, see ASP.NET Performance.

This topic contains the following sections:


How ASP.NET Health Monitoring Works
Web Events
Consuming Web Events Using Event Providers
Enabling and Disabling Web Events
Effect of Health Monitoring on Performance
Extending ASP.NET Health-Monitoring Features
Securing ASP.NET Health Monitoring
How ASP.NET Health Monitoring Works
ASP.NET can raise Web health-monitoring events (also called Web events) at various times during the course of application
processing. Web events are consumed by providers (listeners), which read the information packaged with the event and then
record the information. Each provider is written to record the Web event data in a different way. For example, one provider
might write to the Windows event log, while another might send an e-mail message.
The following list shows step-by-step how health monitoring works:
1. ASP.NET builds a merged collection of application configuration settings when an application starts. For more
information, see ASP.NET Configuration File Hierarchy and Inheritance. Providers and events are registered in the
configuration settings for the application.
2. A Web health-monitoring event (a Web event) occurs. For example, this can be an event caused by a security operation
that fails, such as a failure during URL authorization for a Web request.
3. ASP.NET checks the configuration settings for registered providers and events. Health-monitoring configuration settings
are contained in the healthMonitoring element of configuration files. For information about how to configure ASP.NET
applications, see Configuring ASP.NET Applications.
The following health-monitoring settings are required.
Types of Web events are assigned to named groups in the eventMappings collection element. For example, events
that occur when a security operation fails are named Failure Audits and are mapped by default to the
WebFailureAuditEvent class in the root Web.config configuration file, using an element such as the following:

<eventMappings>
<add
name="Failure Audits"
type="System.Web.Management.WebFailureAuditEvent"
<!-- additional attributes here -->
/>
<!-- additional <add> elements here -->
</eventMappings>

Types of event providers (listeners) are assigned to event provider classes in the providers collection element. For
example, the event provider that consumes all error events is named EventLogProvider and is mapped to the
EventLogWebEventProvider class in the root Web.config configuration file, using an element such as the following:

<providers>
<add
name="EventLogProvider"
type="System.Web.Management.EventLogWebEventProvider"
<!-- additional attributes here for some providers -->
/>
<!-- additional <add> elements here -->
</providers>

Event providers subscribe to events in the rules collection element. Event providers can subscribe to more than one
Web event, and Web events can be subscribed to by more than one event provider. By default, the
EventLogProvider subscribes to the Failure Audits events in the root Web.config file, using an element such as
the following:

<rules>
<add
name="Failure Audits Default"
eventName="Failure Audits"
provider="EventLogProvider"
<!-- additional attributes here -->
/>
</rules>

4. When an event is raised, an instance of the Web event class is created. Event data is collected in the properties of this
object. For example, the properties of the WebFailureAuditEvent object include information about the event identifier,
source, date and time, and a special WebApplicationInformation class that contains information about the application
domain, path, and so on. Built-in events are raised automatically by ASP.NET. Custom events must be explicitly raised
using the Raise method.
5. The event provider consumes the event and records the event information. For example, the EventLogProvider writes
event information to the Windows event log. Other providers deliver event data using different mechanisms. For more
information, see Consuming Web Events Using Event Providers below.
ASP.NET comes with built-in Web events and providers already configured as system defaults. However there are only two
events enabled in the rules element: All Errors and Failure Audits. Both are enabled and are subscribed to by the
EventLogProvider.

Web Events
Web events can contain information about the ASP.NET worker process, application domain, request data, response data,
application errors, and configuration errors. The following managed Web event classes are available in ASP.NET as members of
the System.Web.Management namespace. All event classes inherit from the WebBaseEvent base class. For information about
how to obtain event data, see Consuming Web Events Using Event Providers later in this topic.
Event class Description
WebApplicationLifetimeEvent Represents a significant event in the lifetime of an ASP.NET application. Application lifeti
me events include events such as application startup and shutdown events. If an applica
tion is terminated, you can determine why by viewing the related event-message field.

WebAuditEvent Serves as the base class for all ASP.NET health-monitoring audit events.

WebAuthenticationFailureAuditEvent Provides information about ASP.NET authentication failures.

WebAuthenticationSuccessAuditEvent Provides information about successful authentication events.

WebBaseErrorEvent Serves as the base class for all the health-monitoring error events.

WebBaseEvent Serves as the base class for the ASP.NET health-monitoring events.

WebErrorEvent Provides information about errors caused by problems with configuration or applicatio
n code. An example is the error issued by ASP.NET when an error is found in a page.

WebFailureAuditEvent Provides information about security failures.

WebHeartbeatEvent Serves as a timer for the ASP.NET health-monitoring system. These events are raised at
an interval defined by the heartbeatInterval attribute of the healthMonitoring config
uration section.

WebManagementEvent Serves as the base class for events that carry application and process information.

WebRequestErrorEvent Defines the event that carries information about Web-request errors.

WebRequestEvent Serves as the base class for events providing Web-request information.

WebSuccessAuditEvent Provides information about successful security events. An example of this is a successful
URL authorization for a Web request.

WebViewStateFailureAuditEvent Provides Web-application view state failure information.

By default, ASP.NET automatically records some Web event data. For example, some event data, such as the number of times
that an event occurs, is captured using performance counters. In these situations, performance counters are used instead of
Web events to minimize the impact on the performance of health-monitored applications. This behavior is not customizable.
For more information, see ASP.NET Performance, performance counters, and the Performance monitoring pages in MSDN.
Customizing Events
You can customize Web events in the following ways:
You can limit the number of event notifications that occur in a given time span and specify the interval between events
using attributes of the rules element. The following example shows a fragment from the configuration file in which the
Default profile is configured for Failure Audit events. The Default profile specifies the following settings

The minimum number of times an event can occur before an event notification is sent is 1.
The maximum number of times an event can occur before notifications stop is 2147483647 (infinite).
The minimum time interval between two events is one minute.

<rules>
<add
name="Failure Audits Default"
eventName="Failure Audits"
provider="EventLogProvider"
profile="Default"
minInstances="1"
maxLimit="Infinite"
minInterval="00:01:00"
custom=""
/>
<!-- additional <add> elements here -->
</rules>

You can subscribe an existing provider or a custom provider to a Web event by configuring a new rules element in your
Web.config file. The following example code shows how the EventLogWebEventProvider subscribes to a custom event
named SampleCustomWebEvent. The EventLogProvider is already configured in the root Web.config file.

<rules>
<add
name="Sample Custom Events"
eventName="SampleCustomWebEvent"
provider="EventLogProvider"
profile="Default"
minInstances="1"
maxLimit="Infinite"
minInterval="00:01:00"
custom=""
/>
</rules>
<eventMappings>
<add
name="SampleCustomWebEvent"
type="Microsoft.Samples.Web.Management.SampleCustomWebEvent"
startEventCode="0"
endEventCode="2147483647"
/>
</eventMappings>

If none of the built-in event classes meets your needs, you can create custom events by inheriting from existing event classes.
For more information, see Extending ASP.NET Health Monitoring.
Note
Do not place the source code that you create for custom event providers and custom Web events in the App_Code directory.
Instead, compile the source code into assemblies and place those assemblies in the Bin directory. For more information on a
pplication folders, see ASP.NET Web Site Layout.

Consuming Web Events Using Event Providers


Event providers consume Web event data. By default, the ASP.NET health-monitoring system can deliver Web event data using
the built-in providers listed in the following table. More than one provider can listen for the same event, and more than one
event can be consumed by the same provider. For information about subscribing event providers to Web events, see
Enabling and Disabling Web Events below.
Event Providers Details
EventLogWebEventProvider Writes Web event data to the Windows event log. By default, this provider is configured to w
rite all errors to the Windows event log. Security operation errors are logged under the even
t name Failure Audits and logs all other errors are logged under the event name All Erro
rs.

To read event log data, you can view data using the Windows Event Viewer or read event lo
g data programmatically. For more information, see Reading the Event Log.
SqlWebEventProvider Logs Web event data to a Microsoft SQL server database. By default, this provider logs data
to the SQL Server Express database in the Web application's App_Data folder. It does not su
bscribe to any events by default.

WmiWebEventProvider Passes Web events to WMI, converting them to WMI events. By default, this provider does n
ot subscribe to any events.
To listen for WMI events, you can build an application such as the one illustrated in
Walkthrough: Listening for WMI Events in ASP.NET Health Monitoring. For more informatio
n, see Using WMI to Deliver ASP.NET Health Monitoring Events. WMI applications do not ha
ve to be written in managed code.

SimpleMailWebEventProvider an Sends an e-mail message when Web events are raised. By default, these providers are not c
d onfigured and do not subscribe to any events.
TemplatedMailWebEventProvider

TraceWebEventProvider Passes event data to the ASP.NET page tracing system. By default, this provider is not config
ured and does not subscribe to any events. Tracing provides you the ability to start and stop
event tracing sessions, to instrument applications to provide trace events, and to consume tr
ace events. You can use the events to debug an application and perform capacity and perfor
mance analysis. For more information, see ASP.NET Tracing.
Customizing Event Providers
You can customize event providers in the following ways:
You can buffer event data that will be consumed by the SQL or mail event providers. For more information, see
Buffering ASP.NET Health Monitoring Events.
You can configure event providers to consume existing or custom Web events by configuring a new rules element in
your Web.config file. The following example shows how the MyCustomEventProvider subscribed to the
WebHeartbeatEvent. The Heartbeats event is already configured in the root Web.config file.

<rules>
<add
name="Heartbeat Events"
eventName="Heartbeats"
provider="Sample Custom Event Provider"
profile="Default"
minInstances="1"
maxLimit="Infinite"
minInterval="00:01:00"
custom=""
/>
</rules>
<providers>
<add
name="Sample Custom Event Provider"
type="System.Web.Management.SampleCustomEventProvider"
/>
</providers>

You can create your own custom event providers by inheriting from the WebEventProvider or
BufferedWebEventProvider classes. Custom event providers can be used to log events to a custom log file, send event
data to third-party applications, and so on. For more information, see Extending ASP.NET Health Monitoring. For code
examples, see Implementing Custom ASP.NET Health Monitoring Events and Providers.

Enabling and Disabling Web Events


An event is enabled if it is mapped to an event provider in the rules element of a configuration file. The eventMappings and the
providers element must also be configured for the event and provider, but unless the two are connected in the rules element,
the event is not raised. For more information, see Configuring ASP.NET Health Monitoring.
To disable an event, you can remove all references to the event from the rules configuration collection.
Effect of Health Monitoring on Performance
The performance of your application is affected by how extensively you use ASP.NET health-monitoring features. To minimize
the impact on the performance of health-monitored applications, configure the minInterval attribute of the rules element to
increase minimum time interval between two events.
Event Buffering
You can configure the SqlWebEventProvider and MailWebEventProvider event providers to buffer events. Buffering collects
event data and sends it all at once instead of logging the information or sending an e-mail message immediately when the
event occurs. This helps to minimize the impact of health monitoring on application performance. In addition, event buffering
also protects SQL Server and the SMTP server from heavy loads due to high event volume. For more information, see
Buffering ASP.NET Health Monitoring Events, BufferedWebEventProvider, and the bufferModes Element.
Extending ASP.NET Health-Monitoring Features
If you already have a monitoring infrastructure, you can integrate ASP.NET health-monitoring system into it. For example, WMI
can be used to capture ASP.NET Web events and record the data using an existing data store.
Using the classes of the System.Web.Management namespace, you can create custom Web events or custom event
providers. For more information, see Extending ASP.NET Health Monitoring.
Securing ASP.NET Health Monitoring
By default, the ASP.NET health-monitoring system is configured to protect sensitive data and protect against performance
issues. For more information, see Securing ASP.NET Health Monitoring.
See Also
Reference
healthMonitoring Element (ASP.NET Settings Schema)
System.Web.Management
Concepts
ASP.NET Web Site Layout
Other Resources
ASP.NET Health Monitoring
ASP.NET

Configuring ASP.NET Health Monitoring


The ASP.NET health monitoring system (implemented using classes in the System.Web.Management namespace) enables you to add instrumentation to Web applications—
that is, to add health monitoring events (referred to as Web events) that provide health status information. You can then configure the application with built-in or customized
monitoring providers to process this information and report on the health status and the performance characteristics of the instrumented application. For more information,
see ASP.NET Health Monitoring Overview.
You add Web events and providers to an application by configuring the healthMonitoring section in the configuration file and using built-in or custom classes for processing
the event data. The tasks you perform are:
Configure and enable Web events to monitor.
Configure and enable event providers that listen for and process various Web events.
For more information about configuration files, see ASP.NET Configuration Files.
Web Event Class Hierarchy
When a Web event is raised, an instance of the associated event class is created. Event data is collected in the properties of this object. Event providers process this data. For
more information, see "How ASP.NET Health Monitoring Works" in ASP.NET Health Monitoring Overview.
Web events can contain information about the worker process, application domain, request data, response data, application errors, configuration errors, and audit events.
Health information contained in a parent event class is inherited by any child event classes.
The relationships between the Web event classes are shown in the following illustration. They are members of the System.Web.Management namespace.
Web event class hierarchy

The further down in the hierarchy of Web event classes, the more specific the data is to the ASP.NET application. For example, derived classes expose information such as
stack traces, client IPs, and thread and process information.
For a code example of a custom Web event, see Implementing Custom ASP.NET Health Monitoring Events and Providers.
Web Event Information
To use Web events, you must understand the information they convey. The rows in the following table refer to the Web event classes. The columns refer to the information
classes, which are usually included as properties in the Web event classes. Using the table, you can decide what Web event class you need to use or inherit from to obtain the
desired information.
If your application is not running with Full trust, only the WebBaseEvent class is inheritable. This helps protect against exposing sensitive information through the information
classes listed in this table.
Web event classes WebApplicationInformation WebProcessInformation WebProcessStatistics WebRequestInformation WebThreadInformation
WebBaseEvent Data generated by this class. Not available Not available Not available Not available

WebManagementEvent Data generated by the parent c Data generated by this cla Not available Not available Not available
lass ss.

WebHeartBeatEvent Data generated by the parent c Data generated by the par Data generated by this Not available Not available
lass. ent class class.

WebRequestEvent Data generated by the parent c Data generated by the par Not available Data generated by this clas Not available
lass ent class s.

WebApplicationLifetimeEvent Data generated by the parent c Data generated by the par Not available Not available Not available
lass ent class

WebBaseErrorEvent Data generated by the parent c Data generated by the par Not available Not available Not available
lass ent class

WebErrorEvent Data generated by the parent c Data generated by the par Not available Data generated by this clas Data generated by this cla
lass ent class s. ss.
WebRequestErrorEvent Data generated by the parent c Data generated by the par Not available Data generated by the pare Data generated by the par
lass ent class nt class ent class

WebAuditEvent Data generated by the parent c Data generated by the par Not available Data generated by this clas Not available
lass ent class s.

WebSuccessAuditEvent Data generated by the parent c Data generated by the par Not available Data generated by the pare Not available
lass ent class nt class

WebAuthenticationSuccessAuditEvent Data generated by the parent c Data generated by the par Not available Data generated by the pare Not available
lass ent class nt class

WebFailureAuditEvent Data generated by the parent c Data generated by the par Not available Data generated by the pare Not available
lass ent class nt class

WebAuthenticationFailureAuditEvent Data generated by the parent c Data generated by the par Not available Data generated by the pare Not available
lass ent class nt class

WebViewStateFailureAuditEvent Data generated by the parent c Data generated by the par Not available Data generated by the pare Not available
lass ent class nt class

Provider Class Hierarchy


ASP.NET includes built-in providers that can you can use to process Web events. You can also inherit from built-in classes to create your own custom provider, subject to the
inheritance limitations listed here:
The WebEventProvider class can be inherited by applications that run under any trust level.
The BufferedWebEventProvider class can be inherited by applications that run under any trust level.
The SqlWebEventProvider class can be inherited only by applications that run under Full trust.
Other classes cannot be inherited by applications, regardless of trust level.
For more information and code examples, see the respective class overviews or Implementing Custom ASP.NET Health Monitoring Events and Providers.
The relationship between the Web provider classes of the System.Web.Management namespace is shown in the following illustration:
Web provider class hierarchy

See Also
Tasks
How to: Implement and Raise Custom ASP.NET Health Monitoring Events
How to: Implement the Health Monitoring Custom Provider Example
Reference
healthMonitoring Element (ASP.NET Settings Schema)
Concepts
Using ASP.NET Health Monitoring Events
Implementing Custom ASP.NET Health Monitoring Events and Providers
Other Resources
Configuring ASP.NET Applications
ASP.NET

Using ASP.NET Health Monitoring Events


There are two approaches you can follow when using the ASP.NET health monitoring events:
Use built-in Web event and provider classes. You will not usually need to provide custom implementations of any
ASP.NET Web event classes. Note that your application does not raise these events, the .NET Framework does. However,
you need to configure them as explained elsewhere. For more information, see
How to: Send E-mail for Health Monitoring Notifications.
Create custom classes for either Web events or providers, or both. You typically create custom Web events if you need to
append custom information to what is already provided by the built-in Web events. You typically create custom
providers if you want to deliver event data through a mechanism other than that available with the built-in providers. For
more information, see Extending ASP.NET Health Monitoring.
For additional information on custom health monitoring events, search for "health monitoring" in the MSDN Library.
Using Built-in Web Events and Providers
Using built-in Web events and providers for health monitoring is the most common strategy and requires only that you
configure the application to use the events and providers you need. In particular, you must do the following:
Add the built-in ASP.NET Web event class you need to the eventMappings element of the healthMonitoring section in the
application's configuration file.
Add the provider that consumes the event to the providers element of the healthMonitoring section.
Add an item to the rules element that defines the association between the event and the provider.
By default, the built-in ASP.NET health monitoring classes are configured in the healthMonitoring section of the root
Web.config file. The healthMonitoring section establishes the following default configuration:
All the Web event classes that derive from WebBaseEvent are specified in the eventMappings element. This section is
used to assign a friendly name to a group of event classes.
All event classes that derive from WebBaseEvent are included in at least one of the groups defined in the
eventMappings element. For a list of these classes, see the section "Web Events" in ASP.NET Health Monitoring Overview.
The EventLogWebEventProvider, WmiWebEventProvider, and SqlWebEventProvider event providers are specified in the
providers element. You can specify other built-in providers in the providers element, such as the
SimpleMailWebEventProvider, TemplatedMailWebEventProvider, or TraceWebEventProvider event providers.
The rules that associate the Web error and audit failure events to the EventLogWebEventProvider classes are specified
in the rules element. You can enable other Web events and providers by adding more rules elements. An event is
considered enabled if it is mapped to an event provider in the rules element. The eventMappings and the providers
elements must be configured for the event, but unless the two are connected in the rules element, the event is not
enabled.
Parameter values for the configured items are specified, such as those that limit the number of events that can occur,
specify the interval between two events, or specify event buffering options for the SQL and mail providers.
The following code example shows the default configuration for built-in health monitoring classes in the root Web.config file:

<healthMonitoring heartbeatInterval="0" enabled="true">


<bufferModes>
<add name="Critical Notification"
maxBufferSize="100"
maxFlushSize="20"
urgentFlushThreshold="1"
regularFlushInterval="Infinite"
urgentFlushInterval="00:01:00"
maxBufferThreads="1" />
<add name="Notification"
maxBufferSize="300"
maxFlushSize="20"
urgentFlushThreshold="1"
regularFlushInterval="Infinite"
urgentFlushInterval="00:01:00"
maxBufferThreads="1" />
<add name="Analysis"
maxBufferSize="1000"
maxFlushSize="100"
urgentFlushThreshold="100"
regularFlushInterval="00:05:00"
urgentFlushInterval="00:01:00"
maxBufferThreads="1" />
<add name="Logging"
maxBufferSize="1000"
maxFlushSize="200"
urgentFlushThreshold="800"
regularFlushInterval="00:30:00"
urgentFlushInterval="00:05:00"
maxBufferThreads="1" />
</bufferModes>
<providers>
<add
name="EventLogProvider"
type="System.Web.Management.EventLogWebEventProvider,
System.Web,Version=2.0.0.0,Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a" />
<add
ConnectionStringName="LocalSqlServer"
maxEventDetailsLength="1073741823"
buffer="false"
bufferMode="Notification"
name="SqlWebEventProvider"
type="System.Web.Management.SqlWebEventProvider,
System.Web,Version=2.0.0.0,Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a" />
<add
name="WmiWebEventProvider"
type="System.Web.Management.WmiWebEventProvider,
System.Web,Version=2.0.0.0,Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a" />
</providers>

<profiles>
<add
name="Default"
minInstances="1"
maxLimit="Infinite"
minInterval="00:01:00"
custom="" />
<add
name="Critical"
minInstances="1"
maxLimit="Infinite"
minInterval="00:00:00"
custom="" />
</profiles>

<rules>
<add
name="All Errors Default"
eventName="All Errors" provider="EventLogProvider"
profile="Default"
minInstances="1"
maxLimit="Infinite"
minInterval="00:01:00"
custom="" />
<add
name="Failure Audits Default"
eventName="Failure Audits"
provider="EventLogProvider"
profile="Default"
minInstances="1"
maxLimit="Infinite"
minInterval="00:01:00"
custom="" />
</rules>

<eventMappings>
<add
name="All Events"
type="System.Web.Management.WebBaseEvent,
System.Web,Version=2.0.0.0,Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a"
startEventCode="0"
endEventCode="2147483647" />
<add
name="Heartbeats"
type="System.Web.Management.WebHeartbeatEvent,
System.Web,Version=2.0.0.0,Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a"
startEventCode="0"
endEventCode="2147483647" />
<add
name="Application Lifetime Events"
type="System.Web.Management.WebApplicationLifetimeEvent,
System.Web,Version=2.0.0.0,Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a"
startEventCode="0"
endEventCode="2147483647" />
<add
name="Request Processing Events"
type="System.Web.Management.WebRequestEvent,
System.Web,Version=2.0.0.0,Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a"
startEventCode="0"
endEventCode="2147483647" />
<add
name="All Errors"
type="System.Web.Management.WebBaseErrorEvent,
System.Web,Version=2.0.0.0,Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a"
startEventCode="0"
endEventCode="2147483647" />
<add
name="Infrastructure Errors"
type="System.Web.Management.WebErrorEvent,
System.Web,Version=2.0.0.0,Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a"
startEventCode="0"
endEventCode="2147483647" />
<add
name="Request Processing Errors"
type="System.Web.Management.WebRequestErrorEvent,
System.Web,Version=2.0.0.0,Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a"
startEventCode="0"
endEventCode="2147483647" />
<add
name="All Audits"
type="System.Web.Management.WebAuditEvent,
System.Web,Version=2.0.0.0,Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a"
startEventCode="0" endEventCode="2147483647" />
<add
name="Failure Audits"
type="System.Web.Management.WebFailureAuditEvent, System.Web,Version=2.0.0.0,
Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
startEventCode="0"
endEventCode="2147483647" />
<add
name="Success Audits"
type="System.Web.Management.WebSuccessAuditEvent,
System.Web,Version=2.0.0.0,Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a"
startEventCode="0"
endEventCode="2147483647" />
</eventMappings>
</healthMonitoring>

Configuring a Custom Provider


If you require custom processing of Web event information, you can build your own custom health event provider. You can
implement a custom event provider by creating a class that inherits from the WebEventProvider or the
BufferedWebEventProvider class. For an example, see How to: Implement the Health Monitoring Custom Provider Example.
Creating a custom provider is the most common health monitoring customization and requires that you modify the
configuration file in the following ways:
Add the custom provider that processes the event to the providers element of the healthMonitoring section in the
configuration file.
Add an item to the rules element that defines the association between the event and the provider.
Put the assembly containing the custom provider implementation in the application's Bin subdirectory. You cannot put
the provider source code file in the App_Code subdirectory, because the health monitoring system is configured and
created before any code files in the App_Code subdirectory are compiled.
The type attribute of the providers element requires at least the class name. If the assembly is not located in the
application's Bin directory, the assembly must be strongly named and installed in the global assembly cache. In that case,
the type attribute of the providers element requires the complete strong name, as shown in the following code example,
where the Version and PublicKeyToken match your assembly:

type="Microsoft.Samples.Web.Management.SampleCustomEventProvider, Sample.SampleCustomE
ventProvider,Version=n.n.n.n,Culture=neutral, PublicKeyToken=xxxx"

The following code example associates the SampleCustomEventProvider provider with the WebHeartbeatEvent event. The
Heartbeats event is already configured in the root Web.config file.

<healthMonitoring
heartBeatInterval="1"
enabled="true">
<rules>
<add
name="Heartbeat Events"
eventName="Heartbeats"
provider="Sample Custom Event Provider"
profile="Default"
minInstances="1"
maxLimit="Infinite"
minInterval="00:01:00"
custom=""
/>
</rules>
<providers>
<add
name="Sample Custom Event Provider"
type="Microsoft.Samples.Web.Management.SampleCustomEventProvider, Sample.SampleCustom
EventProvider,Version=1.0.0.0,Culture=neutral, PublicKeyToken=xxxxxxxxxxxx"
/>
</providers>
</healthMonitoring>
Configuring a Custom Event
If you require custom health event information, you can build a custom health event. For an example, see
How to: Implement and Raise Custom ASP.NET Health Monitoring Events. Creating a custom Web event is less common than
creating a custom provider. It requires not only that you modify the configuration file but also that the custom event be
explicitly raised at the proper time.
For information on the appropriate time to raise an event and have it contain data, use the Web Event Information table in
Extending ASP.NET Health Monitoring.
To configure the event, you must do the following:
Add the custom health event class to the eventMappings element of the healthMonitoring section.
Add a rules element that defines the association between the event and the provider.
Add the assembly containing the custom Web event implementation to the Bin subdirectory of the ASP.NET application
or add the event source code file to the App_Code subdirectory.
If you use an assembly, the type attribute of the eventMappings element requires at least the class name and the
assembly file name, as shown in the following code example:

type="System.Web.Management.SampleCustomWebEvent, Sample.SampleCustomWebEvent"

If you use a source code file, you need to specify only the class name.
The following code example associates the EventLogWebEventProvider event provider with a custom event named
SampleCustomWebEvent. The EventLogProvider event provider is already configured in the root Web.config file.

<healthMonitoring
heartBeatInterval="0"
enabled="true">
<rules>
<add
name="Sample Custom Events"
eventName="SampleCustomWebEvent"
provider="EventLogProvider"
profile="Default"
minInstances="1"
maxLimit="Infinite"
minInterval="00:01:00"
custom=""
/>
</rules>
<eventMappings>
<add
name="SampleCustomWebEvent"
type="System.Web.Management.SampleCustomWebEvent, Sample.SampleCustomWebEvent,Version
=1.0.0.0,Culture=neutral, PublicKeyToken=xxxxxxxxxxxx" "
startEventCode="0"
endEventCode="2147483647"
/>
</eventMappings>
</healthMonitoring>

See Also
Tasks
How to: Send E-mail for Health Monitoring Notifications
How to: Implement and Raise Custom ASP.NET Health Monitoring Events
How to: Implement the Health Monitoring Custom Provider Example
Reference
healthMonitoring Element (ASP.NET Settings Schema)
Concepts
Extending ASP.NET Health Monitoring
Other Resources
Configuring ASP.NET Applications
ASP.NET

How to: Send E-mail for Health Monitoring Notifications


You can configure an ASP.NET application to send an e-mail notification when an ASP.NET health-monitoring Web event
occurs. To do this, you can configure one of the available e-mail Web-event providers.
The ASP.NET health-monitoring system comes with several event providers that consume health-monitoring Web-event data.
Only the EventLogWebEventProvider, SqlWebEventProvider, and WmiWebEventProvider event providers are preconfigured in
the root Web.config file. This topic describes how to add configuration settings for the e-mail Web-event providers, and how to
enable those providers to listen for certain events.
For a list of Web events that your provider can listen for, see the <eventMappings> element in your root Web.config file, or see
the "Web Events" section of ASP.NET Health Monitoring Overview.
Sending E-mail from Your Web Application
The code examples in this topic require your Web application to be configured to send e-mail messages. The following
procedure shows you how to configure your application if you already have the Simple Mail Transfer Protocol (SMTP) service
installed and configured on your Web server, and have access to an SMTP server that can deliver the e-mail messages. For
more information, see How to: Install and Configure SMTP Virtual Servers in IIS.
To configure your ASP.NET application to send e-mail
Open the Web.config file for your application and configure the <mailSettings> element within the <system.net>
section. You need to specify a delivery method in the deliveryMethod attribute of the <smtp> element, and the name
of the SMTP server in the host attribute of the <network> element. It is also recommended that you set the
defaultCredentials attribute to true. (Other attributes are available and are documented in the element topics.)
Your configuration settings might look like the following example.

<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<system.net>
<mailSettings>
<smtp deliveryMethod="Network">
<network
defaultCredentials="true"
host="smtpservername"
/>
</smtp>
</mailSettings>
</system.net>
<!-- Other configuration settings. -->
</configuration>

Configuring the Mail Providers


To configure the SimpleMailWebEventProvider Web event provider
1. Open the Web.config file for your application and add a new <providers> element within the <healthMonitoring>
element of the <system.web> section. This new providers element is where you will configure the
SimpleMailWebEventProvider Web event provider. This provider is included with the ASP.NET health-monitoring system,
but it is not preconfigured for you in the root Web.config file.
Your configuration settings might look like the following example.

<configuration>
<system.web>
<healthMonitoring enabled="true" heartbeatInterval="0">
<providers>
<add
name="exampleMailWebEventProvider"
type="System.Web.Management.SimpleMailWebEventProvider"
to="someone@contoso.com"
from="someone@contoso.com"
buffer="false"
subjectPrefix="WebEvent has fired"
/>
</providers>
</healthMonitoring>
</system.web>
<!-- Other configuration settings. -->
</configuration>

For the purposes of this procedure, disable event buffering by setting the buffer attribute to false. The name attribute is
arbitrary, and it is used to identify the provider in the next step. Change the to and from attributes to your own e-mail
address to complete the testing steps later in this procedure.
2. Add a new <rules> element within the <healthMonitoring> element. This new rules element configures the e-mail
providers to listen for all Web events.
Your configuration settings might look like the following example.

<configuration>
<system.web>
<healthMonitoring enabled="true" heartbeatInterval="0">
<!-- <providers> element from the previous step -->
<rules>
<add
name="Testing Mail Event Providers"
eventName="All Events"
provider="exampleMailWebEventProvider"
profile="Default"
minInstances="1"
maxLimit="Infinite"
minInterval="00:01:00"
custom=""
/>
</rules>
</healthMonitoring>
</system.web>
<!-- Other configuration settings. -->
</configuration>

The provider attribute is the same as the name attribute of your providers element from the previous step. The
eventName attribute of this rules element is the same as the name attribute of the preconfigured eventMappings
element in the root Web.config file. This configuration will send an e-mail message for every Web event that occurs in
your ASP.NET application. This includes, but is not limited to, application starting and stopping, configuration changes,
and requests.
For the purposes of this procedure, define your rules element and your provider element from the previous step in the
same configuration file. Alternatively, your provider element can exist in a configuration file that is higher in the chain of
configuration files, toward the root Web.config file.
3. Test your configuration by requesting a page from your application. It is possible that you have already received an e-
mail message if you changed configuration settings, which would raise an application restart event. The e-mail you
receive might have a subject line and message body similar to the following example message.

Subject: Event Notification 1, part 1: WebEvent has fired <event>


Body:
** Application Information **
---------------
Application domain: /LM/w3svc/1/ROOT/<vdir info>
Trust level: Full
Application Virtual Path: /<vdir> Application Path: <path> Machine name: <machine name
>

** Events **
---------------
<event information>
---------------

To configure the TemplatedMailWebEventProvider Web event provider


1. Open the Web.config file for your application and add a new <providers> element within the <healthMonitoring>
element of the <system.web> section. This new providers element is where you will configure the
TemplatedMailWebEventProvider Web event provider. This provider is included with the ASP.NET health-monitoring
system, but it is not pre-configured for you in the root Web.config file.
Your configuration settings might look like the following example.

<configuration>
<system.web>
<healthMonitoring enabled="true" heartbeatInterval="0">
<providers>
<add
name="exampleTemplatedMailWebEventProvider"
type="System.Web.Management.TemplatedMailWebEventProvider"
template="template.aspx"
detailedTemplateErrors="true"
to="someone@contoso.com"
from="someone@contoso.com"
buffer="true"
bufferMode="Notification"
maxMessagesPerNotification="1"
maxEventsPerMessage="1"
/>
</providers>
</healthMonitoring>
</system.web>
<!-- Other configuration settings. -->
</configuration>

For the purposes of this procedure, enable event buffering by setting the buffer attribute to false. The bufferMode
attribute value, Notification, is predefined in the root Web.config file. For more information about buffering, see
Buffering ASP.NET Health Monitoring Events.
The name attribute is arbitrary, and is used to identify the provider in the next step. Change the to and from attributes to
your own e-mail address to complete the testing steps later in this procedure.
2. Add a new <rules> element within the <healthMonitoring> element. This new rules element configures the e-mail
providers to listen for all Web events.
Your configuration settings might look like the following example.

<configuration>
<system.web>
<healthMonitoring enabled="true" heartbeatInterval="0">
<!-- <providers> element from the previous step -->
<rules>
<add
name="Testing Templated Mail Event Providers"
eventName="Request Processing Events"
provider="exampleTemplatedMailWebEventProvider"
profile="Default"
minInstances="1"
maxLimit="Infinite"
minInterval="00:00:00"
custom=""
/>
</rules>
</healthMonitoring>
</system.web>
<!-- Other configuration settings. -->
</configuration>

The provider attribute is the same as the name attribute of your providers element from the previous step. The
eventName attribute of this rules attribute is the same as the name attribute of the preconfigured eventMappings
element in the root Web.config file. This configuration will send an e-mail message for every request made to a page or
other resource in your ASP.NET application.
3. Create an e-mail template file named Template.aspx and place it in the root of your application. This file name is the
value of the template attribute of the providers element. When a request event occurs in your application, the template
file is populated with data using string expressions and sent as the notification e-mail message. For information about
using expressions, see ASP.NET Expressions Overview.
Your template file might look like the following example.

<%@ Page Language="cs" %>


<%@ Import Namespace="System.Web.Management" %>

<script runat="server">

void Page_Load()
{
MailEventNotificationInfo info = TemplatedMailWebEventProvider.CurrentNotification
;
Label0.Text = "EventsDiscardedByBuffer: " + info.EventsDiscardedByBuffer + '\n';
Label1.Text = "EventsInBuffer: " + info.EventsInBuffer + '\n';
Label2.Text = "NotificationSequence: " + info.NotificationSequence + '\n';
Label3.Text = "NotificationType: " + info.NotificationType + '\n';
Label4.Text = "EventsInNotification: " + info.EventsInNotification + '\n';
Label5.Text = "EventsRemaining: " + info.EventsRemaining + '\n';
Label6.Text = "MessagesInNotification: " + info.MessagesInNotification + '\n';
Label7.Text = "eventsDiscardedDueToMessageLimit: " + info.EventsDiscardedDueToMess
ageLimit + '\n';
Label8.Text = "messageSequence: " + info.MessageSequence + '\n';
Label9.Text = "LastNotificationUtc: " + info.LastNotificationUtc.ToLocalTime().ToS
tring() + '\n';

EventList.DataSource = info.Events;
EventList.DataBind();
}
</script>

<asp:Label runat="server" id="Label0" /><p />


<asp:Label runat="server" id="Label1" /><p />
<asp:Label runat="server" id="Label2" /><p />
<asp:Label runat="server" id="Label3" /><p />
<asp:Label runat="server" id="Label4" /><p />
<asp:Label runat="server" id="Label5" /><p />
<asp:Label runat="server" id="Label6" /><p />
<asp:Label runat="server" id="Label7" /><p />
<asp:Label runat="server" id="Label8" /><p />
<asp:Label runat="server" id="Label9" /><p />

<asp:DataList id="EventList" runat="server">


<ItemTemplate>
Event Received
Sequence: <%# DataBinder.Eval(Container.DataItem, "EventSequence") %><br>
Details: <%# Container.DataItem.ToString() %>
</ItemTemplate>
</asp:DataList>

4. Test your configuration by requesting a page from your application. You should quickly receive an e-mail message that
includes a subject line and message body similar to the following example message.

Subject: Event Notification 1, part 1: <event>


Body:
EventsDiscardedByBuffer: 0
EventsInBuffer: 0
NotificationSequence: 1
NotificationType: Flush
EventsInNotification: 1
EventsRemaining: 0
MessagesInNotification: 1
eventsDiscardedDueToMessageLimit: 0
messageSequence: 1
LastNotificationUtc: 1/1/0001 12:00:00 AM
Event Received Sequence: 1
Details:
<event information>

See Also
Reference
healthMonitoring Element (ASP.NET Settings Schema)
<eventMappings>
<providers>
<rules>
<smtp>
Concepts
ASP.NET Health Monitoring Overview
Buffering ASP.NET Health Monitoring Events
Configuring ASP.NET Health Monitoring
ASP.NET

Buffering ASP.NET Health Monitoring Events


You can configure the SQL and mail health monitoring event providers (SqlWebEventProvider, SimpleMailWebEventProvider,
and TemplatedMailWebEventProvider) to use event buffering. This helps reduce the impact on application performance of
sending frequent e-mail messages or performing frequent SQL server insertions. Buffering health monitoring events also
protects the SMTP server and SQL Server from heavy loads due to high event volume.
SQL Event Provider Buffering
If you enable buffering for the SQL event provider, the provider buffers event information according to the specified buffer
mode before inserting the event information into the database in a batch.
By default, the SqlWebEventProvider provider is not configured to use buffering, and each time an event is raised, its
information is immediately inserted into the database. You can override this default setting by enabling buffering in the
providers element of the Web.config file where the SQL provider is specified; you do so by setting the buffer attribute of the
add element to true. If you configure your own SQL provider (that is, you do not use SqlWebEventProvider), and if you do
not specify a value for the buffer attribute, then the default is true.
You can customize buffering behavior by selecting a predefined buffering mode. Alternatively, you can add custom elements to
the bufferModes collection. Each element defines properties such as the size of the buffer and the frequency for flushing the
buffer. You can then configure the provider to use one of the buffer modes you have defined.
The example that follows shows the configuration settings for the SQL event provider with buffering enabled.
Note
The Analysis bufferModes element is already configured in the root Web.config file and does not need to be declared agai
n in an application-level Web.config file. The SqlWebEventProvider providers element is also configured in the root Web.con
fig file, but the buffer attribute is set to false and the bufferMode attribute is set to Notification. Therefore the providers
element shown in the example needs to be declared in an application-level Web.config file, and you must use a clear or
remove element to remove the higher-level configuration for the SqlWebEventProvider provider.

In the example, the SQL event provider is configured to use the Analysis buffer mode when buffering is enabled, which is
defined in the bufferModes element. In this mode, the provider flushes the event information every 5 minutes. It flushes up to
100 events per notification, and buffers up to 1000 events in case of a sudden rise in the frequency of events. The provider
guarantees not to send events more often then once every minute.

<healthMonitoring>
<providers>
<clear/>
<add
ConnectionStringName="LocalSqlServer"
maxEventDetailsLength="1073741823"
buffer="true"
bufferMode="Analysis"
name="SqlWebEventProvider"
type="System.Web.Management.SqlWebEventProvider,System.Web, Version=2.0.0.0,Culture=n
eutral,PublicKeyToken=b03f5f7f11d50a3a"
/>
</providers>
<bufferModes>
<add
name="Analysis"
maxBufferSize="1000"
maxFlushSize="100"
urgentFlushThreshold="100"
regularFlushInterval="00:05:00"
urgentFlushInterval="00:01:00"
maxBufferThreads="1"
/>
</bufferModes>
</healthMonitoring>
Email Event Provider Buffering
If you enable buffering for the mail event providers, the providers buffer events before sending e-mail messages as event
notifications. If you configure an email event provider and do not specify a value for the buffer attribute of the add element for
the mail event provider, the default is true. You can disable buffering by setting the buffer attribute to false.
You can customize buffering behavior by selecting a predefined buffering mode. Alternatively, you can add custom elements to
the bufferModes collection. Each element defines properties such as the size of the buffer and the frequency for flushing the
buffer. You can then configure the provider to use one of the buffer modes you have defined. It is recommended that you use
the CriticalNotification mode.
The following example shows the configuration settings for the email event providers with buffering disabled for the
SimpleMailWebEventProvider and enabled for the TemplatedMailWebEventProvider. The
TemplatedMailWebEventProvider provider is configured to use the CriticalNotification buffer mode, which is already
configured in the root Web.config file. In CriticalNotification mode, the provider attempts to flush all event information as
soon as events are received, but the flush attempt will not succeed more frequently than every minute to avoid putting an
undue load on the e-mail server. The messages are of manageable size (at most the information for 20 events).
If the health monitoring system receives more event information than the maximum allowed, the oldest events will start being
dropped when new events are generated. The health monitoring system tries to avoid dropping events by flushing more
frequently when the buffer is getting full, but it will not attempt to send out any information for events if they have been
dropped (other than a notification in the next flush that events were dropped). Newer events will be delayed at most five
minutes if the provider is under heavy load, assuming they are not dropped because of a full buffer.

<healthMonitoring>
<providers>
<!-- mail provider with attributes that are always relevant -->
<add
name="SimpleMailWebEventProvider"
type="System.Web.Management.SimpleMailWebEventProvider"
to="SystemAdministrator@contoso.com"
from="HealthMonitoring@contoso.com"
buffer="false"
/>
<!-- mail provider with attributes that are relevant only
when buffering is enabled -->
<add
name="SampleTemplatedMailWebEventProvider"
type="System.Web.Management.TemplatedMailWebEventProvider"
to="SystemAdministrator@contoso.com"
from="HealthMonitoring@contoso.com"
buffer="true"
bufferMode="Critical Notification"
template="Template.aspx" />
</providers>
<bufferModes>
<add
name="Critical Notification"
maxBufferSize="100" maxFlushSize="20"
urgentFlushThreshold="1"
regularFlushInterval="Infinite"
urgentFlushInterval="00:01:00"
maxBufferThreads="1"
/>
</bufferModes>
</healthMonitoring>

For the example to work, you must configure an SMTP server in the configuration file using an element such as the following.
For more information, see <mailSettings> Element (Network Settings).

<system.net>
<mailSettings>
<smtp deliveryMethod="Network">
<network
defaultCredentials="true"
host="127.0.0.1"
port="25"
username="username"
password="password" />
</smtp>
</mailSettings>
</system.net>

Note
There are security risks associated with storing clear-text passwords in a configuration file. If you keep credentials in the confi
guration file, you should encrypt the contents of the <mailSettings> configuration element using protected configuration. Fo
r more information, see Encrypting Configuration Information Using Protected Configuration.

Buffer Mode Settings


You can set the following attributes of the add Element for bufferMode for healthMonitoring (ASP.NET Settings Schema)
element in the bufferModes element to specify buffer behavior:
regularFlushInterval The regular event information flush interval.
urgentFlushThreshold A value specifying the number of events whose information should be buffered before the
buffer is flushed.
The following settings specify the guarantees made by the provider to the event receiver.
maxBufferSize A number specifying the maximum number of events whose information the buffer will hold. If the
number of events in the buffer would exceed this value, older events are dropped.
maxFlushSize The maximum number of events whose information the provider will flush at a time.
urgentFlushInterval The minimum time that the provider will wait before performing another urgent flush. If the time
represented by the urgentFlushInterval property has not passed since the last flush but the buffer is full, information
from older events will be discarded from the buffer by the newer information. The provider keeps track of how many
events were discarded, and includes a warning in the next event information that is sent.

See Also
Reference
<bufferModes>
<providers>
SqlWebEventProvider
SimpleMailWebEventProvider
TemplatedMailWebEventProvider
Concepts
ASP.NET Health Monitoring Overview
ASP.NET

Using WMI to Deliver ASP.NET Health Monitoring Events


One way to monitor the ASP.NET health events is to use the Windows Management Instrumentation (WMI) event provider,
WmiWebEventProvider. This provider converts Web health monitoring events (Web events) to WMI events. WMI provides a
standard object model in which the entities you want to monitor can be represented as objects. These entities represent
computers, network cards, printers, software applications, and so on. These entities are mapped into the WMI object model so
that they can be monitored by custom applications. The following illustration shows the relationship between the ASP.NET
Web events, WMI, and a consumer application that listens for WMI events.
Relationship between ASP.NET and WMI

Connection Between Health Events and WMI


ASP.NET health monitoring provides the infrastructure for the connection between health events and WMI. It does so by
mapping these events into the WMI classes so that they can be treated as WMI objects. It also provides the support to process
the health events and dispatch them to the WMI system. For details about how to map ASP.NET events to WMI, see
Walkthrough: Listening for WMI Events in ASP.NET Health Monitoring. For more information about WMI, see
Windows Management Instrumentation in the Platform SDK on MSDN.
The following list describes the steps required to monitor health events with WMI:
1. Define the mapping between the Web event classes and WMI objects. This step is already done for you for each of the
standard Web event classes. These mappings are contained in the Managed Object Format (MOF) file for ASP.NET,
%SystemRoot%\Microsoft.NET\Framework\<version>\aspnet.mof file.
Note
All custom events are mapped to the base event type in WMI. It is not possible to map a custom ASP.NET health monito
ring event to an arbitrary WMI event.

For example, the following code shows the definition of the WMI class mapped to the WebHeartBeatEvent type.

class HeartbeatEvent : ManagementEvent {


/*
* ProcessStatistics
*/
DATETIME ProcessStartTime;
sint32 ThreadCount;
sint64 WorkingSet;
sint64 PeakWorkingSet;
sint64 ManagedHeapSize;
sint32 AppdomainCount;
sint32 RequestsExecuting;
sint32 RequestsQueued;
sint32 RequestsRejected;
};

For more information about MOF files, see Managed Object Format in the WMI SDK in MSDN.
2. Define an ASP.NET health monitoring provider responsible for processing the events.
The standard provider is WmiWebEventProvider, which is already configured by default in the healthMonitoring
section of the root Web.config file using the following code.

<providers>
<add
name="WmiWebEventProvider"
type="System.Web.Management.WmiWebEventProvider,System.Web, Version=2.0.0.0,Cultur
e=neutral,PublicKeyToken=b03f5f7f11d50a3a"
/>
</providers>

3. Enter the appropriate settings in the healthMonitoring section of the configuration file to create the association
between Web event classes and the WMI event provider, WmiWebEventProvider.
By default, there are no Web events subscribed to by the WMI event provider. You can use the following code in an
application-level Web.config file to subscribe WMI event provider to all Web events. The All Events event type is
configured by default in the eventMappings element in the root Web.config file, and is mapped to the WebBaseEvent
class.

<rules>
<add
name="Testing Wmi"
eventName="All Events"
provider="WmiWebEventProvider"
profile="Critical"
/>
</rules>

4. Create an application to listen for WMI events, or use a third-party application.


The code example in Walkthrough: Listening for WMI Events in ASP.NET Health Monitoring creates a console application
that displays event information whenever a Web event is raised.
Customizing the WMI Health Events Infrastructure
When a Web event occurs, ASP.NET health monitoring dispatches it to the WmiWebEventProvider object that processes it,
fills in the appropriate data according to the related MOF class definition, and then dispatches this data to the WMI system,
using a call to unmanaged code.
The only customization option for sending Web events to WMI is if you create your own custom application that consumes
ASP.NET health monitoring events after they have been issued as WMI events. In this case, the only configuration change you
need to make is to configure a new rules element as listed above. Your application will listen for the ASP.NET health events in
the form of WMI events, as issued by the operating system. For more information, see
Walkthrough: Listening for WMI Events in ASP.NET Health Monito

You might also like