У меня есть сайт MVC, который я разрабатываю, это многопользовательское приложение. Я настроил кеш файл на changebyheader = "host". Теперь я хотел бы аннулировать кеш только по имени хоста.
RemoveOutputCacheItem принимает только абсолютные виртуальные пути и не позволяет настраивать имя хоста (там, будучи не виртуальным путем).
Любая помощь в том, как добиться этого?
Благодарю.
Обновить
Вот как я могу получить внутренние ключи кеша
var runtimeType = typeof(HttpRuntime);
var ci = runtimeType.GetProperty(
"CacheInternal",
BindingFlags.NonPublic | BindingFlags.Static);
var cache = ci.GetValue(ci, new object[0]);
var cachesInfo = cache.GetType().GetField(
"_caches",
BindingFlags.NonPublic | BindingFlags.Instance);
var cacheEntries = cachesInfo.GetValue(cache);
var outputCacheEntries = new List<object>();
foreach (Object singleCache in cacheEntries as Array)
{
var singleCacheInfo =
singleCache.GetType().GetField("_entries",
BindingFlags.NonPublic | BindingFlags.Instance);
var entries = singleCacheInfo.GetValue(singleCache);
foreach (DictionaryEntry cacheEntry in entries as Hashtable)
{
var cacheEntryInfo = cacheEntry.Value.GetType().GetField("_value",
BindingFlags.NonPublic | BindingFlags.Instance);
var value = cacheEntryInfo.GetValue(cacheEntry.Value);
if (value.GetType().Name == "CachedRawResponse")
{
var key = (string)cacheEntry.Value.GetType().BaseType.GetField("_key", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(cacheEntry.Value);
key = key.Substring(key.IndexOf("/"));
outputCacheEntries.Add(key);
}
}
}
var keys = new StringBuilder();
foreach (string key in outputCacheEntries)
{
if (key.Contains(Request.Url.Host))
{
keys.Append(key + " ");
HttpResponse.RemoveOutputCacheItem(key);
}
}
Этот RemoveOutputCacheItem не работает с этим ключом.
Их ключ генерируется следующим образом: /HQNnoneV+n+FCNhostVHOSTNAME.comDE Даже прямой вызов RemoveOutputCache ("/HOSTNAME.com") тоже не работает (с различными настройками).
Обновление # 2
Поэтому прочитайте исходный код ссылки (http://referencesource.microsoft.com/#System.Web/HttpResponse.cs,3222f830c91ccb06), и кажется, что он должен попытаться создать настраиваемый ключ. Поэтому я должен иметь возможность RemoveOutputCache ("/"), и он должен создать для меня настраиваемый ключ, но, похоже, он также не работает должным образом, по-прежнему кажется, что он очищает все ключи.
Я немного опаздываю на вечеринку, но у меня была такая же потребность, и в итоге я был вдохновлен ответами в этом SO-вопросе: Очистка кэша страниц в ASP.NET
Я установил следующий ниже тест и смог успешно очистить кеш на хост без дополнительного кода...
[OutputCache(VaryByHeader = "host", Duration = 600, Location = OutputCacheLocation.Server)]
public ActionResult TestPage()
{
var key = GetCacheKey("TestPage");
HttpContext.Cache[key] = new object();
Response.AddCacheItemDependency(key);
return Content(DateTime.Now.ToString());
}
public ActionResult TestClearCache()
{
var key = GetCacheKey("TestPage");
HttpContext.Cache.Remove(key);
return Content("Cache cleared");
}
private string GetCacheKey(string page)
{
return string.Concat(page, Request.Url.Host.ToLower());
}
Ответ заключается в том, что это невозможно сделать таким образом. Копание в фактический код для RemoveOutputCache, где он генерирует ключ, не проходит в параметре varyby, и поэтому я не могу получить конкретный ключ.
Возможно, если бы я выкопал немного больше в генерации ключей, возможно, я мог бы написать метод gen gen, но я пошел другим путем. Это просто, чтобы дать всем остальным ответ на мою проблему.
Снова я хотел только изменить заголовок, отсутствие параметров и иметь возможность сделать недействительными только один элемент в кеше.
Вы можете попробовать VaryByCustom
[OutputCache(Duration = 3600, VaryByCustom = "hostname")]
И определите VaryByCustom как:
public override string GetVaryByCustomString(HttpContext Context, string Custom)
{
//Here you set any cache invalidation policy
if (Custom == "hostname")
{
return Context.Request.Url.Host;
}
return base.GetVaryByCustomString(Context, Custom);
}