Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
[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
You can’t perform that action at this time.