State for the Stateless Protocol


Preserving content and data (rather, managing state) is appropriately considered to be a critical part of ASP.NET application design. For this reason, the .NET platform has extensive support for state management and it offers many choices to fit your needs. These choices can easily be grouped into the following two general categories:

  • State management based on the client

  • State management based on the server

As the categories imply, your state management design choices will be decided between preserving content/data on the client side or the server side. Once you choose between the two, you will be faced with other design choices. As shown in Figure 15-3, you can imagine having a basic decision tree for state management.

click to expand
Figure 15-3: A state management decision tree for ASP.NET

Although the choices shown in Figure 15-3 are not necessarily cut-and-dry and often offer overlapping benefits, this basic decision tree should help get you started. Otherwise, the discussions that follow provide more details that should help prepare you for making those choices.

Note  

To help demonstrate how you would implement the various state management solutions, I have created two sample ASP.NET applications: StateManagementVB and StateManagementCobol. Relevant code snippets from these sample projects are included in each related section. The user interface for the sample applications is shown later in the section " User Interface for the Sample Applications."

Client-Based State Management

Generally speaking, you will want to look to client-based state management when you need to preserve small amounts of content/data. The following list presents the various types of client-based state management choices:

  • Query strings

  • Persistent cookies

  • Hidden forms fields

  • View state

In some cases, security concerns, user browser configurations, or just coding styles and preferences may be among the factors that will make one choice or another a better design candidate. Other factors exist that you will want to be aware of and take into consideration. In the following sections, you will drill down into each client-based state management choice for a more complete understanding.

Query Strings

The query string approach to storing and retrieving data is a very simple yet useful technique. Have you ever noticed a Web URL that included a question mark (?) as part of the URL string? If so, you have seen part of the implementation of a query string. The query string approach is an available option for programmatically passing a small amount of data from one Web page to another Web page.

Tip  

To retrieve query strings, the .NET Framework support includes use of the System.Web.HttpRequest class. Use this class to access the intrinsic Request object and the QueryString property. Be aware that the values stored in the QueryString property are stored as the type NameValueCollection class (as in System.Collections.Specialized.NameValueCollection ).

Say that you coded the page-to-page navigation logic using the Response object's Redirect method. When you code the URL parameter, you need only append a question mark symbol followed by one or more name /value pairs (e.g., name1=value1 , name2=value2 , and so on). The targeted page need only pull the passed values from the QueryString property of the Request object. That's it. It's that simple.

The simplicity of this client-side state management approach is certainly an important factor to consider for its use. If the data being passed is not of a sensitive nature and security is not a concern, the query string approach is certainly a viable option for client-side state management.

Note  

When you pass data using the query string approach, you will notice that the URL and the passed query string data appears in the browser's address bar as follows : http://www.somewebsite.com/targetedpage.aspx?name1=value1 .

Query String Code Samples

The code snippets in Listings 15-1 through 15-4 are taken from the sample projects created for this chapter.

Listing 15-1: Creating and Passing a QueryString in VB .NET
start example
 Response.Redirect("WebForm2.aspx?PassedQueryStringValue=" & Me.TextBox1.Text) 
end example
 
Listing 15-2: Retrieving a Passed QueryString in VB .NET
start example
 Me.TextBox1.Text = Request.QueryString("PassedQueryStringValue") 
end example
 
Listing 15-3: Creating and Passing a QueryString in COBOL .NET
start example
 001633    INITIALIZE MiscString 001634    SET MiscString1 TO PROP-TEXT OF TextBox1 001635    STRING "WebForm2.aspx?PassedQueryStringValue=" DELIMITED BY SIZE 001636           MiscString1 DELIMITED BY SPACES 001637            INTO MiscString 001638    INVOKE MyResponse "Redirect" USING BY VALUE MiscString. 
end example
 
Listing 15-4: Retrieving a Passed QueryString in COBOL .NET
start example
 000872    SET MyParamsObject TO PROP-PARAMS OF PROP-REQUEST OF SELF 000873    INVOKE MyParamsObject "get_Item"  000874    USING BY VALUE "PassedQueryStringValue" RETURNING MiscString1 000875    SET PROP-TEXT OF TextBox1 TO MiscString1 
end example
 

Persistent Cookies

Persistent cookies are basically small files that can be persisted (saved) to the client's local environment/hard disk. These files are then later retrieved as per the state management needs of your Web application. You would typically store small amounts of data in a cookie. Used in this way, persistent cookies are another client-based alternative for state management.

Note  

There has long been a 4096-byte maximum size limit of the cookie. Newer browsers are expected to increase the maximum size to an 8192-byte limit.

As with the query string approach, the implementation of a persistent cookies state solution is simple, requires minimal program coding to accomplish, and makes use of the Response and Request objects. Additionally, like query strings, persistent cookies should be used when security concerns do not apply and the data being persisted in the cookie is not of a sensitive nature. Nevertheless, persistent cookies (or just cookies ) do differ from query strings in a couple of significant ways.

Note  

You should not confuse persistent cookies with session cookies. I discuss session cookies later in the section "To Be a Cookieless Session or Not to Be a Cookieless Session."

For example, the use of cookies is dependent on end users' willingness to allow cookies from your Web site. As you may know, some people are not comfortable with the idea of Web sites saving a state-holding file onto their local hard disk. You and I, as developers, may not see a problem with cookies. However, not everyone approaches the topic of cookies with open arms.

