State Management


The HTTP protocol is stateless. The connection that is initiated from the client to the server can be closed after every request. However, normally it is necessary to remember some client information from one page to the other. There are several ways to accomplish this.

The main difference among the various ways to keep state is whether the state is stored on the client or on the server. The following table shows an overview of state management techniques and how long the state can be valid.

State Type

Client or Server Resource

Time Valid

ViewState

Client

Just within a single page.

Cookie

Client

Temporary cookies are deleted when the browser is closed; permanent cookies are stored on the disk of the client system.

Session

Server

Session state is associated with a browser session. The session is invalidated with a timeout (by default 20 minutes).

Application

Server

Application state is shared among all clients. This state is valid until the server restarts.

Cache

Server

Similar to application state, cache is shared. However, there's much better control when the cache should be invalidated.

Now let's take a more detailed look at these techniques.

Client-Side State Management

First, you are going to step into client-side state management: ViewState and cookies.

ViewState

One technique to store state on the client was already discussed: ViewState. ViewState is used automatically by the Web server controls to make events work. The ViewState contains the same state as the control when sent to the client. When the browser sends the form back to the server, the ViewState contains the original values, but the values of the controls that are sent contain the new values. If there's a difference, the corresponding event handlers will be invoked.

The disadvantage to using ViewState is that data is always transferred from the server to the client, and vice versa, which increases network traffic. To reduce the network traffic, ViewState can be turned off. The ViewState can be turned off for all controls within the page by setting the EnableViewState property to false with the Page directive:

 <%@ Page Language="C#" AutoEventWireUp="true" CodeFile="Default.aspx.cs" Inherits="Default_aspx" EnableViewState="false" %> 

The ViewState can also be configured on a control by setting the EnableViewState property of a control. No matter what the page configuration says, when the EnableViewState property is defined for the control, the control value is used. The value of the page configuration is used only for these controls when the ViewState is not configured.

It is also possible to store custom data inside the ViewState. This can be done by using an indexer with the ViewState property of the Page class. You can define a name that is used to access the ViewState value with the index argument.

 ViewState["mydata"] = "my data"; 

Reading the previously stored ViewState can be done as shown here:

 string mydata = (string)ViewState["mydata"]; 

In the HTML code that is sent to the client you can see the ViewState of the complete page within a hidden field:

 <input type="hidden" name="__VIEWSTATE" value="/wEPDwUKLTU4NzY5NTcwNw8WAh4HbXlzdGF0ZQUFbXl2YWwWAgIDD2QWAg IFDw8WAh4EVGV4dAUFbXl2YWxkZGTCdCywUOcAW97aKpcjt1tzJ7ByUA==" /> 

Using hidden fields has the advantage that every browser can use this feature, and the user cannot turn it off.

The ViewState is only remembered within a page. If the state should be valid across different pages, the use of cookies is an option for state on the client.

Cookies

A cookie is defined in the HTTP header. Use the HttpResponse class to send a cookie to the client. Response is a property of the Page class that returns an object of type HttpResponse. The HttpResponse class defines the Cookies property that returns an HttpCookieCollection. Multiple cookies can be returned to the client with the HttpCookieCollection.

The following sample code shows how a cookie can be sent to the client. First, an HttpCookie object is instantiated. In the constructor of this class, the name of the cookie is set — here it is mycookie. The HttpCookie class has a Values property to add multiple cookie values. If you just have one cookie value to return, you can use the Value property instead. However, if you plan to send multiple cookie values, it is better to add the values to a single cookie instead of using multiple cookies.

 string myval = "myval"; HttpCookie cookie = new HttpCookie("mycookie"); cookie.Values.Add("mystate", myval); Response.Cookies.Add(cookie); 

Cookies can be temporary and valid within a browser session, or they can be stored on the client disk. To make the cookie permanent, the Expires property must be set with the HttpCookie object. With the Expires property the date is defined when the cookie is not valid anymore; here, it is set to a date three months from now.

Although a specific date can be set, there is no guarantee that the cookie is stored until the date is reached. The user can delete the cookies, and the browser application will also delete the cookie if there are too many cookies stored locally. The browser can have a limit of 20 cookies for a single server, and 300 cookies for all servers. When the limit is reached, the cookies that haven't been used for some time are deleted.

HttpCookie cookie = new HttpCookie("mycookie"); cookie.Values.Add("mystate", "myval"); cookie.Expires = DateTime.Now.AddMonths(3); Response.Cookies.Add(cookie);

When the client requests a page from the server, and a cookie for this server is available on the client, the cookie is sent to the server as part of the HTTP request. Reading the cookie in the ASP.NET page can be done by accessing the cookies collection in the HttpRequest object.

Similarly to the HTTP response, the Page class has a Request property that returns an object of type HttpRequest. The property Cookies returns an HttpCookieCollection that can now be used to read the cookies that are sent by the client. A cookie can be accessed by its name with the indexer, and then the Values property of the HttpCookie is used to get the value from the cookie.

 HttpCookie cookie = Request.Cookies["mycookie"]; string myval = cookie.Values["mystate"]; 

ASP.NET makes it easy to use cookies. However, you must be aware of the cookie's restrictions. As already discussed, a browser accepts just 20 cookies from a single server and 300 cookies for all servers. Also, there's a restriction in the size of a cookie. A cookie cannot store more then 4K of data. These restrictions are in place so the client disk won't be filled with cookies.

Server-Side State Management

Instead of remembering state with the client, it is also possible to remember state with the server. Using client-side state has the disadvantage that the data sent across the network increases. Using server-side state has the disadvantage that the server must allocate resources for its clients.

