I have a project where we use a service architecture, with Ninject to resolve our services. Nearly all our services use async.
Now, I want to add caching to a couple of the services.
I have never worked with caching in async methods, so I am unsure how to do it. I just know that I currently get this error as HttpContext.Current is null:
So, what strategy should I go for to make this work?
My IoC setup: NinjectWebCommon.cs:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<Context>().To<Context>().InRequestScope();
kernel.Bind<UserManager<User>>().To<UserManager>().InTransientScope();
kernel.Bind<IUserTokenProvider<User, string>>().ToMethod((x) =>
{
var provider = OwinConfig.DataProtectionProvider;
return new DataProtectorTokenProvider<User>(provider.Create("ASP.NET Identity"));
}).InTransientScope();
kernel.Bind<ICacheService>().To<HttpCache>();
kernel.Bind<IUserService>().To<UserService>();
// Lots of nice services
}
My ICacheService:
public interface ICacheService
{
object GetById(string cacheKey);
object Create(string cacheKey, object obj);
object Create(string cacheKey, object obj, DateTime expire);
void Delete(string cacheKey);
void DeleteByContaining(string containing);
string GetCacheKey(string methodName, string value);
bool ContainsKey(string cacheKey);
}
CacheService:
public class HttpCache : ICacheService
{
private static readonly ILog logger = LogManager.GetLogger(typeof (HttpCache));
public object GetById(string cacheKey)
{
if (ContainsKey(cacheKey))
{
return HttpContext.Current.Cache[cacheKey];
}
return null;
}
public object Create(string cacheKey, object obj)
{
return Create(cacheKey, obj, DateTime.UtcNow.AddHours(5));
}
public object Create(string cacheKey, object obj, DateTime expire)
{
if (!ContainsKey(cacheKey))
{
HttpContext.Current.Cache.Insert(cacheKey,
obj,
null,
expire,
Cache.NoSlidingExpiration);
}
return GetById(cacheKey);
}
public void Delete(string cacheKey)
{
HttpContext.Current.Cache.Remove(cacheKey);
}
public void DeleteByContaining(string containing)
{
List<string> deleteList = new List<string>();
HttpContext oc = HttpContext.Current;
// find all cache keys in the system... maybe insane? I don't know lol
IDictionaryEnumerator en = oc.Cache.GetEnumerator();
while (en.MoveNext())
{
var k = en.Key.ToString();
if (k.Contains(containing))
{
deleteList.Add(k);
}
}
foreach (var del in deleteList)
{
Delete(del);
}
}
public bool ContainsKey(string cacheKey)
{
return HttpContext.Current.Cache[cacheKey] != null;
}
public string GetCacheKey(string methodName, string value)
{
return string.Format("{0}_{1}", methodName, value);
}
}
My caller:
public async Task<City> GetById(int id)
{
var cacheKey = _cacheService.GetCacheKey(MethodBase.GetCurrentMethod().Name, id.ToString());
if (!_cacheService.ContainsKey(cacheKey))
{
var city = await _db.Cities.FirstAsync(c => c.Id == id);
_cacheService.Create(cacheKey, city);
return city;
}
return (City)_cacheService.GetById(cacheKey);
}

System.Runtime.Caching.