Tip  

The Cookies property of the intrinsic Response and Request objects is used to create and retrieve cookies, respectively. The objects being added and retrieved are of the types System.Web.HttpCookieCollection and System.Web.HttpCookie .

Another example of where persistent cookies differ from query strings is in the capability of persistent cookies to allow expiration control of the persisted file. In other words, you can use persistent cookies to maintain state beyond the life of a page, a session, or even an application.

As you can see, each state management technique has its own strengths and weaknesses. One of the cookies approach's strengths is that it has been successfully implemented in many applications. Consequently, the use of cookies continues to be a state maintenance choice worthy of serious consideration.

Persistent Cookies Code Samples

The code snippets in Listings 15-5 through 15-8 are taken from the sample applications created for this chapter. Shown in both VB .NET and COBOL .NET, the persistent cookie is created and then retrieved.

Listing 15-5: Creating a Persistent Cookie in VB .NET
start example
 Dim MyFirstCookie As New HttpCookie("MiscText") MyFirstCookie.Value = Me.TextBox1.Text MyFirstCookie.Expires = DateTime.Now.AddSeconds(15) Response.Cookies.Add(MyFirstCookie) 
end example
 
Listing 15-6: Retrieving a Persistent Cookie in VB .NET
start example
 Dim myRetrievedCookie As HttpCookie myRetrievedCookie = Me.Request.Cookies("MiscText") Dim myCookieIsExpired As Boolean = (myRetrievedCookie Is Nothing) If myCookieIsExpired Then     Me.TextBox5.Text = "No Cookie" Else     Me.TextBox5.Text = Me.Request.Cookies("MiscText").Value End If 
end example
 
Listing 15-7: Creating a Persistent Cookie in COBOL .NET
start example
 002980    INVOKE CLASS-COOKIE "NEW" USING BY VALUE "MiscText"  002981       RETURNING MyCookieObject 002990    SET PROP-VALUE OF MyCookieObject TO PROP-TEXT OF TextBox1 003000    SET NowDateTime TO PROP-NOW OF CLASS-DATETIME 003010    INVOKE NowDateTime "AddSeconds" USING BY VALUE 15  003011       RETURNING WhenToExpire 003020    SET PROP-EXPIRES OF MyCookieObject TO WhenToExpire 003030    SET MyCurrentContext TO PROP-CURRENT OF CLASS-HTTPCONTEXT 003040    SET MyResponse TO PROP-RESPONSE OF MyCurrentContext 003050    SET MyCookieCollection TO PROP-COOKIES OF MyResponse 003060    INVOKE MyCookieCollection "Add" USING BY VALUE MyCookieObject 
end example
 
Listing 15-8: Retrieving a Persistent Cookie in COBOL.NET
start example
 003153    SET MyCookieCollection TO PROP-COOKIES OF PROP-REQUEST OF SELF 003154    INVOKE MyCookieCollection "get_Item"  003155       USING BY VALUE "MiscText" RETURNING MyCookieObject 003156    IF MyCookieObject NOT EQUAL NULL 003158        SET PROP-TEXT OF TextBox5 TO PROP-VALUE OF MyCookieObject 003159    ELSE 003160        SET PROP-TEXT OF TextBox5 TO "No Cookie" 003170    END-IF 
end example
 

Hidden Forms Fields

Similar to cookies and query strings, hidden forms fields are used for preserving small quantities of information, when security is not an issue, to preserve page-level state. A hidden forms field is simply an HTML element turned into an HTML server control. However, during runtime, this HTML server control is invisible. As shown in Figure 15-4, the Hidden HTML element appears in the VS .NET IDE Toolbox, under the HTML tab.

click to expand
Figure 15-4: The Hidden HTML element in the VS .NET IDE Toolbox

You can either type the appropriate HTML into the .aspx file or drag and drop the Hidden HTML element from the Toolbox onto your Web Form. Either way, you will want to this Hidden HTML element to an HTML server control (e.g., by adding the runat ="server" HTML attribute). The following code snippet shows an example of the HTML that would be used in the .aspx file:

 <input id="HiddenControl"         type=hidden         value="Your Initial Value, if desired"  runat=server> 

To store information into the hidden forms field, you simply set the Value property of the HTML server control. You can accomplish this either by editing the HTML code (as shown in the preceding code snippet) or by coding logic in the server-side code-behind file.

Tip  

The .NET Framework provides the System.Web.UI.HtmlControls.HtmlInputHidden class to expose the few class members against which you programmatically manipulate the hidden forms field . You will find that the reference terms "hidden control" and "hidden forms field" are used interchangeably.

I mentioned earlier that the hidden forms field is invisible during runtime. Well, that is not totally true. Yes, the field is invisible when you view the GUI (the Web Form). However, if you were to view the actual browser page source during runtime (by selecting View Source from your browser window), you would notice that the HTML for this hidden control is shown alongside the other HTML. More important, the content of the Value property is shown as well.

As long as the information saved in the Value property is not sensitive security-wise, this is considered acceptable. This is very important to realize. If security is an issue, the hidden forms field is not an appropriate solution for state management.

Hidden Forms Fields Code Samples

Listings 15-9 through 15-12 demonstrate the technique of populating and retrieving values with a hidden forms field.

Listing 15-9: Populating a Hidden Forms Field in VB .NET
start example
 Me.Hidden1.Value = Me.TextBox1.Text 
end example
 
Listing 15-10: Retrieving a Hidden Forms Field in VB.NET
start example
 Me.TextBox3.Text = Me.Hidden1.Value 
end example
 
Listing 15-11: Populating a Hidden Forms Field in COBOL .NET
start example
 SET PROP-VALUE OF Hidden1 TO PROP-TEXT OF TextBox1 
end example
 
Listing 15-12: Retrieving a Hidden Forms Field in COBOL.NET
start example
 SET PROP-TEXT OF TextBox3 TO PROP-VALUE OF Hidden1 
end example
 

Introducing View State

As a lead-in to the discussion of view state, let's quickly reflect back on two topics: the inheritance of System.Web.UI.Control [3] and the page life cycle.

The Web Form (Page class) and practically all the HTML and Web server controls inherit indirectly from the base class System.Web.UI.Control. This is important to realize because of the properties (and methods ) that are inherited from the base class System.Web.UI.Control.

Among these inherited members exists a very special property: the ViewState property. The Page class (server control) and practically all of the other server control classes expose this inherited ViewState property. One other inherited property, EnableViewState , can be set on each control to True or False. Setting True per control will enable the ViewState property to preserve data for the respective control.

Note  

This is yet another example of how understanding some of the basic points of object orientation will assist you in your .NET retraining effort.

The other topic I want to reflect on was discussed in the earlier section "Preparation for Cache and State." Please notice the pair of ViewState page-level events ( LoadViewState and SaveViewState ) that are raised. The LoadViewState event is among the events that are raised prior to the Page Load event. On the other hand, the SaveViewState event is among the events that are raised after the Page Load event.

You can see where this is leading. Now you are ready to move on to the actual view state topic. Thanks for your patience.

Using View State (the Other Hidden Forms Field)

You have basically two ways to get data into a control's ViewState property. You can use the control during runtime on the user interface by entering data into a TextBox server control during runtime. Optionally, you can programmatically set a control's ViewState property in the code-behind file.

When the SaveViewState event/method fires, the accumulated values of all available server control ViewState properties (per page) are saved to a String. This String is then used as the value of an automatically generated Hidden control (yes, another Hidden control) and sent to the browser along with the other HTML. Later, when the page is sent to the server again, the LoadViewState event/method will fire before the Page Load event takes place to restore any previously saved ViewState values.

The code in Listing 15-13 (which you can view by selecting View Source in your browser window) shows the HTML that is generated for this "other" Hidden control and sent to the browser. Because the ViewState values are hashed (and compressed), you can consider the information somewhat secure. Perhaps it's secure enough to be a deterrent, but not secure enough for the storage of passwords, financial information, and so forth.

Listing 15-13: The Hidden Control HMTL Generated to Support ViewState
start example
 <input type="hidden"  name="__VIEWSTATE" value="a String Text that is hashed and generally indecipherable" /> 
end example
 
Caution  

The ViewState information, as shown in the browser source window, is indecipherable . However, a skilled hacker may be able to manipulate the Hidden control's Value property. This is something to be aware of. Yes, the ViewState approach to state management is the most secure choice among the client-side state management choices. However, you should consider the level of security that accompanies ViewState as "limited."

You will find that the .NET Framework uses the System.Web.UI.StateBag class as a type for storage into the ViewState property. Given the common characteristics of a key/value pair collection type, this is useful information. In other words, the StateBag class has properties such as Count and Item . Additionally, the StateBag class has methods such as Add , Remove , and Clear .

Tip  

For performance reasons (network traffic, object serialization, and so on), you should only have the EnableViewState property turned on (per server control, page, or user control) according to your needs. If appropriate, you can set the EnableViewState property at server, site, application, and subdirectory levels using your XML-based configuration files. (I discuss the configuration file in Chapter 18.) Optionally, you can use the @ Page or @ Control directive to control the setting of the EnableViewState property.

As time allows, it would be a good idea to drill down further to discover more facts about ViewState. For now, you must move on. At this point, you have covered each of the client-based state management solutions. Following the view state code samples section, you will turn your attention to the server-based solutions for state management.

View State Code Samples

Listings 15-14 through 15-17 demonstrate the code needed to use view state.

Listing 15-14: Populating View State in VB .NET
start example
 Me.ViewState("MyNewViewSTate") = Me.TextBox1.Text 
end example
 
Listing 15-15: Retrieving View State in VB.NET
start example
 Me.TextBox2.Text = CStr(Me.ViewState("MyNewViewSTate")) 
end example
 
Listing 15-16: Populating View State in COBOL .NET
start example
 003066 SET MiscString1 TO PROP-TEXT OF TextBox1 003067 SET MyViewState TO PROP-VIEWSTATE OF SELF 003068 INVOKE MyViewState "set_Item"  003069 USING BY VALUE "MyNewViewSTate" MiscString1 
end example
 
Listing 15-17: Retrieving View State in COBOL.NET
start example
 003171 SET MyViewState TO PROP-VIEWSTATE OF MyPage 003172 INVOKE MyViewState "get_Item"  003173 USING BY VALUE "MyNewViewSTate" RETURNING MiscObject 003174 SET PROP-TEXT OF TextBox2 TO MiscObject AS CLASS-STRING 
end example
 

Server-Based State Management

Generally speaking, the server-based state management solutions offer a higher degree of security than that offered by the client-based solutions. You should look to state-based solutions when you want to preserve relatively larger amounts of application-level or session-level state. For each level (application and session) the .NET Framework leverages each of the respective intrinsic objects.

Note  

Server-based state management is applicable to both ASP.NET applications and ASP.NET XML Web services.

Application-Level State

In the section "Preparation for Cache and State," I briefly touched on the various application-level events that are raised when an HTTP request is sent to IIS. I would like to draw your attention to two specific events/methods for this application-level state discussion: Application_Start and Application_End . You will typically see these events/methods [4] predefined in the Global.asax file.

At the moment that the Application_Start event/method is raised, two intrinsic objects are instantiated and made available: the Application object and the Cache object. These two objects continue to exist and be available until the Application_End event/method is raised. You can use either of these two objects for your needs to "globally" preserve data. In other words, potentially for the life of a given application, across multiple sessions, across multiple HTTP requests , you can preserve data.

Note  

The Cache class referred to in this section is a different .NET Framework class from the one referred to in the earlier section "Save Your Cache!" The Cache class discussed in that earlier section is exposed by the Response object and is used for output cache management. The Cache class referred to in this section is exposed by the Context and Page objects and is used for application-level state management.

Once you are certain that you need to preserve data at the application level (i.e., across multiple sessions), you will want to take the following points into con sideration to help you choose between the two application-level state management techniques:

  • The length of time you wish to "preserve" the data and the approach that you wish to take to remove the data (if you are not preserving the data indefinitely)

  • The accumulated size of the preserved data

  • The need to update state outside of the Start and End application-level events/methods or the need to work with a multithreaded application design

  • The need for some preserved data to be associated with an external element (e.g., a file or directory) where a dependency may exist

You will now take a look at the two application-level state management tech niques to see how the points in the preceding list apply to each.

Note  

Data saved in the Application and Cache objects is granted a "global" scope. The extent of the "global" scope encompasses the entire IIS Application folder. This would typically be equivalent to the Solution folder shown in the VS .NET IDE Solution Explorer window.

Using the Application Class for State Management

In short, the following points are general guidelines to use that speak to the choice of using the Application class for application-level state management:

  • Use the Application class if the accumulated size of the preserved data is small and relatively static.

  • Use the Application class if you want the data to remain in memory for the entire life of the application.

  • Use the Clear method of the HttpApplicationState class to explicitly remove all the contents of the collection.

  • If you perform any updates to the HttpApplicationState collection outside of the Start and End application-level events/methods, use the Lock and Unlock methods to protect against concurrent update collisions.

Unfortunately, just telling you when to use the Application class does not really give you a solid understanding of the actual Application class. To better understand the Application class and the role it fulfills in state management, you will want to first understand some basic terminology.

For example, there is an intrinsic object identified as application that is actually represented by the .NET Framework System.Web.HttpApplication class. This particular class, HttpApplication , has a property called Application . There is a key/value pair collection type called HttpApplicationState that the Application property provides access to.

Note  

This is a very important point that's easy to overlook. The actual Application object has a property called Application, which provides the ApplicationState collection . Wouldn't it have been nice if Microsoft had named the Application property of the Application object ApplicationState instead?

Confused ? Don't worry. You aren't done yet. Say that you're working with the Context object ( System.Web.HttpContext ), and you notice that two properties are available: Application and ApplicationInstance . If you access the Application property of the Context object, you get the HttpApplicationState key/value pair collection. On the other hand, the ApplicationInstance property of the Context object provides a reference to an instance of the Application object (System.Web.HttpApplication).

Less confused? Good. Then you won't mind me mentioning that you can also access the HttpApplicationState key/value pair collection using the Application property of the Page object (the infamous System.Web.UI.Page class). In fact, you're more likely to see code that accesses the HttpApplicationState key/value pair collection using this approach.

Tip  

Notice that Microsoft is consistent (most of the time). Whether you are using the Application property from the Context object or the Application property from the Page object, you are getting the ApplicationState key/value pair collection. If you want to reference an instance of the Application object, you use the ApplicationInstance property of the Context object.

In other words, when you are in the code-behind file, and you just see the word "Application" being used to populate or retrieve application state data, understand that you are accessing the Application property of the Page object. Thus, you are accessing the HttpApplicationState key/value pair collection, not an instance of the Application object.

Tip  

You can use the Contents property of the HttpApplicationState class to obtain a reference to the HttpApplicationState object . This is useful when you want to iterate through the collection of values that may have been stored in the HttpApplicationState key/value pair collection.

Clear as mud? Great! Now, I can simply mention that the HttpApplicationState key/value pair collection is the repository for application-level state management when using the Application class.

Following the Application class code samples section, you will turn to take a look at the Cache class to review what it offers for application-level state management.

Application Class Code Samples

Listings 15-18 through 15-21 demonstrate how to use the ApplicationState class to preserve data. Notice that the Global.asax file is being used when the application-level state is captured.

