Can't modify OutputCacheContext.Tags from IOutputCachePolicy.ServeResponseAsync
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 5h
- Merged PRs (30d)
- 276
Description
### Is there an existing issue for this?
- [X] I have searched the existing issues
### Describe the bug
Assigning tags in `ServeResponseAsync` doesn't work; the tags don't get attached to the entries, so retrieving or evicting them does nothing.
It makes sense to be able to add tags to the cache entry in `ServeResponseAsync` (in a custom `IOutputCachePolicy`).
Work might be done during the request which resolves the value to be used in the tag, which is why it can't be assigned in `CacheRequestAsync` before the request has actually executed.
I believe the source of the issue is this block in `OutputCacheMiddleware`:
```
// Hook up to listen to the response stream
ShimResponseStream(context);
try
{
await _next(httpContext);
// The next middleware might change the policy
foreach (var policy in policies)
{
await policy.ServeResponseAsync(context, httpContext.RequestAborted);
}
// If there was no response body, check the response headers now. We can cache things like redirects.
StartResponse(context);
// Finalize the cache entry
await FinalizeCacheBodyAsync(context);
```
`ShimResponseStream` triggers `FinalizeCacheHeaders` which creates a copy of the tags (`ToArray()`) before the request gets executed in `await _next` - then even though the policy's `ServeResponseAsync` is using the request data to modify the tags, they don't get persisted by the call to FinalizeCacheBodyAsync, which uses the copy of the tags made in `ShimResponseStream`.
For a fix, what about removing this line in `FinalizeCacheHeaders`: `Tags = context.Tags.ToArray()`
And adding this one in `FinalizeCacheBodyAsync`: `context.CachedResponse.Tags = context.Tags.ToArray();`
For now I'm working around it by using reflection to set the `OutputCacheContext.CachedResponse.Tags` array inside `ServerResponseAsync` - reflection being necessary because CachedResponse (both the property and the class `OutputCacheEntry`) are internal
### Expected Behavior
Assigning tags in `ServeResponseAsync` should attach them to the stored cache entry.
### Steps To Reproduce
Create an implementation of `IOutputCachePolicy` and add:
```
public ValueTask ServeResponseAsync(OutputCacheContext context, CancellationToken cancellation)
{
context.AllowCacheStorage = true;
context.Tags.Add("MyTagHere");
return ValueTask.CompletedTask;
}
```
### Exceptions (if any)
_No response_
### .NET Version
7.0.101
### Anything else?
ASP.NET Core 7.0.2
Visual Studio Professional 2022
Contributor guide
Assessment
This issue has not been assessed yet.