写入MVC 3+中的只读会话

Kei*_*ith 27 asp.net-mvc session session-state asp.net-mvc-3

我遇到过ASP会话的好奇行为.您可以强制控制器在用户会话之外 - 我希望能够执行此操作,以便可以同时执行多个请求并使用会话使它们连续执行.

禁用会话状态按预期工作:

[SessionState(SessionStateBehavior.Disabled)]
public class SampleController : Controller
{
    public ActionResult Test() 
    {
        // Access to the session should be denied
        object test = Session["test"];
        return Content(test);
    }
}
Run Code Online (Sandbox Code Playgroud)

转到〜/ Sample/Test会抛出一个System.Web.HttpException,如预期的那样.但是,只读会话似乎有点奇怪:

[SessionState(SessionStateBehavior.ReadOnly)]
public class SampleController : Controller
{
    public ActionResult Test() 
    {
        // Read from the session should be fine
        object test = Session["test"];
        return Content(test);
    }

    public ActionResult SetTest(string value) 
    {
        // Write to the session should fail 
        Session["test"] = value;

        // Read it back from the session
        object test = Session["test"];
        return Content(test);
    }
}
Run Code Online (Sandbox Code Playgroud)

所以现在我希望〜/ Sample/Test能够正常工作,而且确实如此.奇怪的是该集合也是如此:我转到〜/ Sample/SetTest?value = foo并且它不会抛出异常,实际上它返回"foo".如果我调用 〜/ Sample/SetTest?value = bar然后〜/ Sample/Test我得到"bar",表示会话已被写入.

所以在SessionStateBehavior.ReadOnly我已成功写入会话并阅读我的价值.

我认为这可能是由于以下三点之一:

  • 在MVC 3中[SessionState(SessionStateBehavior.ReadOnly)]被破坏/忽略.
  • [SessionState]当会话被写入,并成为可写的被覆盖.
  • SessionStateBehavior.ReadOnly实际上表明某种肮脏/乐观访问.

谁能确认一下?

我怀疑最后一个是真的,基于自定义会话提供程序文档 - 如果是,那么实现如何工作?写入'只读'会话是否存在并发错误(即最后写入获胜)或是否存在损坏会话和破坏异常的风险?

更新

看起来这是设计(来自微软的文档):

请注意,即使EnableSessionState属性标记为ReadOnly,同一应用程序中的其他ASP.NET页面也可能会写入会话存储,因此来自存储的只读会话数据请求可能仍会等待锁定要释放的数据.

看起来上面的第二个选项实际上是它 - 会话被锁定并且模式变为可写.

cha*_*dmk 10

〜/样品/ SetTestα值= FOO

是的,它不会抛出任何错误,但它也没有在请求结束时保持会话.按照设计,在请求生命周期的最后,您写入会话的任何内容都会更新(仅当会话可写时).

在我的测试〜/ Sample/Test中什么也没有返回.

我认为当会话是readonly时,他们应该在这里快速失败.

顺便提一下你的样本需要重写

string test = (string)this.Session["test"]; 
Run Code Online (Sandbox Code Playgroud)

  • 发现的问题 - 在某些情况下,ASP会从只读中覆盖`SessionStateBehavior`.大多数写入都会默默地失败,但是global.ascx中的操作似乎(有时)强制它回写,令人烦恼地将会话锁定在页面生命周期中不可预测的位置.我已经决定完全放弃ASP会话 - 我需要的是脏读和上次写入获胜,它根本不能支持. (2认同)