隨着Web時代的到來,在無狀態的HTTP世界中管理狀態成爲Web開發者的一個大問題。最近出現了幾種存儲和檢索數據的不同技術。本文我將解釋ASP.NET開發者能怎樣通過頁面請求維護或傳遞狀態。
在ASP.NET中,有幾種保持用戶請求間數據的途徑--實際上太多了,使沒有經驗的開發者對在哪個特定的環境下使用哪個對象很困惑。爲了回答這個問題,需要考慮下面三個條件:
保持方法 誰需要數據 保持多長時間 數據量大小
Application 所有用戶 整個應用程序生命期 任意大小
Cookie 一個用戶 可以很短,如果用戶不刪除也可以很長 小的、簡單數據
Form Post 一個用戶 到下一次請求(可以跨越多個請求重複使用) 任意大小
QueryString 一個或一組用戶 到下一次請求(可以跨越多個請求重複使用) 小的、簡單數據
Sessions 一個用戶 用戶活動時一直保持+一段時間(一般20分鐘) 可以是任何大小,但是因爲用戶有單獨的Sessions 存儲,所有它應該最小。
Cache 所有用戶或某些用戶 根據需要 可大可小、可簡單可複雜
Context 一個用戶 一個請求 可以保持大對象,但是一般不這樣使用
ViewState 一個用戶 一個Web窗體 最小
Config file 所有用戶 知道配置文件被更新 可以保持大量數據,通常組織小的字符串和XML結構
表1. ASP.NET中的數據容器對象
<form id="Application" method="post" runat="server">
<asp:validationsummary id="valSummary" Runat="server">
</asp:validationsummary>
<table>
<tr>
<td colSpan="3">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="3"><asp:button id="btnSubmit" Runat="server"
Text="Update Value"></asp:button></td>
</tr>
</table>
<asp:Label ID="lblResult" Runat="server" />
</form>
Application.aspx.cs
private void btnSubmit_Click(object sender, System.EventArgs e)
{
if(IsValid)
{
Application.Lock();
Application[txtName.Text] = txtValue.Text;
Application.UnLock();
lblResult.Text = "The value of <b>" + txtName.Text +
"</b> in the Application object is <b>" +
Application[txtName.Text].ToString() + "</b>";
}
}
Cookies
圖2.單值和多值cookie
HttpCookie cookie;
if(Request.Cookies[txtName.Text] == null)
cookie = new HttpCookie(txtName.Text, txtValue.Text);
else
cookie = Request.Cookies[txtName.Text];
if(txtSubValueName.Text.Length > 0)
cookie.Values.Add(txtSubValueName.Text, txtSubValueValue.Text);
cookie.Expires = System.DateTime.Now.AddDays(1); // tomorrow
Response.AppendCookie(cookie);
//檢索cookie的值
if(!Request.Cookies[txtName.Text].HasKeys)
lblResult.Text = "The value of the <b>" + txtName.Text + "</b>
cookie is <b>" + Request.Cookies[txtName.Text].Value.ToString() +
"</b>";
else
{
lblResult.Text = "The value of the <b>" + txtName.Text + "</b>
cookie is <b>" + Request.Cookies[txtName.Text].Value.ToString() +
"</b>, with subvalues:<br>";
foreach(string key in Request.Cookies[txtName.Text].Values.Keys)
{
lblResult.Text += "[" + key + " = " +
Request.Cookies[txtName.Text].Values[key].ToString() + "]<br>";
}
}
刪除Cookie
// 把的值設置爲空並把終止時間設置爲過去某個時刻
Response.Cookies[txtName.Text].Value = null;
Response.Cookies[txtName.Text].Expires =
System.DateTime.Now.AddMonths(-1); //上個月
<h1>Form 1</h1>
<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="3">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="3">
<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="form2.aspx" method="post" name="form2" id="form2">
<input type="hidden" name="username" value="<%# username %>" >
<input type="submit" value="Go to Form2.aspx"
</form>
Form1.aspx.cs
private void Page_Load(object sender, System.EventArgs e)
{
if(!IsPostBack) // 新的請求或者來自form2.aspx的請求
{
// 檢查窗體集合
if(Request.Form["username"] == null)
pnlSetValue.Visible = true;
else
{
//需要設置用戶名值
pnlSetValue.Visible = false;
username = Request.Form["username"].ToString();
lblUsername.Text = username;
//數據綁定到隱藏的窗體字段值
this.DataBind();
}
}
}
{
if(IsValid)
{
//隱藏窗體來設置值
pnlSetValue.Visible = false;
username = txtName.Text;
lblResult.Text = "Username set to " + txtName.Text + ".";
lblUsername.Text = username;
this.DataBind();
}
}
Form2.aspx
<h1>Form 2</h1>
<form id="Application" method="post" runat="server">
<p>Your username: <asp:Label ID="lblUsername" Runat="server" /></p>
</form>
<form action="form1.aspx" method="post" id="form2" name="form2">
<input type="hidden" name="username" value="<%# username %>" >
<input type="submit" value="Go to Form1.aspx"
</form>
Form2.aspx.cs
private void Page_Load(object sender, System.EventArgs e)
{
if(Request.Form["username"] != null)
{
username = Request.Form["username"].ToString();
lblUsername.Text = username;
this.DataBind();
}
}
<form id="Querystring" method="post" runat="server">
<asp:validationsummary id="valSummary" Runat="server">
</asp:validationsummary>
<table>
<tr>
<td colSpan="3">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="3"><asp:button id="btnSubmit" Runat="server"
Text="Update Value"></asp:button></td>
</tr>
</table>
<asp:Label ID="lblResult" Runat="server" />
<a href="querystring.aspx?x=1">Set querystring x equal to 1</a>
</form>
Querystring.aspx.cs
private void Page_Load(object sender, System.EventArgs e)
{
// 檢索cookie的值
if(Request.QueryString.HasKeys())
{
lblResult.Text = "The values of the <b>" + txtName.Text +
"</b> querystring parameter are:<br>";
foreach(string key in Request.QueryString.Keys)
{
lblResult.Text += "[" + key + " = " +
Request.QueryString[key].ToString() + "]<br>";
}
}
}
{
if(IsValid)
{
string url = "querystring.aspx?";
foreach(string key in Request.QueryString.Keys)
{
url += key + "=" + Request.QueryString[key].ToString() + "&";
}
Response.Redirect(url + txtName.Text + "=" +
Server.UrlEncode(txtValue.Text));
}
}
Sessions
private void btnSubmit_Click(object sender, System.EventArgs e)
{
if(IsValid)
{
// 設置Sessions值
Sessions[txtName.Text] = txtValue.Text;
lblResult.Text = "The value of <b>" + txtName.Text + "</b> in the Sessions object is <b>" + Sessions[txtName.Text].ToString() + "</b>";
}
}
你需要記住的是即使沒有使用,Sessionss也會有應用程序開銷。把Sessionss狀態設置爲只讀的也可以優化只需要讀而不需要寫數據的頁面。可以使用下面兩種途徑之一來配置Sessionss:
<%@ Page EnableSessionsstate="false" %>
<%@ Page EnableSessionsstate="readonly" %>
<Sessionsstate timeout="10" cookieless="false" mode="Inproc" />
ASP.NET中的新狀態容器
// 給緩存添加項
Cache["myKey"] = myValue;
Response.Write(Cache["myKey"]);
Cache.Insert("myKey",myValue, null, System.DateTime.Now.AddSeconds(10),
System.Web.Caching.Cache.NoSlidingExpiration);
private void Page_Load(object sender, System.EventArgs e)
{
string cacheKey = "myKey";
string data = "";
// 檢查數據是否已經被緩存了
if(Cache[cacheKey]==null)
{
// 因爲數據在緩存中,所有讀取數據
data = System.DateTime.Now.ToString();
CacheItemRemovedCallback callBack =new CacheItemRemovedCallback(onRemove);
System.DateTime.Now.AddSeconds(5),
System.Web.Caching.Cache.NoSlidingExpiration,
System.Web.Caching.CacheItemPriority.Default,
callBack);
}
else
{
Label1.Text = "Cached: " + Cache[cacheKey].ToString();
}
}
{
//建立回調委託的一個實例
CacheItemRemovedCallback callBack =new CacheItemRemovedCallback(onRemove);
Cache.Insert(key,val.ToString() +
"*",null,System.DateTime.Now.AddSeconds(5),Cache.NoSlidingExpiration,
System.Web.Caching.CacheItemPriority.Default, callBack);
}
Cache對象的功能比先前我們討論的大多數對象多得多。這也是ASP.NET更強大的功能之一,並且我明確地推薦閱讀關於它的更多內容。
// 給Context添加項
Context.Items["myKey"] = myValue;
Response.Write(Context["myKey"]);
// 給ViewState添加項
ViewState["myKey"] = myValue;
Response.Write(ViewState["myKey"]);
namespace MSDN.StateManagement
{
public class HelloPerson : System.Web.UI.Control
{
public string PersonName
{
get
{
string s = (string)ViewState["PersonName"];
return ((s == null) ? "" : s);
}
set
{
ViewState["PersonName"] = value;
}
}
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
writer.Write("Hello " + PersonName);
}
}
}
<configuration>
<!-應用程序特殊設置 -->
<appSettings>
<add key="connectionString" value="server=myDBServer;
uid=myUID;pwd=myPassword;database=myDB" />
</appSettings>
<system.web>
<!-所有的wsb設置 -->
</system.web>
</configuration>
ooo
String strConnString =
ConfigurationSettings.AppSettings["connectionString"];