【问题标题】:ASP.NET Session State ProvidersASP.NET 会话状态提供程序
【发布时间】:2012-08-23 23:07:22
【问题描述】:
我们的 ASP.NET 应用在同一个会话中并行发送多个 Ajax 请求。在其中一些请求期间,我们还会读/写HttpSessionState。我想要的是所有并发请求出于性能原因并行执行。我得到的是它们由 ASP.NET 序列化。我尝试配置enableSessionState="ReadOnly",但这会破坏我们的表单身份验证。
有没有办法在一个会话中同时获得会话状态和并发?我需要使用自定义SessionState 或Provider 吗?有这样的样本吗?
PS 在访问 SessionState 时,我并不担心线程安全 - 我可以通过编程方式做到这一点。
【问题讨论】:
标签:
asp.net
ajax
session
session-state
【解决方案1】:
来自 MSDN (link):
但是,如果对同一个会话发出两个并发请求(通过使用相同的 SessionID 值),则第一个请求将获得对会话信息的独占访问权。第二个请求只有在第一个请求完成后才会执行。
因此,至少对于那些需要对 Session 进行写访问的 AJAX 调用,您对默认提供程序不走运。
不确定您是否可以使用自定义提供程序解决此问题。
您可以通过阻止HttpModule 中的ASP.NET_SessionId cookie 来实现那些不需要访问会话的AJAX 调用的并行执行。看到我的answer 到这个question。
编辑:为了使这个答案更加独立,我添加了HttpModule 的略微修改版本和一些讨论(进一步向下)。下面是可用于防止 Session 状态序列化 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 cookie(注意,我们不会在客户端上使其过期)。
这意味着在请求管道中,服务器将创建一个新会话。为了防止这个新创建的会话破坏客户端现有的ASP.NET_SessionId cookie,我们在它创建后立即放弃它。
最终结果是每个被模块“拦截”的请求都会像没有会话一样执行。