Listing 15-18: Updating the Application Class in the Global.asax File in VB .NET
start example
 Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)     Application("MyTimeTheAppStarted") = DateTime.Now End Sub . . . Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)     Application("MyTimeTheLastRequestWasMade") = DateTime.Now End Sub 
end example
 
Listing 15-19: Retrieving the Application Class in VB .NET
start example
 Me.TextBox6.Text = Application("MyTimeTheAppStarted") Me.TextBox7.Text = Application("MyTimeTheLastRequestWasMade") 
end example
 
Listing 15-20: Updating the Application Class in the Global.asax File in COBOL .NET
start example
 . . . 000290 METHOD-ID. APPLICATION_START AS "Application_Start" IS PROTECTED. 000300 DATA DIVISION. 000301 WORKING-STORAGE SECTION. 000302    01 MyHttpApplicationState OBJECT REFERENCE CLASS-HttpApplicationState. 000303    01 NowDateTime   OBJECT REFERENCE CLASS-DATETIME. 000310 LINKAGE SECTION. 000320 01 PARAM-SENDER     OBJECT REFERENCE CLASS-OBJECT. 000330 01 PARAM-E OBJECT REFERENCE CLASS-EVENTARGS. 000340 PROCEDURE DIVISION USING BY VALUE PARAM-SENDER PARAM-E. 000341  000342    SET NowDateTime TO PROP-NOW OF CLASS-DATETIME 000343    SET MyHttpApplicationState TO PROP-APPLICATION OF SELF 000344    INVOKE MyHttpApplicationState "set_Item"  000345    USING BY VALUE "MyTimeTheAppStarted" NowDateTime 000350  000360 END METHOD APPLICATION_START. . . . 000470 METHOD-ID. APPLICATION_BEGINREQUEST  000471            AS "Application_BeginRequest" IS PROTECTED. 000480 DATA DIVISION. 000481 WORKING-STORAGE SECTION. 000483   01 MyHttpApplicationState OBJECT REFERENCE CLASS-HttpApplicationState. 000484   01 NowDateTime OBJECT REFERENCE CLASS-DATETIME. 000490 LINKAGE SECTION. 000500 01 PARAM-SENDER OBJECT REFERENCE CLASS-OBJECT. 000510 01 PARAM-E OBJECT REFERENCE CLASS-EVENTARGS. 000520 PROCEDURE DIVISION USING BY VALUE PARAM-SENDER PARAM-E. 000521  000523    SET NowDateTime TO PROP-NOW OF CLASS-DATETIME 000524    SET MyHttpApplicationState TO PROP-APPLICATION OF SELF 000525    INVOKE MyHttpApplicationState "set_Item"  000526    USING BY VALUE "MyTimeTheLastRequestWasMade" NowDateTime 000530  000540 END METHOD APPLICATION_BEGINREQUEST. . . . 
end example
 
Listing 15-21: Retrieving the Application Class in COBOL .NET
start example
 003680    SET MyHttpApplicationState TO PROP-APPLICATION OF SELF 003690    INVOKE MyHttpApplicationState "get_Item"  003700    USING BY VALUE "MyTimeTheAppStarted" RETURNING MiscObject1 003710    SET PROP-TEXT OF TextBox6 TO MiscObject1::"ToString"() 003720 003730    INVOKE MyHttpApplicationState "get_Item"  003740    USING BY VALUE "MyTimeTheLastRequestWasMade" RETURNING MiscObject1 003750    SET PROP-TEXT OF TextBox7 TO MiscObject1::"ToString"() 
end example
 
Using the Cache Class for State Management

Considering that you survived my long explanation about the Application class, I will spare you the trouble this time around. However, I will offer up just two points before getting in the simple details of why you will want to use the Cache class.

The first point is just a reminder. The discussion in this section bears abso lutely no relationship with the topic of output cache management previously discussed in the section "Save Your Cache!"

As for the other point, notice that the Cache class ( System.Web.Caching.Cache ) is exposed by the Cache property of both the Context object and the Page object. Again, Microsoft is being consistent. After all, both the Context object and Page object exposed the Application object (rather, the HttpApplicationState object).

That's it. Let's now take a look at the great features of the Cache class.

In case you did not meet the recommended criteria for using the Application class, and you still want to preserve data at the application level, the Cache class just may be the perfect solution for you. Here are the major features offered by the Cache class:

  • Easily expire data: Avoid having to explicitly remove the preserved data from memory.

  • Easily allow for prioritization of data expiration: It's possible to expire less- used data ahead of data being used more frequently.

  • Easily associate the preserved data with external elements (e.g., files, directories, and so on) to create dependencies: For example, you can cause data in the cache to be removed based on whether or not its external dependent target source changes.

  • Easily implement a callback/delegate feature: You can use the CacheItemRemovedCallback delegate and the CacheItemRemovedReason enumeration to raise/handle an event when a cached item is removed from the cache.

  • Easily avoid concurrent updating concerns: There is no need to use a Lock/ Unlock approach with the Cache class. It is completely thread-safe.

The implementation of the Cache class is rather simple, but its features are powerful. Yes, the Application class is a viable option for application-level state management. However, the opportunities made available by the Cache class might leave you wondering why the Application class would be used at all anymore.

Understand that the Application class existed before ASP.NET existed. That is, in the legacy Web (ASP) applications, this fancy Cache class did not exist as a second application-level state management option. The Application class was it .

I will dare to suggest that backward compatibility might be one of two reasons you will want to be aware of the Application class choice. You never know when you will need to maintain (or convert) a legacy Web (ASP) application. The second reason for learning about the Application class is that it is simple to use and it works.

start sidebar
A Quick Mainframe CICS Diversion

The callback/dependency-type features provided by the Cache class (for application-level state management) will remind you of one of the features you used in your CICS mainframe applications. When you used intrapartition CICS TD queues for data preservation, you may have had the chance to use the triggering-type feature referred to as Automatic Transaction Initiation (ATI). Yes, the new is gradually catching up with the old ” finally.

end sidebar
 

When you need to use application-level state management in your ASP.NET application design, you will want to know what your choices are. Obviously, the two choices (the Application class and the Cache class) have overlapping features. Being aware of them should increase the chances of you implementing application-level state management properly in your application.

Following the Cache class code samples section, you will continue your server-based state management exploration and turn your attention to the topic of session-level state management.

Cache Class Code Samples

Listings 15-22 through 15-25 show the basic use of the Cache class. You will want to experiment with several other options as you continue your retraining effort.

Listing 15-22: Updating the Application Cache Class in VB .NET
start example
 Cache.Insert("MyApplicationCache", Me.TextBox1.Text) 
end example
 
Listing 15-23: Retrieving the Application Cache Class in VB .NET
start example
 Me.TextBox10.Text = CType(Cache("MyApplicationCache"), String) 
end example
 
Listing 15-24: Updating the Application Cache Class in COBOL .NET
start example
 003320    SET MiscString1 TO PROP-TEXT OF TextBox1 003330    SET MyApplicationCache TO PROP-CACHE OF SELF 003340    INVOKE MyApplicationCache "set_Item"  003350    USING BY VALUE "MyApplicationCache" MiscString1 
end example
 
Listing 15-25: Retrieving the Application Cache Class in COBOL .NET
start example
 003870    SET MyApplicationCache TO PROP-CACHE OF SELF 003880    INVOKE MyApplicationCache "get_Item"  003890               USING BY VALUE "MyApplicationCache" RETURNING MiscObject1 003900    SET PROP-TEXT OF TextBox10 TO MiscObject1::"ToString"() 
end example
 

Session-Level State

Before you dive into the specifics of ASP.NET's support for session-level management, I would like to quickly establish a common understanding of what a session is.

Generally speaking, when you open a browser window and send your first HTTP request to a specific Web site, you have begun a new session. As you con tinue your Web visit, using any available tabs, buttons , and other controls on the site, you are typically continuing your session. Closing your browser window is recognized as the end of your session.

Note  

Some Web sites may offer login and logout features. As far as that given Web site is concerned , a login/ logoff may equate to the beginning and the end of a particular session for that specific user.

A session is generally understood to be user specific, originating from a spe cific browser window and, in most cases, from a specific computer. When any of these variables changes, a new session is usually understood to have begun or ended. Additionally, sessions are generally understood to have an expiration period established that is enacted following a given period of inactivity.

In your ASP.NET applications, you can identify when a session starts and ends. The Session HTTP module ( System.Web.SessionState.SessionStateModule ) will raise either the session_onStart event or the session_onEnd event according to the nature of the appropriate HTTP request. These events are subsequently handled in the Global.asax file by the session_Start and session_End events/methods, respectively.

Cross-Reference  

The topic of session-level events was further discussed in the previous section "Preparation for Cache and State."

With this understanding, you can define session-level state management as the preservation of data through the life of a given session. You will now take a look at the basic .NET Framework support for session state. Following that discussion, you will explore several options that you can take advantage of in ASP.NET for session-level state management.

Session State and the .NET Framework

Both the Page and Context objects expose a property called Session . Using the Session property, you can reference the System.Web.SessionState.HttpSessionState class. As you might have guessed, the HttpSessionState class provides the key/ value pair type collection into which you will store your "preserved session-level data." The HttpSessionState class exposes a SessionID property (a 120-bit string field) that uniquely identifies each session.

Understand the subtle implication of this. When you use the word "Session" in your code-behind file, you will be referencing the Session property of the page that is providing the HttpSessionState key/value pair type collection. Optionally, you can use the Session property from the Context object for the same returned result: the HttpSessionState key/value pair type collection.

start sidebar
Hey, They Forgot to Create a Session Object!

I have to ask, why didn't Microsoft create a Session object? Think about it. Take into consideration that the Context object has two properties to support the "Application." The Context object exposes an Application property that provides the ApplicationState object and the ApplicationInstance property that provides the Application object.

Therefore, when I discovered that the Context object had a Session property that returns a SessionState object, I expected to find a SessionInstance property that would return a Session object. To my surprise, there is only the Session property and the SessionState object. That is it. Interesting? Giving Microsoft the ben-efit of the doubt, I am sure they had their reasons.

end sidebar
 
A Configuration Primer

Although Chapter 18 presents a full discussion of the XML-based configuration files, I need to cover a few basic points here that relate to session state man agement. At this time, I will limit the discussion to the application-level configuration file.

To begin with, the application-level XML-based configuration file (named Web.config) is located in your ASP.NET Web application folder. Typically, there is a Web.config file created, by default, for each ASP.NET application. As shown in Figure 15-5, you can access the Web.config file from the VS .NET IDE Solution Explorer window.


