自定义会话状态存储提供程序

自定义会话状态存储提供程序

 此版本程序只是说明  自定义会话  可以放在不同的地方, 可以改造成 把会话分布式存储 等。

一、Web.config 

<sessionState mode="Custom" customProvider="JinshuaiCustomSessionStateProvider">
  <providers>
       <add name="JinshuaiCustomSessionStateProvider" type="SessionStateWebApplication.Sessions.JinshuaiCustomSessionStateProvider" connectionStringName="DefaultConnection" />
</providers>
</sessionState>

二、 JinshuaiCustomSessionStateProvider 提供程序

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Collections.Specialized;
  4 using System.IO;
  5 using System.Linq;
  6 using System.Web;
  7 using System.Web.SessionState;
  8
  9 namespace SessionStateWebApplication.Sessions
 10 {
 11     public class JinshuaiCustomSessionStateProvider : SessionStateStoreProviderBase
 12     {
 13         private static Dictionary<string, CustomSession> _dic = new Dictionary<string, CustomSession>();
 14
 15         public string AppName
 16         {
 17             get { return "jinshuaiTest"; }
 18         }
 19
 20         public int TimeOut { get; set; }
 21
 22
 23         public override void Initialize(string name, NameValueCollection config)
 24         {
 25             TimeOut = 20;
 26
 27             base.Initialize(name, config);
 28         }
 29
 30
 31         public override SessionStateStoreData CreateNewStoreData(HttpContext context, int timeout)
 32         {
 33             TimeOut = timeout;
 34             return new SessionStateStoreData(new SessionStateItemCollection(), SessionStateUtility.GetSessionStaticObjects(context), timeout);
 35         }
 36
 37         public override void CreateUninitializedItem(HttpContext context, string id, int timeout)
 38         {
 39             var newSession = new CustomSession
 40             {
 41                 SessionId = id,
 42                 LockDate = DateTime.Now,
 43                 Locked = false,
 44                 LockId = 0,
 45                 SessionItems = string.Empty,
 46                 Timeout = timeout,
 47                 Expires = DateTime.Now.AddMinutes(timeout),
 48                 Created = DateTime.Now,
 49                 ApplicationName = AppName
 50             };
 51             _dic.Add(id, newSession);
 52
 53         }
 54
 55         public override void Dispose()
 56         {
 57
 58         }
 59
 60         public override void EndRequest(HttpContext context)
 61         {
 62
 63         }
 64
 65         public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions)
 66         {
 67
 68             return GetItemByExclusive(false, context, id, out locked, out lockAge, out lockId, out actions);
 69         }
 70
 71         public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions)
 72         {
 73             return GetItemByExclusive(true, context, id, out locked, out lockAge, out lockId, out actions);
 74         }
 75
 76
 77
 78         public SessionStateStoreData GetItemByExclusive(bool isExclusive, HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions)
 79         {
 80             locked = false;
 81             lockAge = TimeSpan.Zero;
 82             lockId = null;
 83             actions = SessionStateActions.None;
 84
 85             CustomSession tempSession = null;
 86
 87
 88             if (_dic.ContainsKey(id))
 89             {
 90                 tempSession = _dic[id];
 91             }
 92             else
 93             {
 94                 //没找到相应的会话
 95                 return null;
 96             }
 97
 98             //如果过期
 99             if (tempSession.Expires <= DateTime.Now)
100             {
101                 _dic.Remove(id);
102                 return null;
103             }
104
105
106             //是否独占访问
107             if (isExclusive)
108             {
109                 if (tempSession.Locked)
110                 {
111                     locked = true;
112                     lockAge = (DateTime.Now - tempSession.LockDate);
113                     lockId = tempSession.LockId;
114                     actions = (SessionStateActions)tempSession.Flags;
115                     return null;
116                 }
117             }
118
119             return Deserialize(context, tempSession.SessionItems, tempSession.Timeout);
120
121         }
122
123
124
125
126
127         public override void InitializeRequest(HttpContext context)
128         {
129
130         }
131
132         public override void ReleaseItemExclusive(HttpContext context, string id, object lockId)
133         {
134             if (!_dic.ContainsKey(id)) return;
135
136             var tempSession = _dic[id];
137             tempSession.LockId = (int)(lockId??0);
138             tempSession.Locked = false;
139             tempSession.Expires = DateTime.Now.AddMinutes(tempSession.Timeout);
140         }
141
142         public override void RemoveItem(HttpContext context, string id, object lockId, SessionStateStoreData item)
143         {
144
145             if (!_dic.ContainsKey(id)) return;
146
147             _dic.Remove(id);
148
149         }
150
151         public override void ResetItemTimeout(HttpContext context, string id)
152         {
153
154             if (!_dic.ContainsKey(id)) return;
155
156             var tempSession = _dic[id];
157             tempSession.Expires = DateTime.Now.AddMinutes(tempSession.Timeout);
158
159         }
160
161         public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem)
162         {
163
164             string sessItems = Serialize((SessionStateItemCollection)item.Items);
165
166             if (newItem)
167             {
168                 var newSession = new CustomSession
169                 {
170                     SessionId = id,
171                     LockDate = DateTime.Now,
172                     Locked = false,
173                     LockId = 0,
174                     SessionItems = sessItems,
175                     Timeout = TimeOut,
176                     Expires = DateTime.Now.AddMinutes(TimeOut),
177                     Created = DateTime.Now,
178                     ApplicationName = AppName
179                 };
180                 _dic.Add(id, newSession);
181
182             }
183             else
184             {
185
186                 if (!_dic.ContainsKey(id))
187                 {
188                     var newSession = new CustomSession
189                     {
190                         SessionId = id,
191                         LockDate = DateTime.Now,
192                         Locked = false,
193                         LockId = 0,
194                         SessionItems = sessItems,
195                         Timeout = TimeOut,
196                         Expires = DateTime.Now.AddMinutes(TimeOut),
197                         Created = DateTime.Now,
198                         ApplicationName = AppName
199                     };
200                     _dic.Add(id, newSession);
201
202                 }
203
204                 var tempSession = _dic[id];
205                 tempSession.Expires = DateTime.Now.AddMinutes(TimeOut);
206                 tempSession.SessionItems = sessItems;
207                 tempSession.LockId =(int)(lockId??0);
208                 tempSession.LockDate = DateTime.Now;
209
210             }
211
212
213         }
214
215         public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback)
216         {
217
218             return false;
219         }
220
221
222
223
224
225
226
227         private string Serialize(SessionStateItemCollection items)
228         {
229             MemoryStream ms = new MemoryStream();
230             BinaryWriter writer = new BinaryWriter(ms);
231
232             if (items != null)
233                 items.Serialize(writer);
234
235             writer.Close();
236
237             return Convert.ToBase64String(ms.ToArray());
238         }
239
240         private SessionStateStoreData Deserialize(HttpContext context,
241           string serializedItems, int timeout)
242         {
243             MemoryStream ms =
244               new MemoryStream(Convert.FromBase64String(serializedItems));
245
246             SessionStateItemCollection sessionItems =
247               new SessionStateItemCollection();
248
249             if (ms.Length > 0)
250             {
251                 BinaryReader reader = new BinaryReader(ms);
252                 sessionItems = SessionStateItemCollection.Deserialize(reader);
253             }
254
255             return new SessionStateStoreData(sessionItems,
256               SessionStateUtility.GetSessionStaticObjects(context),
257               timeout);
258         }
259
260
261     }
262
263
264     [Serializable]
265     public class CustomSession
266     {
267
268         public string SessionId
269         {
270             get;
271             set;
272         }
273
274         public string ApplicationName
275         {
276             get;
277             set;
278         }
279         public DateTime Created
280         {
281             get;
282             set;
283         }
284         public DateTime Expires
285         {
286             get;
287             set;
288         }
289         public DateTime LockDate
290         {
291             get;
292             set;
293         }
294         public int LockId
295         {
296             get;
297             set;
298         }
299         public int Timeout
300         {
301             get;
302             set;
303         }
304         public bool Locked
305         {
306             get;
307             set;
308         }
309         public string SessionItems
310         {
311             get;
312             set;
313         }
314         public int Flags
315         {
316             get;
317             set;
318         }
319
320
321     }
322 }

