0% found this document useful (0 votes)
934 views136 pages

Welcome To The ASP - Bookmarks

The document provides an introduction and overview of the ASP.NET QuickStart tutorial. It explains that the QuickStart samples are designed to acquaint developers with ASP.NET syntax, architecture, and features in a short and easy to understand way. By completing the QuickStart, developers will become familiar with ASP.NET syntax, architecture, features, and best practices. It also provides information on the expected expertise level, how to work with the samples, and where to find additional resources.

Uploaded by

api-3835536
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
934 views136 pages

Welcome To The ASP - Bookmarks

The document provides an introduction and overview of the ASP.NET QuickStart tutorial. It explains that the QuickStart samples are designed to acquaint developers with ASP.NET syntax, architecture, and features in a short and easy to understand way. By completing the QuickStart, developers will become familiar with ASP.NET syntax, architecture, features, and best practices. It also provides information on the expected expertise level, how to work with the samples, and where to find additional resources.

Uploaded by

api-3835536
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd

1

Welcome to the [Link] QuickStart Tutorial

The [Link] QuickStart is a series of [Link] samples and supporting commentary designed to
quickly acquaint developers with the syntax, architecture, and power of the [Link] Web
programming framework. The QuickStart samples are designed to be short, easy-to-understand
illustrations of [Link] features. By the time you have completed the QuickStart tutorial, you will
be familiar with:

• [Link] Syntax. While some of the [Link] syntax elements will be familiar to veteran
ASP developers, several are unique to the new framework. The QuickStart samples cover
each element in detail.
• [Link] Architecture and Features. The QuickStart introduces the features of [Link]
that enable developers to build interactive, world-class applications with much less time
and effort than ever before.
• Best Practices. The QuickStart samples demonstrate the best ways to exercise the power
of [Link] while avoiding potential pitfalls along the way.

What Level of Expertise Is Assumed in the QuickStart?


If you have never developed Web pages before, the QuickStart is not for you. You should be
fluent in HTML and general Web development terminology. You do not need previous ASP
experience, but you should be familiar with the concepts behind interactive Web pages, including
forms, scripts, and data access.

Working with the QuickStart Samples


The QuickStart samples are best experienced in the order in which they are presented. Each
sample builds on concepts discussed in the preceding sample. The sequence begins with a simple
form submittal and builds up to integrated application scenarios.

Additional Information
For additional [Link] samples, articles, code downloads, discussions or FAQs consult The Official
Microsoft [Link] Site .
For additional technical support for the .NET Framework SDK samples consult the Microsoft
Support Knowledge Base.

What is [Link]?

[Link] is a programming framework built on the common language runtime that can be used on
a server to build powerful Web applications. [Link] offers several important advantages over
previous Web development models:

• Enhanced Performance. [Link] is compiled common language runtime code running


on the server. Unlike its interpreted predecessors, [Link] can take advantage of early
binding, just-in-time compilation, native optimization, and caching services right out of
the box. This amounts to dramatically better performance before you ever write a line of
code.

• World-Class Tool Support. The [Link] framework is complemented by a rich toolbox


and designer in the Visual Studio integrated development environment. WYSIWYG
editing, drag-and-drop server controls, and automatic deployment are just a few of the
features this powerful tool provides.

• Power and Flexibility. Because [Link] is based on the common language runtime,
the power and flexibility of that entire platform is available to Web application
developers. The .NET Framework class library, Messaging, and Data Access solutions are
all seamlessly accessible from the Web. [Link] is also language-independent, so you
2
can choose the language that best applies to your application or partition your
application across many languages. Further, common language runtime interoperability
guarantees that your existing investment in COM-based development is preserved when
migrating to [Link].

• Simplicity. [Link] makes it easy to perform common tasks, from simple form
submission and client authentication to deployment and site configuration. For example,
the [Link] page framework allows you to build user interfaces that cleanly separate
application logic from presentation code and to handle events in a simple, Visual Basic -
like forms processing model. Additionally, the common language runtime simplifies
development, with managed code services such as automatic reference counting and
garbage collection.

• Manageability. [Link] employs a text-based, hierarchical configuration system,


which simplifies applying settings to your server environment and Web applications.
Because configuration information is stored as plain text, new settings may be applied
without the aid of local administration tools. This "zero local administration" philosophy
extends to deploying [Link] Framework applications as well. An [Link] Framework
application is deployed to a server simply by copying the necessary files to the server.
No server restart is required, even to deploy or replace running compiled code.

• Scalability and Availability. [Link] has been designed with scalability in mind, with
features specifically tailored to improve performance in clustered and multiprocessor
environments. Further, processes are closely monitored and managed by the [Link]
runtime, so that if one misbehaves (leaks, deadlocks), a new process can be created in
its place, which helps keep your application constantly available to handle requests.

• Customizability and Extensibility. [Link] delivers a well-factored architecture that


allows developers to "plug-in" their code at the appropriate level. In fact, it is possible
to extend or replace any subcomponent of the [Link] runtime with your own custom-
written component. Implementing custom authentication or state services has never
been easier.

• Security. With built in Windows authentication and per-application configuration, you


can be assured that your applications are secure.

The remainder of the QuickStart presents practical examples of these concepts.

Language Support

The Microsoft .NET Platform currently offers built-in support for three languages: C#, Visual
Basic, and JScript.

The exercises and code samples in this tutorial demonstrate how to use C#, Visual Basic, and
JScript to build .NET applications. For information regarding the syntax of the other languages,
refer to the complete documentation for the .NET Framework SDK.

The following table is provided to help you understand the code samples in this tutorial as well as
the differences between the three languages:

Variable Declarations

Dim x As Integer
Dim s As String
3
Dim s1, s2 As String
Dim o 'Implicitly Object
Dim obj As New Object()
Public name As String
C# VB JScript

Statements

[Link]("foo")
C# VB JScript

Comments

' This is a comment

' This
' is
' a
' multiline
' comment

C# VB JScript

Accessing Indexed Properties

Dim s, value As String


s = [Link]("Name")
value = [Link]("Key").Value

'Note that default non-indexed properties


'must be explicitly named in VB
C# VB JScript

Declaring Indexed Properties

' Default Indexed Property


Public Default ReadOnly Property DefaultProperty(Name As String) As String
Get
Return CStr(lookuptable(Name))
End Get
End Property

C# VB JScript

Declaring Simple Properties


4
Public Property Name As String

Get
...
Return ...
End Get

Set
... = Value
End Set

End Property
C# VB JScript

Declare and Use an Enumeration

' Declare the Enumeration


Public Enum MessageSize

Small = 0
Medium = 1
Large = 2
End Enum

' Create a Field or Property


Public MsgSize As MessageSize

' Assign to the property using the Enumeration values


MsgSize = small
C# VB JScript

Enumerating a Collection

Dim S As String
For Each S In Coll
...
Next
C# VB JScript

Declare and Use Methods

' Declare a void return function


Sub VoidFunction()
...
End Sub

' Declare a function that returns a value


Function StringFunction() As String
...
Return CStr(val)
End Function

' Declare a function that takes and returns values


Function ParmFunction(a As String, b As String) As String
...
5
Return CStr(A & B)
End Function

' Use the Functions


VoidFunction()
Dim s1 As String = StringFunction()
Dim s2 As String = ParmFunction("Hello", "World!")
C# VB JScript

Custom Attributes

' Stand-alone attribute


<STAThread>

' Attribute with parameters


<Obsolete("Obsolete message here")>

' Attribute with named parameters


<Obsolete("Obsolete message here", true)>
C# VB JScript

Arrays

Dim a(2) As String


a(0) = "1"
a(1) = "2"
a(2) = "3"

Dim a2(2,2) As String


a(0,0) = "1"
a(1,0) = "2"
a(2,0) = "3"

C# VB JScript

Initialization

Dim s As String = "Hello World"


Dim i As Integer = 1
Dim a() As Double = { 3.00, 4.00, 5.00 }
C# VB JScript

If Statements

If Not ([Link] = Nothing)


...
End If
C# VB JScript

Case Statements
6
Select Case FirstName
Case "John"
...
Case "Paul"
...
Case "Ringo"
...
Case Else
...
End Select

C# VB JScript

For Loops

Dim I As Integer
For I = 0 To 2
a(I) = "test"
Next
C# VB JScript

While Loops

Dim I As Integer
I = 0
Do While I < 3
[Link]([Link]())
I += 1
Loop
C# VB JScript

Exception Handling

Try
' Code that throws exceptions
Catch E As OverflowException
' Catch a specific exception
Catch E As Exception
' Catch the generic exceptions
Finally
' Execute some cleanup code
End Try
C# VB JScript

String Concatenation

' Using Strings


Dim s1, s2 As String
s2 = "hello"
s2 &= " world"
7
s1 = s2 & " !!!"

' Using StringBuilder class for performance


Dim s3 As New StringBuilder()
[Link]("hello")
[Link](" world")
[Link](" !!!")
C# VB JScript

Event Handler Delegates

Sub MyButton_Click(Sender As Object,


E As EventArgs)
...
End Sub
C# VB JScript

Declare Events

' Create a public event


Public Event MyEvent(Sender as Object, E as EventArgs)

' Create a method for firing the event


Protected Sub OnMyEvent(E As EventArgs)
RaiseEvent MyEvent(Me, E)
End Sub
C# VB JScript

Add or Remove Event Handlers to Events

AddHandler [Link], AddressOf [Link]


RemoveHandler [Link], AddressOf [Link]
C# VB JScript

Casting

Dim obj As MyObject


Dim iObj As IMyObject
obj = Session("Some Value")
iObj = CType(obj, IMyObject)

C# VB JScript

Conversion

Dim i As Integer
Dim s As String
Dim d As Double

i = 3
8
s = [Link]()
d = CDbl(s)

' See also CDbl(...), CStr(...), ...


C# VB JScript

Class Definition with Inheritance

Imports System

Namespace MySpace

Public Class Foo : Inherits Bar

Dim x As Integer

Public Sub New()


[Link]()
x = 4
End Sub

Public Sub Add(x As Integer)


Me.x = Me.x + x
End Sub

Overrides Public Function GetNum() As Integer


Return x
End Function

End Class

End Namespace

' vbc /out:[Link] /t:library


' [Link]
C# VB JScript

Implementing an Interface

Public Class MyClass : Implements IEnumerable


...

Function IEnumerable_GetEnumerator() As IEnumerator _


Implements [Link]
...
End Function
End Class
C# VB JScript

Class Definition with a Main Method

Imports System

Public Class ConsoleVB

Public Sub New()


9
[Link]()
[Link]("Object Created")
End Sub

Public Shared Sub Main()


[Link]("Hello World")
Dim cvb As New ConsoleVB
End Sub

End Class

' vbc /out:[Link] /t:exe [Link]


C# VB JScript

Standard Module

Imports System

Public Module ConsoleVB

Public Sub Main()


[Link]("Hello World")
End Sub

End Module

' vbc /out:[Link] /t:exe [Link]


Introducing Web Forms
What is [Link] Web Forms?
Writing Your First Web Forms Page
Using ASP <%%> Render Blocks
Introduction to Server Controls
Handling Server Control Events
Using Custom Server Controls
Lists, Data, and Databinding
Form Validation Controls
Code-Behind Web Forms
Section Summary
What is [Link] Web Forms?

The [Link] Web Forms page framework is a scalable common language runtime programming
model that can be used on the server to dynamically generate Web pages.

Intended as a logical evolution of ASP ([Link] provides syntax compatibility with existing
pages), the [Link] Web Forms framework has been specifically designed to address a number
of key deficiencies in the previous model. In particular, it provides:

• The ability to create and use reusable UI controls that can encapsulate common
functionality and thus reduce the amount of code that a page developer has to write.
• The ability for developers to cleanly structure their page logic in an orderly fashion (not
"spaghetti code").
• The ability for development tools to provide strong WYSIWYG design support for pages
(existing ASP code is opaque to tools).

This section of the QuickStart provides a high-level code walkthrough of some key [Link] Web
Forms features. Subsequent sections of the QuickStart drill down into more specific details.
10

Writing Your First Web Forms Page

[Link] Web Forms pages are text files with an .aspx file name extension. They can be deployed
throughout an IIS virtual root directory tree. When a browser client requests .aspx resources, the
[Link] runtime parses and compiles the target file into a .NET Framework class. This class can
then be used to dynamically process incoming requests. (Note that the .aspx file is compiled only
the first time it is accessed; the compiled type instance is then reused across multiple requests).

An [Link] page can be created simply by taking an existing HTML file and changing its file name
extension to .aspx (no modification of code is required). For example, the following sample
demonstrates a simple HTML page that collects a user's name and category preference and then
performs a form postback to the originating page when a button is clicked:

VB [Link]
[Run Sample] | [View
Source]

Important: Note that nothing happens yet when you click the Lookup button. This is because
the .aspx file contains only static HTML (no dynamic content). Thus, the same HTML is sent back
to the client on each trip to the page, which results in a loss of the contents of the form fields
(the text box and drop-down list) between requests.

Using ASP <% %> Render Blocks

[Link] provides syntax compatibility with existing ASP pages. This includes support for <% %>
code render blocks that can be intermixed with HTML content within an .aspx file. These code
blocks execute in a top-down manner at page render time.

The below example demonstrates how <% %> render blocks can be used to loop over an HTML
block (increasing the font size each time):

VB [Link]
[Run Sample] | [View
Source]

Important: Unlike with ASP, the code used within the above <% %> blocks is actually
compiled--not interpreted using a script engine. This results in improved runtime execution
performance.

[Link] page developers can utilize <% %> code blocks to dynamically modify HTML output
much as they can today with ASP. For example, the following sample demonstrates how <% %>
code blocks can be used to interpret results posted back from a client.
11

VB [Link]
[Run Sample] | [View
Source]

Important: While <% %> code blocks provide a powerful way to custom manipulate the text
output returned from an [Link] page, they do not provide a clean HTML programming model.
As the sample above illustrates, developers using only <% %> code blocks must custom manage
page state between round trips and custom interpret posted values.

Introduction to [Link] Server Controls

In addition to (or instead of) using <% %> code blocks to program dynamic content, [Link]
page developers can use [Link] server controls to program Web pages. Server controls are
declared within an .aspx file using custom tags or intrinsic HTML tags that contain a
runat="server" attribute value. Intrinsic HTML tags are handled by one of the controls in the
[Link] namespace. Any tag that doesn't explicitly map to one of the
controls is assigned the type of [Link].

The following sample uses four server controls: <form runat=server>, <asp:textbox
runat=server>, <asp:dropdownlist runat=server>, and <asp:button runat=server>. At
run time these server controls automatically generate HTML content.

VB [Link]
[Run Sample] | [View
Source]

Important: Note that these server controls automatically maintain any client-entered values
between round trips to the server. This control state is not stored on the server (it is instead
stored within an <input type="hidden"> form field that is round-tripped between requests).
Note also that no client-side script is required.

In addition to supporting standard HTML input controls, [Link] enables developers to utilize
richer custom controls on their pages. For example, the following sample demonstrates how the
<asp:adrotator> control can be used to dynamically display rotating ads on a page.

VB [Link]
[Run Sample] | [View
12
Source]

Important: A detailed listing of all built-in server controls can be found in the Web Forms Control
Reference section of this QuickStart.

Handling Server Control Events

Each [Link] server control is capable of exposing an object model containing properties,
methods, and events. [Link] developers can use this object model to cleanly modify and
interact with the page.

The following example demonstrates how an [Link] page developer can handle the OnClick
event from the <asp:button runat=server> control to manipulate the Text property of the
<asp:label runat=server> control.

VB [Link]
[Run Sample] | [View
Source]

This simple sample is functionally equivalent to the "Intro3" sample demonstrated earlier in this
section. Note, however, how much cleaner and easier the code is in this new server-control-based
version.

Using Custom Server Controls

[Link] ships with 45 built-in server controls that can be used out of the box (for details, see
Web Forms Controls Reference). In addition to using the built-in [Link] controls, developers
also can use controls developed by third-party vendors.

The following sample shows a simple calendar control. The Calendar control is declared within
the page using an <acme:calendar runat=server> tag. Note that the <% Register %>
directive at the top of the page is responsible for registering the "Acme" XML tag prefix with the
"Acme" code namespace of the control implementation. The [Link] page parser will then utilize
this namespace to load the Calendar control class instance at run time.

VB [Link]
[Run Sample] | [View
Source]

The Calendar control in this sample has been designed to perform "uplevel-like" processing on
Internet Explorer 5.5 or higher and "downlevel" processing on all other browsers. This browser
sniffing is nowhere near as complex as that provided by the [Link] built-in server controls. For
Internet Explorer 5.5 or higher browsers it generates DHTML output. This DHTML output does not
13
require round trips back to the server when doing day selections and month navigations. For all
other browsers the control generates standard HTML 3.2. This HTML 3.2 does require round trips
back to the server to handle client-side user interactions.

Important: The code that a page developer writes is identical regardless of whether an "uplevel"
or "downlevel" browser is used to access the page. The Calendar control itself encapsulates all of
the logic required to handle the two scenarios.

Lists, Data, and Data Binding

[Link] ships with a built-in set of data grid and list controls. These can be used to provide
custom UI driven from queries against a database or other data source. For example, the
following sample demonstrates how a <asp:datagrid runat=server> control can be used to
databind book information collected using a SQL database query.

VB [Link]
[Run Sample] | [View
Source]

The <asp:datagrid runat=server> control provides an easy way to quickly display data results
using a traditional grid-control UI. Alternatively, [Link] developers can use the <asp:DataList
runat=server> control and a custom ItemTemplate template to customize data information,
as in the following sample.

VB [Link]
[Run Sample] | [View
Source]

Note that the <asp:datalist runat=server> control enables end users to exactly control the
structure and layout of each item within the list (using the ItemTemplate template property).
The control also automatically handles the two-column wrapping of content (users can control the
number of columns using the RepeatColumns property on the data list).

The following sample provides an alternate view of the <asp:datalist runat=server> control.

VB [Link]
[Run Sample] | [View
14
Source]

Note that the control, data model, and page user in this example are exactly the same as those
in the previous sample. The only difference is that, here, alternative templates are declaratively
supplied to the code.

Form Validation Controls

The [Link] Web Forms page framework provides a set of validation server controls that provide
an easy-to-use but powerful way to check input forms for errors, and, if necessary, display
messages to the user.

Validation controls are added to an [Link] page like other server controls. There are controls for
specific types of validation, such as range checking or pattern matching, plus a
RequiredFieldValidator that ensures that a user does not skip an entry field.

The following example demonstrates how to use two <asp:requiredfieldvalidator


runat=server> controls on a page to validate the contents of the TextBox and DropDownList
controls.

VB [Link]
[Run Sample] | [View
Source]

Note that the validation controls have both uplevel and downlevel client support. Uplevel
browsers perform validation on the client (using JavaScript and DHTML) and on the server.
Downlevel browsers perform the validation only on the server. The programming model for the
two scenarios is identical.

Note that [Link] page developers can optionally check the [Link] property at run time
to determine whether all validation server controls on a page are currently valid. This provides a
simple way to determine whether or not to proceed with business logic. For example, the
following sample performs a [Link] check before executing a database lookup on the
specified category.

VB [Link]
[Run Sample] | [View
Source]

Code-Behind Web Forms


15
[Link] supports two methods of authoring dynamic pages. The first is the method shown in
the preceding samples, where the page code is physically declared within the originating .aspx
file. An alternative approach--known as the code-behind method--enables the page code to be
more cleanly separated from the HTML content into an entirely separate file.

The following sample demonstrates the use of the code-behind method of writing [Link] page
code.

VB [Link]
[Run Sample] | [View
Source]

Section Summary

1. [Link] Web Forms provide an easy and powerful way to build dynamic Web UI.
2. [Link] Web Forms pages can target any browser client (there are no script library or
cookie requirements).
3. [Link] Web Forms pages provide syntax compatibility with existing ASP pages.
4. [Link] server controls provide an easy way to encapsulate common functionality.
5. [Link] ships with 45 built-in server controls. Developers can also use controls built by
third parties.
6. [Link] server controls can automatically project both uplevel and downlevel HTML.
7. [Link] templates provide an easy way to customize the look and feel of list server
controls.
8. [Link] validation controls provide an easy way to do declarative client or server data
validation.

Working with Server Controls


Declaring Server Controls
Manipulating Server Controls
Handling Control Action Events
Handling Multiple Control Action Events
Performing Page Navigation (Scenario 1)
Performing Page Navigation (Scenario 2)
This section of the QuickStart illustrates some common core concepts and common actions
performed by end users when using [Link] server controls within a page.

Declaring Server Controls

[Link] server controls are identified within a page using declarative tags that contain a
runat="server" attribute. The following example declares three <asp:label runat="server">
server controls and customizes the text and style properties of each one individually.
16
VB [Link]
[Run Sample] | [View
Source]

Manipulating Server Controls

You can programmatically identify an individual [Link] server control within a page by providing
it with an id attribute. You can use this id reference to programmatically manipulate the server
control's object model at run time. For example, the following sample demonstrates how a page
developer could programmatically set an <asp:label runat="server"> control's Text property
within the Page_Load event.

VB [Link]
[Run Sample] | [View
Source]

Handling Control Action Events

[Link] server controls can optionally expose and raise server events, which can be handled by
page developers. A page developer may accomplish this by declaratively wiring an event to a
control (where the attribute name of an event wireup indicates the event name and the attribute
value indicates the name of a method to call). For example, the following code example
demonstrates how to wire an OnClick event to a button control.

VB [Link]
[Run Sample] | [View
Source]

Handling Multiple Control Action Events

Event handlers provide a clean way for page developers to structure logic within an [Link]
page. For example, the following sample demonstrates how to wire and handle four button events
on a single page.
17

VB [Link]
[Run Sample] | [View
Source]

Performing Page Navigation (Scenario 1)

Page navigation among multiple pages is a common scenario in virtually all Web applications. The
following sample demonstrates how to use the <asp:hyperlink runat=server> control to
navigate to another page (passing custom query string parameters along the way). The sample
then demonstrates how to easily get access to these query string parameters from the target
page.

VB [Link]
[Run Sample] | [View
Source]

Performing Page Navigation (Scenario 2)

Not all page navigation scenarios are initiated through hyperlinks on the client. Client-side page
redirects or navigations can also be initiated from the server by an [Link] page developer by
calling the [Link](url) method. This is typically done when server-side validation is
required on some client input before the navigation actually takes place.

The following sample demonstrates how to use the [Link] method to pass
parameters to another target page. It also demonstrates how to easily get access to these
parameters from the target page.

VB [Link]
[Run Sample] | [View
Source]
Applying Styles to Controls
18
Applying Styles to HTMLControls
Applying Styles to Web Controls
Section Summary
The Web is a flexible environment for user interfaces, with extreme variations in the look and feel
of different Web sites. The widespread adoption of cascading style sheets (CSS) is largely
responsible for the rich designs encountered on the Web. All of [Link]'s HTML server controls
and Web server controls have been designed to provide first-class support for CSS styles. This
section discusses how to use styles in conjunction with server controls and demonstrates the very
fine control over the look and feel of your Web Forms that they provide.

Applying Styles to HTML Controls

Standard HTML tags support CSS through a style attribute, which can be set to a semicolon-
delimited list of attribute/value pairs. For more information about the CSS attributes supported by
the Internet Explorer browser, see MSDN Web Workshop's CSS Attributes Reference page. All of
the [Link] HTML server controls can accept styles in exactly the same manner as standard
HTML tags. The following example illustrates a number of styles applied to various HTML server
controls. If you view the source code on the page returned to the client, you will see that these
styles are passed along to the browser in the control's rendering.

VB [Link]
[Run Sample] | [View
Source]

CSS also defines a class attribute, which can be set to a CSS style definition contained in a
<style>...</style> section of the document. The class attribute makes it easy to define styles
once and apply them to several tags without having to redefine the style itself. Styles on HTML
server controls also can be set in this manner, as demonstrated in the following sample.

VB [Link]
[Run Sample] | [View
Source]

When an [Link] page is parsed, the style information is populated into a Style property (of
type CssStyleCollection) on the [Link] class. This
property is essentially a dictionary that exposes the control's styles as a string-indexed collection
of values for each style-attribute key. For example, you could use the following code to set and
subsequently retrieve the width style attribute on an HtmlInputText server control.

<script language="VB" runat="server" >

Sub Page_Load(Sender As Object, E As EventArgs)


19
[Link]("width") = "90px"
[Link]([Link]("width"))
End Sub

</script>

<input type="text" id="MyText" runat="server"/>


C# VB JScript

This next sample shows how you can programmatically manipulate the style for an HTML server
control using this Style collection property.

VB [Link]
[Run Sample] | [View
Source]

Applying Styles to Web Server Controls

Web server controls provide an additional level of support for styles by adding several strongly
typed properties for commonly used style settings, such as background and foreground color, font
name and size, width, height, and so on. These style properties represent a subset of the style
behaviors available in HTML and are represented as "flat" properties exposed directly on the
[Link] base class. The advantage of using these
properties is that they provide compile-time type checking and statement completion in
development tools such as Microsoft Visual Studio .NET.

The following sample shows a WebCalendar control with several styles applied to it (a calendar
without styles applied is included for contrast). Note that when setting a property that is a class
type, such as Font, you need to use the subproperty syntax PropertyName-SubPropertyName .

VB [Link]
[Run Sample] | [View
Source]

The [Link] namespace includes a Style base class that encapsulates


common style attributes (additional style classes, such as TableStyle and TableItemStyle,
inherit from this common base class). Many Web server controls expose properties of this type
for specifying the style of individual rendering elements of the control. For example, the
WebCalendar exposes many such style properties: DayStyle, WeekendDayStyle,
TodayDayStyle, SelectedDayStyle, OtherMonthDayStyle, and NextPrevStyle. You can set
individual properties of these styles using the subproperty syntax PropertyName-
SubPropertyName, as the following sample demonstrates.
20

VB [Link]
[Run Sample] | [View
Source]

A slightly different syntax allows each Style property to be declared as a child element nested
within Web server control tags.

<ASP:Calendar ... runat="server">


<TitleStyle BorderColor="darkolivegreen" BorderWidth="3"
BackColor="olivedrab" Height="50px" />
</ASP:Calendar>

The following sample shows alternative syntax but is functionally equivalent to the preceding one.

VB [Link]
[Run Sample] | [View
Source]

As with HTML server controls, you can apply styles to Web server controls using a CSS class
definition. The WebControl base class exposes a String property named CssClass for setting
the style class:

VB [Link]
[Run Sample] | [View
Source]

If an attribute is set on a server control that does not correspond to any strongly typed property
on the control, the attribute and value are populated in the Attributes collection of the control.
By default, server controls will render these attributes unmodified in the HTML returned to the
requesting browser client. This means that the style and class attributes can be set on Web
server controls directly instead of using the strongly typed properties. While this requires some
understanding of the actual rendering of the control, it can be a flexible way to apply styles as
well. It is especially useful for the standard form input controls, as illustrated in the following
sample.
21

VB [Link]
[Run Sample] | [View
Source]

Web server control styles can also be set programmatically, using the ApplyStyle method of the
base WebControl class, as in the following code.

<script language="VB" runat="server">


Sub Page_Load(Src As Object, E As EventArgs)
Dim MyStyle As New Style
[Link] = [Link]
[Link] = [Link]
[Link] = New Unit(1)

[Link] (MyStyle)
[Link] (MyStyle)
[Link] (MyStyle)
End Sub
</script>

Login: <ASP:TextBox id="MyLogin" runat="server" />/<p/>


Password: <ASP:TextBox id="MyPassword" TextMode="Password" runat="server" />
View: <ASP:DropDownList id="MySelect" runat="server"> ...
</ASP:DropDownList>
C# VB JScript

The following sample demonstrates the code above.

VB [Link]
[Run Sample] | [View
Source]

Section Summary

1. [Link]'s HTML server control and Web server control families provide first-class
support for CSS styles.
2. Styles may be applied by setting either the style or the class attributes of a control.
These settings are accessible programmatically through the control's Attributes
collection. In the case of HTML server controls, individual values for style-attribute keys
can be retrieved from the control's Style collection.
3. Most commonly used style settings are exposed on Web server controls as strongly
typed properties of the control itself.
22
4. The [Link] namespace includes a Style base class that
encapsulates common style attributes. Many Web server controls expose properties of
this type to control individual rendering elements.
5. Styles may be set programmatically on Web server controls using the ApplyStyle
method of the WebControl base class.

Server Control Form Validation


Introduction to Validation
Types of Validation Controls
Client-Side Validation
Displaying Validation Errors
Working with CompareValidator
Working with RangeValidator
Working with Regular Expressions
Performing Custom Validation
Bringing It All Together
Section Summary
Introduction to Validation

The Web Forms framework includes a set of validation server controls that provide an easy-to-use
but powerful way to check input forms for errors and, if necessary, display messages to the user.

Validation controls are added to a Web Forms page like other server controls. There are controls
for specific types of validation, such as range checking or pattern matching, plus a
RequiredFieldValidator that ensures that a user does not skip an entry field. You can attach
more than one validation control to an input control. For example, you might specify both that an
entry is required and that it must contain a specific range of values.

Validation controls work with a limited subset of HTML and Web server controls. For each control,
a specific property contains the value to be validated. The following table lists the input controls
that may be validated.

Control Validation Property


HtmlInputText Value
HtmlTextArea Value
HtmlSelect Value
HtmlInputFile Value
TextBox Text
ListBox [Link]
DropDownList [Link]
RadioButtonList [Link]

Types of Validation Controls

The simplest form of validation is a required field. If the user enters any value in a field, it is
valid. If all of the fields in the page are valid, the page is valid. The following example illustrates
this using the RequiredFieldValidator.
23

VB [Link]
[Run Sample] | [View
Source]

There are also validation controls for specific types of validation, such as range checking or
pattern matching. The following table lists the validation controls.

Control Name Description


RequiredFieldValidator Ensures that the user does not skip an entry.
CompareValidator Compares a user's entry with a constant value
or a property value of another control using a
comparison operator (less than, equal to,
greater than, and so on).
RangeValidator Checks that a user's entry is between
specified lower and upper boundaries. You can
check ranges within pairs of numbers,
alphabetic characters, or dates. Boundaries
can be expressed as constants.
RegularExpressionValidator Checks that the entry matches a pattern
defined by a regular expression. This type of
validation allows you to check for predictable
sequences of characters, such as those in
social security numbers, e-mail addresses,
telephone numbers, postal codes, and so on.
CustomValidator Checks the user's entry using validation logic
that you code yourself. This type of validation
allows you to check for values derived at run
time.
ValidationSummary Displays the validation errors in summary
form for all of the validators on a page.

Client-Side Validation

The validation controls always perform validation checking in server code. However, if the user is
working with a browser that supports DHTML, the validation controls can also perform validation
using client script. With client-side validation, any errors are detected on the client when the form
is submitted to the server. If any of the validators are found to be in error, the submission of the
form to the server is cancelled and the validator's Text property is displayed. This permits the
user to correct the input before submitting the form to the server. Field values are revalidated as
soon as the field containing the error loses focus, thus providing the user with a rich, interactive
validation experience.

Note that the Web Forms page framework always performs validation on the server, even if the
validation has already been performed on the client. This helps prevent users from being able to
bypass validation by impersonating another user or a preapproved transaction.
24
Client-side validation is enabled by default. If the client is capable, uplevel validation will be
performed automatically. To disable client-side validation, set the page's ClientTarget property
to "Downlevel" ("Uplevel" forces client-side validation).

VB [Link]
[Run Sample] | [View
Source]

Displaying Validation Errors

When the user's input is processed (for example, when the form is submitted), the Web Forms
page framework passes the user's entry to the associated validation control or controls. The
validation controls test the user's input and set a property to indicate whether the entry passed
the validation test. After all validation controls have been processed, the IsValid property on the
page is set; if any of the controls shows that a validation check failed, the entire page is set to
invalid.

If a validation control is in error, an error message may be displayed in the page by that
validation control or in a ValidationSummary control elsewhere on the page. The
ValidationSummary control is displayed when the IsValid property of the page is false. It polls
each of the validation controls on the page and aggregates the text messages exposed by each.
The following example illustrates displaying errors with a ValidationSummary control.

VB [Link]
[Run Sample] | [View
Source]

Working with CompareValidator

The CompareValidator server control compares the values of two controls. CompareValidator
uses three key properties to perform its validation. ControlToValidate and ControlToCompare
contain the values to compare. Operator defines the type of comparison to perform--for
example, Equal or Not Equal. CompareValidator performs the validation by evaluating these
properties as an expression, as follows:

( ControlToValidate ControlToCompare )
If the expression evaluates true, the validation result is valid.
25
The CompareValidator server control could also be used to do Datatype [Link]
example, if birth date information has to be collected from a user registration page,
CompareValidator control could be used to make sure that the date is in a recognized format
before it is submitted to the database.

The following sample shows how to use the CompareValidator control.

VB [Link]
[Run Sample] | [View
Source]

Working with RangeValidator

The RangeValidator server control tests whether an input value falls within a given range.
RangeValidator uses three key properties to perform its validation. ControlToValidate
contains the value to validate. MinimumValue and MaximumValue define the minimum and
maximum values of the valid range.

This sample shows how to use the RangeValidator control.

VB [Link]
[Run Sample] | [View
Source]

Working with Regular Expressions

The RegularExpressionValidator server control checks that the entry matches a pattern
defined by a regular expression. This type of validation allows you to check for predictable
sequences of characters, such as those in social security numbers, e-mail addresses, telephone
numbers, postal codes, and so on.

RegularExpressionValidator uses two key properties to perform its validation.


ControlToValidate contains the value to validate. ValidationExpression contains the regular
expression to match.

These samples illustrates using the RegularExpressionValidator control.


26

VB [Link]
[Run Sample] | [View
Source]

VB [Link]
[Run Sample] | [View
Source]

Performing Custom Validation

The CustomValidator server control calls a user-defined function to perform validations that the
standard validators can't handle. The custom function can execute on the server or in client-side
script, such as JScript or VBScript. For client-side custom validation, the name of the custom
function must be identified in the ClientValidationFunction property. The custom function must
have the form

function myvalidator(source, arguments)


Note that source is the client-side CustomValidator object, and arguments is an object with
two properties, Value and IsValid. The Value property is the value to be validated and the
IsValid property is a Boolean used to set the return result of the validation.

For server-side custom validation, place your custom validation in the validator's
OnServerValidate delegate.

The following sample shows how to use the CustomValidator control.

VB [Link]
[Run Sample] | [View
Source]

Bringing It All Together

This sample shows a typical registration form, using the variations of validation controls discussed
in this topic.
27

VB [Link]
[Run Sample] | [View
Source]

Section Summary

1. Validator controls can be used to validate input on any Web Forms page.
2. More than one control can be used on a given input field.
3. Client-side validation may be used in addition to server validation to improve form
usability.
4. The ValidationSummary control can be used to provide centralized error feedback by
querying all validation controls for error messages
5. Simple validation can be performed using the CompareValidator and RangeValidator
classes. These are commonly used on numeric data.
6. Complex pattern validation can be performed using the RegularExpressionValidator.
Pattern validation is useful for strings like names, address, phone numbers, and email
addresses.
7. The CustomValidator control lets the user define custom validation criteria.

Web Forms User Controls


Introduction to User Controls
Exposing User Control Properties
Encapsulating Events in a User Control
Creating User Controls Programmatically
Section Summary
Introduction to User Controls

In addition to the built-in server controls provided by [Link], you can easily define your own
controls using the same programming techniques that you have already learned for writing Web
Forms pages. In fact, with just a few modifications, almost any Web Forms page can be reused in
another page as a server control (note that a user control is of type
[Link], which inherits directly from [Link]). A Web
Forms page used as a server control is named a user control for short. As a matter of convention,
the .ascx extension is used to indicate such controls. This ensures that the user control's file
cannot be executed as a standalone Web Forms page (you will see a little that there are a few,
albeit important, differences between a user control and a Web Forms page). User controls are
included in a Web Forms page using a Register directive:

<%@ Register TagPrefix="Acme" TagName="Message" Src="[Link]" %>

The TagPrefix determines a unique namespace for the user control (so that multiple user
controls with the same name can be differentiated from each other). The TagName is the unique
name for the user control (you can choose any name). The Src attribute is the virtual path to the
user control--for example "[Link]" or "/MyApp/Include/[Link]". After
registering the user control, you may place the user control tag in the Web Forms page just as
you would an ordinary server control (including the runat="server" attribute):

<Acme:Message runat="server"/>
28
The following example shows a user control imported into another Web Forms page. Note that
the user control in this case is just a simple static file.

VB [Link]
[Run Sample] | [View
Source]

Exposing User Control Properties

When a Web Forms page is treated as a control, the public fields and methods of that Web Form
are promoted to public properties (that is, tag attributes) and methods of the control as well. The
following example shows an extension of the previous user control example that adds two public
String fields. Notice that these fields can be set either declaratively or programmatically in the
containing page.

VB [Link]
[Run Sample] | [View
Source]

In addition to promoting public fields to control properties, the property syntax may be used.
Property syntax has the advantage of being able to execute code when properties are set or
retrieved. The following example demonstrates an Address user control that wraps the text
properties of TextBox controls within it. The benefit of doing this is that the control inherits the
automatic state management of the TextBox control for free.

Notice that there are two Address user controls on the containing Web Forms page that set the
Caption property to "Billing Address" and "Shipping Address", respectively. The real power of
user controls is in this type of reusability.

VB [Link]
[Run Sample] | [View
Source]

Another useful user control is a Login control for collecting user names and passwords.
29

VB [Link]
[Run Sample] | [View
Source]

In this example, form validation controls are added to the Login user control.

VB [Link]
[Run Sample] | [View
Source]

Encapsulating Events in a User Control

User controls participate in the complete execution lifecycle of the request, much the way
ordinary server controls do. This means that a user control can handle its own events,
encapsulating some of the page logic from the containing Web Forms page. The following
example demonstrates a product-listing user control that internally handles its own postbacks.
Note that the user control itself has no wrapping <form runat="server"> control. Because only
one form control may be present on a page ([Link] does not allow nested server forms), it is
left to the containing Web Forms page to define this.

VB [Link]
[Run Sample] | [View
Source]

Creating User Controls Programmatically

Just as ordinary server controls can be created programmatically, so user controls can be. The
page's LoadControl method is used to load the user control, passing the virtual path to the user
control's source file:

Dim c1 As Control = LoadControl("[Link]")


30
CType(c1, (Pagelet7VB)).Category = "business"
[Link](c1)
C# VB JScript

The type of the user control is determined by a ClassName attribute on the Control directive.
For example, a user control saved with the file name "[Link]" is assigned the strong type
"Pagelet7CS" as follows:

<%@ Control ClassName="Pagelet7CS" %>

Because the LoadControl method returns a type of [Link], it must be cast to


the appropriate strong type in order to set individual properties of the control. Finally, the user
control is added to the base page's ControlCollection.

VB [Link]
[Run Sample] | [View
Source]

Important The strong type for a user control is available to the containing Web Forms page only
if a Register directive is included for the user control (even if there are no user control tags
actually declared).

Section Summary

1. User controls allow developers to easily define custom controls using the same
programming techniques as for writing Web Forms pages.
2. As a matter of convention, an .ascx file name extension is used to indicate such
controls. This ensures that a user control file cannot be executed as a standalone Web
Forms page.
3. User controls are included into another Web Forms page using a Register directive,
which specifies a TagPrefix, TagName, and Src location.
4. After the user control has been registered, a user control tag may be placed in a Web
Forms page as an ordinary server control (including the runat="server" attribute).
5. The public fields, properties, and methods of a user control are promoted to public
properties (tag attributes) and methods of the control in the containing Web Forms
page.
6. User controls participate in the complete execution lifecycle of every request and can
handle their own events, encapsulating some of the page logic from the containing Web
Forms page.
7. User controls should not contain any form controls but should instead rely on their
containing Web Forms page to include one if necessary.
8. User controls may be created programmatically using the LoadControl method of the
[Link] class. The type of the user control is determined by the [Link]
runtime, following the convention filename_extension.
9. The strong type for a user control is available to the containing Web Forms page only if
a Register directive is included for the user control (even if there are no user control
tags actually declared).

Data Binding Server Controls


31
Data Binding Overview and Syntax
Binding to Simple Properties
Binding to Collections & Lists
Binding Expressions or Methods
[Link]()
Section Summary
Data Binding Overview and Syntax

[Link] introduces a new declarative data binding syntax. This extremely flexible syntax permits
the developer to bind not only to data sources, but also to simple properties, collections,
expressions, and even results returned from method calls. The following table shows some
examples of the new syntax.

Simple Customer: <%# custID %>


property
Collection Orders: <asp:ListBox id="List1" datasource='<%# myArray %>'
runat="server">
Expression Contact: <%# ( [Link] + " " + [Link] ) %>
Method Outstanding Balance: <%# GetBalance(custID) %>
result

Although this syntax looks similar to the ASP shortcut for [Link] -- <%= %> -- its
behavior is quite different. Whereas the ASP [Link] shortcut syntax was evaluated
when the page was processed, the [Link] data binding syntax is evaluated only when the
DataBind method is invoked.

DataBind is a method of the Page and all server controls. When you call DataBind on a parent
control, it cascades to all of the children of the control. So, for example, [Link]()
invokes the DataBind method on each of the controls in the DataList templates. Calling
DataBind on the Page -- [Link]() or simply DataBind() -- causes all data binding
expressions on the page to be evaluated. DataBind is commonly called from the Page_Load
event, as shown in the following example.

Protected Sub Page_Load(Src As Object, E As EventArgs)


DataBind()
End Sub
C# VB JScript

You can use a binding expression almost anywhere in the declarative section of an .aspx page,
provided it evaluates to the expected data type at run time. The simple property, expression, and
method examples above display text to the user when evaluated. In these cases, the data
binding expression must evaluate to a value of type String. In the collection example, the data
binding expression evaluates to a value of valid type for the DataSource property of ListBox.
You might find it necessary to coerce the type of value in your binding expression to produce the
desired result. For example, if count is an integer:

Number of Records: <%# [Link]() %>

Binding to Simple Properties


32
The [Link] data binding syntax supports binding to public variables, properties of the Page,
and properties of other controls on the page.

The following example illustrates binding to a public variable and simple property on the page.
Note that these values are initialized before DataBind() is called.

VB [Link]
[Run Sample] | [View
Source]

The following example illustrates binding to a property of another control.

VB [Link]
[Run Sample] | [View
Source]

Binding to Collections and Lists

List server controls like DataGrid, ListBox and HTMLSelect use a collection as a data source.
The following examples illustrate binding to usual common language runtime collection types.
These controls can bind only to collections that support the IEnumerable, ICollection, or
IListSource interface. Most commonly, you'll bind to ArrayList, Hashtable, DataView and
DataReader.

The following example illustrates binding to an ArrayList.

VB [Link]
[Run Sample] | [View
Source]

The following example illustrates binding to a DataView. Note that the DataView class is
defined in the [Link] namespace.
33

VB [Link]
[Run Sample] | [View
Source]

The following example illustrates binding to a Hashtable.

VB [Link]
[Run Sample] | [View
Source]

Binding Expressions or Methods

Often, you'll want to manipulate data before binding to your page or a control. The following
example illustrates binding to an expression and the return value of a method.

VB [Link]
[Run Sample] | [View
Source]

[Link]

The [Link] framework supplies a static method that evaluates late-bound data binding
expressions and optionally formats the result as a string. [Link] is convenient in that
it eliminates much of the explicit casting the developer must do to coerce values to the desired
data type. It is particularly useful when data binding controls within a templated list, because
often both the data row and the data field must be cast.

Consider the following example, where an integer will be displayed as a currency string. With the
standard [Link] data binding syntax, you must first cast the type of the data row in order to
retrieve the data field, IntegerValue. Next, this is passed as an argument to the [Link]
method.
34
<%# [Link]("{0:c}", (CType([Link],
DataRowView)("IntegerValue"))) %>
C# VB JScript

This syntax can be complex and difficult to remember. In contrast, [Link] is simply a
method with three arguments: the naming container for the data item, the data field name, and
a format string. In a templated list like DataList, DataGrid, or Repeater, the naming container
is always [Link]. Page is another naming container that can be used with
[Link].

<%# [Link]([Link], "IntegerValue", "{0:c}") %>


C# VB JScript

The format string argument is optional. If it is omitted, [Link] returns a value of type
object, as shown in the following example.

<%# CType([Link]([Link], "BoolValue"), Boolean) %>


C# VB JScript

It is important to note that [Link] can carry a noticeable performance penalty over
the standard data binding syntax because it uses late-bound reflection. Use [Link]
judiciously, especially when string formatting is not required.

VB [Link]
[Run Sample] | [View
Source]

Section Summary

1. The [Link] declarative data binding syntax uses the <%# %> notation.
2. You can bind to data sources, properties of the page or another control, collections,
expressions, and results returned from method calls.
3. List controls can bind to collections that support the ICollection, IEnumerable, or
IListSource interface, such as ArrayList, Hashtable, DataView, and DataReader.
4. [Link] is a static method for late binding. Its syntax can be simpler than the
standard data binding syntax, but performance is slower.

Server-Side Data Access


Introduction to Server-Side Data
Connections, Commands, and DataSets
Accessing SQL-based Data
Binding SQL Data to a DataGrid
Performing a Parameterized Select
Inserting Data in a SQL Database
Updating Data in a SQL Database
Deleting Data in a SQL Database
Sorting Data from a SQL Database
35
Working with Master-Detail Relationships
Writing and Using Stored Procedures
Accessing XML-based Data
Section Summary
Introduction to Server-Side Data

Data access is the heart of any real-world application, and [Link] provides a rich set of controls
that are well-integrated with the managed data access APIs provided in the common language
runtime. This section walks through several iterations of a sample that uses the [Link]
DataGrid control to bind to the results of SQL queries and XML data files. This section assumes
some familiarity with database fundamentals and the SQL query language.

Server-side data access is unique in that Web pages are basically stateless, which presents some
difficult challenges when trying to perform transactions such as inserting or updating records
from a set of data retrieved from a database. As you'll see in this section, the DataGrid control
can help manage these challenges, allowing you to concentrate more on your application logic
and less on the details of state management and event handling.

Connections, Commands, and Datasets

The common language runtime provides a complete set of managed data access APIs for data-
intensive application development. These APIs help to abstract the data and present it in a
consistent way regardless of its actual source (SQL Server, OLEDB, XML, and so on). There are
essentially three objects you will work with most often: connections, commands, and datasets.

• A connection represents a physical connection to some data store, such as SQL Server
or an XML file.
• A command represents a directive to retrieve from (select) or manipulate (insert,
update, delete) the data store.
• A dataset represents the actual data an application works with. Note that datasets are
always disconnected from their source connection and data model and can be modified
independently. However, changes to a dataset can be easily reconciled with the
originating data model.

For a more detailed walkthrough of the managed data access solution in the common language
runtime, please read the [Link] Overview section of this tutorial.

Accessing SQL-based Data

An application typically needs to perform one or more select, insert, update, or delete queries to
a SQL database. The following table shows an example of each of these queries.

