I’m presently helping a client refresh their solution to the latest technology in K2, ASP.NET MVC, Sharepoint etc and found quite a poor issue with how caching works in MVC 2 compared to MVC 1.
The scenario, lets say we have a single controller with InitialiseA(), InitialiseB() and Start(). The two init methods would set some session variables or do something in the database and then send back a redirect to action to go off to Start. This is what I expect to happen;
- I navigate to http://mysite/controller/InitialiseA
- Sets “ABC” in session
- Sends back a 302 with content moved to /controller/Start
- Browser redirects to http://mysite/controller/Start
- Status 200 - Renders “ABC”
- I navigate to http://mysite/controller/InitialiseB
- Sets “DEF” in session
- Sends back a 302 with content moved to /controller/Start
- Browser redirects to http://mysite/controller/Start
- Status 200 - Renders “DEF”
The reality is significantly different though. The above is how it would work in MVC1, but in MVC2, the following happens;
- I navigate to http://mysite/controller/InitialiseA
- Sets “ABC” in session
- Sends back a 302 with content moved to /controller/Start
- Browser redirects to http://mysite/controller/Start
- Status 200 - Renders “ABC”
- I navigate to http://mysite/controller/InitialiseB
- Sets “DEF” in session
- Sends back a 302 with content moved to /controller/Start
- Browser sends no further requests to server and instead just renders the same result as my previous hit to /controller/Start;
- Renders “ABC”
The result of the first invocation of Start is being cached and so, when the browser gets the 302 response it realises it already has the content for the redirected url and just renders that. So what’s changed?
MVC1 used to send an expires HTTP response header set to the current time, meaning the browser wouldn’t cache the result. MVC 2 however doesn’t send this by default, so I found myself with a bunch of issues around the scenario described above. In just so happens that in this case all of my controllers descend from one common abstract base controller, so I was able to add the OutputCache(Location=OutputCacheLocation.None) attribute to this base class as follows;
[OutputCache(Location=OutputCacheLocation.None)] public abstract class MyBaseController : Framework.Web.Mvc.ControllerBase { .. }
No comments:
Post a Comment