After two weeks of programming I can finally state that my first Windows Phone 7 application is 100% functional and ready. Now it only needs to go through the marketplace certification tests and then I’ll be the proud owner of an official WP7 app.The following days I will put up short blogs describing some of the things I’ve learned while making this app; small tips, links to interesting guides, etc. I will not describe the app itself in these posts (scheduled once the app is published) and try to formulate my problems and solutions as generic as possible. Consider these posts a gathering of my recent acquired new WP7 development knowledge.
This first post will explain the problem with WP7 devices caching urls you are trying to reach.
Sending commands to my mediacenter (the app I made is an IP remote control for my media center) is done by sending an http-request of the following form (shortened):
uristring = http://mymediacenter/remoteservice.php?fcm=c
This request will send the c-command to the remote. Implementing this in WP7 is a breeze using the WebClient class:
WebClient client = new WebClient();
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(sendCommandCompleted);
where uri contains the httprequest string containing the command. The moment DownloadStringAsync() is started and once the request arrives at the media center, the command is executed. The media center service will return a “success” string which can be parsed in the sendCommandCompleted method for further error checking if needed.
Actually this code is heart of my app and should work always….however, it doesn’t on my WP7 phone. What happens is this: the WebClient-class will cache any url that was previously send on the device. If at any time during the lifetime of the app the same url needs to be send again, the device will simply NOT send the request and return the original result it received from the request to the sendCommandCompleted method. In other words, to the user it will look like the request was in fact send, however, nothing is transmitted ‘over the wire’. The only workaround without changing your code is by restarting the application on your phone. This will empty the cache, but once again you can only send each command once.
The only way to solve this particular problem is by creating a new url each time, making the WP7 device believe that is has never before send anything to the given url (other solutions exist if you have access to the service you are using, see here). The best way to do this is to add a random string as extra parameter behind the original url, for example:
uristring += "&r=" + Guid.NewGuid().ToString();
This will result in the following string, where the part after r= will vary each time:
Two notes here:
- The ‘r’ parameter can be any letter you choose, as long as it’s not a parameter your remote services knows (otherwise it will try and parse the random string right behind it)
Using Guid, a rather long random string is created (16bytes). Depending on how long the app will typically live it might be interesting to have a shorter random string (simply use the Random class) in order to conserve precious bits being send on your phone.
Problem 1 solved!
6 gedachten over “Creating a WP7 app: Caching urls problem”
Actually, for your random value:
a) any value will do as long as it’s different from the previous one(s):
A common case among web developers is to append the unix timestamp (as an integer) to content url’s (images, css, …) to prevent the browser from using the cached one.
b) it should be possible to use the random value as the variable name itself, provided it has only allowed chars:
Actually, your real problem is on the server side. You should be setting the header cache-control: to “no-cache”. The WebClient class is being well-behaved here. It’s doing what the server has inadvertently asked it to do.
I agree with robaticus; if you have control over the server side of things, you should solve this by adding/setting the proper cache headers.
Also, there’s a slight mistake in your post: you say that a string of 16 bytes is created. But a guid is only 16 bytes when it is represented as a _number_. The string representation consists of two characters per original byte value (hex) plus in your case the dashes.
You should have used HTTP POST, not HTTP GET. I think, that would also solve your problem.
Thank you for the post. So much.. 🙂
This was the problem that I faced twice; first one was yearrss ago in VB6.
I remember that I used number 4 as one of the parameters to solve this.
I have an update button and BackgroundAgent Tasks.., and every few seconds/minutes my remote server’s content changes.. Thanks again.
I used this for random attachment;
DateTime AnyRandomTime = DateTime.Now;
string AnyRandomString = null;
AnyRandomString = AnyRandomTime.TimeOfDay.TotalMilliseconds.ToString ();
url += “&r=” + AnyRandomString; //”&r=” + Guid.NewGuid().ToString();