with route practices example best attribute c# asp.net-web-api outputcache http-caching

c# - practices - web api route attribute



Almacenamiento en caché de resultados para un ApiController(MVC4 Web API) (5)

Estoy intentando almacenar en caché el resultado de un método ApiController en la API web.

Aquí está el código del controlador:

public class TestController : ApiController { [OutputCache(Duration = 10, VaryByParam = "none", Location = OutputCacheLocation.Any)] public string Get() { return System.DateTime.Now.ToString(); } }

NB También probé el atributo OutputCache en el controlador mismo, así como varias combinaciones de sus parámetros.

La ruta está registrada en Global.asax:

namespace WebApiTest { public class Global : HttpApplication { protected void Application_Start(object sender, EventArgs e) { RouteTable.Routes.MapHttpRoute("default", routeTemplate: "{controller}"); } } }

Recibo una respuesta exitosa, pero no está almacenada en caché en ninguna parte:

HTTP/1.1 200 OK Cache-Control: no-cache Pragma: no-cache Content-Type: application/xml; charset=utf-8 Expires: -1 Server: Microsoft-IIS/7.5 X-AspNet-Version: 4.0.30319 X-Powered-By: ASP.NET Date: Wed, 18 Jul 2012 17:56:17 GMT Content-Length: 96 <string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">18/07/2012 18:56:17</string>

No pude encontrar documentación para el almacenamiento en caché de resultados en la API web.

¿Es esto una limitación de la API web en MVC4 o estoy haciendo algo mal?


Durante los últimos meses, he estado trabajando en el almacenamiento en caché de HTTP para ASP.NET Web API. He contribuido con WebApiContrib para el lado del servidor y se puede encontrar información relevante en mi blog .

Recientemente comencé a expandir el trabajo y agregar también el lado del cliente en la biblioteca de CacheCow . Los primeros paquetes NuGet se han lanzado ahora (gracias a Tugberk ) Más por venir. Escribiré una publicación en el blog pronto sobre esto. Así que mira el espacio.

Pero para responder a su pregunta, ASP.NET Web API desactiva de forma predeterminada el almacenamiento en caché. Si desea que la respuesta se guarde en caché, debe agregar el encabezado CacheControl a la respuesta en su controlador (y, de hecho, mejor estar en un controlador de delegación similar a CachingHandler en CacheCow).

Este fragmento es de HttpControllerHandler en el código fuente de ASP.NET Web Stack:

CacheControlHeaderValue cacheControl = response.Headers.CacheControl; // TODO 335085: Consider this when coming up with our caching story if (cacheControl == null) { // DevDiv2 #332323. ASP.NET by default always emits a cache-control: private header. // However, we don''t want requests to be cached by default. // If nobody set an explicit CacheControl then explicitly set to no-cache to override the // default behavior. This will cause the following response headers to be emitted: // Cache-Control: no-cache // Pragma: no-cache // Expires: -1 httpContextBase.Response.Cache.SetCacheability(HttpCacheability.NoCache); }


La respuesta de Aliostad indica que la API web desactiva el almacenamiento en caché, y el código de HttpControllerHandler muestra que CUANDO responde.Headers.CacheControl es nulo.

Para hacer que su ejemplo de ApiController Action devuelva un resultado almacenable en caché, puede:

using System.Net.Http; public class TestController : ApiController { public HttpResponseMessage Get() { var response = Request.CreateResponse(HttpStatusCode.OK); response.Content = new StringContent(System.DateTime.Now.ToString()); response.Headers.CacheControl = new CacheControlHeaderValue(); response.Headers.CacheControl.MaxAge = new TimeSpan(0, 10, 0); // 10 min. or 600 sec. response.Headers.CacheControl.Public = true; return response; } }

y obtendrá un encabezado de respuesta HTTP como este:

Cache-Control: public, max-age=600 Content-Encoding: gzip Content-Type: text/plain; charset=utf-8 Date: Wed, 13 Mar 2013 21:06:10 GMT ...


Puede usar esto en un controlador MVC normal:

[OutputCache(Duration = 10, VaryByParam = "none", Location = OutputCacheLocation.Any)] public string Get() { HttpContext.Current.Response.Cache.SetOmitVaryStar(true); return System.DateTime.Now.ToString(); }

pero el atributo OutputCache está en el espacio de nombres System.Web.Mvc y no está disponible en un ApiController.


WebAPI no tiene ningún soporte integrado para el atributo [OutputCache] . Eche un vistazo a este artículo para ver cómo puede implementar esta característica usted mismo.


Ya llegué muy tarde, pero aún así pienso publicar este excelente artículo sobre el almacenamiento en caché en WebApi

https://codewala.net/2015/05/25/outputcache-doesnt-work-with-web-api-why-a-solution/

public class CacheWebApiAttribute : ActionFilterAttribute { public int Duration { get; set; } public override void OnActionExecuted(HttpActionExecutedContext filterContext) { filterContext.Response.Headers.CacheControl = new CacheControlHeaderValue() { MaxAge = TimeSpan.FromMinutes(Duration), MustRevalidate = true, Private = true }; } }

En el código anterior, hemos reemplazado el método OnActionExecuted y configuramos el encabezado requerido en la respuesta. Ahora he decorado la llamada de API web como

[CacheWebApi(Duration = 20)] public IEnumerable<string> Get() { return new string[] { DateTime.Now.ToLongTimeString(), DateTime.UtcNow.ToLongTimeString() }; }