In Part 2 of this series I described how to retrieve a TermSet, and interpret the results. I suggested using code:
string clientTimestamps = string.Format("<timeStamp>{0}</timeStamp>", lastClientCacheTime ); string clientVersion = "<version>1</version>"; string termStoreIds = string.Format("<termStoreId>{0}</termStoreId>", termStoreId.ToString("D")); string termSetIds = string.Format("<termSetId>{0}</termSetId>", termSetId.ToString("D")); string serverTermSetTimestampXml; string result = _wssTax.GetTermSets(termStoreIds, termSetIds, 1033, clientTimestamps, clientVersion, out serverTermSetTimestampXml);
Fine, but what are these properties we’re passing into GetTermSets()?
Well timeStamps is the time you last retrieved the term set as number of Ticks for that time. E.g.
long clientTime = 0; if (File.Exists(taxonomyFileCachePath)) { clientTime = File.GetLastWriteTimeUtc(taxonomyFileCachePath).Ticks; }
clientVersion is described as:
Collection of versions of the server that each TermSet was downloaded from (always 1 unless the client doesn’t have the TermSet, then it is 0).
That has me puzzled, so I always just send a version of 1.
termStoreIds is the ID of the term store we want to get terms from.
termSetIds is the term set we want to retrieve.
serverTermSetTimestampXml is the an output parameter which contains the last edit times for each of the retrieved term sets.
You may notice that for the above parameters I keep talking about term sets – as if you format your XML strings with multiple entries you should be able to retrieve multiple term sets at the same time. To be honest, though, I reckon this might be more effort than it’s worth, so I’ve written my functions to retrieve one term set at a time.
So what do I get back?
If my last cached time is from before the last editted time on the server, I get back the XML for the term set.
If my last cached time is more recent than the last editted time on the server, I get back XML containing no terms.
Thus, my logic for caching becomes:
- Get the last time I cached the term set.
- Call GetTermSets() on the web service.
- If there are terms in the response then the term set was editted since I last cached them. Write these new terms to the cache.
- Read the terms from the cache.
- Return them.
This would be something like:
long clientTime = 0; if (File.Exists(taxonomyFileCachePath)) { clientTime = File.GetLastWriteTimeUtc(taxonomyFileCachePath).Ticks; } string clientTimestamps = string.Format("<timeStamp>{0}</timeStamp>", clientTime); string clientVersion = "<version>1</version>"; string termStoreIds = string.Format("<termStoreId>{0}</termStoreId>", termStoreId.ToString("D")); string termSetIds = string.Format("<termSetId>{0}</termSetId>", termSetId.ToString("D")); string serverTermSetTimestampXml; //HACK: Hardcoded Locale string result = _wssTax.GetTermSets(termStoreIds, termSetIds, 1033, clientTimestamps, clientVersion, out serverTermSetTimestampXml); // Get the terms from the Web Service Response as a list of 'WssTaxonomyTerm' objects. // WssTaxonomyTerm is my own class to represent a Term in a Termset terms = GetResultsFromString(result); XmlSerializer ser = new XmlSerializer(typeof(List)); //Terms.count could be zero because we already have a cached version in a file locally. //If so, don't overwrite that file. We'll load from it below. //If we did get terms back, then they are more recent than our cache. Save them. They'll be loaded below. if (terms.Count > 0) { using (FileStream fs = new FileStream(taxonomyFileCachePath, FileMode.Create, FileAccess.Write)) { ser.Serialize(fs, terms); } } if (File.Exists(taxonomyFileCachePath)) { using (FileStream fs = new FileStream(taxonomyFileCachePath, FileMode.Open, FileAccess.Read)) { terms = (List)ser.Deserialize(fs); } } return terms;
I think you have “strip tags” on and it altered your source code. The parameters (termstoreid, termsetids, and timestamp?) are supposed to be enclosed in xml elements, aren’t they?
Yes, you’re right – I’ll try and fix that now…
… and done! Thanks Dave.
How do you get the “taxonomyFileCachePath” in the above code?
It’s just a filepath that I chose to store my cached taxonomy terms under. I was using in the user’s APPDATA directory, but you could use any path that your application can write to.