How to Share Session State Between Classic ASP and ASP.NET(

80酷酷网    80kuku.com

  asp.net|sessionApplies to:
   Microsoft® ASP.NET

Summary: Discusses how to share session state between classic ASP and Microsoft ASP.NET using Microsoft .NET Framework classes and the serialization feature of the .NET Framework. Sharing session state allows converting existing ASP applications to ASP.NET applications in stages while running the applications side by side. (12 printed pages)

Download the source code for this article.

Contents
Introduction
Conceptual Overview
ASP.NET implementation
ASP Implementation
Demo Program
Incorporating the COM Object in an Existing ASP Application
Limitation/Improvement
Conclusion

Introduction
Microsoft® ASP.NET is the latest Microsoft technology for developing Web-based applications. It offers a number of advantages over the classic ASP script technology, including: 1) a better development structure by separating the UI presentation from business logic; 2) its code is fully compiled instead of interpreted as in classic ASP; and 3) its compile feature in conjunction with its caching support means significantly better performance for sites written in ASP.NET over equivalent sites written in classic ASP.

Despite the potential benefit of converting existing ASP applications to ASP.NET, many existing ASP applications are mission critical and complex. The conversion process could be resource intensive and induce additional risk to the existing application. One approach to address these issues is to run the ASP and ASP.NET side by side, and convert one section of the application at a time to ASP.NET. In order to run the new and old application side by side, a mechanism is needed to share the session state between classic ASP and ASP.NET. In this article, I'll discuss how the session state can be shared by using several classes and the serialization feature of the Microsoft® .NET Framework.

Conceptual Overview
Cookies are the most common way for Web applications to identify the user session, and can be used to identify session state for both classic ASP and ASP.NET. Session state information is stored in memory in ASP script and can't be shared with other applications, such as ASP.NET. If the session state is stored in a common format in Microsoft® SQL Server, the session state can be accessible by both classic ASP and ASP.NET.

In this example, a cookie named mySession is used to identify the user session. When a user makes a request to the Web application, the user will be issued a unique cookie to identify the session. On subsequent request, the browser will send the unique cookie back to the server to identify the session. Before the requested Web page is loaded, a custom object will reload the user session data from SQL Server using the unique cookie. The session state is accessible in the Web page through the custom object. After the Web request is finished, the session data will be persisted back to the SQL Server as the request terminates (see Figure 1).



Figure 1. Sample data flow

