RssChannelDom DownloadChannelDom(string url) { // look for disk cache first RssChannelDom dom = TryLoadFromDisk(url); if (dom != null) { return(dom); } // download the feed byte[] feed = new WebClient().DownloadData(url); // parse it as XML XmlDocument doc = new XmlDocument(); doc.Load(new MemoryStream(feed)); // parse into DOM dom = RssXmlHelper.ParseChannelXml(doc); // set expiry string ttlString = null; dom.Channel.TryGetValue("ttl", out ttlString); int ttlMinutes = GetTtlFromString(ttlString, _defaultTtlMinutes); DateTime utcExpiry = DateTime.UtcNow.AddMinutes(ttlMinutes); dom.SetExpiry(utcExpiry); // save to disk TrySaveToDisk(doc, url, utcExpiry); return(dom); }
RssChannelDom TryLoadFromDisk(string url) { if (_directoryOnDisk == null) { return(null); // no place to cache } // look for all files matching the prefix // looking for the one matching url that is not expired // removing expired (or invalid) ones string pattern = GetTempFileNamePrefixFromUrl(url) + "_*.rss"; string[] files = Directory.GetFiles(_directoryOnDisk, pattern, SearchOption.TopDirectoryOnly); foreach (string rssFilename in files) { XmlDocument rssDoc = null; bool isRssFileValid = false; DateTime utcExpiryFromRssFile = DateTime.MinValue; string urlFromRssFile = null; try { rssDoc = new XmlDocument(); rssDoc.Load(rssFilename); // look for special XML comment (before the root tag)' // containing expiration and url XmlComment comment = rssDoc.DocumentElement.PreviousSibling as XmlComment; if (comment != null) { string c = comment.Value; int i = c.IndexOf('@'); long expiry; if (long.TryParse(c.Substring(0, i), out expiry)) { utcExpiryFromRssFile = DateTime.FromBinary(expiry); urlFromRssFile = c.Substring(i + 1); isRssFileValid = true; } } } catch { // error processing one file shouldn't stop processing other files } // remove invalid or expired file if (!isRssFileValid || utcExpiryFromRssFile < DateTime.UtcNow) { try { File.Delete(rssFilename); } catch { } // try next file continue; } // match url if (urlFromRssFile == url) { // found a good one - create DOM and set expiry (as found on disk) RssChannelDom dom = RssXmlHelper.ParseChannelXml(rssDoc); dom.SetExpiry(utcExpiryFromRssFile); return(dom); } } // not found return(null); }