【参加讨论】使用应用程序状态
本示例阐释如何使用应用程序状态读取 Application_Start 中的数据集。
因为应用程序和它存储的所有对象可以同时由不同的线程访问,所以最好只将很少修改的数据与应用程序范围一起存储。理想情况是,对象在 Application_Start 事件中初始化,对它的进一步访问是只读的。
在下面的示例中,文件在 Application_Start(在 Global.asax 文件中定义)中读取,内容则以应用程序状态存储在 DataView 对象中。
void Application_Start() {
DataSet ds = new DataSet();
FileStream fs = new FileStream(Server.MapPath("schemadata.xml"),FileMode.Open,FileAccess.Read);
StreamReader reader = new StreamReader(fs);
ds.ReadXml(reader);
fs.Close();
DataView view = new DataView(ds.Tables[0]);
Application["Source"] = view;
}
Sub Application_Start()
Dim ds As New DataSet()
Dim fs As New FileStream(Server.MapPath("schemadata.xml"),FileMode.Open,FileAccess.Read)
Dim reader As New StreamReader(fs)
ds.ReadXml(reader)
fs.Close()
Dim view As New DataView (ds.Tables(0))
Application("Source") = view
End Sub
function Application_Start() : void {
var ds:DataSet = new DataSet();
var fs:FileStream = new FileStream(Server.MapPath("schemadata.xml"),FileMode.Open,FileAccess.Read);
var reader:StreamReader = new StreamReader(fs);
ds.ReadXml(reader);
fs.Close();
var view:DataView = new DataView(ds.Tables[0]);
Application("Source") = view;
}
|
| C# |
VB |
JScript |
|
在 Page_Load 方法中,DataView 随后被检索并用于填充 DataGrid 对象:
void Page_Load(Object sender, EventArgs e) {
DataView Source = (DataView)(Application["Source"]);
...
MyDataGrid.DataSource = Source;
...
}
Sub Page_Load(sender As Object, e As EventArgs)
Dim Source As New DataView = CType(Application("Source"), DataView)
...
MyDataGrid.DataSource = Source
...
End Sub
function Page_Load(sender:Object, e:EventArgs) : void {
var Source:DataView = DataView((Application("Source")));
...
MyDataGrid.DataSource = Source;
...
}
|
| C# |
VB |
JScript |
|
此解决方案的优点是只有第一个请求付出检索数据的代价。所有后面的请求则使用已有的 DataView 对象。由于数据自初始化后从不修改,所以不必为序列化访问做任何规定。
使用会话状态
下例说明如何使用会话状态存储易失的用户首选项。
为了在会话期间为用户提供单独的数据,数据可与会话范围一起存储。在下面的示例中,在 Global.asax 文件中的 Session_Start 事件中初始化用户首选项的值。
void Session_Start() {
Session["BackColor"] = "beige";
...
}
Sub Session_Start()
Session("BackColor") = "beige"
...
End Sub
function Session_Start() : void {
Session("BackColor") = "beige";
...
}
|
| C# |
VB |
JScript |
|
在下面的自定义页中,根据用户输入在 Submit_Click 事件处理程序中修改用户首选项的值。
protected void Submit_Click(Object sender, EventArgs e) {
Session["BackColor"] = BackColor.Value;
...
Response.Redirect(State["Referer"].ToString());
}
Protected Sub Submit_Click(sender As Object, e As EventArgs)
Session("BackColor") = BackColor.Value
...
Response.Redirect(State("Referer").ToString())
End Sub
protected function Submit_Click(sender:Object, e:EventArgs) : void {
Session("BackColor") = BackColor.Value;
...
Response.Redirect(State("Referer").ToString());
}
|
| C# |
VB |
JScript |
|
使用 GetStyle 方法检索个别值:
protected String GetStyle(String key) {
return Session[key].ToString();
}
Protected GetStyle(key As String) As String
Return(Session(key).ToString())
End Sub
protected function GetStyle(key:String) : String {
return Session(key).ToString();
}
|
| C# |
VB |
JScript |
|
GetStyle 方法用于构造会话特定样式:
<style>
body
{
font: <%=GetStyle("FontSize")%> <%=GetStyle("FontName")%>;
background-color: <%=GetStyle("BackColor")%>;
}
a
{
color: <%=GetStyle("LinkColor")%>
}
</style>
若要验证值是否真的与会话范围一起存储了,请将示例页打开两次,然后在第一个浏览器窗口中更改一个值并刷新第二个浏览器窗口。因为两个浏览器实例共享一个公共 Session 对象,所以第二个窗口获得此更改。
配置会话状态:可以通过 web.config 文件中的 <sessionState> 节配置会话状态功能。若要使默认的超时时间(20 分钟)延长一倍,可以将下列内容添加到应用程序的 web.config 文件:
默认情况下,ASP.NET 像 ASP 一样,在处理请求的同一进程中存储会话状态。如果 Cookie 不可用,可以通过将会话标识符添加到 URL 来跟踪会话。若要启用此功能,请设置以下内容:
默认情况下,ASP.NET 像 ASP 一样,在处理请求的同一进程中存储会话状态。另外,ASP.NET 可以在外部进程中存储会话数据,而外部进程甚至可以驻留在另一台计算机上。若要启用此功能:
- 使用服务管理单元或者通过在命令行上执行“net start aspnet_state”来启动 ASP.NET 状态服务。默认情况下,状态服务在端口 42424 上侦听。若要更改此端口,请修改服务的注册表项:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSte\Services\aspnet_state\Parameters\Port
- 将 <sessionState> 节的 mode 属性设置为“StateServer”。
- 用启动 aspnet_state 的计算机的值配置 stateConnectionString 属性。
下面的示例假设状态服务在 Web 服务器所在的同一台计算机(“localhost”)上运行,并且使用默认端口 (42424):
<sessionState
mode="StateServer"
stateConnectionString="tcpip=localhost:42424"
/>
注意,如果对上面的示例使用此设置,可以重置 Web 服务器(在命令行上输入 iisreset),会话状态值将保持。
使用客户端 Cookie
下面的示例说明如何使用客户端 Cookie 存储易失的用户首选项。
在客户端存储 Cookie 是 ASP.NET 的会话状态将请求与会话关联的方法之一。Cookie 也可以直接用于在请求之间保持数据,但数据随后将存储在客户端并随每个请求一起发送到服务器。浏览器对 Cookie 的大小有限制,因此,只有不超过 4096 字节才能保证被接受。
当数据存储在客户端时,文件 cookies1.aspx 中的 Page_Load 方法检查客户端是否已发送了 Cookie。如果没有,则创建并初始化一个新的 Cookie 并将其存储在客户端:
protected void Page_Load(Object sender, EventArgs e) {
if (Request.Cookies["preferences1"] == null) {
HttpCookie cookie = new HttpCookie("preferences1");
cookie.Values.Add("ForeColor", "black");
...
Response.AppendCookie(cookie);
}
}
Protected Sub Page_Load(sender As Object, e As EventArgs)
If Request.Cookies("preferences1") = Null Then
Dim cookie As New HttpCookie("preferences1")
cookie.Values.Add("ForeColor", "black")
...
Response.AppendCookie(cookie)
End If
End Sub
protected function Page_Load(sender:Object, e:EventArgs) : void {
if (Request.Cookies("preferences1") == null) {
var cookie:HttpCookie = new HttpCookie("preferences1");
cookie.Values.Add("ForeColor", "black");
...
Response.AppendCookie(cookie);
}
}
|
| C# |
VB |
JScript |
|
在同一页上,再次使用 GetStyle 方法提供存储在 Cookie 中的个别值:
protected String GetStyle(String key) {
HttpCookie cookie = Request.Cookies["preferences1"];
if (cookie != null) {
switch (key)
{
case "ForeColor" : return cookie.Values["ForeColor"]; break;
...
}
}
return "";
}
Protected Function GetStyle(key As String) As String
Dim cookie As HttpCookie = Request.Cookies("preferences1")
If cookie <> Null Then
Select Case key
Case "ForeColor"
Return(cookie.Values("ForeColor"))
Case ...
End Select
End If
Return("")
End Function
protected function GetStyle(key:String) : String {
var cookie:HttpCookie = Request.Cookies("preferences1");
if (cookie != null) {
switch (key)
{
case "ForeColor" : return cookie.Values("ForeColor"); break;
...
}
}
return "";
}
|
| C# |
VB |
JScript |
|
打开 cookies1.aspx 页并修改首选项以验证此示例是否运行。在另一窗口中打开此页,它应获得新的首选项。关闭所有浏览器窗口,然后再次打开 cookies1.aspx 页。这应删除临时 Cookie 并还原默认首选项值。
若要使 Cookie 在会话之间持久,必须将 HttpCookie 类上的 Expires 属性设置为将来的某个日期。除了 Cookie.Expires 的赋值,下列自定义 .aspx 页上的代码与上一个示例相同:
protected void Submit_Click(Object sender, EventArgs e) {
HttpCookie cookie = new HttpCookie("preferences2");
cookie.Values.Add("ForeColor",ForeColor.Value);
...
cookie.Expires = DateTime.MaxValue; // Never Expires
Response.AppendCookie(cookie);
Response.Redirect(State["Referer"].ToString());
}
Protected Sub Submit_Click(sender As Object, e As EventArgs)
Dim cookie As New HttpCookie("preferences2")
cookie.Values.Add("ForeColor",ForeColor.Value)
...
cookie.Expires = DateTime.MaxValue ' Never Expires
Response.AppendCookie(cookie)
Response.Redirect(State("Referer").ToString())
End Sub
protected function Submit_Click(sender:Object, e:EventArgs) : void {
var cookie:HttpCookie = new HttpCookie("preferences2");
cookie.Values.Add("ForeColor",ForeColor.Value);
...
cookie.Expires = DateTime.MaxValue; // Never Expires
Response.AppendCookie(cookie);
Response.Redirect(State("Referer").ToString());
}
|
| C# |
VB |
JScript |
|
修改值、关闭所有浏览器窗口并再次打开 cookies2.aspx,以验证此示例是否运行。窗口仍应显示自定义的值。
使用视图状态
此示例说明如何使用 ViewState 属性存储请求特定的值。
ASP.NET 为每个控件提供视图状态的服务器端注记。控件可以使用类 StateBag 的一个实例上的 ViewState 属性,在请求之间保存它的内部状态。StateBag 类提供词典样式的接口来存储与字符串键关联的对象。
文件 pagestate1.aspx 显示一个可见的面板并使用键 PanelIndex 在该页的视图状态下存储它的索引:
protected void Next_Click(Object sender, EventArgs e ) {
String PrevPanelId = "Panel" + ViewState["PanelIndex"].ToString();
ViewState["PanelIndex"] = (int)ViewState["PanelIndex"] + 1;
String PanelId = "Panel" + ViewState["PanelIndex"].ToString();
...
}
Protected Sub Next_Click(sender As Object, e As EventArgs)
Dim PrevPanelId As String = "Panel" + ViewState("PanelIndex").ToString()
ViewState("PanelIndex") = CType(ViewState("PanelIndex") + 1, Integer)
Dim PanelId As String = "Panel" + ViewState("PanelIndex").ToString()
...
End Sub
protected function Next_Click(sender:Object, e:EventArgs) : void {
var PrevPanelId:String = "Panel" + ViewState("PanelIndex").ToString();
ViewState("PanelIndex") = int(ViewState("PanelIndex") + 1);
var PanelId:String = "Panel" + ViewState("PanelIndex").ToString();
...
}
|
| C# |
VB |
JScript |
|
注意,如果在多个浏览器窗口中打开该页,每个浏览器窗口最初将显示此名称面板。每个窗口可以独立地在面板之间定位。
- 使用应用程序状态变量存储很少修改但经常使用的数据。
- 使用会话状态变量存储特定于某个会话或用户的数据。数据全部存储在服务器上。这种方法适于短期的、大量的或敏感的数据。
- 将少量易失数据存储在非持久性 Cookie 中。数据存储在客户端,在每次请求时发送到服务器,并在客户端结束执行时失效。
- 将少量非易失数据存储在持久性 Cookie 中。数据存储在客户端直到失效,并在每次请求时发送到服务器。
- 将少量请求特定的数据存储在视图状态中。数据从服务器发送到客户端并返回。