The Tags Property in OutputCache attribute is not working when using custom policies. #58785
Description
Is there an existing issue for this?
- I have searched the existing issues
Describe the bug
Hey, I'm trying to implement OutputCache with MultiTenancy Support, So I had to create a custom policy for that, I also used tags so that I can evict cache by tags + tenant id, this is how I'm doing it:
Custom OutputCache policy, MultitenantCachePolicy:
public class MultitenantCachePolicy : IOutputCachePolicy
{
public ValueTask CacheRequestAsync(OutputCacheContext context, CancellationToken cancellation)
{
var attemptOutputCaching = AttemptOutputCaching(context);
context.EnableOutputCaching = true;
context.AllowCacheLookup = attemptOutputCaching;
context.AllowCacheStorage = attemptOutputCaching;
context.AllowLocking = true;
context.CacheVaryByRules.QueryKeys = "*";
var tenantId = context.HttpContext.Items["tenantId"] as string ?? "";
HashSet<string> newTags = [];
foreach (var tag in context.Tags)
{
newTags.Add($"tenant:{tenantId}:{tag}");
}
newTags.Add($"tenant:{tenantId}");
context.Tags.UnionWith(newTags);
return ValueTask.CompletedTask;
}
public ValueTask ServeFromCacheAsync(OutputCacheContext context, CancellationToken cancellation)
{
var response = context.HttpContext.Response;
if (!StringValues.IsNullOrEmpty(response.Headers.SetCookie))
{
context.AllowCacheStorage = false;
return ValueTask.CompletedTask;
}
if (response.StatusCode != StatusCodes.Status200OK)
{
context.AllowCacheStorage = false;
return ValueTask.CompletedTask;
}
return ValueTask.CompletedTask;
}
public ValueTask ServeResponseAsync(OutputCacheContext context, CancellationToken cancellation)
=> 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;
}
}
And this is how I register it:
services.AddOutputCache(options =>
{
options.AddPolicy(CacheConfig.CachePolicies.MultiTenantCache, o =>
{
o.Expire(TimeSpan.FromMinutes(10))
.VaryByValue(context => CacheExtension.VaryByTenantId(context))
.AddPolicy<MultitenantCachePolicy>();
});
}
And this is how I use it in controller endpoints:
[OutputCache(PolicyName = CacheConfig.CachePolicies.MultiTenantCache, Tags = [CacheConfig.CacheTags.DummyTag])]
The problem is that the DummyTag
is not getting used at all, when i set a breakpoint in CacheRequestAsync
the context Tags list is empty, however, if i set the Tag using this way:
options.AddPolicy(CacheConfig.CachePolicies.MultiTenantCache, o =>
{
o.Expire(TimeSpan.FromMinutes(10))
.VaryByValue(context => CacheExtension.VaryByTenantId(context))
.AddPolicy<MultitenantCachePolicy>()
.Tag(CacheConfig.CacheTags.DummyTag);
});
It works this way, what am I doing wrong here?
Expected Behavior
I should be able to register one custom policy, however, when I use that policy in the OutputCache attribute, I should be able to use the Tags
property so that each controller endpoint has its Tag while sharing the same policy.
Steps To Reproduce
No response
Exceptions (if any)
No response
.NET Version
8.0.403
Anything else?
No response