|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
无法实现跨操作系统的应用。当然这也是微软的理由之一,只有这样才能发挥ASP最佳的能力。可是我却认为正是Windows限制了ASP,ASP的概念本就是为一个能让系统运行于一个大的多样化环境而设计的;asp.net
[媒介:]ASP.NET是微软供应的最新的开辟基于Web的使用法式的手艺。它供应了大批的比传统ASP剧本手艺的优点,包含:
1)经由过程把UI体现层(presentation)与贸易逻辑(business logic)分隔创立了更好的开辟布局;
2)利用完整编译的代码取代了传统ASP的代码翻译;
3)它编译特征与每一个撑持的办法协同,这意味着利用ASP.NET的站点比利用传统的ASP站点的功能更高。
虽然把存在的ASP使用法式转换到ASP.NET有良多潜伏的优点,也有些ASP使用法式义务很主要而且庞杂。转换进程能够需求更多资本并给使用法式带来更多风险。处理这些成绩的路子之一是同时运转ASP和ASP.NET使用法式,在一个时辰将一个对话转换为ASP.NET。为了同时运转新旧法式,需求创立一个机制在传统的ASP与ASP.NET间同享对话形态。本文会商的是如何利用.NET框架组件的类和序列化特征同享形态信息。
概述
Cookie是Web使用法式辨认用户对话的最经常使用的办法,可以用于辨认传统的ASP和ASP.NET对话形态。在ASP剧本中形态信息保留在内存中,不克不及与其它使用法式(例如ASP.NET)同享。假如对话形态利用通用格局保留在微软SQL Server中,它就能够被传统的ASP和ASP.NET配合会见。
在本例中,名为mySession的Cookie用于辨认用户对话。当用户对Web使用法式作出恳求时,将为该用户发生独一的Cookie用于辨认对话。在随后的恳求中,阅读器将该独一的Cookie发送回办事器用来辨认对话。在被恳求的Web页载入前,一个自界说对象将利用该独一的Cookie从SQL Server中从头载入用户对话数据。经由过程自界说对象Web页中的对话形态是可以会见的。Web恳求完成后,假如恳求终止,对话数据将保留回SQL Server(见图1)。
图1.数据流复杂图
ASP.NET完成
在ASP.NET中每个Web页都衍生自System.Web.UI.Page类。Page类纠合了HttpSession对象的一个实例用于处置对话数据。在本例中,叫做SessionPage的自界说Page类来衍生自System.Web.UI.Page,供应了相似Page类的一切特征。独一的区分是默许的HttpSession利用自界说的对话对象重载了(对实例变量利用new修正符,C#答应衍生的类埋没基类的成员)。
public class SessionPage : System.Web.UI.Page
{
...
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[name.ToLower()];
}
set
{
dic[name.ToLower()] = value;
}
}
}
Page类为定制表露了分歧的事务和办法。出格是OnInit办法用于设置Page对象的初始化形态。假如恳求不包括名为mySession的Cookie,将为恳求者发生一个新的mySession Cookie。别的,对话数据将利用自界说数据会见对象SessionPersistence从SQL Server中检索出来。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来串行化和并行化对话形态为二进制格局以供应最好功能。了局的二进制对话数据接着作为图像字段类型被存入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;
}
在恳求的末尾,Page类的Unload事务被启动了,一个同Unload事务一同注册的事务处置办法将串行化对话数据为二进制格局并将了局二进制数据存入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类和与它相干的类被封装在SessionUtility组件中。在一个新ASP.NET项目中,需求作SessionUtility组件的援用,为了与传统的ASP代码同享对话,每一个页面由SessionPage取代Page类衍生出来。一旦移植完成了,新使用法式能经由过程申明SessionPage类中界说的对话变量切换回利用本来的HttpSession对象来显示根基的HttpSession。ASP完成
本来的ASP对话只能将对话数据保留在内存中。为了将对话数据保留到SQL Server,需求写一个自界说的Visual Basic 6.0 COM对象取代如今的对话对象来办理对话形态。该COM对象在每一个Web恳求入手下手时被初始化,并从SQL Server从头载入对话数据。ASP剧本完成时,该对象将终止并把对话形态将前往到SQL Server。
Visual Basic 6 COM Session对象的次要目标是供应对微软Internet信息办事器(IIS)外部对象的会见。Visual Basic 6 COM对话对象利用SessionUtility组件的mySession类来保留对话形态,SessionUtility的SessionPersistence类用于载入和保留对话数据到SQL Server。利用regasm.exe东西将mySession和 SessionPersistence类作为COM对象表露。regasm.exe东西可以注册并为COM客户端创立一个类型库来利用框架组件类。
在对象的机关函数中形态信息被从头载入。机关函数(class_initialize)起首从Application对象中检索对话cookie、对话超时设置(SessionTimeOut)、数据库毗连字符串(SessionDSN),并创立mySession类的一个实例来坚持对话数据。接着机关函数将试图从头利用给定的cookie从SQL Server中载入对话数据。假如SQL Server中没有对话信息,或对话已终止,将发生一个新的cookie。假如SQL Server前往了对话形态数据,对话形态信息将保留在mySession对象中。
Private Sub Class_Initialize()
On Error GoTo ErrHandler:
Const METHOD_NAME As String = "Class_Initialize"
Set mySessionPersistence = New SessionPersistence
Set myObjectContext = GetObjectContext()
mySessionID = ReadSessionID()
myDSNString = GetConnectionDSN()
myTimeOut = GetSessionTimeOut()
myIsNewSession = False
Call InitContents
Exit Sub
ErrHandler:
Err.Raise Err.Number, METHOD_NAME & ":" & Err.Source, Err.Description
End Sub
Private Sub InitContents()
On Error GoTo ErrHandler:
Const METHOD_NAME As String = "InitContents"
If mySessionID = "" Then
Set myContentsEntity = New mySession
mySessionID = mySessionPersistence.GenerateKey
myIsNewSession = True
Else
Set myContentsEntity =mySessionPersistence.LoadSession(mySessionID, myDSNString, myTimeOut)
End If
Exit Sub
ErrHandler:
Err.Raise Err.Number, METHOD_NAME & ":" & Err.Source, Err.Description
End Sub
假如对象实例超越了剧本的局限,将履行解构函数(class_terminate)。解构函数将利用SessionPersistence.SaveSession()办法坚持对话数据。假如是一个新对话,解构函数将新cookie发送回阅读器。
Private Sub Class_Terminate()
On Error GoTo ErrHandler:
Const METHOD_NAME As String = "Class_Terminate"
Call SetDataForSessionID
Exit Sub
ErrHandler:
Err.Raise Err.Number, METHOD_NAME & ":" & Err.Source, Err.Description
End Sub
Private Sub SetDataForSessionID()
On Error GoTo ErrHandler:
Const METHOD_NAME As String = "SetDataForSessionID"
Call mySessionPersistence.SaveSession(mySessionID,
myDSNString, myContentsEntity, myIsNewSession)
If myIsNewSession Then Call WriteSessionID(mySessionID)
Set myContentsEntity = Nothing
Set myObjectContext = Nothing
Set mySessionPersistence = Nothing
Exit Sub
ErrHandler:
Err.Raise Err.Number, METHOD_NAME & ":" & Err.Source, Err.Description
End Sub
例程
例程设计为增添并显示一个数字。不论载入了哪一个页面,因为数字值保留在SQL Server中并在ASP和ASP.NET间同享,数字将不休增添。
创立例程的步调
1. 创立一个新数据库SessionDemoDb。
2. 创立新表SessState(osql.exe -E -d SessionDemoDb -i Session.sql)。
3. 创立新虚拟目次Demo。
4. 在ASP设置装备摆设页中封闭ASP对话。
5. 将web.config、testPage.aspx、Global.asa、testPage.asp和GlobalInclude.asp复制到虚拟目次。
6. 更新Global.asa和web.config中的DSN字符串设置。对话超时设置是可选的,默许为20分钟。
7. 将SessionUtility.dll装置到全局组件缓存(gacutil /i SessionUtility.dll)。
8. 利用regasm.exe把SessionUtility.dll作为COM对象表露(regasm.exe SessionUtility.dll /tlb:SessionUtility.tlb)。
9. 将SessionManager.dll复制到当地目次并利用regsvr32.exe注册(regsvr32 SessionManager.dll)。
10. 付与IUSR_<盘算机名>帐户读取和运转会见SessionMgr.dll的权限。
运转例程的步调
1. 翻开微软Internet Explorer。
2. 为传统的ASP中载入testPage.asp。数字"1"将呈现在Web页中。
3. 点击Internet Explorer的刷新来从头载入该页面。数字将增添。
4. 为ASP.NET改动URL为testPage.aspx。数字依然增添。
5. 假如利用testPage.aspx入手下手,进程不异。
在存在的ASP使用法式中拔出COM对象
开辟ASP使用法式的一个凡是的习气是在每一个剧本入手下手时包括一个文件来同享代码和常量。拔出自界说对话对象的最初路子是在私有包括文件中到场示例代码。最初一步复杂地利用自界说对话变量名取代了一切到对话对象的援用。
限制/改善
本计划不撑持在Session对象中保留了COM对象的ASP使用法式。在这类情形下,为了利用自界说对话对象,需求一个自界说的调剂器来串行化/并行化形态。另外,本计划也不撑持保留字符串类型数组。做一些附加任务可以完成该特征:利用Visual Basic 6.0的Join函数在保留到对话对象前将数组元素毗连成一个字符串,反向操作可使用Visual Basic 6.0的Split函数将字符串分化为自力的数组元素。在.NET框架组件中,Join和Split办法使String类的成员。
结论
ASP.NET提出了新的编程典范和系统布局,并供应了很多比传统ASP的优点。虽然将ASP移植到ASP.NET的进程不复杂,ASP.NET更好的编程模子和更高的功能将使转换进程值得。除在Session对象中保留COM对象的特例,本文会商的路子供应了一个复杂完成迁徙的处理计划。
Windows本身的所有问题都会一成不变的也累加到了它的身上。安全性、稳定性、跨平台性都会因为与NT的捆绑而显现出来; |
|