三 、 使用

protected void Button1_Click(object sender, EventArgs e)
{

Session["jinshuai"] = "你好:" + DateTime.Now.ToString();

}

protected void Button2_Click(object sender, EventArgs e)
{
    this.Label1.Text = (Session["jinshuai"]?? "没找到值").ToString();
}

附:

https://msdn.microsoft.com/zh-cn/library/system.web.sessionstate.sessionstatestoreproviderbase(VS.80).aspx

ASP.NET 会话状态使用会话状态存储提供程序将会话数据写入数据存储区,并从中读取会话数据。会话状态存储提供程序是一个类,它继承SessionStateStoreProviderBase 抽象类并使用特定于数据存储区的实现重写其成员。在处理 ASP.NET 页的过程中,SessionStateModule 类会调用会话状态存储提供程序以便与数据存储区进行通信,从而存储和检索会话变量和相关的会话信息,如超时值。

对于每个 SessionID 属性,每个 ASP.NET 应用程序内的会话数据都将单独存储。ASP.NET 应用程序不共享会话数据。

如本主题中的示例所示,可以为 ASP.NET 应用程序指定一个自定义 SessionStateStoreProviderBase 实现,方法是将 sessionState 配置元素的mode 属性设置为 Custom,并将 customProvider 属性设置为自定义提供程序的名称。

