Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

A Walkthrough to Application State

0.00/5 (No votes)
14 Jun 2010 1  
This article discusses about Application Level events, Application State with a simple example.

Table of Contents

Introduction

There are a lot of articles available on different ways of managing the states in the web. I was not able to find details on Application Object and events. So I read different books and articles and thought of sharing my knowledge with all of you. Hope you will like it and give your feedback and suggestions.

As we all know, web is stateless. A Web page is recreated every time it is posted back to the server. In traditional web programming, all the information within the page and control gets wiped off on every postback. To overcome this problem, ASP.NET Framework provides various ways to preserve the states at various stages like controlstate, viewstate, cookies, session, etc. These can be defined in client side and server side state management. Please see the image below:

Various option to maintain the states

Figure: Options available to maintain the state

There are lot more written about most of them. In this article, I am going to explore mainly Application state, Application events and Application Objects.

Application LifeCycle

First, I am going to explain ASP.NET Application Lifecycle. One needs to really understand the application Lifecycle, so that one can code efficiently and use the resources available. Also it is very important to discuss, as we are going to Application level events, objects, etc.

ASP.NET uses lazy initialization technique for creating the application domains, i.e., Application domain for an application is created only when the first request is received by the web server. We can categorise Application life cycle in several stages. These can be:

  • Stage 1: User first requests any resource from the webserver.
  • Stage 2: Application receives very first request from the application.
  • Stage 3: Application basic Objects are created.
  • Stage 4: An HTTPapplication object is assigned to the request.
  • Stage 5: And the request is processed by the HTTPApplication pipeline.

I'll explain the points one by one.

Stage 1: The Application life cycle starts when a user hits the URL by typing it in the browser. The browser sends this request to the webserver. When webserver receives the request from the browser, it examines the file extension of the requested file and checks which ISAPI extension is required to handle this request and then passes the request to the appropriate ISAPI extension.

URL Request Flow

Figure: URL Processing

Note 1: If any extension is not mapped to any ISAPI extension, then ASP.NET will not receive the request and the request is handled by the server itself and ASP.NET authentication, etc. will not be applied.

Note 2: We can also make our own custom handler, to process any specific file extension.

Stage 2: When ASP.NET receives the first request, the Application manager creates an application domain for it. Application domains are very important because they provide the isolation amongst various applications on the webserver and every application domain is loaded and unloaded separately, and in application domain an instance of class HostingEnvironment is created which provides access to information about all application resources.

ALC1.JPG

Figure: ASP.NET Handling first request

Stage 3: After creating the application domain and hosting environment, ASP.NET initializes the basic objects as HTTPContext, HTTPRequest and HTTPResponse. HTTPContext holds objects to the specific application request as HTTPRequest and HTTPResponse.HTTPRequest contains all the information regarding the current request like cookies, browser information, etc. and HTTPResponse contains the response that is sent to client.

Stage 4: Here all the basic objects are being initialized and the application is being started with the creation of HTTPApplication class, if there is Global.asax (It is derived from HTTPApplication class) in the application, then that is instantiated.

Multiple request processing

Figure: Multiple requests processed by ASP.NET

Note: When the application is accessed for the first time, the HTTPApplication instance is created for further requests. It may be used for other requests as well.

Stage 5: There are a lot of events executed by the HTTPApplication class. Here, I have listed down a few important ones. These events can be used for any specific requirement.

Application Events

Fig: Application Events

What is Global.asax

To handle application events or methods, we can have a file named Global.asax in the root directory of your application. At any single point of time, an HTTPApplication instance handles only one request, so we don't need to think about locking and unlocking of any non static members, but for static members we do require. I'll discuss it in detail in a later section of this article. Following are the commonly used events in the global.asax file.

AppEvents.JPG

Figure: Methods in Global.asax

Application Restarts When

If we are going to change the source code, then ASP.NET requires to recompile into assemblies and also the application will restart as well. In spite of this, there are also certain things that force the application to get restarted. If we'll change in the following folder whether adding, modifying or deleting, the application will restart:

  • Any changes in the application's bin folder
  • Changes in Localisation resources, i.e., App_GlobalResources or App_LocalResources folders
  • Changes in Global.asax file

  • Modification of any source code in App_code folder

  • Any changes in web.config file
  • Any changes in the webservice references, i.e., App_WebReferences folder.

Application State:Intro

Application state is one of the ways available to store some data on the server and faster than accessing the database.The data stored on the Application state is available to all the users(Sessions) accessing the application. So application state is very useful to store small data that is used across the application and same for all the users. Also we can say they are global variables available across the users. As I am saying small data, we should not store heavy data in ApplicationState because it is stored on the server and can cause performance overhead if it is heavy. We'll discuss it later. Technically the data is shared amongst users via HTTPApplcationState class and the data can be stored here in key value pair. It can also be accessed through Application property of the HTTPContext class.

How Application State Works

As I have already discussed above, an instance of HttpApplicationState is created when first time a request comes from any user to access any resource from the application. And this can be accessed through the property Application property of HTTPContext Object. All HTTPModules and Handlers have access to this property. The lifetime of the values spans through the lifetime of the ASP.NET application until the application is unloaded. Normally, we set these Application variables in Application_OnStart event in Global.asax file and access and modify through ASP.NET pages.

How to Save values in Application State

One thing to keep in mind is that application state stores the data as of Object type, so at the time of reading, the values we need to convert it in the appropriate type.

So normally, we use to store the Application wise data in Application state which is shared across the users. So we can save the data in Application_OnStart method in Global.asax file as:

void Application_Start(object sender, EventArgs e)
{ 
Application["Message"] = "Welcome to my Website"; 
}

We can also save object of some Class in Application variable. Let's say we have a class as:

/// <summary>
/// Summary description for Employee
/// </summary>
public class Employee
{
    private string _name;
    public string Name {
        get
        {
            return _name;
        }
        set
        {
            _name = value;
        } 
    }
    private decimal _annualSalary;
    public decimal AnnualSalary
    {
        get
        {
            return _annualSalary;
        }
        set
        {
            _annualSalary = value;
        }
    }
	public Employee()
	{
		//
		// TODO: Add constructor logic here
		//
	}
}

Put this class file in App_Code folder. Now class will be available throughout the application so also in Global.asax. Now to save it in Application_OnStart as:

   void Application_Start(object sender, EventArgs e) 
    {
        Employee objEmployee = new Employee();
        objEmployee.Name = "Brij";
        objEmployee.AnnualSalary = 1000000;
        Application["EmployeeObject"] = objEmployee;
    }

Note: Here one thing I would like to mention is that we don't require to serialize the object to store in Application state as we need to keep in mind in case of viewstate, etc. So there is no need of serialization here. :) We can also modify these values from any method in the application. Here I am modifying Application["Message"] in onclick method of a button in a page as:

protected void Button1_Click(object sender, EventArgs e)
    {
        Application["Message"] = "Welcome Dude!!";
    }

Now we'll get the modified values whenever we try to access it. Let's also add a new variable on another button Click event as:

 protected void Button3_Click(object sender, EventArgs e)
 {
     Application["NewValue"] = "Hello";
 }

This value will also be available throughout the application life. One thing I also want to discuss is that Application state is not thread safe so it can be accessed by multiple threads at the same time, i.e., if we have stored some value in Application state say some counter and we increase it whenever a particular page is accessed. So at a single point of time, two instances of page of a different session can read the same value and update it. So we'll not get the desired result. So here we need some synchronisation mechanism so that at a single point of time only, one can update its value. Here we can call the System.Web.HttpApplicationState.Lock method, set the application state value, and then call the System.Web.HttpApplicationState.UnLock method to unlock the application state, freeing it for other write or update it as:

  if (Application["Counter"] != null)
        {
            Application.Lock();
            Application["Counter"] = ((int)Application["Counter"]) + 1;
            Application.UnLock();
        }

