就算能运行,这样做会导致生成的Cookie的长度较大,因此容易导致浏览器不支持。最终我重写了以上代码(以及另一个序列化的代码):
{
try {
return (new JavaScriptSerializer()).Deserialize<IDictionary<string, object>>(
HttpUtility.UrlDecode(base64EncodedSerializedTempData));
}
catch {
return null;
}
}
public static string SerializeToBase64EncodedString(IDictionary<string, object> values)
{
if( values == null || values.Count == 0 )
return null;
return HttpUtility.UrlEncode(
(new JavaScriptSerializer()).Serialize(values));
}
上面的方法虽然解决了序列化结果过长的问题,但它也引入了新的问题:由于使用IDictionary类型,造成复杂类型在序列化时就丢失了它们的类型信息,因此,在反序列化时,就不能还原正原的类型。也正是因为此原因,这种方法将只适合保存简单基元类型数据。
现有的代码怎么办
本来,这篇博客到这里就没有了。是啊,批也批过了,解决办法也给了,还有什么好说的,不过,突然想到一个很现实的问题,要是有人问我:Fish,我的代码很多的地方在使用Session,如果按你前面的方法,虽可行,但是要改动的代码比较多,而且需要测试,还要重新部署,这个工作量太大了,有没有更好的办法?
是啊,这个还真是个现实的问题。怎么办呢?
针对这个问题,我也认真的思考过,也回忆过曾经如何使用Session,以及用Session都做过些什么。一般说来,用Session基本上也就是保存一些与用户相关的临时信息,而且不同的页面使用的Session冲突的可能性也是极小的,使用方式以 mode="InProc" 为主。其实也就是Cache,只是方便了与“当前用户”的关联而已。
于是针对这个前提,继续想:现在要克服的最大障碍是并发的锁定问题。至于这个问题嘛,我们可以参考一下前面MSND中的说明,就是因为GetItemExclusive这些方法搞出来的嘛。想到这里,似乎办法也就有了:我也来实现一个使用Cache的Provider,并且在具体实现时,故意不搞锁定,不就行了嘛。
最终,我提供二个Provider,它们都是去掉了锁定相关的操作,试了一下,并发问题不存了。但有个问题需要说明一下,ProcCacheSessionStateStore采用Cache保存Session的内容,与 mode="InProc" 类似, CookieSessionStateStore则采用Cookie保存Session对象,但它有个限制,只适合保存简单基元类型数据(且不包含敏感信息),原因与CookieTempDataProvider一样。所以,请根据您的使用场景来选择合适的Provider
以下是使用方法:很简单,只要在web.config中加一段以下配置就好了:
<providers>
<add name="ProcCacheSessionStateStore" type="Fish.SampleCode.ProcCacheSessionStateStore"/>
<add name="CookieSessionStateStore" type="Fish.SampleCode.CookieSessionStateStore"/>
</providers>
</sessionState>
好了,这次不用改代码了,在部署环境中,也只需要修改了一下配置就完事了。
警告:我提供的这二个Provider只是做了简单的测试,并没经过实际的项目检验,如果您需要使用,请自行测试它的可用性。