Quantcast
Channel: CodeSection,代码区,数据库(综合) - CodeSec
Viewing all articles
Browse latest Browse all 6262

Web API caching with CacheManager, CacheOutput and Redis

$
0
0

Customizable and extendable Web API caching with CacheManager , Strathweb.CacheOutput and Redis in the backend.


Web API caching with CacheManager, CacheOutput and Redis

Source code for solution is available here https://github.com/mchudinov/WebApiCache

I like Strathweb.CacheOutput library. It gives cache attribute to Web API actions in a similar way as it is in ASP.NET MVC. To make cache flexible we use CacheManager . It is easy to change cache backed with CacheManager by just changing config options.

1. Install packages

Newtonsoft.Json Microsoft.Web.RedisSessionStateProvider StackExchange.Redis.StrongName CacheManager.Core CacheManager.Serialization.Json CacheManager.StackExchange.Redis Strathweb.CacheOutput.WebApi2

2. Simple cache with CacheManager and Redis

The simple cache solution based on CacheManager and Redis is described here:

ASP.Net cache and session with Redis and CacheManager

Cache implements the following interface:

public interface ICacheProvider { T Get<T>(string key); void Set<T>(string key, T value); void SetSliding<T>(string key, T value); void Set<T>(string key, T value, int duration); void SetSliding<T>(string key, T value, int duration); void Set<T>(string key, T value, DateTimeOffsetexpiration); bool Exists(string key); void Remove(string key); }

3. Add implementation of WebApi.OutputCache.Core.Cache.IApiOutputCache

OuputCache has it’s own cache interface that must be implemented in order to customize backend.

public interface IApiOutputCache { IEnumerable<string> AllKeys { get; } void Add(string key, object o, DateTimeOffsetexpiration, string dependsOnKey = null); bool Contains(string key); T Get<T>(string key) where T : class; void Remove(string key); void RemoveStartsWith(string key); }

I use implementation based on my CacheManager class. Read more about it in my blog post here ASP.Net cache and session with Redis and CacheManager

class CustomCacheProvider : IApiOutputCache { private static readonly ICacheProviderCacheManagerCache = new CacheManagerCache(); private static readonly IList<string> Keys = new List<string>(); public void RemoveStartsWith(string key) { IList<string> keys = Keys.Where(k => k.StartsWith(key)).ToList(); foreach (var k in keys) { Remove(k); } } public T Get<T>(string key) where T : class { return CacheManagerCache.Get<T>(key); } public object Get(string key) { return CacheManagerCache.Get<object>(key); } public void Remove(string key) { Keys.Remove(key); CacheManagerCache.Remove(key); } public bool Contains(string key) { return CacheManagerCache.Exists(key); } public void Add(string key, object o, DateTimeOffsetexpiration, string dependsOnKey = null) { Keys.Add(key); CacheManagerCache.Set(key, o, expiration); } public IEnumerable<string> AllKeys => Keys; }

Add call in Configuration method in startup class:

config.CacheOutputConfiguration().RegisterCacheOutputProvider(() => new CustomCacheProvider());

4. Add custom key generator if needed

public class CustomCacheKeyGenerator : WebApi.OutputCache.V2.DefaultCacheKeyGenerator { public override string MakeCacheKey(HttpActionContextactionContext, MediaTypeHeaderValueheader, bool excludeQueryString = false) { //add your key generation here return base.MakeCacheKey(actionContext, header, excludeQueryString); } }

Add call in Configuration method in Startup class:

config.CacheOutputConfiguration().RegisterDefaultCacheKeyGeneratorProvider(()=>newCustomCacheKeyGenerator());

Test the cache invalidation actually works with new key generation routine! Run some POST or PUT calls and watch that keys are deleted from cache. If they are not, then the custom generated keys are not good.

5. Configure Redis in .config file

<cacheManager.Redis> <connections> <connectionid="RedisHandle" database="0" connectionString=".....:6380,password=....,ssl=True,abortConnect=False"/> </connections> </cacheManager.Redis> <cacheManager> <managers> <cachename="Redis" updateMode="Up" enableStatistics="false" enablePerformanceCounters="false" serializerType="CacheManager.Serialization.Json.JsonCacheSerializer, CacheManager.Serialization.Json"> <handlename="RedisHandle" ref="RedisHandle"/> </cache> </managers> <cacheHandles> <handleDefid="RedisHandle" type="CacheManager.Redis.RedisCacheHandle`1, CacheManager.StackExchange.Redis"/> </cacheHandles> </cacheManager>

6. Create WebAPI action with cache attributes and test cache

Add cache attributes. Cache must be used on GET methods, and invalidated (keys deleted) on POST,PUT and DELETE methods.

[AutoInvalidateCacheOutput] [CacheOutput(ServerTimeSpan = 60)] public class CacheController : ApiController { // GET api/cache public IEnumerable<string> Get() { Console.WriteLine("return from method"); return new[] { "value1", "value2" }; } public void Post(object obj) { // } }

Now we can change cache backend for WebAPi by simply changing configuration.

Sample SoapUI xml file for testing is included into solution. Solution run selfhosted WebAPI on localhost::8080.


Viewing all articles
Browse latest Browse all 6262

Trending Articles