ASP.NET - 状态管理

超文本传输协议 (HTTP) 是一种无状态协议。 当客户端与服务器断开连接时,ASP.NET 引擎将丢弃页面对象。 这样,每个 Web 应用程序都可以扩展以同时服务大量请求,而不会耗尽服务器内存。

但是,需要某种技术来存储请求之间的信息并在需要时检索它。 该信息,即当前会话中当前用户的所有控件和变量的当前值,称为状态。

ASP.NET 管理四种类型的状态:

  • 视图状态
  • 控件状态
  • 会话状态
  • 应用程序状态

视图状态

视图状态是页面及其所有控件的状态。 它由 ASP.NET 框架在帖子之间自动维护。

当页面发送回客户端时,页面及其控件的属性更改将被确定,并存储在名为 _VIEWSTATE 的隐藏输入字段的值中。 当页面再次回发时,_VIEWSTATE 字段将通过 HTTP 请求发送到服务器。

可以启用或禁用视图状态:

  • 整个应用程序通过在中设置EnableViewState属性来显示。 web.config 文件的部分。

  • 页面,通过设置Page指令的EnableViewState属性,如<%@ Page Language="C#" EnableViewState="false" %>

  • 通过设置 Control.EnableViewState 属性实现的控件

它是使用 StateBag 类定义的视图状态对象来实现的,该类定义了视图状态项的集合。 状态包是一个包含属性值对的数据结构,存储为与对象关联的字符串。

StateBag类具有以下属性:

属性 描述
Item(name) 具有指定名称的视图状态项的值。 这是 StateBag 类的默认属性。
Count 视图状态集合中的项目数。
Keys 集合中所有项目的键的集合。
Values 集合中所有项目的值的集合。

StateBag 类具有以下方法:

方法 描述
Add(name, value) 将项目添加到视图状态集合并更新现有项目。
Clear 从集合中删除所有项目。
Equals(Object) 判断指定对象是否等于当前对象。
Finalize 允许它释放资源并执行其他清理操作。
GetEnumerator 返回一个枚举器,用于迭代 StateBag 对象中存储的 StateItem 对象的所有键/值对。
GetType 获取当前实例的类型。
IsItemDirty 检查StateBag对象中存储的StateItem对象以评估其是否已被修改。
Remove(name) 删除指定的项目。
SetDirty 设置 StateBag 对象的状态及其包含的每个 StateItem 对象的 Dirty 属性。
SetItemDirty 设置 StateBag 对象中指定 StateItem 对象的 Dirty 属性。
ToString 返回表示状态包对象的字符串。

示例

以下示例演示了存储视图状态的概念。 让我们保留一个计数器,每次通过单击页面上的按钮回发页面时,该计数器都会增加。 标签控件显示计数器中的值。

标记文件代码如下:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="statedemo._Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >

   <head runat="server">
      <title>
         Untitled Page
      </title>
   </head>
   
   <body>
      <form id="form1" runat="server">
      
         <div>
            <h3>View State demo</h3>
         
            Page Counter:
            
            <asp:Label ID="lblCounter" runat="server" />
            <asp:Button ID="btnIncrement" runat="server" Text="Add Count" onclick="btnIncrement_Click" />
         </div>
         
      </form>
   </body>
   
</html>

示例文件背后的代码如下所示:

public partial class _Default : System.Web.UI.Page
{
   public int counter
   {
      get
      {
         if (ViewState["pcounter"] != null)
         {
            return ((int)ViewState["pcounter"]);
         }
         else
         {
            return 0;
         }
      }
      
      set
      {
         ViewState["pcounter"] = value;
      }
   }
        
   protected void Page_Load(object sender, EventArgs e)
   {
      lblCounter.Text = counter.ToString();
      counter++;
   }
}

它将产生以下结果:

查看状态演示

控件状态

无法修改、直接访问或禁用控件状态。

会话状态

当用户连接到 ASP.NET 网站时,会创建一个新的会话对象。 当会话状态打开时,将为每个新请求创建一个新的会话状态对象。 该会话状态对象成为上下文的一部分,并且可以通过页面使用它。

会话状态通常用于存储应用程序数据,例如库存、供应商列表、客户记录或购物车。 它还可以保留有关用户及其偏好的信息,并跟踪待处理的操作。

使用 120 位 SessionID 来识别和跟踪会话,该 SessionID 作为 cookie 或修改后的 URL 从客户端传递到服务器并返回。 SessionID 是全局唯一且随机的。

会话状态对象是从 HttpSessionState 类创建的,该类定义会话状态项的集合。

HttpSessionState 类具有以下属性:

属性 描述
SessionID 唯一的会话标识符。
Item(name) 具有指定名称的会话状态项的值。 这是 HttpSessionState 类的默认属性。
Count 会话状态集合中的项目数。
TimeOut 获取并设置会话状态提供程序终止会话之前请求之间允许的时间量(以分钟为单位)。

HttpSessionState 类具有以下方法:

方法 描述
Add(name, value) 将项目添加到会话状态集合中。
Clear 从会话状态集合中删除所有项目。
Remove(name) 从会话状态集合中删除指定的项目。
RemoveAll 从会话状态集合中删除所有键和值。
RemoveAt 从会话状态集合中删除指定索引处的项目。

会话状态对象是一个名称-值对,用于存储和检索会话状态对象中的一些信息。 您可以使用以下代码来实现相同的目的:

void StoreSessionInfo()
{
   String fromuser = TextBox1.Text;
   Session["fromuser"] = fromuser;
}

void RetrieveSessionInfo()
{
   String fromuser = Session["fromuser"];
   Label1.Text = fromuser;
}

上面的代码在Session字典对象中只存储字符串,但是,它可以存储所有的原始数据类型以及由原始数据类型组成的数组,以及 DataSet、DataTable、HashTable 和 Image 对象,以及从 ISerialized 对象继承的任何用户定义的类。

示例

以下示例演示了存储会话状态的概念。 页面上有两个按钮,一个用于输入字符串的文本框和一个用于显示上次会话存储的文本的标签。

标记文件代码如下:

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default"  %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >

   <head runat="server">
      <title>
         Untitled Page
      </title>
   </head>
   
   <body>
      <form id="form1" runat="server">
         <div>
            &nbsp; &nbsp; &nbsp;
            
            <table style="width: 568px; height: 103px">
            
               <tr>
                  <td style="width: 209px">
                     <asp:Label ID="lblstr" runat="server" Text="Enter a String"  style="width:94px">
                     </asp:Label>
                  </td>
					
                  <td style="width: 317px">
                     <asp:TextBox ID="txtstr" runat="server" style="width:227px">
                     </asp:TextBox>
                  </td>
               </tr>
	
               <tr>
                  <td style="width: 209px"> </td>
                  <td style="width: 317px"> </td>
               </tr>
	
               <tr>
                  <td style="width: 209px">
                     <asp:Button ID="btnnrm" runat="server" 
                        Text="No action button" style="width:128px" />
                  </td>
	
                  <td style="width: 317px">
                     <asp:Button ID="btnstr" runat="server" 
                        OnClick="btnstr_Click" Text="Submit the String" />
                  </td> 
               </tr>
	
               <tr>
                  <td style="width: 209px">  </td>
	
                  <td style="width: 317px">  </td>  
               </tr>
	
               <tr>
                  <td style="width: 209px">
                     <asp:Label ID="lblsession" runat="server"  style="width:231px"  >
                     </asp:Label>
                  </td>
	
                  <td style="width: 317px">  </td>
               </tr>
	
               <tr>
                  <td style="width: 209px">
                     <asp:Label ID="lblshstr" runat="server">
                     </asp:Label>
                  </td>
	
                  <td style="width: 317px">  </td>
               </tr>
               
            </table>
            
         </div>
      </form>
   </body>
</html>

它在设计视图中应如下所示:

会话设计视图

文件背后的代码如下:

public partial class _Default : System.Web.UI.Page 
{
   String mystr;
   
   protected void Page_Load(object sender, EventArgs e)
   {
      this.lblshstr.Text = this.mystr;
      this.lblsession.Text = (String)this.Session["str"];
   }
   
   protected void btnstr_Click(object sender, EventArgs e)
   {
      this.mystr = this.txtstr.Text;
      this.Session["str"] = this.txtstr.Text;
      this.lblshstr.Text = this.mystr;
      this.lblsession.Text = (String)this.Session["str"];
   }
}

执行文件并观察其工作原理:

会话运行视图

应用程序状态

ASP.NET 应用程序是 Web 服务器上单个虚拟目录中所有网页、代码和其他文件的集合。 当信息存储在应用程序状态时,所有用户都可以使用它。

为了提供应用程序状态的使用,ASP.NET 从 HTTPApplicationState 类为每个应用程序创建一个应用程序状态对象,并将该对象存储在服务器内存中。 该对象由类文件 global.asax 表示。

应用程序状态主要用于存储点击计数器和其他统计数据、全局应用程序数据(例如税率、折扣率等),并跟踪访问网站的用户。

HttpApplicationState 类具有以下属性:

属性 描述
Item(name) 具有指定名称的应用程序状态项的值。 这是 HttpApplicationState 类的默认属性。
Count 应用程序状态集合中的项目数。

HttpApplicationState 类具有以下方法:

方法 描述
Add(name, value) 将一个项目添加到应用程序状态集合中。
Clear 从应用程序状态集合中删除所有项目。
Remove(name) 从应用程序状态集合中删除指定的项目。
RemoveAll 从 HttpApplicationState 集合中删除所有对象。
RemoveAt 按索引从集合中删除 HttpApplicationState 对象。
Lock() 锁定应用程序状态集合,以便只有当前用户可以访问它。
Unlock() 解锁应用程序状态集合,以便所有用户都可以访问它。

应用程序状态数据通常通过编写事件处理程序来维护:

  • Application_Start
  • Application_End
  • Application_Error
  • Session_Start
  • Session_End

以下代码片段显示了存储应用程序状态信息的基本语法:

Void Application_Start(object sender, EventArgs e)
{
   Application["startMessage"] = "The application has started.";
}

Void Application_End(object sender, EventArgs e)
{
   Application["endtMessage"] = "The application has ended.";
}