• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
works guo

成功的渴望与生俱来---- 成功是获得赞美与尊重的最有效的途径
博客园    首页    新随笔    联系   管理    订阅  订阅

Custom Session-State Module


SessionStateModule类



为一个应用程序提供session-state服务.这个类不能继承.

[AspNetHostingPermissionAttribute(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
public sealed class SessionStateModule : IHttpModule


SessionStateModle 是ASP.NET的默认Sssion-state Handler,它写入session 数据并且从session-state存储中找回它和调用Session_OnStart和Session_OnEnd事件.下面详细关于怎样使用ASP.NET session state 去存储和为一个用户session找回值.

你能自定义实现IHttpModule接口取代SessionStateModule.


(1)IHttpModule Interface


提供module初始化和配置事件去实现类.

[AspNetHostingPermissionAttribute(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
[AspNetHostingPermissionAttribute(SecurityAction.InheritanceDemand, Level 
= AspNetHostingPermissionLevel.Minimal)]
public interface IHttpModule



(2)SessionStateUtility Class


提供由session-state modules和session-state储存提供者提供去管理ASP.NET应用程序Session信息helper方法.

[AspNetHostingPermissionAttribute(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
public static class SessionStateUtility


注意
SessionStateUtility类提供static helper方法,这个方法被一个session-state module所使用或一个session-state存储提供者.应用程序开发者不需要使用他们的代码调用这些方法.

下面是session-state module和session-state 储存者使用的方法:


(3)SessionStateUtility.GetHttpSessionStateFromContext Method


从当前请求context中找回session data.
public static IHttpSessionState GetHttpSessionStateFromContext(
    HttpContext context
)


Context参数为HttpContext

返回值类型为System.Web.SessionState.IHttpSessionState.
从当前请求中的Session 数据迁移到IHttpSessionState实现实例.

GetHttpSessionStateFromContext 方法能被一个session-state module使用来从当前请求中找回session data.在触发RelesseRequestState期间是在在一个请求结束时.返回session数据,之后被写入session数据存储.如果Session已经被废弃,这个session数据能从数据存储中被移出和HttpContext,并且Session_OnEnd时间就被执行.

注意:
你能使用RemoveHttpSessionStateFromContext方法去移出session 数据,并且使用 RaiseSessionEnd调用Session_OnEnd事件.

private void OnReleaseRequestState(object source, EventArgs args)
{
    HttpApplication app 
= (HttpApplication)source;
    HttpContext context 
= app.Context;
    
string sessionID;

    
// Read the session state from the context
    HttpSessionStateContainer stateProvider =
      (HttpSessionStateContainer)(SessionStateUtility.GetHttpSessionStateFromContext(context));

    
// If Session.Abandon() was called, remove the session data from the local Hashtable
    
// and execute the Session_OnEnd event from the Global.asax file.
    if (stateProvider.IsAbandoned)
    
{
        
try
        
{
            pHashtableLock.AcquireWriterLock(Int32.MaxValue);

            sessionID 
= pSessionIDManager.GetSessionID(context);
            pSessionItems.Remove(sessionID);
        }

        
finally
        
{
            pHashtableLock.ReleaseWriterLock();
        }


        SessionStateUtility.RaiseSessionEnd(stateProvider, 
this, EventArgs.Empty);
    }


    SessionStateUtility.RemoveHttpSessionStateFromContext(context);
}




(4)SessionStateUtility.AddHttpSessionStateToContext Method


从当前请求context里申请session数据.

public static void AddHttpSessionStateToContext(
    HttpContext context,
    IHttpSessionState container
)


参数:

context:就是HttpContext.

container:类型为IHttpSessionState,实现这个实例添加进去详细的HTTP context.

注意:

AddHttpSessionStateToContext方法被一个session-state module用来在当前请求中添加session 数据,在开始请求触发AcquireRequestState事件期间.在当前请求Session数据既会找回现有session或创建一个新的session.这个Session数据是封装在一个IHttpSesssionState实现的实例中.与当前的HttpContext一起传给AddHttpSessionStateToContext方法中.提供Session数据之后通过当前context的Session属性产生可是使用的应用程序代码.



(5)SessionStateUtility.RemoveHttpSessionStateFromContext方法


从context中移出session data.

public static void RemoveHttpSessionStateFromContext(
    HttpContext context
)


参数:

cotext:就是HttpContext;

注意:
RemoveHttpSessionStateFromContext 方法是从HttpContext中清出session数据.一个 session-state module将在ReleaseRequestState事件handler中调用RemoveHttpSessionStateFromContext.


(6)SessionStateUtility.GetSessionStaticObjects Method


从context中得到一个static Object collection引用.

参数:

context:类型为HttpContext.

GetSessionStaticObjects被使用来找回定义在Global.asax文件中的static object collection.一个session-state module实现将提供返回HttpStaticObjcetCollection 集合去在IHttpSessionState实现的实例中使用AddHttpSessionStateToContext方法添加进当前context.





(7)HttpSessionStateContainer 类


包括Session-state值也有为当前去请求session-level设置.

Session data 传递和从当前的HttpContext中找回,就如HttpSessionStateContainer对象或任何有效的IHttpSessionState接口的实现都可以做到.

ASP.NET提供session-state管理允许你存储信息结合一个唯一浏览器session跨越多个请求.你能存储在用key,index控制的一个值的collection中.访问Session值并且结合通过当前请求的Sesion属性或Page的Session属性给HttpSessionState类所使用,而这个HttpSessionState类访问Sesion-state值和session-level设置都在一个Sesion-state Container设置和引用,而这个HttpSessionState interface的实现已经迁移session-state数据并且由session-state module为HttpApplication添加进当前请求的HttpContext中.

而这个HttpSessionState类调用HttpSessionStateContainer类,来管理在内存中的session的设置和值.

在HttpSessionStateContainer类是HttpSessionState interface的ASP.NET实现.这个HttpSessionStateContainer类不需要调用应用程序代码.如果你要使用custom Session-state module替换SessionStateModule,你能使用HttpSessionStateContainer class或提供你自己的IHttpSessionState interface的实现.



当创建一个SessionStateStoreData时对象一个sessionStateStoreProviderBase还能使用GetSessionStaticObjcets方法.



下面代码为一custom session-state module实现使用Hashtable存储session信息.这个module使用SessionStateUtility 类去引用当前请求的HttpContext和SessionIDManager,重新找回当前的HttpStaticObjcetCollection,并且调用Session_OnEnd事件定义在Global.asax文件.但这里没有防止多个Web请求使用相同的session 标记.

using System;
using System.Web;
using System.Web.SessionState;
using System.Collections;
using System.Threading;
using System.Web.Configuration;
using System.Configuration;

namespace Samples.AspNet.SessionState
{

    
public sealed class MySessionStateModule : IHttpModule, IDisposable
    
{
        
private Hashtable pSessionItems = new Hashtable();
        
private Timer pTimer;
        
private int pTimerSeconds = 10;
        
private bool pInitialized = false;
        
private int pTimeout;
        
private HttpCookieMode pCookieMode = HttpCookieMode.UseCookies;
        
private ReaderWriterLock pHashtableLock = new ReaderWriterLock();
        
private ISessionIDManager pSessionIDManager;
        
private SessionStateSection pConfig;


        
// The SessionItem class is used to store data for a particular session along with
        
// an expiration date and time. SessionItem objects are added to the local Hashtable
        
// in the OnReleaseRequestState event handler and retrieved from the local Hashtable
        
// in the OnAcquireRequestState event handler. The ExpireCallback method is called
        
// periodically by the local Timer to check for all expired SessionItem objects in the
        
// local Hashtable and remove them.

        
private class SessionItem
        
{
            
internal SessionStateItemCollection Items;
            
internal HttpStaticObjectsCollection StaticObjects;
            
internal DateTime Expires;
        }



        
//
        
// IHttpModule.Init
        
//

        
public void Init(HttpApplication app)
        
{
            
// Add event handlers.
            app.AcquireRequestState += new EventHandler(this.OnAcquireRequestState);
            app.ReleaseRequestState 
+= new EventHandler(this.OnReleaseRequestState);

            
// Create a SessionIDManager.
            pSessionIDManager = new SessionIDManager();
            pSessionIDManager.Initialize();

            
// If not already initialized, initialize timer and configuration.
            if (!pInitialized)
            
{
                
lock (typeof(MySessionStateModule))
                
{
                    
if (!pInitialized)
                    
{
                        
// Create a Timer to invoke the ExpireCallback method based on
                        
// the pTimerSeconds value (e.g. every 10 seconds).

                        pTimer 
= new Timer(new TimerCallback(this.ExpireCallback),
                                           
null,
                                           
0,
                                           pTimerSeconds 
* 1000);

                        
// Get the configuration section and set timeout and CookieMode values.
                        Configuration cfg =
                          WebConfigurationManager.OpenWebConfiguration(System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath);
                        pConfig 
= (SessionStateSection)cfg.GetSection("system.web/sessionState");

                        pTimeout 
= (int)pConfig.Timeout.TotalMinutes;
                        pCookieMode 
= pConfig.Cookieless;

                        pInitialized 
= true;
                    }

                }

            }

        }




        
//
        
// IHttpModule.Dispose
        
//

        
public void Dispose()
        
{
            
if (pTimer != null)
            
{
                
this.pTimer.Dispose();
               ((IDisposable)pTimer).Dispose();
            }

        }



        
//
        
// Called periodically by the Timer created in the Init method to check for 
        
// expired sessions and remove expired data.
        
//

        
void ExpireCallback(object state)
        
{
            
try
            
{
                pHashtableLock.AcquireWriterLock(Int32.MaxValue);

                
this.RemoveExpiredSessionData();

            }

            
finally
            
{
                pHashtableLock.ReleaseWriterLock();
            }

        }



        
//
        
// Recursivly remove expired session data from session collection.
        
//
        private void RemoveExpiredSessionData()
        
{
            
string sessionID;

            
foreach (DictionaryEntry entry in pSessionItems)
            
{
                SessionItem item 
= (SessionItem)entry.Value;

                
if ( DateTime.Compare(item.Expires, DateTime.Now)<=0 )
                
{
                    sessionID 
= entry.Key.ToString();
                    pSessionItems.Remove(entry.Key);

                    HttpSessionStateContainer stateProvider 
=
                      
new HttpSessionStateContainer(sessionID,
                                                   item.Items,
                                                   item.StaticObjects,
                                                   pTimeout,
                                                   
false,
                                                   pCookieMode,
                                                   SessionStateMode.Custom,
                                                   
false);

                    SessionStateUtility.RaiseSessionEnd(stateProvider, 
this, EventArgs.Empty);
                    
this.RemoveExpiredSessionData();
                    
break;
                }

            }


        }



        
//
        
// Event handler for HttpApplication.AcquireRequestState
        
//

        
private void OnAcquireRequestState(object source, EventArgs args)
        
{
            HttpApplication app 
= (HttpApplication)source;
            HttpContext context 
= app.Context;
            
bool isNew = false;
            
string sessionID;
            SessionItem sessionData 
= null;
            
bool supportSessionIDReissue = true;

            pSessionIDManager.InitializeRequest(context, 
false, out supportSessionIDReissue);
            sessionID 
= pSessionIDManager.GetSessionID(context);


            
if (sessionID != null)
            
{
                
try
                
{
                    pHashtableLock.AcquireReaderLock(Int32.MaxValue);
                    sessionData 
= (SessionItem)pSessionItems[sessionID];

                    
if (sessionData != null)
                       sessionData.Expires 
= DateTime.Now.AddMinutes(pTimeout);
                }

                
finally
                
{
                    pHashtableLock.ReleaseReaderLock();
                }

            }

            
else
            
{
                
bool redirected, cookieAdded;

                sessionID 
= pSessionIDManager.CreateSessionID(context);
                pSessionIDManager.SaveSessionID(context, sessionID, 
out redirected, out cookieAdded);

                
if (redirected)
                    
return;
            }


            
if (sessionData == null)
            
{
                
// Identify the session as a new session state instance. Create a new SessionItem
                
// and add it to the local Hashtable.

                isNew 
= true;

                sessionData 
= new SessionItem();

                sessionData.Items 
= new SessionStateItemCollection();
                sessionData.StaticObjects 
= SessionStateUtility.GetSessionStaticObjects(context);
                sessionData.Expires 
= DateTime.Now.AddMinutes(pTimeout);

                
try
                
{
                    pHashtableLock.AcquireWriterLock(Int32.MaxValue);
                    pSessionItems[sessionID] 
= sessionData;
                }

                
finally
                
{
                    pHashtableLock.ReleaseWriterLock();
                }

            }


            
// Add the session data to the current HttpContext.
            SessionStateUtility.AddHttpSessionStateToContext(context,
                             
new HttpSessionStateContainer(sessionID,
                                                          sessionData.Items,
                                                          sessionData.StaticObjects,
                                                          pTimeout,
                                                          isNew,
                                                          pCookieMode,
                                                          SessionStateMode.Custom,
                                                          
false));

            
// Execute the Session_OnStart event for a new session.
            if (isNew && Start != null)
            
{
                Start(
this, EventArgs.Empty);
            }

        }


        
//
        
// Event for Session_OnStart event in the Global.asax file.
        
//

        
public event EventHandler Start;


        
//
        
// Event handler for HttpApplication.ReleaseRequestState
        
//

        
private void OnReleaseRequestState(object source, EventArgs args)
        
{
            HttpApplication app 
= (HttpApplication)source;
            HttpContext context 
= app.Context;
            
string sessionID;

            
// Read the session state from the context
            HttpSessionStateContainer stateProvider =
              (HttpSessionStateContainer)(SessionStateUtility.GetHttpSessionStateFromContext(context));

            
// If Session.Abandon() was called, remove the session data from the local Hashtable
            
// and execute the Session_OnEnd event from the Global.asax file.
            if (stateProvider.IsAbandoned)
            
{
                
try
                
{
                    pHashtableLock.AcquireWriterLock(Int32.MaxValue);

                    sessionID 
= pSessionIDManager.GetSessionID(context);
                    pSessionItems.Remove(sessionID);
                }

                
finally
                
{
                    pHashtableLock.ReleaseWriterLock();
                }


                SessionStateUtility.RaiseSessionEnd(stateProvider, 
this, EventArgs.Empty);
            }


            SessionStateUtility.RemoveHttpSessionStateFromContext(context);
        }



    }

}

还有下面的 configuration
<configuration>
<system.web>
<httpModules>
<remove name="Session" />
<add name="Session"
type="Samples.AspNet.SessionState.MySessionStateModule" />
</httpModules>
</system.web>
</configuration>


posted @ 2008-03-17 13:53  works guo  阅读(1684)  评论(1)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3