Query Example
Simple Select SELECT * from Employees WHERE FirstName =
'Bradley';
Join Select SELECT * from Employees E, Managers M WHERE
[Link] = [Link];
Insert INSERT into Employees VALUES ('123-45-
6789','Bradley','Millington','Program Manager');
Update UPDATE Employees SET Title = 'Development Lead'
WHERE FirstName = 'Bradley';
36
Delete DELETE from Employees WHERE Productivity < 10;

To give your page access to the classes you will need to perform SQL data access, you must
import the [Link] and [Link] namespaces into your page.

<%@ Import Namespace="[Link]" %>


<%@ Import Namespace="[Link]" %>

To perform a select query to a SQL database, you create a SqlConnection to the database
passing the connection string, and then construct a SqlDataAdapter object that contains your
query statement. To populate a DataSet object with the results from the query, you call the
command's Fill method.

Dim myConnection As New SqlConnection( _


"server=(local)\NetSDK;database=pubs;Integrated Security=SSPI")
Dim myCommand As New SqlDataAdapter("select * from Authors", myConnection)

Dim ds As New DataSet()


[Link](ds, "Authors")
C# VB JScript

As mentioned earlier in this section, the benefit of using a dataset is that it gives you a
disconnected view of the database. You can operate on a dataset in your application, and then
reconcile your changes with the actual database later. For long-running applications this is often
the best approach. For Web applications, you are usually performing short operations with each
request (commonly to simply display the data). You often don't need to hold a DataSet object
over a series of several requests. For situations like these, you can use a SqlDataReader.

A SqlDataReader provides a forward-only, read-only pointer over data retrieved from a SQL
database. To use a SqlDataReader, you declare a SqlCommand instead of a SqlDataAdapter.
The SqlCommand exposes an ExecuteReader method that returns a SqlDataReader. Note
also that you must explicitly open and close the SqlConnection when you use a SqlCommand.
After a call to ExecuteReader, the SqlDataReader can be bound to an [Link] server control,
as you'll see in the next section.

Dim myConnection As SqlConnection = New SqlConnection( _


"server=(local)\NetSDK;database=pubs;Integrated Security=SSPI")
Dim myCommand As SqlCommand = New SqlCommand("select * from Authors",
myConnection)

[Link]()

Dim dr As SqlDataReader = [Link]()

...

[Link]()
C# VB JScript

When performing commands that do not require data to be returned, such as inserts, updates,
and deletes, you also use a SqlCommand. The command is issued by calling an
ExecuteNonQuery method, which returns the number of rows affected. Note that the
37
connection must be explicitly opened when you use the SqlCommand; the SqlDataAdapter
automatically handles opening the connection for you.

Dim myConnection As New SqlConnection( _


"server=(local)\NetSDK;database=pubs;Integrated Security=SSPI")
Dim myCommand As New SqlCommand( _
"UPDATE Authors SET phone='(800) 555-5555' WHERE au_id = '123-45-6789'",
myConnection)

[Link]()
[Link]()
[Link]()
C# VB JScript

Important: Always remember to close the connection to the data model before the page finishes
executing. If you do not close the connection, you might inadvertently exhaust the connection
limit while waiting for the page instances to be handled by garbage collection.

Binding SQL Data to a DataGrid

The following sample shows a simple select query bound to a DataGrid control. The DataGrid
renders a table containing the SQL data.

VB [Link]
[Run Sample] | [View
Source]

The DataGrid control supports a DataSource property that takes any object that implements
the IList or IListSource interfaces. You can use a DataSet by assigning the DefaultView
property of a table contained in the DataSet to the name of the table you wish to use within the
DataSet. The DefaultView property represents the current state of a table within a DataSet,
including any changes which have been made by application code (row deletions or value
changes, for example). After setting the DataSource property, you call DataBind() to populate
the control.

[Link]=[Link]("Authors").DefaultView
[Link]()
C# VB JScript

An alternative syntax is to specify both a DataSource and a DataMember. In this case,


[Link] automatically gets the DefaultView for you.

[Link]=ds
[Link]="Authors"
[Link]()
C# VB JScript
38
You can also bind directly to a SqlDataReader. In this case you are only displaying data, so
the forward-only nature of the SqlDataReader is perfectly suited to this scenario, and you
benefit from the performance boost that SqlDataReader provides.

VB [Link]
[Run Sample] | [View
Source]

Note: For the remainder of this section, only the DataSet model of data access is shown;
however, any of these samples could be re-written to take advantage of SQLDataReader as
well.

Performing a Parameterized Select

You can also perform a parameterized select using the SqlDataAdapter object. The following
sample shows how you can modify the data selected using the value posted from a select
HtmlControl.

VB [Link]
[Run Sample] | [View
Source]

The SqlDataAdapter maintains a Parameters collection that can be used to replace variable
identifiers (denoted by an "@" in front of the name) with values. You add a new SqlParameter
to this collection that specifies the name, type, and size of the parameter, and then set its Value
property to the value of the select.

[Link](New SqlParameter("@State",
[Link], 2))
[Link]("@State").Value = [Link]
C# VB JScript

Important: Note that the DataGrid's EnableViewState property has been set to false. If the
data will be populated in each request, there is no benefit to having the DataGrid store state
information to be sent through a round trip with form posts. Because the DataGrid stores all of
its data when maintaining state, it is important to turn it off when appropriate to improve the
performance of your pages.

[Link] statically populates the values of the select box, but this will not work well if
those values ever change in the database. Because the select HtmlControl also supports an
IEnumerable DataSource property, you can use a select query to dynamically populate the
39
select box instead, which guarantees that the database and user interface are always in sync.
The following sample demonstrates this process.

VB [Link]
[Run Sample] | [View
Source]

Inserting Data in a SQL Database

To insert a row into the database, you can add a simple input form to the page, and execute an
insert command in the form submit event handler. Just as in the previous two samples, you use
the command object's Parameters collection to populate the command's values. Note that you
also check to make sure the required values are not null before attempting to insert into the
database. This prevents an accidental violation of the database's field constraints. You also
execute the insert command inside of a try/catch block, just in case the primary key for inserted
row already exists.

VB [Link]
[Run Sample] | [View
Source]

Instead of explicitly checking the input values, you could have just as easily used the validator
controls provided with [Link]. The following sample shows how to do that. Note that using the
RegEx Validator provides the additional benefit of checking the format for the author ID, zip code,
and phone number fields.

VB [Link]
[Run Sample] | [View
Source]

Updating Data in a SQL Database


40
Updating a database can often be tricky in Web applications. The DataGrid control provides
some built-in support for this scenario that makes updates easier. To allow rows to be edited, the
DataGrid supports an integer EditItemIndex property, which indicates which row of the grid
should be editable. When this property is set, the DataGrid renders the row at that index as text
input boxes instead of simple labels. A value of -1 (the default) indicates that no rows are
editable. The page can enclose the DataGrid in a server-side form and get access to the edited
data through the DataGrid's object model.

To figure out which row should be editable, you need a way to accept some input from the user
about which row they would like to edit. The DataGrid can contain an EditCommandColumn
that renders links for firing three special events: EditCommand, UpdateCommand, and
CancelCommand. The EditCommandColumn is declaratively added to the DataGrid's
Columns collection, as shown in the following example.

<ASP:DataGrid id="MyDataGrid" runat="server"


...
OnEditCommand="MyDataGrid_Edit"
OnCancelCommand="MyDataGrid_Cancel"
OnUpdateCommand="MyDataGrid_Update"
DataKeyField="au_id"
>

<Columns>
<asp:EditCommandColumn EditText="Edit" CancelText="Cancel" UpdateText="Update"
/>
</Columns>

</ASP:DataGrid>
On the DataGrid tag itself, you wire event handlers to each of the commands fired from the
EditCommandColumn. The DataGridCommandEventArgs argument of these handlers gives
you direct access to the index selected by the client, which you use to set the DataGrid's
EditItemIndex. Note that you need to re-bind the DataGrid for the change to take effect, as
shown in the following example.

Public Sub MyDataGrid_Edit(sender As Object, E As DataGridCommandEventArgs)


[Link] = [Link]
BindGrid()
End Sub
C# VB JScript

When a row of the DataGrid is being edited, the EditCommandColumn renders the Update
and Cancel links. If the client selects Cancel, you simply set the EditItemIndex back to -1. If
the client selects Update, however, you need to execute your update command to the database.
Performing an update query requires that you know the primary key in the database for the row
you wish to update. To support this, the DataGrid exposes a DataKeyField property that you
can set to the field name for the primary key. In the event handler wired to the
UpdateCommand, you can retrieve the key name from the DataGrid's DataKeys collection. You
index into this collection using the ItemIndex of the event, as shown in the following example.

[Link]("@Id").Value =
[Link](CType([Link], Integer))
C# VB JScript

At the end of the Update event handler, you set the EditItemIndex back to -1. The following
sample demonstrates this code in action.
41

VB [Link]
[Run Sample] | [View
Source]

One problem with the preceding example is that the primary key field (au_id) also renders as a
text input box when a row is editable. You don't want the client to change this value, because you
need it to determine which row to update in the database. Fortunately, you can disable this
column from rendering as a text box by specifying exactly what each column looks like for the
editable row. You do this by defining each row in the DataGrid's Columns collection, using the
BoundColumn control to assign data fields with each column. Using this technique gives you
complete control over the order of the columns, as well as their ReadOnly properties. For the
au_id column you set the ReadOnly property to true. When a row is in edit mode, this column
will continue to render as a Label. The following sample demonstrates this technique.

VB [Link]
[Run Sample] | [View
Source]

BoundColumn controls aren't the only controls you can set in the DataGrid's Columns
collection. You can also specify a TemplateColumn, which gives you complete control over the
contents of the column. The template is just arbitrary content; you can render anything you like,
including server controls, inside the DataGrid's columns. The following sample demonstrates
using the TemplateColumn control to render the "State" column as a drop-down list and the
"Contract" column as a check box HtmlControl. The [Link] data binding syntax is used to
output the data field value within the template. Note that there is a bit of tricky logic to make the
drop-down list and check box reflect the state of the data inside the row.

VB [Link]
[Run Sample] | [View
Source]

Just as you can place a drop-down list or check box HtmlControl in a TemplateColumn, you can
also place other controls there. The following sample adds Validator controls to the columns to
check the client input before attempting to perform the update.
42

VB [Link]
[Run Sample] | [View
Source]

Deleting Data in a SQL Database

Deleting from a database is very similar to an update or insert command, but you still need a way
to determine the particular row of the grid to delete. Another control that can be added to the
DataGrid's Columns collection is the ButtonColumn control, which simply renders a button
control. ButtonColumn supports a CommandName property that can be set to Delete. On the
DataGrid, you wire an event handler to the DeleteCommand, where you perform the delete
operation. Again, you use the DataKeys collection to determine the row selected by the client.
The following sample demonstrates this process.

VB [Link]
[Run Sample] | [View
Source]

Sorting Data from a SQL Database

A common requirement for any grid is the ability to sort the data it contains. While the DataGrid
control doesn't explicitly sort its data for you, it does provide a way to call an event handler when
the user clicks a column header, which you can use to sort the data. When the DataGrid's
AllowSorting property is set to true, it renders hyperlinks for the column headers that fire a
Sort command back to the grid. You set the OnSortCommand property of the DataGrid to the
handler you want to call when the user clicks a column link. The name of the column is passed as
a SortExpression property on the DataGridSortCommandEventArgs argument, which you
can use to set the Sort property of the DataView bound to the grid. The following example
demonstrates this process.

<script>
Protected Sub MyDataGrid_Sort(Src As Object, E As
DataGridSortCommandEventArgs)
...
DataView Source = [Link]("Authors").DefaultView
[Link] = [Link]
[Link]()
End Sub
</script>
43
<form runat="server">
<ASP:DataGrid id="MyDataGrid" OnSortCommand="MyDataGrid_Sort"
AllowSorting="true" runat="server" />
</form>
C# VB JScript

The following sample shows this code in action.

VB [Link]
[Run Sample] | [View
Source]

When using BoundColumn controls, you can explicitly set the SortExpression property for
each column, as demonstrated in the following sample.

VB [Link]
[Run Sample] | [View
Source]

Working with Master-Detail Relationships

Often your data model will contain relationships that cannot be represented using just a single
grid. A very common Web-based interface is one in which a row of data can be selected that
navigates the client to a "details" page, which displays detailed information about the selected
row. To accomplish this using the DataGrid, you can add a HyperLinkColumn to the Columns
collection, which specifies the details page to which the client will navigate when the link is
clicked. You use the format string syntax to substitute a field value in this link, which is passed as
a querystring argument. The following example demonstrates this process.

<ASP:DataGrid id="MyDataGrid" runat="server">

<Columns>
<asp:HyperLinkColumn
DataNavigateUrlField="au_id"
DataNavigateUrlFormatString="datagrid13_details.aspx?id={0}"
Text="Get Details"
/>
</Columns>

</ASP:DataGrid>
44
On the details page, you retrieve the querystring argument and perform a join select to obtain
details from the database. The following sample demonstrates this scenario.

VB [Link]
[Run Sample] | [View
Source]

Writing and Using Stored Procedures

In general, performing ad hoc queries comes at the expense of performance. Using stored
procedures can reduce the cost of performing heavy database operations in an application. A
stored procedure is easy to create, and can even be done using a SQL statement. The following
code example creates a stored procedure that simply returns a table.

CREATE Procedure GetAuthors AS


SELECT * FROM Authors
return
GO

You can create stored procedures that accept parameters as well. For example:

CREATE Procedure LoadPersonalizationSettings (@UserId varchar(50)) AS


SELECT * FROM Personalization WHERE UserID=@UserId
return
GO

Using a stored procedure from an [Link] page is just an extension of what you've learned so far
about the SqlCommand object. The CommandText is just the name of the stored procedure
instead of the ad hoc query text. You indicate to the SqlCommand that the CommandText is a
stored procedure by setting the CommandType property.

[Link] = [Link]
C# VB JScript

The following sample demonstrates a call to a stored procedure to fill the DataSet.

VB [Link]
[Run Sample] | [View
Source]
45
Parameters to stored procedures are passed just as they are for ad hoc queries, as shown in
the following samples.

VB [Link]
[Run Sample] | [View
Source]

VB [Link]
[Run Sample] | [View
Source]

Accessing XML-based Data

At the beginning of this section it was mentioned that the DataSet was designed to abstract data
in a way that is independent of the actual data source. You can see this by changing the focus of
your samples from SQL to XML. The DataSet supports a ReadXml method that takes a
FileStream object as its parameter. The file you read in this case must contain both a schema
and the data you wish to read. The DataSet expects data to be in the form, as shown in the
following example.

<DocumentElement>
<TableName>
<ColumnName1>column value</ColumnName1>
<ColumnName2>column value</ColumnName2>
<ColumnName3>column value</ColumnName3>
<ColumnName4>column value</ColumnName4>
</TableName>
<TableName>
<ColumnName1>column value</ColumnName1>
<ColumnName2>column value</ColumnName2>
<ColumnName3>column value</ColumnName3>
<ColumnName4>column value</ColumnName4>
</TableName>
</DocumentElement>

Each TableName section corresponds to a single row in the table. The following sample shows
reading schema and data from an XML file using the ReadXml method of the DataSet. Note that
after the data is read into the DataSet it is indistinguishable from SQL data -- the DataGrid
binds to it just the same, as shown in the following sample.
46

VB [Link]
[Run Sample] | [View
Source]

You can also read the data and schema separately, using the ReadXmlData and
ReadXmlSchema methods of the DataSet, as shown in the following sample.

VB [Link]
[Run Sample] | [View
Source]

Just as the DataSet supports reader methods for XML data, it also supports writing the data. The
following sample implements a tool for selecting data from SQL and writing the result as XML
data or schema text.

VB [Link]
[Run Sample] | [View
Source]

Section Summary

1. The common language runtime's managed data access APIs abstract data and present it
in a consistent way regardless of its actual source (SQL Server, OLEDB, XML, and so
on).
2. To give your page access to the classes you will need to perform SQL data access, you
must import the [Link] and [Link] namespaces into your
page.
3. Populating a dataset from a SQL query involves creating a SqlConnection, associating
a SqlDataAdapter object with the connection that contains your query statement, and
filling the dataset from the command.
4. The DataGrid control supports a DataSource property that takes any object that
implements IList or IListSource interfaces. You can set this to the result of a SQL
query by assigning the DataSet's DefaultView property, which is of type DataView.
5. The SqlDataAdapter maintains a Parameters collection that can be used to replace
variable identifiers (denoted by an "@" in front of the name) with values.
6. When performing commands that do not require data to be returned, such as inserts,
updates, and deletes, you use a SqlCommand instead of the SqlDataAdapter. The
47
command is issued by calling an ExecuteNonQuery method, which returns the
number of rows affected.
7. The SqlConnection must be explicitly opened when you use the SqlCommand (the
SqlDataAdapter automatically handles opening the connection for you). Always
remember to close the SqlConnection to the data model before the page finishes
executing. If you do not close the connection, you migh inadvertantly exhaust the
connection limit while waiting for the page instances to be released to garbage
collection.
8. To allow rows to be edited, the DataGrid supports an integer EditItemIndex property,
which indicates which row of the grid should be editable. When this property is set, the
DataGrid renders the row at that index as text input boxes instead of simple labels.
9. The DataGrid exposes a DataKeyField property that you can set to the field name for
the primary key. In the event handler wired to the UpdateCommand, you can retrieve
the key name from the DataGrid's DataKeys collection.
10. Using BoundColumn controls in the DataGrid gives you complete control over the
order of the columns, as well as their ReadOnly properties.
11. Using TemplateColumn controls in the DataGrid gives you complete control over the
contents of the column.
12. The ButtonColumn control can be used to simply render a button control in each row
for that column, which can be associated with an event.
13. A HyperLinkColumn can be added to the DataGrid's Columns collection, which
supports navigating to another page when the link is clicked.
14. When the DataGrid's AllowSorting property is set to true, it renders hyperlinks for
the column headers that fire a Sort command back to the grid. You set the
OnSortCommand property of the DataGrid to the handler you want to call when the
user clicks a column link.
15. The DataSet supports ReadXml, ReadXmlData, and ReadXmlSchema methods that
take a FileStream as a parameter, which can be used to populate a DataSet from an
XML file.
16. Using stored procedures can reduce the cost of performing heavy database operations in
an application.

Data Access and Customization


Introduction to Templated Controls
Handling Postbacks from a Template
Using Select and Edit Templates
Finding a Control Inside a Template
Section Summary
Introduction to Templated Controls

While the DataGrid server control demonstrated in the previous section is suitable for many Web
application scenarios where a grid-like representation of data is appropriate, many times the
presentation of data needs to be much richer. [Link] offers two controls, DataList and
Repeater, that give you greater flexibility over the rendering of list-like data. These controls are
template-based, and so have no default rendering of their own. The way data is rendered is
completely determined by the your implementation of the control's templates, which describe
how to present data items.

Like the DataGrid control, DataList and Repeater support a DataSource property, which can
be set to any ICollection, IEnumerable, or IListSource type. The data in this DataSource is
bound to the control using its DataBind method. Once the data is bound, the format of each
data item is described by a template.

The ItemTemplate property controls the rendering of each item in the DataSource collection.
Inside an ItemTemplate, you can define any arbitrary presentation code (HTML or otherwise).
48
Using the [Link] data binding syntax, you can insert values from the data bound to the
DataList or Repeater control, as shown in the following example.

<ASP:Repeater id="MyRepeater" runat="server">

<ItemTemplate>
Hello <%# [Link]([Link], "name") %> !
</ItemTemplate>

</ASP:Repeater>

The Container represents the first control in the immediate hierarchy that supports the
[Link] marker interface. In this case, the Container resolves to
an object of type [Link], which has a DataItem
property. As the Repeater iterates over the DataSource collection, the DataItem contains the
current item in this collection. For example, if the data source is set to an ArrayList of Employee
objects, the DataItem is of type Employees. When bound to a DataView, the DataItem is of
type DataRowView.

The following example demonstrates a Repeater control bound to a DataView (returned from a
SQL query). HeaderTemplate and FooterTemplate have also been defined and render at the
beginning and end of the list, respectively.

VB [Link]
[Run Sample] | [View
Source]

The Repeater control just iterates over the bound data, rendering the ItemTemplate once for
each item in the DataSource collection. It does not render anything besides the elements
contained in its templates. While the Repeater is a general purpose iterator, the DataList
provides some additional features for controlling the layout of the list. Unlike the Repeater,
DataList renders additonal elements, like table rows and cells and spans containing style
attributes, outside of the template definition to enable this richer formatting. For example,
DataList supports RepeatColumns and RepeatDirection properties that specify whether data
should be rendered in multiple columns, and in which direction (vertical or horizontal) the data
items should be rendered. DataList also supports style attributes, as shown in the following
example.

<ASP:DataList runat="server" DataSource="<%#MyData%>"


RepeatColumns="2"
RepeatDirection="Horizontal"
ItemStyle-Font-Size="10pt"
ItemStyle-Font-Name="Verdana"
>
...
</ASP:DataList>

Note: The remainder of this section concentrates on the many features of the DataList control.
For more information about the Repeater control, refer to the Repeater topic in the Web Forms
Controls Reference section of this tutorial.
49
The following sample demonstrates the use of the DataList control. Note that the look of the
data items has been changed from the previous example, simply by changing the contents of the
control's ItemTemplate property. The RepeatDirection and RepeatColumns properties
determine how the ItemTemplates are laid out.

VB [Link]
[Run Sample] | [View
Source]

The following example further demonstrates the infinite flexibility of templates by changing the
ItemTemplate yet again. This time, one of the DataItem values has been substituted for the
"src" attribute of an <img> tag. The format String parameter of [Link] has also
been used to substitute a DataItem value in the query string for a URL.

VB [Link]
[Run Sample] | [View
Source]

Handling Postbacks from a Template

As in the DataGrid, you can fire a command from inside a DataList template that is passed to
an event handler wired to the DataList itself. For example, a LinkButton inside the
ItemTemplate might fire a Select command. By setting the OnSelectedIndexChanged
property of the DataList, you can call an event handler in response to this command. The
following example demonstrates this process.

<ASP:DataList id="MyDataList" OnSelectedIndexChanged="MyDataList_Select"


runat="server">

<ItemTemplate>

<asp:linkbutton CommandName="Select" runat="server">


<%# [Link]([Link], "title") %>
</asp:linkbutton>

</ItemTemplate>

</ASP:DataList>

The following sample demonstrates this code in action. In the MyDataList_Select event handler,
you populate several other server controls with the details about the particular selected item.
50

VB [Link]
[Run Sample] | [View
Source]

Note that while the DataList recognizes a few special commands such as Select and
Edit/Update/Cancel, the command string fired inside a template can be any arbitrary string.
For all commands, the DataList's OnItemCommand is fired. You can wire this event to a
handler as in the previous example; the following example shows how to do this.

<script runat="server">

Protected Sub MyDataList_ItemCommand(Sender As Object, E As


DataListCommandEventArgs)
Dim Command As String = [Link]

Select Case Command


Case "Discuss"
ShowDiscussions([Link])
Case "Ratings"
ShowRatings([Link])
End Select
End Sub

</script>

<ASP:DataList id="MyDataList" OnItemCommand="MyDataList_ItemCommand"


runat="server">

<ItemTemplate>

<asp:linkbutton CommandName="Ratings" runat="server">


View Ratings
</asp:linkbutton>
|
<asp:linkbutton CommandName="Discuss" runat="server">
View Discussions
</asp:linkbutton>

</ItemTemplate>

</ASP:DataList>
C# VB JScript

Note that because more than one command can fire this event handler, you must employ a switch
statement to determine the particular command that was fired. The following sample
demonstrates this code in action.
51

VB [Link]
[Run Sample] | [View
Source]

Using Select and Edit Templates

In addition to handling the Select command using a page-level event handler, the DataList can
respond to this event internally. If a SelectedItemTemplate is defined for the DataList, the
DataList renders this template for the item that fired the Select command. The following
example uses the SelectedItemTemplate to make the title of the selected book bold.

VB [Link]
[Run Sample] | [View
Source]

DataList also supports an EditItemTemplate for rendering an item whose index is equal to the
DataList's EditItemIndex property. For details about how editing and updating works, refer to
the Updating Data topic of the Data Access section of this tutorial.

VB [Link]
[Run Sample] | [View
Source]

Finding a Control Inside a Template

Sometimes it is necessary to locate a control contained inside a template. If a control is given an


ID in a template, that control can be retrieved from its container (the first control in the parent
hierarchy that supports INamingContainer). In this case, the container is the DataListItem
control. Note that even though there are several controls with the same ID (by virtue of the
DataList's repetition), each is contained logically in the namespace of the DataListItem
container control.
52
You can go through the DataList's Items collection to retrieve the DataListItem for a given
index, and then call the DataListItem's FindControl method (inherited from the base Control
class) to retrieve a control with a particular ID.

<script runat="server">

Public Sub Page_Load(sender As Object, E As EventArgs))


' set datasource and call databind here

For I=0 To [Link]-1


Dim IsChecked As String =
[Link](i).FindControl("Save").[Link]()
If IsChecked = "True" Then
...
End If
Next
End Sub
</script>

<ASP:DataList id="MyDataList" runat="server">

<ItemTemplate>
<asp:CheckBox id="Save" runat="server"/> <b>Save to Favorites</b>
</ItemTemplate>

</ASP:DataList>
C# VB JScript

The following sample demonstrates this code in action.

VB [Link]
[Run Sample] | [View
Source]

Section Summary

1. The DataList and Repeater controls provide developers fine-tuned control over the
rendering of data-bound lists.
2. Rendering of bound data is controlled using a template, such as the HeaderTemplate,
FooterTemplate, or ItemTemplate.
3. The Repeater control is a general-purpose iterator, and does not insert anything in its
rendering that is not contained in a template.
4. The DataList control offers more control over the layout and style of items, and outputs
its own rendering code for formatting.
5. The DataList supports the Select, Edit/Update/Cancel, and Item Command
events, which can be handled at the page level by wiring event handlers to the
DataList's Command events.
6. DataList supports a SelectedItemTemplate and EditItemTemplate for control over
the rendering of a selected or editable item.
53
7. Controls can be programmatically retrieved from a template using the
[Link] method. This should be called on a DataListItem retrieved from
the DataList's Items collection.

Working With Business Objects


The Application /Bin Directory
Importing Business Objects
A Simple Two-Tier Web Forms Page
A Simple Three-Tier Web Forms Page
Section Summary
Encapsulating logic in business components is an essential part of any real-world application,
Web-based or otherwise. In [Link], business objects are the building blocks for multi-tiered
Web applications, such as those with a layer for data access or common application rules. This
section demonstrates how to write some simple components and include them in your
application's Web Forms pages.

The Application /Bin Directory

A problem with using the COM model for Web application components is that those components
must be registered (typically using the regsvr32 tool) before they can be used from a traditional
ASP application. Remote administration of these types of applications is often not possible,
because the registration tool must be run locally on the server. To make matters more difficult,
these components remain locked on disk once they are loaded by an application, and the entire
Web server must be stopped before these components can be replaced or removed.

[Link] attempts to solve these problems by allowing components to be placed in a well-known


directory, to be automatically found at run time. This well-known directory is always named /bin,
and is located immediately under the root directory for the application (a virtual directory defined
by Internet Information Services (IIS)). The benefit is that no registration is required to make
components available to the [Link] Framework application -- components can be deployed by
simply copying to the /bin directory or performing an FTP file transfer.

In addition to providing a zero-registration way to deploy compiled components, [Link] does


not require these components to remain locked on disk at run time. Behind the scenes, [Link]
duplicates the assemblies found in /bin and loads these "shadow" copies instead. The original
components can be replaced even while the Web server is still running, and changes to the /bin
directory are automatically picked up by the runtime. When a change is detected, [Link] allows
currently executing requests to complete, and directs all new incoming requests to the application
that uses the new component or components.

Importing Business Objects

At its most basic level, a business component is just a class for which you can create an instance
from a Web Forms page that imports it. The following example defines a simple HelloWorld class.
The class has one public constructor (which is executed when an instance of the class is first
created), a single String property called FirstName, and a SayHello method that prints a greeting
using the value of the FirstName property.

Imports System
Imports [Link]

Namespace HelloWorld
54
Public Class HelloObj
Private _name As String

Public Sub New


[Link]()
_name = Nothing
End Sub

Public Property FirstName As String


Get
Return(_name)
End get
Set
_name = value
End Set
End Property

Public Function SayHello() As String


Dim sb As New StringBuilder("Hello ")
If (_name <> Nothing) Then
[Link](_name)
Else
[Link]("World")
End If
[Link]("!")
Return([Link]())
End Function
End Class
End Namespace
C# VB JScript

To compile this class, the C# compiler ([Link]) is run from the command line. The /t option tells
the compiler to build a library (DLL), and the /out option tells the compiler where to place the
resulting assembly. In this case, the /bin directory for the application is directly under the
"aspplus" vroot of this tutorial, and it is assumed this command is being run from the sample
directory, that is, ...\QuickStart\AspPlus\Samples\WebForms\Busobjs.

csc /t:library /out:..\..\..\..\bin\[Link] [Link]

For Visual Basic, the equivalent compilation command is:

vbc /t:library /out:..\..\..\..\bin\[Link] [Link]

For JScript, the equivalent compilation command is:

jsc /out:..\..\..\..\bin\[Link] [Link]

The component is now available to any Web Forms page in the application that needs to use it.
The following [Link] example illustrates this functionality.

VB [Link]
55
[Run Sample] | [View
Source]

Note the Import directive at the top of the page that specifies the namespace to include. Once
the namespace is included using this directive, the class can be used from within the Web Forms
page. Because the assembly is pre-loaded by the [Link] runtime, only a simple namespace
import is required to make the component available. The following code example the Import
directive.

<%@ Import Namespace="HelloWorld" %>

By default, [Link] loads all assemblies from the /bin directory when the application is started.
The assemblies to load are specifed through the configuration system. For details, see the
Configuration Overview section. Additional assemblies can be imported into an application using
configuration as well. For example:

<configuration>
<[Link]>
<compilation>
<assemblies>
<!--The following assemblies are loaded explicitly
from the global cache-->
<add assembly="[Link], Version=1.0.5000.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
<add assembly="[Link], Version=1.0.5000.0,
Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
<add assembly="[Link], Version=1.0.5000.0,
Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
<!--This tells [Link] to load all assemblies from /bin-->
<add assembly="*"/>
</assemblies>
</compilation>
</[Link]>
</configuration>

Note: Each assembly loaded from /bin is limited in scope to the application in which it is running.
This means that peer applications could potentially use different assemblies with the same class
or namespace names, without conflicting.

A Simple Two-Tier Web Forms Page

The classic use for an external component is to perform data access. This simplifies the code in
your page, improving readability and separating your user interface (UI) logic from the system
functionality. The following example demonstrates a simple two-tiered Web Forms page that uses
a data access component to retrieve product information.

VB [Link]
[Run Sample] | [View
Source]
56
The data access component takes a single parameter to its constructor specifying the
connection string to the product database. The Web Forms page calls the component's
GetCategories method to populate a drop-down list, and calls the component's
GetProductsForCategory method to display the products for the category selected by the user.

A Simple Three-Tier Web Forms Page

A three-tiered application model extends the two-tiered scenario to include business rules
between the UI and data access logic. This model allows UI developers to work with a higher level
of abstraction rather than directly manipulating data through low-level data access component
APIs. The middle business component typically enforces business rules and ensures that the
relationships and primary key constraints of the database are honored. The following example
uses the middle component to calculate a discount based on a two-digit Vendor ID entered by the
client.

VB [Link]
[Run Sample] | [View
Source]

Section Summary

