Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
546 views
in Technique[技术] by (71.8m points)

asp.net mvc - Writing to a read only session in MVC 3+

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

~/Sample/SetTest?value=foo

Yes it won't throw any error, but it also didn't persist the session at the end of the request. By design any thing that you write to session gets updated (only if the session is writable) at the very end of the request life-cycle.

In my test ~/Sample/Test returns nothing.

I think they should have failed fast here when the session is readonly.

By the way your sample need to be rewritten

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...