锁定会话存储区数据

由于 ASP.NET 应用程序是多线程的,支持对并发请求的响应,因此并发请求可能会尝试访问同一会话信息。考虑下面一种情况,其中一个框架集中的多个框架都访问同一应用程序。框架集内每个框架的单独请求可能会在 Web 服务器中的不同线程上并发执行。如果每个框架源代码的 ASP.NET 页都访问会话状态变量,则可能会出现多个线程并发访问会话存储区。

为避免在会话存储区发生数据冲突以及意外的会话状态行为,SessionStateModule 和 SessionStateStoreProviderBase 类包含了锁定功能,可以在 ASP.NET 页执行期间,以独占方式为特定的会话锁定会话存储项。请注意,即使 EnableSessionState 属性标记为 ReadOnly,同一应用程序中的其他 ASP.NET 页也可以向会话存储区写入,因此对于存储区中只读会话数据的请求可能最终仍将等待锁定数据的释放。

在调用 GetItemExclusive 方法的过程中,在请求开始时就会对会话存储区数据设置锁定。请求完成后,在调用 SetAndReleaseItemExclusive 方法期间释放锁定。

如果 SessionStateModule 对象在调用 GetItemExclusive 或 GetItem 方法期间遇到锁定的会话数据,它将以半秒为间隔重新请求会话数据,直到锁定被释放或者会话数据的锁定时间超过 ExecutionTimeout 属性的值。如果超过了执行超时时间,SessionStateModule 对象将调用ReleaseItemExclusive 方法以释放会话存储区数据并随即请求会话存储区数据。

在针对当前的响应调用 SetAndReleaseItemExclusive 方法前,由于锁定的会话存储区数据可能已经通过调用单独线程上的ReleaseItemExclusive 方法而释放,因此可能会尝试设置和释放已被另一会话释放并修改的会话状态存储区数据。为了避免这种情况,GetItem 和GetItemExclusive 方法返回一个锁定标识符。此锁定标识符必须包含在每个请求中以修改锁定的会话存储区数据。仅当数据存储区中的锁定标识符与 SessionStateModule 提供的锁定标识符匹配时,才能修改会话存储区数据。

删除过期的会话存储区数据

当针对特定的会话调用 Abandon 方法时,将使用 RemoveItem 方法从数据存储区中删除该会话的数据;否则,数据将保留在会话数据存储区供会话的以后请求使用。由 SessionStateStoreProviderBase 实现来删除过期的会话数据。

时间: 2024-12-20 01:10:07

自定义会话状态存储提供程序的相关文章

自定义ASP.NET Identity(三)- 实现自定义MySQL ASP.NET Identity存储提供程序

ASP.NET Identity是一个可扩展的系统,你可以创建属于你自己的存储提供程序并且将它集成到你的应用中,而不需要重构你的应用.本章将介绍如何创建一个ASP.NET Identity的MySQL存储提供程序.关于如何创建自定义存储提供程序的概述请查看自定义ASP.NET Identity(一)- 自定义ASP.NET Identity存储提供程序.要完成这个指南,你必须安装Visual Studio 2013 Update 2. 这个指南将包含如下内容: 怎样在Azure上创建MySQL数

Azure Redis 缓存的 ASP.NET 会话状态提供程序

