• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

ASP.NET:在MVC中如何使用Session?

原作者: [db:作者] 来自: [db:来源] 收藏 邀请
2011年12月16日11:30 来源:博客 作者:Fish Li 编辑:苏巧红 我要评论(0)
标签: ASP.NET , .NET , web开发

  【IT168技术】本文将介绍Asp.net MVC 中的Session及基于现有代码的处理方法。

  相关阅读:

  ASP.NET:Session的缺点总结及解决方法

  ASP.NET:Session对并发访问的影响

  ASP.NET:session的来龙去脉解析

  Asp.net平台作为底层的框架,它提供了HttpContext.Session这个成员属性让我们可以方便地使用Session,但是在MVC中,Controller抽象类为也提供了这样一个属性,我们只要访问它就可以了(支持更好的测试性)。

   回想一下,前面我们看到SessionStateModule是根据当前HttpHandler来决定是不是启用Session。但是现在 Controller和Page是分开的, Controller又是如何使用Session的呢?要回答这个问题就要扯到路由了,简单地说:现在在MVC处理请求的时候,当前 HttpHandler是 MvcHandler类的实例,它有如下定义:

publicclass MvcHandler : IHttpAsyncHandler, IHttpHandler, IRequiresSessionState {

    因此,在Controller.Session中,它是访问的HttpContext.Session,而MvcHandler实现了 IRequiresSessionState接口,所以,访问HttpContext.Session就可以获取到Session 。注意哦,我上面的代码取自MVC 2.0,从类型实现的接口可以看出,Session将一直有效,不能关闭,而且属于影响并发的那种模式。所以,此时你只能从web.config中全局关 闭它。

  说明,在MVC 3.0 和Asp.net 4.0中,才可以支持Controller订制Session的访问性。

  在这种使用方式下,如果您不想继续使用Session,可以使用上面我列出的替代方法。

  在MVC中,还有一个地方也在使用Session,那就是Controller.TempData这个成员属性。通常我们可能会这样使用它:

TempData["mydata"] ="aaaaaaaaaa"; //or other object
return RedirectToAction("Index");

    在这种地方,这些保存到TempData的数据其实也是存放在Session中的。你可以从web.config中关闭Session,你就能看到异常 了。对于这种使用方法,你仍然可以前面的替代方法,但是,还有另一种方法也能做为替代Session的方法。我们看一下Controller的一段代码:

protected virtual ITempDataProvider CreateTempDataProvider() {
    
returnnew SessionStateTempDataProvider();
}

    TempData就是通过这种Provider的方式来支持其它的保存途径。而且在MvcFutures中,还有一个 CookieTempDataProvider类可供使用。使用也很简单,获取MVC源码,编译项目MvcFutures,然后引用它,重写以上虚方法就 可以了:

protected override ITempDataProvider CreateTempDataProvider()
{
    
returnnew Microsoft.Web.Mvc.CookieTempDataProvider(this.HttpContext);
}

   注意哦,这里有2个陷阱:MVC 2的MvcFutures的CookieTempDataProvider并不能正常工作。至于我在尝试时,发现它是这样写的(注释部分是我加的):

publicstatic IDictionary<string, object> DeserializeTempData(string base64EncodedSerializedTempData)
{
    
byte[] bytes = Convert.FromBase64String(base64EncodedSerializedTempData);
    var memStream
=new MemoryStream(bytes);
    var binFormatter
=new BinaryFormatter();
    
return binFormatter.Deserialize(memStream, null) as TempDataDictionary;    // 这里会导致一直返回null
    
//return binFormatter.Deserialize(memStream, null) as IDictionary<string, object>;    // 这样写才对嘛。
}
 
就算能运行,这样做会导致生成的Cookie的长度较大,因此容易导致浏览器不支持。最终我重写了以上代码(以及另一个序列化的代码):
publicstatic IDictionary<string, object> DeserializeTempData(string base64EncodedSerializedTempData)
{
    
try {
        
return (new JavaScriptSerializer()).Deserialize<IDictionary<string, object>>(
                HttpUtility.UrlDecode(base64EncodedSerializedTempData));
    }
    
catch {
        
return null;
    }
}

publicstaticstring 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中加一段以下配置就好了:

<sessionState mode="Custom" customProvider="CookieSessionStateStore">
    
<providers>
        
<add name="ProcCacheSessionStateStore" type="Fish.SampleCode.ProcCacheSessionStateStore"/>
        
<add name="CookieSessionStateStore" type="Fish.SampleCode.CookieSessionStateStore"/>
    
</providers>
</sessionState>

   好了,这次不用改代码了,在部署环境中,也只需要修改了一下配置就完事了。

  警告:我提供的这二个Provider只是做了简单的测试,并没经过实际的项目检验,如果您需要使用,请自行测试它的可用性。


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
MVC数组模型绑定ASP.NETMVC数组模型绑定发布时间:2022-07-10
下一篇:
ASP.NET之异步处理一(Session处理)发布时间:2022-07-10
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap