Asp.Net的强大功能之一就是能自动保持服务器控件的状态(包括其控件和Html)而无需用户编写任何代码,下面我就介绍下如何实现Asp.Net的状态管理。
在Asp.Net中有四种状态类型:
- <!--[if !supportLists]--> <!--[endif]-->控件状态
该状态不能修改,只能直接访问或者被禁用。
- <!--[if !supportLists]--><!--[endif]-->视图状态
指页面及其所有控件的状态。试图状态子阿往返过程中由ASP.NET框架自动维护。当页面发送到服务器时,读取视图状态。在页面发送到浏览器时,会俯视图状态。视图状态存储在页面一个隐藏字段的状 态包中,状态被编码为一个字符串变量。由于状态通过标但字段来维护,因此这种技术适用于所有浏览 器。
如果无须维护页面视图状态,则可以通过禁用页面视图状态来提高性能。在Page指令中将 EnableViewState属性设置为false,可实现禁用页面视图状态。
另一种方法是省略表单的服务器端标签(<form runat=”server”>),它也可避免维护视图状态,但是要注意这种做法会禁用所有服务器端的处理和控制。
在Web.config配置文件<pages>节的EnableViewState属性为false,可以禁用整个应用程序的视图状态。或者将machine.config配置文件作同样的修改则可以禁用本机中所有应用程序的视图状态。
而控件也可以维护或禁用某个控件的视图状态。我们可以通过设置Control.EnableViewState属性来实现。该属型为Boolean类型,默认值为true。同页面性质一样,禁用控件的视图状态也可提高性能。
在这里要注意的是:视图状态只是针对字符串、整数、布尔值、数组、数组列表和哈希表进行优化。其他.NET数据类型可以在视图状态中被串行化和持久化,但是这会导致性能下降,产生巨大的视图状态字段。
因此,在部分这种情况下,会话状态可能是一个更好的选择。另一方面,视图状态不消耗任何服务 器资源,也不会超时,而会话则会超时。
在上面述说中我们涉及到一个状态包的概念。那什么是状态包?如果值没有和任何控件关联,而需要在交互过程中保留这些值,则可以把这些值保存在页面的状态宝中。状态宝时一个包含属性/值对的数据结构,与对象关联的数据以字符串形式存储。有效对象都是原始数据类型类型(如:整数、字节、字符串、布尔值等)。状态包使用StateBag类实现,它是一个(非类型安全)字典对象。可以如同操作任何字典对象一样,添加或者删除状态包中的项。
状态包使用与视图状态同样的隐藏字段来维持。可通过ViewState关键字设置和获取状态包中内容的值。
- <!--[if !supportLists]--><!--[endif]-->应用程序状态
Web应用程序中包括所有的Web页面、组件、代码、文件和图片。这些内容都存储在虚拟目录或其子目录中。
Global.asax文件包含Web应用程序的全局代码。Global.asax存储在应用程序虚拟根目录中。在 Global.asax文件中包括Application_Start、Application_End、Application_Error、Session_Start和 Session_End事件的处理程序。当应用程序收到第一个用户请求时,引发Application_Start事件。如果global.asax文件被编辑过并且保存了改动,那么当前所有等待的请求都将被完成,同时引发Application_End,然后将重启应用程序。这种顺序有效地重启应用程序,将写入所有的状态信息。而且应用程序的重启对所有用户是透明的,因为它只有在完成了所有的等待请求后,在接受新请求之前才发生。当接受了一个请求,应用程序再次重新开始时,则引发另一个Application_Start事件。
利用字典对象可以实现信息在应用程序范围内的全局共享,每个对象都与一个关键字关联。这是通过HttpApplication类的内置属性Application实现的。Application属性克访问内容集合,而该机和的内容是通过代码直接添加到应用状态之中的。
- <!--[if !supportLists]--><!--[endif]-->会话状态
当我们连接到一个Asp.Net网站时,实际上就已经创建了一个会话。该会话为无状态的Web赋予了状态,使网站能识别来自同一启动会话的浏览器的后续页面请求。这可以保持页面状态,直到会话超时或此次会话结束为止。(注意:在Asp.Net中默认的超时时间是20分钟,超时时间可以设置)
Asp.Net中为会话状态提供以下特性:
<!--[if !supportLists]--> 1.在禁用Cookies的浏览器中运行
<!--[if !supportLists]--> 2.<!--[endif]-->对于已经存在的会话请求进行辨识
<!--[if !supportLists]--> 3.存储会话范围内的数据在多请求钟使用。这些数据可以被配置成持续贯穿于IIS重启和运行在多处理器(Web园)和多服务器(Web场)的环境,像单处理器和单机环境情况下一样。
<!--[if !supportLists]--> 4.<!--[endif]-->激发会话事件,如Session_Start和Session_End,这些在global.asax或者是其他的应用代码里处理
<!--[if !supportLists]--> 5.<!--[endif]-->如果会话结束或超时,则会自动释放会话资源
默认情况下,会话状态作为Asp.Net进程的一部分存储在服务器内存中,但是也可以通过配置将个别会话存储在Asp.Net进程外或者单独的状态服务器上还可以存储在SQL Server数据库上,这样,即使Asp.Net进程重启或者崩溃,会话还能继续运行。
Asp.Net采用120位长的SessionID来标示和跟踪会话,这个SessionID从客户端传送到服务器端并从服务器返回。所用的方式是HTTP Cookie还是修改了URL取决于应用程序的配置。.Net Framework会自动定义SessionID而无需人工编程处理。SessionID由URL-legal ASCII字符组成,并具备
- <!--[if !supportLists]--> <!--[endif]-->SessionID是全局唯一的,不可能存在两个会话具有相同的SessionID
- <!--[if !supportLists]-->SessionID是随机的,即使知道已存在的SessionID也很难活得其它会话的SessionID
会话状态通过HttpSessionState类的内容集合属性实现。这个集合是一个关键值(非泛型)字典,其中包括所有会话状态字段对象,而这些对象是编程直接添加的。使用会话关键字可以设置和检索字典对象。
会话状态的配置:
页面会话状态的配置我们可以由页面顶部的Page指令来控制(在页面的html代码的开头可以找到该 配置项)
默认状态系统是启用会话状态的,我们也可以通过在Page指令中添加EnableSessionState属性来启 用,如
Inherits = " WebStateStudy._Default " EnableSessionState = " true " %>
禁用页面会话状态:
将会话状态设为只读,使其只能读取不能修改会话数据
注意:EnableSessionState是大小写敏感的,禁用会话状态或者将其设置为只读的原因是为了提高 性能。如果在页面中不必使用会话状态,那么可以通过禁用会话状态以得到小幅度的性能提升,同时还可节约服务器资源。
默认情况下,会话状态作为Asp.Net进程的一部分存储在服务期内存中。但通过预设Web.config和SessionState配置节的mode属性,可使会话状态独立于Asp.Net进程存储,或存储在独立的状态服务器,或存储在SQL Server数据库。这样,会话状态可在Asp.Net进程失败停止或重启的情况下仍然存在。除了突发的失败停止,Asp.Net也可被配置为每个进程在处理一定数量的请求或工作一段时间之后定期重启,以提高可靠性和稳定性。会话状态在这些重启间会得以保存。
在Web.config中,会话状态配置信息包含在<System.web>节点中,而<System.web>被包含在 <configuration>节点中。如下:
.
< sessionState
mode = " InProc "
cookieless = " false "
timeout = " 20 "
stateConnectionString = " tcpip=127.0.0.1:42424 "
sqlConnectionString = " data source=127.0.0.1;userid=sa;password= " />
.
</ System.web >
sessionState中有以下几个可选项:
- <!--[if !supportLists]-->allowCustomSqlDatabase
若为True则存储会话数据的SQL数据库可以是用户自定义的数据库。默认为false,此时默认数据库为ASPState,且连接字符串中不能设置Initial Catalog
- <!--[if !supportLists]-->mode
指定对由Web.config所控制的所有页面是否禁用会话状态。若启用则会话状态的存储位置则是该属性
在进程内存储会话状态((Inproc)是最快的方法,它比较适用于少量易变数据。然而,这种方法容易受到进程失败的影响,并不适合多服务器或单机多处理器。对于这些情况,需要使用StateServer或SqlServer。对于失败或重启服务器,SqlServer是最健壮的方法。
- <!--[if !supportLists]-->cookieless
Cookie同会话状态一起使用存储的SessionID,这样服务器可了解请求是与哪个会话相连的。 Cookieless的可能值包括 AutoDetect、UseCookies、UseDeviceProfile和UseUri,其中UseCookie为默认值。
当设置为AutoDetect时,将检测发出请求的客户端是否支持Cookie。当设置为seDeviceProfile 时,将根据HttpBrowserCapabilities设置来确定是否支持使用Cookie。如果这些都不支持使用Cookie或指定了UseUri,则SessionID会向URL添加一个值以实现持久化。
- <!--[if !supportLists]-->cookieName
存储SessionID的cookie的名称。默认值是ASP.NET_SessionId。
- <!--[if !supportLists]-->customPrivder
自定义会话状态提供者的名称。
- <!--[if !supportLists]--><!--[endif]-->regenrateExpiredSessionId
该属性与无cookie会话一起使用。若为true则过期的SessionID会被一个新的标示所替换。默认值为false
- <!--[if !supportLists]--><!--[endif]-->sqlCommandTimeout
SQL命令在被取消前处于空闲状态的事件秒数。默认值是30。
- <!--[if !supportLists]--><!--[endif]--> sqlConnectionString
指定连接到余兴SQL Server实例的连接串。若mode为SqlServer则必须设置它。
- <!--[if !supportLists]--><!--[endif]--> stateConnectionString
指定用于存储会话状态的服务器和端口。若mode设为StateServer时则必须指定它。
- <!--[if !supportLists]--><!--[endif]-->stateNetworkTimeout
当mode值被设置为StateServer时使用,其用于指定在请求被取消之前,TCP/IP网络连接可以处于空闲状态的秒数。默认值为10
- <!--[if !supportLists]--><!--[endif]-->timeout
指定会话超时并在被服务器放弃之前处于不活跃状态的分钟数。默认为20。
- <!--[if !supportLists]--><!--[endif]-->useHostingIdentity
若设为true则ASP.Net进程标识会被模拟。默认值为true
会话中的应用程序对象:
另外一个在会话之间传递信息的方法是通过静态对象。静态对象在global.asax文件中声明。一旦声明对象的Scope属性被设置为Session,那么就可以在应用程序代码中通过名称在会话内访问对象。