1. The [Link] runtime finds business objects (local assemblies) in a well-known /bin
directory, directly under the application root. The /bin directory offers the following
advantages:
o No registration required. No registration is required to make an assembly
available to pages in the application. It is available by virtue of its location in the
/bin directory. Compiled code can be deployed by simply copying or FTPing to
this location.
o No server restart required. When any part of an [Link] Framework
application is changed (for example, when a DLL in /bin is replaced), new
requests immediately begin execution against the changed file or files. Currently
executing requests are allowed to complete before the old application is
gracefully torn down. The Web server does not require a restart when you
change your application, even when replacing compiled code.
o No namespace conflicts. Each assembly loaded from /bin is limited in scope to
the application in which it is running. This means that peer applications could
potentially use different assemblies with the same class or namespace names,
without conflicting.
2. Classes in an assembly are made available to a page in the application using an Import
directive within the .aspx file.
3. Two-tiered applications simplify the code in a page, improving readability and separating
user interface (UI) logic from system functionality.
4. Three-tiered applications extend the two-tiered model to enable UI developers to work
with a higher level of abstraction. The middle business component typically enforces
business rules and ensures that the relationships and primary key constraints of the
database are honored.
57
Authoring Custom Controls
Developing a Simple Custom Control
Defining Simple Properties
Defining Class Properties
Retrieving Inner Content
Developing a Composite Control
Handling Events in a Composite Control
Raising Events from a Composite Control
Maintaining State
Developing a Custom (Non-Composite) Control that Handles Post-back Data
Generating Client-side JavaScript for Custom Post-back
Developing a Templated Control
Developing a Templated Databound Control
Overriding Control Parsing
Defining a Custom Control Builder

This section of the QuickStart demonstrates how advanced developers can write their own
[Link] server controls that work within the [Link] page framework. By writing your own
custom [Link] server controls, you can encapsulate custom user interface and other
functionality in controls that can be reused on [Link] pages. The QuickStart provides an
introduction to authoring custom controls through hands-on examples. For more information
about control authoring, see Developing [Link] Server Controls in the Microsoft .NET
Framework SDK documentation.

Note: The controls described in this section might not work correctly at design time in a forms
designer such as Microsoft Visual Studio .NET, although they work properly at run time on
[Link] pages. To work in a designer, a control needs to apply design-time attributes not
described here. For details about the design-time attributes you need to apply, see Design-Time
Attributes for Components in the SDK documentation.

Developing a Simple Custom Control

It is easy to start authoring your own [Link] server controls. To create a simple custom control,
all you have to do is to define a class that derives from [Link] and override its
Render method. The Render method takes one argument of type
[Link]. The HTML that your control wants to send to the client is
passed as a string argument to the Write method of HtmlTextWriter.

The following example demonstrates a simple control that renders a message string.

VB [Link]
[Run Sample] | [View
Source]

Defining Simple Properties

Properties are like "smart" fields that have accessor methods. You should expose properties
instead of public fields from your controls because properties allow data hiding, can be versioned,
58
and are supported by visual designers. Properties have get/set accessor methods that set and
retrieve properties, and allow additional program logic to be performed if needed.

The following sample shows how to add simple properties that correspond to primitive data types
such as integer, Boolean, and string. The sample defines three properties - Message is of type
string, MessageSize is of type enumeration, and Iterations is of type integer. Note the page
syntax for setting simple and enumeration properties.

VB [Link]
[Run Sample] | [View
Source]

Defining Class Properties

If a class A has a property whose type is class B, then the properties of B (if any) are called
subproperties of A. The following sample defines a custom control SimpleSubProperty that has a
property of type Format. Format is a class that has two primitive properties - Color and Size,
which in turn become subproperties of SimpleSubProperty.

VB [Link]
[Run Sample] | [View Source]

Note that [Link] has a special syntax for setting subproperties. The following code example
shows how to declaratively set the [Link] and [Link] subproperties on
SimpleSubProperty. The "-" syntax denotes a subproperty.

<SimpleControlSamples:SimpleSubProperty Message="Hello There" Format-Color="red"


Format-Size="3" runat=server/>

Retrieving Inner Content

Every control has a Controls property that it inherits from [Link]. This is a
collection property that denotes the child controls (if any) of a control. If a control is not marked
with the ParseChildrenAttribute or marked with
ParseChildrenAttribute(ChildrenAsProperties = false), the [Link] page framework applies
the following parsing logic when the control is used declaratively on a page. If the parser
encounters nested controls within the control's tags, it creates instances of them and adds them
to the Controls property of the control. Literal text between tags is added as a LiteralControl.
Any other nested elements generate a parser error.
59
The following sample shows a custom control, SimpleInnerContent, that renders text added
between its tags by checking if a LiteralControl has been added to its Controls collection. If so,
it retrieves the Text property of the LiteralControl, and appends it to its output string.

VB [Link]
[Run Sample] | [View Source]

Note: If your custom control derives from WebControl, it will not have the parsing logic
described in the sample, because WebControl is marked with
ParseChildrenAttribute(ChildrenAsProperties = true), which results in a different parsing
logic. For more information about the ParseChildrenAttribute, see the SDK documentation.

Developing a Composite Control

You can author new controls by combining existing controls using class composition. Composite
controls are equivalent to user controls that are authored using [Link] page syntax. The main
difference between user controls and composite controls is that user controls are persisted as
.ascx text files, whereas composite controls are compiled and persisted in assemblies.

The key steps in developing a composite control are:

• Override the protected CreateChildControls method inherited from Control to create


instances of child controls and add them to the Controls collection.
• If new instances of your composite control will repeatedly be created on a page,
implement the [Link] interface. This is a tagging
interface that has no methods. When it is implemented by a control, the [Link] page
framework creates a new naming scope under that control. This ensures that the child
controls will have unique IDs in the hierarchical tree of controls.

You do not have to override the Render method because child controls provide rendering logic.
You can expose properties that synthesize properties of the child controls.

The following sample defines a composite control, Composition1, that combines a


[Link] and a [Link] [Link]. Composition1
exposes a custom property, Value, of type integer, that maps to the Text property of TextBox.

VB [Link]
[Run Sample] | [View
Source]
60

Handling Events in a Composite Control

A composite control can handle events raised by its child controls. This is accomplished by
providing event handling methods and attaching delegates to the events raised by the child
controls.

The following sample shows a composite control, Composition2, that adds two button controls
(named Add and Subtract) to the composite control from the previous example and provides
event handling methods for the Click events of the buttons. These methods increment and
decrement the Value property of Composition2. The CreateChildControls method of
Composition2 creates instances of event handlers (delegates) that reference these methods, and
attaches the delegates to the Click events of the Button instances. The end result is a control
that does its own event handling - when the Add button is clicked, the value in the text box is
incremented, and when the Subtract button is clicked, the value is decremented.

VB [Link]
[Run Sample] | [View
Source]

Raising Custom Events from a Composite Control

A composite control can define custom events that it raises in response to events raised by its
child controls.

The following example shows a composite control, Composition3, that raises a custom event,
Change, in response to the TextChanged event of the TextBox child control.

This is accomplished as follows:

• The custom Change event is defined using the standard event pattern. (This pattern
includes the definition of a protected OnChange method that raises the Change event.)

Public Event Change(Sender as Object, E as EventArgs)


Protected Sub OnChange(e As EventArgs)
Change(Me, e)
End Sub
C# VB JScript

• An event-handling method is defined for the TextChanged event of TextBox. This


method raises the Change event by invoking the OnChange method.

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


OnChange([Link])
End Sub
61
C# VB JScript

• The CreateChildControls method creates an instance of an event handler that


references the above method, and attaches the event handler to the TextChanged
event of the TextBox instance.

Protected Overrides Sub CreateChildControls()


...
Dim box As New TextBox()
AddHandler [Link], AddressOf TextBox_Change
...
End Sub
C# VB JScript
The Change event can be handled by a page that hosts the control, as shown in the following
sample. In the sample, the page provides an event-handling method for the Change event that
sets the Value property to zero if the number entered by the user is negative.

VB [Link]
[Run Sample] | [View
Source]

Maintaining State

Every Web Forms control has a ViewState property (inherited from Control) that enables it to
participate in ViewState management. The type of ViewState is [Link],
which is a data structure equivalent to a hashtable. A control can save data in ViewState as
key/value pairs. ViewState is persisted to a string variable by the [Link] page framework and
makes a round trip to the client as a hidden variable. Upon postback, the page framework parses
the input string from the hidden variable and populates the ViewState property of each control
in the control hierarchy of a page. A control can restore its state (set properties and fields to their
values before postback) using the ViewState property. Control developers should be aware that
there is a performance overhead in sending data by round trip to the client, and be judicious
about what they save in ViewState.

The following code example shows a property that is saved in ViewState.

Public Property [Text] As String


Get
Return CStr(ViewState("Text"))
End Get
Set
ViewState("Text") = Value
End Set
End Property
C# VB JScript

The following sample shows a custom control, Label, that has two properties, Text and
FontSize, that are saved in ViewState. The [Link] page that uses Label contains buttons that
62
have event handlers to increase the font size of the text in Label when a button is clicked.
Thus the font size increases every time a button is clicked. This is possible only due to state
management - Label needs to know what the font size was before postback in order to render
the next larger font size after postback.

VB [Link]
[Run Sample] | [View
Source]

Developing a Custom (Non-Composite) Control that Handles Postback Data

You authored a simple custom control at the beginning of this QuickStart. The following example
demonstrates a custom control that does something more meaningful - it renders an input box,
and reads in data entered by the user. A control that examines postback (input) data must
implement the [Link] interface. This signals to the [Link]
page framework that a control should participate in postback data handling. The page framework
passes input data to the LoadPostData method of this interface as key/value pairs. In its
implementation of this method, the control can examine the input data and update its properties
as shown below.

Private _value As Integer = 0


Public Function LoadPostData(postDataKey As String, values As
NameValueCollection) As Boolean
_value = [Link](values([Link]))
Return(False)
End Function
C# VB JScript

The following sample defines a custom control, NonComposition1, that implements


IPostBackDataHandler and has one property, Value. The control renders an HTML input box
whose text attribute is the string representation of Value. The property is set by examining
postback input data. The page that uses NonComposition1 also has two buttons that have event
handlers to increment and decrement the Value property of NonComposition1.

VB [Link]
[Run Sample] | [View Source]

Generating Client-side JavaScript for Custom Postback


63
If a control wants to capture postback events (form submissions from a client), it must
implement the [Link] interface. This signals to the [Link]
page framework that a control wants to be notified of a postback event. The
RaisePostBackEvent method allows the control to handle the event, and to raise other events.
Additionally, the [Link] page framework has a custom event architecture that allows a control
to generate client-side JavaScript that initiates custom postback. Normally, postback is initiated
by only a few elements such as a Submit button or an Image button. However, by emitting client-
side JavaScript, a control can also initiate postback from other HTML elements.

The following example defines a custom control, NonComposition2, that builds on the previous
example, NonComposition1. In addition to the interface provided by NonComposition1, it renders
two HtmlButtons that generate client-side JavaScript to cause postback when clicked. The name
attributes of these buttons are Add and Subtract. The name attribute is passed as a string
argument to RaisePostBackEvent by the page framework. NonComposition2 implements
RaisePostBackEvent to increment the Value property if Add is clicked and to decrement Value
if Subtract is clicked, as shown below.

Public Sub RaisePostBackEvent(eventArgument As String)


If eventArgument = "Add" Then
[Link] = [Link] + 1
Else
[Link] = [Link] - 1
End If
End Sub
C# VB JScript

The user interface that is presented to the client is identical to that in the previous example;
however, the entire UI is rendered by one custom control that also handles the postback events.
The page developer can simply add NonComposition2 to the page, without providing any event
handling logic. The following sample presents this code in action.

VB [Link]
[Run Sample] | [View Source]

Developing a Templated Control

The [Link] page framework allows control developers to author controls that separate the user
interface from the control logic through the use of templates. Page developers can customize the
presentation of the control by providing the UI as parameters between template tags.

Templated controls have one or more properties of type [Link], as shown


in the following example.

Public Property <TemplateContainer(GetType(Template1VB))> MessageTemplate As


ITemplate
C# VB JScript
64
In the code above, the attribute specifies the type of the container (parent) control.

The ITemplate interface has one method, InstantiateIn, that creates a control instance
dynamically. This is invoked on the ITemplate property in the CreateChildControls method, as
shown in the following example.

Protected Overrides Sub CreateChildControls()


If MessageTemplate <> Null Then
[Link](Me)
End if
...
End Sub
C# VB JScript

The following sample shows a simple templated control and an [Link] page that uses it.

VB [Link]
[Run Sample] | [View
Source]

Developing a Templated Databound Control

The following sample shows a more complex use of templates to create a databound control. The
Repeater control defined in this example is similar to the
[Link] control.

VB [Link]
[Run Sample] | [View
Source]

The following sample modifies the preceding sample so that a page consumer can walk its Items
collection during postback to pull out values from it.

VB [Link]
[Run Sample] | [View
65
Source]

Overriding Control Parsing

As you saw in Retrieving Inner Content , if a control A has nested controls within its control tags
on a page, the page parser adds instances of those controls to A's Controls collection. This is
done by invoking the AddSubParsedObject method of A. Every control inherits this method
from Control; the default implementation simply inserts a child control into the control hierarchy
tree. A control can override the default parsing logic by overriding the AddSubParsedObject
method. Note that this discussion is somewhat simplified; more details are given in the next
example.

The following sample defines a custom control, CustomParse1, that overrides the default parsing
logic. When a child control of a certain type is parsed, it adds it to a collection. The rendering
logic of CustomParse1 is based on the number of items in that collection. A simple custom
control, Item, is also defined in the sample.

VB [Link]
[Run Sample] | [View
Source]

Note: If your custom control derives from WebControl, it will not have the parsing logic
described in the sample, because WebControl is marked with
ParseChildrenAttribute(ChildrenAsProperties = true), which results in a different parsing
logic. For more information about the ParseChildrenAttribute, see the SDK documentation. The
Retrieving Inner Content topic also describes this issue in more detail.

Defining a Custom Control Builder

The [Link] page framework uses classes called control builders to process the declarations
within control tags on a page. Every Web Forms control is associated with a default control
builder class, [Link]. The default control builder adds a child control
to the Controls collection for every nested control that it encounters within control tags.
Additionally, it adds Literal controls for text between nested control tags. You can override this
default behavior by associating a custom control builder class with your control. This is done by
applying a control builder attribute to your control, as shown in the following example.

Public Class <ControlBuilderAttribute(GetType(CustomParse2ControlBuilderVB))>


_
CustomParse2VB : Inherits Control
C# VB JScript

The ControlBuilderAttribute above associates the CustomParse2ControlBuilder class with


the CustomParse2 control. You can define your own custom control builder by deriving from
ControlBuilder and overriding its methods.
66
The following sample defines a custom control builder that overrides the
GetChildControlType method inherited from ControlBuilder. This method returns the type of
the control to be added and can be used to decide which controls will be added. In the example,
the control builder will add a child control only if the tag name is "customitem". The code for the
control is very similar to the previous example, except for the addition of the custom attribute.

VB [Link]
[Run Sample] | [View
Source]
Web Forms Controls Reference
[Link]
[Link]
[Link]

HTML server controls are HTML elements exposed to the server so you can program against
them. HTML server controls expose an object model that maps very closely to the HTML elements
that they render.

HtmlAnchor HtmlButton HtmlForm HtmlGenericControl


HtmlInputButton HtmlInputButton HtmlInputButton
HtmlImage
(Button) (Reset) (Submit)
HtmlInputCheckBox HtmlInputFile HtmlInputHidden HtmlInputImage
HtmlInputText
HtmlInputRadioButton HtmlInputText (Text) HtmlSelect
(Password)
HtmlTable HtmlTableCell HtmlTableRow HtmlTextArea

[Link]

Web server controls are [Link] server controls with an abstract, strongly-typed object model.
Web server controls include not only form-type controls such as buttons and text boxes, but also
special-purpose controls such as a calendar. Web server controls are more abstract than HTML
server controls, in that their object model does not necessarily reflect HTML syntax.

AdRotator Button Calendar CheckBox


CheckBoxList CompareValidator CustomValidator DataGrid
DataList DropDownList HyperLink Image
ImageButton Label LinkButton ListBox
Panel PlaceHolder RadioButton RadioButtonList
RangeValidator RegularExpressionValidator Repeater RequiredFieldValidator
Table TableCell TableRow TextBox
ValidationSummary XML
Web Forms Syntax Reference
67
[Link] Web Forms Syntax Elements
Rendering Code Syntax
Declaration Code Syntax
[Link] Server Control Syntax
[Link] Html Server Control Syntax
Databinding Syntax
Object Tag Syntax
Server Side Comment Syntax
Server Side Include Syntax
[Link] Web Forms Syntax Elements

An [Link] Web Forms page is a declarative text file with an .aspx file name extension. In
addition to static content, you can use eight distinct syntax markup elements. This section of the
QuickStart reviews each of these syntax elements and provides examples demonstrating their
use.

Rendering Code Syntax: <% %> and <%= %>

Code rendering blocks are denoted with <% ... %> elements, allow you to custom-control
content emission, and execute during the render phase of Web Forms page execution. The
following example demonstrates how you can use them to loop over HTML content.

<% For I=0 To 7 %>


<font size="<%=i%>"> Hello World! </font> <br>
<% Next %>
C# VB JScript

VB [Link]
[Run Sample] | [View
Source]

Code enclosed by <% ... %> is just executed, while expressions that include an equal sign, <%=
... %>, are evaluated and the result is emitted as content. Therefore <%="Hello World" %>
renders the same thing as the C# code <% [Link]("Hello World"); %>.

