使用SessionStateBehavior.ReadOnly写入会话变量

时间:2017-05-05 21:19:06

标签: c# asp.net asp.net-mvc http session

在我的ASP.NET MVC 5应用程序中,我对控制器内部需要读取存储在会话中的值的方法执行article.tex请求。为避免会话状态锁定问题,我已在类级别将GET设置为SessionStateBehavior

ReadOnly

然而,偶尔,我需要将 [SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)] public class TestController: Controller { var test = Session["KEY"]; ... 变量覆盖到同一方法中的其他内容。 ASP.NET MVC不允许我将Session设置为SessionStateBehavior来执行此操作。我无法将其设置为ReadOnly,因为我再次遇到会话状态锁定问题,阻止了并发的AJAX请求。

对此有什么好处?

编辑:我们正在使用SQL服务器进行会话状态管理。

5 个答案:

答案 0 :(得分:4)

如果您的目标是.NET Framework 4.6.2并且您使用的是SQL Server,则可以利用新的async SessionState module异步访问会话存储提供程序。

下载并安装SessionStateModule和SqlSessionState NuGet包。

还要考虑SQLServer mode在SQL Server数据库中存储会话状态。

注意(来自评论)

虽然ASP.NET Core中的会话是非锁定的,但根据msdn blog,只有SqlSessionStateProviderAsync的下一版本才会引入此功能。

替代提供者

另一个不同的选择是使用StackExchange.Redis:例如对于Azure App Service中的Web应用程序,请按照configuration steps进行操作。 更一般地,在Redis服务器或服务器中,RedisSessionProvider永远不会锁定会话

答案 1 :(得分:2)

因为您正在使用SQL Server会话后端,所以我认为您可以通过手动与会话数据库交互并将其弯曲到您的意愿来实现您想要的目标。

熟悉workings of a session provider,尤其是SqlSessionStateStore课程。在幕后,它所做的只是(de)序列化你的数据并在会话状态数据库中调用存储过程(具体来说,请查看SetAndReleaseItemExclusive)。

如果您可以弄清楚如何构建SessionStateStoreData对象,或者更具体地说是构建它的ISessionStateItemCollection,那么您可以通过HttpContext加上任何会话来访问会话集合。您想要进行更改,然后可以使用反射来调用内部静态SessionStateUtility.SerializeStoreData方法。之后,调用正确的存储过程(基于更新的会话的大小)应该是微不足道的。

答案 2 :(得分:2)

您可以为每个请求动态设置会话状态行为。根据某些条件,您可以切换到SessionStateBehavior.Required,在任何其他情况下,只需使用默认行为。

您需要一个自定义的MvcRouteHandler:

public class MyMvcRouteHandler : MvcRouteHandler
{
    protected override SessionStateBehavior GetSessionStateBehavior(RequestContext requestContext)
    {
        if (someCondition)
        {
            return SessionStateBehavior.Required;
        }
        // fallback to default behavior
        return base.GetSessionStateBehavior(requestContext);
    }
}

requestContext中,您会找到HttpContext,并根据您可以决定该做什么。

您需要为每条必要路线设置此新RouteHandler。您可以在RouteConfig文件中执行此操作,在路由注册后进行此操作:

// ...
routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
// ...

// set MyMvcRouteHandler for every route
foreach (var route in routes.OfType<Route>())
{
    route.RouteHandler = new MyMvcRouteHandler();
}

答案 3 :(得分:2)

问题是一个逻辑问题和两个相反的业务需求:readOnly和在某些条件下需要修改的问题。 所以,我要做的是回到你的逻辑并涵盖条件。 我会使用 Set方法 SetSessionStateBehavior()来进行切换排序。 例如,添加一个简单的if语句,如下所示(sudo代码)

    If a condition is met that requires non readOnly then
     SetSessionStateBehavior(
    SessionStateBehavior required
 )

//在这里做你需要做的事情,然后把它重新设置

答案 4 :(得分:0)

您可以尝试Microsoft.AspNet.SessionState.SqlSessionStateProviderAsync 1.1.0版本,该版本支持具有相同sessionid的并发请求。以下是使用该nupkg的步骤。 (您可以在this blog

上找到有关该软件包的更多详细信息
  1. 安装SqlSessionStateProviderAsync 1.1.0
  2. 将appsetting添加到web.config