for RuBoard |
Preserving state across HTTP requests is a major problem in Web programming, and ASP.NET provides several facilities that are convenient to use. There are two main types of state to be preserved.
Application state is global information that is shared across all users of a Web application.
Session state is used to store data for a particular user across multiple requests to a Web application.
Static data members of a class are shared across all instances of a class. Hence static data members can be used to hold application state.
In our case study the class HotelState has a single static member acme of the class Acme .
class HotelState { static public Acme acme; }
Thus the hotelBroker and customers objects within acme will hold shared data that is the same for all users of the application. Each user will see the same list of hotels.
If you like, you may perform a small experiment at this stage. The directory HotelAdmin contains a special version of the Acme Web site that makes available the hotel administration interface IHotelAdmin to the special user with user ID of "admin." When this privileged user logins, a special home page will be displayed that provides a link to "Administer Hotels," as illustrated in Figure 10-31.
Run this Web application, either from the "Hotel Admin" link on the example programs home page or else via the URL http://localhost/ netcs/HotelAdmin/Main.aspx . Log in as "admin" and follow the link to "Administer Hotels." You will be brought to a page showing a list of all the hotels. Select the first hotel (Dixie) on the list and click the "Delete Selected Hotel" button and then the "Refresh" button. You will now see an updated list of hotels, as shown in Figure 10-32.
If your Web server is on a network, you can now try running the same Web application from a different client. Use the URL http://<server- name >/netcs/HotelAdmin/Main.aspx where "<server-name>" is the name of your server machine. [8] Again log in as "admin" and go to the "Hotel Admin" page. You should see the same list of hotels seen by the other client, with Hotel Dixie not on the list. [9]
[8] On a local machine you can use either the machine name or "localhost."
[9] Remember that at this point we are not using a database. Thus our example illustrates application state preserved in memory.
You can store global application information in the built-in Application object, an instance of the class HttpApplicationState . You can conveniently access this object through the Application property of the Page class. The HttpApplicationState class provides a key-value dictionary that you can use for storing both objects and scalar values.
For example, as an alternative to using the class HotelState with the static member acme that we previously used, we could instead use the Application object. We make up a string name for the key ”for example, "HotelState." In Global.asax we can then instantiate an Acme object and store it in the Application object using the following code.
protected void Application_Start(Object sender, EventArgs e) { Application["HotelState"] = new Acme(); }
You can then retrieve the Acme object associated with "HotelState" by using the index expression on the right-hand side and casting to Acme , as illustrated in the code,
Acme acme = (Acme) Application["HotelState"]; string name = acme.CurrentUser.FirstName;
As a little exercise in employing this technique, you may wish to modify the Step 2 case study to use the Application object in place of a static data member. The solution to this exercise can be found in the directory ApplicationObject . [10]
[10] In our current example of a Web application that is precompiled by Visual Studio, it is quite feasible to use a static variable, that can be shared across pages. But if your application is not precompiled, each page will be compiled individually at runtime, and sharing a static variable is no longer feasible . Hence you will have to use the Application object to share data.
You can store session information for individual users in the built-in Session object, an instance of the class HttpSessionState . You can conveniently access this object through the Session property of the Page class. The HttpSessionState class provides a key-value dictionary that you can use for storing both objects and scalar values, in exactly the same manner employed by HttpApplicationState .
Our case study provides an example of the use of a session variable " UserId " for storing a string representing the user ID. The session variable is created and initialized in Global.asax .
protected void Session_Start(Object sender, EventArgs e) { Session["UserId"] = ""; }
We use this session variable in the Page_Load event of our home page Main.aspx to detect whether we have a returning user or a new user. A new user is redirected to the login page. (Note that "returning" means coming back to the home page during the same session.)
private void Page_Load(object sender, System.EventArgs e) { // Put user code to initialize the page here string userid = (string)Session["UserId"]; if (userid == "") Response.Redirect("Login.aspx"); if (!IsPostBack) { Acme acme = (Acme) Application["HotelState"]; string name = acme.CurrentUser.FirstName; lblUserName.Text = "Welcome, " + name; lblLogin.Text = "(If you are not " + name + ", please login)"; } }
There are some interesting issues in the implementation of session variables .
Typically cookies are used to identify which requests belong to a particular session. What if the browser does not support cookies, or the user has disabled cookies?
There is overhead in maintaining session state for many users. Will session state "expire" after a certain time period?
A common scenario in high-performance Web sites is to use a server farm. How can your application access its data if a second request for a page is serviced on a different machine from that on which the first request was serviced?
Although by default ASP.NET uses cookies to identify which requests belong to a particular session, it is easy to configure ASP.NET to run cookieless. In this mode the Session ID, normally stored within a cookie, is instead embedded within the URL. We will discuss cookieless configuration in the next section.
By default session state times out after 20 minutes. This means that if a given user is idle for that period of time, the session is torn down; a request from the client will now be treated as a request from a new user, and a new session will be created. Again, it is easy to configure the timeout period, as we will discuss in the section on Configuration.
ASP.NET cleanly solves the Web farm problem, and many other issues, through a session state model that separates storage from the application's use of the stored information. Thus different storage scenarios can be implemented without affecting application code. The .NET state server does not maintain "live" objects across requests. Instead, at the end of each Web request, all objects in the Session collection are serialized to the session state store. When the same client returns to the page, the session objects are deserialized.
By default, the session state store is an in-memory cache. It can be configured to be memory on a specific machine, or to be stored in an SQL Server database. In these cases the data is not tied to a specific server, and so session data can be safely used with Web farms.
for RuBoard |