In this lesson we will be looking at application state, and what .NET does to manage web application state for you. ASP.NET applications are hosted in a web server and are accessed over the stateless HTTP protocol. Attempting to manage state in Web applications goes against the fundamental design principles of the Web. A new instance of the Web page class is created each time the page is posted to the server. In traditional Web programming, this would typically mean that all information associated with the page and the controls on the page would be lost with each round trip. For example, if a user enters information into a text box, that information would be lost in the round trip from the browser or client device to the server. As such, if the application uses stateful interaction, it has to implement state management on its own. ASP.NET provides various functionality for state management in ASP.NET applications.
Application state is a collection of user-defined variables that are shared by all instances of an ASP.NET application. These are set and initialized when the Application_OnStart event fires on the loading of the first instance of the applications and are available till the last instance exits.
In a typical windows form application these variable are kept alive for the entire length that the application runs. But in a web environment, these variables reside on the server, and the application is killed once the web page has been served, along with any variables that might have been initialised. Think of each web page as a mini application running on the server and is only alive for a fraction of a second. This is an important point to note. Because you might be expecting a variable that you had previously declared and initialised but now it’s gone. How do you then maintain state for each page if it is only alive for a fraction of a second?
To overcome this inherent limitation of traditional Web programming, ASP.NET includes several options that help you preserve data on both a per-page basis and an application-wide basis. Some of these we have dealt with and touch on in past lessons. These features are as follows:
- View state
- Control state
- Hidden fields
- Cookies
- Query strings
- Application state
- Session state
- Profile Properties
View state, control state, hidden fields, cookies, and query strings all involve storing data on the client in various ways. However, application state, session state, and profile properties all store data in memory on the server. Each option has distinct advantages and disadvantages, depending on the scenario.
Page Object
In previous lessons we spoke about the page object. The most common way to access application state is by means of the Application property of the Page object. What we discussed was that the page object is an object that encapsulated a single request and response from a single user for a single page. The page object gave us access to important information, like whether the current page was a result of a postback or an original request. We are then able to write code based upon that information. The static page object contains other static objects that give us information and allows us to programmatically interact with all aspects of the user interaction with our web application.
Note:This is a general explanation of the more important objects and should not be considered as a detailed explanation. But the significant objects of the page object are.
Request Object
The request object encapsulates all information about the users browser, plus any data that is posted by the browser via the post or get method. For example, any data that is contained in a web form and submitted to you web application.
Response Object
Now any results or information we want to send back to the user, is done via the response object. You will recall that we used “page.response.write” as in page.response.write(“Hello world”). Which would write the text, “Hello world”, into the browser. So this object encapsulates all the information that our application will send back to the browser in Response to the users request.
Session object.
The session object contains information about a single users interaction at a particular time. You can use the Session object to store information needed for a particular user session. Variables stored in the Session object are not discarded when the user jumps between pages.
Application object
The application object stores application wide information. The application object has methods and attributes of the application as a whole. You are able to use these objects to store stateful information between requests.
Form Object
The form object is very similar to the request object but it gives us just a subset of the information. So we would be able to get any information passed via the HTTP post. We would therefore be able to grab any fields of data.
Trace Object
This object contains information that enables us to monitor and debug our applications performance. We will deal with this in more depth in another lesson.
User Object
This allows us to provide some security to our application. You can allow or deny users access to certain resources based on roles that they are associated with.
Server Object
This has information about the web server in general. You can use the Server object to access methods and properties on the server. Information like the file path for instance.
Previous Page Object
Now this gives us information about the previous page that was served to the user before the current page that our code is currently handling.
There are many more of these types of page objects but these are the ones that are most important to you, and probably ones that you will use the most.
View State
So lets talk about and find out about viewstate. Open C# express or Visual studio, and start a new website or project. Keep in mind that I am writing this lesson from the view point of the full version Visual Studio , although most functionality and things we will discuss here are exactly the same in both versions.
So File -> New Website. A dialogue box opens. Name your new website what ever you like. I am using the name “AppStateLesson”. If you are using full VS, select the C# language. Make sure that you have selected the “Asp.net web site” Template from the templates area. Click the OK button. After a moment or two you will see your solution open with the Default.aspx file open in the source view. Select design view. If you are running 2008, then you can also select the split view.
Drag and drop two textboxes, a button and a label control onto the design surface. Change the text on the Button to “Ok” and delete the text from the label. We would normally change the ID’s of each object. You can do that if you want to, but I am going to leave them as they are, just so that we are all on the same page.
Double click on the OK button to get to the code behind click event of the button. We are going to add some code here.
Label1.Text = TextBox1.Text + " " + TextBox2.Text;
Save and run the application to test. When the dialog box comes up, click OK to modify the config file. When the browser and the page come up, type some text into the two textboxes and click the ok button. What would you expect to happen based on the code just written? Very simple the label control was filled with the text you typed into the two text boxes. That’s not rocket science. But what about the textboxes themselves? Notice that after posting back they have retained the text you just typed in. How does this then happen without your intervention?
Right click and view the web page source. You will notice an extra object in the source that you never put there. In fact it is a hidden field named “__VIEWSTATE” and it has some encoded values in it.
Now this is a relatively small view state. The more controls you add to a page, the bigger the view state. This keeps track of the values you and I placed into the text box, as well as any other values of other controls that might be on the page that enable viewstate. We do not understand this, but .Net understands this and can interpret this accordingly. We can then use viewstate to get values from these controls from post back to post back. This is very cool. No programming on my side, .NET takes care of it all.
To test this out close the web page. On the design view of you application, double click on the page to get to the Page_Load event. Add the following code to the onload event.
if (IsPostBack == false)
{
ViewState.Add("ViewStateItem", "Hello World");
}
Note: The viewstate Key ,“ViewStateItem”, Could have been called anything you like, but we called it this just because it is relevant to this lesson. “Hello World” then is the Key value. So viewstate stores key value pairs.
Go back to you Ok Button_click event and change it to look like the following.
Label1.Text = ViewState["ViewStateItem"].ToString();
What we are trying to achieve here is to replace the text value of the label with the value store in viewstate for the key “ViewStateItem”.
So the first time the page is loaded it should save the “Hello World” Value into the viewstate. Then when you click the OK button, it should retrieve the value from the viewstate and replace the text value of the label with the viewstate value. Save and run the application. Click the OK button. Yes, the label displays, “Hello World”.
So viewstate enables you to keep the state of objects and values across different post backs. But what if you wanted to store values across multiple pages. Well you cant do this with viewstate. But you can achieve this with SessionState. Now we touched on the sessionstate object in a previous lesson. So I am just going to refer back to that for now.
Session State
This session object is global across the web site, but is not for the user. In fact s new session object is created for each user to your web site. Because of this, use with caution. You do not want to load hundreds of variables in to the session object for a very busy site. Imagine that if the session object is alive for 20 min, and you have 100 users per minute, and you store 100 variable in the session object. You can soon see how quickly memory can be consumed.
In order to handle these events we have to add a special file to our project called a Global.asax page. To do this click on the add new items button in your tool bar. Select “Global Application Class”, leave the default name. When that is done, you will see a new page. In your design view you will have a new page called Global.asax.cs. In it, will be some default events handlers. Notice the four events handlers:
1. Application start
2. Session Start
3. Application end
4. Session end.
So we can write code to handle these events every time they are triggered. So what can this be used for. Well we can initialise some stuff, keep track of some stuff.
In the session start event type:
Session.Add("SomeValue", "Demonstrating Session State");
Then in your OkButton_click event replace the code with:
Label1.Text = Session["SomeValue"].ToString();
Run and test the application. Click the OK button. You will notice that the value that you placed in the session appears in the label.
Close your browser and lets try something different.
In your Global.asax file. Replace the code in the session start event with this:
Session.Add("SomeValue", Session.SessionID);
Save and Run. You will notice some crazy string in the label. This is the unique session id that every user gets when they initiate a session on your sever. This is how the server is able to track user sessions. This ID uniquely identifies your browser session at this point in time.
So the difference between a View State and a Session state, is that a View State works only for a particular page, but Session State works across multiple pages for a particular user at a particular moment in time.
Profile Object
The weakness with View State and Session State is that they are not strongly Typed. Have a look at how we retrieve values from them. We use literal strings. Like “SomeValue”. Now if we make a typing error, we will never be able to retrieve the correct value, or even cause a page to crash or time-out. This would be difficult to track down.
What would work, is if you could type session.somevalue. It would also be nice if you had control over where the values are stored. Currently session and view state are stored in memory. This could be a potential problem if you have a sudden rush of users to you web site. ASP.NET has what is called the Profile object. It has two huge benefits. First, it is strongly typed. Which means you get the full benefit of intellisense. Second, you get the flexibility of where you store the values. You can store them in a database, an xml file, in memory, or where ever you want.
First we need to define the properties of our profile object in the web.config file. We talked about the web.config file in a previous lesson.
In your solution explorer double click on you "web.config" file to open it up in the source editor. Navigate to before the closing tag, we are going to enter some xml data.
Dont worry about the explanation of theses tags at the moment. Briefly; since we are not using any security and login information we are going to set the anonymousIdentification property to true. We then enable the profile object. We then begin to add properties to the profile by using the add element setting the name property and allowanonymous to true. You can also set its data type. By Default it is a string, but you can set it to a int or a double etc. Now save and close your web.config file.
Going back to your code. In the pageload event replace the code with this.
if (IsPostBack == false)
{
Profile.MyNewProperty = "A new Profile Property";
}
Notice, that as you typed profile.m, the intellisense automatically knew about your new property that you just added to the config file. This is because profile is a strongly typed object.
Then in you button click event, replace the code with this to retrieve the value in the profile object.
Label1.Text = Profile.MyNewProperty;
Save and Run to test. Click the OK button. Notice that the label now reads whatever you typed in your profile property value. Now this can be stored for multiple pages and multiple profiles for your site. This is probably the preferred way to save state in asp.net nowadays.
Special Note. You would probably need sqlexpress to get this to work properly. Profile is set up automatically in SQLExpress when you install asp.net and sqlexpress. As by default the profile is set to store the data in a database and that database is sqlexpress. You can change it, but we won’t cover that in this lesson as it is out of our scope. If you need to change where the profile is stored, you can do some research by Googling “asp.net profile“ or by visiting these sites.
http://odetocode.com/Articles/440.aspx
http://msdn.microsoft.com/en-us/library/014bec1k.aspx
http://msdn.microsoft.com/en-us/library/2y3fs9xs.aspx
What if you want to maintain state at a global setting, for all users and all pages of your web site. Well, as we saw in a previous lesson, the application object will be perfectly suited to this. Remember, that we created a poor mans visitor counter, how we incremented and decremented the counter every time a user visited our site and then left or closed his browser. We used the application object for that. I am not going to go into details and explanation about how that works, but trust that you will refer back to that lesson to refresh you memories. That particular example worked across all users and all pages of our web site.
What are some other ways to pass data between two or more web pages?
Query String
Well one of the most common ways is one that you might already be familiar with. That is the old query string. Lets try and test this out. We are going to use a hyper link control. The beauty about the hyper link control is that we can change the text and url of the control to suite our needs. So you could hard code the url and text, or dynamicly code them or even bind them to a database.
So lets try this out. Close Explorer or stop the debug session if you haven't done so already. In your VS IDE go to your design view. Drag a hyper link control from the standard tabs on the toolbox, and drop it into your design area. Now add another aspx page to your project. In the solution explorer, right click on the web site root node (Not the solution node) and select “Add New Item”. Select the web form. You can leave the defaults as is or change them to suite your needs. Select OK.
On the new form that you just created, in design view, drag a label onto the form. Back to you original default form. Select the hyper link control. In the property window Change the text of the hyper link to say, “Page 2”. Then on the NavigateURL property set that to: “Default2.aspx?MyValue=Wow I just passed data to this form from another form.” You can also select the ellipse button and navigate to the correct page to select it. Then add the query string afterwards. Notice that a query string is in the form of a value pair. The query string is represented by the question mark.
Now in the second page/web form. Double click on the page to open the code behind file. You will notice that the page load event is what we are going to edit now. Type the following into the onload event.
Label1.Text = Request.QueryString["MyValue"].ToString();
What we are doing is retrieving the query string into the text property of the label control on the second form. Now you can add multiple value pairs to retrieve and pass multiple values to and from web pages. You could also use; Label1.Text = Request ["MyValue"].ToString(); The Request has multiple properties that are available to you including the query string, while the query string property has only, you guessed it, the query string values. Save. Select your default.aspx page, run and test.
Now what happens if you have a few controls on your form that you want to post to another form. You do not want to go ahead and code a mile long query string. Is there another way to post the data to another page. Well yes there is. It uses the regular "form post".
Add a new item to you website. Add a web form. You can leave the default or call it Page3. On page3 drop a label control. Like the previous example, double click the page to get to the code behind file. In the page load event type this in:
Label1.Text = Request.Form["TextBox1"].ToString();
Go back to the page2,Default2.aspx page. Add a Text box control and a button control. Selecting the textboxcontrol Make sure its ID is what ever you typed in the request.form value above. In ths case it is “TextBox1”. Now here comes the trick. Normally when you click the button to post the form, the form is, posted back to itself. In other words it will post or send the data to itself. But we do not want that. In .NET2.0 we have the opportunity to change the destination of the post back operation. Selecting the button, go to the properties window. Navigate to a property called “PostBackUrl”. Click the ellipse button to select page3/Default3.asp from your web site. This is going to be the page that we are going to post to, and the page that is going to receive the post data.
Right. Now Select your Default.aspx page, save all and Run to test. Your default page comes up with the hyper link. Click the hyper link, this takes us to page2 with the label changed to the text that you set in the query string. Now type some info into the text box, and click the button. What happens. Page3/Default3.aspx comes up with the text that you typed into the text box appearing in the label text and being diplayed in the web page. What have you just done? You have just passed form data from one page to a different page on your web site. This is refered to as a “Cross page post back”.
Conclusion
So what have we achieved in this lesson. Well we talked about the page objects and other objects associated with that and how to use those objects to programatically maintain state of web applications. We talked about state and how to maintain state. We also talked about how to pass data to and from various pages. What we never spoke about is the other ways of how to maintain state and pass data to and from pages, such as cookie data. But we will get into this at a later stage.