aspnet

80
ASP.NET is a unified Web development model that includes the services necessary for you to build enterprise-class Web applications with a minimum of coding. ASP.NET is part of the .NET Framework, and when coding ASP.NET applications you have access to classes in the .NET Framework. You can code your applications in any language compatible with the common language runtime (CLR), including Microsoft Visual Basic, C#, JScript .NET, and J#. These languages enable you to develop ASP.NET applications that benefit from the common language runtime, type safety, inheritance, and so on. ASP.NET includes: A page and controls framework The ASP.NET compiler Security infrastructure State-management facilities Application configuration Health monitoring and performance features Debugging support An XML Web services framework Extensible hosting environment and application life cycle management An extensible designer environment Page and Controls Framework The ASP.NET page and controls framework is a programming framework that runs on a Web server to dynamically produce and render ASP.NET Web pages. ASP.NET Web pages can be requested from any browser or client device, and ASP.NET renders markup (such as HTML) to the requesting browser. As a rule, you can use the same page for multiple browsers, because ASP.NET renders the appropriate markup for the browser making the request. However, you can design your ASP.NET Web page to target a specific browser, such as Microsoft Internet Explorer 6, and take advantage of the features of that browser. ASP.NET supports mobile controls for Web-enabled devices such as cellular phones, handheld computers, and personal digital assistants (PDAs).

Upload: deepa-d-gursale

Post on 25-Nov-2014

306 views

Category:

Documents


4 download

TRANSCRIPT

Page 1: ASPNET

ASP.NET is a unified Web development model that includes the services necessary for you to build enterprise-class Web applications with a minimum of coding. ASP.NET is part of the .NET Framework, and when coding ASP.NET applications you have access to classes in the .NET Framework. You can code your applications in any language compatible with the common language runtime (CLR), including Microsoft Visual Basic, C#, JScript .NET, and J#. These languages enable you to develop ASP.NET applications that benefit from the common language runtime, type safety, inheritance, and so on.

ASP.NET includes:

A page and controls framework The ASP.NET compiler Security infrastructure State-management facilities Application configuration Health monitoring and performance features Debugging support An XML Web services framework Extensible hosting environment and application life cycle management An extensible designer environment

Page and Controls Framework

The ASP.NET page and controls framework is a programming framework that runs on a Web server to dynamically produce and render ASP.NET Web pages. ASP.NET Web pages can be requested from any browser or client device, and ASP.NET renders markup (such as HTML) to the requesting browser. As a rule, you can use the same page for multiple browsers, because ASP.NET renders the appropriate markup for the browser making the request. However, you can design your ASP.NET Web page to target a specific browser, such as Microsoft Internet Explorer 6, and take advantage of the features of that browser. ASP.NET supports mobile controls for Web-enabled devices such as cellular phones, handheld computers, and personal digital assistants (PDAs).

ASP.NET Web pages are completely object-oriented. Within ASP.NET Web pages you can work with HTML elements using properties, methods, and events. The ASP.NET page framework removes the implementation details of the separation of client and server inherent in Web-based applications by presenting a unified model for responding to client events in code that runs at the server. The framework also automatically maintains the state of a page and the controls on that page during the page processing life cycle.

The ASP.NET page and controls framework also enables you to encapsulate common UI functionality in easy-to-use, reusable controls. Controls are written once, can be used in many pages, and are integrated into the ASP.NET Web page that they are placed in during rendering.

Page 2: ASPNET

The ASP.NET page and controls framework also provides features to control the overall look and feel of your Web site via themes and skins. You can define themes and skins and then apply them at a page level or at a control level.

In addition to themes, you can define master pages that you use to create a consistent layout for the pages in your application. A single master page defines the layout and standard behavior that you want for all the pages (or a group of pages) in your application. You can then create individual content pages that contain the page-specific content you want to display. When users request the content pages, they merge with the master page to produce output that combines the layout of the master page with the content from the content page.

ASP.NET Compiler

All ASP.NET code is compiled, which enables strong typing, performance optimizations, and early binding, among other benefits. Once the code has been compiled, the common language runtime further compiles ASP.NET code to native code, providing improved performance.

ASP.NET includes a compiler that will compile all your application components including pages and controls into an assembly that the ASP.NET hosting environment can then use to service user requests.

Security Infrastructure

In addition to the security features of .NET, ASP.NET provides an advanced security infrastructure for authenticating and authorizing user access as well as performing other security-related tasks. You can authenticate users using Windows authentication supplied by IIS, or you can manage authentication using your own user database using ASP.NET forms authentication and ASP.NET membership. Additionally, you can manage the authorization to the capabilities and information of your Web application using Windows groups or your own custom role database using ASP.NET roles. You can easily remove, add to, or replace these schemes depending upon the needs of your application.

ASP.NET always runs with a particular Windows identity so you can secure your application using Windows capabilities such as NTFS Access Control Lists (ACLs), database permissions, and so on.

State-Management Facilities

ASP.NET provides intrinsic state management functionality that enables you to store information between page requests, such as customer information or the contents of a shopping cart. You can save and manage application-specific, session-specific, page-specific, user-specific, and developer-defined information. This information can be independent of any controls on the page.

Page 3: ASPNET

ASP.NET offers distributed state facilities, which enable you to manage state information across multiple instances of the same application on one computer or on several computers.

ASP.NET Configuration

ASP.NET applications use a configuration system that enables you to define configuration settings for your Web server, for a Web site, or for individual applications. You can make configuration settings at the time your ASP.NET applications are deployed and can add or revise configuration settings at any time with minimal impact on operational Web applications and servers. ASP.NET configuration settings are stored in XML-based files. Because these XML files are ASCII text files, it is simple to make configuration changes to your Web applications. You can extend the configuration scheme to suit your requirements.

Health Monitoring and Performance Features

ASP.NET includes features that enable you to monitor health and performance of your ASP.NET application. ASP.NET health monitoring enables reporting of key events that provide information about the health of an application and about error conditions. These events show a combination of diagnostics and monitoring characteristics and offer a high degree of flexibility in terms of what is logged and how it is logged.

ASP.NET supports two groups of performance counters accessible to your applications:

The ASP.NET system performance counter group The ASP.NET application performance counter group

Debugging Support

ASP.NET takes advantage of the run-time debugging infrastructure to provide cross-language and cross-computer debugging support. You can debug both managed and unmanaged objects, as well as all languages supported by the common language runtime and script languages. For details, see ASP.NET Debugging.

In addition, the ASP.NET page framework provides a trace mode that enables you to insert instrumentation messages into your ASP.NET Web pages

XML Web Services Framework

ASP.NET supports XML Web services. An XML Web service is a component containing business functionality that enables applications to exchange information across firewalls using standards like HTTP and XML messaging. XML Web services are not tied to a particular component technology or object-calling convention. As a result, programs written in any

Page 4: ASPNET

language, using any component model, and running on any operating system can access XML Web services.

Extensible Hosting Environment and Application Life-Cycle Management

ASP.NET includes an extensible hosting environment that controls the life cycle of an application from when a user first accesses a resource (such as a page) in the application to the point at which the application is shut down. While ASP.NET relies on a Web server (IIS) as an application host, ASP.NET provides much of the hosting functionality itself. The architecture of ASP.NET enables you to respond to application events and create custom HTTP handlers and HTTP modules.

Extensible Designer Environment

ASP.NET includes enhanced support for creating designers for Web server controls for use with a visual design tool such as Visual Studio. Designers enable you to build a design-time user interface for a control, so that developers can configure your control's properties and content in the visual design tool.

ASP.NET Web Pages OverviewYou use ASP.NET Web pages as the programmable user interface for your Web application. An ASP.NET Web page presents information to the user in any browser or client device and implements application logic using server-side code. ASP.NET Web pages are:

Based on Microsoft ASP.NET technology, in which code that runs on the server dynamically generates Web page output to the browser or client device.

Compatible with any browser or mobile device. An ASP.NET Web page automatically renders the correct browser-compliant HTML for features such as styles, layout, and so on. Alternatively, you can design your ASP.NET Web pages to run on a specific browser such as Microsoft Internet Explorer 6 and take advantage of browser-specific features.

Compatible with any language supported by the .NET common language runtime, including Microsoft Visual Basic, Microsoft Visual C#, Microsoft J#, and Microsoft JScript .NET.

Built on the Microsoft .NET Framework. This provides all the benefits of the framework, including a managed environment, type safety, and inheritance.

Flexible because you can add user-created and third party controls to them.

Components of ASP.NET Web Pages

In ASP.NET Web pages, user interface programming is divided into two pieces: the visual component and the logic. If you have worked with tools like Visual Basic and Visual C++ in the

Page 5: ASPNET

past, you will recognize this division between the visible portion of a page and the code behind the page that interacts with it.

The visual element consists of a file containing static markup such as HTML or ASP.NET server controls or both. The ASP.NET Web page works as a container for the static text and controls you want to display.

The logic for the ASP.NET Web page consists of code that you create to interact with the page. The code can reside either in a script block in the page or in a separate class. If the code is in a separate class file, this file is referred to as the code-behind file. The code in the code-behind file can be written in Visual Basic, Visual C#, Visual J#, or JScript .NET.

ASP.NET Web pages are compiled into a dynamic-link library (.dll) file. The first time a user browses to the .aspx page, ASP.NET automatically generates a .NET class file that represents the page and then compiles it. The .dll file runs on the server and dynamically produces the HTML output for your page.

What ASP.NET Web Pages Help You Accomplish

Web application programming presents challenges that do not typically arise when programming traditional client-based applications. Among the challenges are:

Implementing a rich Web user interface   It can be difficult and tedious to design and implement a user interface using basic HTML facilities, especially if the page has a complex layout, a large amount of dynamic content, and full-featured user-interactive objects.

Separation of client and server   In a Web application, the client (browser) and server are different programs often running on different computers (and even on different operating systems). Consequently, the two halves of the application share very little information; they can communicate, but typically exchange only small chunks of simple information.

Stateless execution   When a Web server receives a request for a page, it finds the page, processes it, sends it to the browser, and then discards all page information. If the user requests the same page again, the server repeats the entire sequence, reprocessing the page from scratch. Put another way, a server has no memory of pages that it has processed—pages are stateless. Therefore, if an application needs to maintain information about a page, its stateless nature can become a problem.

Unknown client capabilities    In many cases, Web applications are accessible to many users using different browsers. Browsers have different capabilities, making it difficult to create an application that will run equally well on all of them.

Complications with data access   Reading from and writing to a data source in traditional Web applications can be complicated and resource-intensive.

Complications with scalability   In many cases Web applications designed with existing methods fail to meet scalability goals due to the lack of compatibility between the various components of the application. This is often a common failure point for applications under a heavy growth cycle.

Page 6: ASPNET

Meeting these challenges for Web applications can require substantial time and effort. ASP.NET Web pages and the ASP.NET page framework address these challenges in the following ways:

Intuitive, consistent object model   The ASP.NET page framework presents an object model that enables you to think of your forms as a unit, not as separate client and server pieces. In this model, you can program the page in a more intuitive way than in traditional Web applications, including the ability to set properties for page elements and respond to events. In addition, ASP.NET server controls are an abstraction from the physical contents of an HTML page and from the direct interaction between browser and server. In general, you can use server controls the way you might work with controls in a client application and not have to think about how to create the HTML to present and process the controls and their contents.

Event-driven programming model   ASP.NET Web pages bring to Web applications the familiar model of writing event handlers for events that occur on either the client or server. The ASP.NET page framework abstracts this model in such a way that the underlying mechanism of capturing an event on the client, transmitting it to the server, and calling the appropriate method is all automatic and invisible to you. The result is a clear, easily written code structure that supports event-driven development.

Intuitive state management   The ASP.NET page framework automatically handles the task of maintaining the state of your page and its controls, and it provides you with explicit ways to maintain the state of application-specific information. This is accomplished without heavy use of server resources and can be implemented with or without sending cookies to the browser.

Browser-independent applications   The ASP.NET page framework enables you to create all application logic on the server, eliminating the need to explicitly code for differences in browsers. However, it still enables you to take advantage of browser-specific features by writing client-side code to provide improved performance and a richer client experience.

.NET Framework common language runtime support   The ASP.NET page framework is built on the .NET Framework, so the entire framework is available to any ASP.NET application. Your applications can be written in any language that is compatible with the runtime. In addition, data access is simplified using the data access infrastructure provided by the .NET Framework, including ADO.NET.

.NET Framework scalable server performance   The ASP.NET page framework enables you to scale your Web application from one computer with a single processor to a multi-computer Web farm cleanly and without complicated changes to the application's logic.

ASP.NET Application Life Cycle Overview for IIS 5.0 and 6.0This topic outlines the life cycle of ASP.NET applications, listing important life-cycle events and describing how code that you write can fit into the application life cycle. The information in this topic applies to IIS 5.0 and IIS 6.0.

Page 7: ASPNET

Within ASP.NET, several processing steps must occur for an ASP.NET application to be initialized and process requests. Additionally, ASP.NET is only one piece of the Web server architecture that services requests made by browsers. It is important for you to understand the application life cycle so that you can write code at the appropriate life cycle stage for the effect you intend.

Application Life Cycle in General

The following table describes the stages of the ASP.NET application life cycle.

Stage Description

User requests an application resource from the Web server.

The life cycle of an ASP.NET application starts with a request sent by a browser to the Web server (for ASP.NET applications, typically IIS). ASP.NET is an ISAPI extension under the Web server. When a Web server receives a request, it examines the file-name extension of the requested file, determines which ISAPI extension should handle the request, and then passes the request to the appropriate ISAPI extension. ASP.NET handles file name extensions that have been mapped to it, such as .aspx, .ascx, .ashx, and .asmx.

Note:

If a file name extension has not been mapped to ASP.NET, ASP.NET will not receive the request. This is important to understand for applications that use ASP.NET authentication. For example, because .htm files are typically not mapped to ASP.NET, ASP.NET will not perform authentication or authorization checks on requests for .htm files. Therefore, even if a file contains only static content, if you want ASP.NET to check authentication, create the file using a file name extension mapped to ASP.NET, such as .aspx.

Note:

If you create a custom handler to service a particular file name extension, you must map the extension to ASP.NET in IIS and also register the handler in your application's Web.config file. For more information, see HTTP Handlers and HTTP Modules Overview.

ASP.NET receives the first request for the application.

When ASP.NET receives the first request for any resource in an application, a class named ApplicationManager creates an application domain. Application domains provide isolation between applications for global variables and allow each application to be unloaded separately. Within an application domain, an instance of the class named HostingEnvironment is created, which provides access to information about the application such as the name of the folder where the application is stored.

Page 8: ASPNET

The following diagram illustrates this relationship:

ASP.NET also compiles the top-level items in the application if required, including application code in the App_Code folder. For more information, see "Compilation Life Cycle" later in this topic.

ASP.NET core objects are created for each request.

After the application domain has been created and the HostingEnvironment object instantiated, ASP.NET creates and initializes core objects such as HttpContext, HttpRequest, and HttpResponse. The HttpContext class contains objects that are specific to the current application request, such as the HttpRequest and HttpResponse objects. The HttpRequest object contains information about the current request, including cookies and browser information. The HttpResponse object contains the response that is sent to the client, including all rendered output and cookies.

An HttpApplication object is assigned to the request

After all core application objects have been initialized, the application is started by creating an instance of the HttpApplication class. If the application has a Global.asax file, ASP.NET instead creates an instance of the Global.asax class that is derived from the HttpApplication class and uses the derived class to represent the application.

Note:

The first time an ASP.NET page or process is requested in an application, a new instance of HttpApplication is created. However, to maximize performance,

Page 9: ASPNET

HttpApplication instances might be reused for multiple requests.

When an instance of HttpApplication is created, any configured modules are also created. For instance, if the application is configured to do so, ASP.NET creates a SessionStateModule module. After all configured modules are created, the HttpApplication class's Init method is called.

The following diagram illustrates this relationship:

The request is processed by the HttpApplication pipeline.

The following events are executed by the HttpApplication class while the request is processed. The events are of particular interest to developers who want to extend the HttpApplication class.

1. Validate the request, which examines the information sent by the browser and determines whether it contains potentially malicious markup. For more information, see ValidateRequest and Script Exploits Overview.

2. Perform URL mapping, if any URLs have been configured in the

Page 10: ASPNET

UrlMappingsSection section of the Web.config file.3. Raise the BeginRequest event.4. Raise the AuthenticateRequest event.5. Raise the PostAuthenticateRequest event.6. Raise the AuthorizeRequest event.7. Raise the PostAuthorizeRequest event.8. Raise the ResolveRequestCache event.9. Raise the PostResolveRequestCache event.10. Based on the file name extension of the requested resource (mapped in

the application's configuration file), select a class that implements IHttpHandler to process the request. If the request is for an object (page) derived from the Page class and the page needs to be compiled, ASP.NET compiles the page before creating an instance of it.

11. Raise the PostMapRequestHandler event.12. Raise the AcquireRequestState event.13. Raise the PostAcquireRequestState event.14. Raise the PreRequestHandlerExecute event.15. Call the ProcessRequest method (or the asynchronous version

IHttpAsyncHandler.BeginProcessRequest) of the appropriate IHttpHandler class for the request. For example, if the request is for a page, the current page instance handles the request.

16. Raise the PostRequestHandlerExecute event.17. Raise the ReleaseRequestState event.18. Raise the PostReleaseRequestState event.19. Perform response filtering if the Filter property is defined.20. Raise the UpdateRequestCache event.21. Raise the PostUpdateRequestCache event.22. Raise the EndRequest event.23. Raise the PreSendRequestHeaders event.24. Raise the PreSendRequestContent event.

Life Cycle Events and the Global.asax file

During the application life cycle, the application raises events that you can handle and calls particular methods that you can override. To handle application events or methods, you can create a file named Global.asax in the root directory of your application.

If you create a Global.asax file, ASP.NET compiles it into a class derived from the HttpApplication class, and then uses the derived class to represent the application.

An instance of HttpApplication processes only one request at a time. This simplifies application event handling because you do not need to lock non-static members in the application class when you access them. This also allows you to store request-specific data in non-static members of the

Page 11: ASPNET

application class. For example, you can define a property in the Global.asax file and assign it a request-specific value.

ASP.NET automatically binds application events to handlers in the Global.asax file using the naming convention Application_event, such as Application_BeginRequest. This is similar to the way that ASP.NET page methods are automatically bound to events, such as the page's Page_Load event. For details, see ASP.NET Page Life Cycle Overview.

The Application_Start and Application_End methods are special methods that do not represent HttpApplication events. ASP.NET calls them once for the lifetime of the application domain, not for each HttpApplication instance.

The following table lists some of the events and methods that are used during the application life cycle. There are many more events than those listed, but they are not commonly used.

Event or method Description

Application_Start

Called when the first resource (such as a page) in an ASP.NET application is requested. The Application_Start method is called only one time during the life cycle of an application. You can use this method to perform startup tasks such as loading data into the cache and initializing static values.

You should set only static data during application start. Do not set any instance data because it will be available only to the first instance of the HttpApplication class that is created.

Application_ event

Raised at the appropriate time in the application life cycle, as listed in the application life cycle table earlier in this topic.

Application_Error can be raised at any phase in the application life cycle.

Application_EndRequest is the only event that is guaranteed to be raised in every request, because a request can be short-circuited. For example, if two modules handle the Application_BeginRequest event and the first one throws an exception, the Application_BeginRequest event will not be called for the second module. However, the Application_EndRequest method is always called to allow the application to clean up resources.

Init Called once for every instance of the HttpApplication class after all modules have been created.

Dispose Called before the application instance is destroyed. You can use this method to manually release any unmanaged resources. For more information, see Cleaning Up Unmanaged Resources.

Application_End Called once per lifetime of the application before the application is unloaded. Compilation Life Cycle

Page 12: ASPNET

When the first request is made to an application, ASP.NET compiles application items in a specific order. The first items to be compiled are referred to as the top-level items. After the first request, the top-level items are recompiled only if a dependency changes. The following table describes the order in which ASP.NET top-level items are compiled.

Item Description

App_GlobalResourcesThe application's global resources are compiled and a resource assembly is built. Any assemblies in the application's Bin folder are linked to the resource assembly.

App_WebResourcesProxy types for Web services are created and compiled. The resulting Web references assembly is linked to the resource assembly if it exists.

Profile properties defined in the Web.config file

If profile properties are defined in the application's Web.config file, an assembly is generated that contains a profile object.

App_CodeSource code files are built and one or more assemblies are created. All code assemblies and the profile assembly are linked to the resources and Web references assemblies if any.

Global.asax The application object is compiled and linked to all of the previously generated assemblies.

After the application's top level items have been compiled, ASP.NET compiles folders, pages, and other items as needed. The following table describes the order in which ASP.NET folders and items are compiled.

Item Description

App_LocalResources

If the folder containing the requested item contains an App_LocalResources folder, the contents of the local resources folder are compiled and linked to the global resources assembly.

Individual Web pages (.aspx files), user controls (.ascx files), HTTP handlers (.ashx files), and HTTP modules (.asmx files)

Compiled as needed and linked to the local resources assembly and the top-level assemblies.

Themes, master pages, other source filesSkin files for individual themes, master pages, and other source code files referenced by pages are compiled when the referencing page is compiled.

Compiled assemblies are cached on the server and reused on subsequent requests and are preserved across application restarts as long as the source code is unchanged.

Because the application is compiled on the first request, the initial request to an application can take significantly longer than subsequent requests. You can precompile your application to reduce the time required for the first request.

Page 13: ASPNET

Application Restarts

Modifying the source code of your Web application will cause ASP.NET to recompile source files into assemblies. When you modify the top-level items in your application, all other assemblies in the application that reference the top-level assemblies are recompiled as well.

In addition, modifying, adding, or deleting certain types of files within the application's known folders will cause the application to restart. The following actions will cause an application restart:

Adding, modifying, or deleting assemblies from the application's Bin folder. Adding, modifying, or deleting localization resources from the App_GlobalResources or

App_LocalResources folders. Adding, modifying, or deleting the application's Global.asax file. Adding, modifying, or deleting source code files in the App_Code directory. Adding, modifying, or deleting Profile configuration. Adding, modifying, or deleting Web service references in the App_WebReferences

directory. Adding, modifying, or deleting the application's Web.config file.

When an application restart is required, ASP.NET will serve all pending requests from the existing application domain and the old assemblies before restarting the application domain and loading the new assemblies.

HTTP Modules

The ASP.NET application life cycle is extensible through IHttpModule classes. ASP.NET includes several classes that implement IHttpModule, such as the SessionStateModule class. You can also create your own classes that implement IHttpModule.

If you add modules to your application, the modules themselves can raise events. The application can subscribe to in these events in the Global.asax file by using the convention modulename_eventname. For example, to handle the Authenticate event raised by a FormsAuthenticationModule object, you can create a handler named FormsAuthentication_Authenticate.

The SessionStateModule class is enabled by default in ASP.NET. All session events are automatically wired up as Session_event, such as Session_Start. The Start event is raised each time a new session is created.

Page 14: ASPNET

ASP.NET Page Life Cycle OverviewWhen an ASP.NET page runs, the page goes through a life cycle in which it performs a series of processing steps. These include initialization, instantiating controls, restoring and maintaining state, running event handler code, and rendering. It is important for you to understand the page life cycle so that you can write code at the appropriate life-cycle stage for the effect you intend.

If you develop custom controls, you must be familiar with the page life cycle in order to correctly initialize controls, populate control properties with view-state data, and run control behavior code. The life cycle of a control is based on the page life cycle, and the page raises many of the events that you need to handle in a custom control.

This topic contains the following sections:

General Page Life-cycle Stages Life-cycle Events Additional Page Life Cycle Considerations Catch-Up Events for Added Controls Data Binding Events for Data-Bound Controls Login Control Events

General Page Life-Cycle Stages

In general terms, the page goes through the stages outlined in the following table. In addition to the page life-cycle stages, there are application stages that occur before and after a request but are not specific to a page.

Some parts of the life cycle occur only when a page is processed as a postback. For postbacks, the page life cycle is the same during a partial-page postback (as when you use an UpdatePanel control) as it is during a full-page postback.

Stage Description

Page request

The page request occurs before the page life cycle begins. When the page is requested by a user, ASP.NET determines whether the page needs to be parsed and compiled (therefore beginning the life of a page), or whether a cached version of the page can be sent in response without running the page.

StartIn the start stage, page properties such as Request and Response are set. At this stage, the page also determines whether the request is a postback or a new request and sets the IsPostBack property. The page also sets the UICulture property.

Initialization During page initialization, controls on the page are available and each control's UniqueID property is set. A master page and themes are also applied to the page if applicable. If the current request is a postback, the postback data has not yet been loaded and control property values have not been restored to the values from

Page 15: ASPNET

view state.

Load During load, if the current request is a postback, control properties are loaded with information recovered from view state and control state.

Postback event handling

If the request is a postback, control event handlers are called. After that, the Validate method of all validator controls is called, which sets the IsValid property of individual validator controls and of the page.

Rendering

Before rendering, view state is saved for the page and all controls. During the rendering stage, the page calls the Render method for each control, providing a text writer that writes its output to the OutputStream object of the page's Response property.

UnloadThe Unload event is raised after the page has been fully rendered, sent to the client, and is ready to be discarded. At this point, page properties such as Response and Request are unloaded and cleanup is performed.

Life-Cycle Events

Within each stage of the life cycle of a page, the page raises events that you can handle to run your own code. For control events, you bind the event handler to the event, either declaratively using attributes such as onclick, or in code.

Pages also support automatic event wire-up, meaning that ASP.NET looks for methods with particular names and automatically runs those methods when certain events are raised. If the AutoEventWireup attribute of the @   Page directive is set to true, page events are automatically bound to methods that use the naming convention of Page_event, such as Page_Load and Page_Init.

The following table lists the page life-cycle events that you will use most frequently. There are more events than those listed; however, they are not used for most page-processing scenarios. Instead, they are primarily used by server controls on the ASP.NET Web page to initialize and render themselves. If you want to write custom ASP.NET server controls, you need to understand more about these events.

Page Event Typical Use PreInit Raised after the start stage is complete and before the initialization stage

begins.

Use this event for the following:

Check the IsPostBack property to determine whether this is the first time the page is being processed. The IsCallback and IsCrossPagePostBack properties have also been set at this time.

Create or re-create dynamic controls. Set a master page dynamically. Set the Theme property dynamically.

Page 16: ASPNET

Read or set profile property values.

Note:

If the request is a postback, the values of the controls have not yet been restored from view state. If you set a control property at this stage, its value might be overwritten in the next event.

Init

Raised after all controls have been initialized and any skin settings have been applied. The Init event of individual controls occurs before the Init event of the page.

Use this event to read or initialize control properties.

InitComplete

Raised at the end of the page's initialization stage. Only one operation takes place between the Init and InitComplete events: tracking of view state changes is turned on. View state tracking enables controls to persist any values that are programmatically added to the ViewState collection. Until view state tracking is turned on, any values added to view state are lost across postbacks. Controls typically turn on view state tracking immediately after they raise their Init event.

Use this event to make changes to view state that you want to make sure are persisted after the next postback.

PreLoad Raised after the page loads view state for itself and all controls, and after it processes postback data that is included with the Request instance.

Load

The Page object calls the OnLoad method on the Page object, and then recursively does the same for each child control until the page and all controls are loaded. The Load event of individual controls occurs after the Load event of the page.

Use the OnLoad event method to set properties in controls and to establish database connections.

Control events

Use these events to handle specific control events, such as a Button control's Click event or a TextBox control's TextChanged event.

Note:

In a postback request, if the page contains validator controls, check the IsValid property of the Page and of individual validation controls before performing any processing.

LoadComplete

Raised at the end of the event-handling stage.

Use this event for tasks that require that all other controls on the page be loaded.

PreRender Raised after the Page object has created all controls that are required in order

Page 17: ASPNET

to render the page, including child controls of composite controls. (To do this, the Page object calls EnsureChildControls for each control and for the page.)

The Page object raises the PreRender event on the Page object, and then recursively does the same for each child control. The PreRender event of individual controls occurs after the PreRender event of the page.

Use the event to make final changes to the contents of the page or its controls before the rendering stage begins.

PreRenderComplete Raised after each data bound control whose DataSourceID property is set calls its DataBind method. For more information, see Data Binding Events for Data-Bound Controls later in this topic.

SaveStateComplete Raised after view state and control state have been saved for the page and for all controls. Any changes to the page or controls at this point affect rendering, but the changes will not be retrieved on the next postback.

Render

This is not an event; instead, at this stage of processing, the Page object calls this method on each control. All ASP.NET Web server controls have a Render method that writes out the control's markup to send to the browser.

If you create a custom control, you typically override this method to output the control's markup. However, if your custom control incorporates only standard ASP.NET Web server controls and no custom markup, you do not need to override the Render method.

A user control (an .ascx file) automatically incorporates rendering, so you do not need to explicitly render the control in code.

Unload

Raised for each control and then for the page.

In controls, use this event to do final cleanup for specific controls, such as closing control-specific database connections.

For the page itself, use this event to do final cleanup work, such as closing open files and database connections, or finishing up logging or other request-specific tasks.

Note:

During the unload stage, the page and its controls have been rendered, so you cannot make further changes to the response stream. If you attempt to call a method such as the Response.Write method, the page will throw an exception.

Additional Page Life Cycle Considerations

Page 18: ASPNET

Individual ASP.NET server controls have their own life cycle that is similar to the page life cycle. For example, a control's Init and Load events occur during the corresponding page events.

Although both Init and Load recursively occur on each control, they happen in reverse order. The Init event (and also the Unload event) for each child control occur before the corresponding event is raised for its container (bottom-up). However the Load event for a container occurs before the Load events for its child controls (top-down).

When you create a class that inherits from the Page class, in addition to handling events raised by the page, you can override methods from the page's base class. For example, you can override the page's InitializeCulture method to dynamically set culture information. Note that when an event handler is created using the Page_event syntax, the base implementation is implicitly called and therefore you do not need to call it in your method. For example, the base page class's OnLoad method is always called, whether you create a Page_Load method or not. However, if you override the page OnLoad method with the override keyword (Overrides in Visual Basic), you must explicitly call the base method. For example, if you override the OnLoad method on the page, you must call base.Load (MyBase.Load in Visual Basic) in order for the base implementation to be run.

Catch-Up Events for Added Controls

If controls are created dynamically at run time or declaratively within templates of data-bound controls, their events are initially not synchronized with those of other controls on the page. For example, for a control that is added at run time, the Init and Load events might occur much later in the page life cycle than the same events for controls created declaratively. Therefore, from the time that they are instantiated, dynamically added controls and controls in templates raise their events one after the other until they have caught up to the event during which it was added to the Controls collection.

Data Binding Events for Data-Bound Controls

To help you understand the relationship between the page life cycle and data binding events, the following table lists data-related events in data-bound controls such as the GridView, DetailsView, and FormView controls.

Control Event Typical Use DataBinding Raised after the control's PreRender event, which occurs

after the page's PreRender event. (This applies to controls whose DataSourceID property is set declaratively. Otherwise the event happens when you call the control's DataBind method.)

Page 19: ASPNET

This event marks the beginning of the process that binds the control to the data. Use this event to manually open database connections, if required, and to set parameter values dynamically before a query is run.

RowCreated (GridView only) or ItemCreated (DataList, DetailsView, SiteMapPath, DataGrid, FormView, Repeater, and ListView controls)

Raised after the control's DataBinding event.

Use this event to manipulate content that is not dependent on data binding. For example, at run time, you might programmatically add formatting to a header or footer row in a GridView control.

RowDataBound (GridView only) or ItemDataBound (DataList, SiteMapPath, DataGrid, Repeater, and ListView controls)

Raised after the control's RowCreated or ItemCreated event.

When this event occurs, data is available in the row or item, so you can format data or set the FilterExpression property on child data source controls in order to display related data within the row or item.

DataBound

Raised at the end of data-binding operations in a data-bound control. In a GridView control, data binding is complete for all rows and any child controls.

Use this event to format data-bound content or to initiate data binding in other controls that depend on values from the current control's content.

Nested Data-Bound Controls

If a child control has been data bound, but its container control has not yet been data bound, the data in the child control and the data in its container control can be out of sync. This is true particularly if the data in the child control performs processing based on a data-bound value in the container control.

For example, suppose you have a GridView control that displays a company record in each row, and it displays a list of the company officers in a ListBox control. To fill the list of officers, you would bind the ListBox control to a data source control (such as SqlDataSource) that retrieves the company officer data using the company ID in a query.

If the ListBox control's data-binding properties, such as DataSourceID and DataMember, are set declaratively, the ListBox control will try to bind to its data source during the containing row's DataBinding event. However, the CompanyID field of the row does not contain a value until the GridView control's RowDataBound event occurs. In this case, the child control (the ListBox control) is bound before the containing control (the GridView control) is bound, so their data-binding stages are out of sync.

Page 20: ASPNET

To avoid this condition, put the data source control for the ListBox control in the same template item as the ListBox control itself, and do not set the data binding properties of the ListBox declaratively. Instead, set them programmatically at run time during the RowDataBound event, so that the ListBox control does not bind to its data until the CompanyID information is available.

Login Control Events

The Login control can use settings in the Web.config file to manage membership authentication automatically. However, if your application requires you to customize how the control works, or if you want to understand how Login control events relate to the page life cycle, you can use the events listed in the following table.

Control Event Typical Use

LoggingIn

Raised during a postback, after the page's LoadComplete event has occurred. This event marks the beginning of the login process.

Use this event for tasks that must occur prior to beginning the authentication process.

Authenticate

Raised after the LoggingIn event.

Use this event to override or enhance the default authentication behavior of a Login control.

LoggedIn

Raised after the user name and password have been authenticated.

Use this event to redirect to another page or to dynamically set the text in the control. This event does not occur if there is an error or if authentication fails.

LoginError

Raised if authentication was not successful.

Use this event to set text in the control that explains the problem or to direct the user to a different page.

Page and Application Context in ASP.NET Web Applications

Page 21: ASPNET

When a Web application runs, ASP.NET maintains information about the current application, each user session, the current HTTP request, the requested page, and so on. ASP.NET contains a series of classes to encapsulate this context information.

ASP.NET makes instances of these classes available as intrinsic objects that you can access from your code. The following table lists these intrinsic objects and the classes they are instances of.

Object Name Description ASP.NET Class

ResponseProvides access to the output stream for the current page. You can use this class to inject text into the page, to write cookies, and more.

HttpResponse

Request

Provides access to the current page request, including the request headers, cookies, client certificate, query string, and so on. You can use this class to read what the browser has sent.

HttpRequest

ContextProvides access to the entire current context (including the request object). You can use this class to share information between pages.

HttpContext

ServerExposes utility methods that you can use to transfer control between pages, get information about the most recent error, encode and decode HTML text, and more.

HttpServerUtility

ApplicationProvides access to application-wide methods and events for all sessions. Also provides access to an application-wide cache you can use to store information.

HttpApplicationState

Session

Provides information to the current user session. Also provides access to a session-wide cache you can use to store information, along with the means to control how the session is managed.

HttpSessionState

Trace Provides a way to display both system and custom trace diagnostic messages in the HTTP page output. TraceContext

ASP.NET View State OverviewView state is the method that the ASP.NET page framework uses to preserve page and control values between round trips. When the HTML markup for the page is rendered, the current state of the page and values that must be retained during postback are serialized into base64-encoded strings. This information is then put into the view state hidden field or fields.

This topic contains the following sections:

Scenarios

Page 22: ASPNET

Features Background Class Reference

Scenarios

View state is used automatically by the ASP.NET page framework to persist information that must be preserved between postbacks. This information includes any non-default values of controls.

You can also use view state to store application data that is specific to a page.

Features

View state is a repository in an ASP.NET page that can store values that have to be retained during postback. The page framework uses view state to persist control settings between postbacks.

You can use view state in your own applications to do the following:

Keep values between postbacks without storing them in session state or in a user profile. Store the values of page or control properties that you define. Create a custom view state provider that lets you store view state information in a SQL

Server database or in another data store.

For example, you can store information in view state that your code can access during the page load event the next time that the page is sent to the server.

Background

A Web application is stateless. A new instance of the Web page class is created every time that the page is requested from the server. This would ordinarily mean that all information in the page and in its controls would be lost with each round trip. For example, by default if a user enters information into a text box on an HTML Web page, that information is sent to the server. However, it is not returned to the browser in the response.

To overcome this intrinsic limitation of Web programming, the ASP.NET page framework includes several state-management features to preserve page and control values between round trips to the Web server. One of these features is view state

Page 23: ASPNET

By default, the ASP.NET page framework uses view state to preserve page and control values between round trips. When the HTML for the page is rendered, the current state of the page and values that must be retained during postback are serialized into base64-encoded strings. They are then put into a hidden field or fields in the page.

You can access view state in your code by using the page's ViewState property. The ViewState property is a dictionary that contains key/value pairs that contain the view state data.

Security Note:

It is easy for a malicious user to see and modify the contents of a hidden field.

You can change the default behavior and store view state in another location such as a SQL Server database by implementing a custom PageStatePersister class to store page data.

Considerations for Using View State

View state provides state information for a specific ASP.NET page. If you need to use information on more than one page, or if you need the information to persist across visits to the Web site, you must use another method for maintaining state. You can use application state, session state, or profile properties.

View state information is serialized into XML and then encoded by using base-64 encoding, which can generate large amounts of data. When the page is posted to the server, the contents of view state are sent as part of the page postback information. If view state contains a large amount of information, it can affect performance of the page. Test the performance of your pages by using typical data for your application to determine whether the size of view state is causing performance problems.

If you do not have to store control information for individual controls, you can disable view state for a control. If a control on a page is refreshed from the data store on each postback, you can turn view state off for that control in order to reduce the size of view state. For example, you might turn view state off for a control such as the GridView control.

Note:

Even when you explicitly turn view state off, a hidden field is still sent to the browser to indicate that postback is occurring for the page.

Another consideration is that if the amount of data in a hidden field becomes large, some proxies and firewalls will prevent access to the page that contains them. Because the maximum allowed amount can vary with different firewall and proxy implementations, large hidden fields can cause intermittent problems. If the amount of data that is stored in the ViewState property exceeds the value specified in the page's MaxPageStateFieldLength property, the page splits view state into multiple hidden fields. This reduces the size of individual hidden fields below the size that firewalls reject.

Page 24: ASPNET

Some mobile devices do not allow hidden fields at all. Therefore, view state will not work for those devices. For more information and alternatives, see ASP.NET Mobile Web Development Overview.

Control State

In addition to view state, ASP.NET supports control state. The page uses control state to persist control information that must be retained between postbacks, even if view state is disabled for the page or for a control. Like view state, control state is stored in one or more hidden fields.

Saving Values in View State

You can access view state information by using the page's ViewState property, which exposes a dictionary object. You can use this dictionary to store custom values. A typical use is to store the value of custom properties that you define in the page.

Because view state is sent as a hidden field, you can make changes to view state until the page's PreRenderComplete event. After the page is rendered to the browser, changes to view state will not be saved.

The information in the hidden view state field can be seen by users if they view the source of the Web page and can decode base-64 encoded strings. This creates a potential security issue.

Note:

To use the ViewState property, the ASP.NET Web page must have a form element that has the attribute runat="server".

To save a value to view state, create a new item that contains the value to save and add the item to the view state dictionary. The following example shows an ASP.NET Web page with code that saves a string and an integer value in view state.

<%@ Page Language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><script runat="server"> ' Sample ArrayList for the page. Dim PageArrayList As ArrayList

Function CreateArray() As ArrayList ' Create a sample ArrayList. Dim result As ArrayList result = New ArrayList(4) result.Add("item 1") result.Add("item 2") result.Add("item 3") result.Add("item 4") Return result

Page 25: ASPNET

End Function

Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) If (Me.ViewState("arrayListInViewState") IsNot Nothing) Then PageArrayList = CType(Me.ViewState("arrayListInViewState"), ArrayList) Else ' ArrayList isn't in view state, so it must be created and populated. PageArrayList = CreateArray() End If ' Code that uses PageArrayList. End Sub

Sub Page_PreRender(ByVal sender As Object, ByVal e As EventArgs) ' Save PageArrayList before the page is rendered. Me.ViewState.Add("arrayListInViewState", PageArrayList) End Sub</script>

<html xmlns="http://www.w3.org/1999/xhtml" ><head runat="server"> <title>View state sample</title></head><body> <form id="form1" runat="server"> <div> </div> </form></body></html>

Data Types You Can Store in View State

You can store objects of the following types in view state:

Strings Integers Boolean values Array objects ArrayList objects Hash tables Custom type converters

You can store other types of data also, but the class must be compiled with the Serializable attribute so that its values can be serialized for view state.

Reading Values from View State

To read a value from view state, you get the ViewState property of page and then read the value from the view state dictionary.

The following example shows how you can get an ArrayList object named arrayListInViewState from view state and then bind a GridView control to the object as a data source.

Page 26: ASPNET

Dim arrayList As ArrayList

arrayList = CType(ViewState("arrayListInViewState"), ArrayList)

Me.GridView1.DataSource = arrayListMe.GridView1.DataBind()

Values in view state are typed as String. In Visual Basic, if you set Option Strict On, you must cast view state values to the appropriate type before you use them, as shown in the previous example. In C#, you must always cast to the appropriate type when you read view state values.

If you try to get a value out of view state that does not exist, no exception is thrown. To make sure that a value is in view state, check first whether the object exists. The following example shows how to check for a view state entry.

If ViewState("color") Is Nothing Then

' No such value in view state, take appropriate action.End If

If you try to use a nonexistent view state entry in some other way (for example, to examine its type), a NullReferenceException exception is thrown.

By creating a hash value, the ASP.NET page framework can test whether the view state data has been corrupted or tampered with. However, even if it is not tampered with, view state data can still be intercepted and read by malicious users.

ASP.NET State Management OverviewA new instance of the Web page class is created each time the page is posted to the server. In traditional Web programming, this would typically mean that all information associated with the page and the controls on the page would be lost with each round trip. For example, if a user enters information into a text box, that information would be lost in the round trip from the browser or client device to the server.

To overcome this inherent limitation of traditional Web programming, ASP.NET includes several options that help you preserve data on both a per-page basis and an application-wide basis. These features are as follows:

View state Control state Hidden fields Cookies Query strings Application state Session state Profile Properties

Page 27: ASPNET

View state, control state, hidden fields, cookies, and query strings all involve storing data on the client in various ways. However, application state, session state, and profile properties all store data in memory on the server. Each option has distinct advantages and disadvantages, depending on the scenario.

Client-Based State Management Options

The following sections describe options for state management that involve storing information either in the page or on the client computer. For these options, no information is maintained on the server between round trips.

View State

The ViewState property provides a dictionary object for retaining values between multiple requests for the same page. This is the default method that the page uses to preserve page and control property values between round trips.

When the page is processed, the current state of the page and controls is hashed into a string and saved in the page as a hidden field, or multiple hidden fields if the amount of data stored in the ViewState property exceeds the specified value in the MaxPageStateFieldLength property. When the page is posted back to the server, the page parses the view-state string at page initialization and restores property information in the page.

You can store values in view state as well. The following example shows how to store a value in the view state.

[Visual Basic]

ViewState("color") = "red"

[C#]

ViewState["color"] = "red";

Control State

Sometimes you need to store control-state data in order for a control to work properly. For example, if you have written a custom control that has different tabs that show different information, in order for that control to work as expected, the control needs to know which tab is selected between round trips. The ViewState property can be used for this purpose, but view

Page 28: ASPNET

state can be turned off at a page level by developers, effectively breaking your control. To solve this, the ASP.NET page framework exposes a feature in ASP.NET called control state.

The ControlState property allows you to persist property information that is specific to a control and cannot be turned off like the ViewState property.

The following example shows a custom control that stores a value in control state.

Class Sample

Inherits Control

Dim currentIndex As Integer

Protected Overrides Sub OnInit(ByVal e As EventArgs) Page.RegisterRequiresControlState(Me) currentIndex = 0 MyBase.OnInit(e) End Sub

Protected Overrides Function SaveControlState() As Object If currentIndex <> 0 Then Return CType(currentIndex, Object) Else Return Nothing End If End Function

Protected Overrides Sub LoadControlState(ByVal state As Object) If (state <> Nothing) Then currentIndex = CType(state, Integer) End If End Sub

End Class

Hidden Fields

ASP.NET allows you to store information in a HiddenField control, which renders as a standard HTML hidden field. A hidden field does not render visibly in the browser, but you can set its properties just as you can with a standard control. When a page is submitted to the server, the content of a hidden field is sent in the HTTP form collection along with the values of other controls. A hidden field acts as a repository for any page-specific information that you want to store directly in the page.

Security Note:

It is easy for a malicious user to see and modify the contents of a hidden field. Do not store any information in a hidden field that is sensitive or that your application relies on to work properly..

Page 29: ASPNET

A HiddenField control stores a single variable in its Value property and must be explicitly added to the page. The following example shows a HiddenField control with an initial value.

<asp:hiddenfield id="ExampleHiddenField" value="Example Value" runat="server"/>

In order for hidden-field values to be available during page processing, you must submit the page using an HTTP POST command. If you use hidden fields and a page is processed in response to a link or an HTTP GET command, the hidden fields will not be available.

Cookies

A cookie is a small amount of data that is stored either in a text file on the client file system or in-memory in the client browser session. It contains site-specific information that the server sends to the client along with page output. Cookies can be temporary (with specific expiration times and dates) or persistent.

You can use cookies to store information about a particular client, session, or application. The cookies are saved on the client device, and when the browser requests a page, the client sends the information in the cookie along with the request information. The server can read the cookie and extract its value. A typical use is to store a token (perhaps encrypted) indicating that the user has already been authenticated in your application.

Security Note:

The browser can only send the data back to the server that originally created the cookie. However, malicious users have ways to access cookies and read their contents. It is recommended that you do not store sensitive information, such as a user name or password, in a cookie. Instead, store a token in the cookie that identifies the user, and then use the token to look up the sensitive information on the server.

The following example shows how to write a cookie.

Response.Cookies("destination").Value = "CA"

Response.Cookies("destination").Expires = DateTime.Now.AddDays(1)

Query Strings

A query string is information that is appended to the end of a page URL. A typical query string might look like the following example:

http://www.contoso.com/listwidgets.aspx?category=basic&price=100

Page 30: ASPNET

In the URL path above, the query string starts with a question mark (?) and includes two attribute/value pairs, one called "category" and the other called "price."

Query strings provide a simple but limited way to maintain state information. For example, they are an easy way to pass information from one page to another, such as passing a product number from one page to another page where it will be processed. However, some browsers and client devices impose a 2083-character limit on the length of the URL.

Security Note:

Information that is passed in a query string can be tampered with by a malicious user. Do not rely on query strings to convey important or sensitive data. Additionally, a user can bookmark the URL or send the URL to other users, thereby passing that information along with it.

In order for query string values to be available during page processing, you must submit the page using an HTTP GET command. That is, you cannot take advantage of a query string if a page is processed in response to an HTTP POST command.

Server-Based State Management Options

ASP.NET offers you a variety of ways to maintain state information on the server, rather than persisting information on the client. With server-based state management, you can decrease the amount of information sent to the client in order to preserve state, however it can use costly resources on the server. The following sections describe three server-based state management features: application state, session state, and profile properties.

Application State

ASP.NET allows you to save values using application state — which is an instance of the HttpApplicationState class — for each active Web application. Application state is a global storage mechanism that is accessible from all pages in the Web application. Thus, application state is useful for storing information that needs to be maintained between server round trips and between requests for pages.

Application state is stored in a key/value dictionary that is created during each request to a specific URL. You can add your application-specific information to this structure to store it between page requests.

Once you add your application-specific information to application state, the server manages it.

The following example shows how to assign a value in application state.

[Visual Basic]

Page 31: ASPNET

Application("WelcomeMessage") = "Welcome to the Contoso site."

[C#]

Application["WelcomeMessage"] = "Welcome to the Contoso site.";

Session State

ASP.NET allows you to save values by using session state — which is an instance of the HttpSessionState class — for each active Web-application session.

Session state is similar to application state, except that it is scoped to the current browser session. If different users are using your application, each user session will have a different session state. In addition, if a user leaves your application and then returns later, the second user session will have a different session state from the first.

Session state is structured as a key/value dictionary for storing session-specific information that needs to be maintained between server round trips and between requests for pages.

You can use session state to accomplish the following tasks:

Uniquely identify browser or client-device requests and map them to an individual session instance on the server.

Store session-specific data on the server for use across multiple browser or client-device requests within the same session.

Raise appropriate session management events. In addition, you can write application code leveraging these events.

Once you add your application-specific information to session state, the server manages this object. Depending on which options you specify, session information can be stored in cookies, on an out-of-process server, or on a computer running Microsoft SQL Server.

The following example shows how to save a value in session state.

Session("FirstName") = FirstNameTextBox.Text

Session("LastName") = LastNameTextBox.Text

Profile Properties

ASP.NET provides a feature called profile properties, which allows you to store user-specific data. This feature is similar to session state, except that the profile data is not lost when a user's session expires. The profile-properties feature uses an ASP.NET profile, which is stored in a persistent format and associated with an individual user. The ASP.NET profile allows you to

Page 32: ASPNET

easily manage user information without requiring you to create and maintain your own database. In addition, the profile makes the user information available using a strongly typed API that you can access from anywhere in your application. You can store objects of any type in the profile. The ASP.NET profile feature provides a generic storage system that allows you to define and maintain almost any kind of data while still making the data available in a type-safe manner.

To use profile properties, you must configure a profile provider. ASP.NET includes a SqlProfileProvider class that allows you to store profile data in a SQL database, but you can also create your own profile provider class that stores profile data in a custom format and to a custom storage mechanism such as an XML file, or even to a web service.

Because data that is placed in profile properties is not stored in application memory, it is preserved through Internet Information Services (IIS) restarts and worker-process restarts without losing data. Additionally, profile properties can be persisted across multiple processes such as in a Web farm or a Web garden.

The following example shows how to save a profile value.

Profile.PostalCode = txtPostalCode.Text

You must define the PostalCode property in the Web.config file by using the following markup:

<profile> <properties> <add name="PostalCode" /> </properties></profile>

ASP.NET Cookies OverviewA cookie is a small bit of text that accompanies requests and pages as they go between the Web server and browser. The cookie contains information the Web application can read whenever the user visits the site.

This topic contains:

Scenarios Background Code Examples Class Reference Additional Resources What's New

Page 33: ASPNET

Scenarios

Cookies provide a means in Web applications to store user-specific information. For example, when a user visits your site, you can use cookies to store user preferences or other information. When the user visits your Web site another time, the application can retrieve the information it stored earlier.

Background

A cookie is a small bit of text that accompanies requests and pages as they go between the Web server and browser. The cookie contains information the Web application can read whenever the user visits the site.

For example, if a user requests a page from your site and your application sends not just a page, but also a cookie containing the date and time, when the user's browser gets the page, the browser also gets the cookie, which it stores in a folder on the user's hard disk.

Later, if user requests a page from your site again, when the user enters the URL the browser looks on the local hard disk for a cookie associated with the URL. If the cookie exists, the browser sends the cookie to your site along with the page request. Your application can then determine the date and time that the user last visited the site. You might use the information to display a message to the user or check an expiration date.

Cookies are associated with a Web site, not with a specific page, so the browser and server will exchange cookie information no matter what page the user requests from your site. As the user visits different sites, each site might send a cookie to the user's browser as well; the browser stores all the cookies separately.

Cookies help Web sites store information about visitors. More generally, cookies are one way of maintaining continuity in a Web application—that is, of performing state management. Except for the brief time when they are actually exchanging information, the browser and Web server are disconnected. Each request a user makes to a Web server is treated independently of any other request. Many times, however, it's useful for the Web server to recognize users when they request a page. For example, the Web server on a shopping site keeps track of individual shoppers so the site can manage shopping carts and other user-specific information. A cookie therefore acts as a kind of calling card, presenting pertinent identification that helps an application know how to proceed.

Cookies are used for many purposes, all relating to helping the Web site remember users. For example, a site conducting a poll might use a cookie simply as a Boolean value to indicate whether a user's browser has already participated in voting so that the user cannot vote twice. A

Page 34: ASPNET

site that asks a user to log on might use a cookie to record that the user already logged on so that the user does not have to keep entering credentials.

Cookie Limitations

Most browsers support cookies of up to 4096 bytes. Because of this small limit, cookies are best used to store small amounts of data, or better yet, an identifier such as a user ID. The user ID can then be used to identify the user and read user information from a database or other data store. (See the section "Cookies and Security" below for information about security implications of storing user information.)

Browsers also impose limitations on how many cookies your site can store on the user's computer. Most browsers allow only 20 cookies per site; if you try to store more, the oldest cookies are discarded. Some browsers also put an absolute limit, usually 300, on the number of cookies they will accept from all sites combined.

A cookie limitation that you might encounter is that users can set their browser to refuse cookies. If you define a P3P privacy policy and place it in the root of your Web site, more browsers will accept cookies from your site. However, you might have to avoid cookies altogether and use a different mechanism to store user-specific information. A common method for storing user information is session state, but session state depends on cookies, as explained later in the section "Cookies and Session State."

Although cookies can be very useful in your application, the application should not depend on being able to store cookies. Do not use cookies to support critical features. If your application must rely on cookies, you can test to see whether the browser will accept cookies. See the "Checking Whether a Browser Accepts Cookies" section later in this topic.

Writing Cookies

The browser is responsible for managing cookies on a user system. Cookies are sent to the browser via the HttpResponse object that exposes a collection called Cookies. You can access the HttpResponse object as the Response property of your Page class. Any cookies that you want to send to the browser must be added to this collection. When creating a cookie, you specify a Name and Value. Each cookie must have a unique name so that it can be identified later when reading it from the browser. Because cookies are stored by name, naming two cookies the same will cause one to be overwritten.

You can also set a cookie's date and time expiration. Expired cookies are deleted by the browser when a user visits the site that wrote the cookies. The expiration of a cookie should be set for as long as your application considers the cookie value to be valid. For a cookie to effectively never expire, you can set the expiration date to be 50 years from now.

Note:

Page 35: ASPNET

Users can clear the cookies on their computer at any time. Even if you store cookies with long expiration times, a user might decide to delete all cookies, wiping out any settings you might have stored in cookies.

If you do not set the cookie's expiration, the cookie is created but it is not stored on the user's hard disk. Instead, the cookie is maintained as part of the user's session information. When the user closes the browser, the cookie is discarded. A non-persistent cookie like this is useful for information that needs to be stored for only a short time or that for security reasons should not be written to disk on the client computer. For example, non-persistent cookies are useful if the user is working on a public computer, where you do not want to write the cookie to disk.

You can add cookies to the Cookies collection in a number of ways. The following example shows two methods to write cookies:

Response.Cookies("userName").Value = "patrick"Response.Cookies("userName").Expires = DateTime.Now.AddDays(1)

Dim aCookie As New HttpCookie("lastVisit")aCookie.Value = DateTime.Now.ToString()aCookie.Expires = DateTime.Now.AddDays(1)Response.Cookies.Add(aCookie)

The example adds two cookies to the Cookies collection, one named userName and the other named lastVisit. For the first cookie, the values of the Cookies collection are set directly. You can add values to the collection this way because Cookies derives from a specialized collection of type NameObjectCollectionBase.

For the second cookie, the code creates an instance of an object of type HttpCookie, sets its properties, and then adds it to the Cookies collection via the Add method. When you instantiate an HttpCookie object, you must pass the cookie name as part of the constructor.

Both examples accomplish the same task, writing a cookie to the browser. In both methods, the expiration value must be of type DateTime. However, the lastVisited value is also a date-time value. Because all cookie values are stored as strings, the date-time value has to be converted to a String .

Cookies with More Than One Value

You can store one value in a cookie, such as user name and last visit. You can also store multiple name-value pairs in a single cookie. The name-value pairs are referred to as subkeys. (Subkeys are laid out much like a query string in a URL.) For example, instead of creating two separate cookies named userName and lastVisit, you can create a single cookie named userInfo that has the subkeys userName and lastVisit.

You might use subkeys for several reasons. First, it is convenient to put related or similar information into a single cookie. In addition, because all the information is in a single cookie, cookie attributes such as expiration apply to all the information. (Conversely, if you want to

Page 36: ASPNET

assign different expiration dates to different types of information, you should store the information in separate cookies.)

A cookie with subkeys also helps you limit the size of cookie files. As noted earlier in the "Cookie Limitations" section, cookies are usually limited to 4096 bytes and you can't store more than 20 cookies per site. By using a single cookie with subkeys, you use fewer of those 20 cookies that your site is allotted. In addition, a single cookie takes up about 50 characters for overhead (expiration information, and so on), plus the length of the value that you store in it, all of which counts toward the 4096-byte limit. If you store five subkeys instead of five separate cookies, you save the overhead of the separate cookies and can save around 200 bytes.

To create a cookie with subkeys, you can use a variation of the syntax for writing a single cookie. The following example shows two ways to write the same cookie, each with two subkeys:

Response.Cookies("userInfo")("userName") = "patrick"Response.Cookies("userInfo")("lastVisit") = DateTime.Now.ToString()Response.Cookies("userInfo").Expires = DateTime.Now.AddDays(1)

Dim aCookie As New HttpCookie("userInfo")aCookie.Values("userName") = "patrick"aCookie.Values("lastVisit") = DateTime.Now.ToString()aCookie.Expires = DateTime.Now.AddDays(1)Response.Cookies.Add(aCookie)

Controlling Cookie Scope

By default, all cookies for a site are stored together on the client, and all cookies are sent to the server with any request to that site. In other words, every page in a site gets all of the cookies for that site. However, you can set the scope of cookies in two ways:

Limit the scope of cookies to a folder on the server, which allows you to limit cookies to an application on the site.

Set scope to a domain, which allows you to specify which subdomains in a domain can access a cookie.

Limiting Cookies to a Folder or Application

To limit cookies to a folder on the server, set the cookie's Path property, as in the following example:

Dim appCookie As New HttpCookie("AppCookie")appCookie.Value = "written " & DateTime.Now.ToString()appCookie.Expires = DateTime.Now.AddDays(1)appCookie.Path = "/Application1"Response.Cookies.Add(appCookie)

Page 37: ASPNET

Note:

You can also write cookies by adding them to the Cookies collection directly as shown in earlier examples.

The path can either be a physical path under the site root or a virtual root. The effect will be that the cookie is available only to pages in the Application1 folder or virtual root. For example, if your site is called www.contoso.com, the cookie created in the previous example will be available to pages with the path http://www.contoso.com/Application1/ and to any pages beneath that folder. However, the cookie will not be available to pages in other applications such as http://www.contoso.com/Application2/ or just http://www.contoso.com/.

Note:

In some browsers, the path is case sensitive. You cannot control how users type URLs into their browsers, but if your application depends on cookies tied to a specific path, be sure that the URLs in any hyperlinks you create match the case of the Path property value.

Limiting Cookie Domain Scope

By default, cookies are associated with a specific domain. For example, if your site is www.contoso.com, the cookies you write are sent to the server when users request any page from that site. (This might not include cookies with a specific path value.) If your site has subdomains—for example, contoso.com, sales.contoso.com, and support.contoso.com—then you can associate cookies with a specific subdomain. To do so, set the cookie's Domain property, as in this example:

Response.Cookies("domain").Value = DateTime.Now.ToString()Response.Cookies("domain").Expires = DateTime.Now.AddDays(1)Response.Cookies("domain").Domain = "support.contoso.com"

When the domain is set in this way, the cookie will be available only to pages in the specified subdomain. You can also use the Domain property to create a cookie that can be shared among multiple subdomains, as shown in the following example:

Response.Cookies("domain").Value = DateTime.Now.ToString()Response.Cookies("domain").Expires = DateTime.Now.AddDays(1)Response.Cookies("domain").Domain = "contoso.com"

The cookie will then be available to the primary domain as well as to sales.contoso.com and support.contoso.com domains.

Reading Cookies

When a browser makes a request to the server, it sends the cookies for that server along with the request. In your ASP.NET applications, you can read the cookies using the HttpRequest object, which is available as the Request property of your Page class. The structure of the HttpRequest

Page 38: ASPNET

object is essentially the same as that of the HttpResponse object, so you can read cookies out of the HttpRequest object much the same way you wrote cookies into the HttpResponse object. The following code example shows two ways to get the value of a cookie named username and display its value in a Label control:

If Not Request.Cookies("userName") Is Nothing Then Label1.Text = Server.HtmlEncode(Request.Cookies("userName").Value)End If

If Not Request.Cookies("userName") Is Nothing Then Dim aCookie As HttpCookie = Request.Cookies("userName") Label1.Text = Server.HtmlEncode(aCookie.Value)End If

Before trying to get the value of a cookie, you should make sure that the cookie exists; if the cookie does not exist, you will get a NullReferenceException exception. Notice also that the HtmlEncode method was called to encode the contents of a cookie before displaying it in the page. This makes certain that a malicious user has not added executable script into the cookie. For more about cookie security, see the "Cookies and Security" section.

Note:

Because different browsers store cookies differently, different browsers on the same computer won't necessarily be able to read each other's cookies. For example, if you use Internet Explorer to test a page one time, but then later use a different browser to test again, the second browser won't find the cookies saved by Internet Explorer.

Reading the value of a subkey in a cookie is likewise similar to setting it. The following code example shows one way to get the value of a subkey:

If Not Request.Cookies("userInfo") Is Nothing Then Label1.Text = _ Server.HtmlEncode(Request.Cookies("userInfo")("userName")) Label2.Text = _ Server.HtmlEncode(Request.Cookies("userInfo")("lastVisit"))End If

In the preceding example, the code reads the value of the subkey lastVisit, which was set earlier to the string representation of a DateTime value. Cookies store values as strings, so if you want to use the lastVisit value as a date, you have to convert it to the appropriate type, as in this example:

Dim dt As DateTime

dt = DateTime.Parse(Request.Cookies("userInfo")("lastVisit"))

The subkeys in a cookie are typed as a collection of type NameValueCollection. Therefore, another way to get an individual subkey is to get the subkeys collection and then extract the subkey value by name, as shown in the following example:

Page 39: ASPNET

If Not Request.Cookies("userInfo") Is Nothing Then Dim UserInfoCookieCollection As _ System.Collections.Specialized.NameValueCollection UserInfoCookieCollection = Request.Cookies("userInfo").Values Label1.Text = _ Server.HtmlEncode(UserInfoCookieCollection("userName")) Label2.Text = _ Server.HtmlEncode(UserInfoCookieCollection("lastVisit"))End If

Changing a Cookie's Expiration Date

The browser is responsible for managing cookies, and the cookie's expiration time and date help the browser manage its store of cookies. Therefore, although you can read the name and value of a cookie, you cannot read the cookie's expiration date and time. When the browser sends cookie information to the server, the browser does not include the expiration information. (The cookie's Expires property always returns a date-time value of zero.) If you are concerned about the expiration date of a cookie, you must reset it, which is covered in the "Modifying and Deleting Cookies" section.

Reading Cookie Collections

You might occasionally need to read through all the cookies available to the page. To read the names and values of all the cookies available to the page, you can loop through the Cookies collection using code such as the following.

Dim i As IntegerDim output As System.Text.StringBuilder = New System.Text.StringBuilderDim aCookie As HttpCookieFor i = 0 to Request.Cookies.Count - 1 aCookie = Request.Cookies(i) output.Append("Cookie name = " & Server.HtmlEncode(aCookie.Name) _ & "<br />") output.Append("Cookie value = " & _ Server.HtmlEncode(aCookie.Value) & "<br /><br />")NextLabel1.Text = output.ToString()

Note:

When you run this code, you might see a cookie named ASP.NET_SessionId. That is a cookie that ASP.NET uses to store a unique identifier for your session. The session cookie is not persisted on your hard disk. For more about session cookies, see the "Cookies and Session State" later in this topic.

A limitation of the preceding example is that if the cookie has subkeys, the display shows the subkeys as a single name/value string. You can read a cookie's HasKeys property to determine whether the cookie has subkeys. If so, you can read the subkey collection to get individual

Page 40: ASPNET

subkey names and values. You can read subkey values from the Values collection directly by index value. The corresponding subkey names are available in the AllKeys member of the Values collection, which returns an array of strings. You can also use the Keys member of the Values collection. However, the AllKeys property is cached the first time it is accessed. In contrast, the Keys property builds an array each time it is accessed. For this reason, the AllKeys property is much faster on subsequent accesses within the context of the same page request.

The following example shows a modification of the preceding example. It uses the HasKeys property to test for subkeys, and if subkeys are detected, the example gets subkeys from the Values collection:

Dim i As Integer

Dim j As IntegerDim output As System.Text.StringBuilder = New StringBuilder()Dim aCookie As HttpCookieDim subkeyName As StringDim subkeyValue As StringFor i = 0 To Request.Cookies.Count - 1 aCookie = Request.Cookies(i) output.Append("Name = " & aCookie.Name & "<br />") If aCookie.HasKeys Then For j = 0 To aCookie.Values.Count - 1 subkeyName = Server.HtmlEncode(aCookie.Values.AllKeys(j)) subkeyValue = Server.HtmlEncode(aCookie.Values(j)) output.Append("Subkey name = " & subkeyName & "<br />") output.Append("Subkey value = " & subkeyValue & _ "<br /><br />") Next Else output.Append("Value = " & Server.HtmlEncode(aCookie.Value) & _ "<br /><br />") End IfNextLabel1.Text = output.ToString()

Alternatively, you can extract the subkeys as a NameValueCollection object as shown in the following example:

Dim i As IntegerDim j As IntegerDim output As System.Text.StringBuilder = New StringBuilder()Dim aCookie As HttpCookieDim subkeyName As StringDim subkeyValue As StringFor i = 0 To Request.Cookies.Count - 1 aCookie = Request.Cookies(i) output.Append("Name = " & aCookie.Name & "<br />") If aCookie.HasKeys Then Dim CookieValues As _ System.Collections.Specialized.NameValueCollection = _ aCookie.Values Dim CookieValueNames() As String = CookieValues.AllKeys

Page 41: ASPNET

For j = 0 To CookieValues.Count - 1 subkeyName = Server.HtmlEncode(CookieValueNames(j)) subkeyValue = Server.HtmlEncode(CookieValues(j)) output.Append("Subkey name = " & subkeyName & "<br />") output.Append("Subkey value = " & subkeyValue & _ "<br /><br />") Next Else output.Append("Value = " & Server.HtmlEncode(aCookie.Value) & _ "<br /><br />") End IfNextLabel1.Text = output.ToString

Modifying and Deleting Cookies

You cannot directly modify a cookie. Instead, changing a cookie consists of creating a new cookie with new values and then sending the cookie to the browser to overwrite the old version on the client. The following code example shows how you can change the value of a cookie that stores a count of the user's visits to the site:

Dim counter As Integer

If Request.Cookies("counter") Is Nothing Then counter = 0Else counter = Int32.Parse(Request.Cookies("counter").Value)End Ifcounter += 1Response.Cookies("counter").Value = counter.ToStringResponse.Cookies("counter").Expires = DateTime.Now.AddDays(1)

Deleting Cookies

Deleting a cookie—physically removing it from the user's hard disk—is a variation on modifying it. You cannot directly remove a cookie because the cookie is on the user's computer. However, you can have the browser delete the cookie for you. The technique is to create a new cookie with the same name as the cookie to be deleted, but to set the cookie's expiration to a date earlier than today. When the browser checks the cookie's expiration, the browser will discard the now-outdated cookie. The following code example shows one way to delete all the cookies available to the application:

Dim aCookie As HttpCookieDim i As IntegerDim cookieName As StringDim limit As Integer = Request.Cookies.Count - 1For i = 0 To limit cookieName = Request.Cookies(i).Name aCookie = New HttpCookie(cookieName) aCookie.Expires = DateTime.Now.AddDays(-1) Response.Cookies.Add(aCookie)Next

Page 42: ASPNET

Modifying or Deleting Subkeys

Modifying an individual subkey is the same as creating it, as shown in the following example:

Response.Cookies("userInfo")("lastVisit") = DateTime.Now.ToString()Response.Cookies("userInfo").Expires = DateTime.Now.AddDays(1)

To delete an individual subkey, you manipulate the cookie's Values collection, which holds the subkeys. You first recreate the cookie by getting it from the Cookies object. You can then call the Remove method of the Values collection, passing to the Remove method the name of the subkey to delete. You then add the cookie to the Cookies collection so it will be sent in its modified form back to the browser. The following code example shows how to delete a subkey. In the sample, the name of the subkey to remove is specified in a variable.

Dim subkeyName As String

subkeyName = "userName"Dim aCookie As HttpCookie = Request.Cookies("userInfo")aCookie.Values.Remove(subkeyName)aCookie.Expires = DateTime.Now.AddDays(1)Response.Cookies.Add(aCookie)

Cookies and Security

The security issues with cookies are similar to those of getting data from the client. In your application, cookies are another form of user input and are therefore subject to examining and spoofing. A user can as a minimum see the data that you store in a cookie, since the cookie is available on the user's own computer. The user can also change the cookie before the browser sends it to you.

You should never store sensitive data in a cookie, such as user names, passwords, credit card numbers, and so on. Do not put anything in a cookie that should not be in the hands of a user or of someone who might somehow steal the cookie.

Similarly, be suspicious of information you get out of a cookie. Do not assume that the data is the same as when you wrote it out; use the same safeguards in working with cookie values that you would with data that a user has typed into a Web page. The examples earlier in this topic showed HTML-encoding the contents of a cookie before displaying the value in a page, as you would before displaying any information you get from users.

Cookies are sent between browser and server as plain text, and anyone who can intercept your Web traffic can read the cookie. You can set a cookie property that causes the cookie to be transmitted only if the connection uses the Secure Sockets Layer (SSL). SSL does not protect the cookie from being read or manipulated while it is on the user's computer, but it does prevent the cookie from being read while in transit because the cookie is encrypted.

Page 43: ASPNET

Determining Whether a Browser Accepts Cookies

Users can set their browser to refuse cookies. No error is raised if a cookie cannot be written. The browser likewise does not send any information to the server about its current cookie settings.

Note:

The Cookies property does not indicate whether cookies are enabled. It indicates only whether the current browser inherently supports cookies.

One way to determine whether cookies are accepted is by trying to write a cookie and then trying to read it back again. If you cannot read the cookie you wrote, you assume that cookies are turned off in the browser.

The following code example shows how you might test whether cookies are accepted. The sample consists of two pages. The first page writes out a cookie, and then redirects the browser to the second page. The second page tries to read the cookie. It in turn redirects the browser back to the first page, adding to the URL a query string variable with the results of the test.

The code for the first page looks like this:

Protected Sub Page_Load(ByVal sender As Object, _

ByVal e As EventArgs) Handles Me.Load If Not Page.IsPostBack Then If Request.QueryString("AcceptsCookies") Is Nothing Then Response.Cookies("TestCookie").Value = "ok" Response.Cookies("TestCookie").Expires = _ DateTime.Now.AddMinutes(1) Response.Redirect("TestForCookies.aspx?redirect=" & _ Server.UrlEncode(Request.Url.ToString)) Else Label1.Text = "Accept cookies = " & _ Server.UrlEncode(Request.QueryString("AcceptsCookies")) End If End IfEnd Sub

The page first tests to see if this is a postback, and if not, the page looks for the query string variable name AcceptsCookies that contains the test results. If there is no query string variable, the test has not been completed, so the code writes out a cookie named TestCookie. After writing out the cookie, the sample calls Redirect to transfer to the test page TestForCookies.aspx. Appended to the URL of the test page is a query string variable named redirect containing the URL of the current page; this will allow you to redirect back to this page after performing the test.

The test page can consist entirely of code; it does not need to contain controls. The following code example illustrates the test page.

Page 44: ASPNET

Sub Page_Load()

Dim redirect As String = Request.QueryString("redirect") Dim acceptsCookies As String If Request.Cookies("TestCookie") Is Nothing Then acceptsCookies = "no" Else acceptsCookies = "yes" ' Delete test cookie. Response.Cookies("TestCookie").Expires = _ DateTime.Now.AddDays(-1) End If Response.Redirect(redirect & "?AcceptsCookies=" & acceptsCookies, _ True)End Sub

After reading the redirect query string variable, the code tries to read the cookie. For housekeeping purposes, if the cookie exists, it is immediately deleted. When the test is finished, the code constructs a new URL from the URL passed to it in the redirect query string variable. The new URL also includes a query string variable containing test results. The final step is to use the new URL to redirect the browser to the original page.

An improvement in the example would be to keep the cookie test results in a persistent store such as a database so that the test does not have to be repeated each time the user views the original page. (Storing the test results in session state by default requires cookies.)

Cookies and Session State

When a user navigates to your site, the server establishes a unique session for that user that lasts for the duration of the user's visit. For each session, ASP.NET maintains session state information where applications can store user-specific information.

ASP.NET must track a session ID for each user so that it can map the user to session state information on the server. By default, ASP.NET uses a non-persistent cookie to store the session state. However, if a user has disabled cookies on the browser, session state information cannot be stored in a cookie.

ASP.NET offers an alternative in the form of cookieless sessions. You can configure your application to store session IDs not in a cookie, but in the URLs of pages in your site. If your application relies on session state, you might consider configuring it to use cookieless sessions. However, under some limited circumstances, if the user shares the URL with someone else—perhaps to send the URL to a colleague while the user's session is still active—then both users can end up sharing the same session, with unpredictable results.

Class Reference

HttpCookie Provides a type-safe way to create and manipulate individual HTTP cookies.

Page 45: ASPNET

Cookies Gets the response cookie collection.Cookies Gets a collection of cookies sent by the client.

ASP.NET Session State OverviewUse ASP.NET session state to store and retrieve values for a user.

This topic contains:

Background Class Reference

Background

ASP.NET session state enables you to store and retrieve values for a user as the user navigates ASP.NET pages in a Web application. HTTP is a stateless protocol. This means that a Web server treats each HTTP request for a page as an independent request. The server retains no knowledge of variable values that were used during previous requests. ASP.NET session state identifies requests from the same browser during a limited time window as a session, and provides a way to persist variable values for the duration of that session. By default, ASP.NET session state is enabled for all ASP.NET applications.

Alternatives to session state include the following:

Application state, which stores variables that can be accessed by all users of an ASP.NET application.

Profile properties, which persists user values in a data store without expiring them. ASP.NET caching, which stores values in memory that is available to all ASP.NET

applications. View state, which persists values in a page. Cookies. The query string and fields on an HTML form that are available from an HTTP request.

Session Variables

Session variables are stored in a SessionStateItemCollection object that is exposed through the HttpContext.Session property. In an ASP.NET page, the current session variables are exposed through the Session property of the Page object.

The collection of session variables is indexed by the name of the variable or by an integer index. Session variables are created by referring to the session variable by name. You do not have to declare a session variable or explicitly add it to the collection. The following example shows

Page 46: ASPNET

how to create session variables in an ASP.NET page for the first and last name of a user, and set them to values retrieved from TextBox controls.

Session("FirstName") = FirstNameTextBox.Text

Session("LastName") = LastNameTextBox.Text

Session variables can be any valid .NET Framework type. The following example stores an ArrayList object in a session variable named StockPicks. The value returned by the StockPicks session variable must be cast to the appropriate type when you retrieve it from the SessionStateItemCollection.

' When retrieving an object from session state, cast it to ' the appropriate type.Dim stockPicks As ArrayList = CType(Session("StockPicks"), ArrayList)

' Write the modified stock picks list back to session state.Session("StockPicks") = stockPicks

Note:

When you use a session-state mode other than InProc, the session-variable type must be either a primitive .NET type or serializable. This is because the session-variable value is stored in an external data store. For more information, see Session-State Modes.

Session Identifiers

Sessions are identified by a unique identifier that can be read by using the SessionID property. When session state is enabled for an ASP.NET application, each request for a page in the application is examined for a SessionID value sent from the browser. If no SessionID value is supplied, ASP.NET starts a new session and the SessionID value for that session is sent to the browser with the response.

By default, SessionID values are stored in a cookie. However, you can also configure the application to store SessionID values in the URL for a "cookieless" session.

A session is considered active as long as requests continue to be made with the same SessionID value. If the time between requests for a particular session exceeds the specified time-out value in minutes, the session is considered expired. Requests made with an expired SessionID value result in a new session.

Security Note:

SessionID values are sent in clear text, whether as a cookie or as part of the URL. A malicious user could get access to the session of another user by obtaining the SessionID value and including it in requests to the server. If you are storing sensitive information in session state, it is recommended that you use SSL to encrypt any communication between the browser and server that includes the SessionID value.

Page 47: ASPNET

Cookieless SessionIDs

By default, the SessionID value is stored in a non-expiring session cookie in the browser. However, you can specify that session identifiers should not be stored in a cookie by setting the cookieless attribute to true in the sessionState section of the Web.config file.

The following example shows a Web.config file that configures an ASP.NET application to use cookieless session identifiers.

<configuration> <system.web> <sessionState cookieless="true" regenerateExpiredSessionId="true" /> </system.web></configuration>

ASP.NET maintains cookieless session state by automatically inserting a unique session ID into the page's URL. For example, the following URL has been modified by ASP.NET to include the unique session ID lit3py55t21z5v55vlm25s55:

http://www.example.com/(S(lit3py55t21z5v55vlm25s55))/orderform.aspx

When ASP.NET sends a page to the browser, it modifies any links in the page that use an application-relative path by embedding a session ID value in the links. (Links with absolute paths are not modified.) Session state is maintained as long as the user clicks links that have been modified in this manner. However, if the client rewrites a URL that is supplied by the application, ASP.NET may not be able to resolve the session ID and associate the request with an existing session. In that case, a new session is started for the request.

The session ID is embedded in the URL after the slash that follows the application name and before any remaining file or virtual directory identifier. This enables ASP.NET to resolve the application name before involving the SessionStateModule in the request.

Note:

To improve the security of your application, you should allow users to log out of your application, at which point the application should call the Abandon method. This reduces the potential for a malicious user to get the unique identifier in the URL and use it to retrieve private user data stored in the session.

Regenerating Expired Session Identifiers

By default, the session ID values that are used in cookieless sessions are recycled. That is, if a request is made with a session ID that has expired, a new session is started by using the

Page 48: ASPNET

SessionID value that is supplied with the request. This can result in a session unintentionally being shared when a link that contains a cookieless SessionID value is used by multiple browsers. (This can occur if the link is passed through a search engine, through an e-mail message, or through another program.) You can reduce the chance of session data being shared by configuring the application not to recycle session identifiers. To do this, set the regenerateExpiredSessionId attribute of the sessionState configuration element to true. This generates a new session ID when a cookieless session request is made with an expired session ID.

Note:

If the request that is made with the expired session ID is made by using the HTTP POST method, any posted data will be lost when regenerateExpiredSessionId is true. This is because ASP.NET performs a redirect to make sure that the browser has the new session identifier in the URL.

Custom Session Identifiers

You can implement a custom class to supply and validate SessionID values. To do so, create a class that inherits the SessionIDManager class and override the CreateSessionID and Validate methods with your own implementations. For an example, see the example provided for the CreateSessionID method.

You can replace the SessionIDManager class by creating a class that implements the ISessionIDManager interface. For example, you might have a Web application that associates a unique identifier with non-ASP.NET pages (such as HTML pages or images) by using an ISAPI filter. You can implement a custom SessionIDManager class to use this unique identifier with ASP.NET session state. If your custom class supports cookieless session identifiers, you must implement a solution for sending and retrieving session identifiers in the URL.

Session Modes

ASP.NET session state supports several storage options for session variables. Each option is identified as a session-state Mode type. The default behavior is to store session variables in the memory space of the ASP.NET worker process. However, you can also specify that session state should be stored in a separate process, in a SQL Server database, or in a custom data source. If you do not want session state enabled for your application, you can set the session mode to Off.

For more information, see Session-State Modes.

Session Events

ASP.NET provides two events that help you manage user sessions. The Session_OnStart event is raised when a new session starts, and the Session_OnEnd event is raised when a session is abandoned or expires. Session events are specified in the Global.asax file for an ASP.NET application.

Page 49: ASPNET

The Session_OnEnd event is not supported if the session Mode property is set to a value other than InProc, which is the default mode.

Note:

If the Global.asax file or Web.config file for an ASP.NET application is modified, the application will be restarted and any values stored in application state or session state will be lost. Be aware that some anti-virus software can update the last-modified date and time of the Global.asax or Web.config file for an application.

Configuring Session State

Session state is configured by using the sessionState element of the system.web configuration section. You can also configure session state by using the EnableSessionState value in the @ Page directive.

The sessionState element enables you to specify the following options:

The mode in which the session will store data. The way in which session identifier values are sent between the client and the server. The session Timeout value. Supporting values that are based on the session Mode setting.

The following example shows a sessionState element that configures an application for SQLServer session mode. It sets the Timeout value to 30 minutes, and specifies that session identifiers are stored in the URL.

<sessionState mode="SQLServer" cookieless="true " regenerateExpiredSessionId="true " timeout="30" sqlConnectionString="Data Source=MySqlServer;Integrated Security=SSPI;" stateNetworkTimeout="30"/>

You can disable session state for an application by setting the session-state mode to Off. If you want to disable session state for only a particular page of an application, you can set the EnableSessionState value in the @ Page directive to false. The EnableSessionState value can also be set to ReadOnly to provide read-only access to session variables.

Concurrent Requests and Session State

Access to ASP.NET session state is exclusive per session, which means that if two different users make concurrent requests, access to each separate session is granted concurrently. However, if two concurrent requests are made for the same session (by using the same SessionID value), the first request gets exclusive access to the session information. The second request executes only after the first request is finished. (The second session can also get access if the

Page 50: ASPNET

exclusive lock on the information is freed because the first request exceeds the lock time-out.) If the EnableSessionState value in the @ Page directive is set to ReadOnly, a request for the read-only session information does not result in an exclusive lock on the session data. However, read-only requests for session data might still have to wait for a lock set by a read-write request for session data to clear.

Back to top

Class Reference

The following table lists key classes that relate to session state are in the System.Web.SessionState namespace.

Member DescriptionSessionIDManager Manages unique identifiers for ASP.NET session state.SessionStateItemCollection Used to store session state variables.

ASP.NET Application State OverviewApplication state is a data repository available to all classes in an ASP.NET application. Application state is stored in memory on the server and is faster than storing and retrieving information in a database. Unlike session state, which is specific to a single user session, application state applies to all users and sessions. Therefore, application state is a useful place to store small amounts of often-used data that does not change from one user to another.

Using Application State

Application state is stored in an instance of the HttpApplicationState class. This class exposes a key-value dictionary of objects.

The HttpApplicationState instance is created the first time a user accesses any URL resource in an application. The HttpApplicationState class is most often accessed through the Application property of the HttpContext class.

You can use application state in two ways. You can add, access, or remove values from the Contents collection directly through code. The HttpApplicationState class can be accessed at any time during the life of an application. However, it is often useful to load application state data when the application starts. To do so, you can put code to load application state into the Application_Start method in the Global.asax file.

Page 51: ASPNET

Alternatively, you can add objects to the StaticObjects collection via an <object runat="server"> declaration in your Web application's Global.asax file. Application state defined in this way can then be accessed from code anywhere in your application. The following example shows an object declaration for an application state value:

<object runat="server" scope="application" ID="MyInfo" PROGID="MSWC.MYINFO"></object>

You can add objects to the StaticObjects collection only in the Global.asax file. The collection throws a NotSupportedException if you attempt to add objects directly through code.

You can access members of objects stored in application state without having to reference the Application collection. The following code example shows how to reference a member of an object defined in the StaticObjects collection of application state. Notice that the label identifier that is defined in the Global.asax file is used as the variable name.

Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Label1.Text = MyInfo.TitleEnd SubApplication State Considerations

When using application state, you must be aware of the following important considerations:

Resources   Because it is stored in memory, application state is very fast compared to saving data to disk or a database. However, storing large blocks of data in application state can fill up server memory, causing the server to page memory to disk. As an alternative to using application state, you can use the ASP.NET cache mechanism for storing large amounts of application data. The ASP.NET cache also stores data in memory and is therefore very fast; however, ASP.NET actively manages the cache and will remove items when memory becomes scarce.

Volatility   Because application state is stored in server memory, it is lost whenever the application is stopped or restarted. For example, if the Web.config file is changed, the application is restarted and all application state is lost unless application state values have been written to a non-volatile storage medium such as a database.

Scalability   Application state is not shared among multiple servers serving the same application, as in a Web farm, or among multiple worker processes serving the same application on the same server, as in a Web garden. Your application therefore cannot rely on application state containing the same data for application state across different servers or processes. If your application will run in multi-processor or multi-server environments, consider using a more scalable option, such as a database, for data that must preserve fidelity across the application.

Concurrency   Application state is free-threaded, which means that application state data can be accessed simultaneously by many threads. Therefore, it is important to ensure that

Page 52: ASPNET

when you update application state data, you do so in a thread-safe manner by including built-in synchronization support. You can use the Lock and UnLock methods to ensure data integrity by locking the data for writing by only one source at a time. You can also reduce the likelihood of concurrency problems by initializing application state values in the Application_Start method in the Global.asax file.

ASP.NET CachingCaching

Caching is the process of storing frequently used data, usually data that is costly to generate, for reuse. Typically this data is stored in memory since retrieving data from memory is much more efficient than retrieving the data from other locations, such as a database.

ASP.NET has several facilities for supporting caching: a Cache API for storing arbitrary data and an Output Cache used to store frequently requested Pages.

Let's discuss a quick example.

A catalog used on an e-commerce site might only change once a week. An ASP.NET Web application could be built that provides a front-end interface for that catalog, allowing customers to purchase products. When a customer is simply browsing the catalog, the system is making (in most cases) network calls to a back-end database server. The database server is also doing calculations on the data, such as a join query, and returning results.

This type of configuration is quite common, be it a catalog or some other type of commonly requested data from a database. However, the design in the above example can be improved upon. We know that the data in the database only changes once a week, and we know that there are several performance costs associated with retrieving the data:

1. Executing of the ASP.NET code to make the database request.2. Use of the network for the Web server to communicate with the database server.3. Work done on the database server to compile and execute the query (or simply execute stored

procedure).

Caching allows us to eliminate much of the above work and improve the performance and scalability of our application. We can improve performance by caching the results and serving them statically (versus dynamically on each request) and our scalability increases since we're using fewer resources to service each request.

Beta 1 of ASP.NET introduced the Cache API as well as Page output caching, which uses the Cache API. Let's discuss these two features in more detail.

Page 53: ASPNET

Cache API

Storing frequently requested data in memory is nothing new for ASP developers. We've had two types of objects that solve this problem:

Session objects Application objects

Session is used to store per-user data across multiple requests. There have been some changes for Session in ASP.NET but most of these changes are application level changes and don't affect the way Session is used, that is, it's still a simple key/value pair.

The Application object from ASP is also carried forward to ASP.NET, and it to remains identical in function (key/value pairs). For example, we could write the following in either ASP or ASP.NET:

Application("SomeInterestingData") = "Example data"Response.Write(Application("SomeInterestingData")

The same semantics are used for Session. We simply name a key, in this case we used SomeInterestingData, and assign it a value, in this case the string "Example data".

ASP.NET introduces another key/value pair object—Cache. In addition to simply storing key/value pairs, Cache adds additional functionality specifically designed to store transient data:

Dependencies—A key added to the Cache can set up dependency relationships that can force that key to be removed from the Cache. The supported dependencies include key, file, and time.

Automatic Expiration—Underused items added to the Cache that have no dependencies will automatically expire if they are underused.

Support for Callback—Code paths can be added that will be called when an item is removed from the Cache, giving us an opportunity to update the Cache or not remove the item.

When we code our applications to use the Cache we do have to make one consideration:

Always check if the item exists in the Cache before attempting to use it.

Because the Cache will expire, items based on dependencies or under use, we must always write our code to create or retrieve the item we need if it doesn't exist within the Cache.

For example, if we wrote a function that returned a populated DataSet:

Private Function LoadDataSet() As DataSet Dim sqlConnection As SQLConnection Dim sqlAdapater As SQLDataSetCommand Dim datasetProducts As New DataSet() Dim sqlDSN As String Dim sqlSelect As String

Page 54: ASPNET

' Connection String and Select statement sqlDSN = "server=localhost;uid=<user id>;pwd=<password>;database=grocertogo" sqlSelect = "Select * From Products"

' Connect sqlConnection = new SQLConnection(sqlDSN) sqlAdapater = new SQLDataSetCommand(sqlSelect, sqlConnection)

' Fill dataset create product table sqlAdapter1.FillDataSet(datasetProducts, "products")

Return productsEnd Function

We could easily write code that took advantage of the Cache. Executing LoadDataSet() only when the resulting DataSet is not already in the Cache:

Public Function GetProductData() As DataSet If (IsNothing(Cache("ProductData")) Then Cache("ProductData") = LoadDataSet()

Return Cache("ProductData")End Function

However, this isn't really all that different from using Application. We essentially could accomplish exactly this same thing. Where this gets interesting is when we set up dependencies.

Cache Dependencies

Dependencies allow us to invalidate a particular item within the Cache based on changes to files, changes to other Cache keys, or at a fixed point in time. Let's look at each of these dependencies.

File-based Dependency

File-based dependency invalidates a particular Cache item when file(s) on disk change. For example, if instead of loading our ProductData from a database, we loaded it from an XML file:

Dim dom As XmlDocument()dom.Load(Server.MapPath("product.xml")Cache("ProductData") = dom

We obviously would also want to invalidate the data within the Cache if product.xml changes. Assuming product.xml is in the same directory as the requesting application:

Dim dependency as new CacheDependency(Server.MapPath("product.xml"))Cache.Insert("ProductData", dom, dependency)

Page 55: ASPNET

In the above code sample, we're creating an instance of a CacheDependency class, dependency, and passing in the path to the product.xml file. We then use the Insert() method of the Cache to create our ProductData key that is dependent upon the file it retrieves its data from.

Key-based Dependency

Key-based dependency invalidates a particular Cache item when another Cache item changes. For example, if our application added multiple DataSets to the Cache, such as ProductData, SalesData, and MarketingData and SalesData and MarketingData rely upon ProductData being valid. We could use a key-based dependency to invalidate SalesData and MarketingData if ProductData changes. We set up this dependency when we create the Cache entries for SalesData and MarketingData:

Dim dependency (1) As StringdependencyKey(0) = "ProductData"Dim productDataDependency As new CacheDependency(nothing, dependencyKey)

Cache.Insert("SalesData", LoadDataSet("Sales"), productDataDependency)

In the above example code, we use the Insert() method to create a new Cache entry named SalesData passing in an instance of a CacheDependency class named productDataDependency which names the Cache key ProductData. Now, whenever ProductData changes, SalesData will be removed from the Cache.

Time-based Dependency

Time-based dependency simply expires the item at a defined point in time. Again, we would use the Insert() method of the Cache to create this dependency. We have two options for time-based dependency:

Absolute—Sets an absolute time; for example, current time + 10 minutes for the Cache entry to expire.

Sliding—Resets the time for the item in the Cache to expire on each request.

We can use the Sliding expiration option to Cache our ProductData DataSet for a maximum of 10 minutes. As long as requests for ProductData are made within a 10-minute window, the data is made valid for another 10 minutes:

' 10 minute time spanDim span As New TimeSpan(0,10,0)Cache.Insert("ProductData", LoadDataSet(), nothing, nothing, span)

Although this has been a relatively lightweight discussion of the Cache API, hopefully you've seen just how easy it is to use. Underneath the covers, ASP.NET makes use of the Cache API and it's time based expiration policy to support the concept of page output caching. In a future column will dig into more detail on the Cache API.

Page 56: ASPNET

Page Output Caching

Page output caching is a feature of ASP.NET that allows for the entire contents of a given page to be stored in the Cache. We've been using the Cache API in the above example to store DataSets in the Cache. What if, rather than simply storing the DataSet, we determine that the entire page (that displays the results of the DataSet) can be cached? The benefit here is that rather than dynamically executing the ASP.NET page on each request, we serve it statically from memory. This can be a huge performance enhancement!

There is both a low-level and high-level API for working with Page Output Caching. We're only going to discuss the high-level API in the remainder of this article, but we'll discuss the low-level API in a future column (post Beta 2).

The high-level API consists of a Page directive that instructs ASP.NET to Cache the results from the page for a period of time:

<%@ OutputCache Duration="10" %>

This directive, added to the top of an ASP.NET page, simply instructs ASP.NET to cache the results of the page for 10 seconds. After 10 seconds the page will re-execute. Here's an example that uses this directive:

<%@ OutputCache Duration="10" %><Script runat="server"> Public Sub Page_Load() span1.InnerHtml = DateTime.Now.ToString("r") End Sub</Script><font size=6>The time is: <font color=red><span id="span1" runat="server"/></font></font>

This page simply executes on the first request, displays the time at which it was requested, and then is served from the Cache for a period of 10 seconds. For example, if we request the page at 10:30:12, we would see that value for the output for 10 seconds, after which the page is re-executed.

Summary

The Cache is a new feature for us ASP developers. However, it is both easy to use and powerful. The API is similar to Application and Session, a simple key/value pair dictionary, but unlike Application or Session, items within the Cache can expire. Unlike Application, the Cache supports file, key, and time based dependencies, as well as callbacks, which we'll save for our post Beta 2 discussion. The Cache is also used by ASP.NET for ASP.NET Page Output Caching. In a future column we'll discuss some of the new Cache features that will be appearing in Beta 2, such as Partial Page Caching and Web Service Caching, and we'll also look at some of the more advanced features like callbacks.

Page 57: ASPNET