Note: For languages that use marks to end or separate statements (for example, the semicolon
(;) in C#), it is important to place those marks correctly depending on how your code should be
rendered.

C# code
<% [Link]("Hello World"); A semicolon is necessary to end the statement.
%>
<%="Hello World"; %> Wrong: Would result in "[Link]("Hello
World";);".
<%="Hello World" %> A semicolon is not necessary.
68

Declaration Code Syntax: <script runat="server">

Code declaration blocks define member variables and methods that will be compiled into the
generated Page class. These blocks can be used to author page and navigation logic. The
following example demonstrates how a Subtract method can be declared within a <script
runat="server"> block, and then invoked from the page.

<script language="VB" runat=server>


Function Subtract(num1 As Integer, num2 As Integer) As Integer
Return(num1 - num2)
End Function
</script>

<%
...
number = subtract(number, 1)
...
%>
C# VB JScript

VB [Link]
[Run Sample] | [View
Source]

Important: Unlike ASP -- where functions could be declared within <% %> blocks -- all
functions and global page variables must be declared in a <script runat=server> tag.
Functions declared within <% %> blocks will now generate a syntax compile error.

[Link] Server Control Syntax

Custom [Link] server controls enable page developers to dynamically generate HTML user
interface (UI) and respond to client requests. They are represented within a file using a
declarative, tag-based syntax. These tags are distinguished from other tags because they contain
a "runat=server" attribute. The following example demonstrates how an <asp:label
runat="server"> server control can be used within an [Link] page. This control corresponds
to the Label class in the [Link] namespace, which is included by
default.

By adding a tag with the ID "Message", an instance of Label is created at run time:

<asp:label id="Message" font-size=24 runat="server"/>


The control can then be accessed using the same name. The following line sets the Text property
of the control.

[Link] = "Welcome to [Link]"


C# VB JScript
69

VB [Link]
[Run Sample] | [View
Source]

[Link] HTML Server Control Syntax

HTML server controls enable page developers to programmatically manipulate HTML elements
within a page. An HTML server control tag is distinguished from client HTML elements by means
of a "runat=server" attribute. The following example demonstrates how an HTML <span
runat=server> server control can be used within an [Link] page.

As with other server controls, the methods and properties are accessible programmatically, as
shown in the following example.

<script language="VB" runat="server">


Sub Page_Load(sender As Object, e As EventArgs)
[Link] = "Welcome to [Link]"
End Sub
</script>
...
<span id="Message" style="font-size:24" runat="server"/>
C# VB JScript

VB [Link]
[Run Sample] | [View
Source]

Data Binding Syntax: <%# %>

The data binding support built into [Link] enables page developers to hierarchically bind control
properties to data container values. Code located within a <%# %> code block is only executed
when the DataBind method of its parent control container is invoked. The following example
demonstrates how to use the data binding syntax within an <asp:datalist runat=server>
control.

Within the datalist, the template for one item is specified. The content of the item template is
specified using a data binding expression and the [Link] refers to the data source
used by the datalist MyList.

<asp:datalist id="MyList" runat=server>


70
<ItemTemplate>
Here is a value: <%# [Link] %>
</ItemTemplate>
</asp:datalist>
In this case the data source of the MyList control is set programmatically, and then DataBind()
is called.

Sub Page_Load(sender As Object, e As EventArgs)


Dim items As New ArrayList()

[Link]("One")
[Link]("Two")
[Link]("Three")

[Link] = items
[Link]()
End Sub
C# VB JScript

Calling the DataBind method of a control causes a recursive tree walk from that control on down
in the tree; the DataBinding event is raised on each server control in that hierarchy, and data
binding expressions on the control are evaluated accordingly. So, if the DataBind method of the
page is called, then every data binding expression within the page will be called.

VB [Link]
[Run Sample] | [View
Source]

Object Tag Syntax: <object runat="server" />

Object tags enable page developers to declare and create instances of variables using a
declarative, tag-based syntax. The following example demonstrates how the object tag can be
used to create an instance of an ArrayList class.

<object id="items" class="[Link]" runat="server"/>


The object will be created automatically at run time and can then be accessed through the ID
"items".

Sub Page_Load(sender As Object, e As EventArgs)


[Link]("One")
[Link]("Two")
[Link]("Three")
...
End Sub
C# VB JScript
71

VB [Link]
[Run Sample] | [View
Source]

Server-Side Comment Syntax: <%-- Comment --%>

Server-side comments enable page developers to prevent server code (including server controls)
and static content from executing or rendering. The following sample demonstrates how to block
content from executing and being sent down to a client. Note that everything between <%-- and
--%> is filtered out and only visible in the original server file, even though it contains other
[Link] directives.

<%--
<asp:calendar id="MyCal" runat=server/>
<% For I=0 To 44 %>
Hello World <br>
<% Next %>
--%>
C# VB JScript

VB [Link]
[Run Sample] | [View
Source]

Server-Side Include Syntax: <-- #Include File="[Link]" -->

Server-side #Includes enable developers to insert the raw contents of a specified file anywhere
within an [Link] page. The following sample demonstrates how to insert a custom header and
footer within a page.

<!-- #Include File="[Link]" -->


...
<!-- #Include File="[Link]" -->

VB [Link]
72
[Run Sample] | [View
Source]
Introducing XML Web services

The Internet is quickly evolving from today's Web sites that just deliver user interface pages to
browsers to a next generation of programmable Web sites that directly link organizations,
applications, services, and devices with one another. These programmable Web sites become
more than passively accessed sites - they become reusable, intelligent XML Web services.

The common language runtime provides built-in support for creating and exposing Web Services,
using a programming abstraction that is consistent and familiar to both [Link] Web Forms
developers and existing Visual Basic users. The resulting model is both scalable and extensible,
and embraces open Internet standards (HTTP, XML, SOAP, WSDL) so that it can be accessed and
consumed from any client or Internet-enabled device.

XML Web services created using [Link]

[Link] provides support for XML Web services with the .asmx file. An .asmx file is a text file
that is similar to an .aspx file. These files can be part of an [Link] application that includes
.aspx files. These files are then URI-addressable, just as .aspx files are.

The following example shows a very simple .asmx file.

<%@ WebService Language="VB" Class="HelloWorld" %>

Imports System
Imports [Link]

Public Class HelloWorld :Inherits WebService

<WebMethod()> Public Function SayHelloWorld() As String


Return("Hello World")
End Function

End Class
C# VB JScript

This file starts with an [Link] directive WebService, and sets the language to C#, Visual Basic,
or JScript. Next, it imports the namespace [Link]. You must include this
namespace. Next, the class HelloWorld is declared. This class is derived from the base class
WebService; note that deriving from the WebService base class is optional. Finally, any
methods that will be accessible as part of the service have the attribute [WebMethod] in C#,
<WebMethod()> in Visual Basic, or WebMethodAttribute in JScript, in front of their
signatures.

To make this service available, we might name the file [Link] and place it on a
server called [Link] inside a virtual directory called someFolder. Using a Web
browser, you could then enter the URL
[Link] and the resulting page would
show the public methods for this XML Web service (those marked with the WebMethod
attribute), as well as which protocols (such as SOAP, or HTTP GET) you can use to invoke these
methods.
73
Entering the address: [Link]
into the browser returns a Web Service Description Language (WSDL) document. This WSDL
document is very important, and is used by clients that will access the service.

Accessing XML Web services

In addition to the [Link] server side technology that allows developers to create XML Web
services, the .NET Framework provides a sophisticated set of tools and code to consume XML Web
services. Because XML Web services are based on open protocols such as the Simple Object
Access Protocol (SOAP), this client technology can also be used to consume XML Web services not
created using [Link].

Within the SDK, there is a tool called the Web Services Description Language tool ([Link]).
This command-line tool is used to create proxy classes from WSDL. For example, you could
enter:

WSDL [Link]

to create a proxy class called [Link].

This class would look very similar to the class created in the previous section. It would contain a
method called SayHelloWorld that returns a string. Compiling this proxy class into an application
and then calling this proxy class's method results in the proxy class packaging a SOAP request
across HTTP and receiving the SOAP-encoded response, which is then marshaled as a string.

From the client perspective, the code would be simple, as shown in the following example.

Dim myHelloWorld As New HelloWorld()


Dim sReturn As String = [Link]()
C# VB JScript

The return would be "Hello World".

The rest of this section deals with more advanced XML Web services topics, such as sending and
receiving complex data types. There is also a section on Text Pattern Matching, a technology that
addresses any URI that returns text as if it were a XML Web service. You can also perform data
binding operations with XML Web services; this topic is discussed in the Data section.

Write a Simple XML Web service

You can write a simple XML Web service in a few minutes using any text editor. The service
demonstrated in this section, MathService, exposes methods for adding, subtracting, dividing,
and multiplying two numbers. At the top of the page, the following directive identifies the file as a
XML Web service in addition to specifying the language for the service (C#, in this case).

<%@ WebService Language="C#" Class="MathService" %>

In this same file, you define a class that encapsulates the functionality of your service. This class
should be public, and can optionally inherit from the XML Web service base class. Each method
that will be exposed from the service is flagged with a [WebMethod] attribute in front of it.
Without this attribute, the method will not be exposed from the service. This is sometimes useful
for hiding implementation details called by public XML Web service methods, or in the case
where the XML Web service class is also used in local applications (a local application can use
any public class, but only WebMethod classes are remotely accessible as XML Web services).
74

Imports System
Imports [Link]

Public Class MathService : Inherits WebService

<WebMethod()> Public Function Add(a As Integer, b As Integer) As Integer


Return(a + b)
End Function

End Class
C# VB JScript

XML Web service files are saved under the .asmx file extension. Like .aspx files, these are
automatically compiled by the [Link] runtime when a request to the service is made
(subsequent requests are serviced by a cached precompiled type object). In the case of
MathService, you have defined the WebService class in the .asmx file itself. Note that if an
.asmx file is requested by a browser, the [Link] runtime returns a XML Web service Help page
that describes the XML Web service.

VB [Link]
VB [Link]?wsdl
[Run Sample] | [View
[View Sample]
Source]

Precompiled XML Web services

If you have a precompiled class that you want to expose as a XML Web service (and this class
exposes methods marked with the [WebMethod] attribute), you can create an .asmx file with
only the following line.
<%@ WebService Class="[Link]" %>

[Link] defines the XML Web service class, and is contained in the
\bin subdirectory of the [Link] application.

Consuming a XML Web service from a Client Application

To consume this service, you need to use the Web Services Description Language command-line
tool ([Link]) included in the SDK to create a proxy class that is similar to the class defined in
the .asmx file. (It will contain only the WebMethod methods.) Then, you compile your code with
this proxy class included.

[Link] accepts a variety of command-line options, however to create a proxy only one option
is required: the URI to the WSDL. In this example, we are passing a few extra options that
specify the preferred language, namespace, and output location for the proxy. We are also
compiling against a previously saved WSDL file instead of the URI to the service itself:

[Link] /l:CS /n:MathService /out:[Link] [Link]


75
Once the proxy class exists, you can create objects based on it. Each method call made with
the object then goes out to the URI of the XML Web service (usually as a SOAP request).

VB [Link]
[Run Sample] | [View Source]
XML Web service Type Marshaling

This section illustrates that various data types can be passed to and returned from XML Web
service methods. Because the XML Web services implementation is built on top of the XML
Serialization architecture, it supports a significant number of data types. The following table lists
the supported data types for XML Web service methods when using the SOAP protocol (for
example, using the proxy generated by the Web Services Description Language tool, [Link]).

Type Description
Primitive Types Standard primitive types. The complete list of supported
primitives are String, Char, Byte, Boolean, Int16, Int32,
Int64, UInt16, UInt32, UInt64, Single, Double, Guid,
Decimal, DateTime (as XML's dateTime), DateTime (as
XML's date), DateTime (as XML's time), and
XmlQualifiedName (as XML's QName).
Enum Types Enumeration types, for example, "public enum color
{ red=1, blue=2 }"
Arrays of Primitives, Enums Arrays of the above primitives, such as string[] and
int[]
Classes and Structs Class and struct types with public fields or properties.
The public properties and fields are serialized.
Arrays of Classes (Structs) Arrays of the above.
DataSet [Link] DataSet Types (see the next section for an
example). DataSets can also appear as fields in structs
or classes.

Note: Microsoft Visual Studio .NET and the [Link]


SDK utility have support for "strong-typing" a DataSet.
These tools generate a class that inherits from DataSet
to produce DataSet1, adding several
methods/properties/etc that are specific to a particular
XML schema. If you pass DataSet, XML Web services
always transmits the schema along with the data (so it
knows what tables and columns you are passing), and
their types (for example, int, string). If you pass a
subclass of DataSet (for example, DataSet1), XML Web
services assumes you are adding tables/columns in the
constructor, and assumes that those tables/columns
represent your schema.
76
Arrays of DataSet Arrays of the above.
XmlNode XmlNode is an in-memory representation of an XML
fragment (like a lightweight XML document object
model). For example, "<comment>This
is<b>pretty</b> neat</comment>" could be stored in
an XmlNode. You can pass XmlNodes as parameters,
and they are added to the rest of the XML being passed
to the XML Web service (the other parameters) in a
SOAP-compliant manner. The same is true for return
values. This allows you to pass or return XML whose
structure changes from call to call, or where you may
not know all the types being passed. XmlNode can also
appear as fields in structs or classes.
Arrays of XmlNode Arrays of above.
Return values:

Whether calling a XML Web service using SOAP or HTTP GET/POST, all the above types are
supported for return values.

Parameters:

Both by-value and by-reference (in/out) parameters are supported when using the SOAP protocol. By-
reference parameters can send the value both ways: up to the server, and back to the client. When
passing input parameters to a XML Web service using HTTP GET/POST, only a limited set of data
types are supported, and they must be by-value parameters. The supported types for HTTP GET/POST
parameters are listed below:

Type Description
Primitive Types (limited) Most standard primitive types. The complete list of
supported primitives are Int32, String, Int16, Int64,
Boolean, Single, Double, Decimal, DateTime, UInt16,
UInt32, UInt64, and Currency. From the client's
perspective, all these types turn into string.
Enum Types Enumeration types, for example, "public enum color
{ red=1, blue=2 }". From the client's perspective,
enums become classes with a static const string for each
value.
Arrays of Primitives, Enums Arrays of the above primitives, such as string[] and int[]

The following example demonstrates the use of the types listed above, using a SOAP proxy
generated from [Link]. Note that because there is more than one public class defined in the
.asmx file, you must specify which is to be treated as the XML Web service class using the
"Class" attribute of the XML Web service directive:

<%@ WebService Language="C#" Class="DataTypes" %>


77

VB [Link]
VB [Link]?wsdl
[Run Sample] | [View
[View Sample]
Source]

• The SayHello method shows returning a String from a service.


• The SayHelloName method returns a String, and also takes a String as a parameter.
• The GetIntArray method shows how to return an array of integers.
• The GetMode method returns an enum value.
• The GetOrder method returns a class (which is almost the same as a struct here).
• The GetOrders method returns an array of Order objects.

Using the [Link] command line proxy generation tool, the marshaling of these data types is
transparent to the consuming client application. A sample client application for the above XML
Web service follows:

VB [Link]
[Run Sample] | [View Source]
Use Data in XML Web services

This sample shows how DataSets, a powerful new XML-based way to represent disconnected
data, can be returned from a XML Web service method. This is an extremely powerful use of
XML Web services, as DataSets can store complex information and relationships in an intelligent
structure. By exposing DataSets through a service, you can limit the database connections your
data server is experiencing.

The method GetTitleAuthors connects to a database and issues two SQL statements: one that
returns a list of authors, and another that returns a list of book titles. It places both result sets
into a single DataSet called ds, and returns this DataSet.

The method PutTitleAuthors illustrates a XML Web service method that takes a DataSet as a
parameter, returning an integer that represents the number of rows received in the "Authors"
table of the DataSet. Although the implementation of this method is somewhat simplistic, this
method could also intelligently merge the passed data with the database server.
78

VB [Link]
VB [Link]?wsdl
[Run Sample] | [View
[View Sample]
Source]

The client application for this XML Web service calls GetTitleAuthors and binds the Authors table
to a DataGrid control, as you've seen in previous examples. To illustrate the PutTitleAuthors
method, the client removes three rows of data from the DataSet before calling this method,
printing out the number of rows received by the service.

VB [Link]
[Run Sample] | [View Source
Use Objects and Intrinsics

This sample illustrates how to access [Link] intrinsics such as the Session and Application
objects. It also shows how to turn off Session on a per-[WebMethod] basis.

The first method in the sample .asmx file, UpdateHitCounter, accesses the Session and adds 1
to the "HitCounter" value. It then returns this value as a String. The second method,
UpdateAppCounter does the same thing, but with the Application. Notice the following:

<WebMethod(EnableSession:=true)>
C# VB JScript

Session state for XML Web services is disabled by default, and you have to use a special attribute
property to enable Sessions. However, Sessions aren't needed for this object, since it only uses
the Application object.

VB [Link]
VB [Link]?wsdl
[Run Sample] | [View
[View Sample]
Source]

When the client proxy is accessed, it contains a cookie collection. This collection is used to accept
and return the APSESSIONID cookie that [Link] uses to track Sessions. This is what allows this
client to receive varying answers to the Session hit method.
79

VB [Link]
[Run Sample] | [View Source]
HTML Text Pattern Matching

This example demonstrates how to create a client proxy for any URI that serves up text. Instead
of authoring the .asmx file, you can create a WSDL file that describes an HTML (or XML or any
other nonbinary format) page you currently offer. The WSDL can be used to generate a client
proxy, using the [Link] command line tool that will use RegEx to parse the named HTML page
and extract values.

You can do this by adding <Match> tags in the Response section of the WSDL. These tags take
an attribute called pattern, which is the Regular Expression that corresponds to the piece of text
on the page that is the property's value. (Note: the property from the proxy class is read-only.)

The consuming code can then create the object, access the Matches object that is returned by
the functioned name in the WSDL, and gain access to any piece of the HTML as a property. No
understanding of WSDL, regular expressions, or even HTML is needed to use the proxy class. It
behaves like any other .NET Framework class would.

VB [Link]
[Run Sample] | [View
Source]
Application Overview
What is an [Link] Application?
Creating an Application
Lifetime of an Application
A Note on Multiple Threads
Section Summary
What is an [Link] Application?

[Link] defines an application as the sum of all files, pages, handlers, modules, and executable
code that can be invoked or run in the scope of a given virtual directory (and its subdirectories)
on a Web application server. For example, an "order" application might be published in the
"/order" virtual directory on a Web server computer. For IIS the virtual directory can be set up in
the Internet Services Manager; it contains all subdirectories, unless the subdirectories are virtual
directories themselves.

Each [Link] Framework application on a Web server is executed within a unique .NET
Framework application domain, which guarantees class isolation (no versioning or naming
conflicts), security sandboxing (preventing access to certain machine or network resources), and
static variable isolation.
80
[Link] maintains a pool of HttpApplication instances over the course of a Web application's
lifetime. [Link] automatically assigns one of these instances to process each incoming HTTP
request that is received by the application. The particular HttpApplication instance assigned is
responsible for managing the entire lifetime of the request and is reused only after the request
has been completed. This means that user code within the HttpApplication does not need to be
reentrant.

Creating an Application

To create an [Link] Framework application you can use an existing virtual directory or create a
new one. For example, if you installed Windows 2000 Server including IIS, you probably have a
directory C:\InetPub\WWWRoot. You can configure IIS using the Internet Services Manager,
available under Start -> Programs -> Administrative Tools. Right-click on an existing directory
and choose either New (to create a new virtual directory) or Properties (to promote an existing
regular directory).

By placing a simple .aspx page like the following in the virtual directory and accessing it with the
browser, you trigger the creation of the [Link] application.

<%@Page Language="VB"%>
<html>
<body>
<h1>hello world, <% [Link]([Link]()) %></h1>
</body>
</html>
C# VB JScript

Now you can add appropriate code to use the Application object--to store objects with application
scope, for example. By creating a [Link] file you also can define various event handlers-- for
the Application_Start event, for example.

Lifetime of an Application

An [Link] Framework application is created the first time a request is made to the server;
before that, no [Link] code executes. When the first request is made, a pool of
HttpApplication instances is created and the Application_Start event is raised. The
HttpApplication instances process this and subsequent requests, until the last instance exits
and the Application_End event is raised.

Note that the Init and Dispose methods of HttpApplication are called per instance and thus
can be called several times between Application_Start and Application_End. Only these
events are shared among all instances of HttpApplication in one [Link] application.

A Note on Multiple Threads

If you use objects with application scope, you should be aware that [Link] processes requests
concurrently and that the Application object can be accessed by multiple threads. Therefore the
following code is dangerous and might not produce the expected result, if the page is repeatedly
requested by different clients at the same time.

<%
Application("counter") = CType(Application("counter"), Int32) + 1
%>
81
C# VB JScript

To make this code thread safe, serialize the access to the Application object using the Lock and
UnLock methods. However, doing so also means accepting a considerable performance hit:

<%
[Link]()
Application("counter") = CType(Application("counter"), Int32) + 1
[Link]()
%>
C# VB JScript

Another solution is to make the object stored with an application scope thread safe. For example,
note that the collection classes in the [Link] namespace are not thread safe for
performance reasons.

Section Summary

1. [Link] Framework applications consist of everything under one virtual directory of the
Web server.
2. You create an [Link] Framework application by adding files to a virtual directory on
the Web server.
3. The lifetime of an [Link] Framework application is marked by Application_Start and
Application_End events.
4. Access to application-scope objects must be safe for multithreaded access.

Using the [Link] File


The [Link] File
Application or Session-Scoped Events
Application or Session-Scoped Objects
Section Summary
The [Link] File

In addition to writing UI code, developers can also add application level logic and event handling
code into their Web applications. This code does not handle generating UI and is typically not
invoked in response to individual page requests. Instead, it is responsible for handling higher-
level application events such as Application_Start, Application_End, Session_Start,
Session_End, and so on. Developers author this logic using a [Link] file located at the
root of a particular Web application's virtual directory tree. [Link] automatically parses and
compiles this file into a dynamic .NET Framework class--which extends the HttpApplication base
class--the first time any resource or URL within the application namespace is activated or
requested.

The [Link] file is parsed and dynamically compiled by [Link] into a .NET Framework class
the first time any resource or URL within its application namespace is activated or requested. The
[Link] file is configured to automatically reject any direct URL request so that external users
cannot download or view the code within.

Application or Session-Scoped Events

Developers can define handlers for events of the HttpApplication base class by authoring
methods in the [Link] file that conform to the naming pattern
"Application_EventName(AppropriateEventArgumentSignature)". For example:
82

<script language="VB" runat="server">

Sub Application_Start(Sender As Object, E As EventArgs)


' Application startup code goes here
End Sub
</script>
C# VB JScript

If the event handling code needs to import additional namespaces, the @ import directive can be
used on an .aspx page, as follows:

<%@ Import Namespace="[Link]" %>

The following sample illustrates the lifetime of Application, Session, and Request.

VB [Link]
[Run Sample] | [View
Source]

The first time the page is opened, the Start event is raised for the application and the session:

Sub Application_Start(Sender As Object, E As EventArgs)


' Application startup code goes here
End Sub

Sub Session_Start(Sender As Object, E As EventArgs)


[Link]("Session is Starting...<br>")
[Link] = 1
End Sub
C# VB JScript

The BeginRequest and EndRequest events are raised on each request. When the page is
refreshed, only messages from BeginRequest, EndRequest, and the Page_Load method will
appear. Note that by abandoning the current session (click the "End this session" button) a new
session is created and the Session_Start event is raised again.

Application or Session-Scoped Objects

Static objects, .NET Framework classes, and COM components all can be defined in the
[Link] file using the object tag. The scope can be appinstance, session, or application.
The appinstance scope denotes that the object is specific to one instance of HttpApplication
and is not shared.

<object id="id" runat="server" class=".NET Framework class Name"


scope="appinstance"/>
<object id="id" runat="server" progid="COM ProgID" scope="session"/>
<object id="id" runat="server" classid="COM ClassID" scope="application"/>
83
Section Summary

1. [Link] Framework applications can define event handlers with application-wide or


session-wide scope in the [Link] file.
2. [Link] Framework applications can define objects with application-wide or session-
wide scope in the [Link] file.

Managing Application State


Using Application State
Using Session State
Using Client-Side Cookies
Using ViewState
Section Summary
Using Application State

This sample illustrates the use of application state to read a dataset in Application_Start.

VB [Link]
[Run Sample] | [View
Source]

Because an application and all the objects it stores can be concurrently accessed by different
threads, it is better to store only infrequently modified data with application scope. Ideally an
object is initialized in the Application_Start event and further access is read-only.

In the following sample a file is read in Application_Start (defined in the [Link] file) and
the content is stored in a DataView object in the application state.

Sub Application_Start()
Dim ds As New DataSet()

Dim fs As New
FileStream([Link]("[Link]"),[Link],[Link])
Dim reader As New StreamReader(fs)
[Link](reader)
[Link]()

Dim view As New DataView ([Link](0))


Application("Source") = view
End Sub
C# VB JScript

In the Page_Load method, the DataView is then retrieved and used to populate a DataGrid
object:

Sub Page_Load(sender As Object, e As EventArgs)


Dim Source As New DataView = CType(Application("Source"), DataView)
84
...
[Link] = Source
...
End Sub
C# VB JScript

The advantage of this solution is that only the first request pays the price of retrieving the data.
All subsequent requests use the already existing DataView object. As the data is never modified
after initialization, you do not have to make any provisions for serializing access.

Using Session State

The following sample illustrates the use of session state to store volatile user preferences.

VB [Link]
[Run Sample] | [View
Source]

To provide individual data for a user during a session, data can be stored with session scope. In
the following sample, values for user preferences are initialized in the Session_Start event in
the [Link] file.

Sub Session_Start()
Session("BackColor") = "beige"
...
End Sub
C# VB JScript

In the following customization page, values for user preferences are modified in the
Submit_Click event handler according to user input.

Protected Sub Submit_Click(sender As Object, e As EventArgs)


Session("BackColor") = [Link]
...

[Link](State("Referer").ToString())
End Sub
C# VB JScript

The individual values are retrieved using the GetStyle method:

Protected GetStyle(key As String) As String


Return(Session(key).ToString())
End Sub
C# VB JScript

The GetStyle method is used to construct session-specific styles:


85
<style>
body
{
font: <%=GetStyle("FontSize")%> <%=GetStyle("FontName")%>;
background-color: <%=GetStyle("BackColor")%>;
}
a
{
color: <%=GetStyle("LinkColor")%>
}
</style>

To verify that the values are really stored with session scope, open the sample page twice, then
change one value in the first browser window and refresh the second one. The second window
picks up the changes because both browser instances share a common Session object.

Configuring session state: Session state features can be configured via the <sessionState>
section in a [Link] file. To double the default timeout of 20 minutes, you can add the
following to the [Link] file of an application:

If cookies are not available, a session can be tracked by adding a session identifier to the URL.
This can be enabled by setting the following:

By default, [Link] will store the session state in the same process that processes the request,
just as ASP does. Additionally, [Link] can store session data in an external process, which can
even reside on another machine. To enable this feature:

• Start the [Link] state service, either using the Services snap-in or by executing "net
start aspnet_state" on the command line. The state service will by default listen on port
42424. To change the port, modify the registry key for the service:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\aspnet_state\Parameters\
Port
• Set the mode attribute of the <sessionState> section to "StateServer".
• Configure the stateConnectionString attribute with the values of the machine on
which you started aspnet_state.

The following sample assumes that the state service is running on the same machine as the Web
server ("localhost") and uses the default port (42424):
<sessionState
mode="StateServer"
stateConnectionString="tcpip=localhost:42424"
/>
Note that if you try the sample above with this setting, you can reset the Web server (enter
iisreset on the command line) and the session state value will persist.

Using Client-Side Cookies

The following sample illustrates the use of client-side cookies to store volatile user preferences.
86

VB [Link]
[Run Sample] | [View
Source]

Storing cookies on the client is one of the methods that [Link]'s session state uses to associate
requests with sessions. Cookies can also be used directly to persist data between requests, but
the data is then stored on the client and sent to the server with every request. Browsers place
limits on the size of a cookie; therefore, only a maximum of 4096 bytes is guaranteed to be
acceptable.

When the data is stored on the client, the Page_Load method in the file [Link] checks
whether the client has sent a cookie. If not, a new cookie is created and initialized and stored on
the client:

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


If [Link]("preferences1") = Null Then
Dim cookie As New HttpCookie("preferences1")
[Link]("ForeColor", "black")
...
[Link](cookie)
End If
End Sub
C# VB JScript

On the same page, a GetStyle method is used again to provide the individual values stored in
the cookie:

Protected Function GetStyle(key As String) As String


Dim cookie As HttpCookie = [Link]("preferences1")
If cookie <> Null Then
Select Case key
Case "ForeColor"
Return([Link]("ForeColor"))
Case ...
End Select
End If
Return("")
End Function
C# VB JScript

Verify that the sample works by opening the [Link] page and modifying the preferences.
Open the page in another window, it should pick up the new preferences. Close all browser
windows and open the [Link] page again. This should delete the temporary cookie and
restore the default preference values.
87

VB [Link]
[Run Sample] | [View
Source]

To make a cookie persistent between sessions, the Expires property on the HttpCookie class
has to be set to a date in the future. The following code on the [Link] page is
identical to the previous sample, with the exception of the assignment to [Link]:

Protected Sub Submit_Click(sender As Object, e As EventArgs)


Dim cookie As New HttpCookie("preferences2")
[Link]("ForeColor",[Link])
...
[Link] = [Link] ' Never Expires

[Link](cookie)

[Link](State("Referer").ToString())
End Sub
C# VB JScript

Verify that the sample is working by modifying a value, closing all browser windows, and opening
[Link] again. The window should still show the customized value.

Using ViewState

This sample illustrates the use of the ViewState property to store request-specific values.

VB [Link]
[Run Sample] | [View
Source]

[Link] provides the server-side notion of a view state for each control. A control can save its
internal state between requests using the ViewState property on an instance of the class
StateBag. The StateBag class provides a dictionary-like interface to store objects associated
with a string key.

The file [Link] displays one visible panel and stores the index of it in the view state of
the page with the key PanelIndex:

Protected Sub Next_Click(sender As Object, e As EventArgs)


Dim PrevPanelId As String = "Panel" + ViewState("PanelIndex").ToString()
ViewState("PanelIndex") = CType(ViewState("PanelIndex") + 1, Integer)
88
Dim PanelId As String = "Panel" + ViewState("PanelIndex").ToString()
...
End Sub
C# VB JScript

Note that if you open the page in several browser windows, each browser window will initially
show the name panel. Each window can independently navigate between the panels.

Section Summary

1. Use application state variables to store data that is modified infrequently but used often.
2. Use session state variables to store data that is specific to one session or user. The data
is stored entirely on the server. Use it for short-lived, bulky, or sensitive data.
3. Store small amounts of volatile data in a nonpersistent cookie. The data is stored on the
client, sent to the server on each request, and expires when the client ends execution.
4. Store small amounts of non-volatile data in a persistent cookie. The data is stored on
the client until it expires and is sent to the server on each request.
5. Store small amounts of request-specific data in the view state. The data is sent from the
server to the client and back.

HTTP Handlers and Factories


Overview
Configuring HTTP Handlers and Factories
Creating a Custom HTTP Handler
Section Summary
Overview

[Link] provides a low-level request/response API that enables developers to use .NET
Framework classes to service incoming HTTP requests. Developers accomplish this by authoring
classes that support the [Link] interface and implement the
ProcessRequest() method. Handlers are often useful when the services provided by the high-
level page framework abstraction are not required for processing the HTTP request. Common
uses of handlers include filters and CGI-like applications, especially those that return binary data.

Each incoming HTTP request received by [Link] is ultimately processed by a specific instance of
a class that implements IHTTPHandler. IHttpHandlerFactory provides the infrastructure that
handles the actual resolution of URL requests to IHttpHandler instances. In addition to the
default IHttpHandlerFactory classes provided by [Link], developers can optionally create and
register factories to support rich request resolution and activation scenarios.

Configuring HTTP Handlers and Factories

HTTP handlers and factories are declared in the [Link] configuration as part of a [Link] file.
[Link] defines an <httphandlers> configuration section where handlers and factories can be
added and removed. Settings for HttpHandlerFactory and HttpHandler are inherited by
subdirectories.

For example, [Link] maps all requests for .aspx files to the PageHandlerFactory class in the
global [Link] file:

<httphandlers>
...
<add verb="*" path="*.aspx" type="[Link],[Link]"
/>
...
</httphandlers>
89
Creating a Custom HTTP Handler

The following sample creates a custom HttpHandler that handles all requests to
"[Link]".

VB SimpleHandler
[Run Sample] | [View
Source]

A custom HTTP handler can be created by implementing the IHttpHandler interface, which
contains only two methods. By calling IsReusable, an HTTP factory can query a handler to
determine whether the same instance can be used to service multiple requests. The
ProcessRequest method takes an HttpContext instance as a parameter, which gives it access
to the Request and Response intrinsics. In the following sample, request data is ignored and a
constant string is sent as a response to the client.

Public Class SimpleHandler : Inherits IHttpHandler


Public Sub ProcessRequest(context As HttpContext)
[Link]("Hello World!")
End Sub

Public Function IsReusable() As Boolean


Return(True)
End Function
End Class
C# VB JScript

After placing the compiled handler assembly in the application's \bin directory, the handler class
can be specified as a target for requests. In this case, all requests for "[Link]" will
be routed to an instance of the SimpleHandler class, which lives in the namespace
[Link].

Section Summary

1. HTTP Handlers and factories are the backbone of the [Link] page framework.
2. Factories assign each request to one handler, which processes the request.
3. Factories and handlers are defined in the [Link] file. Settings for factories are
inherited by subdirectories.
4. To create a custom handler, implement IHttpHandler and add the class in the
<httphandlers> section of the [Link] in the directory.

Caching Overview
90
Caching is a technique widely used in computing to increase performance by keeping
frequently accessed or expensive data in memory. In the context of a Web application, caching is
used to retain pages or data across HTTP requests and reuse them without the expense of
recreating them.

[Link] has three kinds of caching that can be used by Web applications:

• Output caching, which caches the dynamic response generated by a request.


• Fragment caching, which caches portions of a response generated by a request.
• Data caching, which caches arbitrary objects programmatically. To support this, [Link]
provides a full-featured cache engine that allows programmers to easily retain data
across requests.

Output caching is useful when the contents of an entire page can be cached. On a heavily
accessed site, caching frequently accessed pages for even a minute at a time can result in
substantial throughput gains. While a page is cached by the output cache, subsequent requests
for that page are served from the output page without executing the code that created it.

Sometimes it is not practical to cache an entire page - perhaps portions of the page must be
created or customized for each request. In this case, it is often worthwhile to identify objects or
data that are expensive to construct and are eligible for caching. Once these items are identified,
they can be created once and then cached for some period of time. Additionally, fragment caching
can be used to cache regions of a page's output.

Choosing the time to cache an item can be an interesting decision. For some items, the data
might be refreshed at regular intervals or the data is valid for a certain amount of time. In that
case, the cache items can be given an expiration policy that causes them to be removed from the
cache when they have expired. Code that accesses the cache item simply checks for the absence
of the item and recreates it, if necessary.

The [Link] cache supports file and cache key dependencies, allowing developers to make a
cache item dependent on an external file or another cache item. This technique can be used to
invalidate items when their underlying data source changes.

Page Output Caching

Output caching is a powerful technique that increases request/response throughput by caching


the content generated from dynamic pages. Output caching is enabled by default, but output
from any given response is not cached unless explicit action is taken to make the response
cacheable.

To make a response eligible for output caching, it must have a valid expiration/validation policy
and public cache visibility. This can be done using either the low-level OutputCache API or the
high-level @ OutputCache directive. When output caching is enabled, an output cache entry is
created on the first GET request to the page. Subsequent GET or HEAD requests are served
from the output cache entry until the cached request expires.

The output cache also supports variations of cached GET or POST name/value pairs.

The output cache respects the expiration and validation policies for pages. If a page is in the
output cache and has been marked with an expiration policy that indicates that the page expires
60 minutes from the time it is cached, the page is removed from the output cache after 60
minutes. If another request is received after that time, the page code is executed and the page
can be cached again. This type of expiration policy is called absolute expiration - a page is valid
until a certain time.
91
The following example demonstrates a simple way to output cache responses using the @
OutputCache directive. The example simply displays the time when the response was
generated. To see output caching in action, invoke the page and note the time at which the
response was generated. Then refresh the page and note that the time has not changed,
indicating that the second response is being served from the output cache.

VB [Link]
[Run Sample] | [View
Source]

The following directive activates output caching on the response:

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


This directive simply indicates that the page should be cached for 60 seconds and that the page
does not vary by any GET or POST parameters. Requests received while the page is still cached
are satisfied from the cache. After 60 seconds, the page is removed from the cache; the next
request is handled explicitly and caches the page again.

Of course, in the previous example, very little work is saved by output caching. The following
example shows the same technique for output caching, but queries a database and displays the
results in a grid.

VB [Link]
[Run Sample] | [View
Source]

In the final example, the application is modified slightly to allow the user to selectively query for
authors in various states. This example demonstrates caching requests varying by the
name/value pairs in the query string using the VaryByParam attribute of the @ OutputCache
directive.

<%@ OutputCache Duration="60" VaryByParam="state" %>


For each state in the data set, there is a link that passes the desired state as part of the query
string. The application then constructs the appropriate database query and shows authors
belonging only to the selected state.

Note that the first time you click the link for a given state, it generates a new timestamp at the
bottom of the page. Thereafter, whenever a request for that state is resubmitted within a minute,
you get the original timestamp indicating that the request has been cached.
92

VB [Link]
[Run Sample] | [View
Source]

Applications that want more control over the HTTP headers related to caching can use the
functionality provided by the [Link] class. The following example shows
the code equivalent to the page directives used in the previous samples.

[Link]([Link](60))
[Link]([Link])
C# VB JScript

To make this a sliding expiration policy, where the expiration time out resets each time the page
is requested, set the SlidingExpiration property as shown in the following code.

[Link]([Link](60))
[Link]([Link])
[Link](True)
C# VB JScript

Note: When sliding expiration is enabled (SetSlidingExpiration(true)), a request made to the


origin server always generates a response. Sliding expiration is useful in scenarios where there
are downstream caches that can satisfy client requests, if the content has not expired yet,
without requesting the content from the origin server.

Applications being ported from ASP may already be setting cache policy using the ASP properties;
for example:

[Link] = "Public"
[Link] = 60
C# VB JScript

These properties are supported by [Link] and have the same effect as the other examples that
have been shown.

Section Summary

1. Output caching caches the content generated by [Link] pages.


2. Pages are not placed in the output cache unless they have a valid expiration or
validation policy and public cache visibility.

Page Fragment Caching

In addition to output caching an entire page, [Link] provides a simple way for you to output
cache regions of page content, which is appropriately named fragment caching. You delineate
93
regions of your page with a user control, and mark them for caching using the @
OutputCache directive introduced in the previous section. This directive specifies the duration
(in seconds) that the output content of the user control should be cached on the server, as well
as any optional conditions by which it should be varied.

For example, the following directive instructs [Link] to output cache the user control for 120
seconds, and to vary the caching using the "CategoryID" and "SelectedID" querystring or form
post parameters.

<%@ OutputCache Duration="120" VaryByParam="CategoryID;SelectedID"%>

The VaryByParam attribute is extremely powerful and allows user control authors to instruct
[Link] to cache/store multiple instances of an output cache region on the server. For example,
the following URLs to the host page of the previous user control cache separate instances of the
user control content.

[Link]
[Link]

Logic within a user control can then dynamically generate different content (which is cached
separately) depending on the arguments provided.

In addition to supporting the VaryByParam attribute, fragment caching also supports a


VaryByControl attribute. Whereas the VaryByParam attribute varies cached results based on
name/value pairs sent using POST or GET, the VaryByControl attribute varies the cached
fragment by controls within the user control. For example:

<%@ OutputCache Duration="120" VaryByParam="none" VaryByControl="Category" %>

Note that similar to output-cached pages, explict use of VaryByParam is required even if it is
not used.

If the user control contained a drop-down select box control named Category, the user control's
output would vary based on the selected value within that control.

Just as it is possible to nest user controls recursively within a page (that is, a user control
declared within another server control), it is also possible to nest output-cached user controls
recursively. This provides a powerful composition model that enables cached regions to be
composed of further subcached regions.

The following sample code demonstrates how to cache two menu sections of a page using a
declarative user control.

<%@ Register TagPrefix="Acme" TagName="Menu" Src="[Link]" %>

<html>
<body>
<table>
<tr>
<td>
<Acme:Menu Category="LeftMenu" runat=server/>
</td>
<td>
<h1>Hi, the time is now: <%=Now%> </h1>
94
</td>
<td>
<Acme:Menu Category="RightMenu" runat=server/>
</td>
<tr>
</table>
</body>
</html>
C# VB JScript

The following sample code shows the implementation of the "Acme:Menu" user control with
caching support.

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

<script language="VB" runat=server>

Public Category As String;

Sub Page_Load(sender As Object, e As EventArgs)

Dim conn As AdoConnection = New AdoConnection("MyDSN")

[Link] = [Link]("select * from menu where category="


& Category)
[Link]()
End Sub

</script>

<asp:datagrid id="MyMenu" runat=server/>


C# VB JScript

Note that this example output caches the response of each user control for a period of 120
seconds. All logic necessary to recreate each menu user control in the event of a cache miss
(either because 120 seconds has expired or because memory conditions on the server have
become scarce) is encapsulated cleanly within the user control.

The following example shows simple fragment caching. The sample caches the output from a
control that retrieves data from an SQL Server database, while keeping the dynamic properties of
the parent page. You can see that the page is dynamic because the time is updated with every
refresh, while the control is only updated every 60 seconds.

VB [Link]
[Run Sample] | [View Source]

Caveats
95
Note: Attempts to programmatically manipulate an output-cached control from its containing
page result in an error. For example, attempts to use a declarative data binding expression on the
user control tag generates parser errors, as shown in the following code.

<!-- The following tags generate parser errors. -->


<Acme:Menu Category='<%# [Link]("Category")' runat="server"/>

The reason for this is simple. In cases when the content of a user control is output cached, an
instance of the control is created only on the first request; thus, once cached, the control is no
longer available. Instead, you should encapsulate all the logic necessary to create the content of
a user control directly within the control itself; this is typically done within the user control's
Page_Load event or Page_PreRender event.

You can declare and use other declarative property parameters to customize the control. For
example, the previous user control can be customized as follows:

<Acme:Menu Category="LeftMenu" runat=server/>


<Acme:Menu Category="RightMenu" runat=server/>

These declarations cause the appropriate code to be generated and executed by the page
compiler in the event that the control is created as a result of a cache miss. User control
developers can then access these settings just as they would in a non-cached user control
scenario.

Section Summary

1. In addition to output caching an entire page, [Link] provides a simple way for you to
output cache regions of page content, which is appropriately named fragment caching.
2. You delineate regions of your page with a user control and mark them for caching using
the @ OutputCache directive introduced in the previous section.
3. Just as it is possible to nest user controls recursively within a page (that is, a user
control declared within another server control), it is also possible to nest output-cached
user controls recursively.
4. Attempts to programmatically manipulate an output-cached control from its containing
page result in an error. Instead, you should encapsulate all the logic necessary to create
the content of a user control directly within the control itself, typically within the user
control's Page_Load event or Page_PreRender event.
5. It is possible to declare and use other declarative property parameters to customize the
control.

Page Data Caching


Introduction to Data Caching
Using the Data Cache
Section Summary
Introduction to Data Caching

[Link] provides a full-featured cache engine that can be used by pages to store and retrieve
arbitrary objects across HTTP requests. The [Link] cache is private to each application and
stores objects in memory. The lifetime of the cache is equivalent to the lifetime of the application;
that is, when the application is restarted, the cache is recreated.

The cache provides a simple dictionary interface that allows programmers to easily place objects
in and retrieve them from the cache. In the simplest case, placing an item in the cache is just like
adding an item to a dictionary:
96

Cache("mykey") = myValue
C# VB JScript

Retrieving the data is just as simple. The existence of the object should be checked before
retrieving the data from the cache as shown in the example below:

myValue = Cache("mykey")
If Not (myValue Is Nothing) Then
DisplayData(myValue)
End If
C# VB JScript

For applications that need more sophisticated functionality, the [Link] cache supports
scavenging, expiration, and file and key dependencies.

• Scavenging means that the cache attempts to remove infrequently used or unimportant
items if memory becomes scarce. Programmers who want to control how scavenging
occurs can provide hints to the scavenger when items are inserted into the cache that
indicate the relative cost of creating the item and the relative rate at which the item
must be accessed to remain useful.
• Expiration allows programmers to give cache items lifetimes, which can be explicit (for
example, expire at 6:00) or can be relative to an item's last use (for example, expire 20
minutes after the item was last accessed). After an item has expired, it is removed from
the cache and future attempts to retrieve it return the null value unless the item is
reinserted into the cache.
• File and key dependencies allow the validity of a cache item to be based on an external
file or on another cache item. If a dependency changes, the cache item is invalidated
and removed from the cache. For an example of how you might use this functionality,
consider the following scenario: an application reads financial information from an XML
file that is periodically updated. The application processes the data in the file and
creates a graph of objects that represent that data in a consumable format. The
application caches that data and inserts a dependency on the file from which the data
was read. When the file is updated, the data is removed from the cache and the
application can reread it and reinsert the updated copy of the data.

Using the Data Cache

The following sample shows a simple use of the cache. It executes a database query and caches
the result, which it continues to use for the lifetime of the application. When you run the sample,
note the message at the bottom of the page. When first requested, it indicates that the data was
explicitly retrieved from the database server. After refreshing the page, the page notes that the
cached copy was used.

VB [Link]
[Run Sample] | [View
Source]
97
The next example shows a cache item that depends on an XML file. It is similar to the first
example, although in this case the data is retrieved from an XML data source instead of a
database server. When the data is cached, the XML file is added as a dependency.

When a new record is added using the form at the bottom of the page, the XML file is updated
and the cached item must be recreated.

VB [Link]
[Run Sample] | [View
Source]

Note that a file dependency is added by using [Link] and supplying a CacheDependency
object referencing the XML file.

[Link]("MyData", Source, _
New CacheDependency([Link]("[Link]")))
C# VB JScript

A cache item can depend on a single or multiple files or keys. As mentioned previously, an
application can also set expiration policy on a cache item. The following code sets an absolute
cache expiration time.

[Link]("MyData", Source, Nothing, _


[Link](1), [Link])
C# VB JScript

The relevant parameter is the call to [Link](1), which indicates that the
item expires 1 hour from the time it is inserted. The final argument, [Link] indicates
that there is no relative expiration policy on this item.

The following code shows how to set a relative expiration policy. It inserts an item that expires 20
minutes after it is last accessed. Note the use of [Link], which indicates that
there is no absolute expiration policy on this item.

[Link]("MyData", Source, Nothing, [Link], _


[Link](20))
C# VB JScript

Section Summary

1. Data caching allows arbitrary objects to be cached programmatically.


2. The [Link] cache supports expiration and dependencies.
3. The cache is scoped to an application and its lifetime is equivalent to the lifetime of the
application.

Configuration Overview
98
A central requirement of any Web application server is a rich and flexible configuration
system--one that enables developers to easily associate settings with an installable application
(without having to "bake" values into code) and enables administrators to easily customize these
values post-deployment. The [Link] configuration system has been designed to meet the needs
of both of these audiences; it provides a hierarchical configuration infrastructure that enables
extensible configuration data to be defined and used throughout an application, site, and/or
machine. It has the following qualities that make it uniquely suited to building and maintaining
Web applications:

• [Link] allows configuration settings to be stored together with static content, dynamic
pages, and business objects within a single application directory hierarchy. A user or
administrator simply needs to copy a single directory tree to set up an [Link]
Framework application on a machine.
• Configuration data is stored in plain text files that are both human-readable and human-
writable. Administrators and developers can use any standard text editor, XML parser, or
scripting language to interpret and update configuration settings.
• [Link] provides an extensible configuration infrastructure that enables third-party
developers to store their own configuration settings, define the persistence format of
their own configuration settings, intelligently participate in their processing, and control
the resulting object model through which those settings are ultimately exposed.
• Changes to [Link] configuration files are automatically detected by the system and
are applied without requiring any user intervention (in other words, an administrator
does not need to restart the Web server or reboot the machine for them to take effect).
• Configuration sections can be locked down when using the <location> tag and the
allowOverride attribute.

To learn more about the [Link] configuration system and how it works, see Configuration File
Format and Retrieving Configuration.

Configuration File Format

[Link] configuration files are XML-based text files--each named [Link]--that can appear in
any directory on an [Link] Web application server. Each [Link] file applies configuration
settings to the directory it is located in and to all virtual child directories beneath it. Settings in
child directories can optionally override or modify settings specified in parent directories. The root
configuration file--WinNT\[Link]\Framework\<version>\config\[Link]--provides
default configuration settings for the entire machine. [Link] configures IIS to prevent direct
browser access to [Link] files to ensure that their values cannot become public (attempts to
access them will cause [Link] to return 403: Access Forbidden).

At run time [Link] uses these [Link] configuration files to hierarchically compute a unique
collection of settings for each incoming URL target request (these settings are calculated only
once and then cached across subsequent requests; [Link] automatically watches for file
changes and will invalidate the cache if any of the configuration files change).

For example, the configuration settings for the URL


[Link] would be computed by applying [Link] file
settings in the following order:

Base configuration settings for machine.


C:\WinNT\[Link]\Framework\v.1.00\config\[Link]

Overridden by the configuration settings for the site (or the root application).
C:\inetpub\wwwroot\[Link]

Overridden by application configuration settings.


99
D:\MyApplication\[Link]

Overridden by subdirectory configuration settings.


D:\MyApplication\MyDir\[Link]
If a [Link] file is present at the root directory for a site, for example "Inetpub\wwwroot", its
configuration settings will apply to every application in that site. Note that the presence of a
[Link] file within a given directory or application root is completely optional. If a [Link]
file is not present, all configuration settings for the directory are automatically inherited from the
parent directory.

Configuration Section Handlers and Sections

A [Link] file is an XML-based text file that can contain standard XML document elements,
including well-formed tags, comments, text, cdata, and so on. The file may be ANSI, UTF-8, or
Unicode; the system automatically detects the encoding. The root element of a [Link] file is
always a <configuration> tag. [Link] and end-user settings are then encapsulated within the
tag, as follows:
<configuration>
<!- Configuration settings would go here. -->
</configuration>
All configuration information resides between the <configuration> and </configuration> root
XML tags. Configuration information between the tags is grouped into two main areas: the
configuration section handler declaration area and the configuration section settings area.

• Configuration section handlers - The [Link] configuration infrastructure makes no


assumptions regarding the file format or supported settings within a [Link] file.
Instead, it delegates the processing of [Link] data to configuration section
handlers, .NET Framework classes that implement the IConfigurationSectionHandler
interface. An individual IConfigurationSectionHandler declaration needs to appear
only once, typically in the [Link] file. The [Link] files in child directories
automatically inherit this declaration. Configuration section handlers are declared within
a [Link] file using section tag directives nested within a <configSections> tag.
Section tags may be further qualified by section group tags to organize them into logical
groups (see below). Each section tag identifies a tag name denoting a specific section of
configuration data and an associated IConfigurationSectionHandler class that
processes it.
• Configuration section groups - [Link] configuration allows hierarchical grouping of
sections for organizational purposes. A <sectionGroup> tag may appear inside a
<configSections> tag or inside other <sectionGroup> tags. For example, [Link]
section handlers all appear within the <[Link]> section group.
• Configuration sections - [Link] configuration settings are represented within
configuration tag sections, also nested within a <configuration> tag (and optional
section group tags). For each configuration section, an appropriate section handler must
be defined in the config hierarchy. For example, in the sample below, the tag
<httpModules> is the configuration section that defines the HTTP modules
configuration data. The [Link]
class is responsible for interpreting the content contained within the <httpModules>
tag at run time. Note that both the section handler definition and the section must have
the same section group qualifier (in this case, <[Link]>). Also note that tag
names are case-sensitive and must be typed exactly as shown. Various attributes and
settings for [Link] are also case-sensitive and will not be examined by the
configuration runtime if the case does not match.

<configuration>

<configSections>
<sectionGroup name="[Link]">
100
<section
name="httpModules"
type="[Link],[Link],
Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
/>
</sectionGroup>
</configSections>

<[Link]>
<httpModules>
<add
name="CookielessSession"
type="[Link],[Link],
Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
/>
<add
name="OutputCache"
type="[Link],[Link], Version=1.0.3300.0,
Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
/>
<add
name="Session"
type="[Link],[Link],
Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
/>
<add
name="WindowsAuthentication"
type="[Link],[Link],
Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
/>
<add
name="FormsAuthentication"
type="[Link],[Link],
Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
/>
<add
name="PassportAuthentication"
type="[Link],[Link],
Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
/>
<add
name="UrlAuthorization"
type="[Link],[Link],
Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
/>
<add
name="FileAuthorization"
type="[Link],[Link],
Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
/>
</httpModules>
</[Link]>

</configuration>

Using Location and Path

By default, all configuration settings defined within the top-level <configuration> tag are
applied to the current directory location of the containing [Link] file and to all of the child
paths beneath it. You can optionally apply configuration settings to specific child paths under the
101
current config file by using the <location> tag with an appropriately constraining path
attribute. If the config file is the main [Link] file, you can apply settings to specific
virtual directories or applications and the virtual path needs to include the friendly name of the
site like, <location path="Default Web Site/EnglishPages/[Link]">, which is also
shown in the example below. If the config file is a [Link] file, you can apply settings to a
specific file, child directory, virtual directory, or application.
<configuration>

<location path="EnglishPages">
<[Link]>
<globalization
requestEncoding="iso-8859-1"
responseEncoding="iso-8859-1"
/>
</[Link]>
</location>

<location path="Default Web Site/EnglishPages/[Link]">


<[Link]>
<globalization
requestEncoding="Shift-JIS"
responseEncoding="Shift-JIS"
/>
</[Link]>
</location>

</configuration>

Locking down configuration settings

In addition to specifying path information using the <location> tag, you can also specify
security so that settings cannot be overridden by another configuration file further down the
configuration hierarchy. To lock down a group of settings, you can specify an allowOverride
attribute on the surrounding <location> tag and set it to false. The following code locks down
impersonation settings for two different applications.
<configuration>

<location path="app1" allowOverride="false">


<[Link]>
<identity impersonate="false" userName="app1" password="app1pw" />
</[Link]>
</location>

<location path="app2" allowOverride="false">


<[Link]>
<identity impersonate="false" userName="app2" password="app2pw" />
</[Link]>
</location>

</configuration>

Note that if a user tries to override these settings in another configuration file, the configuration
system will throw an error:

<configuration>

<[Link]>
<identity userName="developer" password="loginpw" />
</[Link]>
102
</configuration>

Standard [Link] Configuration Section

[Link] ships with a number of standard configuration section handlers that are used to process
configuration settings within [Link] files. The following table provides brief descriptions of the
sections, along with pointers to more information.
Section Name Description
<httpModules> Responsible for configuring HTTP modules within an
application. HTTP modules participate in the processing of
every request into an application. Common uses include
security and logging.
<httpHandlers> Responsible for mapping incoming URLs to IHttpHandler
classes. Subdirectories do not inherit these settings. Also
responsible for mapping incoming URLs to
IHttpHandlerFactory classes. Data represented in
<httpHandlers> sections are hierarchically inherited by
subdirectories. For more information, see the Http
Handlers and Factories section of this tutorial.
<sessionState> Responsible for configuring the session state HTTP
module. For more information, see the Managing
Application State section of this tutorial.
<globalization> Responsible for configuring the globalization settings of an
application. For more information, see the Localization
section of this tutorial.
<compilation> Responsible for all compilation settings used by [Link].
For more information, see the Business Objects and
Debugging sections of this tutorial.
<trace> Responsible for configuring the [Link] trace service. For
more information, see the Tracing section of this tutorial.
<processModel> Responsible for configuring the [Link] process model
settings on IIS Web server systems.
<browserCaps> Responsible for controlling the settings of the browser
capabilities component. For more information, see the
Retrieving Configuration section of this tutorial.

Optional Attributes - The following attributes are applicable only for [Link] applications. The
configuration system ignores these attributes when other types of applications are running.

Attribute Description
allowDefinition Specifies which configuration file the section can be used in.
Use one of the following values:
Everywhere
Allows the section to be used in any configuration
file. This is the default.
MachineOnly
Allows the section to be used only in the machine
configuration file ([Link]).
MachineToApplication
Allows the section to be used in the machine
configuration file or the application configuration file.
103
allowLocation Determines whether the section can be used within the
<location> element. Use one of the following values:
true
Allows the section to be used within the <location>
element. This is the default.
false
Does not allow the section to be used within the
<location> element.
Retrieving Configuration

[Link] allows developers to access configuration settings from within an application either by
exposing configuration settings directly (as strongly typed properties) or by using general
configuration APIs. The following sample shows a page that accesses the <browserCaps>
configuration section using the Browser property of the [Link] class. This
is a hash table of attributes that reflect the capabilities of the browser client that is currently
accessing the page. The actual <browserCaps> section data is included in the [Link]
file.

VB [Link]
[Run Sample] | [View
Source]

In addition to accessing configuration settings, as demonstrated above, developers also can use
the [Link] class to retrieve the data for any arbitrary
configuration section. Note that the particular object returned by ConfigurationSettings
depends on the section handler mapped to the configuration section (see
[Link]). The following code demonstrates how you can access
the configuration data exposed for a <customconfig> section. In this example, it is assumed
that the configuration section handler returns an object of type CustomConfigSettings with the
property Enabled.

Dim config As CustomConfigSettings =


CType([Link]("customconfig"), CustomConfigSettings)

If [Link] = True Then


' Do something here.
End If
C# VB JScript

Using Application Settings

Configuration files are perfectly suited for storing custom application settings, such as database
connection strings, file paths, or remote XML Web service URLs. The default configuration
sections (defined in the [Link] file) include an <appSettings> section that may be used
to store these settings as name/value pairs. The following example shows an <appSettings>
configuration section that defines database connection strings for an application.
<configuration>
<appSettings>
104
<add key="pubs" value="server=(local)\NetSDK;database=pubs;Integrated
Security=SSPI" />
<add key="northwind"
value="server=(local)\NetSDK;database=northwind;Integrated Security=SSPI" />
</appSettings>
</configuration>
The ConfigurationSettings object exposes a special AppSettings property that can be used to
retrieve these settings:

Dim dsn As String = [Link]("pubs")


C# VB JScript

The following sample illustrates this technique.

VB [Link]
[Run Sample] | [View
Source]
Deploying [Link] Applications
File System Layout of [Link] Applications
Resolving Class References to Assemblies
[Link] Framework application Startup and Class Resolution
Code Replacement
Section Summary
File System Layout of [Link] Applications

[Link] can be used to host multiple Web applications, each identified using a unique URL prefix
within a Web site (where a Web site is represented on a Web server as a unique HostName/Port
combination). For example, a single Microsoft Internet Information Services (IIS) Web server
with two mapped IP addresses (one aliased to "[Link]" and the other to "intranet") and
three logical sites ([Link] [Link] [Link] port 81) could
expose the following six [Link] applications.

Application URL Description


[Link] "Root" application on intranet
site.
[Link] "Root" application on
[Link] site.
[Link] "Root" application on
[Link] port 81 site.
[Link] "Training" application on
intranet site.
[Link] "HR" application on intranet
site.
[Link] "Compensation" application on
intranet site.

Note: The URL for the compensation application mentioned in the table is rooted within the HR
application URL namespace. However, this URL hierarchy notation does not imply that the
105
compensation application is contained or nested within the HR application. Rather, each
application maintains an independent set of configuration and class resolution properties; both
are logical peer child sites of the intranet site.

Each [Link] Framework application exposed within a URL namespace is backed using a file
system directory located on either a local or remote file share. Application directories are not
required to be centrally located within a contiguous part of the file system; they can be scattered
throughout a disk. For example, the [Link] applications mentioned previously could be located
in the different directories listed in the following table.

Application URL Physical path


[Link] c:\inetpub\wwwroot
[Link] c:\inetpub\msnroot
[Link] d:\msnroot81
[Link] d:\serverapps\trainingapp
[Link] \\hrweb\sillystuff\reviews
[Link] c:\inetpub\wwwroot\compensation

Resolving Class References to Assemblies

Assemblies are the unit of class deployment in the common language runtime. Developers writing
.NET Framework classes using Visual Studio .NET version 7.0 will produce a new assembly with
each Visual Studio project that they compile. Although it is possible to have an assembly span
multiple portable executable (PE) files (several module DLLs), Visual Studio .NET will, by default,
compile all assembly code into a single DLL (1 Visual Studio .NET project = 1 .NET Framework
assembly = 1 physical DLL).

You can use an assembly on a computer by deploying it into an assembly cache. The assembly
cache can be either global to a computer or local to a particular application. Only code intended
to be shared across multiple applications should be placed in the global system assembly cache.
Code specific to a particular application, such as most Web application logic, should be deployed
in the application's local assembly cache. One advantage of deploying an assembly within an
application's local assembly cache is that only code within that application can access it. (This is a
nice feature for scenarios involving ISPs.) It also facilitates side-by-side versioning of the same
application because classes are private to each application version instance.

An assembly can be deployed into an application's local assembly cache by simply copying,
XCOPYing, or FTPing the appropriate files into a directory that has been marked as an "assembly
cache location" for that particular application. No additional registration tool must be run once the
appropriate files are copied, and no reboot is necessary. This eliminates some of the difficulties
currently associated with deploying COM components within ASP applications (currently, an
administrator must log on to the Web server locally and run [Link]).

By default, an [Link] Framework application is automatically configured to use the \bin


subdirectory, located immediately under the application root, as its local assembly cache. The
\bin directory is also configured to deny any browser access so that a remote client cannot
download and steal the code. The following example shows a possible directory layout for an
[Link] application, where the \bin directory is immediately under the application root.

C:\inetpub\wwwroot
[Link]
[Link]
106
\bin <= Application assembly cache directory
[Link]
[Link]

\order
[Link]
[Link]

\img
[Link]
[Link] Framework application Startup and Class Resolution

[Link] Framework applications are lazily constructed the first time a client requests a URL
resource from them. Each [Link] Framework application is launched within a unique application
domain (AppDomain)--a new common language runtime construct that enables process hosts to
provide extensive code, security, and configuration isolation at run time.

[Link] is responsible for manually creating an application domain when a new application is
started. As part of this process, [Link] provides configuration settings for the common
language runtime to use. These settings include:

• The directory paths that make up the local assembly cache. (Note: It is the .NET
Framework application domain isolation architecture that allows each application to
maintain its own local assembly cache.)
• The application's security restrictions (what the application can access on the system).

Because [Link] does not have compile-time knowledge of any applications you write on top of
it, it cannot use static references to resolve and reference application code. Instead, [Link]
must use a dynamic class/assembly resolution approach to make the transition from the [Link]
runtime into application code.

[Link] configuration and page activation files will enable you to dynamically reference a target-
compiled .NET Framework class by specifying an assembly and class name combination. The
string format for this union follows the pattern

classname, assemblyname
. The common language runtime can then use this simple string reference to resolve and load the
appropriate class.

Code Replacement

.NET Framework assemblies are typically compiled and deployed into a Windows DLL-based PE
format. When the common language runtime's loader resolves a class implemented within this
type of assembly, it calls the Windows LoadLibrary routine on the file (which locks its access on
disk), and then maps the appropriate code data into memory for run-time execution. Once
loaded, the DLL file will remain locked on disk until the application domain referencing it is either
torn down or manually recycled.

Although [Link] cannot prevent the common language runtime from locking a loaded assembly
DLL on disk, it can support you by ensuring that the physical DLLs in a Web application's private
assembly cache are never actually loaded by the runtime. Instead, shadow copies of the
assembly DLLs are made immediately prior to their use. These shadow assemblies--not the
original files--are then locked and loaded by the runtime.
107
Because the original assembly files always remain unlocked, you are free to delete, replace,
or rename them without cycling the Web server or having to use a registration utility. FTP and
similar methods work just fine. [Link] maintains an active list of all assemblies loaded within a
particular application's application domain and uses file-change monitoring code to watch for any
updates to the original files.

Section Summary

1. [Link] Framework applications are identified by a unique URL and live in the file
system of the Web server.
2. [Link] can use shared assemblies, which reside in the global cache, and application-
specific assemblies, which reside in the \bin directory of the application's virtual root.
3. [Link] Framework applications run in the context of application domains
(AppDomains), which provide isolation and enforce security restrictions.
4. Classes can be dynamically referenced using "classname, assemblyname".
5. [Link] uses shadow copies of assembly files to avoid locking, it and monitors the files
so that changes are picked up immediately.

Using the Process Model


Process Model Configuration
Reactive Process Recycling
Proactive Process Recycling
Logging Process Model Events
Enabling Web Gardens
Section Summary
One of the most important requirements for [Link] Framework applications is reliability. The
architecture of applications running inside the server process (in IIS, [Link]) does not
produce a solid foundation for building reliable applications that can continue to run over a long
period of time. Too many resources are shared on the process level, and it is too easy for an error
to bring down the entire server process.

To solve this problem, [Link] provides an out-of-process execution model, which protects the
server process from user code. It also enables you to apply heuristics to the lifetime of the
process to improve the availability of your Web applications. Using asynchronous interprocess
communication enables you to provide the best balance of performance, scalability, and reliability.

Process Model Configuration

Process model settings are exposed in the root configuration file for the computer,
[Link]. The configuration section is named <processModel> and is shown in the
following example. On Windows 2000 and Windows XP, the process model is enabled by default
(enable="true"). On the Windows Server 2003 family, [Link] runs by default in IIS6 native
mode (Worker Process Isolation Mode).

<processModel
enable="true"
timeout="Infinite"
idleTimeout="Infinite"
shutdownTimeout="[Link]"
requestLimit="Infinite"
requestQueueLimit="5000"
restartQueueLimit="10"
memoryLimit="60"
webGarden="false"
cpuMask="0xffffffff"
userName="machine"
password="AutoGenerate"
108
logLevel="Errors"
clientConnectedCheck="[Link]"
comAuthenticationLevel="Connect"
comImpersonationLevel="Impersonate"
responseRestartDeadlockInterval="[Link]"
responseDeadlockInterval="[Link]"
maxWorkerThreads="20"
maxIoThreads="20"
/>

Most of these settings control when a new worker process is started to serve requests (gracefully
taking the place of an old worker process). The process model supports two types of recycling:
reactive and proactive. The 'userName' and 'password' attributes define the account under which
the [Link] worker process runs. These default to 'machine' and 'autogenerate' respectively.
These values tell [Link] to use the built-in ASPNET account and to use a cryptographically
strong random password stored in the Local Security Authority (LSA) for that account. As noted
above, by default on the Windows Server 2003 family, [Link] runs as part of the w3wp process
using the default identity "NETWORK SERVICE". If IIS5 Isolation mode is configured on the
Windows Server 2003 family, the [Link] worker process would run in the ASPNET account.

If you want a more privileged process, you can set the userName attribute to System, which
causes the [Link] worker process to run with the same identity as the [Link] process. This
process runs by default as the System identity. When so configured, the [Link] worker process
will have the right to access nearly all resources on the local machine. In Windows 2000,
Windows XP, and the Windows Server 2003 family systems, the System account also has network
credentials and can access network resources as the machine account.

To configure the process to run as System, change the userName attribute in the
<processModel> section of [Link] as follows:

<processModel userName="system" password="autogenerate" />

Reactive Process Recycling

Reactive process recycling occurs when a process is misbehaving or unable to serve requests. The
process typically displays detectable symptoms, such as deadlocks, access violations, memory
leaks, and so on, in order to trigger a process recycle. You can control the conditions that trigger
a process restart by using the configuration settings described in the following table.

Setting Description
requestQueueLimit Handles deadlock conditions. The DWORD value is set to the
maximum allowed number of requests in the queue, after
which the worker process is considered to be misbehaving.
When the number is exceeded, a new process is launched
and the requests are reassigned. The default is 5000
requests.
memoryLimit Handles memory leak conditions. The DWORD value is set to
the percentage of physical memory that the worker process
can consume before it is considered to be misbehaving.
When that percentage is exceeded, a new process is
launched and the requests are reassigned. The default is
60%.
shutdownTimeout Specifies the amount of time the worker process has to shut
itself down gracefully (string value in hr:min:sec format).
When the time out expires, the [Link] ISAPI shuts down
109
the worker process. The default is "[Link]".

Proactive Process Recycling

Proactive process recycling restarts the worker process periodically even if the process is healthy.
This can be a useful way to prevent denials of service due to conditions the process model is
unable to detect. A process can be restarted after a specific number of requests or after a time-
out period has elapsed.

Setting Description
timeout String value in hr:min:sec format that configures the time limit after
which a new worker process will be launched to take the place of the
current one. The default is Infinite, a keyword indicating that the
process should not be restarted.
idleTimeout String value in hr:min:sec format that configures the amount of
inactivity, after which the worker process is automatically shut down.
The default is Infinite, a keyword indicating that the process should
not be restarted.
requestLimit DWORD value set to the number of requests after which a new worker
process will be launched to take the place of the current one. The
default is Infinite, a keyword indicating that the process should not
be restarted.

Logging Process Model Events

The process model can write events to the Windows event log when process cycling occurs. This
is controlled by the logLevel attribute in the <processModel> configuration section.

Setting Description
logLevel Controls that process cycling events are logged to the event log. The
value can be:

• All: All process cycling events are logged.


• None: No events are logged.

• Errors: Only unexpected events are logged.

When a cycling event occurs, if logging is enabled for that event, the following events are written
to the application event log.

Event Log
Shutdown Reason Description
Type
Unexpected Error The [Link] worker process has shut down
unexpectedly.
RequestQueueLimit Error The [Link] worker process has been
restarted because the request queue limit
was exceeded.
RequestLimit Information The [Link] worker process has been
restarted because the request limit was
exceeded.
Timeout Information The [Link] worker process has been
110
restarted because the time-out interval was
met.
IdleTimeout Information The [Link] worker process has been shut
down because the idle time-out interval
was met.
MemoryLimitExceeded Error The [Link] worker process was restarted
because the process memory limit was
exceeded.

Enabling Web Gardens

The process model helps enable scalability on multiprocessor computers by distributing the work
to several processes, one per CPU, each with processor affinity set to its CPU. This eliminates
cross-processor lock contention and is ideal for large SMP systems. This technique is called Web
gardening. The configuration settings for enabling Web gardens are listed in the following table.
Note that these settings take effect only after a server is restarted. IIS must be cycled in order
for this change to take place.

Setting Description
webGarden Controls CPU affinity. True indicates that processes should be
affinitized to the corresponding CPU. The default is False.
cpuMask Specifies which processors on a multiprocessor server are eligible to
run [Link] processes. The cpuMask value specifies a bit pattern that
indicates the CPUs eligible to run [Link] threads. [Link] launches
one worker process for each eligible CPU. If webGarden is set to
false, cpuMask is ignored and only one worker process will run
regardless of the number of processors in the machine. If
webGarden is set to true, [Link] launches one worker process for
each CPU that corresponds to a set bit in cpuMask. The default value
of cpuMask is 0xffffffff.

Web gardening has some side effects that you should be aware of:

• If your application uses session state, it must choose an out-of-process provider (NT
Service or SQL).
• Application state and application statics are per process, not per computer.
• Caching is per process, not per computer.

Section Summary

1. [Link] provides an out-of-process execution model, which protects the server process
from user code. It also enables you to apply heuristics to the lifetime of the process to
improve the overall availability of Web applications.
2. The <processModel> settings are exposed in the root configuration file for the
computer's [Link] file. On Windows 2000 and Windows XP, the process model is
enabled by default. On the Windows Server 2003 family, it is not.
3. The process model supports two types of recycling: reactive and proactive. Reactive
process recycling occurs when a process is misbehaving or unable to serve requests.
Proactive process recycling restarts the worker process periodically, even when the
process may be healthy.
4. The process model can write events to the Windows event log when process cycling
occurs. This is controlled by the log-level attribute in the <processModel>
configuration section.
111
5. The process model helps enable scalability on multiprocessor computers by
distributing the work to several processes, one per CPU, each with processor affinity set
to its CPU. This technique is called Web gardening.

Handling Errors
Customizing Error Pages
Handling Errors Programmatically
Writing to the Event Log
Section Summary

When an error occurs on a page, [Link] sends information about the error to the client. Errors
are divided into four categories:

• Configuration errors: Occur when the syntax or structure of a [Link] file in the
configuration hierarchy is incorrect.
• Parser errors: Occur when the [Link] syntax on a page is malformed.
• Compilation errors: Occur when statements in a page's target language are incorrrect.
• Run-time errors: Occur during a page's execution, even though the errors could not be
detected at compile time.

By default, the information shown for a run-time error is the call stack (the chains of
procedure calls leading up to the exception). If debug mode is enabled, [Link] displays
the line number in source code where the run-time error originated. Debug mode is a
valuable tool for debugging your application. You can enable debug mode at the page
level, using the following directive:

<%@ Page Debug="true" %>

You can also enable debug mode at the application level, using the [Link] file in the
application's root directory, as shown in the following example.

Note: Running debug mode incurs a heavy performance penalty. Be sure to disable it
before deploying your finished application.

The following example demonstrates the use of debug mode to show source line numbers
for a run-time exception.

VB [Link]
[Run Sample] | [View
Source]

Customizing Error Pages

Depending on the circumstances, you might want to handle application errors in different
ways. For example, at development time you probably want to see the detailed error
pages that [Link] provides to help you identify and fix problems. However, once an
application is being served in a production environment, you probably do not want to
display detailed errors to your customer clients. You can use [Link] to specify whether
errors are shown to local clients, to remote clients, or to both. By default, errors are
112
shown only to local clients (those clients on the same computer as the server). You can
also specify a custom error page to redirect clients to if an error occurs.

Custom errors are enabled in the [Link] file for an application. For example:

<configuration>
<[Link]>
<customErrors defaultRedirect="[Link]"
mode="RemoteOnly" />
</[Link]>
</configuration>

This configuration enables local clients to see the default [Link] detailed error pages but
redirects remote clients to a custom page, [Link]. This page could be an .aspx
page as well. [Link] passes the path of the page on which the error occurred to the
error page as a QueryString argument. Note that if the execution of the error page
generates an error, a blank page is sent back to the remote client.

<%@ Page Language="VB" Description="Error page"%>

<html>
<head>
<title>Error page</title>
</head>

<body>
<h1>Error page</h1>
Error originated on: <%=[Link]("ErrorPage") %>
</body>
</html>
C# VB JScript

Note: Only files mapped to the aspnet_isapi.dll extension in IIS generate these errors.
Files not served through the aspnet_isapi.dll are not processed by [Link] and generate
IIS errors. See the IIS documentation for information about configuring IIS custom errors.

The following table describes the configuration attributes and values for the
<customErrors> tag.

Attribute Description
mode Indicates whether custom errors are enabled, disabled, or only shown
to remote computers. Values: On, Off, RemoteOnly (default).
defaultRedirect Indicates the default URL to which a browser should be redirected if
an error occurs. This attribute is optional.

The Mode attribute determines whether errors are shown to local clients, remote clients,
or both. The effects of each setting are described in the following table.

Mode Local host request Remote host request


On Custom error page. Custom error page.
Off [Link] error page. [Link] error page.
RemoteOnly [Link] error page. Custom error page.
113
The following sample demonstrates how the <customErrors> configuration section is
used.

VB [Link]
[Run Sample] | [View
Source]

In addition to redirecting to a common page for all errors, you can also assign specific
error pages to specific error status codes. The <customErrors> configuration section
supports an inner <error> tag that associates HTTP status codes with custom error
pages. For example:

<configuration>
<[Link]>
<customErrors mode="RemoteOnly" defaultRedirect="/[Link]">
<error statusCode="500" redirect="/error/[Link]"/>
<error statusCode="404" redirect="/error/[Link]"/>
<error statusCode="403" redirect="/error/[Link]"/>
</customErrors>
</[Link]>
</configuration>

The following table describes the attributes and values for the <error> tag.

Attribute Description
StatusCode HTTP status code of errors for which the custom error page should be
used. Examples: 403 Forbidden, 404 Not Found, or 500 Internal
Server Error.
Redirect URL to which the client browser should be redirected if an error
occurs.

The following example demonstrates how to use the <error> tag. Note that the example
specifies an .aspx page for "File Not Found" errors so that the missing page URL passed
via the QueryString can be printed.

VB [Link]
[Run Sample] | [View
Source]

Handling Errors Programmatically


114
You can also handle errors in code, at either the page level or the application level. The
Page base class exposes a Page_Error method, which you can override in your pages.
The method is called whenever an uncaught exception is thrown at run time.

<script language="C#" runat="server">

Sub Page_Error(Source As Object, E As EventArgs)


Dim message As String = "<font face=verdana color=red>" _
& "<h4>" & [Link]() & "</h4>" _
& "<pre><font color='red'>" _
& [Link]().ToString() & "</pre>" _
& "</font>"

[Link](message)
End Sub

</script>
C# VB JScript

The following sample demonstrates the Page_Error method.

VB [Link]
[Run Sample] | [View
Source]

You could do something useful in this method, like sending an e-mail to the site
administrator saying that the page failed to execute properly. [Link] provides a set of
classes in the [Link] namespace for just this purpose. To import this
namespace, use an @Import directive at the top of your page, as follows:

<%@ Import Namespace="[Link]" %>

You can then use the MailMessage and SmtpMail objects to programmatically send e-
mail.

Dim mail As New MailMessage


[Link] = "automated@[Link]"
[Link] = "administrator@[Link]"
[Link] = "Site Error"
[Link] = message
[Link] = [Link]
[Link](mail)
C# VB JScript

The following sample shows how to send a mail message in response to a page error.

Note: This sample does not actually send mail unless you have configured the SMTP mail
service on your machine. For more information about the SMTP mail service, consult the
IIS documentation.
115

VB [Link]
[Run Sample] | [View
Source]

In addition to handling errors at the page level, you might want to handle errors at the
application level. To do this, use the Application_Error event in [Link]. This event
occurs for any unhandled exception thrown within the application.

Sub Application_Error(sender As Object, e As EventArgs)


'...Do something here
End Sub
C# VB JScript

Writing to the Event Log

The [Link] namespace provides classes for writing to the Windows event
log. To use this namespace in your pages, you must first import the namespace, as
follows:

<%@ Import Namespace="[Link]"%>

The EventLog class encapsulates the log itself. It provides static methods for detecting or
creating logs and can be instantiated to write log entries from code. The following example
shows this functionality within the Application_Error method of [Link]. Whenever
an unhandled exception occurs in the application, an entry containing the error message
and stack trace is made to the application log.

Sub Application_Error(sender As Object, e As EventArgs)

Dim Message As String = "\n\nURL:\n [Link] & [Link] _


& "\n\nMESSAGE:\n " & [Link]().Message _
& "\n\nSTACK TRACE:\n" & [Link]().StackTrace

' Create event log if it does not exist

Dim LogName As String = "Application"


If (Not [Link](LogName))
[Link](LogName, LogName)
End If

' Insert into event log


Dim Log As New EventLog
[Link] = LogName
[Link](Message, [Link])

End Sub
C# VB JScript
116
The complete source code for the preceding example follows. Note that this code is
disabled so that it cannot run here, to prevent entries to your Windows event log. If you
would like to see this code run, create an IIS virtual root pointing to the directory that
contains this file.

VB [Link]
[View Source]

Section Summary

1. Errors are divided into four categories: configuration errors, parser errors,
compilation errors, and run-time errors.
2. By default, the information shown for a run-time error is the call stack (the chain
of procedure calls leading up to the exception). If debug mode is enabled,
[Link] displays the line number in source code where the run-time error
originated.
3. [Link] enables you to specify whether errors are shown to local clients, to
remote clients, or to both. By default, errors are only shown to local clients
(clients on the same computer as the server). You can also specify a custom
error page to redirect clients to if an error occurs.
4. In addition to redirecting to a common page for all errors, you can also assign
specific error pages to specific error status codes. The <customErrors>
configuration section supports an inner <error> tag for associating HTTP status
codes with custom error pages.
5. You can also handle errors in code, at either the page level or application level.
The Page base class exposes a HandleError method, which you can override in
your pages. The method will be called whenever an uncaught exception is thrown
at run time.
6. The [Link] namespace exposes classes for programmatically
sending e-mail. This is useful for notifying an administrator when an error
occurs.
7. In addition to handling errors at the page level, you can use the
Application_Error event in [Link] to handle errors at the application level.
This event will occur for any unhandled exception thrown within the application.
8. The [Link] namespace provides classes for writing to the
Windows event log.

The Microsoft .NET Framework SDK Debugger

No matter how skilled a programmer you are, you are bound to make mistakes once in a while.
Tracking down problems in your code can be baffling without the appropriate tool. Fortunately,
the compiled nature of [Link] means that debugging Web applications is no different than
debugging any other managed applications, and the .NET Framework SDK includes a lightweight
debugger that is perfectly suited for this task.

This section describes the steps required to debug [Link] Framework applications using the
debugger provided in this SDK. The debugger supports manual-attach debugging of processes on
a local development computer. The debugger documentation included in this SDK is your best
resource for information about specific features.
117
Enabling Debug Mode for [Link] Applications

Because many parts of an [Link] Framework application are dynamically compiled at runtime
(.aspx and .asmx files, for example), you must configure the [Link] runtime to compile the
application with symbolic information before the application can be debugged. Symbols (.pdb
files) tell the debugger how to find the original source files for a binary, and how to map
breakpoints in code to lines in those source files. To configure an application to compile with
symbols, include a debug attribute on the compilation section within the [Link] group of
the [Link] file at the application's root directory, as follows:
<configuration>
<compilation debug="true"/>
</configuration>
Important: You should only enable this setting when you are debugging an application, because
it can significantly affect application performance.

Debugging [Link] Applications

When you have enabled debugging for the application, you should issue a request to the page
you want to debug. This ensures that the [Link] runtime process (Aspnet_wp.exe) is created
and the application is loaded into memory.

To begin debugging:

1. Launch the .NET Framework debugger, [Link].


2. Use the File...Miscellaneous Files...Open File menu to open the source file for the
page you want to debug.
3. From the Tools menu, choose Debug Processes. The screen in the figure following
these instructions will appear.
4. Check the Show system processes checkbox, if it is not checked.
5. Find the Aspnet_wp.exe process and double-click it to bring up the Attach to Process
dialog.
6. Make sure your application appears in the list of running applications, and select OK to
attach.
7. Close the Programs dialog.
118
Important: When you attach to the Aspnet_wp.exe process, all threads in that process are
frozen. Under no circumstances should you attempt to debug a live production application,
because client requests can not execute normally until the debugger is detached.

Setting Breakpoints

To set a breakpoint in your page, click the left-hand margin on a line containing an executable
statement or function/method signature. A red dot appears where the breakpoint is set. Move the
mouse over the breakpoint to ensure that it is appropriately mapped to the correct application
instance in the Aspnet_wp.exe process.

Reissue the request to the page from your browser. The debugger will stop at the breakpoint and
gain the current window focus. From this point, you can step, set variable watches, view locals,
stack information, disassembly, and so on. You can see the intrinsic objects on the page, like
Request, Response, and Session by using this (C#) or Me (VB) in the watch window.

Generating Symbols for Pre-Compiled Components

To debug pre-compiled components, such as business objects or code-behind files, you must
compile with symbolic information prior to debugging. Symbols for assemblies are typically found
by means of a path-based search algorithm. The algorithm used by the PDB library ([Link])
to find symbolic information is as follows:

1. Search the same path as the assembly. This is the normal location for .pdb files.
For local assemblies, place the symbols (.pdb files) in the application's /bin directory
with the DLLs.
2. Search path as specified in the PE file (the NB10 debug header).
119
3. Search NT symbol file locations (environment variables _NT_SYMBOL_PATH and
_NT_ALT_SYMBOL_PATH).

Note: If symbolic information cannot be found, the debugger prompts for a user-specified
location.

Section Summary

1. The debugger described in this section supports manual-attach debugging of processes


on a local development computer.
2. Debugging allows the [Link] runtime to dynamically compile with symbolic
information. Enable this by setting <compilation debug="true"/> in the [Link] file
located in the application's root directory. The debugger setting should only be enabled
when you are debugging an application, because it degrades application performance.
3. To debug an application, issue a request to a page, attach the debugger to the
Aspnet_wp.exe process, set breakpoints, and reissue the page request.
4. When attached to the Aspnet_wp.exe process, all threads in that process are frozen.
Under no circumstances should you debug a live production application, since client
requests can not execute normally until the debugger is detached.
5. To debug pre-compiled components, such as business objects or code-behind files, you
must compile with symbolic information prior to debugging.

Security Overview

An important part of many Web applications is the ability to identify users and control access to
resources. The act of determining the identity of the requesting entity is known as authentication.
Generally, the user must present credentials, such as a name/password pair in order to be
authenticated. Once an authenticated identity is available, it must be determined whether that
identity can access a given resource. This process is known as authorization. [Link] works in
conjunction with IIS to provide authentication and authorization services to applications.

An important feature of COM objects is the ability to control the identity under which COM object
code is executed. When a COM object executes code with the identity of the requesting entity,
this is known as impersonation. [Link] Framework applications can optionally choose to
impersonate requests.

Some applications also want to be able to dynamically tailor content, based on the requesting
identity or based on a set of roles that a requesting identity belongs to. [Link] Framework
applications can dynamically check whether the current requesting identity participates in a
particular role. For example, an application might want to check to see whether the current user
belongs to the manager's role, in order to conditionally generate content for managers.

Windows-based Authentication

When you use [Link] Windows authentication, [Link] attaches a WindowsPrincipal object
to the current request. This object is used by URL authorization. The application can also use it
programmatically to determine whether a requesting identity is in a given role.

If [Link]("Administrators") Then
DisplayPrivilegedContent()
End If
C# VB JScript
120
The WindowsPrincipal class determines roles by NT group membership. Applications that
want to determine their own roles can do so by handling the
WindowsAuthentication_OnAuthenticate event in their [Link] file and attaching their
own class that implements [Link] to the request, as shown in
the following example:

' Create a class that implements IPrincipal


Public Class MyPrincipal : Inherits IPrincipal
' Implement application-defined role mappings
End Class

' In a [Link] file


Public Sub WindowsAuthentication_OnAuthenticate(Source As Object, e As
WindowsAuthenticationEventArgs)
' Attach a new application-defined class that implements IPrincipal to
' the request.
' Note that since IIS has already performed authentication, the provided
' identity is used.
[Link] = New MyPrincipal([Link])
End Sub
C# VB JScript

The following sample shows how to access the name of an authenticated user, which is available
as [Link]. Programmers familiar with ASP should note that this value is also still
available as the AUTH_USER server variable:

VB Windows Authentication
[Run Sample] | [View Source]
Windows-based Authentication

When you use [Link] Windows authentication, [Link] attaches a WindowsPrincipal object
to the current request. This object is used by URL authorization. The application can also use it
programmatically to determine whether a requesting identity is in a given role.

If [Link]("Administrators") Then
DisplayPrivilegedContent()
End If
C# VB JScript

The WindowsPrincipal class determines roles by NT group membership. Applications that want
to determine their own roles can do so by handling the
WindowsAuthentication_OnAuthenticate event in their [Link] file and attaching their
own class that implements [Link] to the request, as shown in
the following example:

' Create a class that implements IPrincipal


Public Class MyPrincipal : Inherits IPrincipal
121
' Implement application-defined role mappings
End Class

' In a [Link] file


Public Sub WindowsAuthentication_OnAuthenticate(Source As Object, e As
WindowsAuthenticationEventArgs)
' Attach a new application-defined class that implements IPrincipal to
' the request.
' Note that since IIS has already performed authentication, the provided
' identity is used.
[Link] = New MyPrincipal([Link])
End Sub
C# VB JScript

The following sample shows how to access the name of an authenticated user, which is available
as [Link]. Programmers familiar with ASP should note that this value is also still
available as the AUTH_USER server variable:

VB Windows Authentication
[Run Sample] | [View Source]
Forms-Based Authentication

Forms-based authentication is an [Link] authentication service that enables applications to


provide their own logon UI and do their own credential verification. [Link] authenticates users,
redirects unauthenticated users to the logon page, and performs all the necessary cookie
management. This sort of authentication is a popular technique used by many Web sites.

An application has to be configured to use forms-based authentication by setting


<authentication> to Forms, and denying access to anonymous users. The following example
shows how this can be done in the [Link] file for the desired application:

Administrators use forms-based authentication to configure the name of the cookie to use, the
protection type, the URL to use for the logon page, length of time the cookie is in effect, and the
path to use for the issued cookie. The following table shows the valid attributes for the <Forms>
element, which is a sub-element of the <authentication> element shown in the following
example:
122
Attribute Description
loginUrl Specifies the URL to which the request is redirected for
unauthenticated users. This can be on the same computer or a remote
one. If it is on a remote computer, both computers need to be using
the same value for the decryptionkey attribute.
name Name of the HTTP cookie to use for authentication purposes. Note that
if more than one application wants to use forms-based authentication
services on a single computer, they should each configure a unique
cookie value. In order to avoid causing dependencies in URLs, [Link]
uses "/" as the Path value when setting authentication cookies, so that
they are sent back to every application on the site.
timeout Amount of time in integer minutes, after which the cookie expires. The
default value is 30. The timeout attribute is a sliding value, expiring n
minutes from the time the last request was received. In order to avoid
adversely affecting performance and to avoid multiple browser
warnings for those who have cookies warnings turned on, the cookie is
updated if the time is more than half gone. (This means a loss of
possible precision in some cases.)
path Path to use for the issued cookie. The default value is "/" to avoid
difficulties with mismatched case in paths, since browsers are strictly
case-sensitive when returning cookies. Applications in a shared-server
environment should use this directive to maintain private cookies.
(Alternatively, they can specify the path at runtime using the APIs to
issue cookies.)
protection Method used to protect cookie data. Valid values are as follows:

• All: Use both data validation and encryption to protect the


cookie. The configured data validation algorithm is based on
the element. Triple DES is used for encryption, if available and
if the key is long enough (48 bytes). All is the default (and
suggested) value.
• None: Use for sites that are only using cookies for
personalization and have weaker security requirements. Both
encryption and validation can be disabled. Although you should
use caution if you use cookies in this way, this setting provides
the best performance of any method of doing personalization
using the .NET Framework.
• Encryption: Encrypts the cookie using TripleDES or DES, but
data validation is not done on the cookie. This type of cookie
can be subject to chosen plaintext attacks.

• Validation: Does not encrypt the contents of the cookie, but


validates that the cookie data has not been altered in transit.
To create the cookie, the validation key is concatenated in a
buffer with the cookie data and a MAC is computed and
appended to the outgoing cookie.

After the application has been configured, you need to provide a logon page. The following
example shows a simple logon page. When the sample is run, it requests the [Link] page.
Unauthenticated requests are redirected to the logon page ([Link]), which presents a simple
form that prompts for an e-mail address and a password. (Use
Username="someone@[Link]" and Password="password" as credentials.)

After validating the credentials, the application calls the following:


123

[Link]([Link],
[Link])
C# VB JScript

This redirects the user back to the originally requested URL. Applications that do not want to
perform the redirection can call either [Link] to retrieve the
cookie value or [Link] to attach a properly encrypted cookie to
the outgoing response. These techniques can be useful for applications that provide a logon UI
embedded in the containing page or that want to have more control over where users are
redirected. Authentication cookies can either be temporary or permanent ("persistent").
Temporary cookies last only for the duration of the current browser session. When the browser is
closed, the cookie is lost. Permanent cookies are saved by the browser and are sent back across
browser sessions unless explicitly deleted by the user.

VB Forms-Based/Cookie Authentication
[Run Sample] | [View Source]

The authentication cookie used by forms authentication consists of a linear version of the
[Link] class. The information includes the user
name (but not the password), the version of forms authentication used, the date the cookie was
issued, and a field for optional application-specific data.

Application code can revoke or remove authentication cookies using the


[Link] method. This removes the authentication cookie regardless of
whether it is temporary or permanent.

It is also possible to supply forms-based authentication services with a list of valid credentials
using configuration, as shown in the following example:

The application can then call [Link], supplying the username and
password, and [Link] will verify the credentials. Credentials can be stored in cleartext, or as
SHA1 or MD5 hashes, according to the following values of the passwordFormat attribute:

Hash Type Description


Clear Passwords are stored in cleartext
SHA1 Passwords are stored as SHA1 digests
MD5 Passwords are stored as MD5 digests
Authorizing Users and Roles
124
[Link] is used to control client access to URL resources. It is configurable for the HTTP
method used to make the request (GET or POST) and can be configured to allow or deny access
to groups of users or roles. The following example shows access being granted to a user named
someone and a role named Admins. All other users are denied access.

Permissible elements for authorization directives are either allow or deny. Each allow or deny
element must contain a users or a roles attribute. Multiple users or roles can be specified in a
single element by providing a comma-separated list.

The HTTP method can be indicated using the Verb attribute:

This example lets Mary and John POST to the protected resources, while only allowing everyone
else to use GET.

There are two special usernames:

• *: All users
• ?: Anonymous (unauthenticated) users

These special usernames are commonly used by applications using forms-based authentication to
deny access to unauthenticated users, as shown in the following example:

URL authorization is computed hierarchically and the rules used to determine access are as
follows:

• Rules relevant to the URL are collected from across the hierarchy and a merged list of
rules is constructed.
• The most recent rules are placed at the head of the list. This means that configuration in
the current directory is at the head of the list, followed by configuration in the
immediate parent, and so on, up to the top-level file for the computer.
• Rules are checked until a match is found. If the match is allowable, access is granted. If
not, access is disallowed.

What this means is that applications that are not interested in inheriting their configuration
should explicitly configure all of the possibilities relevant to their applications.

The default setting in the machine-wide configuration file ([Link]) is to grant access to
all users. Unless an application is configured to the contrary (and assuming that a user is
authenticated and passes the file authorization ACL check), access is granted.
125
When roles are checked, URL authorization effectively marches down the list of configured
roles and does something that looks like the following pseudocode:

If [Link]("ConfiguredRole") Then
ApplyRule()
End If
C# VB JScript

What this means for your application is that you use your own class that implements
[Link] to provide your own role-mapping semantics, as
explained in Windows-based Authentication.

The following sample uses forms-based authentication services. It explicitly denies access to
someone@[Link] and anonymous users. Try logging into the sample with
Username="someone@[Link]" and Password="password". Access will be denied and
you will be redirected back to the logon page. Now log on as
Username="[Link]@[Link]" and Password="password". You will see that
access is granted.

VB Forms-Based/Cookie Authentication with URL Authorization


[Run Sample] | [View Source]
User Account Impersonation

As mentioned in the Security Overview, impersonation is the ability of a thread to execute in a


security context different from that of the process owning the thread. What this means for a Web
application is that if a server is impersonating, it is doing work using the identity of the client
making the request.

By default, [Link] does not do per-request impersonation. This is different from ASP, which
does impersonate on every request. If desired, you can configure an application to impersonate
on every request with the following Configuration directive:

Since [Link] does dynamic compilation, enabling impersonation requires that all accounts have
read/write access to the application's Codegen directory (where dynamically compiled objects are
stored by the [Link] runtime) as well as the global assembly cache (%Windir%\assembly).
Some applications require impersonation to be enabled for ASP compatibility or to use Windows
authentication services.

Security and XML Web services


Windows Authentication and Authorization
Custom Authentication and Authorization (with Soap Headers)
Section Summary

This section describes methods for securing your XML Web services. If you haven't already read
the Security section of this tutorial, take the time to do so now before continuing in this topic.
126
Windows Authentication and Authorization

You use the same technique to secure your XML Web services using Windows authentication that
you used for .aspx pages (described in the Windows-based Authentication section). To require
authentication, you enable Integrated Windows authentication for your application and
disable Anonymous access in the IIS management console. To allow or deny specific users
access to your service, use the [Link] configuration system or set ACLs on the service file itself,
as shown in the following example:

<configuration>

<[Link]>
<authentication mode="Windows"/>
</[Link]>

<location path="[Link]">

<[Link]>
<authorization>
<allow users="Administrator"/>
<allow users="DOMAIN\Bradley"/>
<deny roles="BUILTIN\Power Users"/>
</authorization>
</[Link]>

</location>

</configuration>

This works well when you know that the client of the XML Web service will be running as a
specific Windows user. A more interesting case is that of a client running as one user, but acting
on behalf of another. Consider an [Link] page that accesses a secure XML Web service that
does not impersonate the client who accesses it. In such a case, you should programmatically set
the username and password before connecting to the Web service. The following example uses
basic authentication and illustrates a simple XML Web service:

<%@ WebService language="VB" Class="SecureService" %>

Imports [Link]
Imports System

Class SecureService : Inherits WebService

<WebMethod()> Public Function SecureTest As String


Return "Hello from the secure web service"
End
End Class
C# VB JScript

You could require basic authentication for this service by making appropriate settings in IIS as
follows:

1. Open the IIS MMC console.


2. Start->Run "inetmgr"
3. In the left pane, expand the tree to find your virtual directory.
127
4. In the right pane, right-click [Link], and choose Properties.
5. Select the File Security tab. Under Anonymous Access and Authentication
Control, click Edit.
o Disable anonymous access.
o Disable integrated Windows authentication.
o Enable basic authentication.
6. Click OK to save these settings and exit the MMC console.

The base XML Web service proxy class provides two properties, Username and Password,
that you can use to specify the credentials with which to connect to the remote Web service.
These must be set to valid Windows credentials on the Web service's computer or domain.

<%@ Import Namespace="SecureService" %>

<html>
<script language="VB" runat="server">

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

Dim s As New SecureService

[Link] = New [Link]("Administrator",


"test123")

[Link] = [Link]()
End Sub

</script>

<body>
<h4><font face="verdana">
<asp:Label id="Message" runat="server"/>
</font></h4>
</body>

</html>
C# VB JScript

The base XML Web service class also provides a User property of type
[Link], which you can use to retrieve information about the
client user. Again, you can authorize access to your Web service using the Authorization section
in the [Link] configuration system.

Custom Authentication and Authorization with Soap Headers

Windows authentication works well for intranet scenarios, in which you are authenticating against
a user in your own domain. On the Internet, however, you probably want to perform custom
authentication and authorization, perhaps against a SQL database. In that case, you should pass
custom credentials (such as the username and password) to your service and let it handle the
authentication and authorization itself.

A convenient way to pass extra information along with a request to a XML Web service is a SOAP
header. To do this, define a class that derives from SOAPHeader in your service, and then
declare a public field of your service as that type. This is exposed in the public contract for your
service, and made available to the client when the proxy is created from [Link], as
in the following example:
128
Imports [Link]
Imports [Link]

' AuthHeader class extends from SoapHeader


Public Class AuthHeader : Inherits SoapHeader
Public Username As String
Public Password As String
End Class

Public Class HeaderService : Inherits WebService


Public sHeader As AuthHeader
...
End Class
C# VB JScript

Each WebMethod in your service can define a set of associated headers using the SoapHeader
custom attribute. By default, the header is required, but it is possible to define optional headers
as well. The SoapHeader attribute specifies the name of a public field or property of the Client
or Server class (referred to as a Headers property in this topic). XML Web services sets the
value of a Headers property before the method is called for input headers, and retrieves the
value when the method returns for output headers. For more information about output or
optional headers see the .NET Framework SDK documentation.

<WebMethod(), SoapHeader("sHeader")> Public Function SecureMethod() As String

If (sHeader Is Nothing)
Return "ERROR: Please supply credentials"
Else
Return "USER: " & [Link]
End If
End Function
C# VB JScript

A client then sets the header on the proxy class directly before making a method call that
requires it, as shown in the following example:

Dim h As New HeaderService


Dim myHeader As New AuthHeader
[Link] = "JohnDoe"
[Link] = "password"
[Link] = myHeader
Dim result As String = [Link]()
C# VB JScript

To see this code in action, run the following sample:

VB [Link]
129
[Run Sample] | [View
Source]

Section Summary

1. Securing your XML Web services on the server using Windows authentication follows
exactly the same model as described for .aspx page.
2. You can also programmatically set Windows credentials using the Username and
Password properties on the XML Web service proxy class.
3. Lastly, you can do custom authentication by passing credential information as
SOAPHeaders, along with a SOAP request to the method that requires it.

Performance Overview

Feature-rich web applications are not very useful if they cannot perform well. The demands of the
Web are so great that code is expected to do more in less time than ever before. This section
describes some key principles of Web application performance, tips for writing code that performs
well, and tools for measuring performance.

[Link] provides a number of built-in performance enhancements. For example, pages are
compiled only once and cached for subsequent requests. Because these compiled pages are
saved to disk, even a complete server restart does not invalidate them. [Link] also caches
internal objects, such as server variables, to speed user code access. Further, [Link] benefits
from all of the performance enhancements to the common language runtime: just-in-time
compiling, a fine-tuned common language runtime for both single- and multiprocessor
computers, and so on.

However, all of these enhancements cannot protect you from writing code that does not perform
well. Ultimately, you must ensure that your application can meet the demands of its users. The
next section describes a few of the common ways to avoid performance bottlenecks. However,
first you need to understand the following metrics:

• Throughput: The number of requests a Web application can serve per unit of time,
often measured in requests/second. Throughput can vary, depending on the load
(number of client threads) applied to the server. This is usually considered the most
important performance metric to optimize.
• Response Time: The length of time between the issuance of a request and the first
byte returned to the client from the server. This is often the most perceptable aspect of
performance to the client user. If an application takes a long time to respond, the user
can become impatient and go to another site. The response time of an application can
vary independently of (even inversely to) the rate of throughput.
• Execution Time: The time it takes to process a request, usually measured between the
first byte and the last byte returned to the client from the server. Execution time directly
affects the throughput calculation.
• Scalability: The measurement of an application's ability to perform better as more
resources (memory, processors, or computers) are allocated to it. Often, it is a
measurement of the rate of change of throughput with respect to the number of
processors.

Writing applications that perform well is all about striking a balance between these metrics. No
single measurement can characterize how your application will behave under varying
circumstances, but several measurements taken together can paint a reasonable picture of an
application's performance.

Performance Tuning Tips


130
Any programming model has its common performance pitfalls, and [Link] is no exception.
This section describes some of the ways in which you can avoid performance bottlenecks in your
code.

1. Disable Session State when not in use: Not all applications or pages require per-
user session state. If it is not required, disable it completely. This is easily accomplished
using a page-level directive, such as the following:
2. <%@ Page EnableSessionState="false" %>

Note: If a page requires access to session variables but does not create or modify them,
set the value of the directive to ReadOnly. Session State can also be disabled for XML Web
service methods. See Using Objects and Intrinsics in the XML Web services section.

3. Choose your Session State provider carefully: [Link] provides three distinct ways
to store session data for your application: in-process session state, out-of-process
session state as a Windows Service, and out-of-process session state in a SQL database.
Each has its advantages, but in-process session state is by far the fastest solution. If
you are only storing small amounts of volatile data in session state you should use the
in-process provider. The out-of-process solutions are primarily useful in Web garden and
Web farm scenarios or in situations in which data cannot be lost in the event of a
server/process restart.
4. Avoid excessive round trips to the server: The Web Forms page framework is one
of the best features of [Link], because it can dramatically reduce the amount of code
you need to write to accomplish a task. Programmatic access to page elements using
server controls and the postback event handling model are arguably the most time-
saving features. However, there are appropriate and inappropriate ways to use these
features, and it is important to know when it is appropriate to use them.

An application typically needs to make a round trip to the server only when retrieving data
or storing data. Most data manipulations can take place on the client between round trips.
For example, validating form entries can often take place on the client before the user
submits data. In general, if you do not need to relay information back to the server, then
you should not make a round trip to the server.

If you are writing your own server controls, consider having them render client-side code
for up-level (ECMAScript-capable) browsers. By employing "smart" controls, you can
dramatically reduce the number of unecessary hits to your Web server.

5. Use [Link] to avoid extra work on a round trip: If you are handling
server control postbacks, you often need to execute different code the first time the
page is requested from the code you do use for the round trip when an event is fired. If
you check the [Link] property, your code can execute conditionally,
depending on whether there is an initial request for the page or a responce to a server
control event. It might seem obvious to do this, but in practice it is possible to omit this
check without changing the behavior of the page. For example:
131

<script language="VB" runat="server">

Public ds As DataSet
...

Sub Page_Load(sender As Object, e As EventArgs)


' ...set up a connection and command here...
If Not ([Link])
Dim query As String = "select * from Authors where
FirstName like '%JUSTIN%'"
[Link](ds, "Authors")
[Link]()
End If
End Sub

Sub Button_Click(sender As Object, e As EventArgs)


Dim query As String = "select * from Authors where FirstName
like '%BRAD%'"
[Link](ds, "Authors")
[Link]()
End Sub

</script>

<form runat="server">
<asp:datagrid datasource='<%# [Link]("Authors").DefaultView %>'
runat="server"/><br>
<asp:button onclick="Button_Click" runat="server"/>
</form>
C# VB JScript

6. The Page_Load event executes on every request, so we checked [Link] so


that the first query does not execute when we process the Button_Click event
postback. Note that even without this check our page would behave identically, since
the binding from the first query would be overturned by the call to DataBind in the
event handler. Keep in mind that it can be easy to overlook this simple performance
improvement when you write your pages.
7. Use server controls sparingly and appropriately: Even though it is extremely easy
to use, a server control might not always be the best choice. In many cases, a simple
rendering or databinding substitution will accomplish the same thing. For example:
132
<script language="VB" runat="server">

Public imagePath As String


Sub Page_Load(sender As Object, e As EventArgs)
'...retrieve data for imagePath here...
DataBind()
End Sub

</script>

<%--the span and img server controls are unecessary...--%>


The path to the image is: <span innerhtml='<%# imagePath %>'
runat="server"/><br>
<img src='<%# imagePath %>' runat="server"/>

<br><br>

<%-- use databinding to substitute literals instead...--%>


The path to the image is: <%# imagePath %><br>
<img src='<%# imagePath %>' />

<br><br>

<%-- or a simple rendering expression...--%>


The path to the image is: <%= imagePath %><br>
<img src='<%= imagePath %>' />
C# VB JScript

8. In this example, a server control is not needed to substitute values into the resulting
HTML sent back to the client. There are many other cases where this technique works
just fine, even in server control templates. However, if you want to programmatically
manipulate the control's properties, handle events from it, or take advantage of its state
preservation, then a server control would be appropriate. You should examine your use
of server controls and look for code you can optimize.
9. Avoid excessive server control view state: Automatic state management is a
feature that enables server controls to re-populate their values on a round trip without
requiring you to write any code. This feature is not free however, since the state of a
control is passed to and from the server in a hidden form field. You should be aware of
when ViewState is helping you and when it is not. For example, if you are binding a
control to data on every round trip (as in the datagrid example in tip #4), then you do
not need the control to maintain it's view state, since you will wipe out any re-populated
data in any case.

ViewState is enabled for all server controls by default. To disable it, set the
EnableViewState property of the control to false, as in the following example:

<asp:datagrid EnableViewState="false" datasource="..." runat="server"/>

You can also turn ViewState off at the page level. This is useful when you do not post
back from a page at all, as in the following example:

<%@ Page EnableViewState="false" %>

Note that this attribute is also supported by the User Control directive. To analyze the
amount of view state used by the server controls on your page, enable tracing and look at
the View State column of the Control Hierarchy table. For more information about the
Trace feature and how to enable it, see the Application-level Trace Logging feature.
133
10. Use [Link] for String concatenation: Use the [Link]
method in your pages or user controls for string concatenation. This method offers
buffering and concatenation services that are very efficient. If you are performing
extensive concatenation, however, the technique in the following example, using
multiple calls to [Link], is faster than concatenating a string with a single call
to the [Link] method.

[Link]("a")
[Link](myString)
[Link]("b")
[Link]([Link]())
[Link]("c")
[Link](myString2)
[Link]("d")
C# VB JScript

11. Do not rely on exceptions in your code: Exceptions are very expensive and should
rarely occur in your code. You should never use exceptions as a way to control normal
program flow. If it is possible to detect in code a condition that would cause an
exception, you should do that instead of waiting to catch the exception before handling
that condition. Common scenarios include checking for null, assigning to a string that
will be parsed into a numeric value, or checking for specific values before applying math
operations. For example:

' Consider changing this:

Try
result = 100 / num

Catch (e As Exception)
result = 0
End Try

// To this:

If Not (num = 0)
result = 100 / num
Else
result = 0
End If
C# VB JScript

12. Use early binding in Visual Basic or JScript code: One of the advantages of Visual
Basic, VBScript, and JScript is their typeless nature. Variables can be created simply by
using them and need no explicit type declaration. When assigning from one type to
another, conversions are performed automatically, as well. This can be both an
advantage and a disadvantage, since late binding is a very expensive convenience in
terms of performance.

The Visual Basic language now supports type-safe programming through the use of a
special Option Strict compiler directive. For backward compatibility, [Link] does not
enable Option Strict by default. However, for optimal perfomance, you should enable
Option Strict for your pages by using a Strict attribute on the page or Control directive:

<%@ Page Language="VB" Strict="true" %>


134
<%

Dim B
Dim C As String

' This causes a compiler error:


A = "Hello"

' This causes a compiler error:


B = "World"

' This does not:


C = "!!!!!!"

' But this does:


C = 0

%>

JScript also supports typeless programming, though it offers no compiler directive to force
early binding. A variable is late-bound if:

o It is declared explicitly as an object.


o It is a field of a class with no type declaration.
o It is a private function/method member with no explicit type declaration and the
type cannot be inferred from its use.

The last distinction is complicated. The JScript compiler optimizes if it can figure out the
type, based on how a variable is used. In the following example, the variable A is early-
bound but the variable B is late-bound:

var A;
var B;

A = "Hello";
B = "World";
B = 0;

For the best performance, declare your JScript variables as having a type. For example,
"var A : String".

13. Port call-intensive COM components to managed code: The .NET Framework
provides a remarkably easy way to interoperate with traditional COM components. The
benefit is that you can take advantage of the new platform while preserving your
existing code. However, there are some circumstances in which the performance cost of
keeping your old components is greater than the cost to migrate your components to
managed code. Every situation is unique, and the best way to decide what needs to be
changed is to measure site performance. In general, however, the performance impact
of COM interoperability is proportional to the number of function calls made or the
amount of data marshaled from unmanaged to managed code. A component that
requires a high volume of calls to interact with it is called "chatty," due to the number of
communications between layers. You should consider porting such components to fully
managed code to benefit from the performance gains provided by the .NET platform.
Alternatively, you might consider redesigning your component to require fewer calls or
to marshal more data at once.
135
14. Use SQL stored procedures for data access: Of all the data access methods
provided by the .NET Framework, SQL-based data access is the best choice for building
scalable web applications with the best performance. When using the managed SQL
provider, you can get an additional performance boost by using compiled stored
procedures instead of ad hoc queries. For an example of using SQL stored procedures,
refer to the Server-Side Data Access section of this tutorial.
15. Use SqlDataReader for a fast-forward, read-only data cursor: A SqlDataReader
object provides a forward, read-only cursor over data retrieved from a SQL database.
SqlDataReader is a more performant option than using a DataSet if it can be used for
your scenario. Because SqlDataReader supports the IEnumerable interface, you can
even bind server controls, as well. For an example of using SqlDataReader, see the
Server-Side Data Access section of this tutorial.
16. Cache data and output wherever possible: The [Link] programming model
provides a simple mechanism for caching page output or data when it does not need to
be dynamically computed for every request. You can design your pages with caching in
mind to optimize those places in your application that you expect to have the most
traffic. More than any feature of the .NET Framework, the appropriate use of caching
can enhance the performance of your site, sometimes by an order of magnitude or
more. For more information about how to use caching, see the Cache Services section of
this tutorial.
17. Enable Web gardening for multiprocessor computers: The [Link] process model
helps enable scalability on multiprocessor machines by distributing the work to several
processes, one for each CPU, each with processor affinity set to its CPU. The technique
is called Web gardening, and can dramatically improve the performance of some
applications. To learn how to enable Web gardening, refer to the Using the Process
Model section.
18. Do not forget to disable Debug mode: The <compilation> section in [Link]
configuration controls whether an application is compiled in Debug mode, or not. Debug
mode degrades performance significantly. Always remember to disable Debug mode
before you deploy a production application or measure performance. For more
information about Debug mode, refer to the section entitled The SDK Debugger.

Measuring Performance

Measuring Web server performance is a skill that can only be refined by repeated experience and
experimentation. There are many variables at play, such as the number of clients, speed of client
connections, server resources, application code, and so on. It helps to have good tools at your
disposal, and fortunately those are available.

Microsoft provides the Web Application Stress (WAS) tool, which simulates multiple HTTP clients
hitting your Web site. You can control the client load, number of connections, format of cookies,
headers, and several other parameters from the tool's graphical interface. After a test run, WAS
provides you with reports containing performance metrics such as response time, throughput,
and performance counter data relevant to your application. The goal is simple: to maximize
throughput and CPU utilization under high degrees of load. WAS is available from the Microsoft
Internet Information Server Resource Kit and is also downloadable separately from
[Link]

[Link] also exposes a number of performance counters that can be used to track the execution
of your applications. Unlike traditional ASP, most of these performance counters are exposed per-
application, instead of globally for the entire machine. The per-application counters are available
under the [Link] Framework applications performance object, and you need to select a
particular application instance when selecting a counter to monitor. Of course, you can still see
the counter values for all applications using a special "__Total__" application instance in System
Monitor. [Link] also exposes global-only counters which are not bound to a particular
136
application instance. These counters are located under the [Link] System performance
object. To view all available counters for [Link] (on Windows 2000 systems):

1. Select Start->Programs->Administrative Tools->Performance.


2. Click the View Report button in System Monitor.
3. Click the Add button.
4. Select [Link] Applications, then choose the All counters radio button. Click OK.
5. Select [Link], then choose the All counters radio button. Click OK.

The [Link] Trace feature is also useful for identifying performance bottlenecks in your code. It
can show you important timing information between successive trace output statements, as well
as information about the server control heierarchy, the amount of viewstate used, and the render
size of controls on your page. For more information about the Trace feature, refer to the Tracing
section of this tutorial.

You might also like