Attributes of the Page Object
In ASP.old, you wrote the majority of your page-rendering code against five objects (Application, Request, Response, Server, and Session). All these objects exist in ASP.NET, although their relative utility is diminished somewhat by the more structured event-driven paradigm provided by ASP.NET.
For example, in ASP.old you typically built applications based on forms that were submitted to the server and handled in script. The script automatically parsed the elements of the form into members of the Request.Form collection. You could then send data back to the browser as a combination of templated HTML and calls to the Write method of the Response object.
In ASP.NET, you don't have to use Request.Form to read the contents of form controls; instead, you can read the properties of those controls directly. This makes programming much easier, eliminating a conceptual hurdle to building sophisticated user interfaces and ensuring that data handled by your application is strongly typed from end to end. You do not need to use Response.Write to send output to the browser, either. Although you may be accustomed to using this quite frequently in ASP.old, you'll almost never see it in ASP.NET.
The following sections describe elements of the Page object in more depth, including the familiar Request, Response, Server, and Session objects, and adding some new functionality provided by the Page object that's unique to ASP.NET.
Page Directives
Page directives are commands, inserted at the top of an ASP.NET page, that represent a mixed bag of settings pertaining to how the page is rendered and processed.
Table 3.1 shows a complete list of ASP.NET page directives.
Table 3.1 ASP.NET Page Directives
Directive |
Description |
@Page |
A mixed bag of settings pertaining to how the page is rendered, buffered, globalized, and so forth. |
@Control |
Settings specific to how user controls are rendered. |
@Import |
Imports a namespace. |
@Implements |
Utilizes a COM interface. |
@Register |
Registers a server control tag prefix and namespace for use in the page. |
@Assembly |
Links an assembly to the page. |
@OutputCache |
Determines how the page caches output. |
You insert a page directive at the top of the page. Listing 3.23 shows an example of a typical @Page directive.
Listing 3.23 Typical @Page Directive
<%@ Page language="VB" debug="true" strict="true" trace="true" %>
This Page directive instructs ASP.NET to interpret code in the page as Visual Basic .NET, to activate debugging, to execute code in strict mode (a mode unique to the Visual Basic .NET language), and to execute in Trace mode to assist with debugging and performance analysis.
Note
The @Page directive is used when you want to change the default settings for a single page in your ASP.NET Web application. However some of the settings in the @Page directive can also be altered for an entire directory (using the Web.config settings file) or an entire server (using the Machine.config settings file). See Chapter 6, "Configuration and Deployment," for more information on how to use these files to configure your server.
The next few sections give examples and scenarios that demonstrate and describe when you would use the various page directives. (The debugging and tracing features of ASP.NET are covered in Chapter 4, "Debugging ASP.NET Applications.")
Setting Single-Thread Compatibility Using the AspCompat Attribute
COM components built with Visual Basic 6.0 use single-threaded apartment (STA) threading. To use an STA component with ASP.NET, your ASP.NET page must also use single threaded apartments.
Setting the AspCompat attribute of the @Page directive to true causes your page to execute on a single thread, ensuring compatibility with STA components.
This attribute should be used sparingly because it degrades ASP.NET performance. Use it only in cases where you are unable to port the STA object to .NET.
Controlling Event Handlers Using the AutoEventWireup Attribute
The AutoEventWireup attribute of the @Page directive is used to override the default event procedures used to handle Page events. This attribute is set to true by default.
In general, most of the time this will have bearing only on the name of the procedure used to handle the Page object's Load event. When AutoEventWireup is true, the event procedure is called Page_Load. If AutoEventWireup is false, you have to create a custom event handler to handle the Page object's events.
This feature is used most often with code behind. Listing 3.24 shows an example of a procedure definition for a code-behind Page_Load event.
Listing 3.24 Definition of a Code-Behind Page_Load Event Procedure Without AutoEventWireup
Private Sub MyPageLoad(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' TODO: Enter your event code here End Sub
You can see that this procedure definition differs from a normal Page_Load. It is named differently from what you might expect. It can be named differently because it contains the clause Handles MyBase.Load. This associates the event handler with the Load event of the page, which is necessary because AutoEventWireup was set to false. It also allows us to associate a subroutine with any name with a specified event. (You'll see this pattern frequently in Web forms pages you create using Visual Studio .NET.) In this context, MyBase refers to the Page object itself. The class that implements code behind always inherits from the Page object, and MyBase always returns a reference to the class from which the current object inherited.
For more information on how code behind works, see the section "Separating Presentation from Code Using Code Behind" earlier in this chapter.
Deactivating Page Buffering Using the Buffer Attribute
When the Web server is building a page for display in the browser, it can either send the data to the browser a little at a time, or it can store the entire page and send it to the browser in one fell swoop. Sending the data to the browser all at once is called buffering. Buffering a page can yield significant performance improvements because it potentially lowers the number of TCP packets that must be sent to return the page to the user. It can also make for a more positive perceived user experience because a buffered page renders all at once instead of progressively painting as data arrives.
In ASP.NET, buffering is turned on by default. Setting the Buffer attribute in the @Page directive to false turns off buffering.
Denoting the Code-Behind Class Using the ClassName Attribute
You use the ClassName attribute to denote the code-behind class used by the page. For more information on how code behind works, see the section "Separating Presentation from Code Using Code Behind" earlier in this chapter.
Specifying the Target Client Using the ClientTarget Attribute
You can use the ClientTarget attribute to specify the user agent (a.k.a. browser type) for which the server controls in your application should render their content. It makes sense to use this option in a situation where you have a captive audience that has standardized on a particular browser (as in an intranet), and you are using server controls that adapt to browser capabilities.
Note
The ASP.NET documentation doesn't explicitly state that setting this value produces a performance gain, but presumably it would because server controls would not have to sniff the browser before rendering themselves.
Every browser is supposed to pass a user agent string identifying the type and version number of the browser each time it makes an HTTP request. You can programmatically retrieve the user agent string reported by the browser by inspecting the value of Page.Request.UserAgent.
Note that some browsers try to trick the Web server into thinking that they're a different kind of browser by passing a bogus user-agent string. For example, by default, Opera 5.0 identifies itself to the browser as Internet Explorer 5.0. This is done to ensure that the browser will work with Web applications that sniff the browser in brain-dead ways (for example, by attempting to detect the brand of the browser instead of its underlying capabilities).
Setting the Language Using the CodePage Attribute
A code page is a set of mappings between text characters and numbers.
One common code page in the United States is UTF-8, also known as Unicode, and described in Internet RFC 2279 (see http://www.ietf.org/rfc/rfc2279.txt if you're really interested).
It's necessary only to specify the CodePage attribute when the page you've authored was written using a different code page than the Web server it's running on. We're hoping you don't do this too often.
Setting Compiler Options Using the CompilerOptions Attribute
You can use the CompilerOptions attribute to pass additional arguments to the compiler when the page is run. To do this, you'll need to have an excellent handle on how compiler switches work, a page that somehow lacks a capability found in a compiler switch, and fortitude.
We wracked our brains trying to figure out why you would use this feature, but we couldn't come up with much. The documentation isn't much help, either. Many of the compiler switches are already represented in ASP.NET in various ways (for example, /optionstrict), so it's possible that the CompilerOptions is simply a hook that ASP.NET provides for you, enabling you to take advantage of future compiler options that may become available before ASP.NET officially supports them.
Setting the ContentType Attribute
The ContentType attribute maps to an HTTP setting that tells the browser what kind of data to expect as the response to a request. Almost always, the data sent from the Web server will be an HTML page. However, you may want to change this. You can use the ContentType attribute of the Page directive to make this change.
You change the ContentType attribute in situations where your ASP.NET page is designed to send data other than HTML to the browser; one common, real-world situation would be sending XML directly to the browser. To do this, set the content type to "text/xml". If the output of the page contains well-formed XML data (and nothing but XML data), and your browser has the capability to display XML directly (that is, Internet Explorer 5.0 or later), the XML will render directly in the browser.
Specifying International Culture Using the Culture Attribute
You can use the Culture attribute to specify for which culture the content of your Web page is intended. Culture in this context means international dialect and language. For example, the culture attribute "en-US" stands for U.S. English, whereas "en-GB" stands for the kind of English that our good friends in the United Kingdom speak.
Certain operations in the .NET framework, such as the formatting of strings, are culture dependent. For example, many European cultures use a comma instead of the decimal point used by Americans and other sensible cultures. (Just kidding.)
Activating Debugging Using the Debug Attribute
Setting the Debug attribute to true activates ASP.NET Debug mode, which provides rich debugging information in the browser to remote machines when an error is encountered in an ASP.NET page.
Debugging is covered in Chapter 4.
Setting the Description Attribute
The Description attribute enables you to append a textual description of your choice to your page. This page isn't accessible programmatically; it's presumably just a way for you to insert a comment describing the page in the @Page directive.
Setting the EnableSessionState Attribute
Session state refers to the capability of a Web application to store information for individual users as the user navigates from page to page. Session state is turned on by default; you may want to consider setting the EnableSessionState attribute to falsethat deactivates session state and can increase performance.
See Chapter 5, "State Management and Caching," for a general discussion of how session state works in ASP.NET.
Activating View State Using the EnableViewState and EnableViewStateMac Attribute
View State is the feature of ASP.NET that causes a control's properties to be retained across round trips to the server. It is discussed more fully in the section "Postback and View State," later in this chapter.
View State is enabled in ASP.NET pages by default. Setting the EnableViewState attribute to false enables you to turn View State off. Note that it is also possible to turn View State off on a control-by-control basis, for controls that support it, by setting the control's ViewStateEnabled property to false.
Turning off View State can increase application performance by reducing the amount of data that must be sent to and from the server.
Setting EnableViewStateMac to true enables an additional check to ensure that View State information was not altered between the time it was sent to the browser by the server and the time it was resubmitted to the server (Mac in this context stands for Machine Authentication Check). This is an important security feature that you should employ whenever sensitive data is stored in View State.
Setting the ErrorPage Attribute
The ErrorPage attribute enables you to redirect to a custom error page of your choosing. The value for the attribute can be any URL. This attribute is commonly set in applications where it's likely that the user will enter a bogus value (a long URL, for example, or perhaps a mistyped query string parameter), and you don't want the user to be confronted with a grungy ASP.NET error page.
Setting VB Option Explicit Mode Using the Explicit Attribute
The Option Explicit setting in Visual Basic forces the developer to declare variables before using them. Setting the Explicit attribute of the @Page directive is the same as using Option Explicit in code.
This setting has no meaning in pages written in languages other than Visual Basic.
Inheriting from a Class Using the Inherits Attribute
Each ASP.NET page is treated as a class. You can cause your ASP.NET page to inherit from another class by setting the Inherits attribute.
You typically use the Inherits attribute to take advantage of code-behind functionality. Code-behind functionality is described in more detail in the section "Separating Presentation from Code Using Code Behind" in this chapter.
Setting the Language Attribute
The Language attribute determines the programming language used in the page. By default, you can choose VB, C#, or JScript, although other .NET languages could be used as well. Note that an ASP.NET page can only have one language.
Setting the Locale Identifier Using the LCID Attribute
The locale identifier (LCID) is an integer that corresponds to a national language setting. The idea behind an LCID is to give the client some idea of what national language the application supports. Because the LCID value is a 32-bit number, the value can be quite granular when describing different dialects of the same language. For example, the LCID value 1033 denotes United States English; the value 2057 denotes the flavour of English spoken in the United Kingdom.
By default, ASP.NET uses your Web server's locale (set in operating system configuration) as the locale for each page. Setting this attribute to a different value overrides the locale setting.
Setting the Src Attribute for Code Behind
The code executed by a particular ASP.NET page can be located in an external file. You use the Src (source) attribute to specify the name of the external file.
You typically use the src attribute to take advantage of code-behind functionality. Code-behind functionality is described in more detail in the section "Separating Presentation from Code Using Code Behind" in this chapter.
Setting the Strict Attribute to Prevent Narrowing Conversions
The Strict attribute sets a Visual Basic-specific attribute. When the option is turned on, you can't perform implicit narrowing conversions; that is, you can't perform data conversions that would cause a loss of precision in Visual Basic. Listing 3.25 shows an example of an implicit narrowing conversion.
Listing 3.25 An Implicit Narrowing Conversion in Visual Basic; Illegal When Option Strict Is Turned On
Dim x As Integer Dim y As Double y = 3.14159 x = y
If you run this code when Option Strict is turned off, the value of x is 3. When Option Strict is turned on, the code produces an error.
Turning Strict on as an @Page directive attribute is the same as using the Visual Basic directive Option Strict. Option Strict exists because implicit narrowing conversions can be an obscure and difficult-to-debug source of errors in Visual Basic code.
When Option Strict is on, you also can't use variables without first declaring them, and you can't use late binding. (It's rare that you'd want to use these "features" in ASP.NET anyway, so this is generally a good thing.)
Option Strict is set to false by default. Turning on this setting has no meaning for pages written in languages other than VB.
Setting the Trace Attribute to Activate Tracing
Setting the Trace attribute to True activates tracing for the current page. Tracing helps developers debug an ASP.NET application. Your trace code might simply indicate that a particular piece of code executed successfully; trace code can also give you a sense of how control flows as a page executes and how long each operation in the lifetime of a page takes to accomplish.
Tracing is covered in more detail in Chapter 4.
Setting the TraceMode Attribute to Sort Trace Information
The TraceMode attribute determines how trace information is displayed when tracing is turned on. Setting TraceMode to SortByTime displays trace entries from earliest to latest. Setting the attribute to SortByCategory groups trace entries by type.
Tracing is covered in more detail in Chapter 4.
Setting the Transaction Attribute to Support Transactions
You can add support for transactions to your pages by using the Transaction attribute. Transactions are set to NotSupported by default; other settings are Supported, Required, and RequiresNew.
Setting the WarningLevel Attribute
You can force the .NET compiler to treat compiler warnings as errors by setting the WarningLevel attribute of the @Page directive to true.
Five levels of compiler warnings exist, numbered 0 through 4. When the compiler transcends the warning level set by this attribute, compilation fails. The meaning of each warning level is determined by the programming language and compiler you're using; consult the reference specification for your compiler to get more information about the warning levels associated with compiler operations and what triggers compiler warnings.
@Control Directives
You use an @Control directive in place of an @Page directive in a user control (.ASCX) file. User controls are script files that provide programmable user-interface functionality. The @Control directive has many of the same attributes as the @Page directive.
User controls are discussed in Chapter 10, "Building User Controls and Server Controls."
@Import Directives
The @Import directive is used to make classes found in that namespace easier to access. When you import a namespace, you don't have to refer to the full namespace syntax to refer to a class in that namespace; you can, for example, use the name DataSet instead of System.Data.Dataset.
An Import directive looks like this:
<@ Import namespace="System.Data" %>
You can have as many Import directives in your page as you want; each namespace reference should have its own Import directive.
Note that you can use classes in any namespace loaded into the Global Assembly Cache (GAC); this includes all .NET framework classes and anything else you've stuck in the GAC.
Implementing External Interfaces with the @Implements Directive
You use the @Implements directive to implement an interface. To understand why this feature exists, remember that every ASP.NET page is really a kind of subclass of the Page object. If you want the object to have access to functionality that requires the implementation of an interface, you must use this directive.
For example, you could use @Implements in user-control development to implement the IPostBackEventHandler interface as a way of raising events associated with postback.
You can't use the @Implements directive in a code-behind class (use the normal Implements statement instead).
Registering Controls with the @Register Directive
The @Register directive is used to make your ASP.NET page aware of user controls and server controls. It also gives custom ASP.NET controls a programmer-defined namespace, ensuring that the name of one control doesn't conflict with the name of another control.
Custom ASP.NET user interface controls are discussed in Chapter 10.
@Assembly Directives
The @Assembly directive is used to make your ASP.NET page aware of external components. You can use one of two elements with this directiveName or Src. Name is the name of a precompiled assembly (without the .DLL extension). Src represents the name of a source code file (such as myclass.vb).
@OutputCache Directives
You can use @OutputCache directives to control how page caching works. Page caching is a feature that can improve performance on ASP.NET pages whose content changes infrequently.
Caching is discussed in more detail in Chapter 5.
Events Raised by the Page Object
The Page object raises a set of events that you can respond to in code.
The events raised by the Page object are standard .NET events, which means they receive a minimum of two arguments: a Sender (a reference to the object that raised the event) and a collection that represents arguments passed to that event (inherited from System.EventArgs). The contents of this collection differ, depending on the event procedure.
Table 3.2 shows a list of events supported by the Page object.
Table 3.2 Events Supported by the Page Object
Event |
Description |
AbortTransaction |
A transaction was aborted. |
CommitTransaction |
A transaction was completed. |
DataBinding |
Data binding was completed. |
Disposed |
The page has been released from memory. This is the last event. |
Error |
An unhandled exception was thrown on the page. |
Init |
The page was first loaded. This is the first event raised by the page. |
Load |
The page is loaded. |
PreRender |
The page content is about to be displayed. |
Unload |
The page is about to be unloaded from memory. |
As you've seen in the code examples to this point, the most common event handled in the Page object is Load. Many of the initialization events, such as Init and PreRender, are essentially the same as Load; they exist here only because the Page object and ASP.NET Web controls inherit from the same class (System.Web.UI.Control).