写入MVC 3+中的只读会话

时间:2012-01-20 09:26:52

标签: asp.net-mvc asp.net-mvc-3 session session-state

我遇到了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);
    }
}

转到〜/ 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);
    }
}

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

所以在SessionStateBehavior.ReadOnly我已成功写入会话并重新读取我的价值。

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

  • 在MVC 3 [SessionState(SessionStateBehavior.ReadOnly)]被破坏/忽略。
  • 会话写入并变为可写时,[SessionState]被覆盖。
  • SessionStateBehavior.ReadOnly实际上表示某种脏/乐观访问。

任何人都可以确认吗?

我怀疑最后一个是真的,基于custom session provider documentation - 如果是,那么实现如何工作?写入“只读”会话是否存在并发错误(即最后写入获胜)或是否存在损坏会话和破坏异常的风险?

更新

看起来这是设计的(来自Microsoft's docs):

  

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

看起来上面的第二个选项实际上是这样 - 会话被锁定,模式变为可写。

1 个答案:

答案 0 :(得分:10)

〜/ Sample / SetTest?value = foo

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

在我的测试中〜/ Sample / Test什么都不返回。

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

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

string test = (string)this.Session["test"];