Azure Redis Cache 提供了一个会话状态提供程序,你可以使用其在缓存中(而不是内存中或在 SQL Server 数据库中)存储会话状态.要使用缓存会话状态提供程序,先首先配置缓存,然后使用 Redis 缓存会话状态 NuGet 包配置用于缓存的 ASP.NET 应用程序. 在缓存中存储 ASP.NET 会话状态 若要使用 Redis Cache Session State NuGet 程序包配置 Visual Studio 中的应用程序,请右键单击解决方案资源管理器中的项目,然后选

基于 cookie 的 TempData 提供程序

原文链接http://brockallen.com/2012/06/11/cookie-based-tempdata-provider/ TempData是一个不错的功能,在 MVC 中,如果我没有记错,启发Flash 模块从滑轨上的红宝石.它基本上是保持某种状态跨重定向方法. 在 Rails 的默认实现使用 cookie 来存储数据,这使得这相当轻量的机制,将数据从一个请求传递到下一个.不幸的是 TempData 在 MVC 的默认实现使用会话状态作为后备存储使得它不太理想.这就是为什么我想要

联系人提供程序

联系人提供程序是一个强大而又灵活的 Android 组件,用于管理设备上有关联系人数据的中央存储库. 联系人提供程序是您在设备的联系人应用中看到的数据源,您也可以在自己的应用中访问其数据,并可在设备与在线服务之间传送数据. 提供程序储存有多种数据源,由于它会试图为每个联系人管理尽可能多的数据,因此造成其组织结构非常复杂. 为此,该提供程序的 API 包含丰富的协定类和接口,为数据检索和修改提供便利. 本指南介绍下列内容: 提供程序基本结构 如何从提供程序检索数据 如何修改提供程序中的数据 如何编

解决“无法连接到WMI提供程序,您没有权限或者该服务器无法访问。“

最近在学习PowerDesigner,在创建PDM模型的时候,遇到了一点儿小问题,本以为要重装SQLServer,百度了一下,问题就轻松解决了.问题的背景是这样的,在创建数据源的时候,总是测试连接不成功,我就想打开配置管理器查看一下是不是出了什么问题.结果,就出现了下面的弹窗:↓↓↓ 出错提示: 启动SQL Server 2005 配置管理器时,出现以下提示错误 无法连接到WMI提供程序.您没有权限或者该服务器无法访问...... Invalid class [0x80041010] 出错原因:

没有安装提供程序“System.Data.SqlServerCe.3.5”的解决方法

在Windows 8.1系统下运行带数据库功能的应用,报错并提示:"System.InvalidOperationException"类型的未经处理的异常在 System.Data.Linq.dll 中发生其他信息: 无法打开"Bible.sdf".没有安装提供程序"System.Data.SqlServerCe.3.5".1.没有安装Microsoft SQL Server Compact 3.5的先下载并安装:http://www.micro

如何 ︰ 执行批量更新和插入使用.NET 提供程序在 C#.NET OpenXML

https://support.microsoft.com/zh-cn/kb/315968 如何 ︰ 执行批量更新和插入使用.NET 提供程序在 C#.NET OpenXML Email Print 注意:这篇文章是由无人工介入的微软自动的机器翻译软件翻译完成.微软很高兴能同时提供给您由人工翻译的和由机器翻译的文章, 以使您能使用您的语言访问所有的知识库文章.然而由机器翻译的文章并不总是完美的.它可能存在词汇,语法或文法的问题,就像是一个外国人在说中文时总是可能犯这样的错误.虽然我们经常升级

此成员资格提供程序没有被配置为支持密码恢复。

MembershipUser mu = Membership.GetUser(txtUserName.Text.Trim()); txtOldPassword.Text = mu.GetPassword(); 为何以上代码会报错:此成员资格提供程序没有被配置为支持密码恢复? 查找了一下,出现以上报错,是因为密码存储不是以明文方式存入数据库的,所以无法找到密码. 此成员资格提供程序没有被配置为支持密码恢复.

【WP8】自定义配置存储类

之前在WP7升级到WP8的时候遇到配置不兼容的问题 情景:之前只有一个WP7版本,现在需要发布WP8版本,让用户可以从原来的WP7版本升级到WP8版本 一般情况下从WP7升级到WP8没什么问题 但是在项目中升级到WP8的时候,原先在WP7下保存在IsolatedStorageSettings的数据都不出来,经过调试发现 1.IsolatedStorageSettings存放数据的隔离存储控件的"__ApplicationSettings"文件中,存放的格式如下 {"test&