Figure 15-5: Using the VS .NET Solution Explorer window to access the Web.config file

As shown in Figure 15-6, you can also use Windows Explorer (outside of the VS .NET IDE) to navigate to your application folder to locate, browse, and edit your Web.config file. [5]

click to expand
Figure 15-6: Using Windows Explorer to locate and edit the Web.config file

Whether you use Windows Explorer or the VS .NET IDE Solution Explorer window, you can double-click the Web.config file to "open" it. Once you open the Web.config file, you will see a generous number of XML statements and com ments. Scroll down to near the bottom of the Web.config file and you will see the <sessionState> XML element. The default setting for the <sessionState> XML element should resemble the following code snippet. Note that the Web.config file created in your COBOL .NET ASP.NET application may be missing the stateConnectionString and sqlConnectionString attributes. You can manually add these two attributes if needed.

 <sessionState              mode="InProc"             stateConnectionString="tcpip=127.0.0.1:42424"             sqlConnectionString="data source=127.0.0.1;user id=sa;password="             cookieless="false"              timeout="20"   /> 

The syntactical rules for the <sessionState> XML element are as follows:

 <sessionState              mode="OffInprocStateServerSQLServer"             stateConnectionString="tcpip=your server: your port"             sqlConnectionString="your sql connection string"             cookieless="truefalse"             timeout="your desired number of minutes"  /> 

Please take a moment to examine both of the preceding code snippets. The first one should resemble what you will see the first time you open your ASP.NET application's Web.config file. [6] The second one is a pseudo-code example that details the options that are available to you for each of the relevant <sessionState> XML attributes.

Tip  

For performance reasons, you should enable session state support according to the needs of your application. To enable or disable session state support for specific pages, you have the choice of using the @ Page directive (in the .aspx file) or adding and using a <Pages> element in your XML-based configuration file (using the enableSessionState attribute). Optionally, you can use the <sessionState> XML element ( mode="Off" ) to disable session state support for an entire application.

Cross-Reference  

I further discuss the configuration file in Chapter 18.

The Web.config file is responsible for ASP.NET application-level configuration settings. As its name implies, the <sessionState> XML element deals specifically with your session state configuration choices.

This section was provided as a quick primer on the session state portion of the XML-based configuration file. Now that you have established a point of reference, you can move on to the remaining portions of this chapter's session-level state management discussion.

To Be a Cookieless Session or Not to Be a Cookieless Session

Given the idea of what a session is, how does ASP.NET distinguish the HTTP requests coming from one session from those coming from a different session? This is where session cookies (also known as HTTP cookies ) come into the picture.

Although a session cookie is a different kind of cookie than the persisted cookie discussed earlier, it is still a cookie. In other words, the concerns of using cookies ”rather, the concerns of occasionally not being able to use cookies ”still apply.

This is where the cookieless="truefalse" option comes into the picture. As shown in the earlier section "A Configuration Primer," you can edit your Web.config file to easily turn on and off the "cookieless" feature. This configuration setting has the following effect:

  • cookieless="false" : This is the default setting. For the life of the session, a cookie (a small file) is passed to and from the client as part of the HTTP request header. The SessionID is obtained from the HTTP cookie.

  • cookieless="true" : This setting will cause the SessionID to be merged with the URL (called URL munging ). ASP.NET will then parse the URL as each HTTP request is processed to extract the SessionID.

When you use the default cookieless="false" setting, you will see something like the following in the address bar of your browser window (for the StateManagementCobol sample ASP.NET application):

 http://localhost/StateManagementCobol/WebForm1.aspx 

When you use the cookieless="true" setting, that same navigation appears differently in your browser's address bar. Instead, you see something that resembles the following. Notice that a 120-bit unique SessionID has been merged (munged) into the URL.

 http://localhost/StateManagementCobol/(finpzp45o5avhf55ai4i5b45)/WebForm1.aspx 

The use of cookies is a common practice. Nevertheless, because your client's browser may be set to not accept them, you do need to take this into consider ation. Depending on your need, you can use this configuration feature to control whether or not your application even attempts to pass an HTTP (session) cookie to the client.

Fortunately, ASP.NET is intelligent enough to handle either scenario (cookieless or not) and still provide full support for session-level state man agement. The next decision you need to make is related to the location in which the preserved session data is maintained . As you will see, this too is controlled in the Web.config file.

In-Process vs. Out-of-Process Session State

When you use session-level state management, you have the opportunity to decide on the location where your preserved data will be stored. In other words, as you add key/value pairs into the System.Web.SessionState.HttpSessionState class, you have option of having the HttpSessionState key/value pair collection either saved in the memory (referred to as in-process ) or saved in a database (referred to as out-of-process ).

You would use the Web.config file to choose the "mode" for your session-level state management. The two "connection string" attributes are ignored if you are using the in-process session state mode. The following code snippet shows the three XML attributes discussed in the section:

 . . . mode="OffInprocStateServerSQLServer" stateConnectionString="tcpip=your server: your port" sqlConnectionString="your sql connection string" . . . 

The in-process option offers the fastest processing model. When recovery is not a concern, this option is perfect for maintaining noncritical session-level data. Additionally, if your ASP.NET application is hosted on one physical Web server and does not participate in a Web farm “type of configuration, the in-process model may be the right choice for you. It is the default configuration setting ( mode="Inproc" ), as seen your Web.config file.

