c# - Almacenamiento en caché de la API web de ASP.NET con CacheCow
caching asp.net-web-api (3)
Estoy tratando de implementar el almacenamiento en caché utilizando CacheCow. Tengo dos problemas:
En algunos casos, necesito invalidar manualmente el caché de algunos recursos.
Por ejemplo, tengo un recurso que se llama
purchase
, y otro que se llamapointMovements
. No están totalmente conectados, pero hacer una publicación en lapurchase
implica algunos cambios en elpointMovement
depointMovement
. Cachecow no está detectando estos cambios porque no estoy llamando a la API depointmovements
. Entonces, cuando llamo al punto final de lospointmovements
depointmovements
, los valores se almacenan en caché y no puedo obtener los nuevos valores.Para resolver esto, necesito invalidarlo manualmente, ¿cómo es posible?
Hay algunos controladores que no quiero almacenar en caché. Estoy tratando de usar atributos para hacerlo, pero no está funcionando. Estoy siguiendo este artículo pero los atributos son ignorados.
¿Cómo puedo especificar qué controladores almacenar en caché?
Lo siento por la respuesta tardía.
Como dijo @Tri Q, la forma de hacerlo es usar los atributos que he explicado en este blog:
Resolví tu pregunta # 1 usando el código a continuación. Aquí extiendo la interfaz IRoutePatternProvider
. Recuerde, lo que devuelve en GetRoutePattern
debe coincidir con lo que devuelve en GetLinkedRoutePatterns
. Solo entonces la adición y eliminación funcionarán. Pruébalo.
Dentro de Application_Start
CachingHandler cacheHandler = new CachingHandler(GlobalConfiguration.Configuration);
cacheHandler.RoutePatternProvider = new CacheRoutePatternProvider();
GlobalConfiguration.Configuration.MessageHandlers.Add(cacheHandler);
Clase personalizada
public class CacheRoutePatternProvider : IRoutePatternProvider
{
public string GetRoutePattern(HttpRequestMessage request)
{
string path = request.RequestUri.AbsolutePath;
if (!path.EndsWith("/"))
path += "/";
return path;
}
public IEnumerable<string> GetLinkedRoutePatterns(HttpRequestMessage request)
{
string path = request.RequestUri.AbsolutePath;
if(!path.EndsWith("/"))
path += "/";
int segmentIndex;
// return each segment of the resource heirarchy
while ((segmentIndex = path.LastIndexOf("/")) > 0)
{
path = path.Substring(0, segmentIndex);
if(path.Contains("/api/"))
yield return path + "/";
}
yield break;
}
}
Encontré el mismo conjunto de problemas y encontré una solución para el problema 2 (deshabilitar el almacenamiento en caché independientemente de la configuración predeterminada).
// This forces the server to not provide any caching by refreshing its cache table immediately (0 sec)
[HttpCacheRefreshPolicy(0)]
// This forces the client (browser) to not cache any data returned from the server (even if ETag is present) by setting the time-out to 0 and no-cache to true.
[HttpCacheControlPolicy(true, 0, true)]
public void MyController : ApiControler {... }
Los atributos se deben aplicar juntos para que esto funcione. También puede controlar el almacenamiento en caché en el nivel de acción proporcionando las mismas reglas para cada acción.
Todavía tengo que encontrar la solución para el problema 1. pero mire este espacio para actualizaciones.
Actualización He encontrado una solución al problema 1.
- Registre CachingHandler con su contenedor IoC (en mi caso es
IUnityContainer
) - Inyecte el ICachingHandler en su controlador Web API.
- Para invalidar el recurso, use
ICachingHandler.InvalidateResource(HttpRequestMessage)
Por favor vea un ejemplo de código a continuación. La solución ha sido probada.
pubic class Bootstrapper
{
//...
// Create a new caching handler and register it with the container.
public void RegisterCache(HttpConfiguration config, IUnityContainer container)
{
var cachingHandler = new CachingHandler(config);
// ...
container.RegisterInstance<ICachingHandler>(cachingHandler);
}
}
public class ResourceContoller : ApiController
{
private ICachingHandler _cachingHandler;
public ResourceContoller(ICachingHandler cachingHandler)
{
_cachingHandler = cachingHandler;
}
[HttpPost]
public void DeleteResource(int resourceId)
{
// Do the delete
// ...
// Now invalidate the related resource cache entry
// Construct a http request message to the related resource
// HINT: The "DefaultApi" may not be your api route name, so change this to match your route.
// GOTCHA: The route matching mechanism is case sensitive, so be aware!
var relatedResource = new HttpRequestMessage(HttpMethod.Get, Url.Link("DefaultApi", new {controller = "linkedresource", action = "getlinkedresource", id: resourceId}));
// Invalidate the resource with the caching handler.
_cachingHandler.InvalidateResource(relatedResource);
}
}