[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] | |
public class CachedAttribute : Attribute, IAsyncActionFilter | |
{ | |
private readonly int _timeToLiveSeconds; | |
public CachedAttribute(int timeToLiveSeconds) | |
{ | |
_timeToLiveSeconds = timeToLiveSeconds; | |
} | |
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) | |
{ | |
//Get service settings for redis | |
var cacheSettings = context.HttpContext.RequestServices.GetRequiredService<RedisOptions>(); | |
if (!cacheSettings.Enabled) | |
{ | |
await next(); | |
return; | |
} | |
//Get the service, generate unique key from request | |
var cacheService = context.HttpContext.RequestServices.GetRequiredService<IResponseCacheService>(); | |
var cacheKey = GenerateCacheKeyFromRequest(context.HttpContext.Request); | |
//get data from cache | |
var cachedResponse = await cacheService.GetCachedResponseAsync(cacheKey); | |
//return response if data found in cache | |
if (!string.IsNullOrEmpty(cachedResponse)) | |
{ | |
var contentResult = new ContentResult | |
{ | |
Content = cachedResponse, | |
ContentType = "application/json", | |
StatusCode = 200 | |
}; | |
context.Result = contentResult; | |
return; | |
} | |
//else, continue along request pipeline | |
var executedContext = await next(); | |
//if the result of the request is sucessful, save the response in the cache for subsequent requests | |
if (executedContext.Result is OkObjectResult okObjectResult) | |
{ | |
await cacheService.CacheResponseAsync(cacheKey, okObjectResult.Value, TimeSpan.FromSeconds(_timeToLiveSeconds)); | |
} | |
} | |
private static string GenerateCacheKeyFromRequest(HttpRequest request) | |
{ | |
var keyBuilder = new StringBuilder(); | |
keyBuilder.Append($"{request.Path}"); | |
foreach (var (key, value) in request.Query.OrderBy(x => x.Key)) | |
{ | |
keyBuilder.Append($"|{key}-{value}"); | |
} | |
return keyBuilder.ToString(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment