熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

在ASP與ASP.NET之間共享對話狀態(1)

2022-06-13   來源: .NET編程 

  前言
  
  ASPNET是微軟提供的最新的開發基於Web的應用程序的技術它提供了大量的比傳統ASP腳本技術的好處包括
  
  )通過把UI表現層(presentation)與商業邏輯(business logic)分開建立了更好的開發結構
  
  )使用完全編譯的代碼代替了傳統ASP的代碼翻譯
  
  )它編譯特性與每個支持的方法協同這意味著使用ASPNET的站點比使用傳統的ASP站點的性能更高
  
  盡管把存在的ASP應用程序轉換到ASPNET有很多潛在的好處也有些ASP應用程序任務很重要並且復雜轉換過程可能需要更多資源並給應用程序帶來更多風險解決這些問題的途徑之一是同時運行ASP和ASPNET應用程序在一個時刻將一個對話轉換為ASPNET為了同時運行新舊程序需要建立一個機制在傳統的ASP與ASPNET間共享對話狀態本文討論的是怎樣使用NET框架組件的類和序列化特性共享狀態信息
  
  概述
  
  Cookie是Web應用程序識別用戶對話的最常用的方法可以用於識別傳統的ASP和ASPNET對話狀態在ASP腳本中狀態信息保存在內存中不能與其它應用程序(例如ASPNET)共享如果對話狀態使用通用格式保存在微軟SQL Server中它就可以被傳統的ASP和ASPNET共同訪問
  
  在本例中名為mySession的Cookie用於識別用戶對話當用戶對Web應用程序作出請求時將為該用戶產生唯一的Cookie用於識別對話在隨後的請求中浏覽器將該唯一的Cookie發送回服務器用來識別對話在被請求的Web頁載入前一個自定義對象將使用該唯一的Cookie從SQL Server中重新載入用戶對話數據通過自定義對象Web頁中的對話狀態是可以訪問的Web請求完成後如果請求終止對話數據將保存回SQL Server(見圖
  
  
數據流簡單圖

  

  ASPNET實現
  
  在ASPNET中每一個Web頁都衍生自SystemWebUIPage類Page類集合了HttpSession對象的一個實例用於處理對話數據在本例中叫做SessionPage的自定義Page類來衍生自SystemWebUIPage提供了類似Page類的所有特性唯一的區別是默認的HttpSession使用自定義的對話對象重載了(對實例變量使用new修改符C#允許衍生的類隱藏基類的成員)
  
  public class SessionPage : SystemWebUIPage
  {
  
  public new mySession Session = null;
  
  }
  
  自定義的對話類使用HybridDictionary對象來相應保存內存中的對話狀態(HybridDictionary可用於處理任意數量的對話元素)為了與傳統的ASP通用該自定義對話對象將限制對話數據類型為字符串型(默認的HttpSession允許對話保存任意類型的數據不能與傳統的ASP通用)
  
  [Serializable]
  public class mySession
  {
  private HybridDictionary dic = new HybridDictionary();
  
  public mySession()
  {
  }
  
  public string this [string name]
  {
  get
  {
  return (string)dic[nameToLower()];
  }
  set
  {
  dic[nameToLower()] = value;
  }
  }
  }
  
  Page類為定制暴露了不同的事件和方法特別是OnInit方法用於設置Page對象的初始化狀態如果請求不包含名為mySession的Cookie將為請求者產生一個新的mySession Cookie另外對話數據將使用自定義數據訪問對象SessionPersistence從SQL Server中檢索出來DSN和SessionExpiration的值從nfig中檢索
  
  override protected void OnInit(EventArgs e)
  {
  InitializeComponent();
  baseOnInit(e);
  }
  private void InitializeComponent()
  {
  cookie = thisRequestCookies[sessionPersistenceSessionID];
  
  if (cookie == null)
  {
  Session = new mySession();
  CreateNewSessionCookie();
  IsNewSession = true;
  }
  else
  Session = sessionPersistenceLoadSession(
  ServerUrlDecode(cookieValue)ToLower()Trim()
  dsn
  SessionExpiration
  );
  
  thisUnload += new EventHandler(thisPersistSession);
  }
  private void CreateNewSessionCookie()
  {
  cookie = new HttpCookie(sessionPersistenceSessionID
  sessionPersistenceGenerateKey());
  thisResponseCookiesAdd(cookie);
  }
  
  SessionPersistence類使用微軟NET框架組件的BinaryFormatter來串行化和並行化對話狀態為二進制格式以提供最佳性能結果的二進制對話數據接著作為圖象字段類型被存入SQL Server
  
  public mySession LoadSession(string key string dsn
  int SessionExpiration)
  {
  SqlConnection conn = new SqlConnection(dsn);
  SqlCommand LoadCmd = new SqlCommand();
  LoadCmdCommandText = command;
  LoadCmdConnection = conn;
  SqlDataReader reader = null;
  mySession Session = null;
  
  try
  {
  LoadCmdParametersAdd(@ID new Guid(key));
  connOpen();
  reader = LoadCmdExecuteReader();
  if (readerRead())
  {
  DateTime LastAccessed =readerGetDateTime()AddMinutes(SessionExpiration);
  if (LastAccessed >= DateTimeNow)
  Session = Deserialize((Byte[])reader[Data]);
  }
  }
  finally
  {
  if (reader != null)
  readerClose();
  if (conn != null)
  connClose();
  }
  
  return Session;
  }
  private mySession Deserialize(Byte[] state)
  {
  if (state == null) return null;
  
  mySession Session = null;
  Stream stream = null;
  
  try
  {
  stream = new MemoryStream();
  streamWrite(state stateLength);
  streamPosition = ;
  IFormatter formatter = new BinaryFormatter();
  Session = (mySession)formatterDeserialize(stream);
  }
  finally
  {
  if (stream != null)
  streamClose();
  }
  return Session;
  }
  
  在請求的末尾Page類的Unload事件被啟動了一個同Unload事件一起注冊的事件處理方法將串行化對話數據為二進制格式並將結果二進制數據存入SQL Server
  
  private void PersistSession(Object obj SystemEventArgs arg)
  { sessionPersistenceSaveSession(
  ServerUrlDecode(cookieValue)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();
  SaveCmdConnection = conn;
  
  try
  {
  if (IsNewSession)
  SaveCmdCommandText = InsertStatement;
  else
  SaveCmdCommandText = UpdateStatement;
  
  SaveCmdParametersAdd(@ID new Guid(key));
  SaveCmdParametersAdd(@Data Serialize(Session));
  SaveCmdParametersAdd(@LastAccessed DateTimeNowToString());
  
  connOpen();
  SaveCmdExecuteNonQuery();
  }
  finally
  {
  if (conn != null)
  connClose();
  }
  }
  private Byte[] Serialize(mySession Session)
  {
  if (Session == null) return null;
  
  Stream stream = null;
  Byte[] state = null;
  
  try
  {
  IFormatter formatter = new BinaryFormatter();
  stream = new MemoryStream();
  formatterSerialize(stream Session);
  state = new Byte[streamLength];
  streamPosition = ;
  streamRead(state (int)streamLength);
  streamClose();
  }
  finally
  {
  if (stream != null)
  streamClose();
  }
  return state;
  }
  
  SessionPage類以及與它相關的類被封裝在SessionUtility組件中在一個新ASPNET項目中需要作SessionUtility組件的引用為了與傳統的ASP代碼共享對話每個頁面由SessionPage代替Page類衍生出來一旦移植完成了新應用程序能通過說明SessionPage類中定義的對話變量切換回使用原來的HttpSession對象來顯示基本的HttpSession
From:http://tw.wingwit.com/Article/program/net/201311/12202.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.