Я отвечаю на свой вопрос с помощью решения, которое мы приняли только для протокола.
В нашем OutputCacheAttribute
мы добавляем пустой объект кеша с ключом, который зависит от запрошенного URL и некоторых параметров. Это будет использоваться для внешней недействительности страницы.
Затем мы также добавляем еще один объект с ключом, который зависит от текущего запроса и содержит предыдущий cacheKey.
Наконец, устанавливается статический ValidationCallback. Обратный вызов получает значение ключа для текущего запроса, который является ключом зависимости. Затем, если оно не равно нулю, получает значение зависимости, если оно равно нулю, зависимость была удалена, и мы устанавливаем validationStatus
в HttpValidationStatus.Invalid
.
Код для иллюстрации:
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
base.OnResultExecuting(filterContext);
// Build dependencies
BuildDependencies(paramsToDepend, filterContext.Controller, this.Duration);
}
private void BuildDependencies(IEnumerable<string> paramsToDepend, ControllerBase controller, int duration)
{
string[] valuesToInclude = GetValuesToInclude(paramsToInclude, controller.ControllerContext);
// Build the caché key for the current request
var cacheKey = CacheKeyProvider.GetCacheKeyFor(controller, paramsToDepend);
var cache = controller.ControllerContext.HttpContext.Cache;
var cacheValue = cache.Get(cacheKey);
if (cacheValue == null)
{
// The key is created if not exists
Provider.Add(cacheKey, new object(), Context.CurrentDateTime.AddSeconds(duration).ToUniversalTime());
}
// Add the dependency
Provider.Set(CachePrefix + controller.ControllerContext.HttpContext.Request.Path, cacheKey, Context.CurrentDateTime.AddSeconds(duration).ToUniversalTime());
// Register callback
controller.ControllerContext.HttpContext.Response.Cache.AddValidationCallback(new HttpCacheValidateHandler(ValidationCallback), null);
}
public static void ValidationCallback(HttpContext context, object data, ref HttpValidationStatus validationStatus)
{
var provider = OutputCache.Providers[OutputCache.DefaultProviderName];
var dependency = provider.Get(CachePrefix + context.Request.RawUrl) as string;
if (dependency == null) return;
var depValue = provider.Get(dependency);
// If it's null, someone has invelidated the caché (an entity was modified)
if (depValue == null)
{
validationStatus = HttpValidationStatus.Invalid;
}
}