[转]ASP.NET HttpModule for handling session end with StateServer

简介:

from:http://www.codeproject.com/KB/aspnet/SessionEndStatePersister.aspx

 

Introduction

The Session_End event is a useful event which an be handled in Global.asax to perform any actions when a session ends, such as logging an activity to the database, cleaning up temporary session files, etc.

However, when using any kind of state management other than InProc (such as StateServer or SqlStateServer), the ASP.NET web application does not fire the Session_End event, and any code in this method will not be executed.

Background

Some browsing around returned a couple of good articles. The article Page tracking in ASP.NET offers a similar solution, though is geared around page tracking whereas my requirement was simply to find an alternative to the Session_End event that would work with the ASP.NET StateServer.

There's another excellent article called Preventing Multiple Logins in ASP.NET This is where I got the idea of using the application cache with a sliding expiry to trigger an event when the session ends.

How it works

The SessionEndModule class hooks into the PreRequestHandlerExecute event and inserts/replaces an item in the application cache, with a sliding expiry equal to the session expiry, and a callback method to be called when the item is removed from the application cache. The key of the cache item is the SessionId, and the value is the value of the item in the session with the key set as the SessionObjectKey.

When the item expires and the callback method is called. The key, value and reason of the expired item is passed to this callback method. The key is the SessionId, the value is the value copied from the session, and the reason is why the item was removed from the cache (was it removed, expired, underused, or it's dependency changed).

The callback method then checks that the item was removed as a result of it expiring, wraps the values into a SessionEndEventArgs class (which exposes SessionId and SessionObject properties), and fires the SessionEnd event.

Using the code

The code consists of a HttpModule called SessionEndModule, which needs to be included in the project via the web.config file. It exposes a static property named SessionObjectKey and a static event named SessionEnd which will be fired when a session ends. The value of the SessionObjectKey will be returned in the event arguments for the SessionEnd event.

First lets set up web.config

 Collapse  Copy Code
<httpModules>
<add name="SessionEndModule" type="SessionTestWebApp.Components.SessionEndModule, SessionTestWebApp"/>
</httpModules>
<!-- Use the state server (rather than InProc), and set the timeout to 1 minute for easier testing-->
<sessionState mode="StateServer" stateConnectionString="tcpip=127.0.0.1:42424" timeout="1" cookieless="false"/>

Then we need set up Global.asax

 Collapse  Copy Code
protected void Application_Start(object sender, EventArgs e)
{
// In our sample application, we want to use the value of Session["UserEmail"] when our session ends
SessionEndModule.SessionObjectKey = "UserEmail";
// Wire up the static 'SessionEnd' event handler
SessionEndModule.SessionEnd += new SessionEndEventHandler(SessionTimoutModule_SessionEnd);
}

Then we need to create our event handler method for the SessionEnd event:

 Collapse  Copy Code
private static void SessionTimoutModule_SessionEnd(object sender, SessionEndedEventArgs e)
{
Debug.WriteLine("SessionTimoutModule_SessionEnd : SessionId : " + e.SessionId);
// This will be the value in the session for the key specified in Application_Start
// In this demonstration, we've set this to 'UserEmail', so it will be the value of Session["UserEmail"]
object sessionObject = e.SessionObject;
string val = (sessionObject == null) ? "[null]" : sessionObject.ToString();
Debug.WriteLine("Returned value: " + val);
}

In this demo, lets also wire up the Session_Start and put some test data in the session

 Collapse  Copy Code
protected void Session_Start(object sender, EventArgs e)
{
Debug.WriteLine("Session started: " + Session.SessionID);
Session["UserId"] = new Random().Next(1, 100);
Session["UserEmail"] = new Random().Next(100, 1000).ToString() + "@domain.com";
Debug.WriteLine("UserId: " + Session["UserId"].ToString() + ", UserEmail: " +
Session["UserEmail"].ToString());
}

Testing the code

Start this project in debug mode and keep an eye on the output window. When the session starts, the session contents will populated with a random UserId and UserEmail. The session will end after approximately 1 minute, and fire the SessionEnd event, which will execute the SessionTimoutModule_SessionEnd method and print the SessionId of the session that ended and the UserEmail it contained.

Returning more than one session value

The HttpModule.SessionEnd event only supports returning the value of a single session variable. If you need to return more than one value, the easiest way is to create a serializable class, with properties for all your values, and store that in the session instead.

For example:

 Collapse  Copy Code
[Serializable]
public class SessionInfo
{
public string UserId;
public string UserName;
public string UserEmail;
}
SessionInfo sessionInfo = new SessionInfo();
sessionInfo.UserId = 10;
sessionInfo.UserName = "Bob Jones";
sessionInfo.UserEmail = "bobjones@company.com";
Session["SessionInfo"] = sessionInfo;

In Global.asax, you would then set the SessionObjectKey to 'SessionInfo':

 Collapse  Copy Code
SessionEndModule.SessionObjectKey = "SessionInfo";

You can then access this in the SessionEnd event:

 Collapse  Copy Code
private static void SessionTimoutModule_SessionEnd(object sender, SessionEndedEventArgs e)
{
Debug.WriteLine("SessionTimoutModule_SessionEnd : SessionId : " + e.SessionId);
SessionInfo sessionInfo = e.SessionObject as SessionInfo;
if (sessionObject == null)
{
Debug.WriteLine("Returned value is null");
}
else
{
Debug.WriteLine("Returned values - UserId: " + sessionInfo.UserId + ", UserName: " +
sessionInfo.UserName + ", UserEmail: " + sessionInfo.UserEmail);
}
}

Known limitations

As the module hooks into the PreRequestHandler event, the value of the SessionObjectKey stored in the application cache before the page executes. This means that if you change the session variable being returned by the module in the SessionEnd event (or the SessionInfo object) on a page, and then the session times out, the SessionEnd event will contain the old value. It's possible to change this to use the PostRequestHandler event, though I've experienced some strange behaviour with this, especially when using Response.TransmitFile.

This code also won't work on scenerarios where you are using a server farm. In the article 'Preventing Multiple Logins in ASP.NET', Peter Bromberg discusses this problem in more depth and offers some ideas for working around this.

History

Version 1.0 - 02 November 2007

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Munsifali Rashid


I'm a freelance web developer with 7+ years experience developing solutions using Microsoft technologies.

Originally from London (UK) but now living in Orlando, FL, I'm currently working on various projects for numerous digital agencies across the globe, providing them with development and consulting services.

My website and blog are at http://www.mlogix-inc.com/
Occupation: Web Developer
Company: mLogix Inc
Location: United States United States
欢迎加群互相学习,共同进步。QQ群:iOS: 58099570 | Android: 572064792 | Nodejs:329118122 做人要厚道,转载请注明出处!



















本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/sunshine-anycall/archive/2009/03/10/1407498.html ,如需转载请自行联系原作者



相关文章
|
存储 开发框架 NoSQL
ASP.NET WEB——项目中Cookie与Session的用法
ASP.NET WEB——项目中Cookie与Session的用法
144 0
|
开发框架 .NET
ASP.NET Core NET7 增加session的方法
ASP.NET Core NET7 增加session的方法
152 0
|
存储 开发框架 .NET
ASP.NET Session的认识和解释
ASP.NET Session的认识和解释
122 1
|
开发框架 JavaScript .NET
Asp.Net Core中Session使用
Asp.Net Core中Session使用
245 0
|
存储 开发框架 .NET
ASP.NET中利用Application和Session统计在线人数、历史访问量
先来简单说一下ASP.NET中的Application和Session 下图是我们非常熟悉的Web应用程序的结构:
ASP.NET中利用Application和Session统计在线人数、历史访问量
|
缓存 前端开发 API
.Net WebApi中使用Session使用
.Net WebApi中使用Session使用
375 0
|
存储 中间件 .NET
ASP.NET Core Web Api之JWT VS Session VS Cookie(二)
ASP.NET Core Web Api之JWT VS Session VS Cookie(二)前言本文我们来探讨下JWT VS Session的问题,这个问题本没有过多的去思考,看到评论讨论太激烈,就花了一点时间去研究和总结,顺便说一句,这就是写博客的好处,一篇博客写出有的可能是经验积累,有的可能是学习分享,但都逃不过看到文章的你有更多或更好的想法,往返交流自身能收获更多,何乐而不为呢?希望本文能解惑或者能得到更多的交流。
2984 0
|
10月前
|
监控 前端开发 API
一款基于 .NET MVC 框架开发、功能全面的MES系统
一款基于 .NET MVC 框架开发、功能全面的MES系统
237 5
|
开发框架 前端开发 JavaScript
ASP.NET MVC 教程
ASP.NET 是一个使用 HTML、CSS、JavaScript 和服务器脚本创建网页和网站的开发框架。
200 7