ASP.NET implementation
In ASP.NET, every Web page derives from the System.Web.UI.Page class. The Page class aggregates an instance of the HttpSession object for session data. In this example, a custom Page class called SessionPage is derived from the System.Web.UI.Page to offer all the same features as the Page class. The only difference with the derived page is that the default HttpSession is overridden with a custom session object. (Using the new modifier for the instance variable, C# allows the derived class to hide members of the base class.)

   public class SessionPage : System.Web.UI.Page
   {
      ...
      public new mySession Session = null;
      ...
   }

The custom session class is responsible for storing the session state in memory using the HybridDictionary object. (HybridDictionary can efficiently handle any number of session elements.) The custom session class will limit the session data type to be string only for interoperability with the classic ASP. (The default HttpSession allows any type of data to be stored in the session, which will not interoperate with the classic ASP.)

   [Serializable]
public class mySession
   {
      private HybridDictionary dic = new HybridDictionary();

      public mySession()
      {
      }

      public string this [string name]
      {
         get
         {
            return (string)dic[name.ToLower()];
         }
         set
         {
            dic[name.ToLower()] = value;
         }
      }
   }

The Page class exposes different events and methods for customization. In particular, the OnInit method is used to set the initialize state of the Page object. If the request does not have the mySession cookie, a new mySession cookie will be issued to the requester. Otherwise, the session data will be retrieved from SQL Server using a custom data access object, SessionPersistence. The dsn and SessionExpiration values are retrieved from the web.config.

      override protected void OnInit(EventArgs e)
      {
         InitializeComponent();
         base.OnInit(e);
      }
      private void InitializeComponent()
      {    
         cookie = this.Request.Cookies[sessionPersistence.SessionID];

         if (cookie == null)
         {
            Session = new mySession();
            CreateNewSessionCookie();
            IsNewSession = true;
         }
         else
            Session = sessionPersistence.LoadSession(
Server.UrlDecode(cookie.Value).ToLower().Trim(),
dsn,
SessionExpiration
);
            
         this.Unload += new EventHandler(this.PersistSession);
      }
      private void CreateNewSessionCookie()
      {
         cookie = new HttpCookie(sessionPersistence.SessionID,
            sessionPersistence.GenerateKey());
         this.Response.Cookies.Add(cookie);
      }

The SessionPersistence class uses the BinaryFormatter of the Microsoft .NET Framework to serialize and deserialize the session state in binary format for optimal performance. The resulting binary session state data can then be stored in the SQL Server as an image field type.

      public  mySession LoadSession(string key, string dsn,
                                    int SessionExpiration)
      {
         SqlConnection conn = new SqlConnection(dsn);
         SqlCommand LoadCmd = new SqlCommand();
         LoadCmd.CommandText = command;
         LoadCmd.Connection = conn;
         SqlDataReader reader = null;
         mySession Session = null;

         try
         {
            LoadCmd.Parameters.Add("ID", new Guid(key));
            conn.Open();
            reader = LoadCmd.ExecuteReader();
            if (reader.Read())
            {
               DateTime LastAccessed =
reader.GetDateTime(1).AddMinutes(SessionExpiration);
               if (LastAccessed >= DateTime.Now)
                  Session = Deserialize((Byte[])reader["Data"]);
            }
         }
         finally
         {
            if (reader != null)
               reader.Close();
            if (conn != null)
               conn.Close();
         }
         
         return Session;
      }
private mySession Deserialize(Byte[] state)
      {
         if (state == null) return null;
         
         mySession Session = null;
         Stream stream = null;

         try
         {
            stream = new MemoryStream();
            stream.Write(state, 0, state.Length);
            stream.Position = 0;
            IFormatter formatter = new BinaryFormatter();
            Session = (mySession)formatter.Deserialize(stream);
         }
         finally
         {
            if (stream != null)
               stream.Close();
         }
         return Session;
      }

At the end of the request, the Page class Unload event is fired, and an event handler registered with the Unload event will serialize the session data into binary format and save the resulting binary data into SQL Server.

      private void PersistSession(Object obj, System.EventArgs arg)
      {      sessionPersistence.SaveSession(
               Server.UrlDecode(cookie.Value).ToLower().Trim(),
               dsn, Session, IsNewSession);
      }
      public void SaveSession(string key, string dsn,
mySession Session, bool IsNewSession)
      {
         SqlConnection conn = new SqlConnection(dsn);
         SqlCommand SaveCmd = new SqlCommand();         
         SaveCmd.Connection = conn;
         
         try
         {
            if (IsNewSession)
               SaveCmd.CommandText = InsertStatement;
            else
               SaveCmd.CommandText = UpdateStatement;

            SaveCmd.Parameters.Add("ID", new Guid(key));
            SaveCmd.Parameters.Add("Data", Serialize(Session));
            SaveCmd.Parameters.Add("LastAccessed", DateTime.Now.ToString());
      
            conn.Open();
            SaveCmd.ExecuteNonQuery();
         }
         finally
         {
            if (conn != null)
               conn.Close();
         }
      }
private Byte[] Serialize(mySession Session)
      {
         if (Session == null) return null;

         Stream stream = null;
         Byte[] state = null;

         try
         {
            IFormatter formatter = new BinaryFormatter();
            stream = new MemoryStream();
            formatter.Serialize(stream, Session);
            state = new Byte[stream.Length];
            stream.Position = 0;
            stream.Read(state, 0, (int)stream.Length);
            stream.Close();
         }
         finally
         {
            if (stream != null)
               stream.Close();
         }
         return state;
      }

The SessionPage class and its associated classes are packaged in the SessionUtility assembly. In a new ASP.NET project, a reference will be made to the SessionUtility assembly, and every page will derive from the SessionPage instead of from the Page class in order to share session with classic ASP codes. Once the porting is completed, the new application can switch back to use the native HttpSession object by commenting out the Session variable declaration in the SessionPage class to unhide the base HttpSession.

分享到
  • 微信分享
  • 新浪微博
  • QQ好友
  • QQ空间

上一篇关于验证控件

下一篇ms--help

点击: