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

ASP.NET保持用戶狀態的九種選擇(上)

2022-06-13   來源: .NET編程 
  摘要ASPNET為保持用戶請求之間的數據提供了多種不同的途徑你可以使用Application對象cookiehidden fieldsSessions或Cache對象以及它們的大量的方法決定什麼時候使用它們有時很困難本文將介紹了上述的技術給出了什麼時候使用它們的一些指導盡管這些技術中有些在傳統ASP中已經存在但是有了NET框架組件後該在什麼時候使用它們發生了變化為了在ASPNET中保持數據你需要調整從先前的ASP中處理狀態中學習到的知識

  隨著Web時代的到來在無狀態的HTTP世界中管理狀態成為Web開發者的一個大問題最近出現了幾種存儲和檢索數據的不同技術本文我將解釋ASPNET開發者能怎樣通過頁面請求維護或傳遞狀態

  在ASPNET中有幾種保持用戶請求間數據的途徑實際上太多了使沒有經驗的開發者對在哪個特定的環境下使用哪個對象很困惑為了回答這個問題需要考慮下面三個條件

   ◆ 誰需要數據?

   ◆ 數據需要保持多長時間?

   ◆ 數據集有多大?

  通過回答這些問題你能決定哪個對象為保持ASPNET應用程序請求間數據提供了最佳的解決方案列出了不同的狀態管理對象並描述了什麼時候使用它們ASPNET中添加了四個新的對象CacheContextViewState和WebConfig文件

  ASPNET也支持傳統的ASP對象包括Application Cookie有隱藏字段的 Form Post QueryString和Sessions注意這五個數據容器的正確使用方法發生了改變因此有經驗的程序員在考慮這些熟悉的對象時也許需要學習一些知識

 保持方法  誰需要數據  保持多長時間  數據量大小  Application  所有用戶  整個應用程序生命期  任意大小  Cookie  一個用戶  可以很短如果用戶不刪除也可以很長  小的簡單數據  Form Post  一個用戶  到下一次請求(可以跨越多個請求重復使用)  任意大小  QueryString  一個或一組用戶  到下一次請求(可以跨越多個請求重復使用)  小的簡單數據  Sessions  一個用戶  用戶活動時一直保持+一段時間(一般分鐘)  可以是任何大小但是因為用戶有單獨的Sessions 存儲所有它應該最小  Cache  所有用戶或某些用戶  根據需要  可大可小可簡單可復雜  Context  一個用戶   一個請求  可以保持大對象但是一般不這樣使用  ViewState  一個用戶  一個Web窗體  最小  Config file  所有用戶  知道配置文件被更新  可以保持大量數據通常組織小的字符串和XML結構表 ASPNET中的數據容器對象

  Application

  讓我們通過回答上面的狀態問題判定條件來說明該對象誰需要數據?所有的用戶需要訪問它需要保持數據多長時間?永久保持或在應用程序生存期中保持數據多大?可以是任何大小在任何給定的時刻只有數據的一個副本存在

  在傳統ASP中Application對象提供了一個保存頻繁使用但很少改變的數據片的位置例如菜單內容和參考數據盡管在ASPNET 中Application依然作為數據容器存在但是有其它一些更適合以前保存在傳統ASP應用程序的Application集合中的數據的對象

  在傳統的ASP中如果被保存的數據在應用程序的生存期中根本不會改變(或很少改變例如只讀數據和大多數情況下是讀操作的數據)Application對象是理想的選擇連接字符串就是保存在Application變量中的一個最普通的數據片但是在ASPNET中類似的配置數據最好保存在Webconfig文件中如果使用Application對象一個需要考慮的問題是任何寫操作要麼在Application_OnStart事件(globalasax)中要麼在ApplicationLock部分中完成盡管使用ApplicationLock來確保寫操作正確地執行是必要的但是它串行化了對Application對象的請求而這對於應用程序來說是個嚴重的性能瓶頸演示了怎樣使用Application對象它包括一個Web窗體和它的代碼文件

  Applicationaspx

 <form id=Application method=post runat=server
