30 votes

Mise en cache de la sortie pour un ApiController (API Web MVC4)

J'essaie de mettre en cache la sortie d'un fichier ApiController méthode dans API Web MVC4 .

Voici le code du contrôleur :

using System.Web.Http;
using System.Web.Mvc;
using System.Web.UI;

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

N.B. J'ai également essayé l'attribut OutputCache sur le contrôleur lui-même, ainsi que plusieurs combinaisons de ses paramètres.

La route est enregistrée dans Global.asax :

using System;
using System.Web;
using System.Web.Http;
using System.Web.Routing;

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

J'obtiens une réponse positive, mais elle n'est mise en cache nulle part :

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>

Je n'ai pas pu trouver de documentation sur la mise en cache de la sortie dans l'API Web.

Est-ce une limitation de l'API Web dans MVC4 ou est-ce que je fais quelque chose de mal ?

25voto

Luciano Carvalho Points 807

La réponse d'Aliostad indique que l'API Web désactive la mise en cache, et le code de HttpControllerHandler montre qu'il le fait lorsque response.Headers.CacheControl est nul.

Pour que l'action ApiController de votre exemple renvoie un résultat pouvant être mis en cache, vous pouvez :

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;
    }
}

et vous obtiendrez un en-tête de réponse HTTP comme celui-ci :

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
...

24voto

Cory Points 3759

L'interface WebAPI n'a pas de support intégré pour l'attribut OutputCache. Prenez un regard sur cet article pour voir comment vous pouvez mettre en œuvre cette fonctionnalité vous-même.

13voto

Aliostad Points 47792

Au cours des derniers mois, j'ai travaillé sur la mise en cache HTTP pour l'API Web ASP.NET. J'ai contribué à WebApiContrib pour le côté serveur et les informations pertinentes peuvent être trouvées sur mon blog .

Récemment, j'ai commencé à étendre le travail et à ajouter le côté client également dans le projet CacheCow bibliothèque. Les premiers paquets NuGet sont maintenant disponibles (merci à Tugberk ) Plus à venir. J'écrirai bientôt un billet de blog à ce sujet. Alors, surveillez l'espace.


Mais pour répondre à votre question, l'API Web ASP.NET désactive par défaut la mise en cache. Si vous voulez que la réponse soit mise en cache, vous devez ajouter l'en-tête CacheControl à la réponse dans votre contrôleur (et en fait, il vaut mieux que ce soit dans un gestionnaire de délégation similaire à CachingHandler dans CacheCow).

Cet extrait est tiré de HttpControllerHandler en code source 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);
        }

6voto

Je suis très en retard, mais j'ai quand même pensé à poster cet excellent article sur la mise en cache dans 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
        };
    }
}

Dans le code ci-dessus, nous avons surchargé la méthode OnActionExecuted et défini l'en-tête requis dans la réponse. J'ai maintenant décoré l'appel à l'API Web comme suit

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

-14voto

broxten Points 3

Vous pouvez l'utiliser sur un contrôleur MVC ordinaire :

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

mais l'attribut OutputCache se trouve dans l'espace de noms System.Web.Mvc et n'est pas disponible dans un ApiController.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X