在ASP與ASP.NET之間共享對(duì)話狀態(tài)(1)
[ 來(lái)源:動(dòng)網(wǎng) |作者:佚名 ]
[前言:]ASP.NET是微軟提供的的開(kāi)發(fā)基于Web的應(yīng)用程序的技術(shù)。它提供了大量的比傳統(tǒng)ASP腳本技術(shù)的好處,包括: 1)通過(guò)把UI表現(xiàn)層(presentation)與商業(yè)邏輯(business logic)分開(kāi)建立了更好的開(kāi)發(fā)結(jié)構(gòu); 2)使用完全編譯的代碼代替了傳統(tǒng)ASP的代碼翻譯; 3)它編譯特性與每個(gè)支持的方法協(xié)同,這意味著使用ASP.NET的站點(diǎn)比使用傳統(tǒng)的ASP站點(diǎn)的性能更高。 盡管把存在的ASP應(yīng)用程序轉(zhuǎn)換到ASP.NET有很多潛在的好處,也有些ASP應(yīng)用程序任務(wù)很重要并且復(fù)雜。轉(zhuǎn)換過(guò)程可能需要更多資源并給應(yīng)用程序帶來(lái)更多風(fēng)險(xiǎn)。解決這些問(wèn)題的途徑之一是同時(shí)運(yùn)行ASP和ASP.NET應(yīng)用程序,在一個(gè)時(shí)刻將一個(gè)對(duì)話轉(zhuǎn)換為ASP.NET。為了同時(shí)運(yùn)行新舊程序,需要建立一個(gè)機(jī)制在傳統(tǒng)的ASP與ASP.NET間共享對(duì)話狀態(tài)。本文討論的是怎樣使用.NET框架組件的類和序列化特性共享狀態(tài)信息。 概述 Cookie是Web應(yīng)用程序識(shí)別用戶對(duì)話的最常用的方法,可以用于識(shí)別傳統(tǒng)的ASP和ASP.NET對(duì)話狀態(tài)。在ASP腳本中狀態(tài)信息保存在內(nèi)存中,不能與其它應(yīng)用程序(例如ASP.NET)共享。如果對(duì)話狀態(tài)使用通用格式保存在微軟SQL Server中,它可以被傳統(tǒng)的ASP和ASP.NET共同訪問(wèn)。 在本例中,名為mySession的Cookie用于識(shí)別用戶對(duì)話。當(dāng)用戶對(duì)Web應(yīng)用程序作出請(qǐng)求時(shí),將為該用戶產(chǎn)生的Cookie用于識(shí)別對(duì)話。在隨后的請(qǐng)求中,瀏覽器將該的Cookie發(fā)送回服務(wù)器用來(lái)識(shí)別對(duì)話。在被請(qǐng)求的Web頁(yè)載入前,一個(gè)自定義對(duì)象將使用該的Cookie從SQL Server中重新載入用戶對(duì)話數(shù)據(jù)。通過(guò)自定義對(duì)象Web頁(yè)中的對(duì)話狀態(tài)是可以訪問(wèn)的。Web請(qǐng)求完成后,如果請(qǐng)求終止,對(duì)話數(shù)據(jù)將保存回SQL Server(見(jiàn)圖1)。 圖1.數(shù)據(jù)流簡(jiǎn)單圖 ASP.NET實(shí)現(xiàn) 在ASP.NET中每一個(gè)Web頁(yè)都衍生自System.Web.UI.Page類。Page類集合了HttpSession對(duì)象的一個(gè)實(shí)例用于處理對(duì)話數(shù)據(jù)。在本例中,叫做SessionPage的自定義Page類來(lái)衍生自System.Web.UI.Page,提供了類似Page類的所有特性。的區(qū)別是默認(rèn)的HttpSession使用自定義的對(duì)話對(duì)象重載了(對(duì)實(shí)例變量使用new修改符,C#允許衍生的類隱藏基類的成員)。 public class SessionPage : System.Web.UI.Page { ... public new mySession Session = null; ... } 自定義的對(duì)話類使用HybridDictionary對(duì)象來(lái)相應(yīng)保存內(nèi)存中的對(duì)話狀態(tài)(HybridDictionary可用于處理任意數(shù)量的對(duì)話元素)。為了與傳統(tǒng)的ASP通用,該自定義對(duì)話對(duì)象將限制對(duì)話數(shù)據(jù)類型為字符串型(默認(rèn)的HttpSession允許對(duì)話保存任意類型的數(shù)據(jù),不能與傳統(tǒng)的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; } } } Page類為定制暴露了不同的事件和方法。特別是OnInit方法用于設(shè)置Page對(duì)象的初始化狀態(tài)。如果請(qǐng)求不包含名為mySession的Cookie,將為請(qǐng)求者產(chǎn)生一個(gè)新的mySession Cookie。另外,對(duì)話數(shù)據(jù)將使用自定義數(shù)據(jù)訪問(wèn)對(duì)象SessionPersistence從SQL Server中檢索出來(lái)。DSN和SessionExpiration的值從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); } SessionPersistence類使用微軟.NET框架組件的BinaryFormatter來(lái)串行化和并行化對(duì)話狀態(tài)為二進(jìn)制格式以提供性能。結(jié)果的二進(jìn)制對(duì)話數(shù)據(jù)接著作為圖象字段類型被存入SQL Server。 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; } 在請(qǐng)求的末尾,Page類的Unload事件被啟動(dòng)了,一個(gè)同Unload事件一起注冊(cè)的事件處理方法將串行化對(duì)話數(shù)據(jù)為二進(jìn)制格式并將結(jié)果二進(jìn)制數(shù)據(jù)存入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; } SessionPage類以及與它相關(guān)的類被封裝在SessionUtility組件中。在一個(gè)新ASP.NET項(xiàng)目中,需要作SessionUtility組件的引用,為了與傳統(tǒng)的ASP代碼共享對(duì)話,每個(gè)頁(yè)面由SessionPage代替Page類衍生出來(lái)。一旦移植完成了,新應(yīng)用程序能通過(guò)說(shuō)明SessionPage類中定義的對(duì)話變量切換回使用原來(lái)的HttpSession對(duì)象來(lái)顯示基本的HttpSession。
來(lái)源:http://edu.chinaz.com