ASP.NET

  ASP.NET From Scratch  

Web Server and ASP.NET Application Life Cycle in Depth IIS6 and IIS 7  

A Web Server (like Internet Information Server/Apache/etc.) is a piece of software that enables a website to be viewed using HTTP. We can abstract this concept by saying that a web server is a piece of software that allows resources (web pages, images, etc.) to be requested over the HTTP protocol. I am sure many of you have thought that a web server is just a special super computer, but it's just the software that runs on it that makes the difference between a normal computer and a web server.

 

 

 

  

As everyone knows, in a Web Communication, there are two main actors: the Client and the Server.

The client and the server, of course, need a connection to be able to communicate with each other, and a common set of rules to be able to understand each other. The rules they need to communicate are called protocols. Conceptually, when we speak to someone, we are using a protocol. The protocols in human communication are rules about appearance, speaking, listening, and understanding. These rules, also called protocols of conversation, represent different layers of communication. They work together to help people communicate successfully. The need for protocols also applies to computing systems. A communications protocol is a formal description of digital message formats and the rules for exchanging those messages in or between computing systems and in telecommunications.

 

 

   


HTTP knows all the "grammar", but it doesn't know anything about how to send a message or open a connection. That's why HTTP is built on top of TCP/IP. Below, you can see the conceptual model of this protocol on top of the HTTP protocol:

 

 

   

TCP/IP is in charge of managing the connection and all the low level operations needed to deliver the message exchanged between the client and the server.
In this article, I won't explain how TCP/IP works, because I should write a whole article on it, but it's good to know it is the engine that allows the client and the server to have message exchanges.

 

HTTP is a connectionless protocol, but it doesn't mean that the client and the server don't need to establish a connection before they start to communicate with each other. But, it means that the client and the server don't need to have any prearrangements before they start to communicate.

Connectionless means the client doesn't care if the server is ready to accept a request, and on the other hand, the server doesn't care if the client is ready to get the response, but a connection is still needed.

In connection-oriented communication, the communicating peers must first establish a logical or physical data channel or connection in a dialog preceding the exchange of user data.

Now, let's see what happens when a user puts an address into the browser address bar.
  • The browser breaks the URL into three parts:
  • The browser communicates with a name server(DNS) to translate the server name "www.Pelusoft.co.uk" into an IP address, which it uses to connect to the server machine.
  • The browser then forms a connection to the server at that IP address on port 80. (We'll discuss ports later in this article.)
  • Following the HTTP protocol, the browser sents a GET request to the server, asking for the file "http://www.pelusoft.co.uk.com/index.htm". (Note that cookies may be sent from the browser to the server with the GET request -- see How Internet Cookies Work for details.)
  • The server then sents the HTML text for the web page to the browser. Cookies may also be sent from the server to the browser in the header for the page.)
  • The browser reads the HTML tags and formats the page onto your screen.

 

 

  

The current practice requires that the connection be established by the client prior to each request, and closed by the server after sending the response. Both clients and servers should be aware that either party may close the connection prematurely, due to user action, automated time-out, or program failure, and should handle such closing in a predictable fashion. In any case, the closing of the connection by either or both parties always terminates the current request, regardless of its status.

At this point, you should have an idea about how the HTTP - TCP/IP protocol works. Of course, there is a lot more to say, but the scope of this article is just a very high view of these protocols just to better understand all the steps that occur since the user starts to browse a web site.

Now it's time to go ahead, moving the focus on to what happens when the web server receives the request and how it can get the request itself.

 

As I showed earlier, a web server is a "normal computer" that is running a special software that makes it a Web Server. Let's suppose that IIS runs on our web server. From a very high view, IIS is just a process which is listening on a particular port (usually 80). Listening means it is ready to accept a connections from clients on port 80. A very important thing to remember is: IIS is not ASP.NET. This means that IIS doesn't know anything about ASP.NET; it can work by itself. We can have a web server that is hosting just HTML pages or images or any other kind of web resource. The web server, as I explained earlier, has to just return the resource the browser is asking for.

 

 

 

 

 

 

 

 

 

 

 

Old Browser is using Serial connection HandShaking Mechanism 

 

 

 

 

Modern Browsers using parallel connection Handshaking mechanism

 

  

Modern browsers are using Persistent Connection mechanism in Modern browsers

 HTTP persistent connection, also called HTTP keep-alive, or HTTP connection reuse, is the idea of using a single TCP connection to send and receive multiple HTTP requests/responses, as opposed to opening a new connection for every single request/response pair. 

 

    


ASP.NET and IIS
 

The web server can also support server scripting (as ASP.NET). What I show in this paragraph is what happens on the server running ASP.NET and how IIS can "talk" with the ASP.NET engine. When we install ASP.NET on a server, the installation updates the script map of an application to the corresponding ISAPI extensions to process therequest given to IIS. For example, the "aspx" extension will be mapped to aspnet_isapi.dll and hence requests for anaspx page to IIS will be given to aspnet_isapi (the ASP.NET registration can also be done using Aspnet_regiis). The script map is shown below:

  


 

The ISAPI filter is a plug-in that can access an HTTP data stream before IIS gets to see it. Without the ISAPI filter, IIS can not redirect a request to the ASP.NET engine (in the case of a .aspx page). From a very high point of view, we can think of the ISAPI filter as a router for IIS requests: every time there is a resource requested whose file extension is present on the map table (the one shown earlier), it redirect the request to the right place. In the case of an .aspx page, it redirects the request to the .NET runtime that knows how to elaborate the request. 
 

When a request comes in:

  • IIS creates/runs the work processor (w3wp.exe) if it is not running.
  • The aspnet_isapi.dll is hosted in the w3wp.exe process. IIS checks for the script map and routes the requestto aspnet_isapi.dll.
  • The request is passed to the .NET runtime that is hosted into w3wp.exe as well.






Finally, the request gets into the ASP.NET runtime 



This paragraph focuses on how the runtime handles the request and shows all the objects involved in the process.
First of all, let's have a look at what happens when the request gets to the runtime.
  • When ASP.NET receives the first request for any resource in an application, a class named Application Manager 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 Hosting Environment is created, which provides access to information about the application such as the name of the folder where the application is stored.
  • After the application domain has been created and the Hosting Environment object instantiated, ASP.NET creates and initializes core objects such as HttpContextHttpRequest, and HttpResponse.
  • 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.
Those are the first steps that happens against a client request. Most articles don't say anything about these steps. In this article, we will analyze in depth what happens at each step.
Below, you can see all the steps the request has to pass though before it is elaborated.









Application Manager 

The first object we have to talk about is the Application Manager.  Application Manager is actually an object that sits on top of all running ASP.NET AppDomains, and can do things like shut them all down or check for idle status.  For example, when you change the configuration file of your web application, the Application Manager is in charge to restart the AppDomain to allow all the running application instances (your web site instance) to be created again for loading the new configuration file you may have changed.   

Requests that are already in the pipeline processing will continue to run through the existing pipeline, while any newrequest coming in gets routed to the new AppDomain. To avoid the problem of "hung requests", ASP.NET forcefully shuts down the AppDomain after the request timeout period is up, even if requests are still pending.    

Application Manager is the "manager", but the Hosting Environment contains all the "logic" to manage the application instances. It's like when you have a class that uses an interface: within the class methods, you just call the interface method. In this case, the methods are called within the Application Manager, but are executed in the Hosting Environment (let's suppose the Hosting Environment is the class that implements the interface).  

At this point, you should have a question: how is it possible the Application Manager can communicate with the Hosting Environment since it lives in an AppDomain? (We said the AppDomain creates a kind of boundary around the application to isolate the application itself.) In fact, the Hosting Environment has to inherit from the MarshalByRefObject class to use Remoting to communicate with the Application Manager. The Application Manager creates a remote object (the Hosting Environment) and calls methods on it.

So we can say the Hosting Environment is the "remote interface" that is used by the Application Manager, but the code is "executed" within the Hosting Environment object.






HttpApplication

On the previous paragraph, I used the term "Application" a lot. HttpApplication is an instance of your web application. It's the object in charge to "elaborate" the request and return the response that has to be sent back to the client. An HttpApplication can elaborate only one request at a time. However, to maximize performance,HttpApplication instances might be reused for multiple requests, but it always executes one request at a time.

This simplifies application event handling because you do not need to lock non-static members in the application class when you access them. This also allows you to store request-specific data in non-static members of the application class. For example, you can define a property in the Global.asax file and assign it a request-specific value.

You can't manually create an instance of HttpApplication; it is the Application Manager that is in charge to do that. You can only configure what is the maximum number of HttpApplications you want to be created by the Application Manager. There are a bunch of keys in the machine config that can affect the Application Manager behavior:


With maxWorkerThreads and minWorkerThreads, you set up the minimum and maximum number of HttpApplications. For more information, have a look at: ProcessModel Element.


Just to clarify what we have said until now, we can say that against a request to a WebApplication, we have:
  • A Worker Process w3wp.exe is started (if it is not running).
  • An instance of ApplicationManager is created.
  • An ApplicationPool is created.
  • An instance of a Hosting Environment is created.
  • A pool of HttpAplication instances is created (defined with the machine.config).
Until now, we talked about just one WebApplication, let's say WebSite1, under IIS. What happens if we create another application under IIS for WebSite2?
  • We will have the same process explained above.
  • WebSite2 will be executed within the existing Worker Process w3wp.exe (where WebSite1 is running).
  • The same Application Manager instance will manage WebSite2 as well. There is always an instance per Work Proces w3wp.exe.
  • WebSite2 will have its own AppDomain and Hosting Environment.
  • Within a new AppDomain will be run instances of WebSite2 (HttpApplication instances).



It's very important to notice that each web application runs in a separate AppDomain so that if one fails or does something wrong, it won't affect the other web apps that can carry on their work. At this point, we should have another question:

What would happen if a Web Application, let's say WebSite1, does something wrong affecting the Worker Process (even if it's quite difficult)?


What if I want to recycle the application domain?

To summarize what we have said, an AppPool consists of one or more processes. Each web application that you are running consists of (usually, IIRC) an Application Domain. The issue is when you assign multiple web applications to the same AppPool, while they are separated by the Application Domain boundary, they are still in the same process (w3wp.exe). This can be less reliable/secure than using a separate AppPool for each web application. On the other hand, it can improve performance by reducing the overhead of multiple processes.

An Internet Information Services (IIS) application pool is a grouping of URLs that is routed to one or more worker processes. Because application pools define a set of web applications that share one or more worker processes, they provide a convenient way to administer a set of web sites and applications and their corresponding worker processes. Process boundaries separate each worker process; therefore, a web site or application in an application pool will not be affected by application problems in other application pools. Application pools significantly increase both the reliability and manageability of a web infrastructure.



I want to better understand the difference between an AppDomain and an Application Pool

Just for better understanding, let's say you are working with Internet Explorer. As you know, you can open more than one tab for browsing more than one web site in the same instance of IE.Let' say you open four tabs browsing different web sites, so that each tab will show a different web site.

After lots of pints of beer, let's assume that each tab is running within a different App Domain and each web site we are browsing is a different web app under IIS. All the web sites we are browsing are sharing the same instance of IE (iexplorer.exe). In this example, let's compare the IE instance (iexplorer.exe) to the ASP.NET Worker Process (w3wp.exe). If one tab is stuck for any reason (as sometime happens :-)), it's going to affect all the other tabs running under the same iexplorer.exe instance (some times, IE gets stuck and it doesn't respond to any interaction anymore, showing Not responding), so you are forced to kill the process to carry on working.

By killing the process, you will not able to browse any of the web sites you were browsing, even if it was just one process that made got IE stuck. So what can we do if we want to isolate web site browsing at process level so that if one web site does something wrong, we can carry on browsing the other web sites? Simple, you can open two instance of IE and open two tabs on each instance. In this case, two iexplore.exe instances will be running, and they will be completely independent of each other: if a tab is stuck on one instance of Internet Explorer, you can kill that process, but the other one will carry on to work.


ASP.NET Authentication And Authorization

Before proceeding ahead we need to understand four important vocabularies which you will see in this article again and again: - authentication, authorization, principal and identity. Let’s first start with authentication and authorization. If you search in www.google.com for the dictionary meaning of authentication and authorization, you will land up with something below:-

Authentication: - prove genuineness
Authorization: - process of granting approval or permission on resources.

The same dictionary meaning applies to ASP.NET as well. In ASP.NET authentication means to identify the user or in other words its nothing but to validate that he exists in your database and he is the proper user. Authorization means does he have access to a particular resource on the IIS website. A resource can be an ASP.NET web page, media files (MP4, GIF, JPEG etc), compressed file (ZIP, RAR) etc.

So the first process which happens is authentication and then authorization. Below is a simple graphical representation of authentication and authorization. So when the user enters ‘userid’ and ‘password’ he is first authenticated and identified by the user name.

Now when the user starts accessing resources like pages, ASP DOTNET authentication, videos etc, he is checked whether he has the necessary access for the resources. The process of identifying the rights for resources is termed as ‘Authorization’.                                       






Detecting authentication and authorization: - The principal and identity objects

At any moment of time if you want to know who the user is and what kind of authentication type he using you can use the identity object. If you want to know what kind of roles it’s associated with then we need to use the principal object. In other words to get authentication details we need to the identity object and to know about authorization details of that identity we need the principal object.













Types of authentication and authorization in ASP.NET

There are three ways of doing authentication and authorization in ASP.NET:-

• Windows authentication: - In this methodology ASP.NET web pages will use local windows users and groups to authenticate and authorize resources.

• Forms Authentication: - This is a cookie based authentication where username and password are stored on client machines as cookie files or they are sent through URL for every request. Form-based authentication presents the user with an HTML-based Web page that prompts the user for credentials.

• Passport authentication :- Passport authentication is based on the passport website provided
by the Microsoft .So when user logins with credentials it will be reached to the passport website ( i.e. hotmail,devhood,windows live etc) where authentication will happen. If Authentication is successful it will return a token to your website.

• Anonymous access: - If you do not want any kind of authentication then you will go for Anonymous access.

GenericPrincipal and GenericIdentity objects represent users who have been authenticated using Forms authentication or other custom authentication mechanisms. With these objects, the role list is obtained in a custom manner, typically from a database.
FormsIdentity and PassportIdentity objects represent users who have been authenticated with Forms and Passport authentication respectively.




Windows Authentication


When you configure your ASP.NET application as windows authentication it will use local windows user and groups to do authentication and authorization for your ASP.NET pages. Below is a simple snap shot which shows my windows users and roles on my computer.








5 steps to enable authentication and authorization using windows



We will do a small sample to get a grasp of how authentication and authorization works with windows. We will create 2 users one ‘Administrator’ and other a simple user with name ‘Shiv’. We will create two simple ASPX pages ‘User.aspx’ page and ‘Admin.aspx’ page. ‘Administrator’ user will have access to both ‘Admin.aspx’ and ‘User.aspx’ page , while user ‘Shiv’ will only have access to ‘User.aspx’ page.


Create a website - Step 1




The next step is to create a simple web site with 3 pages (User.aspx, Admin.aspx and Home.aspx) as shown below.




Creating user in windows directory - Step 2


The next step is we go to the windows directory and create two users. You can see in my computer we have ‘Administrator’ and ‘Shiv’.






 Setup We.Config file - Step 3 






 Setup Authorization - Step 4
 

We also need to specify the authorization part. We need to insert the below snippet in the ‘web.config’ file stating that only ‘Administrator’ users will have access to





 Setup Configure IIS - Step 5

The next step is to compile the project and upload the same on an IIS virtual directory. On the IIS virtual directory we need to ensure to remove anonymous access and check the integrated windows authentication as shown in the below figure.












Basic Authentication








We then copied the ‘Authorization:Basic’ data and ran the below program. LOL, we can see our windows userid and password.













Integrated Authentication




Integrated Windows authentication (formerly called NTLM, and also known as Windows NT Challenge/Response authentication) uses either Kerberos v5 authentication or NTLM authentication, depending upon the client and server configuration.

(The above paragraph is ripped from http://msdn.microsoft.com/en-us/library/ff647076.aspx  ).


Let’s try to understand what NTLM and Kerberos authentication is all about and then we will try to understand other aspects of integrated authentication.
NTLM is a challenge response authentication protocol. Below is how the sequence of events happens:-


• Client sends the username and password to the server.
• Server sends a challenge.
• Client responds to the challenge with 24 byte result.
• Servers checks if the response is properly computed by contacting the domain controller.
• If everything is proper it grants the request.














Order of Security Precedence

One of the things which you must have noticed is that integrated, digest and basic authentication are check boxes. In other words we can check all the three at one moment of time. If you check all the 3 options at one moment of time depending on browser security support one of the above methods will take precedence.






Let’s understand how the security precedence works as per browser security. 

• Browser makes a request; it sends the first request as Anonymous. In other words it does not send any credentials.

• If the server does not accept Anonymous IIS responds with an "Access Denied" error message and sends a list of the authentication types that are supported by the browser.

• If Windows NT Challenge/Response is the only one supported method then the browser must support this method to communicate with the server. Otherwise, it cannot negotiate with the server and the user receives an "Access Denied" error message.

• If Basic is the only supported method, then a dialog box appears in the browser to get the credentials, and then passes these credentials to the server. It attempts to send these credentials up to three times. If these all fail, the browser is not connected to the server.

• If both Basic and Windows NT Challenge/Response are supported, the browser determines which method is used. If the browser supports Windows NT Challenge/Response, it uses this method and does not fall back to Basic. If Windows NT Challenge/Response is not supported, the browser uses Basic.
You can read more about precedence from http://support.microsoft.com/kb/264921.

In order words the precedence is:-

1. Windows NT challenge ( Integrated security)
2. Digest
3. Basic










Forms Authentication



Forms authentication is a cookie/URL based authentication where username and password are stored on client machines as cookie files or they are sent encrypted on the URL for every request if cookies are not supported.

Below are the various steps which happen in forms authentication:-


• Step 1:- User enters “userid” and “password” through a custom login screen developed for authentication and authorization.

• Step 2:- A check is made to ensure that the user is valid. The user can be validated from ‘web.config’ files, SQL Server, customer database, windows active directory and various other kinds of data sources.

• Step 3:- If the user is valid then a cookie text file is generated on the client end. This cookie test file signifies that the user has been authenticated. Hence forth when the client computer browses other resources of your ASP.NET site the validation is not conducted again. The cookie file indicates that the user has logged in.








Form Authentication using Web.config as a data store




























Forms authentication using ASP.NET Membership and Role

















Forms Authentication using Single Sign On





Passport Authentication


Passport authentication is based on the passport website provided by the Microsoft .So when user logins with credentials it will be reached to the passport website ( i.e. hotmail,devhood,windows live etc) where authentication will happen. If Authentication is successful it will return a token to your website.

I am leaving this section for now, will update in more details soon.


ASP.NET Impersonation

 

Visual Studio .NET 2003

Another important security feature is the ability to control the identity under which code is executed. Impersonation is when ASP.NET executes code in the context of an authenticated and authorized client. By default, ASP.NET does not use impersonation and instead executes all code using the same user account as the ASP.NET process, which is typically the ASPNET account. This is contrary to the default behavior of ASP, which uses impersonation by default. In Internet Information Services (IIS) 6, the default identity is the NetworkService account.
Note   Impersonation can significantly affect performance and scaling. It is generally more expensive to impersonate a client on a call than to make the call directly.
Using impersonation, ASP.NET applications can optionally execute the processing thread using the identity of the client on whose behalf they are operating. You usually use impersonation for resource access control. Delegation is a more powerful form of impersonation and makes it possible for the server process to access remote resources while acting as the client. For more information, see ASP.NET Delegation.
Note   Impersonation is local to a particular thread. When code changes threads, such as when using thread pooling, the new thread executes using the process identity by default. When impersonation is required on the new thread, your application should save the security token (WindowsIdentity.Token Property) from the original thread as part of the state for the completion thread.
If you enable impersonation, ASP.NET can either impersonate the authenticated identity received from IIS or one specified in the application's Web.config file. You have the following three options when configuring impersonation:
  • Impersonation is disabled. This is the default setting. For backward compatibility with ASP, you must enable impersonation and change the ASP.NET process identity to use the Local System account. In this instance, the ASP.NET thread runs using the process token of the application worker process regardless of which combination of IIS and ASP.NET authentication is used. By default, the process identity of the application worker process is the ASPNET account. For more information, see ASP.NET Process Identity.
Copy
<identity impersonate="false" />
  • Impersonation enabled. In this instance, ASP.NET impersonates the token passed to it by IIS, which is either an authenticated user or the anonymous Internet user account (IUSR_machinename).
Copy
<identity impersonate="true" />
  • Impersonation enabled for a specific identity. In this instance, ASP.NET impersonates the token generated using an identity specified in the Web.config file.
Copy
<identity impersonate="true"
userName="domain\user"
password="password" />
If the application resides on a UNC share, ASP.NET always impersonates the IIS UNC token to access that share unless a configured account is used. If you provide an explicitly configured account, ASP.NET uses that account in preference to the IIS UNC token.
 
You should exercise care when using impersonation because it makes it possible for an application to potentially process code using permissions not anticipated by the application designer. For example, if your application impersonates an authenticated intranet user, that application possesses administrative privileges when impersonating a user with those privileges. Likewise, if the impersonated user possesses more restrictive permissions than anticipated, the user may not be able to use the application.




ASP.NET Application Life Cycle Overview for IIS 5.0 and 6.0



StageDescription
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.
clip_image001Note
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.
clip_image001[1]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.
The following diagram illustrates this relationship:
clip_image003
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.
clip_image001[2]Note
The first time an ASP.NET page or process is requested in an application, a new instance of HttpApplication is created. However, to maximize performance, HttpApplication instances might be reused for multiple 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:
clip_image005
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.



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


Item Description
App_GlobalResources The application's global resources are compiled and a resource assembly is built. Any assemblies in the application's Bin folder are linked to the resource assembly.
App_WebResources Proxy types for Web services are created and compiled. The resulting Web references assembly is 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_Code Source 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 files Skin 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. For more information, see How to: Precompile ASP.NET Web Site Projects.


ASP.NET Application Life Cycle Overview for IIS 7.0

A request in IIS 7.0 Integrated mode passes through stages that are like the stages of requests for ASP.NET resources in IIS 6.0. However, in IIS 7.0, these stages include several additional application events, such as the MapRequestHandler, LogRequest, and PostLogRequest events. 
 
The main difference in processing stages between IIS 7.0 and IIS 6.0 is in how ASP.NET is integrated with the IIS server. In IIS 6.0, there are two request processing pipelines. One pipeline is for native-code ISAPI filters and extension components. The other pipeline is for managed-code application components such as ASP.NET. In IIS 7.0, the ASP.NET runtime is integrated with the Web server so that there is one unified request processing pipeline for all requests. For ASP.NET developers, the benefits of the integrated pipeline are as follows:
 
· The integrated pipeline raises all the events that are exposed by the HttpApplication object, which enables existing ASP.NET HTTP modules to work in IIS 7.0 Integrated mode.
 
· Both native-code and managed-code modules can be configured at the Web server, Web site, or Web application level. This includes the built-in ASP.NET managed-code modules for session state, forms authentication, profiles, and role management. Furthermore, managed-code modules can be enabled or disabled for all requests, regardless of whether the request is for an ASP.NET resource like an .aspx file.
 
· Managed-code modules can be invoked at any stage in the pipeline. This includes before any server processing occurs for the request, after all server processing has occurred, or anywhere in between.
 
· You can register and enable or disable modules through an application’s Web.config file. 
 
The following illustration shows the configuration of an application's request pipeline. The example includes the following:
 
· The Anonymous native-code module and the Forms managed-code module (which corresponds to FormsAuthenticationModule). These modules are configured, and they are invoked during the Authentication stage of the request.
 
· The Basic native-code module and the Windows managed-code module (which corresponds to WindowsAuthenticationModule). They are shown, but they are not configured for the application.
 
· The Execute handler stage, where the handler (a module scoped to a URL) is invoked to construct the response. For aspx files, the PageHandlerFactory handler is used to respond to the request. For static files, the native-code StaticFileModule module responds to the request. 
 
· The Trace native-code module. This is shown, but it is not configured for the application.
· The Custom module managed-code class. It is invoked during the Log request stage. 



 
clip_image002



For information about known compatibility issues with ASP.NET applications that are being migrated from earlier versions of IIS to IIS 7.0, see the "Known Differences Between Integrated Mode and Classic Mode" section of Upgrading ASP.NET Applications to IIS 7.0: Differences between IIS 7.0 Integrated Mode and Classic mode.
clip_image003Life Cycle Stages





The following table lists the stages of the ASP.NET application life cycle with Integrated mode in IIS 7.0.

 
Stage Description
A request is made for an application resource. The life cycle of an ASP.NET application starts with a request sent by a browser to the Web server.
In Classic mode in IIS 7.0 and in IIS 6.0, the ASP.NET request pipeline is separate from the Web server pipeline. Modules apply only to requests that are routed to the ASP.NET ISAPI extension. If the file-name extension of the requested resource type is not explicitly mapped to ASP.NET, ASP.NET functionality is not invoked for the request because the request is not processed by the ASP.NET runtime.
In integrated mode in IIS 7.0, a unified pipeline handles all requests. When the integrated pipeline receives a request, the request passes through stages that are common to all requests. These stages are represented by the RequestNotification enumeration. All requests can be configured to take advantage of ASP.NET functionality, because that functionality is encapsulated in managed-code modules that have access to the request pipeline. For example, even though the .htm file-name extension is not explicitly mapped to ASP.NET, a request for an HTML page still invokes ASP.NET modules. This enables you to take advantage of ASP.NET authentication and authorization for all resources.
The unified pipeline receives the first request for the application. When the unified pipeline receives the first request for any resource in an application, an instance of the ApplicationManager class is created, which is the application domain that the request is processed in. Application domains provide isolation between applications for global variables and enable each application to be unloaded separately. In the application domain, an instance of the HostingEnvironment class is created, which provides access to information about the application, such as the name of the folder where the application is stored.
During the first request, top-level items in the application are compiled if required, which includes application code in the App_Code folder. You can include custom modules and handlers in the App_Code folder as described in Managed-code Modules in IIS 7.0 later in this topic.
Response objects are created for each request. After the application domain has been created and the HostingEnvironment object has been instantiated, application objects such as HttpContext, HttpRequest, and HttpResponse are created and initialized. 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, which includes cookies and browser information. The HttpResponse object contains the response that is sent to the client, which includes all the rendered output and cookies.
The following are some key differences between IIS 6.0 and IIS 7.0 running in Integrated mode and with the .NET Framework 3.0 or later:
· The SubStatusCode property of the HttpResponse object is available for setting codes that are useful for failed-request tracing. For more information, see Troubleshooting Failed Requests Using Failed Request Tracing in IIS 7.0.
· The Headers property of the HttpResponse object provides access to response headers for the response.
· Two properties of the HttpContext object, IsPostNotification and CurrentNotification, are used when one event handler handles several HttpApplication events.
· The Headers and ServerVariables property of the HttpRequest object are write-enabled.
An HttpApplication object is assigned to the request After all 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. It then uses the derived class to represent the application.
clip_image003[1]Note
The first time that an ASP.NET page or process is requested in an application, a new instance of the HttpApplication class is created. However, to maximize performance, HttpApplication instances might be reused for multiple requests.
Which ASP.NET modules are loaded (such as the SessionStateModule) depends on the managed-code modules that the application inherits from a parent application. It also depends on which modules are configured in the configuration section of the application's Web.config file. Modules are added or removed in the application's Web.config modules element in the system.webServer section. For more information, see How to: Configure the <system.webServer> Section for IIS 7.0.
The request is processed by the HttpApplication pipeline. The following tasks are performed by the HttpApplication class while the request is being processed. The events are useful for page developers who want to run code when key request pipeline events are raised. They are also useful if you are developing a custom module and you want the module to be invoked for all requests to the pipeline. Custom modules implement the IHttpModule interface. In Integrated mode in IIS 7.0, you must register event handlers in a module's Init method.
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 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. Raise the MapRequestHandler event. An appropriate handler is selected based on the file-name extension of the requested resource. The handler can be a native-code module such as the IIS 7.0 StaticFileModule or a managed-code module such as the PageHandlerFactory class (which handles .aspx files).
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 LogRequest event.
23. Raise the PostLogRequest event.
24. Raise the EndRequest event.
25. Raise the PreSendRequestHeaders event.
26. Raise the PreSendRequestContent event.

 
   
 

Page life cycle in IIS Integrated mode

Ex:
 
In Integrated mode, the ASP.NET request-processing stages that are exposed to modules are directly connected to the corresponding stages of the IIS 7 pipeline. The complete pipeline contains the following stages, which are exposed as HttpApplication events in ASP.NET:
1. BeginRequest. The request processing starts.
2. AuthenticateRequest. The request is authenticated. IIS 7 and ASP.NET authentication modules subscribe to this stage to perform authentication.
3. PostAuthenticateRequest.
4. AuthorizeRequest. The request is authorized. IIS 7 and ASP.NET authorization modules check whether the authenticated user has access to the resource requested.
5. PostAuthorizeRequest.
6. ResolveRequestCache. Cache modules check whether the response to this request exists in the cache, and return it instead of proceeding with the rest of the execution path. Both ASP.NET Output Cache and IIS 7 Output Cache features execute.
7. PostResolveRequestCache.
8. MapRequestHandler. This stage is internal in ASP.NET and is used to determine the request handler.
9. PostMapRequestHandler.
10. AcquireRequestState. The state necessary for the request execution is retrieved. ASP.NET Session State and Profile modules obtain their data.
11. PostAcquireRequestState.
12. PreExecuteRequestHandler. Any tasks before the execution of the handler are performed.
13. ExecuteRequestHandler. The request handler executes. ASPX pages, ASP pages, CGI programs, and static files are served.
14. PostExecuteRequestHandler
15. ReleaseRequestState. The request state changes are saved, and the state is cleaned up here. ASP.NET Session State and Profile modules use this stage for cleanup.
16. PostReleaseRequestState.
17. UpdateRequestCache. The response is stored in the cache for future use. The ASP.NET Output Cache and IIS 7 Output Cache modules execute to save the response to their caches.
18. PostUpdateRequestCache.
19. LogRequest. This stage logs the results of the request, and is guaranteed to execute even if errors occur.
20. PostLogRequest.
21. EndRequest. This stage performs any final request cleanup, and is guaranteed to execute even if errors occur.
By using the familiar ASP.NET APIs, the ability to execute in the same stages as IIS 7 modules makes tasks that were only previously accessible in native ISAPI filters and extensions now possible in managed code.
For example, you can now write modules that do the following:
1. Intercept the request before any processing has taken place, for example rewriting URLs or performing security filtering.
2. Replace built-in authentication modes.
3. Modify the incoming request contents, such as request headers.
4. Filter outgoing responses for all content types.
See Developing an IIS 7 Module with .NET for a good example of how to extend IIS 7 with a custom ASP.NET authentication module.



Expanded ASP.NET APIs 
 
The ASP.NET APIs remain backward compatible with previous releases, which allows existing modules to work in IIS 7 without modification, and to apply to all application content without code changes. 
 
However, modules that are written for IIS 7 Integrated mode can take advantage of a few additional APIs to enable key request-processing scenarios that were not previously available. 
 
The new HttpResponse.Headers collection allows modules to inspect and manipulate response headers that other application components generate. For example, you can change the Content-Type header that is generated by an ASP page to prompt a download dialog box in the browser. The Cookies collection on the HttpResponse class is also enhanced to allow modification of cookies that are generated as part of the request processing, even if they were created outside of ASP.NET. 
 
The HttpRequest.Headers collection is write-enabled, which allows modules to manipulate the incoming request headers. Use this to change the behavior of other server components – for example, you can force a localized application to respond to the client in a different language by dynamically changing the value of the Accept-Language header. 
 
Finally, the HttpRequest.ServerVariables collection is now writeable, which allows IIS 7 server variables to be set. ASP.NET modules use this functionality to change values that are provided by IIS 7, and to create new server variables that are visible to other application frameworks, like PHP.

Runtime Integration 
 
In addition to the new APIs, Integrated mode enables existing ASP.NET functionality to provide more value to your application. 
 
The tracing facilities that are provided by ASP.NET, including the System.Diagnostics.Trace class and the ASP.NET page tracing feature, now emit trace information into the IIS 7 trace system. This enables the trace information that is generated during request processing by both IIS 7 and ASP.NET components to be placed in a single log file, facilitating better diagnostics of server issues. 
 
The ASP.NET response-filtering feature, which allows responses to be changed by using a Stream interface before it goes to the client, is enhanced to allow filtering of non-ASP.NET content. Therefore, you can use ASP.NET filtering on all server content, or selectively install the filter only for requests to content that you want to process. With this capability, you can write filtering features that inject or censor certain content in the site's responses, regardless of whether this content comes from an ASPX page or a static file.
image





Exploring Session in ASP.NET


Introduction

This article will give you a very good understanding of session. In this article, I have covered the basics of session, different ways of storing session objects, session behaviour in web farm scenarios, session on Load Balancer, etc. I have also explained details of session behaviour in a live production environment. Hope you will enjoy this article and provide your valuable suggestions and feedback.

What is Session?

Web is stateless, which means a new instance of a web page class is re-created each time the page is posted to the server. As we all know, HTTP is a stateless protocol, it can't hold client information on a page. If the user inserts some information and move to the next page, that data will be lost and the user would not be able to retrieve that information. What do we need here? We need to store information. Session provides a facility to store information on server memory. It can support any type of object to store along with our own custom objects. For every client, session data is stored separately, which means session data is stored on a per client basis. Have a look at the following diagram:

image
Fig: For every client, session data is stored separately


State management using session is one of the best ASP.NET features, because it is secure, transparent from users, and we can store any kind of object in it. Along with these advantages, some times session can cause performance issues in high traffic sites because it is stored in server memory and clients read data from the server. Now let's have a look at the advantages and disadvantages of using session in our web applications.

Advantages and disadvantages of Session?


Following are the basic advantages and disadvantages of using session. I have describe in details with each type of session at later point of time.
 

Advantages:

· It helps maintain user state and data all over the application.
· It is easy to implement and we can store any kind of object.
· Stores client data separately.
· Session is secure and transparent from the user.
 

Disadvantages:

· Performance overhead in case of large volumes of data/user, because session data is stored in server memory.
· Overhead involved in serializing and de-serializing session data, because in the case of StateServer and SQLServer session modes, we need to serialize the objects before storing them.
Besides these, there are many advantages and disadvantages of session that are based on the session type. I have discussed all of them in the respective sections below.

Storing and retrieving values from Session

Storing and retrieving values in session are quite similar to that in ViewState. We can interact with session state with the System.Web.SessionState.HttpSessionState class, because this provides the built-in session object in ASP.NET pages.
The following code is used for storing a value to session:
clip_image002Collapse | Copy Code
//Storing UserName in Session
Session["UserName"] = txtUser.Text;
Now, let's see how we can retrieve values from session:
 
 
clip_image002[1]Collapse | Copy Code
//Check weather session variable null or not
if (Session["UserName"] != null)
{
//Retrieving UserName from Session
lblWelcome.Text = "Welcome : " + Session["UserName"];
}
else
{
//Do Something else
}
We can also store other objects in session. The following example shows how to store a DataSet in session.
 
 
clip_image002[2]Collapse | Copy Code
//Storing dataset on Session
Session["DataSet"] = _objDataSet;
The following code shows how we to retrieve that DataSet from session:
 
 
clip_image002[3]Collapse | Copy Code
//Check weather session variable null or not
if (Session["DataSet"] != null)
{
//Retrieving UserName from Session
DataSet _MyDs = (DataSet)Session["DataSet"];
}
else
{
//Do Something else
}
 
References:
· MSDN (read the session variable section)



Session ID


ASP.NET uses a 120 bit identifier to track each session. This is secure enough and can't be reverse engineered. When a client communicates with a server, only the session ID is transmitted between them. When the client requests for data, ASP.NET looks for the session ID and retrieves the corresponding data. This is done in the following steps:

· Client hits the web site and information is stored in the session.
· Server creates a unique session ID for that client and stores it in the Session State Provider.
· The client requests for some information with the unique session ID from the server.
· Server looks in the Session Providers and retrieves the serialized data from the state server and type casts the object.
Take a look at the the pictorial flow:

clip_image002
Fig: Communication of client, web server, and State Provider


Session Mode and State Provider


In ASP.NET, there are the following session modes available:
· InProc
· StateServer
· SQLServer
· Custom
For every session state, there is a Session Provider. The following diagram will show you how they are related:

clip_image002[6]
Fig: Session state architecture


We can choose the session state provider based on which session state we are selecting. When ASP.NET requests for information based on the session ID, the session state and its corresponding provider are responsible for sending the proper information. The following table shows the session mode along with the provider name:

Session State Mode State Provider
InProc In-memory object
StateServer Aspnet_state.exe
SQLServer Database
Custom Custom provider
 
Apart from that, there is another mode Off. If we select this option, the session will be disabled for the application. But our objective is to use session, so we will look into the above four session state modes.


Session States

Session state essentially means all the settings that you have made for your web application for maintaining the session. Session State itself is a big thing. It says all about your session configuration, either in the web.config or from the code-behind. In the web.config, <SessionState> elements are used for setting the configuration of the session. Some of them are Mode, Timeout, StateConnectionString, CustomProvider, etc. I have discussed about each and every section of the connection string. Before I discuss Session Mode, take a brief overview of session events.

image
 
References:
· Application and Session Events

Session Mode

I have already discussed about session modes in ASP.NET. Following are the different types of session modes available in ASP.NET:
· Off
· InProc
· StateServer
· SQLServer
· Custom
If we set session Mode="off" in web.config, session will be disabled in the application. For this, we need to configure web.config the following way:
 
clip_image002[8]


InProc Session Mode

This is the default session mode in ASP.NET. Its stores session information in the current Application Domain. This is the best session mode for web application performance. But the main disadvantage is that, it will lose data if we restart the server. There are some more advantages and disadvantages of the InProc session mode. I will come to those points later on.

Overview of InProc session mode

As I have already discussed, in InProc mode, session data will be stored on the current application domain. So it is easily and quickly available.

clip_image002[10]
 
InProc session mode stores its session data in a memory object on the application domain. This is handled by a worker process in the application pool. So if we restart the server, we will lose the session data. If the client request for data, the state provider read the data from an in-memory object and returns it to the client. In web.config, we have to mention the session mode and also set the timeout.
clip_image004
 
The above session timeout setting keeps the session alive for 30 minute. This is configurable from the code-behind too.
 
clip_image006Collapse | Copy Code
Session.TimeOut=30;
There are two types of session events available in ASP.NET: Session_Start() and Session_End and this is the only mode that supports the Session_End() event. This event is called after the session timeout period is over. The general flow for the InProc session state is like this:

clip_image002[12]
 
When the Session_End() is called depends on the session timeout. This is a very fast mechanism because no serialization occurs for storing and retrieving data, and data stays inside the same application domain.

When should we use the InProc session mode?
InProc is the default session mode. It can be very helpful for a small web site and where the number of users is very less. We should avoid InProc in a Web Garden scenario (I will come to this topic later on).

Advantages and disadvantages
Advantages:
· It store session data in a memory object of the current application domain. So accessing data is very fast and data is easily available.
· There is not requirement of serialization to store data in InProc session mode.
· Implementation is very easy, similar to using the ViewState.
 
Disadvantages:
Although InProc session is the fastest, common, and default mechanism, it has a lot of limitations:
· If the worker process or application domain is recycled, all session data will be lost.
· Though it is the fastest, more session data and more users can affect performance, because of memory usage.
· We can't use it in web garden scenarios.
· This session mode is not suitable for web farm scenarios.
As per the above discussion, we can conclude that InProc is a very fast session storing mechanism but suitable only for small web applications. InProc session data will get lost if we restart the server, or if the application domain is recycled. It is also not suitable for Web Farm and Web Garden scenarios.

StateServer Session Mode


Overview of StateServer session mode

This is also called Out-Proc session mode. StateServer uses a stand-alone Windows Service which is independent of IIS and can also be run on a separate server. This session state is totally managed by aspnet_state.exe. This server may run on the same system, but it's outside of the main application domain where your web application is running. This means if you restart your ASP.NET process, your session data will still be alive. This approaches has several disadvantages due to the overhead of the serialization and de-serialization involved, it also increases the cost of data access because every time the user retrieves session data, our application hits a different process.

image



Configuration for StateServer session mode

In StateServer mode, session data is stored in a separate server which is independent of IIS and it is handled by aspnet_state.exe. This process is run as a Windows Service. You can start this service from the Windows MMC or from the command prompt.
clip_image002[14]
By default, the "Startup Type" of the ASP.NET state service is set to Manual; we have to set it to Automatic.
clip_image004[5]
 
From the command prompt, just type "net start aspnet_state". By default, this service listens to TCP port 42424, but we can change the port from the Registry editor as show in the picture below:
 
clip_image006
 
Now have a look at the web.config configuration for the StateServer setting. For the StateServer setting, we need to specify the stateConnectionString. This will identify the system that is running the state server. By default, stateConnectionString used the IP 127.0.0.1 (localhost) and port 42424.
 
clip_image008
 
When we are using StateServer, we can configure the stateNetworkTimeOut attribute to specify the maximum number of seconds to wait for the service to respond before canceling the request. The default timeout value is 10 seconds.
 
clip_image010
For using StateServer, the object which we are going to store should be serialized, and at the time of retrieving, we need to de-serialize it back. I have described this below with an example.


How the StateServer Session Mode works
We use the StateServer session mode to avoid unnecessary session data loss when restarting our web server. StateServer is maintained by the aspnet_state.exe process as a Windows service. This process maintains all the session data. But we need to serialize the data before storing it in StateServer session mode.
 
clip_image002[16]
 
As shown in the above figure, when the client sends a request to the web server, the web server stores the session data on the state server. The StateServer may be the current system or a different system. But it will be totally independent of IIS. The destination of the StateServer will depend on the web.config stateConnectionString setting. If we set it to 127.0.0.1:42424, it will store data in the local system itself. For changing the StateServer destination, we need to change the IP, and make sure aspnet_state.exe is up and running on that system. Otherwise you will get the following exception while trying to store data on session.




clip_image002[18]
 
When we are storing an object on session, it should be serialized. That data will be stored in the StateServer system using the State Provider. And at the time of retrieving the data, the State Provider will return the data. The complete flow is given in the picture below:
 
clip_image004[7]


Example of StateServer Session Mode
 
Here is a simple example of using the StateServer session mode. I have created this sample web application directly on IIS so that we can easily understand its usage.
Step 1: Open Visual Studio > File > New > Web Sites. Choose Location as HTTP and create the web application.
clip_image002[20]
Now if you open IIS, you will see a virtual directory created with the name of your web application, in my case it is StateServer.
clip_image004[9]
 
Step 2: Create s simple UI that will take the roll number and the name of a student. We will store the name and roll number in a state server session. I have also created a class StudentInfo. This class is listed below:
 
clip_image006[4]Collapse | Copy Code
[Serializable]
public class StudentInfo
{
//Default Constructor
public StudentInfo()
{
}
/// <summary>
/// Create object of student Class
/// </summary>
/// <param name="intRoll">Int RollNumber</param>
/// <param name="strName">String Name</param>
public StudentInfo(int intRoll, string strName)
{
this.Roll = intRoll;
this.Name = strName;
}
private int intRoll;
private string strName;
public int Roll
{
get
{
return intRoll;
}
set
{
intRoll = value;
}
}
public string Name
{
get
{
return strName;
}
set
{
strName = value;
}
}
}
Now have a look at the code-behind. I have added two buttons: one for storing session and another for retrieving session.
clip_image006[5]Collapse | Copy Code
protected void btnSubmit_Click(object sender, EventArgs e)
{
StudentInfo _objStudentInfo =
new StudentInfo(Int32.Parse( txtRoll.Text) ,txtUserName.Text);
Session["objStudentInfo"] = _objStudentInfo;
ResetField();
}
protected void btnRestore_Click(object sender, EventArgs e)
{
StudentInfo _objStudentInfo = (StudentInfo) Session["objStudentInfo"];
txtRoll.Text = _objStudentInfo.Roll.ToString();
txtUserName.Text = _objStudentInfo.Name;
}
 
Step 3: Configure your web.config for state server as I have already explained. And please make sure aspnet_state.exe is up and running on the configured server.
 
Step 4: Run the application.
clip_image008[5]
Enter the data, click on Submit.
There are the following tests that I have made which will totally explain how exactly StateServer is useful.
First: Remove the [Serializable ] keyword from the StudentInfo class and try to run the application. When you click on the Submit button, you will get the following error:
clip_image010[5]
Which clearly says that you have to serialize the object before storing it.
Second: Run the application, store data by clicking on the Submit button. Restart IIS.
clip_image012
In the case of InProc, you will have already lost your session data, but with StateServer, click on Restore Session and you will get your original data, because StateServer data does not depend on IIS. It keeps it separately.
Third: Stop aspnet_state.exe from the Windows Services MMC and submit the data. You will get the following error:
clip_image014
because your State Server process is not running. So please keep in mind these three points when using StateServer mode.
Advantages and Disadvantages
Based on the above discussion:
 
Advantages:
· It keeps data separate from IIS so any issues with IIS will not hamper session data.
· It is useful in web farm and web garden scenarios.
 
Disadvantages:
· Process is slow due to serialization and de-serialization.
· State Server always needs to be up and running.
I am stopping here on StateServer, you will find some more interesting points on it in the Load Balancer, Web Farm, and Web Garden section.
 
References:
· State Server Session Mode
· ASP.NET Session State



SQLServer Session Mode


Overview of SQL Server Session Mode
This session mode provide us more secure and reliable session management in ASP.NET. In this session mode, session data is serialized and stored in A SQL Server database. The main disadvantage of this session storage method is the overhead related with data serialization and de-serialization. It is the best option for using in web farms though.
clip_image002[22]
To setup SQL Server, we need these SQL scripts:
· For installing: InstallSqlState.sql
· For uninstalling: UninstallSQLState.sql
The easiest way to configure SQL Server is using the aspnet_regsql command.
I have explained in detail the use of these files in the configuration section. This is the most useful state management in web farm scenarios.
 
When should we use SQLServer Session Mode?
· SQL Server session mode is a more reliable and secure session state management.
· It keeps data in a centralized location (database).
· We should use the SQLServer session mode when we need to implement session with more security.
· If there happens to be frequent server restarts, this is an ideal choice.
· This is the perfect mode for web farm and web garden scenarios (I have explained this in detail later).
· We can use SQLServer session mode when we need to share session between two different applications.
 
Configuration for SQLServer Session Mode
In SQLServer session mode, we store session data in SQL Server, so we need to first provide the database connection string in web.config. The sqlConnectionString attribute is used for this.
After we setup the connection string, we need to configure the SQL Server. I will now explain how to configure your your SQL Server using the aspnet_regsql command.
Step 1: From command prompt, go to your Framework version directory. E.g.: c:\windows\microsoft.net\framework\<version>.
Step 2: Run the aspnet_regsql command with the following parameters:
clip_image004
Have a look at the parameters and their uses:
Parameters Description
-ssadd Add support for SQLServer mode session state.
-sstype p P stands for Persisted. It persists the session data on the server.
-S Server name.
-U User name.
-P Password.
After you run the command, you will get the following message:
clip_image006[8]
That's all.
Step 3: Open SQL Server Management Studio, check if a new database ASPState has been created, and there should be two tables:
· ASPStateTempApplications
· ASPStateTempSessions
clip_image008[7]
Change the configuration string of the StateServer example and run the same sample application.
Just store the roll number and user name and click on the Submit button. Open the ASPStateTempSessions table from SQL Server Management Studio.. here is your session data:
clip_image010
Now do the following test that I have already explained in the StateServer mode section:
1. Remove the Serialize keyword from the StydentInfo class
2. Reset IIS and click on Restore Session
3. Stop SQL Server Services
I think I have explained the SQLServer session mode well.
Advantages and Disadvantages
Advantages:
· Session data not affected if we restart IIS.
· The most reliable and secure session management.
· It keeps data located centrally, is easily accessible from other applications.
· Very useful in web farms and web garden scenarios.
Disadvantages:
· Processing is very slow in nature.
· Object serialization and de-serialization creates overhead for the application.
· As the session data is handled in a different server, we have to take care of SQL Server. It should be always up and running.
References:
· Read more about SQLServer mode


Custom Session Mode

Overview of Custom Session Mode
Commonly we use the InProc, StateServer, or SQLServer session modes for our application, but we also need to know the fundamentals of the Custom session mode. This session mode is quite interesting, because Custom session gives full control to us to create everything, even the session ID. You can write your own algorithm to generate session IDs.
You can implement custom providers that store session data in other storage mechanisms simply by deriving from the SessionStateStoreProviderBase class. You can also generate a new session ID by implementing ISessionIDManager.
These are the methods called during the implementation of Custom session:
clip_image002[24]
In the Initialize method, we can set a custom provider. This will initialize the connection with that provider. SetItemExpireCallback is used to set SessionTimeOut. We can register a method that will be called at the time of session expiration. InitializeRequest is called on every request and CreateNewStoreData is used to create a new instance of SessionStateStoreData.
 
When should we use Custom Session Mode?
We can use Custom session mode in the following cases:
· We want to store session data in a place other than SQL Server.
· When we have to use an existing table to store session data.
· When we need to create our own session ID.
 
What configuration do we need for it?
We need to configure our web.config like this:
clip_image004[11]
If you want to explore this more, please check the References section.
 
Advantages and Disadvantages
 
Advantages:
· We can use an existing table for storing session data. This is useful when we have to use an existing database.
· It's not dependent on IIS, so restarting the web server does not have any effect on session data.
· We can crate our own algorithm for generating session ID.
 
Disadvantages:
· Processing of data is very slow.
· Creating a custom state provider is a low-level task that needs to be handled carefully to ensure security.
It is always recommended to use a third party provider rather than create your own.
 
References:













Overview of production deployment

Production environments are where we deploy our applications on a live production server. It is a major and big challenge for web developers to deploy their applications on a live server, because in a big production environment, there are a large number of users and it is hard to handle the load for so many users with a single server. Here comes in the concepts of Web Farm, Load Balancer, Web Garden, etc.
Just a few months back, I deployed a web application in a live production environment which is accessed by millions of user and there were more than 10 Active Directory instances, more than 10 web servers over a Load Balancer, and several database server, Exchange Server, LCS Server, etc. The major risk involved in multiple servers is session management. The following picture shows a general diagram of production environments:
 
clip_image002[26]
I will try to explain the different scenarios that you need to keep in mind while deploying your application.
 
 

Application Pool

This is one of the most important things you should create for your applications in a production environment. Application pools are used to separate sets of IIS worker processes that share the same configuration. Application pools enable us to isolate our web application for better security, reliability, and availability. The worker process serves as the process boundary that separates each application pool so that when one worker process or application has an issue or is recycled, other applications or worker processes are not affected.
clip_image004[13]
 
Identity of Application Pool
Application pool identity configuration is an important aspect of security in IIS 6.0 and IIS 7.0, because it determines the identity of the worker process when the process is accessing a resource. In IIS 7.0, there are three predefined identities that are the same as in IIS 6.0.
Application Pool Identity Description
LocalSystem Built-in account that has administrative privileges on the server. It can access both local and remote resources. For any kind accessing of server files or resources, we have to set the identity of the application pool to LocalSystem.
LocalServices Built-in account has privileges of an authenticated local user account. It does not have any network access permission.
NetworkServices This is the default identity of Application Pool. NetworkServices has the privileges of an authenticated local user account.
 
Creating and assigning Application Pool
Open IIS Console, right click on Application Pool Folder > Create New.
clip_image006[5]
 
Give the Application Pool ID and click OK.
clip_image008[9]
 
Now, right click on the Virtual Directory (I am using StateServer web sites) and assign StateServerAppPool to the StateServer Virtual Directory.
 
clip_image010[7]
So this StateServer web site will run independently with StateServerAppPool. Any problem related with other applications will not affect this application. This is the main advantage of creating application pools separately.
 

Web Garden

By default, each application pool runs with a single worker process (W3Wp.exe). We can assign multiple worker processes with a single application pool. An application pool with multiple worker processes is called a Web Garden. Many worker processes with the same Application Pool can sometimes provide better throughput performance and application response time. And each worker process should have its own Thread and memory space.
clip_image012[5]
As shown in the picture, in IIS, there may be multiple application pools and each application pool will have at least one worker process. A Web Garden should contain multiple worker processes.
There are certain restrictions in using a Web Garden with your web application. If we use the InProc session mode, our application will not work correctly because the session will be handled by a different worker process. To avoid this problem, we should use the OutProc session mode and we can use a session state server or SQL-Server session state.
Main advantage: The worker processes in a Web Garden share the requests that arrive for that particular application pool. If a worker process fails, another worker process can continue processing the requests.
How to Create a Web Garden?
Right click on Application Pool > Go to Performance tab > Check Web Garden section (highlighted in picture):
clip_image014[5]
By default, it would be 1. Just change it to more than one.
How Session depends on Web Garden?
I have already explained that InProc is handled by a worker process. It keeps data inside its memory object. Now if we have multiple worker processes, then it would be very difficult to handle the session because each and every worker process has its own memory, so if my first request goes to WP1 and it keeps my session data and the second request goes to WP2, I am trying to retrieve session data and it will not be available, which will throw an error. So please avoid Web Gardens in InProc session mode.
We can use StateServer or SQLServer session modes in Web Gardens because as I have already explained, these two session modes do not depend on worker processes. In my example, I have also explained that if you restart IIS, you are still able to access your session data.
In short:
Session Mode Recommended
InProc No
StateServer Yes
SQLServer Yes

 

 

Web Farm and Load Balancer

This is the most common terms that are used in production deployments. These terms come in when we are using multiple web servers for deploying our applications. The main reason for using these is we have to distribute the load over multiple servers. A Load Balancer is used to distribute the load on multiple servers.
clip_image015
If we take a look at the above diagram, the client request the URL and it will hit a Load Balancer, which decides which server to access. The load balancer will distribute the traffic over all the different web servers.
 
Now how does this affect Session?
Handling Session in web farm and load balancer scenarios
Handling session is one of the most challenging jobs in a web farm.
InProc: In InProc session mode, session data is stored in an in-memory object of the worker process. Each server will have its own worker process and will keep session data inside its memory.
clip_image017
If one server is down, and if the request goes to a different server, the user is not able to get session data. So it is not recommended to use InProc in Web Farms.
 
StateServer: I have already explained what a state server is and how to configure a state server, etc. For web farm scenarios, you can easily understand how much this is important because all session data will be stored in a single location.
 
clip_image019
Remember, in a web farm, you have to make sure you have the same <machinekey> in all your web servers. Other things are the same as I have describe earlier. All web.config files will have the same configuration (stateConnectionString) for session state.
 
SQL Server: This is another approach, the best that we can use in a web farm. We need to configure the database first. The required steps have been explained covered.
clip_image021
As shown in the above picture, all web server session data will be stored in a single SQL Server database. And it is easily accessible. Keep one thing in mind, you should serialize objects in both StateServer and SQLServer modes. If one of the web servers go down, the load balancer will distribute the load to other servers and the user will still be able to read session data from the server, because data is stored in a centralized database server.
In summary, we can use either StateServer or SQLServer session mode in a web farm. We should avoid InProc.


Session and Cookies

Clients use cookies to work with session. Because clients need to present the appropriate session ID with each request. We can do this in the following ways:
Using cookies
ASP.NET creates a special cookie named ASP.NET_SessionId automatically when a session collection is used. This is the default. Session ID is transmitted through that cookie.
cookie is a small bit of text that accompanies requests and pages as they go between the Web server and browser. The cookie contains information the Web application can read whenever the user visits the site.
For example, if a user requests a page from your site and your application sends not just a page, but also a cookie containing the date and time, when the user's browser gets the page, the browser also gets the cookie, which it stores in a folder on the user's hard disk.
Later, if user requests a page from your site again, when the user enters the URL the browser looks on the local hard disk for a cookie associated with the URL. If the cookie exists, the browser sends the cookie to your site along with the page request. Your application can then determine the date and time that the user last visited the site. You might use the information to display a message to the user or check an expiration date.
Cookies are associated with a Web site, not with a specific page, so the browser and server will exchange cookie information no matter what page the user requests from your site. As the user visits different sites, each site might send a cookie to the user's browser as well; the browser stores all the cookies separately.
Cookies help Web sites store information about visitors. More generally, cookies are one way of maintaining continuity in a Web application—that is, of performing state management. Except for the brief time when they are actually exchanging information, the browser and Web server are disconnected. Each request a user makes to a Web server is treated independently of any other request. Many times, however, it's useful for the Web server to recognize users when they request a page. For example, the Web server on a shopping site keeps track of individual shoppers so the site can manage shopping carts and other user-specific information. A cookie therefore acts as a kind of calling card, presenting pertinent identification that helps an application know how to proceed.
Cookies are used for many purposes, all relating to helping the Web site remember users. For example, a site conducting a poll might use a cookie simply as a Boolean value to indicate whether a user's browser has already participated in voting so that the user cannot vote twice. A site that asks a user to log on might use a cookie to record that the user already logged on so that the user does not have to keep entering credentials.
 
 
Cookie Limitations
Most browsers support cookies of up to 4096 bytes. Because of this small limit, cookies are best used to store small amounts of data, or better yet, an identifier such as a user ID. The user ID can then be used to identify the user and read user information from a database or other data store. (See the section "Cookies and Security" below for information about security implications of storing user information.)
Browsers also impose limitations on how many cookies your site can store on the user's computer. Most browsers allow only 20 cookies per site; if you try to store more, the oldest cookies are discarded. Some browsers also put an absolute limit, usually 300, on the number of cookies they will accept from all sites combined.
A cookie limitation that you might encounter is that users can set their browser to refuse cookies. If you define a P3P privacy policy and place it in the root of your Web site, more browsers will accept cookies from your site. However, you might have to avoid cookies altogether and use a different mechanism to store user-specific information. A common method for storing user information is session state, but session state depends on cookies, as explained later in the section "Cookies and Session State."
 
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.
 
image
 
 
Cookies with More Than One Value
You can store one value in a cookie, such as user name and last visit. You can also store multiple name-value pairs in a single cookie. The name-value pairs are referred to as subkeys. (Subkeys are laid out much like a query string in a URL.) For example, instead of creating two separate cookies named userName and lastVisit, you can create a single cookie named userInfo that has the subkeys userName and lastVisit.
You might use subkeys for several reasons. First, it is convenient to put related or similar information into a single cookie. In addition, because all the information is in a single cookie, cookie attributes such as expiration apply to all the information. (Conversely, if you want to assign different expiration dates to different types of information, you should store the information in separate cookies.)
 
image
 
 
Reading Cookies
When a browser makes a request to the server, it sends the cookies for that server along with the request. In your ASP.NET applications, you can read the cookies using the HttpRequest object, which is available as the Request property of your Page class. The structure of the HttpRequest object is essentially the same as that of the HttpResponse object, so you can read cookies out of the HttpRequest object much the same way you wrote cookies into the HttpResponse object. The following code example shows two ways to get the value of a cookie named username and display its value in a Label control:
 
image
 
 
Cookie munging
Some older browsers do not support cookies or the user may disable cookies in the browser, in that case, ASP.NET transmits session ID in a specially modified (or “munged”) URL.
 
image
 
 
How Cookie Munging works?
When the user requests for a page on a server, the server encoded the session ID and adds it with every HREF link in the page. When the user clicks on a link, ASP.NET decodes that session ID and passes it to the page that the user is requesting. Now the requesting page can retrieve session variables. This all happens automatically if ASP.NET detects that the user's browser does not support cookies.
 
How to implement Cookie Munging?
For this, we have to make our session state cookie-less.
Ex: <SesstionState Cookieless=”true”></SesstionState>
 
Removing Session
Following are the list of methods that are used to remove Session:
Method Description
Session.Remove(strSessionName); Removes an item from the session state collection.
Session.RemoveAll() Removes all items from the session collection.
Session.Clear() Remove all items from session collection. Note: There is no difference between Clear and RemoveAll. RemoveAll() calls Clear() internally.
Session.Abandon() Cancels the current session.
 
Enabling and disabling Session
For performance optimization, we can enable or disable session because each and every page read and write access of the page involves some performance overhead. So it is always better to enable and disable session based on requirements rather than enable it always. We can enable and disable session state in two ways:
· Page level
· Application level
 
Page level
We can disable session state in page level using the EnableSessionState attribute in the Page directive.
clip_image002[28]
This will disable the session activities for that particular page.
The same way, we can make it read-only also. This will permit to access session data but will not allow writing data on session.
clip_image004[15]
 
Application level
Session state can be disabled for the entire web application using the EnableSessionState property in Web.Config.
clip_image006[7]
Generally we use page level because some pages may not require any session data or may only read session data.




Introduction

This article is a beginner's tutorial on ASP.NET caching mechanism. We will try to see different types of caching available in ASP.NET and which caching technique is right for which scenario. We will also try to see how can we customize the caching behaviour so that it suits our needs.
 

Background

As ASP.NET web developers, we are mostly involved in developing web pages that are dynamic, i.e., contents coming from databases, Server directories, XML files or getting pulled from some other websites. Caching means to store something in memory that is being used frequently to provide better performance. Now can we think of the usability of caching in ASP.NET.
Let us imagine a scenario when the contents of a web page are being pulled from a database. The user asks for contents depending on some criteria. Now if the database is getting changed very frequently that even between two requests of same user, we anticipate database change, then we can in no way cache the data that the user is requesting. But if the database is not getting changed that frequently, we can have some caching in place so that if the user is requesting the same data very frequently, we don't hit the database every time (since we know contents are not changed).
The two keys terms here are frequency and criteria. Frequency is the number of times we are anticipating the user requests for a particular page and criteria is what governs the uniqueness of result that is being displayed on the page.
Frequency is important because we need to figure out the interval in which database is changing and compare it with the frequency of user requests so that we can have caching in place and also make sure that user is not viewing out dated data.
Criteria is important because we need to make sure that we have caching implemented for the page on every unique criteria. It should not be the case that user is requesting contents based on criteria01 and we are showing him the cached results of criteria00 (cached earlier for him).
So with all this theory in mind, let's go ahead and see how ASP.NET provides caching features without us writing a lot of code to manage the same.

Types of Caching

There are two types of caching available in ASP.NET:
1. Page Output Caching
2. Application Caching
 
 

Page Output Caching

Page output caching refer to the ability of the web server to cache a certain webpage after user request in its memory so that further requests for the same page will check for the cached page's validity and will not result in resource usage (DB access or file access) and the page will be returned to user from cache.
Now the question is how can we ensure that the user is not viewing the out dated data. ASP.NET provides us various configuration options which will let us program in such a way that we can ensure that the user never gets stale data.
Let us have a simple web page with a textbox, button and a label. Right now, the caching is not enabled for this page so everytime the postback occurs, the request to the web server is made. We can verify this by displaying the current time in the label.
 
protected void Page_Load(object sender, EventArgs e)
{
    Label1.Text = DateTime.Now.ToLongTimeString();
}
 

Now let us go ahead and enable caching for this page by adding the following declaration to the page:
 
<%@ OutputCache Duration="30" VaryByParam="none" %>
 

Here we are saying that this page should be cached for 30 seconds, We can verify this by pressing the button. The time string will not change for 30 seconds and the second property VaryByParam specifies that caching doesn't depend on anything doing so can lead to a situation where user can see stale data, like in our case for 30 seconds if we write something in textbox and do a postback, it will keep reverting to the old data that was in the textbox at the time page was cached.
 
clip_image004
 
So it's a good idea to say that the cached page is not valid if the data in textbox is changed so let's do that now:
 
 

<%@ OutputCache Duration="30" VaryByParam="TextBox1" %>
 

So now we can see that the page output will be cached as long as the contents of the textbox are not changed. If we change the contents of the textbox, then the server processes the page again and then caches it again.
 
clip_image006
 
So what we saw is that we can specify the Duration the page should be cached which is related to the talk about frequency we did earlier. The Duration should be chosen so that during that time we are not expecting any change in data and for the criteria, we saw how we can use VaryByCustom to make sure that the output for every different criteria is generated and the cached copy is not just presented to the user.

Let us look as some other parameters that we can use to customize caching behavior.
· VaryByParam: List of strings that are sent to server via POST that are checked to validate cache
· VaryByControl: List of controls whose value will determine the validity of cache
· SqlDependency: Defines the Database-tablename pair on which the validity of cache depends
· VaryByCustom: Used for custom output cache requirements
· VaryByHeader: HTTPs header that determines the cache validity
 

If we need different output pages based on query string, then we can specify the list of querystring parameters here or we can simply say VaryByParam ="*" to do the same for all querystring parameters. Now let us just have a quick look at what we need to do if we need to change the cached page based on query string parameter.
 
<%@ OutputCache Duration="30" VaryByParam="name" %>
 
protected void Button2_Click(object sender, EventArgs e)
{
    int name;
    if (Request.QueryString["name"] == null)
    {
        name = 1;
    }
    else
    {
        name =  Convert.ToInt32(Request.QueryString["name"]) + 1;
    }
    Response.Redirect("varybyqs.aspx?name=" + name.ToString());
}
 
 

clip_image008

 
 
 
In order to cache a page's output, we need to specify an @OutputCache directive at the top of the page. The syntax is as shown below:

<%@ OutputCache Duration=5  VaryByParam="None" %>

As you can see, there are two attributes to this directive. They are:

  • Duration - The time in seconds of how long the output should be cached. After the specified duration has elapsed, the cached output will be removed and page content generated for the next request. That output will again be cached for 10 seconds and the process repeats.
  • VaryByParam - This attribute is compulsory and specifies the querystring parameters to vary the cache.
    In the above snippet, we have specified the VaryByParam attribute as None which means the page content to be served is the same regardless of the parameters passed through the querystring [see Example 1 in the sample download].
    If there are two requests to the same page with varying querystring parameters, e.g.: .../PageCachingByParam.aspx?id=12 and .../PageCachingByParam.aspx?id=15] and separate page content is generated for each of them, the directive should be:
     
    <%@ OutputCache Duration=5 VaryByParam="id" %>

    The page content for the two requests will each be cached for the time specified by the Duration attribute [see Example 2 in the sample download].
    To specify multiple parameters, use semicolon to separate the parameter names. If we specify the VaryByParam attribute as *, the cached content is varied for all parameters passed through the querystring.

Some pages generate different content for different browsers. In such cases, there is provision to vary the cached output for different browsers. The @OutputCache directive has to be modified to:
 
<%@ OutputCache Duration=5 VaryByParam="id" VaryByCustom="browser" %>
 

This will vary the cached output not only for the browser but also its major version. I.e., IE5, IE 6, Netscape 4, Netscape 6 will all get different cached versions of the output.
 
 
 

Partial Page Caching (or) Fragment Caching


Sometimes we might want to cache just portions of a page. For example, we might have a header for our page which will have the same content for all users. There might be some text/image in the header which might change everyday. In that case, we will want to cache this header for a duration of a day.

The solution is to put the header contents into a user control and then specify that the user control content should be cached. This technique is called fragment caching.
To specify that a user control should be cached, we use the @OutputCache directive just like we used it for the page.



<%@ OutputCache Duration=10  VaryByParam="None" %>
 

With the above directive, the user control content will be cached for the time specified by the Duration attribute [10 secs]. Regardless of the querystring parameters and browser type and/or version, the same cached output is served. [See Example 3 in the download for a demonstration].
Similar to output caching, partial page caching allows you to cache certain blocks of your website. You can, for example, only cache the center of the page. Partial page caching is achieved with the caching of user controls. You can build your ASP.NET pages consisting of numerous user controls and then apply output caching on the user controls you select. This will cache only parts of the page that you want, leaving other parts of the page outside the reach of caching. This is a very nice feature, and if done correctly, it can lead to pages that perform better.

Note: Typically, UserControls are placed on multiple pages to maximize reuse. However, when these UserControls (ASCX files) are cached with the @OutputCache directive, they are cached on a per page basis. That means even if a User Control outputs identical HTML when placed on pageA.aspx as it does when placed on pageB.aspx, its output is cached twice. You can prevent this happening by adding Shared = true in the output cache directive.
 
<%@ OutputCache Duration="300" VaryByParam="*" Shared="true" %>
 

By putting the Shared attributed, the memory savings can be surprisingly large. If you have an ASCX User control using the OutputCache directive, remember that the User Control exists only for the first request.


Also, if we have a requirement for partial page caching (Fragment caching), we can simply use the controls that require caching and put them in a user control. We can then use the same above mentioned technique to enable caching behaviour in the custom control and we have partial page caching in place. (See the code for implementation.)
 
clip_image010
Note: The above mentioned approaches enabled us to use caching by using declarations on the page. We can also control caching programmatically.
 
 

Application Data Caching


Output caching and partial page caching is useful if you want to cache the output of a page. However, if you like to cache a DataSet object or any collection object, you can use data caching to implement that.

ASP.NET has a class called Cache to cache specific data items for later use on a particular page or group of pages. The Cache enables you to store everything from simple name/value pairs to more complex objects like datasets and entire aspx pages.
 

          To store data into the cache, you can use the code below:

    C#

    Cache["MyDataSet"] = myDataSet;
     
    To retrieve data from the cache, you can use the code below:
    C#

    DataSet ds = new DataSet();
    ds = (DataSet) Cache["MyDataSet"];

 


Application data caching is a mechanism for storing the Data objects on cache. It has nothing to do with the page caching. ASP.NET allows us to store the object in a Key-Value based cache. We can use this to store the data that need to cached. Let us work on the same example and try to store the DateTime object in the Application Cache now.
 
protected void Page_Load(object sender, EventArgs e)
{
    if (IsPostBack == false)
    {
        Cache["time"] = DateTime.Now;
    }
 
    Label1.Text = ((DateTime)Cache["time"]).ToLongTimeString();
}

 
What this code will do is that it will store the DateTime object in application cache and will keep displaying the time of initial request by using the object from the cache.
 
clip_image012
 
 

There are various parameters associated with application data caching that can be used to control its behavior.
· Dependencies: Any file or item in cache that invalidates this cache item
· absoluteExpiration: Absolute time when this object should be removed from cache
· slidingExpiration: Relative time when this object should be removed from the cache
· priority: Defines the priority of the item. This is useful when server runs out of memory as in that case it start removing items from cache with lowest priority first
· onRemoveCallBack: This is the event handler that will be called when the object is removed from cache. It gives us a place to take further actions.

 
 

Understanding Asp.net Cache Sliding Expiration and Absolute Expiration




Asp .Net provides two different ways to expire the cache on the basis of time. Here are two approaches:-
 

  1. Sliding Expiration
  2. Absolute Expiration 



1. Absolute Expiration


Absolute expiration means that your data will be removed from cache after fixed amount of time either it is accessed or not. Generally we use it when we are displaying data which is changing but we can afford to display outdated data in our pages.  Mostly I put all of my dropdown values in cache with Absolute Expiration. Here is how you can code:-

DataTable dt = GetDataFromDatabase();
Cache.Insert("AbsoluteCacheKey", dt, null,
DateTime.Now.AddMinutes(1), //Data will expire after 1 minute
System.Web.Caching.Cache.NoSlidingExpiration);
 
2. Sliding Expiration


Sliding expiration means that your data will be removed from cache if that is not accessed for certain amount of time. Generally we store that data in this cache mode which is accessed many time on certain occasions. For example if you go in account settings section of a site, then you will be frequently accessing account information in that section. But most of the time you wont be using account setting's related data so there is no point of storing that data in cache. In such scenarios sliding expiration should be used. here is how you can save data in cache with sliding expiration:-

DataTable dt = GetDataFromDatabase();
Cache.Insert("SlidingExpiration", data, null,
System.Web.Caching.Cache.NoAbsoluteExpiration,
TimeSpan.FromMinutes(1));//Data will be cached for 1 mins









What is state management?

Web is Stateless. It means a new instance of the web page class is re-created each time the page is posted to the server. As we all know HTTP is a stateless protocol, its can't holds the client information on page. As for example , if we enter a text and client on submit button, text does not appear after post back , only because of page is recreated on its round trip.
 
clip_image002
 
As given in above pages, page is recreated before its comes to clients and happened for each and every request. So it is a big issue to maintain the state of the page and information for a web application. That is the reason to start concept of State Management. To overcome this problem ASP.NET 2.0 Provides some features like View State, Cookies, Session, Application objects etc. to manage the state of page.
There are some few selection criteria to selected proper way to maintain the state, as there are many way to do that. Those criteria are:
· How much information do you need to store?
· Does the client accept persistent or in-memory cookies?
· Do you want to store the information on the client or on the server?
· Is the information sensitive?
· What performance and bandwidth criteria do you have for your application?
· What are the capabilities of the browsers and devices that you are targeting?
· Do you need to store information per user?
· How long do you need to store the information?
· Do you have a Web farm (multiple servers), a Web garden (multiple processes on one machine), or a single process that serves the application?
So, when ever you start to think about state management, you should think about above criteria. based on that you can choose the best approaches for manages state for your web application.
 
 

Different types of state management?

There are two different types of state management:
1. Client Side State Management
  1. o View State
  2. o Hidden Field
  3. o Cookies
  4. o Control State
2. Server Side State Management
  1. o Session
  2. o Application Object
  3. o Caching
  4. o Database
 
Client Side state management does not use any server resource , it store information using client side option. Server Side state management use server side resource for store data. Selection of client side and server side state management should be based on your requirements and the selection criteria that are already given.
 
 

What is view state?

View State is one of the most important and useful client side state management mechanism. It can store the page value at the time of post back (Sending and Receiving information from Server) of your page. ASP.NET pages provide the ViewState property as a built-in structure for automatically storing values between multiple requests for the same page.
 
Example:
 
If you want to add one variable in View State,
ViewState["Var"]=Count;
 
For Retrieving information from View State
string Test=ViewState["TestVal"];
 

Sometimes you may need to typecast ViewState Value to retreive. As I give an Example to strore and retreive object in view state  in the last of  this article.
 
 

Advantages of view state?


This are the main advantage of using View State:
· Easy to implement
· No server resources are required
· Enhanced security features ,like it can be encoded and compressed.
 
 

Disadvantages of view state?


This are the main disadvantages of using View State:
· It can be performance overhead if we are going to store larger amount of data , because it is associated with page only.
· Its stored in a hidden filed in hashed format (which I have discussed later) still it can be easily trapped.
· It does not have any support on mobile devices.
 
 

When we should use view state?


I already describe the criteria of selecting State management. A few point you should remember when you select view state for maintain your page state.
· Size of data should be small , because data are bind with page controls , so for larger amount of data it can be cause of performance overhead.
· Try to avoid storing secure data in view state
 
clip_image006

 


 


 




When we should avoid view state?


You won't need view state for a control for following cases,
· The control never change
· The control is repopulated on every postback
· The control is an input control and it changes only of user actions.

 


 


 


Where is view state stored?


View State stored the value of page controls as a string which is hashed and encoded in some hashing and encoding technology. It only contain information about page and its controls. Its does not have any interaction with server. It stays along with the page in the Client Browser. View State use Hidden field to store its information in a encoding format.
Suppose you have written a simple code , to store a value of control:
 

ViewState["Value"] = MyControl.Text;

 
Now, Run you application, In Browser, RighClick > View Source , You will get the following section of code
 
clip_image008

Fig : View state stored in hidden field
Now , look at the value. looks likes a encrypted string, This is Base64 Encoded string, this is not a encoded string. So it can easily be decoded. Base64 makes a string suitable for HTTP transfer plus it makes it a little hard to read . Read More about Base64 Encoding . Any body can decode that string and read the original value. so be careful about that. There is a security lack of view state.
 
 

How to store object in view state?


We can store an object easily as we can store string or integer type variable. But what we need ? we need to convert it into stream of byte. because as I already said , view state store information in hidden filed in the page. So we need to use Serialization. If object which we are trying to store in view state ,are not serializable , then we will get a error message .
 

Just take as example,


//Create a simple class and make it as Serializable

[Serializable]

public class student

{

    public int Roll;

    public string Name;

    public void AddStudent(int intRoll,int strName)

      {

        this.Roll=intRoll;

        this.Name=strName;

           }

}

Now we will try to store object of "Student" Class in a view state.
 


 //Store Student Class in View State

student _objStudent = new student();

_objStudent.AddStudent(2, "Abhijit");

ViewState["StudentObject"] = _objStudent;

 

//Retrieve Student information view state

 student _objStudent;

_objStudent = (student)ViewState["StudentObject"]; 

 

 

 

How to trace your view state information?


If you want to trace your view state information, by just enable "Trace" option of Page Directive
 
clip_image011

 
Now Run your web application, You can view the details of View State Size along with control ID in Control Tree Section. Don't worry about "Render Size Byte" , this only the size of rendered control.
clip_image013

Fig : View State Details

 


 


 


 


Enabling and Disabling View State


You can enable and disable View state for a single control as well as at page level also. To turnoff view state for a single control , set EnableViewState Property of that control to false. e.g.:
 

TextBox1.EnableViewState =false;

 

To turnoff the view state of entire page, we need to set EnableViewState to false of Page Directive as shown bellow.
 
clip_image015

 
Even you disable view state for the entire page , you will see the hidden view state tag with a small amount of information, ASP.NET always store the controls hierarchy for the page at minimum , even if view state is disabled.
For enabling the same, you have to use the same property just set them as True
as for example, for a single control we can enabled view state in following way,
 

TextBox1.EnableViewState =true;

 

and for a page level,
 
clip_image017

 


 


 


 


 


How to make view state secure?


As I already discuss View state information is stored in a hidden filed in a form of Base64 Encoding String, and it looks like:
clip_image018

Fig : View state stored in hidden field
 
Many of ASP.NET Programmers assume that this is an Encrypted format, but I am saying it again, that this is not a encrypted string. It can be break easily. To make your view state secure, There are two option for that,
· First, you can make sure that the view state information is tamper-proof by using "hash code". You can do this by adding "EnableViewStateMAC=true" with your page directive. MAC Stands for "Message Authentication Code"
 
clip_image020



A hash code , is a cryptographically strong checksum, which is calculated by ASP.NET and its added with the view state content and stored in hidden filed. At the time of next post back, the checksum data again verified , if there are some mismatch, Post back will be rejected. we can set this property to web.config file also.
· Second option is to set ViewStateEncryptionMode="Always" with your page directives, which will encrypt the view state data. You can add this in following way
 
clip_image022

 
It ViewStateEncryptionMode has three different options to set:
· Always
· Auto
· Never
Always, mean encrypt the view state always, Never means, Never encrypt the view state data and Auto Says , encrypt if any control request specially for encryption. For auto , control must call Page.RegisterRequiresViewStateEncryption() method for request encryption.
we can set the Setting for "EnableViewStateMAC" and ViewStateEncryptionMode" in web.config also.
 
clip_image024

Note : Try to avoid View State Encryption if not necessary , because it cause the performance issue
 

 



ASP.NET Page Life Cycle with State Management objects

Introducing Viewstate Outside the ASP.NET Context 
In its very basic form, Viewstate is nothing more than a property which has a key/value pair indexer:




Viewstate[“mystringvariable”] = “myvalue”;


Viewstate[“myintegervariable”] = 1; 

 

As you can see, the indexer accepts a string as a key and an object as the value. The ViewState property is defined in the “System.Web.UI.Control” class. Since all ASP.NET pages and controls derive from this class, they all have access to the ViewState property. The type of the ViewState property is “System.Web.UI.StateBag”.
The very special thing about the StateBag class is the ability to “track changes”. Tracking is, by nature, off; it can be turned on by calling the “TrackViewState()” method. Once tracking is on, it cannot be turned off. Only when tracking is on, any change to the StateBag value will cause that item to be marked as “Dirty”.




Info: In case you are wondering (and you should be) about the reason behind this “tracking” behavior of the StateBag, do not worry; this will be explained in detail along with examples about how tracking works, in the next sections.

Introducing Viewstate Inside the ASP.NET Context


When dealt within the context of ASP.NET, the Viewstate can be defined as the technique used by an ASP.NET web page to remember the change of state spanning multiple requests. As you know, ASP.NET is a stateless technology; meaning that two different requests (two postbacks) to the same web page are considered completely unrelated. This raises the need of a mechanism to track the change of state for this web page between the first and the second request.
 
The Viewstate of an ASP.NET page is created during the page life cycle, and saved into the rendered HTML using in the “__VIEWSTATE” hidden HTML field. The value stored in the “__VIEWSTATE” hidden field is the result of serialization of two types of data:
 
1. Any programmatic change of state of the ASP.NET page and its controls. (Tracking and “Dirty” items come into play here. This will be detailed later.) 
2. Any data stored by the developer using the Viewstate property described previously.
This value is loaded during postbacks, and is used to preserve the state of the web page.


Info: The process of creating and loading the Viewstate during the page life cycle will be explained in detail later. Moreover, what type of information is saved in the Viewstate is also to be deeply discussed.

   
One final thing to be explained here is the fact that ASP.NET server controls use Viewstate to store the values of their properties. What does this mean? Well, if you take a look at the source code of the TextBox server control, for example, you will find that the “Text” property is defined like this:
   
public string Text


{


    get { return (string)ViewState["Text"]; }


    set { ViewState["Text"] = value; }


}
 
You should apply this rule when developing your own server controls. Now, this does not mean that the value of the “Text” property set at design time is saved in the rendered serialized ViewState field. For example, if you add the following TextBox to your ASP.NET page:   


<asp:TextBox runat="server" ID="txt" Text="sometext" />
  

According to the fact that the “Text” property uses Viewstate to store its value, you might think that the value is actually serialized in the __VIEWSTATE hidden field. This is wrong because the data serialized in the hidden __VIEWSTATE consists only of state changes done programmatically. Design time data is not serialized into the __VIEWSTATE (more on this later). For now, just know that the above declaration of the “Text” property means that it is utilizing Viewstate in its basic form: an indexed property to store values much like the Hashtable collection does.


Generating the compiled class 
The first step (actually, step 0 as explained in the info block below) of the life cycle is to generate the compiled class that represents the requested page. As you know, the ASPX page consists of a combination of HTML and Server controls. A dynamic compiled class is generated that represents this ASPX page. This compiled class is then stored in the “Temporary ASP.NET Files” folder. As long as the ASPX page is not modified (or the application itself is restarted, in which case the request will actually be the first request and then the generation of the class will occur again), then future requests to the ASPX page will be served by the same compiled class.

Info: If you have read my previous article about request processing, you will likely recall that the last step of the request handling is to find a suitable HTTP Handler to handle the request. Back then, I explained how the HTTP Handler Factory will either locate a compiled class that represents the requested page or will compile the class in the case of the first request. Well, do you see the link? This is the compiled class discussed here. So, as you may have concluded, this step of generating the compiled class actually occurs during the ASP.NET request handling architecture. You can think of this step as the intersection between where the ASP.NET request handling architecture stops and the ASP.NET page life cycle starts.

 
This compiled class will actually contain the programmatic definition of the controls defined in the aspx page. In order to fully understand the process of dynamic generation, let us consider the following example of a simple ASPX page for collecting the username and the password:
 
clip_image001

 
Now, upon the first request for the above page, the generated class is created and stored in the following location: 

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\


         <application name>\< folder identifier1>\< file identifier1>.cs

The compiled class “DLL” is also created in the same location with the same file identifier, as follows:
 
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\

         <application name>\< folder identifier1>\< file identifier1>.dll
 

As you can see, the generated class and its corresponding DLL are created, and will serve any new request for the ASPX page until one of the following conditions occur:

· The ASPX file is modified
· The application is restarted, for example, as a result of IIS reset or app domain restart

The following code is extracted from the compiled class. Note that the code is reformatted and “cleaned up” for presentation purposes.
 
clip_image004

 
 
OK, so now is the really interesting part. Start examining the code above, and you will be able to notice the following:
 
· The class – unsurprisingly – inherits from the “System.Web.IHttpHandler”. As explained earlier, this makes it eligible for acting as an HTTP Handler for the request. 
· All the controls – both HTML and Web Controls – are defined in the class. Notice how the static properties (such as “Text” and “TextMode”) are set inside the class. This is very important to remember because this is a vital point when discussing the Viewstate later in this article. 
· The “BuildControlTree” is called to create the control hierarchy. As you may know, controls inside an ASPX page are built into a tree hierarchy. For example, in the above example, the hierarchy would be as follows: The root parent is the page class itself, under which the direct child controls are the HTML Literal (the "b" tag) and the HTML Form. The HTML Form, in its turn, has two direct child controls which are the HTML Literal (the "div" tag) and the HTML Table. The HTML Table, in its turn, has child controls such as the Web Control for the username label and the Web Control for the password label, and so on until the complete hierarchy is built. Again, this is a very important point to remember because it will be revisited when discussing the Viewstate.  
PreInit (New to ASP.NET 2.0) 
The entry point of the page life cycle is the pre-initialization phase called “PreInit”. This is the only event where programmatic access to master pages and themes is allowed. Note that this event is not recursive, meaning that it is accessible only for the page itself and not for any of its child controls. 
Init (Recursive)

Next is the initialization phase called “Init”. The “Init” event is fired reclusively for the page itself and for all the child controls in the hierarchy (which is created during the creation of the compiled class, as explained earlier). Note that against many developers’ beliefs, the event is fired in a bottom to up manner and not an up to bottom within the hierarchy. This means that following up with our previous example, the “Init” event is fired first for the most bottom control in the hierarchy, and then fired up the hierarchy until it is fired for the page itself. You can test this behavior yourself by adding a custom or user control to the page. Override the “OnInit” event handler in both the page and the custom (or user) control, and add break points to both event handlers. Issue a request against the page, and you will notice that the event handler for the control will be fired up before that of the page.
 
InitComplete (New to ASP.NET 2.0)

The initialization complete event called “InitComplete” signals the end of the initialization phase. It is at the start of this event that tracking of the ASP.NET Viewstate is turned on. Recall that the StateBag class (the Type of Viewstate) has a tracking ability which is off by default, and is turned on by calling the “TrackViewState()” method. Also recall that, only when tracking is enabled will any change to a Viewstate key mark the item as “Dirty”. Well, it is at the start of “InitComplete” where “Page.TrackViewState()” is called, enabling tracking for the page Viewstate.



Info: Later, I will give detailed samples of how the Viewstate works within each of the events of the life cycle. These examples will hopefully aid in understanding the inner workings of the Viewstate.LoadViewState

This event happens only at postbacks. This is a recursive event, much like the “Init” event. In this event, the Viewstate which has been saved in the __VIEWSTATE during the previous page visit (via the SaveViewState event) is loaded and then populated into the control hierarchy.
 
LoadPostbackdata (Recursive)

This event happens only at postbacks. This is a recursive event much like the “Init” event. During this event, the posted form data is loaded into the appropriate controls. For example, assume that, on your form, you had a TextBox server control, and you entered some text inside the TextBox and posted the form. The text you have entered is what is called postback data. This text is loaded during the LoadPostbackdata event and handed to the TextBox. This is why when you post a form, you find that the posted data is loaded again into the appropriate controls. This behavior applies to most controls like the selected item of a drop down list or the “checked” state of a check box, etc…
A very common conceptual error is the thought that Viewstate is responsible for preserving posted data. This is absolutely false; Viewstate has nothing to do with it. If you want a proof, disable the Viewstate on your TextBox control or even on the entire page, and you will find that the posted data is still preserved. This is the virtue of the LoadPostbackdata event.
 
PreLoad (New to ASP.NET 2.0)

This event indicates the end of system level initialization.
 
Load (Recursive)

This event is recursive much like the “Init” event. The important thing to note about this event is the fact that by now, the page has been restored to its previous state in case of postbacks. That is because the LoadViewState and the LoadPostbackdata events are fired, which means that the page Viewstate and postback data are now handed to the page controls.
 
RaisePostbackEvent

This event is fired only at postbacks. What this event does is inspect all child controls of the page and determine if they need to fire any postback events. If it finds such controls, then these controls fire their events. For example, if you have a page with a Button server control and you click this button causing a postback, then the RaisePostbackEvent inspects the page and finds that the Button control has actually raised a postback event – in this case, the Button's Click event. The Button's Click event is fired at this stage.
 
LoadComplete (New to ASP.NET 2.0)

This event signals the end of Load.
 
Prerender (New to ASP.NET 2.0)

This event allows for last updates before the page is rendered.
 
PrerenderComplete (New to ASP.NET 2.0)

This event signals the end of “Prerender”.
 
SaveViewstate (Recursive)

This event is recursive, much like the “Init” event. During this event, the Viewstate of the page is constructed and serialized into the __VIEWSTATE hidden field.



Info: Again, what exactly goes into the __VIEWSTATE field will be discussed later.

SaveStateControl (New to ASP.NET 2.0)

State Control is a new feature of ASP.NET 2.0. In ASP.NET 1.1, Viewstate was used to store two kinds of state information for a control:
 

· Functionality state
· UI state

 
This resulted in a fairly large __VIEWSTATE field. A very good example is the DataGrid server control. In ASP.NET 1.1, DataGrid uses the Viewstate to store its UI state such as sorting and paging. So, even if you wanted to disable Viewstate on the DataGrid and rebind the data source on each postback, you simply cannot do that if your DataGrid was using sorting or paging. The result was that the DataGrid ended up using Viewstate to store both its bounded data and its UI state such as sorting and paging.
 
ASP.NET 2.0 solved this problem by partitioning the Viewstate into two:

· The Viewstate we are discussing here
· The Control State

 
The Control State is used to store the UI state of a control such as the sorting and paging of a DataGrid. In this case, you can safely disable the DataGrid Viewstate (provided, of course, that you rebind the data source at each postback), and the sorting and paging will still work simply because they are saved in the Control State.
The Control State is also serialized and stored in the same __VIEWSTATE hidden field. The Control State cannot be set off.
 
Render (Recursive)

This is a recursive event much like the “Init” event. During this event, the HTML that is returned to the client requesting the page is generated.
 
Unload (Recursive)

This is a recursive event much like the “Init” event. This event unloads the page from memory, and releases any used resources.
 
 
 

Role of Viewstate in the Page Life Cycle

Viewstate in the “Init” event

The important thing to note in the “Init” event is that Viewstate tracking is not yet enabled. In order to demonstrate this, let us take the following example:
 


protected override void OnInit(EventArgs e)


(


    bool ret;


    ret = ViewState.IsItemDirty("item");//returns false


    ViewSTate["item"] = "1";


    ret = ViewState.IsItemDirty("item");returns false


    base.OnInit(e);


}

 

Note that in the above example, the item is still not marked as “Dirty” even after it is being set. This is due to the fact that at this stage, the “TrackViewState()” method is not called yet. It will be called in the “InitComplete” event.


Info: You can force the tracking of Viewstate at any stage that you want. For example, you can call the “Page.TrackViewState()” method at the start of the “Init” event and thus enabling tracking. In this case, the “Init” event will behave exactly like the “InitComplete” event, to be discussed next.

Viewstate in the “InitComplete” event

In the “InitComplete” event, the Viewstate tracking is enabled. If we take the same example:
 

protected override void OnInitComplete(EventArgs e)


(


    bool ret;


    ret = ViewState.IsItemDirty("item");//returns false


    ViewSTate["item"] = "1";


    ret = ViewState.IsItemDirty("item");//returns true


 


    base.OnInitComplete(e);


}

 

This time, note that first, the item is not marked as “Dirty”. However, once it is set, then it is marked as “Dirty”. This is due to the fact that at the start of this event, the “TrackViewState()” method is called.
 
 
Viewstate in the “LoadViewState”and “SaveViewState” events



