最近在开发一ASP.NET2.0系统时,在程序中做删除或创建文件操作时,出现session丢失问题。在网上搜了不少资料,最后终于解决了,采用了如下方法:
1、
asp.net Session
的实现:
asp.net的Session是基于HttpModule技术做的,HttpModule可以在请求被处理之前,对请求进行状态控制,由于Session本身就是用来做状态维护的,因此用HttpModule做Session是再合适不过了。
asp.net的Session是基于HttpModule技术做的,HttpModule可以在请求被处理之前,对请求进行状态控制,由于Session本身就是用来做状态维护的,因此用HttpModule做Session是再合适不过了。
ASP.NET
提供了
Session
对象,从而允许程序员识别、存储和处理同一个浏览器对象对服务器上某个特定网络应用程序的若干次请求的上下文信息。
Session
对应浏览器与服务器的同一次对话,在浏览器第一请求网络应用程序的某个页面时,服务器会触发
Session_onStart
事件;在对话超时或者被关闭的时候会触发
Session_onEnd
事件。
程序员可以在代码中响应这两个事件来处理与同一次对话相关的任务,如开辟和释放该次对话要使用的资源等。
在
ASP.NET
的程序中要使用
Session
对象时,必须确保页面的
@page
指令中
EnableSessionState
属性是
True
或者
Readonly
,并且在
web.config
文件中正确的设置了
SessionState
属性。
ASP.NET
中
Session
的状态保持是由
web.config
文件中的
<system.web>
标记下的
<sessionstate>
标记的
mode
属性来决定的。该属性有四种可能的值:
Off
、
Inproc
、
StateServer
和
SQlServer.
设为
Off
会禁用
Session.
Inproc
是缺省的设置
,
这种模式和以前的
ASP
的会话状态
的方法是类似的
,
会话的状态会被保存在
ASP.NET
进程中,它的优点是显而易见的:性能。进程内的数据访问自然会比夸进程的访问快。
然而,这种方法
Session
的状态依赖于
ASP.NET
进程,当
IIS
进程崩溃或者正常重起启时,保存在进程中的状态将丢失。
为了克服
Inproc
模式的缺点,
ASP.NET
提供了两种进程外保持会话状态的方法。
ASP.NET
首先提供了提供了一个
Windows
服务:
ASPState
,
这个服务启动后,
ASP.NET
应用程序可以将
mode
属性设置为
“SateServer”,
来使用这个
Windows
服务提供的状态管理方法。
除了在
web.config
文件中设置
mode
属性为
StateServer
外,还必须设置运行
StateServer
服务器的
IP
地址和端口号
.
如果在
IIS
所在的机器运行
StateServer
则
IP
地址就是
127.0.0.1,
端口号通常是
42424.
配置如下:
mode=”StateServer”
stateConnectionString="tcpip=127.0.0.1:42424"
使用这种模式
,
会话状态的存储将不依赖
IIS
进程的失败或者重启
,
会话的状态将存储在
StateServer
进程的内存空间中。
另一种会话状态模式是
SQLServer
模式。这种模式是将会话的状态保存在
SQL Server
数据库中的。使用这种模式前,必须至少有一台
SQL Server
服务器,并在服务器中建立需要的表和存储过程。
.NET SDK
提供了两个脚本来简化这个工作:
InstallSqlState.sql
和
UnInstallSqlState.sql
。这两国文件存放在下面路径中:
<%SYSTEMDRIVER%>/Winnt/Microsoft.NET/Framework/<%version%>/
要配置
SQL Server
服务器,可以在命令行中运行
SQL Server
提供的命令行工具
osql.exe
osql -s [server name] -u [user] -p [password] <InstallSqlState.sql
例如:
osql -s (local) -u as -p “”-i InstallSqlState.sql
做好必要的数据库准备工作后,将
web.config
文件中的
sessionstate
元素的
mode
属性改为
”sqlserver”,
并指定
SQL
连接字符串。具体如下:
mode="SQLServer"
sqlConnectionString="data source=127.0.0.1;userid=sa;password=;Trusted_Connection=yes"
使用
SQLServer
模式处了可以使
Session
的状态不依赖于
IIS
服务器之外,还可以利用
SQL Server
的集群,使状态存储不依赖于单个的
SQL Server,
这样就可以为应用程序提供极大的可靠性。
|
2、
丢失原因:
转(
1
):
Asp.net
默认配置下,
Session
莫名丢失的原因及解决办法
|
正常操作情况下
Session
会无故丢失。因为程序是在不停的被操作,排除
Session
超时的可能。另外,
Session
超时时间被设定成
60
分钟,不会这么快就超时的。
这次到 优快云 上搜了一下帖子,发现好多人在讨论这个问题,然后我又 google 了一下,发现微软网站上也有类似的内容。 现在我就把原因和解决办法写出来。
原因:
由于
Asp.net
程序是默认配置,所以
Web.Config
文件中关于
Session
的设定如下:
<sessionState
mode
=
'InProc'
stateConnectionString
=
'tcpip=127.0.0.1:42424'
sqlConnectionString
=
'data source=127.0.0.1;Trusted_Connection=yes'
cookieless
=
'true'
timeout
=
'60'
/>
我们会发现 sessionState 标签中有个属性 mode ,它可以有 3 种取值: InProc 、 StateServer?SQLServer (大小写敏感) 。默认情况下是 InProc ,也就是将 Session 保存在进程内( IIS5 是 aspnet_wp.exe ,而 IIS6 是 W3wp.exe ),这个进程不稳定,在某些事件发生时,进程会重起,所以造成了存储在该进程内的 Session 丢失。
[
asp
的
Session
是具有进程依赖性的。
ASP Session
状态存于
IIS
的进程中,也就是
inetinfo.exe
这个程序。所以当
inetinfo.exe
进程崩溃时,这些信息也就丢失。
]
哪些情况下该进程会重起呢?微软的 一篇文章 告诉了我们: 1 、配置文件中 processModel 标签的 memoryLimit 属性 2 、 Global.asax 或者 Web.config 文件被更改 3 、 Bin 文件夹中的 Web 程序( DLL )被修改 4 、杀毒软件扫描了一些 .config 文件。 更多的信息请参考 PRB: Session variables are lost intermittently in ASP.NET applications
解决办法:
前面说到的
sessionState
标签中
mode
属性可以有三个取值,除了
InProc
之外,还可以为
StateServer
、
SQLServer
。这两种存
Session
的方法都是进程外的,所以当
aspnet_wp.exe
重起的时候,不会影响到
Session
。
现在请将 mode 设定为 StateServer 。 StateServer 是本机的一个服务 ,可以在系统服务里看到服务名为 ASP.NET State Service 的服务,默认情况是不启动的。当我们设定 mode 为 StateServer 之后,请手工将该服务启动。 这样,我们就能利用本机的 StateService 来存储 Session 了,除非电脑重启或者 StateService 崩掉,否则 Session 是不会丢的(因 Session 超时被丢弃是正常的)。 除此之外,我们还可以将 Session 通过其他电脑的 StateService 来保存 [ 如使用状态服务器 ] 。具体的修改是这样的。同样还在 sessionState 标签中,有个 stateConnectionString='tcpip=127.0.0.1:42424' 属性,其中有个 ip 地址,默认为本机( 127.0.0.1 ),你可以将其改成你所知的运行了 StateService 服务的电脑 IP ,这样就可以实现位于不同电脑上的 Asp.net 程序互通 Session 了。 如果你有更高的要求,需要在服务期重启时 Session 也不丢失,可以考虑将 mode 设定成 SQLServer ,同样需要修改 sqlConnectionString 属性。关于使用 SQLServer 保存 Session 的操作,请访问 这里 。 在使用 StateServer 或者 SQLServer 存储 Session 时,所有需要保存到 Session 的对象除了基本数据类型(默认的数据类型,如 int 、 string 等)外,都必须序列化。 只需将 [Serializable] 标签放到要序列化的类前就可以了。 如: [Serializable] public class MyClass { ...... } 具体的序列化相关的知识请参 这里 。 至此,问题解决。 |