using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Text; using System.Threading.Tasks; namespace BuildFeedApp.Service { public static class ApiCache { public static int SecondsBeforeStale { get; set; } private static Dictionary _cache = new Dictionary(); static ApiCache() { //ServicePointManager.DefaultConnectionLimit = 20; SecondsBeforeStale = 15; } /// /// Download and parse a JSON document into the specified type /// /// Object that JSON Reperesents /// The URL that the JSON can be retreived from /// public async static Task GetApi(string url) { if (_cache.ContainsKey(url) && (_cache[url].ExpiryTime > DateTime.Now || !await IsAPIStale(url, _cache[url].LastModified))) { return (T)(_cache[url].Value); } else { var cat = await FetchAPI(url); _cache[url] = cat; return (T)(cat.Value); } } private async static Task FetchAPI(string url) { HttpWebRequest wreq = HttpWebRequest.CreateHttp(url); ApiCacheEntry ret = new ApiCacheEntry(); using (HttpWebResponse wres = await wreq.GetResponseAsync() as HttpWebResponse) { ret.ExpiryTime = DateTime.Now.AddSeconds(SecondsBeforeStale); //ret.LastModified = wres.LastModified; using (Stream s = wres.GetResponseStream()) using (StreamReader sr = new StreamReader(s)) using (JsonReader jr = new JsonTextReader(sr)) { JsonSerializer jsz = new JsonSerializer(); ret.Value = jsz.Deserialize(jr); } } return ret; } private async static Task IsAPIStale(string url, DateTime lastChecked) { HttpWebRequest wreq = HttpWebRequest.CreateHttp(url); //wreq.IfModifiedSince = lastChecked; wreq.Method = "HEAD"; try { HttpWebResponse wres = await wreq.GetResponseAsync() as HttpWebResponse; } catch (WebException wex) { HttpWebResponse wres = wex.Response as HttpWebResponse; if (wres.StatusCode == HttpStatusCode.NotModified || wres.StatusCode == HttpStatusCode.NotFound) { return false; } } return true; } } internal struct ApiCacheEntry { public DateTime ExpiryTime { get; set; } public DateTime LastModified { get; set; } public object Value { get; set; } } }