To better understand the role of Viewstate in these events, let us take an example. Say that you have a simple ASPX page that consists of the following:
· A Label server control with its “Text” property set to “statictext”
· A Button server control just to postback the page
· The “Load” event of the page has a statement that sets the “Text” property of the Label control to “dynamictext”. This statement is wrapped inside a “!IsPostback” condition
 
 
When the page first loads, the following will happen:
· During the “Load” event, the “dynamictext” value will be assigned to the “Text” property of the Label
· Later in the life cycle, the “SaveViewSatte” event is fired, and it stores the new assigned value “dynamictext” in the __VIEWSTATE serialized field (in the next sections, you will see how tracking came into play here)
 
 
Now, when you click the Button control, the following will happen:
· The “LoadViewState” event is fired. The __VIEWSTATE value saved in the previous page visit is loaded. The “dynamictext” value is extracted and assigned back to the “Text” property of the Label.
· The “Load” event is fired, but nothing happens there because the code is wrapped inside a “!IsPostback” condition.
See how that because of the Viewstate, the “dynamictext” value is persisted across page postback. Without Viewstate and with the “!IsPostback” condition inside the “Load” event, the value “dynamictext” would have been lost after the postback.
 
 

Viewstate Walkthroughs


OK, so by now, you should have a solid understanding about the page life cycle, the Viewstate, and the role of the Viewstate in the page life cycle. However, we are yet to discuss the cases that tests whether you are an advanced Viewstate user or not. In the next walkthroughs, you shall tackle most of these cases. By the end of this section, you can safely call yourself an advanced Viewstate user.
 
Walkthrough 1: Viewstate of an empty or Viewstate-disabled page

So, let us start by a very simple question. Will you have a value stored in the __VIEWSTATE field if you have a blank ASP.NET page or a page with Viewstate completely disabled? The answer is yes. As a test, create a blank ASP.NET page and run it. Open the View Source page and note the __VIEWSTATE field. You will notice that it contains a small serialized value. The reason is that the page itself saves 20 or so bytes of information into the __VIEWSTATE field, which it uses to distribute postback data and Viewstate values to the correct controls upon postback. So, even for a blank page or a page with disabled Viewstate, you will see a few remaining bytes in the __VIEWSTATE field.
 
Walkthrough 2: What is stored in the Viewstate?

As mentioned previously, the data stored in the __VIEWSTATE field consists of the following:
 

· Data stored by developers using the Viewstate[“”] indexer
· Programmatic change to the Control State

While the former is pretty much clear, the latter is to be explained thoroughly.
OK, so let us assume that you have a web page with only a Label control on it. Now, let us say that at design time, you set the “Text” property of the Label to “statictext”. Now, load the page and open the View Source page. You will see the __VIEWSTATE field. Do you think “statictext” is saved there? The answer is, for sure, not. Recall from our discussion about generating the compiled class of the page, that static properties of controls are assigned at the generated class? So, when the page is requested, the values stored in the generated class are displayed. As such, static properties that are set at design time are never stored in the __VIEWSTATE field. However, they are stored in the generated compiled class, and thus they show up when rendering the page.
Now, let us say that you did some changes to your page such that it consists of the following:

· A Label control with the value “statictext” assigned to its “Text” property
· A Button control to postback the page

· Inside the “Page_Load” event handler of the page, add code to change the value of the Label’s “Text” property to “dynamictext”. Wrap this code inside a “!IsPostback” condition.
Load the page and open the View Source page. This time, you will notice that the __VIEWSTATE field is larger. This is because at runtime, you changed the value of the “Text” property. And, since you have done this inside the “Load” event, where, at this time, tracking of Viewstate is enabled (remember, tracking is enabled in the “InitComplete” event), the “Text” property is marked as “Dirty”, and thus the “SaveViewstate” event stores its new value in the __VIEWSTATE field. Interesting!!
As a proof that the “dynamictext” value is stored in the __VIEWSTATE field (apart from the fact that it is larger), click the Button control causing a postback. You will find that the “dynamictext” value is retained in the Label even though the code in the “Load” event is wrapped inside the “!IsPostback” condition. This is due to the fact that upon postback, the “LoadViewstate” event extracted the value “dynamictext” which was saved by the “SaveViewState” event during the previous page visit and then assigned it back to the Label’s “Text” property.
Let us now go one step further. Repeat the exact same scenario, with one exception: instead of adding the code that will change the value of the “Text” property at the “Page_Load” event handler, override the “OnPreInit” event handler and add the code there. Now, first load the page, and you will see the new text displayed in the Label. But, do you think this time it is stored in the __VIEWSTATE field? The answer is no. The reason is that during the “PreInit” event, Viewstate tracking is not yet enabled, so the change done to the “Text” property is not tracked and thus not saved during the “SaveViewState” event. As a proof, click the Button causing a postback. You will see that the value displayed inside the Label is the design time value “statictext”.
Let us even go one step further. If you have been following this long article carefully, you will recall that during the “Init” event, tracking of Viewstate is not yet enabled. You have even seen an example in the section Viewstate in the “Init” event of how an item keeps being not dirty even after it is being set. Now, going back to our current example, you will most probably be tempted to consider that if we add the code that changes the value of the “Text” property inside the “OnInit” event handler, you will get the same result as when you put it inside the “OnPreInit” event handler; after all, tracking of Viewstate is not enabled yet during either event. Well, if you think so, then you are mistaken. Reason: if you have been following this article carefully, you will recall that the “InitComplete” event (where tracking of Viewstate is enabled) is not a recursive event; it is called only for the page itself, but not for its child controls. This means that, for the child controls, there is no “InitComplete” event; so, where does the tracking of Viewstate start? The answer is at the start of the “Init” event. So, this means that for the page itself, tracking of Viewstate is enabled at the “InitComplete” event; that is why during the “OnInit” event handler, the item was still marked as not being “Dirty” even after modification. However, for child controls, there is no “InitComplete” event, so the Viewstate tracking is enabled as early as the “Init” event. And, since – again as was explained earlier – the “Init” event is called recursively for the page and its controls in a bottom to up manner, by the time the “Init” event of the page itself is fired, the “Init” event of the child controls is already being fired, and thus Viewstate tracking for child controls is on by that time. As such, adding the code that changes the value of the “Text” property inside the “OnInit” event handler will have the same effect as putting it inside the “Page_Load” event handler.
 
Walkthorugh 3: What is the larger Viewstate?

Consider the following example: you have two ASP.NET pages: page1.aspx and page2.aspx. Both pages contain only a single Label control. However, in page1, the Label is declared at design time with its “Text” property set to a small string (say 10 characters); in page2, the Label is declared at design time with its “Text” property set to a lengthy string (say 1000 characters). Now, load both pages at the same time, and examine the View Source for both pages. Compare the two __VIEWSTATE fields, what do you find? You will find that both fields are of the same size even though one Label has its “Text” property storing 10 characters while the other has its “Text” property storing 1000 characters. If you have read walkthroughs 1 and 2, you will for sure know the reason: design time property values are not stored in the Viewstate. The __VIEWSTATE value for both pages is simply the bytes emitted by the page itself.
 
Walkthrough 4: Complete page life cycle scenario

In this walkthrough, we will go through each of the relevant page life cycle events and see what role Viewstate has in each of these events. In this example, we have as ASP.NET page with the following characteristics:

· It contains a single Label control (lbl) with its “Text” property set to “statictext”
· It contains a Button control (btnA) with code in its event handler that sets the “Text” property of “lbl” to “dynamictext”
· It contains a Button control (btnB) whose purpose is to cause a page postback
Now, let us examine what will happen during the page life cycle.
1. The page is first loaded
1. The compiled class of the page is generated and “statictext” is assigned to “lbl.Text
2. Tracking for Viewstate is enabled in the “InitComplete” event
3. “LoadViewState” is not fired because there is no postback
4. “SaveViewstate” is fired, but nothing happens because no change of state is recorded
5. The page is rendered with the value “statictext” inside “lbl
2. btnA is clicked
1. The previously generated compiled class is handed the request; “lbl.Text” is set to “statictext”
2. Tracking for Viewstate is enabled
3. “LoadViewState” is fired, but nothing happens because no change of state was recorded in the previous page visit
4. “RaisePostbackEvent” event is executed and “btnA” click event handler is fired; “lbl.Text” is set to “dynamictext”; since tracking is enabled at this stage, this item is tracked (marked as “Dirty”).
5. “SaveViewState” is fired; “dynamictext” is serialized and stored in the __VIEWSTATE field
6. The page is rendered with the value “dynamictext” inside “lbl
3. btnB is clicked
1. The previously generated compiled class is handed the request; “lbl.Text” is set to “statictext”
2. Tracking for Viewstate is enabled
3. “LoadViewState” is fired; since a change of state was recorded from the previous page visit, __VIEWSTATE is loaded and the value “dynamictext” is extracted; this value is then assigned to “lbl
4. “RaisePostbackEvent” event is executed; nothing happens here because “btnB” has no event handler for its “Click” event
5. “SaveViewState” is fired, but nothing happens because no change of state is recorded
6. The page is rendered with the value “dynamictext” inside “lbl

 
 
Walkthrough 5: Reducing Viewstate size – Disabling Viewstate

Disabling Viewstate would obviously reduce Viewstate size; but, it surely kills the functionality along the way. So, a little more planning is required…
Consider the case where you have a page with a drop down list that should display the countries of the world. On the “Page_Load” event handler, you bind the drop down list to a data source that contains the countries of the world; the code that does the binding is wrapped inside a “!IsPostback” condition. Finally, on the page, you have a button that when clicked should read the selected country from the drop down list. With the setup described above, you will end up with a large __VIEWSTATE field. This is due to the fact that data bound controls (like the drop down list) store their state inside the Viewstate. You want to reduce Viewstate; what options do you have?
1. Option 1: Simply disable the Viewstate on the drop down list
2. Option 2: Disable the Viewstate on the drop down list, and remove the “!IsPostback” condition
3. Option 3: Disable the Viewstate on the drop down list, and move the binding code without the “!IsPostback” condition to the “OnInit” or “OnPreInit” event handlers
If you implement Option 1, you will reduce the Viewstate alright, but with it, you will also lose the list of countries on the first postback of the page. When the page first loads, the code in the “Page_Load” event handler is executed and the list of countries is bound to the list. However, because Viewstate is disabled on the list, this change of state is not saved during the “SaveViewState” event. When the button on the page is clicked causing a postback, since the binding code is wrapped inside a “!IsPostback” condition, the “LoadViewState” event has nothing saved from the previous page visit and the drop down list is empty.
 
If you implement Option 2, you will reduce the Viewstate size and you will not lose the list of countries on postback. However, another problem arises: because the binding code is now executed at each “Page_Load”, the postback data is lost upon postback, and every time, the first item of the list will be selected. This is true because in the page life cycle, the “LoadPostbackdata” event occurs before the “Load” event.
 
Option 3 is the correct option. In this option, you have done the following:
· Disabled Viewstate on the drop down list
· Removed the “!IsPostback” condition from the binding code
· Moved the binding code to the “OnInit” event handler (or the “OnPreInit” event handler)
Since the “Init” event occurs before the “LoadPostbackdata” in the page life cycle, the postback data is preserved upon postbacks, and the selected item from the list is correctly preserved.
Now, remember that in Option 3, you have successfully reduced the Viewstate size and kept the functionality working; but, this actually comes at the cost of rebinding the drop down list at each postback. The performance hit of revisiting the data source at each postback is nothing when compared with the performance boost gained from saving a huge amount of bytes being rendered at the client’s __VIEWSTATE field. This is especially true with the fact that most clients are connected to the Internet via low speed dial up connections.
 
 
Walkthrough 6: Viewstate and Dynamic Controls

The first fact that you should know about dynamic controls is that they should be added to the page at each and every page execution. Never wrap the code that initializes and adds the dynamic control to the page inside a “!IsPostback” condition. The reason is that since the control is dynamic, it is not included in the compiled class generated for the page. So, the control should be added at every page execution for it to be available in the final control tree. The second fact is that dynamic controls play “catch-up” with the page life cycle once they are added. Say, you did the following:
 

Label lbl = new Label();


Page.Controls.Add(lbl);

 
Once the control is added to the “Controls” collection, it plays “catch-up” with the page life cycle, and all the events that it missed are fired. This leads to a very important conclusion: you can add dynamic controls at any time during the page life cycle until the “PreRender” event. Even when you add the dynamic control in the “PreRender” event, once the control is added to the “Controls” collection, the “Init”, “LoadViewState”, “LoadPostbackdata”, “Load”, and “SaveViewstate” are fired for this control. This is called “catch-up”. Note though that it is recommended that you add your dynamic controls during the “PreInit” or “Init” events. This is because it is best to add controls to the control tree before tracking of the Viewstate of other controls is enabled…
Finally, what is the best practice for adding dynamic controls regarding Viewstate? Let us say that you want to add a Label at runtime and assign a value to its “Text” property. What is the best practice to do so? If you are thinking the below, then you are mistaken:




Label lbl = new Label();


Page.Controls.Add(lbl);


lbl.Text = "bad idea";

 

You are mistaken because using the above technique you are actually storing the value of the “Text” property in the Vewstate. Why? Because, recall that once a dynamic control is added to the “Controls” collection, a “catch-up” happens and the tracking for the Viewstate starts. So, setting the value of the “Text” property will cause the value to be stored in the Viewstate.

However, if you do the below, then you are thinking the right way, because you are setting the “Text” property before adding the control to the “Controls” collection. In this case, the value of the “Text” property is added with the control to the control tree and not persisted in Viewstate.



Label lbl = new Label();

lbl.Text = "good idea";

Page.Controls.Add(lbl);


No comments:

Post a Comment