I've come across a curious behaviour of ASP sessions. You can force a controller to be outside of the user's session - I want to be able to do this so that multiple requests can execute at the same time and using a session causes them to execute consecutively.
Disabling session state works as expected:
[SessionState(SessionStateBehavior.Disabled)]
public class SampleController : Controller
{
public ActionResult Test()
{
// Access to the session should be denied
object test = Session["test"];
return Content(test);
}
}
Going to ~/Sample/Test will throw a System.Web.HttpException
, as expected.
However, read-only sessions appear to behave a little strangely:
[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);
}
}
So now I expect ~/Sample/Test to work, and it does. The odd bit is that the set does too: I go to ~/Sample/SetTest?value=foo and it doesn't throw an exception, in fact it returns "foo". If I call ~/Sample/SetTest?value=bar and then ~/Sample/Test I get "bar", indicating that the session has been written to.
So in a SessionStateBehavior.ReadOnly
I have successfully written to the session and read my value back.
I think this could be due to one of three things:
- In MVC 3
[SessionState(SessionStateBehavior.ReadOnly)]
is broken/ignored. - The
[SessionState]
is overridden when the session is written to and becomes writeable. - The
SessionStateBehavior.ReadOnly
actually indicates some kind of dirty/optimistic access.
Can anyone confirm?
I suspect the last one is true, based off the custom session provider documentation - if it is then how does the implementation work? Does writing to a 'read only' session risk concurrency errors (i.e. last write wins) or does it risk corrupt sessions and breaking exceptions?
Update
It looks like this is by design (from Microsoft's docs):
Note that even if the EnableSessionState attribute is marked as ReadOnly, other ASP.NET pages in the same application might be able to write to the session store, so a request for read-only session data from the store might still end up waiting for locked data to be freed.
It looks like the second option above is what it actually does - the session is locked and the mode changed to writable.