So by this way, we can avoid writing the same value from multiple Threads at the same time.

How To Read Values from Application State

So to read from Application state is fairly simple. We should just have a safety check to see whether the value we are accessing is null, if the data will not be in Application state is not there then it will return null and if we'll try to cast it in any different type, it'll throw an exception. As I already discussed, Application state stores the data in object form so we need to typecast after reading it. So we can read the value as:

if(Application["Message"] !=null)
{
      string message = Application["Message"] as string;
}

The object also can be read as:

if (Application["EmployeeObject"] != null)
{
    Employee myObj = Application["EmployeeObject"] as Employee;
    string Name = myObj.Name;
}

A Classic Example of Application State

A classic example of Application variable can be to show the number of online user in a website. This can be done in the following steps:

  • Add an online counter variable ApplicationStart method of Global.asax file as:
    Application["OnlineCounter"] = 0; 

    So in this, a variable will be added when the application first starts and will be initialized to 0 as there will be no logged in user at that point of time.

  • Now as we know whenever a new user opens the website, a new session is created and Session_Start method of Global.asax is called. So we can increase the counter in this method as:
        void Session_Start(object sender, EventArgs e) 
        {
            // Code that runs when a new session is started
           if (Application["OnlineCounter"] != null)
            {
                Application.Lock();
                Application["OnlineCounter"] = 
    			((int)Application["OnlineCounter"]) + 1;
                Application.UnLock();
            }
        }

    We should use the Locks, else we may get the wrong result because this may be updated at the same time and updated data is not correct. How: Let's say we currently have Application["OnlineCounter"] is 5 and at the same time, two sessions read the value 5 and make an increment to 6 and updated it. Application state as 6. So although two users are logged in, the counter is increased by one only. So to avoid this, we should use the locks.

  • So also at the time session ends, we should decrease it by one. As I already discussed, an event Session_End is fired whenever a session ends. So it can be done as:
        void Session_End(object sender, EventArgs e) 
        {
            // Code that runs when a new session is started
            if (Application["OnlineCounter"] != null)
            {
                Application.Lock();
                Application["OnlineCounter"] = 
    		((int)Application["OnlineCounter"]) - 1;
                Application.UnLock();
            }
        }
  • And this value can be accessed throughout the application at any point of time in the application as:
      if (Application["OnlineCounter"] != null)
            {
                int OnlineUsers = ((int)Application["OnlineCounter"]);
            }    

    and this value can be used anywhere in the application.

Application State: Points to Think About Before Using

  • Application state is stored in memory of webserver, so huge amount of data can cause severe performance overhead. Also keep in mind that these variables will be stored in memory till the application ends whether we need the entire time or not. So use it judiciously.
  • If the application goes down or is restarted, then all the data stored in Application state is lost.
  • Also Application data is not shared between multiple servers in webfarm scenario.
  • Application also doesn't work in case of Webgarden. Variables stored in application state in either of those scenarios are global only to the particular process in which the application is running. Each application process can have different values.
  • Application state is not thread safe, so we must keep the synchronisation in mind as discussed above.

Application State vs Caching

Although both provide the same feature and can be used to store the data at application level, there are a lot of differences between both.

Sr No Application State Cache
1 Application variables are one of the techniques provided by ASP/ASP.NET to store the data at application level and this is available to all users. Cache is one technique provided by ASP.NET to store the data at the application level with many options.
2 Application variables are available throughout the lifecycle of the application until explicitly removed or overridden. Cache is volatile. It provides the opportunity to automatically expire the data based on the settings or memory gets reclaimed when memory is scarce.
3 Application variable should be used only when data is limited, i.e., it should not be like we store some dataset and keep adding the data in same, which may lead to choke the webserver Cache provides a flexible way to store data on the webserver and also get removed when memory becomes low.

Feedback and Suggestions

Feedback is always the key area for me. I would request you all to share your feedback and give me some suggestions, which would encourage and help in more writing.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here