<asp:validationsummary id=valSummary Runat=server
</asp:validationsummary>
<table>
<tr>
<td colSpan=>Set Application Variable:</td>
</tr>
<tr>
<td>Name</td>
<td><asp:textbox id=txtName Runat=server></asp:textbox>
</td>
<td><asp:requiredfieldvalidator id=nameRequired
runat=server Display=Dynamic ErrorMessage=Name is
required ControlToValidate=txtName>*
</asp:requiredfieldvalidator></td>
</tr>
<tr>
<td>Value</td>
<td><asp:textbox id=txtValue Runat=server
</asp:textbox></td>
<td><asp:requiredfieldvalidator id=valueRequired
Runat=server Display=Dynamic ErrorMessage=Value is
required ControlToValidate=txtValue>*
</asp:requiredfieldvalidator></td>
</tr>
<tr>
<td colSpan=><asp:button id=btnSubmit Runat=server
Text=Update Value></asp:button></td>
</tr>
</table>
<asp:Label ID=lblResult Runat=server />
</form>
Applicationaspxcs
private void btnSubmit_Click(object sender SystemEventArgs e)
{
if(IsValid)
{
ApplicationLock();
Application[txtNameText] = txtValueText;
ApplicationUnLock();
lblResultText = The value of <b> + txtNameText +
</b> in the Application object is <b> +
Application[txtNameText]ToString() + </b>;
}

  代碼段在ASPNET中訪問Application對象

  它的輸出如下圖所示

 
Application對象的內容

  注意圖中Application對象的內容是追蹤輸出的顯示追蹤是個偉大的調試工具但是在某個點被打開的有追蹤的頁面可能出現在產品環境中如果出現這種情況你肯定不希望顯示敏感的信息這就是為什麼Application對象從來不是推薦的存放敏感信息(例如連接字符串)的位置的主要原因之一

  Cookies

  當特定的用戶需要特定的數據片並且需要把數據在某個可變的時段中保持的時候cookie就非常方便它的生命周期可能與浏覽器窗體的一樣短也可以長達數月數年cookie可以小到只有幾個字節的數據因為它們在每個浏覽器請求中傳遞它們的內容需要盡可能的小

  Cookie提供了一條靈活的強大的維護用戶請求間數據的途徑這就是為什麼Internet上大多數動態站點使用它們的原因因為cookie可以存儲的數據量很受限制最好只在cookie中保存鍵字段其它的數據保存在數據庫或其它的服務器端數據容器中但是由於不是所有的浏覽器都支持cookie並且它可以被用戶禁止或刪除因此它們也不能用於保存關鍵數據你應該很好地處理用戶的cookie被刪除的情況最後cookie作為簡單的明文文本保存在用戶的計算機中因此在它裡面不能保存敏感的未加密的數據


單值和多值cookie

  有種特殊的cookie可以保存單個值或名稱/值對的集合顯示了單個和多個值cookie的示例通過ASPNET的內建追蹤特性輸出這些值可以在ASPNET頁面中使用RequestCookies和ResponseCookies集合來維護這在代碼段中演示

  Cookiesaspxcs

//使用HttpCookie類是指cookie的值和/或子值
HttpCookie cookie;
if(RequestCookies[txtNameText] == null)
cookie = new HttpCookie(txtNameText txtValueText);
else
cookie = RequestCookies[txtNameText];
if(txtSubValueNameTextLength > )
cookieValuesAdd(txtSubValueNameText txtSubValueValueText);
cookieExpires = SystemDateTimeNowAddDays(); // tomorrow
ResponseAppendCookie(cookie);
//檢索cookie的值
if(!RequestCookies[txtNameText]HasKeys)
lblResultText = The value of the <b> + txtNameText + </b>
cookie is <b> + RequestCookies[txtNameText]ValueToString() +
</b>;
else
{
lblResultText = The value of the <b> + txtNameText + </b>
cookie is <b> + RequestCookies[txtNameText]ValueToString() +
</b> with subvalues:<br>;
foreach(string key in RequestCookies[txtNameText]ValuesKeys)
{
lblResultText += [ + key + = +
RequestCookies[txtNameText]Values[key]ToString() + ]<br>;
}
}
刪除Cookie
// 把的值設置為空並把終止時間設置為過去某個時刻
ResponseCookies[txtNameText]Value = null;
ResponseCookies[txtNameText]Expires =
SystemDateTimeNowAddMonths(); //上個月


  代碼段Accessing 在ASPNET中訪問Cookies

  Form Post / 隱藏的窗體字段

  特定的用戶需要窗體的數據並且它需要在單個請求到應用程序終止的任何階段都保持這些數據事實上可以是任意大小的它隨著每個form post在網絡上向前和向後發送

  在傳統的ASP中這是在應用程序中暴露狀態的通常的途徑特別是在多頁面窗體應用程序中但是在ASPNET中這種技術不太適合了因為只要你使用postback模型(也就是頁面發回給自己)Web控件和ViewState自動處理了這些操作ViewState是ASPNET對這種技術的實現我將在本文的後部分討論它訪問通過POST發送的窗體值是使用HttpRequest對象的窗體集合完成的在圖一個ASPNET頁面設置了某個用戶的ID在這以後它保持在一個隱藏的窗體字段中後面的向任何頁面的請求保留這個值直到頁面使用Submit按鈕鏈接到其它的用戶

  Formaspx

 <h>Form </h
<form id=Application method=post runat=server
<p>Your username:
<asp:Label ID=lblUsername Runat=server />
</p>
<asp:Panel Runat=server ID=pnlSetValue
<asp:validationsummary id=valSummary Runat=server
</asp:validationsummary>
<TABLE>
<TR>
<TD colSpan=>Set Hidden Form Username Variable:</TD></TR>
<TR>
<TD>Username</TD>
<TD>
<asp:textbox id=txtName Runat=server></asp:textbox></TD>
<TD>
<asp:requiredfieldvalidator id=nameRequired runat=server
ControlToValidate=txtName ErrorMessage=Name is required
Display=Dynamic>*</asp:requiredfieldvalidator></TD></TR>
<TR>
<TD colSpan=
<asp:button id=btnSubmit Runat=server Text=Set Value
</asp:button></TD></TR></TABLE>
</asp:Panel>
<asp:Label ID=lblResult Runat=server />
</form>
<form action=formaspx method=post name=form id=form
<input type=hidden name=username value=<%# username %>
<input type=submit value=Go to Formaspx
</form>
Formaspxcs
private void Page_Load(object sender SystemEventArgs e)
{
if(!IsPostBack) // 新的請求或者來自formaspx的請求
{
// 檢查窗體集合
if(RequestForm[username] == null)
pnlSetValueVisible = true;
else
{
//需要設置用戶名值
pnlSetValueVisible = false;
username = RequestForm[username]ToString();
lblUsernameText = username;
//數據綁定到隱藏的窗體字段值
thisDataBind();
}
}
}

private void btnSubmit_Click(object sender SystemEventArgs e)
{
if(IsValid)
{
//隱藏窗體來設置值
pnlSetValueVisible = false;
username = txtNameText;
lblResultText = Username set to + txtNameText + ;
lblUsernameText = username;
thisDataBind();
}
}
Formaspx
<h>Form </h
<form id=Application method=post runat=server
<p>Your username: <asp:Label ID=lblUsername Runat=server /></p>
</form>
<form action=formaspx method=post id=form name=form
<input type=hidden name=username value=<%# username %>
<input type=submit value=Go to Formaspx
</form>
Formaspxcs
private void Page_Load(object sender SystemEventArgs e)
{
if(RequestForm[username] != null)
{
username = RequestForm[username]ToString();
lblUsernameText = username;
thisDataBind();
}
}
 
  代碼段在ASPNET中使用隱藏窗體字段

  在ASPNET中一個頁面上只能存在一個服務器端窗體並且該窗體必須提交返回到自身(仍然可以使用客戶端窗體沒有限制)隱藏窗體字段再也沒有用於在NET框架組件上建立的應用程序間傳遞數據的主要原因之一是NET框架組件控件都可以使用ViewState自動維護自己的狀態ViewState簡單地把使用隱藏窗體字段設置和檢索值所包含的工作封裝進一個使用簡單的集合對象中

  QueryString

  QueryString對象中保存的數據由單獨的用戶使用它的生命周期可能只有一個請求那麼短也可能有用戶使用應用程序的時間那麼長(如果構造正確的話)這類數據一般小於KBQueryString中的數據在URL中傳遞對於用戶來說是可見的因此你能猜到使用這種技術時敏感的數據或可用於控制應用程序的數據需要加密

  也就是說QueryString是在ASPNET Web窗體間發送信息的一條很好的途徑例如如果有一個含有產品列表的數據表格(DataGrid)並且在表格上有一個鏈接導向產品的細節頁面使用QueryString就是理想的可以把產品的ID包含在鏈接到產品細節頁面的QueryString中(例如productdetailsaspx?id=使用QueryStrings的另一個好處是頁面的狀態包含在URL中這意味著用戶可以把某個通過QueryStrings建立的窗體放入他的收藏夾中當它們作為收藏返回到頁面時將與作收藏的時候一樣很明顯這只在頁面不依賴QueryString外的所有狀態和不作任何改變的時候有作用

  敏感數據以及任何不希望用戶操作的變量應該避免出現在此處(除非加密使用戶不能閱讀)並且URL中不合法的字符必須使用ServerUrlEncode編碼如圖所示當處理單個ASPNET頁面時對維護狀態來說ViewState是比QueryString好的選擇對於長期的數據存儲CookieSessions或Cache都比QueryStrings更加適於作為數據容器

  Querystringaspx

 <form id=Querystring method=post runat=server
<asp:validationsummary id=valSummary Runat=server
</asp:validationsummary>
<table>
<tr>
<td colSpan=>Set Querystring Variable:</td>
</tr>
<tr>
<td>Name</td>
<td><asp:textbox id=txtName Runat=server></asp:textbox>
</td>
<td><asp:requiredfieldvalidator id=nameRequired
runat=server Display=Dynamic ErrorMessage=Name is
required ControlToValidate=txtName>*
</asp:requiredfieldvalidator></td>
</tr>
<tr>
<td>Value</td>
<td><asp:textbox id=txtValue Runat=server
</asp:textbox></td>
<td><asp:requiredfieldvalidator id=valueRequired
Runat=server Display=Dynamic ErrorMessage=Value is
required ControlToValidate=txtValue>*
</asp:requiredfieldvalidator></td>
</tr>
<tr>
<td colSpan=><asp:button id=btnSubmit Runat=server
Text=Update Value></asp:button></td>
</tr>
</table>
<asp:Label ID=lblResult Runat=server />
<a href=querystringaspx?x=>Set querystring x equal to </a>
</form>
Querystringaspxcs
private void Page_Load(object sender SystemEventArgs e)
{
// 檢索cookie的值
if(RequestQueryStringHasKeys())
{
lblResultText = The values of the <b> + txtNameText +
</b> querystring parameter are:<br>;
foreach(string key in RequestQueryStringKeys)
{
lblResultText += [ + key + = +
RequestQueryString[key]ToString() + ]<br>;
}
}
}

private void btnSubmit_Click(object sender SystemEventArgs e)
{
if(IsValid)
{
string url = querystringaspx?;
foreach(string key in RequestQueryStringKeys)
{
url += key + = + RequestQueryString[key]ToString() + &;
}
ResponseRedirect(url + txtNameText + = +
ServerUrlEncode(txtValueText));
}
}
 
  代碼段在ASPNET中使用QueryStrings傳遞數據

  Sessions

  Sessions數據對於特定的用戶是特定的它的生存期是用戶持續請求的時間加上後來一段時間(一般是分鐘)Sessions可以保持或大或小的數據量但是如果應用程序用於成百上千的用戶那麼總共的存儲應該保持最小

  不幸的是在傳統的ASP中Sessions對象的名聲很不好因為它把應用程序約束到特定的計算機上阻礙了用戶分組和Web范圍的可伸縮性在ASPNET中幾乎沒有這些問題因為改變Sessions保存的位置很簡單在默認情況下(性能最好的情況)Sessions數據仍然保存在本地Web服務器的內存中但是ASPNET支持使用外部狀態服務器或數據庫管理Sessions數據

  使用Sessions對象很簡單並且它的語法與傳統ASP相同但是Sessions對象是保存用戶數據的方法中效率很低的一種因為即使用戶停止使用應用程序後它仍然保持在內存中一段時間這對於非常繁忙的站點的可伸縮性有嚴重的影響其它的選擇允許對釋放內存的更多的控制例如Cache對象也許更適合大量的大數據值並且在默認情況下ASPNET Sessionss依賴於cookie因此如果用戶禁止或不支持cookieSessionss就不能工作但是可以配置Sessionss支持cookie無關對於小的數據量Sessionss對象是保存只需要在用戶當前對話中保持的特定數據的極好位置下面的例子演示了怎樣設置和從Sessionss對象中檢索值

private void btnSubmit_Click(object sender SystemEventArgs e)
{
 if(IsValid)
 {
  // 設置Sessions值
  Sessions[txtNameText] = txtValueText;

  //讀取和顯示剛才的設置
  lblResultText = The value of <b> + txtNameText + </b> in the Sessions object is <b> + Sessions[txtNameText]ToString() + </b>;
 }
}
 
  該Web窗體與Application對象中使用的幾乎相同當允許頁面追蹤時Sessions集合的內容也是可見的
你需要記住的是即使沒有使用Sessionss也會有應用程序開銷把Sessionss狀態設置為只讀的也可以優化只需要讀而不需要寫數據的頁面可以使用下面兩種途徑之一來配置Sessionss

<%@ Page EnableSessionsstate=false %>
<%@ Page EnableSessionsstate=readonly %>

  ASPNET Sessionss可以在Webconfig或Machineconfig中的Sessionsstate元素中配置下面是在 Webconfig中的設置的例子

<Sessionsstate timeout= cookieless=false mode=Inproc />


From:http://tw.wingwit.com/Article/program/net/201311/15004.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.