2010-08-13 8 views
4

Je suis un peu confus au sujet de la granularité offerte par l'appel HttpResponse.RemoveOutputCacheItem(). Je suis intéressé à effectuer une mise en cache de sortie sur des images générées dynamiquement, et je voudrais faire varier le cache de sortie en utilisant au moins les paramètres (appelons-les 'id' et 'size' pour l'amour de l'argument).Invalider des portions du cache de sortie mvc asp.net - avec des niveaux de granularité variables

Ainsi, par exemple:

/Image/User?id=1 
/Image/User?id=1&size=1 
/Image/User?id=1&size=2 

serait-elle mises en cache séparement.

Lorsqu'un utilisateur donné change d'image; Je voudrais invalider tous les éléments de cache de sortie pour cet ID utilisateur (indépendamment de la taille). This question répond à ma question sur un seul paramètre particulier. Mais ... comment est-ce que j'irais vider toutes les réponses en cache pour un utilisateur sans tenir compte de la taille param? (Supposons que je ne connaîtrais pas toutes les valeurs possibles de 'taille' à l'avance).

Je voudrais idéalement faire quelque chose comme:

HttpResponse.RemoveOutputCacheItem("/Image/User?id=1&size=*"); //wishful thinking

Quelqu'un peut-il me diriger dans la bonne direction?

Modifier

@JcMalta ont proposé une solution prometteuse, mais je ne peux pas trouver une collection appropriée qui est exposée pour les éléments du cache de sortie. Une solution viable pourrait inclure une opération similaire à celle qu'il proposait si cela existait quelque part.

Répondre

3

Le cache de sortie a un concept de « dépendances de cache » qui pourrait être ce que vous cherchez .

.NET a une FileCacheDependency qui signifie qu'un élément de cache est automatiquement invalidé si un fichier sur le disque change, et une SqlCacheDependency qui invalide les objets quand les données dans une base de données MSSQL changent. Vous pouvez également écrire des dépendances de cache personnalisées. HttpResponse a un tas de méthodes nommées Add * Dependency/ies pour vous permettre de l'utiliser.

Par exemple, si vos images sont basées un fichier sur le disque, votre gestionnaire au service de l'image redimensionnée pourrait dire:

HttpResponse.AddFileDependency(@"C:\images\user" + userId + ".jpg"); 

Ce enregistre une dépendance pour votre réponse. Lorsque votre réponse est ajoutée au cache de sortie, toutes les dépendances vont avec. Lorsqu'une dépendance est modifiée, l'élément de cache est automatiquement invalidé. Si vos images sont basées sur des fichiers ou des données SQL, cela peut fonctionner pour vous dès la sortie de la boîte.

Vous pouvez également utiliser HttpResponse.AddCacheItemDependency pour qu'un élément de cache dépende d'un autre élément de cache. Si vous savez que l'URL de votre image d'origine "/ Image/User? Id = 1" sera toujours mise en cache, vous pouvez faire en sorte que les images redimensionnées dépendent de l'original, et HttpResponse.RemoveOutputCacheItem() sur l'original les effacera toutes.Si l'image originale n'est pas toujours mise en cache (peut-être que personne n'a demandé l'original, seulement les vignettes), je ne pense pas que cela fonctionnera.

La raison pour laquelle les dépendances de cache intégrées fonctionnent est que Windows et SQL Server disposent tous deux d'API intégrées pour notifier les modifications apportées aux fichiers ou aux données. Les dépendances de cache intégrées sont des wrappers autour de ceux-ci. Mais si aucune de ces solutions ne vous convient, votre dernière approche consiste à implémenter une chose similaire pour votre propre usage.

L'idée de base (non testée) est de sous-classer CacheDependency, appelons cela PictureCacheDependency.

Vous devez configurer une sorte de modèle d'écouteur/observateur de sorte que lorsqu'un utilisateur modifie son image, le code d'édition d'image peut indiquer à tous les objets PictureCacheDependency pertinents que l'image a modifiés. Lorsque cela se produit, PictureCacheDependency doit appeler base.NotifyDependencyChanged et le framework s'occupera du reste.

Vous auriez probablement le constructeur PictureCacheDependency s'enregistrer dans un dictionnaire statique d'événements, en utilisant l'ID utilisateur comme clé. Quelle que soit l'approche, assurez-vous de surcharger CacheDependency.DependencyDispose pour libérer toutes les références, sinon vous perdrez de la mémoire.

+0

Merci pour la réponse; HttpResponse.AddCacheItemDependency semblerait être une bonne option pour moi. – DanP

1

Vraiment c'est du haut de ma tête ... mais peut-être dans la bonne direction:

public void ClearCache(string myImagePrefix) 
{ 
    var cache = System.Web.HttpContext.Current.Cache; 

    IDictionaryEnumerator enumerator = cache.GetEnumerator(); 

    while (enumerator.MoveNext()) 
    { 
     string key = enumerator.Key.ToString(); 
     if(key.StartsWith(myImagePrefix) 
      cache.Remove(key); 
    } 
} 
+0

Juste pour être clair; Je cible le cache de sortie, pas le httpcache, mais le principe serait le même ... – DanP

+0

Malheureusement, pour autant que je sache, une collection appropriée n'est pas exposée pour le cache de sortie, donc je ne peux pas l'utiliser méthode (bonne suggestion, cependant) ... – DanP