Skip to content

Instantly share code, notes, and snippets.

@sixeyed
Created June 4, 2014 15:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sixeyed/e9a1871bad2ed9df9b97 to your computer and use it in GitHub Desktop.
Save sixeyed/e9a1871bad2ed9df9b97 to your computer and use it in GitHub Desktop.
WebApi caching passthrough controller - passthrough JSON from another URL, using simple in-memory cache
using System;
using System.Runtime.Caching;
using System.Web.Http;
using System.Xml;
namespace Sixeyed.Api.Core
{
public class ContentCache
{
private static MemoryCache _Cache;
private static CacheItemPolicy _Policy;
private static TimeSpan _Lifespan;
static ContentCache()
{
_Cache = new MemoryCache("_ContentCache");
_Policy = new CacheItemPolicy();
_Lifespan = XmlConvert.ToTimeSpan("PT10S"); //TODO - from your config
}
public static object Get(string id)
{
return _Cache[id];
}
public static T Get<T>(string id)
{
return (T) Get(id);
}
public static bool Exists(string id)
{
return _Cache[id] != null;
}
public static void Set(string id, object content)
{
_Policy.AbsoluteExpiration = DateTimeOffset.Now.Add(_Lifespan);
_Cache.Set(id, content, _Policy);
}
public static string ComputeKey<TController>(string id)
where TController : ApiController
{
return ComputeKey(typeof(TController), id);
}
public static string ComputeKey(Type type, string id)
{
return string.Format("{0}_{1}", type.GetType().Name, id);
}
}
}
using System.Web.Http;
using Sixeyed.Api.Core;
using Sixeyed.Api.Core.Controllers;
namespace Sixeyed.Api.Controllers
{
public class GitHubController : JsonPassthroughController
{
//example - caching passthrough for the GitHub status API
//http://localhost/Sixeyed.Api/api/github/status
public IHttpActionResult GetStatus()
{
return GetFromCacheOrSource("https://status.github.com/api/status.json");
}
}
}
using Newtonsoft.Json.Linq;
using System.Net;
using System.Web.Http;
namespace Sixeyed.Api.Core.Controllers
{
public abstract class JsonPassthroughController : ApiController
{
public IHttpActionResult GetFromCacheOrSource(string sourceUrl)
{
var cacheKey = ContentCache.ComputeKey(GetType(), sourceUrl);
object content = "{}";
if (!ContentCache.Exists(cacheKey))
{
using (var client = new WebClient())
{
try
{
client.Headers["Accept"] = "application/json";
var json = client.DownloadString(sourceUrl);
content = JObject.Parse(json);
ContentCache.Set(cacheKey, content);
}
catch (WebException wex)
{
var response = wex.Response as HttpWebResponse;
if (response.StatusCode == HttpStatusCode.NotFound)
{
return NotFound();
}
return InternalServerError().
}
}
}
else
{
content = ContentCache.Get(cacheKey);
}
return Ok(content);
}
}
}
@jakelly
Copy link

jakelly commented Jan 6, 2017

This additional reference helped me take your code and bypass using CORS to get a project completed. I'm using the server now to retrieve the json I need from another server (another domain) using your code. Very helpful! Thank you for sharing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment