tirsdag den 20. marts 2012

Caching JSONP requests in MVC3

JSONP is quite nice for situations where you have a large number of client running from different domains, and they all need data from you.

MVC3 does not support JSONP natively. An employee from Microsoft called Ranju has blogged his approach to adding JSONP to MVC3. I like his implementation and it's a pretty straight forward copy/paste to use in your projects. Check it out here: blogorama.nerdworks.in

However if the data takes too long to generate you might want to cache the output.

This is where you run into problems when the client uses standard ways to request JSONP data. The callback parameter has to be made static.

This is the standard jQuery behaviour to fetch JSONP:
$.getJSON("http://YourSite/Controller/GetJSONP?callback=?")

The '?' is automaticly set to a unique value by jQuery which will result in either 2 things for a normal Cacheoutput

  • Your cache is bypassed since your parameters are changing by each request
  • The client breaks because the callback you return isnt the one it stated in it's URL
This is one way to fix these issues:
Instead of using $.getJSON() use $.getScript() instead. With getScript you can specify a static callback parameter.
$.getScript(" http://YourSite/Controller/GetJSONP?callback=DataDownloaded", function(data) {
alert('done'); 
});

function  DataDownloaded (data)
{
alert('done');  
} 

jQuery still adds a unique ID to the actual URL but we can work past that.

This is our method in our controller:
[OutputCache(Duration = 60*30 /* 30mins */, VaryByParam = "callback")]
public JsonpResult GetJSONP(String _, String callback)
{
//Your code here
}
It takes 2 parameters. '_' is generated by jQuery as a unique id. Callback is what we manually set to a static value.

I then added the OutputCache annotation, set the duration to 30 minutes and set it to vary only by "callback".

The result is a cache is built for every unique callback parameter, but jquerys '_' parameter is ignored.

Our result is a slender, fast and working cache that works with JSONP

Update 4/4-2012.
Another way to aproach the problem is to deal with it clientside. By using jQuery.ajax and it's cache setting you can remove the timestamp property alltogether.

cacheBoolean
Default: true, false for dataType 'script' and 'jsonp'
If set to false, it will force requested pages not to be cached by the browser. Setting cache to false also appends a query string parameter, "_=[TIMESTAMP]", to the URL.
More info here: http://api.jquery.com/jQuery.ajax/
Thank you Marc Brooks for this information

2 kommentarer:

  1. You can make newer versions of jQuery allow caching by setting the cache option on the request to true. This will prevent jQuery from adding the _=[TIMESTAMP] parameter (which is there just to bust caches)

    http://api.jquery.com/jQuery.ajax/

    SvarSlet
  2. Hi Marc, thank you for the comment. I have updated the post to reflect the "cache" setting in jQuery.

    SvarSlet