Siden opgraderingen til iOS 6 har vi set Safari's webvisning tage sig friheden til at cache `$.ajax`-opkald. Dette sker i forbindelse med en PhoneGap-applikation, så den bruger Safari WebView. Vores `$.ajax`-opkald er `POST`-metoder, og vi har indstillet cache til false `{cache:false}`, men det sker stadig. Vi prøvede manuelt at tilføje et `TimeStamp` til headerne, men det hjalp ikke.


Vi undersøgte yderligere og fandt ud af, at Safari kun returnerer cachede resultater for webtjenester, der har en funktionssignatur, som er statisk og ikke ændres fra kald til kald. Forestil dig f.eks. en funktion, der hedder noget i stil med:



```
getNewRecordID(intRecordType)
```

Denne funktion modtager de samme inputparametre igen og igen, men de data, den returnerer, skal være forskellige hver gang.


Må være i Apple's hastværk for at få iOS 6 til at zappe imponerende hurtigt, de blev for glade med cache-indstillingerne. Er der andre der har set denne opførsel på iOS 6? Hvis ja, hvad er det præcist, der forårsager den?




---


Den løsning, som vi fandt, var at ændre funktionssignaturen til at være noget i stil med dette:



```
getNewRecordID(intRecordType, strTimestamp)
```

og derefter altid sende en `TimeStamp`-parameter med, og så bare kassere denne værdi på serversiden. Dette fungerer uden om problemet. Jeg håber, at dette hjælper en anden stakkels sjæl, der bruger 15 timer på dette problem som jeg gjorde!


Gemmer Safari på iOS 6 $.ajax-resultater i cache?
=================================================


Efter lidt efterforskning viser det sig, at Safari på iOS6 vil cache POST'er, der enten ikke har nogen Cache-Control-headers eller endda "Cache-Control: max-age=0".


Den eneste måde, jeg har fundet for at forhindre denne caching på globalt niveau i stedet for at skulle hacke tilfældige querystrings i slutningen af servicekald, er at sætte "Cache-Control: no-cache".


Så:


* Ingen Cache-Control eller Expires-headers = iOS6 Safari vil cache
* Cache-Control max-age=0 og en øjeblikkelig Expires = iOS6 Safari vil cache
* Cache-Control: no-cache = iOS6 Safari vil IKKE cache


Jeg har mistanke om, at Apple udnytter dette fra HTTP-specifikationen i afsnit 9.5 om POST:



> 
> Svar på denne metode kan ikke cachelagres, medmindre svaret
> indeholder passende Cache-Control- eller Expires-hovedfelter. Men,
> 303-svaret (Se andet) kan dog bruges til at henvise brugeragenten til at
> hente en ressource, der kan bruges i cachen.
> 
> 
> 


Så i teorien kan man altså cache POST-svar... hvem vidste det? Men ingen andre browserproducenter har nogensinde tænkt, at det ville være en god idé, før nu. Men det er IKKE muligt at cachelagre, når der ikke er sat nogen Cache-Control- eller Expires-headere, kun når der er sat nogle. Så det må være en fejl.


Nedenfor er hvad jeg bruger i den rigtige bit af min Apache config til at målrette hele min API, fordi som det sker jeg don't faktisk ønsker at cache noget, selv får. Hvad jeg don't ved er, hvordan man indstiller dette bare for POSTs.



```
Header set Cache-Control "no-cache"
```

Opdatering: Har lige bemærket at jeg ikke gjorde't påpege at det kun er når POST er den samme, så ændre nogen af POST-dataene eller URL'en og du'er fint. Så du kan som nævnt andetsteds bare tilføje nogle tilfældige data til URL'en eller en smule POST-data.


Opdatering: Du kan begrænse "no-cache" bare til POSTs hvis du ønsker det, som dette i Apache:



```
SetEnvIf Request_Method "POST" IS_POST
Header set Cache-Control "no-cache" env=IS_POST
```

Jeg har også lige haft dette problem i en [PhoneGap](https://en.wikipedia.org/wiki/PhoneGap)-applikation. Jeg løste det ved at bruge JavaScript-funktionen `getTime()` på følgende måde:



```
var currentTime = new Date();
var n = currentTime.getTime();
postUrl = "http://www.example.com/test.php?nocache="+n;
$.post(postUrl, callbackFunction);
```

Jeg spildte et par timer på at finde ud af dette. Det ville have været pænt af Apple at underrette udviklerne om dette cachingproblem.


Jeg havde det samme problem med en webapp, der får data fra ASP.NET webservice


Dette virkede for mig:



```
public WebService()
{
    HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    ...
}
```
