I'm using the new .NET 7 OutputCache in my already developed application. and here is how I added the OutputCache.
builder.Services.AddOutputCache(x => x.AddPolicy("default", new CustomCachePolicy()));
app.UseOutputCache();
internal class CustomCachePolicy : IOutputCachePolicy {
public ValueTask CacheRequestAsync(OutputCacheContext context, CancellationToken cancellation) {
context.AllowCacheLookup = true;
context.AllowCacheStorage = true;
context.AllowLocking = true;
context.EnableOutputCaching = true;
context.ResponseExpirationTimeSpan = TimeSpan.FromSeconds(10);
return ValueTask.CompletedTask;
}
public ValueTask ServeFromCacheAsync(OutputCacheContext context, CancellationToken cancellation) => ValueTask.CompletedTask;
public ValueTask ServeResponseAsync(OutputCacheContext context, CancellationToken cancellation) => ValueTask.CompletedTask;
}
and here is the API I want to cache:
[HttpPost("Filter")]
[OutputCache( PolicyName = "default" )]
public ActionResult<GenericResponse<IQueryable<CategoryEntity>>> Filter(CategoryFilterDto dto) => Result(_repository.Filter(dto));
the problem here is that the Api is going to do some filter from the Body parameters that client is giving, and I want to vary by the params client is sending.
I searched the internet and I saw the VaryByParams
attribute but it seems does not exist in .NET 7.
how can I Vary the output based on the given body parameters in OutputCache of .NET 7
Just ran into this same issue, here's how I ended up doing it:
builder.AddPolicy<CachingPolicy>().VaryByValue(
(context) => {
context.Request.EnableBuffering();
using var reader = new StreamReader(context.Request.Body, leaveOpen: true);
var body = reader.ReadToEndAsync();
// Reset the stream position to enable subsequent reads
context.Request.Body.Position = 0;
var keyVal = new KeyValuePair<string, string>("requestBody", body.Result);
return keyVal;
}
)
Essentially this adds the string representation of the entire body as one of the values that constitutes the cache key. This is probably not ideal as changing anyting about the body, even just the whitespace, will result in a non-cached response, but it should be a good starting point to refine the implementation. If I end up improving it myself I'll edit this answer.