In ASP.NET MVC 5 I often invalidated request cache items with code like this in a controller
Response.RemoveOutputCacheItem("/Client/Photo/1");
The RemoveOutputCacheItem option appears to be removed in ASP.NET Core. What is the alternative?
I worked this out, it is a multi step process.
Firstly you need to create your own OutputCache Policy, something like this
public class OutputCacheWithAuthPolicy : IOutputCachePolicy
{
public static readonly OutputCacheWithAuthPolicy Instance = new();
private OutputCacheWithAuthPolicy() { }
ValueTask IOutputCachePolicy.CacheRequestAsync(OutputCacheContext context, CancellationToken cancellationToken)
{
var attemptOutputCaching = AttemptOutputCaching(context);
context.EnableOutputCaching = true;
context.AllowCacheLookup = attemptOutputCaching;
context.AllowCacheStorage = attemptOutputCaching;
context.AllowLocking = true;
var id = context.HttpContext.Request.RouteValues["id"];
if (id != null)
context.Tags.Add($"Client_{id}");
// Vary by any query by default
context.CacheVaryByRules.QueryKeys = "*";
return ValueTask.CompletedTask;
}
private static bool AttemptOutputCaching(OutputCacheContext context)
{
var request = context.HttpContext.Request;
if (!HttpMethods.IsGet(request.Method) && !HttpMethods.IsHead(request.Method))
{
return false;
}
return true;
}
public ValueTask ServeFromCacheAsync(OutputCacheContext context, CancellationToken cancellation) => ValueTask.CompletedTask;
public ValueTask ServeResponseAsync(OutputCacheContext context, CancellationToken cancellation) => ValueTask.CompletedTask;
}
The important bit is where the tag with the ID is being added. This will be required to evict from the cache later on.
In your Program.cs you will need to configure the policy like this
builder.Services.AddOutputCache(options =>
{
options.AddBasePolicy(builder => builder.Cache());
options.AddPolicy("OutputCacheWithAuthPolicy", OutputCacheWithAuthPolicy.Instance);
})
....
app.UseOutputCache();
In my controller I have code something like this.
public ClientController: Controller
{
public ClientController(IOutputCacheStore outputCache)
{
_outputCache = outputCache;
}
private IOutputCacheStore _outputCache;
[OutputCache(VaryByQueryKeys = ["id"], Duration = 86400, PolicyName = "OutputCacheWithAuthPolicy")]
public IActionResult ProfilePic(int id)
{
var profilePic = GetPic();
return File(profilePic, "image/png");
}
public async Task<IActionResult> EvictPic(int id, CancellationToken token)
{
await _outputCache.EvictByTagAsync($"Client_{id}", token);
....
}
}
You will see the EvictPic action which forcibly evicts it from the cache