Note  

I have provided references at the end of this chapter to assist in your continued research into the two out-of-process options. In the meantime, the in-process option can certainly get you started and headed in the right direction. Later, as your needs dictate , you can easily switch session state "modes" using the Web.config file.

The other choice, to store the HttpSessionState key/value pair collections out of process brings with it another fork in the road, another choice to make. To pre serve your data using the out-of-process model (that is, out of the ASP.NET process), you need to choose between storing the session data in a state server and storing it in a SQL Server database.

The state server option ( mode="StateServer" ) takes advantage of a Windows Service and uses the stateConnectionString XML attribute in the Web.config file. The SQL Server option ( mode="SQLServer" ) takes advantage of an actual SQL Server database and uses the sqlConnectionString XML attribute in the Web.config file.

This brings you to the end of the session-level and server-side state man agement discussion. Considering the many options available for state management, it is likely that you will be able to choose the solution implemen tation that best fits the needs of your application. Be sure to take advantage of the references provided in the "To Learn More" section at the end of this chapter for your continued research and learning.

Following the session state code samples section, you will find a brief dis cussion of a few additional techniques used by ASP.NET to preserve data between each HTTP request. I loosely refer to these techniques as "other types of state management."

Session State Code Samples

Listings 15-26 through 15-29 demonstrate the use of the Session State class. Notice that I have chosen to use the Global.asax file when the Session State class is being updated.

Listing 15-26: Updating the Session State Class Inside the Global.asax File in VB .NET
start example
 Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs)       Session("MyTimeTheSessionStarted") = DateTime.Now       Session("MyTimeTheSessionIdentity") = _          System.Web.HttpContext.Current.Session.SessionID End Sub 
end example
 
Listing 15-27: Retrieving the Session State Class in VB .NET
start example
 Me.TextBox8.Text = Session("MyTimeTheSessionStarted") Me.TextBox9.Text = Session("MyTimeTheSessionIdentity") 
end example
 
Listing 15-28: Updating the Session State Class Inside the Global.asax File in COBOL .NET
start example
 000380 METHOD-ID. SESSION_START AS "Session_Start" IS PROTECTED. 000390 DATA DIVISION. 000391 WORKING-STORAGE SECTION. 000392   01 MyHttpSessionState   OBJECT REFERENCE CLASS-HttpSessionState. 000394   01 NowDateTime          OBJECT REFERENCE CLASS-DATETIME. 000395   01 MiscString1          PIC X(25). 000396   01 MyCurrentContext     OBJECT REFERENCE CLASS-HTTPCONTEXT. 000400 LINKAGE SECTION. 000410 01 PARAM-SENDER OBJECT REFERENCE CLASS-OBJECT. 000420 01 PARAM-E OBJECT REFERENCE CLASS-EVENTARGS. 000430 PROCEDURE DIVISION USING BY VALUE PARAM-SENDER PARAM-E. 000431  000432    SET NowDateTime TO PROP-NOW OF CLASS-DATETIME 000433    SET MyHttpSessionState TO PROP-SESSION OF SELF 000434    INVOKE MyHttpSessionState "set_Item"  000435    USING BY VALUE "MyTimeTheSessionStarted" NowDateTime 000436  000437    SET MyCurrentContext TO PROP-CURRENT OF CLASS-HTTPCONTEXT 000438    SET MyHttpSessionState TO PROP-SESSION OF MyCurrentContext 000439    SET MiscString1 TO PROP-SESSIONID OF MyHttpSessionState 000440    INVOKE MyHttpSessionState "set_Item"  000441    USING BY VALUE "MyTimeTheSessionIdentity" MiscString1 000442  000450 END METHOD SESSION_START. 
end example
 
Listing 15-29: Retrieving the Session State Class in COBOL .NET
start example
 003914    SET MyHttpSessionState TO PROP-SESSION OF SELF 003915    INVOKE MyHttpSessionState "get_Item"  003916    USING BY VALUE "MyTimeTheSessionStarted" RETURNING MiscObject1 003917    SET PROP-TEXT OF TextBox8 TO MiscObject1::"ToString"() 003918 003919    INVOKE MyHttpSessionState "get_Item"  003920    USING BY VALUE "MyTimeTheSessionIdentity" RETURNING MiscObject1 003921    SET PROP-TEXT OF TextBox9 TO MiscObject1::"ToString"() 
end example
 

[3] This topic was previously discussed in the section "The System.Web.UI Namespace" in Chapter 13.

[4] The raised events are application_onStart and application_onEnd . The Application_Start and Application_End methods are provided to handle the raised events.

[5] In the case of COBOL .NET, the Web.config file may not appear in the VS .NET IDE Solution Explorer window. In this case, you can use Windows Explorer outside of the VS .NET IDE to locate and edit the Web.config file.

[6] The stateConnectionString and sqlConnectionString attributes may be missing when you create a Web configuration file using COBOL .NET. You can manually add these two attributes if needed.




COBOL and Visual Basic on .NET
COBOL and Visual Basic on .NET: A Guide for the Reformed Mainframe Programmer
ISBN: 1590590481
EAN: 2147483647
Year: 2003
Pages: 204

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