zoukankan      html  css  js  c++  java
  • Understanding the Session Object in ASP.NET 2.0

    今天csdn上面看到有关Session的文章,写得很好,是.net1.1的,手痒,就把书上的文字复制一下,仅供参考
    http://blog.csdn.net/cityhunter172/archive/2006/05/14/727743.aspx
    http://tb.blog.csdn.net/TrackBack.aspx?PostId=727743
    ---------------------------------------------------
    In classic ASP, the Session object was held in-process (as was everything) to the IIS process. The user
    received a cookie with a unique key in the form of a GUID. The Session key was an index into a dictionary
    where object references could be stored.
    In Asp.Net 2.0 the Session object still offers an in-process option, but also includes an out-of-process
    and database-backed option. Additionally, the developer has the option to enable a cookieless Session
    State where the Session key appears in the URL rather than being sent as a cookie.
    708
    Chapter 19
    Sessions and the Event Model
    The HttpApplication object raises a series of events during the life of the HTTP protocol request:
    ❑ BeginRequest: This event fires at the beginning of every request.
    ❑ AuthenticateRequest: This event is used by the security module and indicates that a request
    is about to be authenticated. This is where the security module, or you, determines who the user is.
    ❑ AuthorizeRequest: This event is used by the security module and indicates that a request is
    about to be authorized. This is where the security module, or you, determines what the user is
    allowed to do.
    ❑ ResolveRequestCache: This event is used by the caching module to determine whether this
    now-authorized request can bypass any additional processing.
    ❑ AcquireRequestState: This event indicates that all session state associated with this HTTP
    request is about to be acquired.
    ❑ PreRequestHandlerExecute: This is the last event you get before the HttpHandler class for
    this request is called.
    ❑ PostRequestHandlerExecute: This is the event that fires just after the HttpHandler is called.
    ❑ ReleaseRequestState: Indicates that the session state should be stored. Session state is persisted
    at this point, using whatever Session-state module is configured in web.config.
    ❑ UpdateRequestCache: All work is complete, and the resulting output is ready to be added to
    the cache.
    ❑ EndRequest: This is the last event called during a request.
    You can see from the preceding list that AcquireRequestState and ReleaseRequestState are two
    significant events in the life of the Session object.
    By the time your application code executes, the Session object has been populated using the Session
    key that was present in the cookie, or as you see later, from the URL. If you want to handle some
    processing at the time the Session begins, rather than handling it in AcquireRequestState, you can
    define an event handler for the Start event of a SessionState HttpModule.
    Your application code, usually in the form of a Page, executes at this point in the
    process.
    Session state is available to you, the developer, after the AcquireRequestState
    event fires. The session state key that is unique to each user is retrieved either from
    a cookie or from the URL.
    709
    State Management
    Sub Session_OnStart()
    ‘this fires after session state has been acquired by the SessionStateModule.
    End Sub
    Pre- and post-events occur at almost every point within the life of an HTTP request. Session state can be
    manipulated at any point after AcquireRequestState, including in the Global.asax within the
    Session_OnStart event.
    The HttpSessionState object can be used within any event in a subclass of the Page object. Because
    the pages you create in Asp.Net 2.0 derive from System.Web.UI.Page, you can access Session State as
    a collection because System.Web.SessionState.HttpSession implements ICollection.
    The Page has a public property aptly named Session that automatically retrieves the Session from the
    current HttpContext. Even though it seems as if the Session object lives inside the page, it actually
    lives in the HttpContext, and the page’s public Session property actually retrieves the reference to the
    Session State. This convenience not only makes it more comfortable for the classic ASP programmer, but
    saves you a little typing as well.
    The Session object can be referred to within a page in this way:
    Session[“SomeSessionState”] = “Here is some data”;
    or
    HttpContext.Current.Session[“SomeSessionState”] = “Here is some data”;
    The fact that the Session object actually lives in the current HTTP context is more than just a piece of
    trivia. This knowledge enables you to access the Session object in contexts other than the page (such as
    in your own HttpHandler).
    Configuring Session State Management
    All the code within a page refers to the Session object using the dictionary-style syntax seen previously,
    but the HttpSessionState object uses a Provider Pattern to extract possible choices for session state
    storage. You can choose between the included providers by changing the sessionState element in
    web.config. Asp.Net ships with the following three storage providers:
    ❑ In-Process Session State Store: Stores sessions in the Asp.Net in-memory cache
    ❑ Out-Of-Process Session State Store: Stores sessions in the Asp.Net State Server service aspnet_
    state.exe
    ❑ Sql Session State Store: Stores sessions in Microsoft SQL Server database and is configured
    with aspnet_regsql.exe
    The Session object includes both Start and End events that you can hook event
    handlers to for your own needs. However, the Session_OnEnd event is supported
    only in the In-Process Session State mode. This event will not be raised if you use
    out-of-process State Server or SQL Server modes. The Session ends, but your
    handlers will never hear about it.
    710
    Chapter 19
    The format of the web.config file’s sessionState element is shown in the following code:
    <configuration>
    <system.web>
    <sessionState mode=”Off|InProc|StateServer|SQLServer|Custom” ../>
    </system.web>
    ...
    Begin configuring session state by setting the mode=”InProc” attribute of the sessionState element in
    the web.config of a new Web site. This is the most common configuration for session state within
    Asp.Net 2.0 and is also the fastest, as you see next.
    In-Process Session State
    When the configuration is set to InProc, session data is stored in the HttpRuntime’s internal cache in
    an implementation of ISessionStateItemCollection that implements ICollection. The session
    state key is a 120-bit value string that indexes this global dictionary of object references. When session
    state is in process, objects are stored as live references. This is an incredibly fast mechanism because no
    serialization occurs, nor do objects leave the process space. Certainly, your objects are not garbagecollected
    if they exist in the In-Process Session object because a reference is still being held.
    Additionally, because the objects are stored (held) in memory, they use up memory until that Session
    times out. If a user visits your site and hits one page, he might cause you to store a 40MB XmlDocument
    in in-process session. If that user never comes back, you are left sitting on that large chunk of memory
    for the next 20 minutes or so (a configurable value) until the Session ends, even if the user never returns.
    InProc Gotchas
    Although the InProc Session model is the fastest, the default, and the most common, it does have a
    significant limitation. If the worker process or application domain recycles, all session state data is lost.
    Also, Asp.Net application may restart for a number of reasons, such as the following:
    ❑ You’ve changed the web.config or Global.asax file or “touched” it by changing its
    modified date.
    ❑ You’ve modified files in the \bin or \App_Code directory.
    ❑ The processModel element has been set in the web.config or machine.config file indicating
    when the application should restart. Conditions that could generate a restart might be a memory
    limit or request-queue limit.
    ❑ Antivirus software modifies any of the previously mentioned files. This is particularly common
    with antivirus software that innoculates files.
    This said, In-Process Session State works great for smaller applications that require only a single Web
    server, or in situations where IP load balancing is returning each user to the server where his original
    Session was created.
    If a user already has a Session key, but is returned to a different machine than the one on which his
    session was created, a new Session is created on that new machine using the session ID supplied by the
    user. Of course, that new Session is empty and unexpected results may occur. However if
    regenerateExpiredSessionId is set to True in the web.config file, a new Session ID is created and
    assigned to the user.
    711
    State Management
    Web Gardening
    Web gardening is a technique for multiprocessor systems wherein multiple instances of the Asp.Net
    worker process are started up and assigned with processor affinity. On a larger Web server with as many
    as four CPUs, you could have anywhere from one to four worker processes hosting Asp.Net 2.0.
    Processor affinity means literally that an Asp.Net 2.0 worker process has an affinity for a particular CPU.
    It’s “pinned” to that CPU. This technique is usually enabled only in very large Web farms.
    Don’t forget that In-Process Session State is just that—in-process. Even if your Web application consists
    of only a single Web server and all IP traffic is routed to that single server, you have no guarantee that
    each subsequent request will be served on the same processor. AWeb garden must follow many of the
    same rules that a Web farm follows.
    Storing Data in the Session Object
    In the following simple example, in a Button_Click event the content of the text box is added
    to the Session object with a specific key. The user then clicks to go to another page within the same
    application, and the data from the Session object is retrieved and presented in the browser.
    Note the use of the <asp:HyperLink> control. Certainly, that markup could have been hard coded as
    HTML, but this small distinction will serve us well later. Additionally, the URL is relative to this site, not
    absolute. Watch for it to help you later in this chapter.
    Listing 19-1 illustrates how simple it is to use the Session object. It behaves like any other
    IDictionary collection and allows you to store keys of type String associated with any kind
    of object. The Retrieve.aspx file referenced will be added in Listing 19-2.
    Listing 19-1: Setting values in session state
    Asp.Net--C#
    <%@ Page Language=”C#” CodeFile=”Default.aspx.cs” Inherits=”_Default” %>
    Asp.Net--VB.NET
    <%@ Page Language=”VB” AutoEventWireup=”false” CodeFile=”Default.aspx.vb”
    Inherits=”_Default” %>
    Asp.Net
    <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.1//EN”
    “http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd”>
    <html xmlns=”http://www.w3.org/1999/xhtml” >
    <head runat=”server”>
    <title>Session State</title>
    </head>
    <body>
    <form id=”form1” runat=”server”>
    If you’re using Web gardening on a multiprocessor system, you must not use In-Process
    Session State or you lose Sessions. In-Process Session State is appropriate only where
    there is a 1:1 ratio of applications to application domains.
    712
    Chapter 19
    <div>
    <asp:TextBox ID=”TextBox1” Runat=”server”></asp:TextBox>
    <asp:Button ID=”Button1” Runat=”server” Text=”Store in Session”
    OnClick=”Button1_Click” />
    <br />
    <asp:HyperLink ID=”HyperLink1” Runat=”server”
    NavigateUrl=”Retrieve.aspx”>Next Page</asp:HyperLink>
    </div>
    </form>
    </body>
    </html>
    VB
    Partial Class _Default
    Inherits System.Web.UI.Page
    Protected Sub Button1_Click(ByVal sender As Object, _
    ByVal e As System.EventArgs)
    Session(“mykey”) = TextBox1.Text
    End Sub
    End Class
    C#
    public partial class _Default : System.Web.UI.Page
    {
    protected void Button1_Click(object sender, EventArgs e)
    {
    Session[“mykey”] = TextBox1.Text;
    }
    }
    The page from Listing 19-1 renders in the browser as shown in Figure 19-2. The Session object is
    accessed as any dictionary indexed by a string key. See Chapter 10 for more on collections and lists.

    Figure 19-2
    713
    State Management
    More details about the page and the Session object can be displayed to the developer if page tracing is
    enabled. You add this element to your application’s web.config file inside the <system.web> element,
    as follows:
    <trace enabled=”true” pageOutput=”true”/>
    Now tracing is enabled, and the tracing output is sent directly to the page. More details on tracing and
    debugging are given in Chapter 21. For now, make this change and refresh your browser.
    In Figure 19-3, the screen shot is split to show both the top and roughly the middle of the large amount
    of trace information that is returned when trace is enabled. Session State is very much baked into the
    fabric of Asp.Net. You can see in the Request Details section of the trace that not only was this page the
    result of an HTTP POST but the Session ID was as well—elevated to the status of first-class citizen.
    However, the Asp.Net Session ID lives as a cookie by default, as you can see in the Cookies collection
    at the bottom of the figure.

    Figure 19-3
    The default name for that cookie is ASP.NET_SessionId, but its name can be configured via the
    cookieName attribute of the <sessionState> element in web.config. Some large enterprises allow
    only certain named cookies past their proxies, so you might need to change this value when working on
    an extranet or a network with a gateway server; but this would be a very rare occurrence. The
    cookieName is changed to use the name “Foo” in the following example.
    <sessionState cookieName=”Foo” mode=”InProc”></sessionState>
    714
    Chapter 19
    The trace output shown in Figure 19-3 includes a section listing the contents of the Session State collection.
    In the figure, you can see that the name mykey and the value Hanselman are currently stored.
    Additionally, you see the CLR data type of the stored value; in this case, it’s System.String.
    Now add the next page, retrieve.aspx, which pulls this value out of the session. Leave the
    retrieve.aspx page as the IDE creates it and add a Page_Load event handler, as shown in Listing 19-2.
    Listing 19-2: Retrieving values from the session
    VB
    Partial Class Retrieve
    Inherits System.Web.UI.Page
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
    Handles Me.Load
    Dim myValue As String = CType(Session(“mykey”), String)
    Response.Write(myValue)
    End Sub
    End Class
    C#
    public partial class Retrieve : System.Web.UI.Page
    {
    protected void Page_Load(object sender, EventArgs e)
    {
    string myValue = (string)Session[“mykey”];
    Response.Write(myValue);
    }
    }
    Because the session contains object references, the resulting object is converted to a string by way of a
    cast in C# or the CType function in VB.
    Making Sessions Transparent
    It is unfortunate that the cast to a string is required to retrieve data from the Session object. Combined
    with the string key used as an index, it makes for a fairly weak contract between the page and the
    Session object. You can create a session helper that is specific to your application to hide these details,
    or you can add properties to a base Page class that presents these objects to your pages in a friendlier
    way. Because the generic Session object is available as a property on System.Web.UI.Page, add a new
    class derived from Page that exposes a new property named MyKey.
    The Value column of the trace output comes from a call to the contained object’s
    ToString() method. If you store your own objects in the Session, you can override
    ToString() to provide a text-friendly representation of your object that might make
    the trace results more useful.
    715
    State Management
    Start by right-clicking your project and selecting Add New Item from the context menu to create a new
    class. Name it SmartSessionPage and click OK. The IDE may tell you that it would like to put this new
    class in the /App_Code folder to make it available to the whole application. Click Yes.
    Your new base page is very simple. Via derivation, it does everything that System.Web.UI.Page does,
    plus it has a new property, as shown in Listing 19-3.
    Listing 19-3: A more session-aware base page
    VB
    Imports Microsoft.VisualBasic
    Imports System
    Imports System.Web
    Public Class SmartSessionPage
    Inherits System.Web.UI.Page
    Private Const MYSESSIONKEY As String = “mykey”
    Public Property MyKey() As String
    Get
    Return CType(Session(MYSESSIONKEY), String)
    End Get
    Set(ByVal value As String)
    Session(MYSESSIONKEY) = value
    End Set
    End Property
    End Class
    C#
    using System;
    using System.Web;
    public class SmartSessionPage : System.Web.UI.Page
    {
    private const string MYKEY = “mykey”;
    public string MyKey
    {
    get
    {
    return (string)Session[MYKEY];
    }
    set
    {
    Session[MYKEY] = value;
    }
    }
    }
    Now, return to your code from Listing 19-1 and derive your pages from this new base class. To do this,
    change the base class in the code-beside files to inherit from SmartSessionPage. Listing 19-4 shows
    how the class in the code-behind file derives from the SmartSessionPage, which in turn derives from
    System.Web.UI.Page. Listing 19-4 outlines the differences to make to Listing 19-1.
    716
    Chapter 19
    Listing 19-4: Deriving from the new base page
    VB--ASPX
    <%@ Page Language=”VB” AutoEventWireup=”false” CodeFile=”Default.aspx.vb”
    Inherits=”_Default” %>
    VB--Default.aspx.vb Code
    Partial Class _Default
    Inherits SmartSessionPage
    Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
    ‘ Session(“mykey”) = TextBox1.Text
    MyKey = TextBox1.Text
    End Sub
    End Class
    C#--ASPX
    <%@ Page Language=”C#” CodeFile=”Default.aspx.cs” Inherits=”_Default” %>
    C#--Default.aspx.cs Code
    public partial class _Default : SmartSessionPage
    {
    protected void Button1_Click(object sender, EventArgs e)
    {
    //Session[“mykey”] = TextBox1.Text;
    MyKey = TextBox1.Text;
    }
    }
    In this code, you change the access to the Session object so it uses the new public property. After the
    changes in Listing 19-3, all derived pages have a public property called MyKey. This property can be
    used without any concern about casting or Session key indexes. Additional specific properties can be
    added as other objects are included in the Session.
    Here’s an interesting language note: In Listing 19-3 the name of the private string value collides with
    the public property in VB because they differ only in case. In C#, a private variable named MYKEY and a
    public property named MyKey are both acceptable. Be aware of things like this when creating APIs that
    will be used with multiple languages. Aim for CLS compliance.
    Advanced Techniques for Optimizing Session Performance
    By default, all pages have write access to the Session. Because it’s possible that more than one page
    from the same browser client might be requested at the same time (using frames, more than one browser
    window on the same machine, and so on), a page holds a reader/writer lock on the same Session for
    the duration of the page request. If a page has a writer lock on the same Session, all other pages
    requested in the same Session must wait until the first request finishes. To be clear, the Session is
    locked only for that SessionID. These locks don’t affect other users with different Sessions.
    717
    State Management
    In order to get the best performance out of your pages that use Session, Asp.Net allows you declare
    exactly what your page requires of the Session object via the EnableSessionState @Page attribute.
    The options are True, False, or ReadOnly:
    ❑ EnableSessionState=”True”: The page requires read and write access to the Session. The
    Session with that SessionID will be locked during each request.
    ❑ EnableSessionState=”False”: The page does not require access to the Session. If the code
    uses the Session object anyway, an HttpException is thrown stopping page execution.
    ❑ EnableSessionState=”ReadOnly”: The page requires read-only access to the Session. A
    reader lock is held on the Session for each request, but concurrent reads from other pages can
    occur. If a page is requested requiring read-only access and two other requests are queued up,
    one requesting read-only access and one requesting read/write access, the read-only page is
    executed while the read/write access page waits.
    By modifying the @Page direction in default.aspx and retrieve.aspx to reflect each page’s actual
    need, you affect performance when the site is under load. Add the EnableSessionState attribute to
    the pages as shown in the following code:
    VB--Default.aspx
    <%@ Page Language=”VB” EnableSessionState=”True” AutoEventWireup=”false”
    CodeFile=”Default.aspx.vb” Inherits=”_Default” %>
    VB--Retrieve.aspx
    <%@ Page Language=”VB” EnableSessionState=”ReadOnly” AutoEventWireup=”false”
    CodeFile=”Retrieve.aspx.vb” Inherits=”Retrieve” %>
    C#--Default.asp
    <%@ Page Language=”C#” EnableSessionState=”True”
    CodeFile=”Default.aspx.cs” Inherits=”_Default”%>
    C#--Retrieve.aspx
    <%@ Page Language=”C#” EnableSessionState=”ReadOnly”
    CodeFile=”Retrieve.aspx.cs” Inherits=”Retrieve” %>
    Under the covers, Asp.Net is using marker interfaces from the System.Web.SessionState
    namespace to keep track of each page’s needs. When the partial class for default.aspx is generated,
    it implements the IRequiresSessionState interface, whereas Retrieve.aspx implements
    IReadOnlySessionState. All HttpRequests are handled by objects that implement IHttpHandler.
    Pages are handled by a PageHandlerFactory. You can find more on HttpHandlers in Chapter 23.
    Internally, the SessionStateModule is executing code similar to the pseudocode that follows:
    If TypeOf HttpContext.Current.Handler Is IReadOnlySessionState Then
    Return SessionStateStore.GetItem(itemKey)
    Else ‘If TypeOf HttpContext.Current.Handler Is IRequiresSessionState
    Return SessionStateStore.GetItemExclusive(itemKey)
    End If
    As the programmer, you know things about the intent of your pages at compile time that Asp.Net
    can’t figure out at runtime. By including the EnableSessionState attribute in your pages, you allow
    Asp.Net to operate more efficiently. Remember, Asp.Net always makes the most conservative decision
    unless you give it more information to act upon.
    718
    Chapter 19
    Out-of-Process Session State
    Out-of-process session state is held in a process called aspnet_state.exe that runs as a Windows
    Service. You can start the Asp.Net state service by using the Services MMC snap-in or by running the
    following net command from the command line:
    net start aspnet_state
    By default, the State Service listens on TCP port 42424, but this port can be changed at the registry key
    for the service, as shown in the following code. The State Service is not started by default.
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\
    aspnet_state\Parameters\Port
    Change the web.config’s settings from InProc to StateServer, as shown in the following code.
    Additionally, you must include the stateConnectionString attribute with the IP address and port on
    which the Session State Service is running. In a Web farm (a group of more than one Web server), you
    could run the State Service on any single server or on a separate machine entirely. In this example, the
    State Server is running on the local machine, so the IP address is the localhost IP 127.0.0.1. If you run the
    State Server on another machine, make sure the appropriate port is open—in this case, TCP port 42424.
    <configuration>
    <system.web>
    <sessionState mode=”StateServer”
    stateConnectionString=”tcpip=127.0.0.1:42424”/>
    </system.web>
    </configuration>
    The State Service used is always the most recent one installed with Asp.Net. That means that if you are
    running Asp.Net 2.0 and 1.1 on the same machine, all the states stored in Session objects for any and
    all versions of Asp.Net are kept together in a single instance of the Asp.Net 2.0 State Service.
    Because your application’s code runs in the Asp.Net Worker Process (aspnet_wp.exe, or w3wp.exe)
    and the State Service runs in the separate aspnet_state.exe process, objects stored in the Session can’t
    be stored as references. Your objects must physically leave the worker process via binary serialization.
    Performance Tip: If you’re coding a page that doesn’t require anything of the Session,
    by all means, set EnableSessionState=”False”. This causes Asp.Net to schedule
    that page ahead of pages that require Session and helps with the overall scalability of
    your app. Additionally, if your application doesn’t use Session at all, set Mode=”Off”
    in your web.config file to reduce overhead for the entire application.
    719
    State Management
    For a world-class, highly available, and scalable Web site, consider using a Session
    model other than InProc. Even if you can guarantee via your load-balancing appliance
    that your Sessions will be sticky, you still have application-recycling issues to contend
    with. The out-of-process state service’s data is persisted across application pool recycles
    but not computer reboots. However, if your state is stored on a different machine
    entirely, it will survive Web Server recycles and reboots.

    Only classes that have been marked with the [Serializable] attribute may be serialized. In the context
    of the Session object, think of the [Serializable] attribute as a permission slip for instances of your
    class to leave the worker process.
    Update the SmartSessionPage file in your \App_Code directory to include a new class called Person, as
    shown in Listing 19-5. Be sure to mark it as Serializable or you will see the error shown in Figure 19-4.

    Figure 19-4
    As long as you’ve marked your objects as [Serializable], they’ll be allowed out of the Asp.Net
    process. Notice that the objects in Listing 19-5 are marked [Serializable].
    For a world-class, highly available, and scalable Web site, consider using a Session
    model other than InProc. Even if you can guarantee via your load-balancing appliance
    that your Sessions will be sticky, you still have application-recycling issues to contend
    with. The out-of-process state service’s data is persisted across application pool recycles
    but not computer reboots. However, if your state is stored on a different machine
    entirely, it will survive Web Server recycles and reboots.
    720
    Chapter 19
    Listing 19-5: A serializable object that can be used in the out-of-process Session
    VB
    <Serializable()> _
    Public Class Person
    Public firstName As String
    Public lastName As String
    Public Overrides Function ToString() As String
    Return String.Format(“Person Object: {0} {1}”, firstName, lastName)
    End Function
    End Class
    C#
    [Serializable]
    public class Person
    {
    public string firstName;
    public string lastName;
    public override string ToString()
    {
    return String.Format(“Person Object: {0} {1}”, firstName, lastName);
    }
    }
    Because you put an instance of the Person class from Listing 19-5 into the Session object that is
    currently configured as StateServer, you should add a strongly typed property to the base Page class
    from Listing 19-3. In Listing 19-6 you see the strongly typed property added. Note the cast on the property
    Get, and the strongly typed return value indicating that this property deals only with objects of type
    Person.
    Listing 19-6: Adding a strongly typed property to SmartSessionPage
    VB
    Public Class SmartSessionPage
    Inherits System.Web.UI.Page
    Private Const MYSESSIONPERSONKEY As String = “myperson”
    Public Property MyPerson() As Person
    Get
    Return CType(Session(MYSESSIONPERSONKEY), Person)
    End Get
    Set(ByVal value As Person)
    Session(MYSESSIONPERSONKEY) = value
    End Set
    End Property
    End Class
    721
    State Management
    C#
    public class SmartSessionPage : System.Web.UI.Page
    {
    private const string MYPERSON = “myperson”;
    public Person MyPerson
    {
    get
    {
    return (Person)Session[MYPERSON];
    }
    set
    {
    Session[MYPERSON] = value;
    }
    }
    Now, add code to create a new Person, populate its fields from the text box, and put the instance into
    the now-out-of-process Session State Service. Then, retrieve the Person and write its values out to the
    browser using the overloaded ToString() method from Listing 19-5.
    In Listing 19-7, the value of the TextBox is split into a string array and the first two strings are put into a
    Person instance. For example, if you entered “Scott Hanselman” as a value, “Scott” is put into
    Person.firstName and “Hanselman” is put into Person.lastName. The values you enter should appear
    when they are retrieved later in Retrieve.aspx and written out to the browser with the overloaded
    ToString method.
    Listing 19-7: Setting and retrieving objects from the Session using State Service and
    a base page
    VB--Default.aspx.vb
    Partial Class _Default
    Inherits SmartSessionPage
    Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
    Dim names As String()
    names = TextBox1.Text.Split(“ “c) ‘ “ “c creates a char
    Dim p As New Person()
    p.firstName = names(0)
    p.lastName = names(1)
    Session(“myperson”) = p
    End Sub
    End Class
    Certain classes in the Framework Class Library are not marked as serializable. If you
    use objects of this type within your own objects, these objects are not serializable at
    all. For example, if you include a DataRow field in a class and add your object to the
    State Service, you receive a message telling you it “. . . is not marked as serializable”
    because the DataRow includes objects that are not serializable.
    722
    Chapter 19
    VB--Retrieve.aspx.vb
    Partial Class Retrieve
    Inherits SmartSession Page
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
    Handles Me.Load
    Dim p As Person = MyPerson
    Response.Write(p) ‘ ToString will be called!
    End Sub
    End Class
    C#--Default.aspx.cs
    public partial class _Default : SmartSessionPage
    {
    protected void Button1_Click(object sender, EventArgs e)
    {
    string[] names = TextBox1.Text.Split(‘ ‘);
    Person p = new Person();
    p.firstName = names[0];
    p.lastName = names[1];
    Session[“myperson”] = p;
    }
    }
    C#--Retrieve.aspx.cs
    public partial class Retrieve : SmartSessionPage
    {
    protected void Page_Load(object sender, EventArgs e)
    {
    Person p = MyPerson;
    Response.Write(p); //ToString will be called!
    }
    }
    Now, launch the browser, enter your name (or “Scott Hanselman” if you like), click the button to store it
    in the Session, and then visit Retrieve.aspx via the hyperlink. You see the result of the ToString()
    method via Response.Write, as shown in Figure 19-5.
    The completed code and techniques shown in Listing 19-7 illustrate a number of best practices for session
    management:
    ❑ Mark your objects as Serializable if you might ever use non-In-Proc session state.
    ❑ Even better, do all your development with a local session state server. This forces you to discover
    non-serializable objects early, gives you a sense of the performance and memory
    usages of aspnet_state.exe, and allows you to choose from any of the session options at
    deployment time.
    ❑ Use a base Page class or helper object with strongly typed properties to simplify your code. It
    enables you to hide the casts made to session keys otherwise referenced throughout your code.
    These best practices apply to all state storage methods, including SQL session state.

    Figure 19-5
    SQL-Backed Session State
    Asp.Net sessions can also be stored in a SQL Server database. InProc offers speed, StateServer offers a
    resilience/speed balance, and storing sessions in SQL Server offers resilience that can serve sessions to a
    large Web farm that persists across IIS restarts, if necessary.
    SQL-backed session state is configured with aspnet_regsql.exe. This tool adds and removes
    support for a number of Asp.Net features such as cache dependency (see Chapter 20) and
    personalization/membership (Chapters 15 and 16) as well as session support. When you run
    aspnet_regsql.exe from the command line without any options, surprisingly, it pops up a GUI as
    shown in Figure 19-6. This utility is located in the .NET Framework’s installed directory, usually
    c:\windows\microsoft.net\framework\<version>.

    The text of the dialog shown in Figure 19-6 contains instructions to run aspnet_regsql from the
    command line with a “-?” switch. You have a huge number of options, so you’ll want to pipe it through
    in a form like aspnet_regsql -? | more. You see the session-state–specific options shown here:
    -- SESSION STATE OPTIONS --
    -ssadd Add support for SQLServer mode session state.
    -ssremove Remove support for SQLServer mode session state.
    -sstype t|p|c Type of session state support:
    t: temporary. Session state data is stored in the
    “tempdb” database. Stored procedures for managing
    session are installed in the “ASPState” database.
    Data is not persisted if you restart SQL. (Default)
    p: persisted. Both session state data and the stored
    procedures are stored in the “ASPState” database.
    c: custom. Both session state data and the stored
    procedures are stored in a custom database. The
    database name must be specified.
    725
    State Management
    -d <database> The name of the custom database to use if -sstype is
    “c”.
    Three options exist for session state support: t, p, and c. The most significant difference is that the
    -sstype t option does not persist session state data across SQL Server restarts, whereas the -sstype p
    option does. Alternatively, you can specify a custom database with the -c option and give the database
    name with -d database.
    The following command-line example configures your system for SQL session support with the SQL
    Server on localhost with an sa password of wrox and a persistent store in the ASPState database (certainly,
    you know not to deploy your system using sa and a weak password, but this simplifies the example). If
    you’re using SQL Express, replace “localhost” with “.\SQLEXPRESS”.
    C:\ >aspnet_regsql -S localhost -U sa -P wrox -ssadd -sstype p
    Start adding session state.
    ...........
    Finished.
    Next, open up Enterprise Manager and look at the newly created database. Two tables are created—
    ASPStateTempApplications and ASPStateTempSessions—as well as a series of stored procedures to
    support moving the session back and forth from SQL to memory.
    If your SQL Server has its security locked down tight, you might get an Error 15501 after executing
    aspnet_regsql.exe that says “An error occurred during the execution of the SQL file
    ‘InstallSqlState.sql’.” The SQL error number is 15501 and the SqlException message is: This
    module has been marked OFF. Turn on ‘Agent XPs’ in order to be able to access the module.
    If the job does not exist, an error from msdb.dbo.sp_delete_job is expected. This is a
    rather obscure message, but aspnet_regsql.exe is trying to tell you that the extended stored
    procedures it needs to enable session state are not enabled for security reasons. You’ll need to allow
    them explicitly. To do so, execute the following commands within the SQL Server 2005 Query Analyzer
    or the SQL Server 2005 Express Manager:
    USE master
    EXECUTE sp_configure ‘show advanced options’, 1
    RECONFIGURE WITH OVERRIDE
    GO
    EXECUTE sp_configure ‘Agent XPs’, 1
    RECONFIGURE WITH OVERRIDE
    GO
    EXECUTE sp_configure ‘show advanced options’, 0
    RECONFIGURE WITH OVERRIDE
    GO
    Now, change the web.config <sessionState> element to use SQL Server, as well as the new
    connection string:
    <sessionState mode=”SQLServer” sqlConnectionString=”data source=127.0.0.1;user
    id=sa;password=Wrox”/>
    726
    Chapter 19
    The session code shown in Listing 19-7 continues to work as before. However, if you open up the
    ASPStateTempSessions table, you see the serialized objects. Notice in Figure 19-7 that the Session ID
    from the trace appears as a primary key in a row in the ASPStateTempSessions table.

    Figure 19-7
    Figure 19-7 shows the SessionId as seen in the Request Details of Asp.Net tracing and how that
    SessionId appears in the SessionId column of the ASPStateTempSessions table in the ASPState
    database just created. Notice also the ASPStateTempApplications table that keeps track of each IIS
    application that may be using the same database to manage sessions.
    If you want to use your own database to store session state, you specify the database name with the
    -d <database> switch of aspnet_regsql.exe and include the allowCustomSqlDatabase=”true”
    attribute and the name of the database in the connection string:
    <sessionState allowCustomSqlDatabase=”true” mode=”SQLServer”
    sqlConnectionString=”data source=127.0.0.1;database=MyCustomASPStateDatabase;”/>
    The user ID and password can be included in the connection string; or Windows Integrated Security
    can be used if the Asp.Net Worker Process’s identity is configured with access in SQL Server.
    727
    State Management
    Extending Session State with Other Providers
    Asp.Net 2.0 Session State is built on a new, extensible, provider-based storage model. You can
    implement custom providers that store session data in other storage mechanisms simply by deriving
    from SessionStateStoreProviderBase. This extensibility feature also allows you to generate session
    IDs via your own algorithms by implementing ISessionIDModule.
    You start by creating a class that inherits from SessionStateStoreProviderBase. The session module
    will call methods on any session provider as long as it derives from
    SessionStateStoreProviderBase. Register your custom provider in your application’s web.config,
    as in the following example:
    <sessionState mode =”Custom” customProvider =”WroxProvider”>
    <providers >
    <add name =”WroxProvider” type =”Wrox.WroxStore, WroxSessionSupplier”/>
    </providers>
    </sessionState>
    Asp.Net initializes the SessionStateModule, and these methods are called on any custom
    implementation:
    ❑ Initialize: This method is inherited ultimately from System.Configuration
    .Provider.ProviderBase and is called immediately after the constructor. With this method,
    you set your provider name and call up to the base implementation of Initialize.
    ❑ SetItemExpireCallback: With this method, you can register any methods to be called when a
    session item expires.
    ❑ BeginRequest: This method is called by the SessionStateModule for each request. This is an
    early opportunity to get ready for any requests for data that are coming.
    ❑ CreateNewStoreData: With this method, you create a new instance of
    SessionStateStoreData, the data structure that holds session items, the session timeout
    values, and any static items.
    When a session item is requested, Asp.Net calls your implementation to retrieve it. Implement the
    following methods to retrieve items:
    ❑ GetItemExclusive: This method is where you get SessionStateStoreData from your chosen
    store. You may have created an Oracle provider, stored data in xml, or wherever you like.
    ❑ GetItem: This is your opportunity to retrieve it as you did in GetItemExclusive except without
    exclusive locking. You may or may not care, depending on what backing store you’ve chosen.
    When it’s time to store an item, the following method is called:
    ❑ SetAndReleaseItemExculsive: Here you should save the SessionStateStoreData object
    to your custom store.
    728
    Chapter 19
    Expect to see a number of third-party session state providers available to both open source and for sale
    soon after the release of Asp.Net 2.0.
    The derivation-based provider module for things such as session state will no doubt create a rich
    ecosystem of enthusiasts who will help push the functionality to new places Microsoft did not expect.
    Cookieless Session State
    In the previous example, the Asp.Net Session State ID was stored in a cookie. Some devices don’t
    support cookies, or a user may have turned off cookie support in his browser. Cookies are convenient
    because the values are passed back and forth with every request and response. That means every
    HttpRequest contains cookie values, and every HttpResponse contains cookie values. What is the only
    other thing that is passed back and forth with every Request and Response? The URL.
    If you include the cookieless=”UseUri” attribute in the web.config, Asp.Net does not send the
    Asp.Net Session ID back as a cookie. Instead, it modifies every URL to include the Session ID just
    before the requested page:
    <sessionState mode=”SQLServer” cookieless=”UseUri” sqlConnectionString=”data
    source=127.0.0.1;user id=sa;password=Wrox”></sessionState>
    Notice that the Session ID appears in the URL as if it were a directory of its own situated between
    the actual Web site virtual directory and the page. With this change, server-side user controls such as the
    HyperLink control, used in Listing 19-1, have their properties automatically modified. The link in
    Listing 19-1 could have been hard-coded as HTML directly in the Designer, but then Asp.Net could not
    modify the target URL shown in Figure 19-8.
    The Session ID is a string that contains only the ASCII characters allowed in a URL. That makes sense
    when you realize that moving from a cookie-based Session-State system to a cookieless system requires
    putting that Session State value in the URL.
    Notice in Figure 19-8 that the request URL contains a Session ID within parentheses. One disadvantage
    to cookieless Sessions is how easily they can be tampered with. Certainly, cookies can be tampered with
    using HTTP sniffers, but URLS can be edited by anyone. The only way Session State is maintained is if
    every URL includes the Session ID in this way.

    Additionally, all URLS must be relative. Remember that the Session ID appears as if it were a directory.
    The Session is lost if a relative URL such as /myapp/retrieve.aspx is invoked. If you are generating
    URLs on the server side, use HttpResponse.ApplyAppPathModifier(). It changes a URL when the
    Session ID is embedded, as shown here:
    Response.Write(Response.ApplyAppPathModifier(“foo/bar.aspx”));
    The previous line generates a URL similar to the following:
    /myapp/ (S(avkbnbml4n1n5mi5dmfqnu45))/foo/bar.aspx
    Notice that not only was session information added to the URL, but it was also converted from a relative
    URL to an absolute URL, including the application’s virtual directory. This method can be useful when
    you need to use Response.Redirect or build a URL manually to redirect from an HTTP page to an
    HTTPS page while still maintaining cookieless session state.

    -------------------------------------------
    《asp.net 2.0 Professional》
    -------------------------------------------
    以上文字和图片未经本人允许请勿转载。
  • 相关阅读:
    Android基于mAppWidget实现手绘地图(五)--如何创建地图资源
    Android基于mAppWidget实现手绘地图(四)--如何附加javadoc
    Android基于mAppWidget实现手绘地图(三)--环境搭建
    Android基于mAppWidget实现手绘地图(二)--概要
    Android基于mAppWidget实现手绘地图(一)--简介
    网络通信之Socket与LocalSocket的比较
    Python-Django 整合Django和jquery-easyui
    Python-Django 第一个Django app
    RobotFramework 官方demo Quick Start Guide rst配置文件分析
    RobotFramework RobotFramework官方demo Quick Start Guide浅析
  • 原文地址:https://www.cnblogs.com/xucanzhao/p/402779.html
Copyright © 2011-2022 走看看