Let's look into the server-side state management techniques.

Session

Session state is associated with a browser session. A session starts when the client at first opens an ASP.NET page on the server, and ends when the client doesn't access the server for 20 minutes.

You can define your own code that should run when a session starts or ends within the Global Application Class. A Global Application Class can be created with the menu Website Add New Item Global Application Class. With a new Global Application Class, the file global.asax is created. Inside this file some event handler routines are defined:

 <%@ Application Language="C#" %> <script runat="server"> void Application_Start(Object sender, EventArgs e) { // Code that runs on application startup } void Application_End(Object sender, EventArgs e) { //  Code that runs on application shutdown } void Application_Error(Object sender, EventArgs e) {  // Code that runs when an unhandled error occurs } void Session_Start(Object sender, EventArgs e) { // Code that runs when a new session is started } void Session_End(Object sender, EventArgs e) { // Code that runs when a session ends.  // Note: The Session_End event is raised only when the sessionstate mode // is set to InProc in the Web.config file. If session mode is set to  // StateServer or SQLServer, the event is not raised. } </script> 

Session state can be stored within an HttpSessionState object. The session state object that is associated with the current HTTP context can be accessed with the Session property of the Page class. In the Session_Start() event handler, session variables can be initialized; in the example, the session state with the name mydata is initialized to 0.

void Session_Start(Object sender, EventArgs e) {     // Code that runs on application startup Session["mydata"] = 0; }

Reading session state, again, can be done with the Session property using the session state name:

 void Button1_Click(object sender, EventArgs e) { int val = (int)Session["mydata"]; Label1.Text = val.ToString(); val += 4; Session["mydata"] = val; } 

To associate the client with its session variables, by default ASP.NET uses a temporary cookie with a session identifier. ASP.NET 2.0 also supports sessions without cookies where URL identifiers are used to map the HTTP requests to the same session.

Application

If data should be shared between different clients, application state can be used. Application state can be used in a manner that's very similar to how session state is used. With application state, the class HttpApplicationState is used, and it can be accessed with the Application property of the Page class.

In the example, the application variable with the name userCount is initialized when the Web application is started. Application_Start() is the event handler method in the file global.asax that gets invoked when the first ASP.NET page of the Website is started. This variable is used to count every user that is accessing the Website.

void Application_Start(Object sender, EventArgs e) {     // Code that runs on application startup Application["userCount"] = 0; }

In the Session_Start() event handler, the value of the application variable userCount is incremented. Before changing an application variable, the application object must be locked with the Lock() method; otherwise, threading problems can occur because multiple clients can access an application variable concurrently. After the value of the application variable was changed, the Unlock() method must be called. Be aware that the time between locking and unlocking is very short — you shouldn't read files or data from the database during that time. Otherwise, other clients must wait until the data access is completed.

void Session_Start(Object sender, EventArgs e) {     // Code that runs when a new session is started Application.Lock(); Application["userCount"] = (int)Application["userCount"] + 1; Application.UnLock(); }

Reading the data from the application state is as easy as it was with the session state:

 Label1.Text = Application["userCount"].ToString(); 

Don't store too much data in the application state, because the application state requires server resources until the server is stopped or restarted.

Cache

Cache is server-side state that is similar to application state in so far as it is shared with all clients. Cache is different from application state in that cache is much more flexible: there are many options to define when the state should be invalidated. Instead of reading a file with every request, or reading the database, the data can be stored inside the cache.

For the cache, the namespace System.Web.Caching and the class Cache are needed. Adding an object to the cache is shown here: the Page class has a Cache property that returns a Cache object. Using the Add() method of the Cache class, any object can be assigned to the cache. The first parameter of the Add() method defines the name of the cache item. The second parameter is the object that should be cached. With the third parameter dependencies can be defined, for example the cache item can be dependent on a file — when the file changes, the cache object is invalidated. With the sample there's no dependency because the null is set with this parameter. With parameters 4 and 5, a time can be set how long the cache item is valid. Parameter 4 defines an absolute time when the cache item should be invalidated, while parameter 5 requires a sliding time that invalidates the cache item after it hasn't been accessed for the time defined with the sliding expiration. Here, a sliding timespan is used so that the cache is invalidated after the cache item hasn't been used for 10 minutes. Parameter 6 defines a cache priority. CacheItemPriority is an enumeration for setting the cache priority. If the ASP.NET worker process has a high memory usage, the ASP.NET runtime removes cache items according to their priority. Items with a lower priority are removed first. With the last parameter, it is possible to define a method that should be invoked when the cache item is removed. An example of where this can be used is when the cache is dependent on a file. When the file changes, the cache item is removed and so the event handler is invoked. With the event handler the cache can be reloaded by reading the file once more.

 Cache.Add("mycache", myobj, null, DateTime.MaxValue, TimeSpan.FromMinutes(10), CacheItemPriority.Normal, null); 

Cache items can be read by using the indexer as you've already seen with the session and application state. Before using the object returned from the Cache property, always check whether the result is null, which happens when the cache is invalidated. When the returned value from the Cache indexer is not null, the returned object can be cast to the type that was used to store the cache item.

 object o = Cache["mycache"]; if (o == null) { // Reload the cache. } else { // Use the cache. MyClass myObj = (MyClass)o; //... } 




Beginning Visual C# 2005
Beginning Visual C#supAND#174;/sup 2005
ISBN: B000N7ETVG
EAN: N/A
Year: 2005
Pages: 278

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net