2012-08-29 106 views
3

我们的ASP.NET应用程序在同一会话上并行发送多个Ajax请求。在其中一些请求中,我们还读取/写入HttpSessionState。我想要的是所有并发请求都是由于性能原因而并行执行的。我得到的是他们被ASP.NET序列化。我尝试过配置enableSessionState="ReadOnly",但这打破了我们的表单身份验证。ASP.NET会话状态提供程序

有没有办法在一个会话中同时获得会话状态和并发?我需要使用自定义的SessionState还是Provider?这里的任何样品?

PS我不担心访问SessionState时的线程安全性 - 我可以通过编程来实现。

回答

2

从MSDN(link):

但是,如果两个并发请求为同一会议上提出的(通过使用相同的SessionID值),第一个请求获取会话信息的独占访问。第二个请求仅在第一个请求完成后执行。

因此,至少对于那些需要对会话进行写访问的AJAX调用,您对运行默认提供程序是不好的。

不确定您是否可以使用自定义提供程序解决此问题。

可以实现不通过在HttpModule阻断ASP.NET_SessionId饼干需要访问会话的AJAX调用parallell执行。看到我的answer到这个question

编辑:为了使这个答案更加自力更生,我添加了HttpModule,并略加修改了一下讨论(进一步下跌)。下面是您可以使用,以防止序列化的Ajax的会话状态的模块代码调用:

using System; 
using System.Web; 

namespace TestModule 
{ 
    public class TestPreventCookie : IHttpModule 
    { 
     public void Dispose() 
     { 
     } 
     public void Init(HttpApplication application) 
     { 
      application.BeginRequest += 
       (new EventHandler(this.Application_BeginRequest)); 
      application.PostAcquireRequestState += 
       (new EventHandler(this.Application_PostAcquireRequestState)); 

     } 
     private void Application_BeginRequest(Object source, EventArgs e) 
     { 
      //prevent session cookie from reaching the service 
      HttpApplication application = (HttpApplication)source; 
      HttpContext context = application.Context; 
      if (BlockCookie(context)) 
      { 
       context.Request.Cookies.Remove("ASP.NET_SessionId"); 
      } 
     } 
     private void Application_PostAcquireRequestState(Object source, EventArgs e) 
     { 
      HttpApplication application = (HttpApplication)source; 
      HttpContext context = application.Context; 
      if (BlockCookie(context)) 
      { 
       var s = context.Session; 
       if (s != null) 
        s.Abandon(); 
      } 
     } 
     private bool BlockCookie(HttpContext context) 
     { 
      // put code here that determines if the session cookie should be blocked 
      // this could be based on the path of the current request for instance 
      // only block the cookie when you *know* that access to the Session is not needed 
     } 
    } 
} 

此模块背后的想法是,使用基于项目需求的一些标准,我们从当前的情况下删除ASP.NET_SessionId饼干(请注意,我们不会在客户端上过期)。

这意味着进一步在请求管道中,服务器将创建一个新的会话。为了防止这个新创建的会话破坏客户端上现有的ASP.NET_SessionId cookie,我们在创建后立即放弃它。

最终的结果是,模块“拦截”的每个请求都会执行,就好像它没有会话一样。